xref: /llvm-project/llvm/test/CodeGen/Thumb/umul_fix_sat.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.sat.i4   (i4,  i4, i32)
5declare  i32 @llvm.umul.fix.sat.i32  (i32, i32, i32)
6declare  i64 @llvm.umul.fix.sat.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 {r4, lr}
12; ARM-NEXT:    push {r4, lr}
13; ARM-NEXT:    mov r2, r1
14; ARM-NEXT:    movs r4, #0
15; ARM-NEXT:    mov r1, r4
16; ARM-NEXT:    mov r3, r4
17; ARM-NEXT:    bl __aeabi_lmul
18; ARM-NEXT:    cmp r1, #3
19; ARM-NEXT:    bhi .LBB0_2
20; ARM-NEXT:  @ %bb.1:
21; ARM-NEXT:    lsrs r0, r0, #2
22; ARM-NEXT:    lsls r1, r1, #30
23; ARM-NEXT:    adds r0, r1, r0
24; ARM-NEXT:    pop {r4, pc}
25; ARM-NEXT:  .LBB0_2:
26; ARM-NEXT:    mvns r0, r4
27; ARM-NEXT:    pop {r4, pc}
28  %tmp = call i32 @llvm.umul.fix.sat.i32(i32 %x, i32 %y, i32 2)
29  ret i32 %tmp
30}
31
32define i64 @func2(i64 %x, i64 %y) nounwind {
33; ARM-LABEL: func2:
34; ARM:       @ %bb.0:
35; ARM-NEXT:    .save {r4, r5, r6, r7, lr}
36; ARM-NEXT:    push {r4, r5, r6, r7, lr}
37; ARM-NEXT:    .pad #20
38; ARM-NEXT:    sub sp, #20
39; ARM-NEXT:    str r3, [sp, #12] @ 4-byte Spill
40; ARM-NEXT:    mov r6, r2
41; ARM-NEXT:    mov r7, r1
42; ARM-NEXT:    str r1, [sp, #8] @ 4-byte Spill
43; ARM-NEXT:    mov r5, r0
44; ARM-NEXT:    movs r4, #0
45; ARM-NEXT:    mov r1, r4
46; ARM-NEXT:    mov r3, r4
47; ARM-NEXT:    bl __aeabi_lmul
48; ARM-NEXT:    str r0, [sp, #16] @ 4-byte Spill
49; ARM-NEXT:    str r1, [sp, #4] @ 4-byte Spill
50; ARM-NEXT:    mov r0, r7
51; ARM-NEXT:    mov r1, r4
52; ARM-NEXT:    mov r2, r6
53; ARM-NEXT:    mov r3, r4
54; ARM-NEXT:    bl __aeabi_lmul
55; ARM-NEXT:    mov r6, r1
56; ARM-NEXT:    ldr r1, [sp, #4] @ 4-byte Reload
57; ARM-NEXT:    adds r7, r0, r1
58; ARM-NEXT:    adcs r6, r4
59; ARM-NEXT:    mov r0, r5
60; ARM-NEXT:    mov r1, r4
61; ARM-NEXT:    ldr r5, [sp, #12] @ 4-byte Reload
62; ARM-NEXT:    mov r2, r5
63; ARM-NEXT:    mov r3, r4
64; ARM-NEXT:    bl __aeabi_lmul
65; ARM-NEXT:    adds r0, r0, r7
66; ARM-NEXT:    str r0, [sp, #4] @ 4-byte Spill
67; ARM-NEXT:    adcs r1, r4
68; ARM-NEXT:    adds r6, r6, r1
69; ARM-NEXT:    mov r7, r4
70; ARM-NEXT:    adcs r7, r4
71; ARM-NEXT:    ldr r0, [sp, #8] @ 4-byte Reload
72; ARM-NEXT:    mov r1, r4
73; ARM-NEXT:    mov r2, r5
74; ARM-NEXT:    mov r3, r4
75; ARM-NEXT:    bl __aeabi_lmul
76; ARM-NEXT:    adds r0, r0, r6
77; ARM-NEXT:    adcs r1, r7
78; ARM-NEXT:    lsrs r6, r0, #2
79; ARM-NEXT:    orrs r6, r1
80; ARM-NEXT:    lsls r0, r0, #30
81; ARM-NEXT:    ldr r3, [sp, #4] @ 4-byte Reload
82; ARM-NEXT:    lsrs r1, r3, #2
83; ARM-NEXT:    adds r2, r0, r1
84; ARM-NEXT:    lsls r0, r3, #30
85; ARM-NEXT:    ldr r1, [sp, #16] @ 4-byte Reload
86; ARM-NEXT:    lsrs r1, r1, #2
87; ARM-NEXT:    adds r3, r0, r1
88; ARM-NEXT:    mvns r1, r4
89; ARM-NEXT:    cmp r6, #0
90; ARM-NEXT:    mov r0, r1
91; ARM-NEXT:    beq .LBB1_3
92; ARM-NEXT:  @ %bb.1:
93; ARM-NEXT:    beq .LBB1_4
94; ARM-NEXT:  .LBB1_2:
95; ARM-NEXT:    add sp, #20
96; ARM-NEXT:    pop {r4, r5, r6, r7, pc}
97; ARM-NEXT:  .LBB1_3:
98; ARM-NEXT:    mov r0, r3
99; ARM-NEXT:    bne .LBB1_2
100; ARM-NEXT:  .LBB1_4:
101; ARM-NEXT:    mov r1, r2
102; ARM-NEXT:    add sp, #20
103; ARM-NEXT:    pop {r4, r5, r6, r7, pc}
104  %tmp = call i64 @llvm.umul.fix.sat.i64(i64 %x, i64 %y, i32 2)
105  ret i64 %tmp
106}
107
108define i4 @func3(i4 %x, i4 %y) nounwind {
109; ARM-LABEL: func3:
110; ARM:       @ %bb.0:
111; ARM-NEXT:    .save {r4, lr}
112; ARM-NEXT:    push {r4, lr}
113; ARM-NEXT:    movs r2, #15
114; ARM-NEXT:    ands r2, r1
115; ARM-NEXT:    lsls r0, r0, #28
116; ARM-NEXT:    movs r4, #0
117; ARM-NEXT:    mov r1, r4
118; ARM-NEXT:    mov r3, r4
119; ARM-NEXT:    bl __aeabi_lmul
120; ARM-NEXT:    cmp r1, #3
121; ARM-NEXT:    bhi .LBB2_2
122; ARM-NEXT:  @ %bb.1:
123; ARM-NEXT:    lsrs r0, r0, #2
124; ARM-NEXT:    lsls r1, r1, #30
125; ARM-NEXT:    adds r0, r1, r0
126; ARM-NEXT:    lsrs r0, r0, #28
127; ARM-NEXT:    pop {r4, pc}
128; ARM-NEXT:  .LBB2_2:
129; ARM-NEXT:    mvns r0, r4
130; ARM-NEXT:    lsrs r0, r0, #28
131; ARM-NEXT:    pop {r4, pc}
132  %tmp = call i4 @llvm.umul.fix.sat.i4(i4 %x, i4 %y, i32 2)
133  ret i4 %tmp
134}
135
136;; These result in regular integer multiplication with a saturation check.
137define i32 @func4(i32 %x, i32 %y) nounwind {
138; ARM-LABEL: func4:
139; ARM:       @ %bb.0:
140; ARM-NEXT:    .save {r4, lr}
141; ARM-NEXT:    push {r4, lr}
142; ARM-NEXT:    mov r2, r1
143; ARM-NEXT:    movs r4, #0
144; ARM-NEXT:    mov r1, r4
145; ARM-NEXT:    mov r3, r4
146; ARM-NEXT:    bl __aeabi_lmul
147; ARM-NEXT:    cmp r1, #0
148; ARM-NEXT:    bls .LBB3_2
149; ARM-NEXT:  @ %bb.1:
150; ARM-NEXT:    mvns r0, r4
151; ARM-NEXT:  .LBB3_2:
152; ARM-NEXT:    pop {r4, pc}
153  %tmp = call i32 @llvm.umul.fix.sat.i32(i32 %x, i32 %y, i32 0)
154  ret i32 %tmp
155}
156
157define i64 @func5(i64 %x, i64 %y) {
158; ARM-LABEL: func5:
159; ARM:       @ %bb.0:
160; ARM-NEXT:    .save {r4, r5, r6, r7, lr}
161; ARM-NEXT:    push {r4, r5, r6, r7, lr}
162; ARM-NEXT:    .pad #12
163; ARM-NEXT:    sub sp, #12
164; ARM-NEXT:    mov r6, r3
165; ARM-NEXT:    str r2, [sp, #8] @ 4-byte Spill
166; ARM-NEXT:    mov r4, r1
167; ARM-NEXT:    mov r2, r0
168; ARM-NEXT:    str r0, [sp, #4] @ 4-byte Spill
169; ARM-NEXT:    movs r5, #0
170; ARM-NEXT:    mov r0, r3
171; ARM-NEXT:    mov r1, r5
172; ARM-NEXT:    mov r3, r5
173; ARM-NEXT:    bl __aeabi_lmul
174; ARM-NEXT:    str r0, [sp] @ 4-byte Spill
175; ARM-NEXT:    mov r7, r1
176; ARM-NEXT:    subs r0, r1, #1
177; ARM-NEXT:    sbcs r7, r0
178; ARM-NEXT:    mov r0, r4
179; ARM-NEXT:    mov r1, r5
180; ARM-NEXT:    ldr r2, [sp, #8] @ 4-byte Reload
181; ARM-NEXT:    mov r3, r5
182; ARM-NEXT:    bl __aeabi_lmul
183; ARM-NEXT:    subs r2, r1, #1
184; ARM-NEXT:    sbcs r1, r2
185; ARM-NEXT:    subs r2, r6, #1
186; ARM-NEXT:    sbcs r6, r2
187; ARM-NEXT:    subs r2, r4, #1
188; ARM-NEXT:    sbcs r4, r2
189; ARM-NEXT:    ands r4, r6
190; ARM-NEXT:    orrs r4, r1
191; ARM-NEXT:    orrs r4, r7
192; ARM-NEXT:    ldr r1, [sp] @ 4-byte Reload
193; ARM-NEXT:    adds r6, r0, r1
194; ARM-NEXT:    ldr r0, [sp, #4] @ 4-byte Reload
195; ARM-NEXT:    mov r1, r5
196; ARM-NEXT:    ldr r2, [sp, #8] @ 4-byte Reload
197; ARM-NEXT:    mov r3, r5
198; ARM-NEXT:    bl __aeabi_lmul
199; ARM-NEXT:    adds r3, r1, r6
200; ARM-NEXT:    mov r2, r5
201; ARM-NEXT:    adcs r2, r5
202; ARM-NEXT:    orrs r2, r4
203; ARM-NEXT:    mvns r1, r5
204; ARM-NEXT:    cmp r2, #0
205; ARM-NEXT:    mov r2, r1
206; ARM-NEXT:    bne .LBB4_2
207; ARM-NEXT:  @ %bb.1:
208; ARM-NEXT:    mov r2, r0
209; ARM-NEXT:  .LBB4_2:
210; ARM-NEXT:    bne .LBB4_4
211; ARM-NEXT:  @ %bb.3:
212; ARM-NEXT:    mov r1, r3
213; ARM-NEXT:  .LBB4_4:
214; ARM-NEXT:    mov r0, r2
215; ARM-NEXT:    add sp, #12
216; ARM-NEXT:    pop {r4, r5, r6, r7, pc}
217  %tmp = call i64 @llvm.umul.fix.sat.i64(i64 %x, i64 %y, i32 0)
218  ret i64 %tmp
219}
220
221define i4 @func6(i4 %x, i4 %y) nounwind {
222; ARM-LABEL: func6:
223; ARM:       @ %bb.0:
224; ARM-NEXT:    .save {r4, lr}
225; ARM-NEXT:    push {r4, lr}
226; ARM-NEXT:    movs r2, #15
227; ARM-NEXT:    ands r2, r1
228; ARM-NEXT:    lsls r0, r0, #28
229; ARM-NEXT:    movs r4, #0
230; ARM-NEXT:    mov r1, r4
231; ARM-NEXT:    mov r3, r4
232; ARM-NEXT:    bl __aeabi_lmul
233; ARM-NEXT:    cmp r1, #0
234; ARM-NEXT:    bls .LBB5_2
235; ARM-NEXT:  @ %bb.1:
236; ARM-NEXT:    mvns r0, r4
237; ARM-NEXT:  .LBB5_2:
238; ARM-NEXT:    lsrs r0, r0, #28
239; ARM-NEXT:    pop {r4, pc}
240  %tmp = call i4 @llvm.umul.fix.sat.i4(i4 %x, i4 %y, i32 0)
241  ret i4 %tmp
242}
243
244define <4 x i32> @vec2(<4 x i32> %x, <4 x i32> %y) nounwind {
245; ARM-LABEL: vec2:
246; ARM:       @ %bb.0:
247; ARM-NEXT:    .save {r4, r5, r6, r7, lr}
248; ARM-NEXT:    push {r4, r5, r6, r7, lr}
249; ARM-NEXT:    .pad #12
250; ARM-NEXT:    sub sp, #12
251; ARM-NEXT:    str r3, [sp, #8] @ 4-byte Spill
252; ARM-NEXT:    mov r7, r2
253; ARM-NEXT:    mov r5, r1
254; ARM-NEXT:    ldr r2, [sp, #32]
255; ARM-NEXT:    movs r6, #0
256; ARM-NEXT:    mov r1, r6
257; ARM-NEXT:    mov r3, r6
258; ARM-NEXT:    bl __aeabi_lmul
259; ARM-NEXT:    mvns r4, r6
260; ARM-NEXT:    cmp r1, #0
261; ARM-NEXT:    mov r1, r4
262; ARM-NEXT:    bhi .LBB6_2
263; ARM-NEXT:  @ %bb.1:
264; ARM-NEXT:    mov r1, r0
265; ARM-NEXT:  .LBB6_2:
266; ARM-NEXT:    str r1, [sp, #4] @ 4-byte Spill
267; ARM-NEXT:    ldr r2, [sp, #36]
268; ARM-NEXT:    mov r0, r5
269; ARM-NEXT:    mov r1, r6
270; ARM-NEXT:    mov r3, r6
271; ARM-NEXT:    bl __aeabi_lmul
272; ARM-NEXT:    cmp r1, #0
273; ARM-NEXT:    mov r5, r4
274; ARM-NEXT:    bhi .LBB6_4
275; ARM-NEXT:  @ %bb.3:
276; ARM-NEXT:    mov r5, r0
277; ARM-NEXT:  .LBB6_4:
278; ARM-NEXT:    ldr r2, [sp, #40]
279; ARM-NEXT:    mov r0, r7
280; ARM-NEXT:    mov r1, r6
281; ARM-NEXT:    mov r3, r6
282; ARM-NEXT:    bl __aeabi_lmul
283; ARM-NEXT:    cmp r1, #0
284; ARM-NEXT:    mov r7, r4
285; ARM-NEXT:    bhi .LBB6_6
286; ARM-NEXT:  @ %bb.5:
287; ARM-NEXT:    mov r7, r0
288; ARM-NEXT:  .LBB6_6:
289; ARM-NEXT:    ldr r2, [sp, #44]
290; ARM-NEXT:    ldr r0, [sp, #8] @ 4-byte Reload
291; ARM-NEXT:    mov r1, r6
292; ARM-NEXT:    mov r3, r6
293; ARM-NEXT:    bl __aeabi_lmul
294; ARM-NEXT:    cmp r1, #0
295; ARM-NEXT:    bhi .LBB6_8
296; ARM-NEXT:  @ %bb.7:
297; ARM-NEXT:    mov r4, r0
298; ARM-NEXT:  .LBB6_8:
299; ARM-NEXT:    ldr r0, [sp, #4] @ 4-byte Reload
300; ARM-NEXT:    mov r1, r5
301; ARM-NEXT:    mov r2, r7
302; ARM-NEXT:    mov r3, r4
303; ARM-NEXT:    add sp, #12
304; ARM-NEXT:    pop {r4, r5, r6, r7, pc}
305  %tmp = call <4 x i32> @llvm.umul.fix.sat.v4i32(<4 x i32> %x, <4 x i32> %y, i32 0)
306  ret <4 x i32> %tmp
307}
308
309define i64 @func7(i64 %x, i64 %y) nounwind {
310; ARM-LABEL: func7:
311; ARM:       @ %bb.0:
312; ARM-NEXT:    .save {r4, r5, r6, r7, lr}
313; ARM-NEXT:    push {r4, r5, r6, r7, lr}
314; ARM-NEXT:    .pad #12
315; ARM-NEXT:    sub sp, #12
316; ARM-NEXT:    str r3, [sp, #8] @ 4-byte Spill
317; ARM-NEXT:    mov r5, r2
318; ARM-NEXT:    mov r6, r1
319; ARM-NEXT:    str r1, [sp, #4] @ 4-byte Spill
320; ARM-NEXT:    mov r7, r0
321; ARM-NEXT:    movs r4, #0
322; ARM-NEXT:    mov r1, r4
323; ARM-NEXT:    mov r3, r4
324; ARM-NEXT:    bl __aeabi_lmul
325; ARM-NEXT:    str r1, [sp] @ 4-byte Spill
326; ARM-NEXT:    mov r0, r6
327; ARM-NEXT:    mov r1, r4
328; ARM-NEXT:    mov r2, r5
329; ARM-NEXT:    mov r3, r4
330; ARM-NEXT:    bl __aeabi_lmul
331; ARM-NEXT:    mov r5, r1
332; ARM-NEXT:    ldr r1, [sp] @ 4-byte Reload
333; ARM-NEXT:    adds r0, r0, r1
334; ARM-NEXT:    str r0, [sp] @ 4-byte Spill
335; ARM-NEXT:    adcs r5, r4
336; ARM-NEXT:    mov r0, r7
337; ARM-NEXT:    mov r1, r4
338; ARM-NEXT:    ldr r6, [sp, #8] @ 4-byte Reload
339; ARM-NEXT:    mov r2, r6
340; ARM-NEXT:    mov r3, r4
341; ARM-NEXT:    bl __aeabi_lmul
342; ARM-NEXT:    ldr r2, [sp] @ 4-byte Reload
343; ARM-NEXT:    adds r0, r0, r2
344; ARM-NEXT:    str r0, [sp] @ 4-byte Spill
345; ARM-NEXT:    adcs r1, r4
346; ARM-NEXT:    adds r5, r5, r1
347; ARM-NEXT:    mov r7, r4
348; ARM-NEXT:    adcs r7, r4
349; ARM-NEXT:    ldr r0, [sp, #4] @ 4-byte Reload
350; ARM-NEXT:    mov r1, r4
351; ARM-NEXT:    mov r2, r6
352; ARM-NEXT:    mov r3, r4
353; ARM-NEXT:    bl __aeabi_lmul
354; ARM-NEXT:    mov r2, r1
355; ARM-NEXT:    adds r3, r0, r5
356; ARM-NEXT:    adcs r2, r7
357; ARM-NEXT:    mvns r1, r4
358; ARM-NEXT:    cmp r2, #0
359; ARM-NEXT:    mov r0, r1
360; ARM-NEXT:    beq .LBB7_3
361; ARM-NEXT:  @ %bb.1:
362; ARM-NEXT:    beq .LBB7_4
363; ARM-NEXT:  .LBB7_2:
364; ARM-NEXT:    add sp, #12
365; ARM-NEXT:    pop {r4, r5, r6, r7, pc}
366; ARM-NEXT:  .LBB7_3:
367; ARM-NEXT:    ldr r0, [sp] @ 4-byte Reload
368; ARM-NEXT:    bne .LBB7_2
369; ARM-NEXT:  .LBB7_4:
370; ARM-NEXT:    mov r1, r3
371; ARM-NEXT:    add sp, #12
372; ARM-NEXT:    pop {r4, r5, r6, r7, pc}
373  %tmp = call i64 @llvm.umul.fix.sat.i64(i64 %x, i64 %y, i32 32)
374  ret i64 %tmp
375}
376
377define i64 @func8(i64 %x, i64 %y) nounwind {
378; ARM-LABEL: func8:
379; ARM:       @ %bb.0:
380; ARM-NEXT:    .save {r4, r5, r6, r7, lr}
381; ARM-NEXT:    push {r4, r5, r6, r7, lr}
382; ARM-NEXT:    .pad #12
383; ARM-NEXT:    sub sp, #12
384; ARM-NEXT:    str r3, [sp, #8] @ 4-byte Spill
385; ARM-NEXT:    mov r5, r2
386; ARM-NEXT:    mov r6, r1
387; ARM-NEXT:    str r1, [sp, #4] @ 4-byte Spill
388; ARM-NEXT:    mov r7, r0
389; ARM-NEXT:    movs r4, #0
390; ARM-NEXT:    mov r1, r4
391; ARM-NEXT:    mov r3, r4
392; ARM-NEXT:    bl __aeabi_lmul
393; ARM-NEXT:    str r1, [sp] @ 4-byte Spill
394; ARM-NEXT:    mov r0, r6
395; ARM-NEXT:    mov r1, r4
396; ARM-NEXT:    mov r2, r5
397; ARM-NEXT:    mov r3, r4
398; ARM-NEXT:    bl __aeabi_lmul
399; ARM-NEXT:    mov r5, r1
400; ARM-NEXT:    ldr r1, [sp] @ 4-byte Reload
401; ARM-NEXT:    adds r0, r0, r1
402; ARM-NEXT:    str r0, [sp] @ 4-byte Spill
403; ARM-NEXT:    adcs r5, r4
404; ARM-NEXT:    mov r0, r7
405; ARM-NEXT:    mov r1, r4
406; ARM-NEXT:    ldr r6, [sp, #8] @ 4-byte Reload
407; ARM-NEXT:    mov r2, r6
408; ARM-NEXT:    mov r3, r4
409; ARM-NEXT:    bl __aeabi_lmul
410; ARM-NEXT:    ldr r2, [sp] @ 4-byte Reload
411; ARM-NEXT:    adds r0, r0, r2
412; ARM-NEXT:    str r0, [sp] @ 4-byte Spill
413; ARM-NEXT:    adcs r1, r4
414; ARM-NEXT:    adds r5, r5, r1
415; ARM-NEXT:    mov r7, r4
416; ARM-NEXT:    adcs r7, r4
417; ARM-NEXT:    ldr r0, [sp, #4] @ 4-byte Reload
418; ARM-NEXT:    mov r1, r4
419; ARM-NEXT:    mov r2, r6
420; ARM-NEXT:    mov r3, r4
421; ARM-NEXT:    bl __aeabi_lmul
422; ARM-NEXT:    adds r0, r0, r5
423; ARM-NEXT:    adcs r1, r7
424; ARM-NEXT:    lsls r1, r1, #1
425; ARM-NEXT:    lsrs r5, r0, #31
426; ARM-NEXT:    adds r2, r1, r5
427; ARM-NEXT:    lsls r0, r0, #1
428; ARM-NEXT:    ldr r1, [sp] @ 4-byte Reload
429; ARM-NEXT:    lsrs r1, r1, #31
430; ARM-NEXT:    adds r3, r0, r1
431; ARM-NEXT:    mvns r1, r4
432; ARM-NEXT:    cmp r5, #0
433; ARM-NEXT:    mov r0, r1
434; ARM-NEXT:    beq .LBB8_3
435; ARM-NEXT:  @ %bb.1:
436; ARM-NEXT:    beq .LBB8_4
437; ARM-NEXT:  .LBB8_2:
438; ARM-NEXT:    add sp, #12
439; ARM-NEXT:    pop {r4, r5, r6, r7, pc}
440; ARM-NEXT:  .LBB8_3:
441; ARM-NEXT:    mov r0, r3
442; ARM-NEXT:    bne .LBB8_2
443; ARM-NEXT:  .LBB8_4:
444; ARM-NEXT:    mov r1, r2
445; ARM-NEXT:    add sp, #12
446; ARM-NEXT:    pop {r4, r5, r6, r7, pc}
447  %tmp = call i64 @llvm.umul.fix.sat.i64(i64 %x, i64 %y, i32 63)
448  ret i64 %tmp
449}
450