xref: /llvm-project/llvm/test/CodeGen/Thumb/umul_fix.ll (revision e30a4fc3e20bf5d9cc2f5bfcb61b4eb0e686a193)
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2; RUN: llc < %s -mtriple=thumbv6m-none-unknown-eabi -mcpu=cortex-m0 | FileCheck %s --check-prefix=ARM
3
4declare  i4  @llvm.umul.fix.i4   (i4,  i4, i32)
5declare  i32 @llvm.umul.fix.i32  (i32, i32, i32)
6declare  i64 @llvm.umul.fix.i64  (i64, i64, i32)
7
8define i32 @func(i32 %x, i32 %y) nounwind {
9; ARM-LABEL: func:
10; ARM:       @ %bb.0:
11; ARM-NEXT:    .save {r7, lr}
12; ARM-NEXT:    push {r7, lr}
13; ARM-NEXT:    mov r2, r1
14; ARM-NEXT:    movs r1, #0
15; ARM-NEXT:    mov r3, r1
16; ARM-NEXT:    bl __aeabi_lmul
17; ARM-NEXT:    lsrs r0, r0, #2
18; ARM-NEXT:    lsls r1, r1, #30
19; ARM-NEXT:    adds r0, r1, r0
20; ARM-NEXT:    pop {r7, pc}
21  %tmp = call i32 @llvm.umul.fix.i32(i32 %x, i32 %y, i32 2)
22  ret i32 %tmp
23}
24
25define i64 @func2(i64 %x, i64 %y) nounwind {
26; ARM-LABEL: func2:
27; ARM:       @ %bb.0:
28; ARM-NEXT:    .save {r4, r5, r6, r7, lr}
29; ARM-NEXT:    push {r4, r5, r6, r7, lr}
30; ARM-NEXT:    .pad #20
31; ARM-NEXT:    sub sp, #20
32; ARM-NEXT:    str r3, [sp, #12] @ 4-byte Spill
33; ARM-NEXT:    mov r4, r2
34; ARM-NEXT:    mov r6, r1
35; ARM-NEXT:    str r1, [sp, #8] @ 4-byte Spill
36; ARM-NEXT:    mov r5, r0
37; ARM-NEXT:    movs r7, #0
38; ARM-NEXT:    mov r1, r7
39; ARM-NEXT:    mov r3, r7
40; ARM-NEXT:    bl __aeabi_lmul
41; ARM-NEXT:    str r0, [sp, #16] @ 4-byte Spill
42; ARM-NEXT:    str r1, [sp, #4] @ 4-byte Spill
43; ARM-NEXT:    mov r0, r6
44; ARM-NEXT:    mov r1, r7
45; ARM-NEXT:    mov r2, r4
46; ARM-NEXT:    mov r3, r7
47; ARM-NEXT:    bl __aeabi_lmul
48; ARM-NEXT:    mov r4, r1
49; ARM-NEXT:    ldr r1, [sp, #4] @ 4-byte Reload
50; ARM-NEXT:    adds r0, r0, r1
51; ARM-NEXT:    str r0, [sp, #4] @ 4-byte Spill
52; ARM-NEXT:    adcs r4, r7
53; ARM-NEXT:    mov r0, r5
54; ARM-NEXT:    mov r1, r7
55; ARM-NEXT:    ldr r6, [sp, #12] @ 4-byte Reload
56; ARM-NEXT:    mov r2, r6
57; ARM-NEXT:    mov r3, r7
58; ARM-NEXT:    bl __aeabi_lmul
59; ARM-NEXT:    mov r5, r1
60; ARM-NEXT:    ldr r1, [sp, #4] @ 4-byte Reload
61; ARM-NEXT:    adds r0, r0, r1
62; ARM-NEXT:    str r0, [sp, #4] @ 4-byte Spill
63; ARM-NEXT:    adcs r5, r4
64; ARM-NEXT:    ldr r0, [sp, #8] @ 4-byte Reload
65; ARM-NEXT:    mov r1, r7
66; ARM-NEXT:    mov r2, r6
67; ARM-NEXT:    mov r3, r7
68; ARM-NEXT:    bl __aeabi_lmul
69; ARM-NEXT:    adds r0, r0, r5
70; ARM-NEXT:    lsls r0, r0, #30
71; ARM-NEXT:    ldr r2, [sp, #4] @ 4-byte Reload
72; ARM-NEXT:    lsrs r1, r2, #2
73; ARM-NEXT:    adds r1, r0, r1
74; ARM-NEXT:    lsls r0, r2, #30
75; ARM-NEXT:    ldr r2, [sp, #16] @ 4-byte Reload
76; ARM-NEXT:    lsrs r2, r2, #2
77; ARM-NEXT:    adds r0, r0, r2
78; ARM-NEXT:    add sp, #20
79; ARM-NEXT:    pop {r4, r5, r6, r7, pc}
80  %tmp = call i64 @llvm.umul.fix.i64(i64 %x, i64 %y, i32 2)
81  ret i64 %tmp
82}
83
84define i4 @func3(i4 %x, i4 %y) nounwind {
85; ARM-LABEL: func3:
86; ARM:       @ %bb.0:
87; ARM-NEXT:    .save {r7, lr}
88; ARM-NEXT:    push {r7, lr}
89; ARM-NEXT:    movs r2, #15
90; ARM-NEXT:    ands r0, r2
91; ARM-NEXT:    ands r2, r1
92; ARM-NEXT:    movs r1, #0
93; ARM-NEXT:    mov r3, r1
94; ARM-NEXT:    bl __aeabi_lmul
95; ARM-NEXT:    lsrs r0, r0, #2
96; ARM-NEXT:    lsls r1, r1, #30
97; ARM-NEXT:    adds r0, r1, r0
98; ARM-NEXT:    pop {r7, pc}
99  %tmp = call i4 @llvm.umul.fix.i4(i4 %x, i4 %y, i32 2)
100  ret i4 %tmp
101}
102
103;; These result in regular integer multiplication
104define i32 @func4(i32 %x, i32 %y) nounwind {
105; ARM-LABEL: func4:
106; ARM:       @ %bb.0:
107; ARM-NEXT:    muls r0, r1, r0
108; ARM-NEXT:    bx lr
109  %tmp = call i32 @llvm.umul.fix.i32(i32 %x, i32 %y, i32 0)
110  ret i32 %tmp
111}
112
113define i64 @func5(i64 %x, i64 %y) nounwind {
114; ARM-LABEL: func5:
115; ARM:       @ %bb.0:
116; ARM-NEXT:    .save {r7, lr}
117; ARM-NEXT:    push {r7, lr}
118; ARM-NEXT:    bl __aeabi_lmul
119; ARM-NEXT:    pop {r7, pc}
120  %tmp = call i64 @llvm.umul.fix.i64(i64 %x, i64 %y, i32 0)
121  ret i64 %tmp
122}
123
124define i4 @func6(i4 %x, i4 %y) nounwind {
125; ARM-LABEL: func6:
126; ARM:       @ %bb.0:
127; ARM-NEXT:    movs r2, #15
128; ARM-NEXT:    ands r1, r2
129; ARM-NEXT:    ands r0, r2
130; ARM-NEXT:    muls r0, r1, r0
131; ARM-NEXT:    bx lr
132  %tmp = call i4 @llvm.umul.fix.i4(i4 %x, i4 %y, i32 0)
133  ret i4 %tmp
134}
135
136define i64 @func7(i64 %x, i64 %y) nounwind {
137; ARM-LABEL: func7:
138; ARM:       @ %bb.0:
139; ARM-NEXT:    .save {r4, r5, r6, r7, lr}
140; ARM-NEXT:    push {r4, r5, r6, r7, lr}
141; ARM-NEXT:    .pad #12
142; ARM-NEXT:    sub sp, #12
143; ARM-NEXT:    str r3, [sp, #8] @ 4-byte Spill
144; ARM-NEXT:    mov r4, r2
145; ARM-NEXT:    mov r5, r1
146; ARM-NEXT:    str r1, [sp, #4] @ 4-byte Spill
147; ARM-NEXT:    mov r7, r0
148; ARM-NEXT:    movs r6, #0
149; ARM-NEXT:    mov r1, r6
150; ARM-NEXT:    mov r3, r6
151; ARM-NEXT:    bl __aeabi_lmul
152; ARM-NEXT:    str r1, [sp] @ 4-byte Spill
153; ARM-NEXT:    mov r0, r5
154; ARM-NEXT:    mov r1, r6
155; ARM-NEXT:    mov r2, r4
156; ARM-NEXT:    mov r3, r6
157; ARM-NEXT:    bl __aeabi_lmul
158; ARM-NEXT:    mov r4, r1
159; ARM-NEXT:    ldr r1, [sp] @ 4-byte Reload
160; ARM-NEXT:    adds r0, r0, r1
161; ARM-NEXT:    str r0, [sp] @ 4-byte Spill
162; ARM-NEXT:    adcs r4, r6
163; ARM-NEXT:    mov r0, r7
164; ARM-NEXT:    mov r1, r6
165; ARM-NEXT:    ldr r7, [sp, #8] @ 4-byte Reload
166; ARM-NEXT:    mov r2, r7
167; ARM-NEXT:    mov r3, r6
168; ARM-NEXT:    bl __aeabi_lmul
169; ARM-NEXT:    mov r5, r1
170; ARM-NEXT:    ldr r1, [sp] @ 4-byte Reload
171; ARM-NEXT:    adds r0, r0, r1
172; ARM-NEXT:    str r0, [sp] @ 4-byte Spill
173; ARM-NEXT:    adcs r5, r4
174; ARM-NEXT:    ldr r0, [sp, #4] @ 4-byte Reload
175; ARM-NEXT:    mov r1, r6
176; ARM-NEXT:    mov r2, r7
177; ARM-NEXT:    mov r3, r6
178; ARM-NEXT:    bl __aeabi_lmul
179; ARM-NEXT:    adds r1, r0, r5
180; ARM-NEXT:    ldr r0, [sp] @ 4-byte Reload
181; ARM-NEXT:    add sp, #12
182; ARM-NEXT:    pop {r4, r5, r6, r7, pc}
183  %tmp = call i64 @llvm.umul.fix.i64(i64 %x, i64 %y, i32 32)
184  ret i64 %tmp
185}
186
187define i64 @func8(i64 %x, i64 %y) nounwind {
188; ARM-LABEL: func8:
189; ARM:       @ %bb.0:
190; ARM-NEXT:    .save {r4, r5, r6, r7, lr}
191; ARM-NEXT:    push {r4, r5, r6, r7, lr}
192; ARM-NEXT:    .pad #12
193; ARM-NEXT:    sub sp, #12
194; ARM-NEXT:    str r3, [sp, #8] @ 4-byte Spill
195; ARM-NEXT:    mov r4, r2
196; ARM-NEXT:    mov r5, r1
197; ARM-NEXT:    str r1, [sp, #4] @ 4-byte Spill
198; ARM-NEXT:    mov r7, r0
199; ARM-NEXT:    movs r6, #0
200; ARM-NEXT:    mov r1, r6
201; ARM-NEXT:    mov r3, r6
202; ARM-NEXT:    bl __aeabi_lmul
203; ARM-NEXT:    str r1, [sp] @ 4-byte Spill
204; ARM-NEXT:    mov r0, r5
205; ARM-NEXT:    mov r1, r6
206; ARM-NEXT:    mov r2, r4
207; ARM-NEXT:    mov r3, r6
208; ARM-NEXT:    bl __aeabi_lmul
209; ARM-NEXT:    mov r4, r1
210; ARM-NEXT:    ldr r1, [sp] @ 4-byte Reload
211; ARM-NEXT:    adds r0, r0, r1
212; ARM-NEXT:    str r0, [sp] @ 4-byte Spill
213; ARM-NEXT:    adcs r4, r6
214; ARM-NEXT:    mov r0, r7
215; ARM-NEXT:    mov r1, r6
216; ARM-NEXT:    ldr r5, [sp, #8] @ 4-byte Reload
217; ARM-NEXT:    mov r2, r5
218; ARM-NEXT:    mov r3, r6
219; ARM-NEXT:    bl __aeabi_lmul
220; ARM-NEXT:    ldr r2, [sp] @ 4-byte Reload
221; ARM-NEXT:    adds r0, r0, r2
222; ARM-NEXT:    str r0, [sp] @ 4-byte Spill
223; ARM-NEXT:    adcs r1, r6
224; ARM-NEXT:    adds r4, r4, r1
225; ARM-NEXT:    mov r7, r6
226; ARM-NEXT:    adcs r7, r6
227; ARM-NEXT:    ldr r0, [sp, #4] @ 4-byte Reload
228; ARM-NEXT:    mov r1, r6
229; ARM-NEXT:    mov r2, r5
230; ARM-NEXT:    mov r3, r6
231; ARM-NEXT:    bl __aeabi_lmul
232; ARM-NEXT:    adds r0, r0, r4
233; ARM-NEXT:    adcs r1, r7
234; ARM-NEXT:    lsls r1, r1, #1
235; ARM-NEXT:    lsrs r2, r0, #31
236; ARM-NEXT:    adds r1, r1, r2
237; ARM-NEXT:    lsls r0, r0, #1
238; ARM-NEXT:    ldr r2, [sp] @ 4-byte Reload
239; ARM-NEXT:    lsrs r2, r2, #31
240; ARM-NEXT:    adds r0, r0, r2
241; ARM-NEXT:    add sp, #12
242; ARM-NEXT:    pop {r4, r5, r6, r7, pc}
243  %tmp = call i64 @llvm.umul.fix.i64(i64 %x, i64 %y, i32 63)
244  ret i64 %tmp
245}
246
247define i64 @func9(i64 %x, i64 %y) nounwind {
248; ARM-LABEL: func9:
249; ARM:       @ %bb.0:
250; ARM-NEXT:    .save {r4, r5, r6, r7, lr}
251; ARM-NEXT:    push {r4, r5, r6, r7, lr}
252; ARM-NEXT:    .pad #12
253; ARM-NEXT:    sub sp, #12
254; ARM-NEXT:    str r3, [sp, #8] @ 4-byte Spill
255; ARM-NEXT:    mov r4, r2
256; ARM-NEXT:    mov r5, r1
257; ARM-NEXT:    str r1, [sp, #4] @ 4-byte Spill
258; ARM-NEXT:    mov r7, r0
259; ARM-NEXT:    movs r6, #0
260; ARM-NEXT:    mov r1, r6
261; ARM-NEXT:    mov r3, r6
262; ARM-NEXT:    bl __aeabi_lmul
263; ARM-NEXT:    str r1, [sp] @ 4-byte Spill
264; ARM-NEXT:    mov r0, r5
265; ARM-NEXT:    mov r1, r6
266; ARM-NEXT:    mov r2, r4
267; ARM-NEXT:    mov r3, r6
268; ARM-NEXT:    bl __aeabi_lmul
269; ARM-NEXT:    mov r4, r1
270; ARM-NEXT:    ldr r1, [sp] @ 4-byte Reload
271; ARM-NEXT:    adds r5, r0, r1
272; ARM-NEXT:    adcs r4, r6
273; ARM-NEXT:    mov r0, r7
274; ARM-NEXT:    mov r1, r6
275; ARM-NEXT:    ldr r7, [sp, #8] @ 4-byte Reload
276; ARM-NEXT:    mov r2, r7
277; ARM-NEXT:    mov r3, r6
278; ARM-NEXT:    bl __aeabi_lmul
279; ARM-NEXT:    adds r0, r0, r5
280; ARM-NEXT:    adcs r1, r6
281; ARM-NEXT:    adds r4, r4, r1
282; ARM-NEXT:    mov r5, r6
283; ARM-NEXT:    adcs r5, r6
284; ARM-NEXT:    ldr r0, [sp, #4] @ 4-byte Reload
285; ARM-NEXT:    mov r1, r6
286; ARM-NEXT:    mov r2, r7
287; ARM-NEXT:    mov r3, r6
288; ARM-NEXT:    bl __aeabi_lmul
289; ARM-NEXT:    adds r0, r0, r4
290; ARM-NEXT:    adcs r1, r5
291; ARM-NEXT:    add sp, #12
292; ARM-NEXT:    pop {r4, r5, r6, r7, pc}
293  %tmp = call i64 @llvm.umul.fix.i64(i64 %x, i64 %y, i32 64)
294  ret i64 %tmp
295}
296