xref: /llvm-project/llvm/test/CodeGen/ARM/select.ll (revision e0ed0333f0fed2e73f805afd58b61176a87aa3ad)
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 4
2; RUN: llc -mtriple=armv7-eabi -mattr=-fpregs %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-ARM
3; RUN: llc -mtriple=armv7-eabi -mattr=+vfp2 %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-VFP
4; RUN: llc -mtriple=thumbv7-apple-darwin -mattr=+neon,+thumb2 %s -o - | FileCheck %s --check-prefix=CHECK-NEON
5
6define i32 @f1(i32 %a.s) {
7; CHECK-LABEL: f1:
8; CHECK:       @ %bb.0: @ %entry
9; CHECK-NEXT:    mov r1, #3
10; CHECK-NEXT:    cmp r0, #4
11; CHECK-NEXT:    movweq r1, #2
12; CHECK-NEXT:    mov r0, r1
13; CHECK-NEXT:    bx lr
14;
15; CHECK-NEON-LABEL: f1:
16; CHECK-NEON:       @ %bb.0: @ %entry
17; CHECK-NEON-NEXT:    movs r1, #3
18; CHECK-NEON-NEXT:    cmp r0, #4
19; CHECK-NEON-NEXT:    it eq
20; CHECK-NEON-NEXT:    moveq r1, #2
21; CHECK-NEON-NEXT:    mov r0, r1
22; CHECK-NEON-NEXT:    bx lr
23entry:
24    %tmp = icmp eq i32 %a.s, 4
25    %tmp1.s = select i1 %tmp, i32 2, i32 3
26    ret i32 %tmp1.s
27}
28
29define i32 @f2(i32 %a.s) {
30; CHECK-LABEL: f2:
31; CHECK:       @ %bb.0: @ %entry
32; CHECK-NEXT:    mov r1, #3
33; CHECK-NEXT:    cmp r0, #4
34; CHECK-NEXT:    movwgt r1, #2
35; CHECK-NEXT:    mov r0, r1
36; CHECK-NEXT:    bx lr
37;
38; CHECK-NEON-LABEL: f2:
39; CHECK-NEON:       @ %bb.0: @ %entry
40; CHECK-NEON-NEXT:    movs r1, #3
41; CHECK-NEON-NEXT:    cmp r0, #4
42; CHECK-NEON-NEXT:    it gt
43; CHECK-NEON-NEXT:    movgt r1, #2
44; CHECK-NEON-NEXT:    mov r0, r1
45; CHECK-NEON-NEXT:    bx lr
46entry:
47    %tmp = icmp sgt i32 %a.s, 4
48    %tmp1.s = select i1 %tmp, i32 2, i32 3
49    ret i32 %tmp1.s
50}
51
52define i32 @f3(i32 %a.s, i32 %b.s) {
53; CHECK-LABEL: f3:
54; CHECK:       @ %bb.0: @ %entry
55; CHECK-NEXT:    mov r2, #3
56; CHECK-NEXT:    cmp r0, r1
57; CHECK-NEXT:    movwlt r2, #2
58; CHECK-NEXT:    mov r0, r2
59; CHECK-NEXT:    bx lr
60;
61; CHECK-NEON-LABEL: f3:
62; CHECK-NEON:       @ %bb.0: @ %entry
63; CHECK-NEON-NEXT:    movs r2, #3
64; CHECK-NEON-NEXT:    cmp r0, r1
65; CHECK-NEON-NEXT:    it lt
66; CHECK-NEON-NEXT:    movlt r2, #2
67; CHECK-NEON-NEXT:    mov r0, r2
68; CHECK-NEON-NEXT:    bx lr
69entry:
70    %tmp = icmp slt i32 %a.s, %b.s
71    %tmp1.s = select i1 %tmp, i32 2, i32 3
72    ret i32 %tmp1.s
73}
74
75define i32 @f4(i32 %a.s, i32 %b.s) {
76; CHECK-LABEL: f4:
77; CHECK:       @ %bb.0: @ %entry
78; CHECK-NEXT:    mov r2, #3
79; CHECK-NEXT:    cmp r0, r1
80; CHECK-NEXT:    movwle r2, #2
81; CHECK-NEXT:    mov r0, r2
82; CHECK-NEXT:    bx lr
83;
84; CHECK-NEON-LABEL: f4:
85; CHECK-NEON:       @ %bb.0: @ %entry
86; CHECK-NEON-NEXT:    movs r2, #3
87; CHECK-NEON-NEXT:    cmp r0, r1
88; CHECK-NEON-NEXT:    it le
89; CHECK-NEON-NEXT:    movle r2, #2
90; CHECK-NEON-NEXT:    mov r0, r2
91; CHECK-NEON-NEXT:    bx lr
92entry:
93    %tmp = icmp sle i32 %a.s, %b.s
94    %tmp1.s = select i1 %tmp, i32 2, i32 3
95    ret i32 %tmp1.s
96}
97
98define i32 @f5(i32 %a.u, i32 %b.u) {
99; CHECK-LABEL: f5:
100; CHECK:       @ %bb.0: @ %entry
101; CHECK-NEXT:    mov r2, #3
102; CHECK-NEXT:    cmp r0, r1
103; CHECK-NEXT:    movwls r2, #2
104; CHECK-NEXT:    mov r0, r2
105; CHECK-NEXT:    bx lr
106;
107; CHECK-NEON-LABEL: f5:
108; CHECK-NEON:       @ %bb.0: @ %entry
109; CHECK-NEON-NEXT:    movs r2, #3
110; CHECK-NEON-NEXT:    cmp r0, r1
111; CHECK-NEON-NEXT:    it ls
112; CHECK-NEON-NEXT:    movls r2, #2
113; CHECK-NEON-NEXT:    mov r0, r2
114; CHECK-NEON-NEXT:    bx lr
115entry:
116    %tmp = icmp ule i32 %a.u, %b.u
117    %tmp1.s = select i1 %tmp, i32 2, i32 3
118    ret i32 %tmp1.s
119}
120
121define i32 @f6(i32 %a.u, i32 %b.u) {
122; CHECK-LABEL: f6:
123; CHECK:       @ %bb.0: @ %entry
124; CHECK-NEXT:    mov r2, #3
125; CHECK-NEXT:    cmp r0, r1
126; CHECK-NEXT:    movwhi r2, #2
127; CHECK-NEXT:    mov r0, r2
128; CHECK-NEXT:    bx lr
129;
130; CHECK-NEON-LABEL: f6:
131; CHECK-NEON:       @ %bb.0: @ %entry
132; CHECK-NEON-NEXT:    movs r2, #3
133; CHECK-NEON-NEXT:    cmp r0, r1
134; CHECK-NEON-NEXT:    it hi
135; CHECK-NEON-NEXT:    movhi r2, #2
136; CHECK-NEON-NEXT:    mov r0, r2
137; CHECK-NEON-NEXT:    bx lr
138entry:
139    %tmp = icmp ugt i32 %a.u, %b.u
140    %tmp1.s = select i1 %tmp, i32 2, i32 3
141    ret i32 %tmp1.s
142}
143
144define double @f7(double %a, double %b) {
145; CHECK-ARM-LABEL: f7:
146; CHECK-ARM:       @ %bb.0:
147; CHECK-ARM-NEXT:    .save {r4, r5, r11, lr}
148; CHECK-ARM-NEXT:    push {r4, r5, r11, lr}
149; CHECK-ARM-NEXT:    mov r4, r3
150; CHECK-ARM-NEXT:    movw r3, #48758
151; CHECK-ARM-NEXT:    mov r5, r2
152; CHECK-ARM-NEXT:    movw r2, #14680
153; CHECK-ARM-NEXT:    movt r2, #51380
154; CHECK-ARM-NEXT:    movt r3, #16371
155; CHECK-ARM-NEXT:    bl __aeabi_dcmplt
156; CHECK-ARM-NEXT:    cmp r0, #0
157; CHECK-ARM-NEXT:    movwne r4, #0
158; CHECK-ARM-NEXT:    movwne r5, #0
159; CHECK-ARM-NEXT:    movtne r4, #49136
160; CHECK-ARM-NEXT:    mov r0, r5
161; CHECK-ARM-NEXT:    mov r1, r4
162; CHECK-ARM-NEXT:    pop {r4, r5, r11, pc}
163;
164; CHECK-VFP-LABEL: f7:
165; CHECK-VFP:       @ %bb.0:
166; CHECK-VFP-NEXT:    vldr d17, .LCPI6_0
167; CHECK-VFP-NEXT:    vmov d18, r0, r1
168; CHECK-VFP-NEXT:    vmov.f64 d16, #-1.000000e+00
169; CHECK-VFP-NEXT:    vcmp.f64 d18, d17
170; CHECK-VFP-NEXT:    vmrs APSR_nzcv, fpscr
171; CHECK-VFP-NEXT:    vmov d19, r2, r3
172; CHECK-VFP-NEXT:    vmovmi.f64 d19, d16
173; CHECK-VFP-NEXT:    vmov r0, r1, d19
174; CHECK-VFP-NEXT:    bx lr
175; CHECK-VFP-NEXT:    .p2align 3
176; CHECK-VFP-NEXT:  @ %bb.1:
177; CHECK-VFP-NEXT:  .LCPI6_0:
178; CHECK-VFP-NEXT:    .long 3367254360 @ double 1.234
179; CHECK-VFP-NEXT:    .long 1072938614
180;
181; CHECK-NEON-LABEL: f7:
182; CHECK-NEON:       @ %bb.0:
183; CHECK-NEON-NEXT:    vldr d17, LCPI6_0
184; CHECK-NEON-NEXT:    vmov d18, r0, r1
185; CHECK-NEON-NEXT:    vmov d19, r2, r3
186; CHECK-NEON-NEXT:    vcmp.f64 d18, d17
187; CHECK-NEON-NEXT:    vmov.f64 d16, #-1.000000e+00
188; CHECK-NEON-NEXT:    vmrs APSR_nzcv, fpscr
189; CHECK-NEON-NEXT:    it mi
190; CHECK-NEON-NEXT:    vmovmi.f64 d19, d16
191; CHECK-NEON-NEXT:    vmov r0, r1, d19
192; CHECK-NEON-NEXT:    bx lr
193; CHECK-NEON-NEXT:    .p2align 3
194; CHECK-NEON-NEXT:  @ %bb.1:
195; CHECK-NEON-NEXT:    .data_region
196; CHECK-NEON-NEXT:  LCPI6_0:
197; CHECK-NEON-NEXT:    .long 3367254360 @ double 1.234
198; CHECK-NEON-NEXT:    .long 1072938614
199; CHECK-NEON-NEXT:    .end_data_region
200    %tmp = fcmp olt double %a, 1.234e+00
201    %tmp1 = select i1 %tmp, double -1.000e+00, double %b
202    ret double %tmp1
203}
204
205; <rdar://problem/7260094>
206;
207; We used to generate really horrible code for this function. The main cause was
208; a lack of a custom lowering routine for an ISD::SELECT. This would result in
209; two "it" blocks in the code: one for the "icmp" and another to move the index
210; into the constant pool based on the value of the "icmp". If we have one "it"
211; block generated, odds are good that we have close to the ideal code for this.
212define arm_apcscc float @f8(i32 %a) nounwind {
213; CHECK-ARM-LABEL: f8:
214; CHECK-ARM:       @ %bb.0:
215; CHECK-ARM-NEXT:    movw r1, #29905
216; CHECK-ARM-NEXT:    movw r2, #1123
217; CHECK-ARM-NEXT:    movt r1, #16408
218; CHECK-ARM-NEXT:    cmp r0, r2
219; CHECK-ARM-NEXT:    movweq r1, #62390
220; CHECK-ARM-NEXT:    movteq r1, #16285
221; CHECK-ARM-NEXT:    mov r0, r1
222; CHECK-ARM-NEXT:    bx lr
223;
224; CHECK-VFP-LABEL: f8:
225; CHECK-VFP:       @ %bb.0:
226; CHECK-VFP-NEXT:    movw r2, #1123
227; CHECK-VFP-NEXT:    adr r1, .LCPI7_0
228; CHECK-VFP-NEXT:    cmp r0, r2
229; CHECK-VFP-NEXT:    addeq r1, r1, #4
230; CHECK-VFP-NEXT:    ldr r0, [r1]
231; CHECK-VFP-NEXT:    bx lr
232; CHECK-VFP-NEXT:    .p2align 2
233; CHECK-VFP-NEXT:  @ %bb.1:
234; CHECK-VFP-NEXT:  .LCPI7_0:
235; CHECK-VFP-NEXT:    .long 0x401874d1 @ float 2.38212991
236; CHECK-VFP-NEXT:    .long 0x3f9df3b6 @ float 1.23399997
237;
238; CHECK-NEON-LABEL: f8:
239; CHECK-NEON:       @ %bb.0:
240; CHECK-NEON-NEXT:    adr r1, LCPI7_0
241; CHECK-NEON-NEXT:    movw r2, #1123
242; CHECK-NEON-NEXT:    cmp r0, r2
243; CHECK-NEON-NEXT:    it eq
244; CHECK-NEON-NEXT:    addeq r1, #4
245; CHECK-NEON-NEXT:    ldr r0, [r1]
246; CHECK-NEON-NEXT:    bx lr
247; CHECK-NEON-NEXT:    .p2align 2
248; CHECK-NEON-NEXT:  @ %bb.1:
249; CHECK-NEON-NEXT:    .data_region
250; CHECK-NEON-NEXT:  LCPI7_0:
251; CHECK-NEON-NEXT:    .long 0x401874d1 @ float 2.38212991
252; CHECK-NEON-NEXT:    .long 0x3f9df3b6 @ float 1.23399997
253; CHECK-NEON-NEXT:    .end_data_region
254  %tmp = icmp eq i32 %a, 1123
255  %tmp1 = select i1 %tmp, float 0x3FF3BE76C0000000, float 0x40030E9A20000000
256  ret float %tmp1
257}
258
259; <rdar://problem/9049552>
260; Glue values can only have a single use, but the following test exposed a
261; case where a SELECT was lowered with 2 uses of a comparison, causing the
262; scheduler to assert.
263declare ptr @objc_msgSend(ptr, ptr, ...)
264define void @f9() optsize {
265; CHECK-LABEL: f9:
266; CHECK:       @ %bb.0: @ %entry
267; CHECK-NEXT:    .save {r11, lr}
268; CHECK-NEXT:    push {r11, lr}
269; CHECK-NEXT:    .pad #8
270; CHECK-NEXT:    sub sp, sp, #8
271; CHECK-NEXT:    movw r2, #0
272; CHECK-NEXT:    movw r3, #0
273; CHECK-NEXT:    mov r1, #1065353216
274; CHECK-NEXT:    mov r0, #0
275; CHECK-NEXT:    movt r2, #16672
276; CHECK-NEXT:    movt r3, #32704
277; CHECK-NEXT:    strd r0, r1, [sp]
278; CHECK-NEXT:    bl objc_msgSend
279; CHECK-NEXT:    add sp, sp, #8
280; CHECK-NEXT:    pop {r11, pc}
281;
282; CHECK-NEON-LABEL: f9:
283; CHECK-NEON:       @ %bb.0: @ %entry
284; CHECK-NEON-NEXT:    str lr, [sp, #-4]!
285; CHECK-NEON-NEXT:    sub sp, #8
286; CHECK-NEON-NEXT:    movs r2, #0
287; CHECK-NEON-NEXT:    movs r3, #0
288; CHECK-NEON-NEXT:    mov.w r0, #1065353216
289; CHECK-NEON-NEXT:    movs r1, #0
290; CHECK-NEON-NEXT:    movt r2, #16672
291; CHECK-NEON-NEXT:    movt r3, #32704
292; CHECK-NEON-NEXT:    strd r1, r0, [sp]
293; CHECK-NEON-NEXT:    bl _objc_msgSend
294; CHECK-NEON-NEXT:    add sp, #8
295; CHECK-NEON-NEXT:    ldr lr, [sp], #4
296; CHECK-NEON-NEXT:    bx lr
297entry:
298  %cmp = icmp eq ptr undef, inttoptr (i32 4 to ptr)
299  %conv191 = select i1 %cmp, float -3.000000e+00, float 0.000000e+00
300  %conv195 = select i1 %cmp, double -1.000000e+00, double 0.000000e+00
301  %add = fadd double %conv195, 1.100000e+01
302  %conv196 = fptrunc double %add to float
303  %add201 = fadd float undef, %conv191
304  %tmp484 = bitcast float %conv196 to i32
305  %tmp478 = bitcast float %add201 to i32
306  %tmp490 = insertvalue [2 x i32] undef, i32 %tmp484, 0
307  %tmp493 = insertvalue [2 x i32] %tmp490, i32 %tmp478, 1
308  call void @objc_msgSend(ptr undef, ptr undef, [2 x i32] %tmp493, i32 0, float 1.000000e+00) optsize
309  ret void
310}
311
312define float @f10(i32 %a, i32 %b) nounwind uwtable readnone ssp {
313; CHECK-ARM-LABEL: f10:
314; CHECK-ARM:       @ %bb.0:
315; CHECK-ARM-NEXT:    mov r2, #0
316; CHECK-ARM-NEXT:    cmp r0, r1
317; CHECK-ARM-NEXT:    moveq r2, #1065353216
318; CHECK-ARM-NEXT:    mov r0, r2
319; CHECK-ARM-NEXT:    bx lr
320;
321; CHECK-VFP-LABEL: f10:
322; CHECK-VFP:       @ %bb.0:
323; CHECK-VFP-NEXT:    vmov.f32 s0, #1.000000e+00
324; CHECK-VFP-NEXT:    vldr s2, .LCPI9_0
325; CHECK-VFP-NEXT:    cmp r0, r1
326; CHECK-VFP-NEXT:    vmoveq.f32 s2, s0
327; CHECK-VFP-NEXT:    vmov r0, s2
328; CHECK-VFP-NEXT:    bx lr
329; CHECK-VFP-NEXT:    .p2align 2
330; CHECK-VFP-NEXT:  @ %bb.1:
331; CHECK-VFP-NEXT:  .LCPI9_0:
332; CHECK-VFP-NEXT:    .long 0x00000000 @ float 0
333;
334; CHECK-NEON-LABEL: f10:
335; CHECK-NEON:       @ %bb.0:
336; CHECK-NEON-NEXT:    vldr s2, LCPI9_0
337; CHECK-NEON-NEXT:    vmov.f32 s0, #1.000000e+00
338; CHECK-NEON-NEXT:    cmp r0, r1
339; CHECK-NEON-NEXT:    it eq
340; CHECK-NEON-NEXT:    vmoveq.f32 s2, s0
341; CHECK-NEON-NEXT:    vmov r0, s2
342; CHECK-NEON-NEXT:    bx lr
343; CHECK-NEON-NEXT:    .p2align 2
344; CHECK-NEON-NEXT:  @ %bb.1:
345; CHECK-NEON-NEXT:    .data_region
346; CHECK-NEON-NEXT:  LCPI9_0:
347; CHECK-NEON-NEXT:    .long 0x00000000 @ float 0
348; CHECK-NEON-NEXT:    .end_data_region
349  %1 = icmp eq i32 %a, %b
350  %2 = zext i1 %1 to i32
351  %3 = sitofp i32 %2 to float
352  ret float %3
353}
354
355define float @f11(i32 %a, i32 %b) nounwind uwtable readnone ssp {
356; CHECK-ARM-LABEL: f11:
357; CHECK-ARM:       @ %bb.0:
358; CHECK-ARM-NEXT:    mov r2, #0
359; CHECK-ARM-NEXT:    cmp r0, r1
360; CHECK-ARM-NEXT:    movweq r2, #0
361; CHECK-ARM-NEXT:    movteq r2, #49024
362; CHECK-ARM-NEXT:    mov r0, r2
363; CHECK-ARM-NEXT:    bx lr
364;
365; CHECK-VFP-LABEL: f11:
366; CHECK-VFP:       @ %bb.0:
367; CHECK-VFP-NEXT:    vmov.f32 s0, #-1.000000e+00
368; CHECK-VFP-NEXT:    vldr s2, .LCPI10_0
369; CHECK-VFP-NEXT:    cmp r0, r1
370; CHECK-VFP-NEXT:    vmoveq.f32 s2, s0
371; CHECK-VFP-NEXT:    vmov r0, s2
372; CHECK-VFP-NEXT:    bx lr
373; CHECK-VFP-NEXT:    .p2align 2
374; CHECK-VFP-NEXT:  @ %bb.1:
375; CHECK-VFP-NEXT:  .LCPI10_0:
376; CHECK-VFP-NEXT:    .long 0x00000000 @ float 0
377;
378; CHECK-NEON-LABEL: f11:
379; CHECK-NEON:       @ %bb.0:
380; CHECK-NEON-NEXT:    vldr s2, LCPI10_0
381; CHECK-NEON-NEXT:    vmov.f32 s0, #-1.000000e+00
382; CHECK-NEON-NEXT:    cmp r0, r1
383; CHECK-NEON-NEXT:    it eq
384; CHECK-NEON-NEXT:    vmoveq.f32 s2, s0
385; CHECK-NEON-NEXT:    vmov r0, s2
386; CHECK-NEON-NEXT:    bx lr
387; CHECK-NEON-NEXT:    .p2align 2
388; CHECK-NEON-NEXT:  @ %bb.1:
389; CHECK-NEON-NEXT:    .data_region
390; CHECK-NEON-NEXT:  LCPI10_0:
391; CHECK-NEON-NEXT:    .long 0x00000000 @ float 0
392; CHECK-NEON-NEXT:    .end_data_region
393  %1 = icmp eq i32 %a, %b
394  %2 = sitofp i1 %1 to float
395  ret float %2
396}
397
398define float @f12(i32 %a, i32 %b) nounwind uwtable readnone ssp {
399; CHECK-ARM-LABEL: f12:
400; CHECK-ARM:       @ %bb.0:
401; CHECK-ARM-NEXT:    mov r2, #0
402; CHECK-ARM-NEXT:    cmp r0, r1
403; CHECK-ARM-NEXT:    moveq r2, #1065353216
404; CHECK-ARM-NEXT:    mov r0, r2
405; CHECK-ARM-NEXT:    bx lr
406;
407; CHECK-VFP-LABEL: f12:
408; CHECK-VFP:       @ %bb.0:
409; CHECK-VFP-NEXT:    vmov.f32 s0, #1.000000e+00
410; CHECK-VFP-NEXT:    vldr s2, .LCPI11_0
411; CHECK-VFP-NEXT:    cmp r0, r1
412; CHECK-VFP-NEXT:    vmoveq.f32 s2, s0
413; CHECK-VFP-NEXT:    vmov r0, s2
414; CHECK-VFP-NEXT:    bx lr
415; CHECK-VFP-NEXT:    .p2align 2
416; CHECK-VFP-NEXT:  @ %bb.1:
417; CHECK-VFP-NEXT:  .LCPI11_0:
418; CHECK-VFP-NEXT:    .long 0x00000000 @ float 0
419;
420; CHECK-NEON-LABEL: f12:
421; CHECK-NEON:       @ %bb.0:
422; CHECK-NEON-NEXT:    vldr s2, LCPI11_0
423; CHECK-NEON-NEXT:    vmov.f32 s0, #1.000000e+00
424; CHECK-NEON-NEXT:    cmp r0, r1
425; CHECK-NEON-NEXT:    it eq
426; CHECK-NEON-NEXT:    vmoveq.f32 s2, s0
427; CHECK-NEON-NEXT:    vmov r0, s2
428; CHECK-NEON-NEXT:    bx lr
429; CHECK-NEON-NEXT:    .p2align 2
430; CHECK-NEON-NEXT:  @ %bb.1:
431; CHECK-NEON-NEXT:    .data_region
432; CHECK-NEON-NEXT:  LCPI11_0:
433; CHECK-NEON-NEXT:    .long 0x00000000 @ float 0
434; CHECK-NEON-NEXT:    .end_data_region
435  %1 = icmp eq i32 %a, %b
436  %2 = uitofp i1 %1 to float
437  ret float %2
438}
439
440define i1 @test_overflow_recombine(i32 %in1, i32 %in2) {
441; CHECK-LABEL: test_overflow_recombine:
442; CHECK:       @ %bb.0:
443; CHECK-NEXT:    mul r2, r0, r1
444; CHECK-NEXT:    smmul r0, r0, r1
445; CHECK-NEXT:    subs r0, r0, r2, asr #31
446; CHECK-NEXT:    movwne r0, #1
447; CHECK-NEXT:    bx lr
448;
449; CHECK-NEON-LABEL: test_overflow_recombine:
450; CHECK-NEON:       @ %bb.0:
451; CHECK-NEON-NEXT:    mul r2, r0, r1
452; CHECK-NEON-NEXT:    smmul r0, r0, r1
453; CHECK-NEON-NEXT:    subs.w r0, r0, r2, asr #31
454; CHECK-NEON-NEXT:    it ne
455; CHECK-NEON-NEXT:    movne r0, #1
456; CHECK-NEON-NEXT:    bx lr
457  %prod = call { i32, i1 } @llvm.smul.with.overflow.i32(i32 %in1, i32 %in2)
458  %overflow = extractvalue { i32, i1 } %prod, 1
459  ret i1 %overflow
460}
461
462declare { i32, i1 } @llvm.smul.with.overflow.i32(i32, i32)
463