xref: /llvm-project/llvm/test/CodeGen/X86/dagcombine-select.ll (revision a2a0089ac3a5781ba74d4d319c87c9e8b46d4eda)
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2; RUN: llc < %s -mtriple=x86_64-unknown-unknown -verify-machineinstrs | FileCheck %s --check-prefixes=CHECK,NOBMI -enable-var-scope
3; RUN: llc < %s -mtriple=x86_64-unknown-unknown -verify-machineinstrs -mattr=+bmi | FileCheck %s -check-prefixes=CHECK,BMI -enable-var-scope
4
5define i32 @select_and1(i32 %x, i32 %y) {
6; CHECK-LABEL: select_and1:
7; CHECK:       # %bb.0:
8; CHECK-NEXT:    xorl %eax, %eax
9; CHECK-NEXT:    cmpl $11, %edi
10; CHECK-NEXT:    cmovgel %esi, %eax
11; CHECK-NEXT:    retq
12  %c = icmp slt i32 %x, 11
13  %s = select i1 %c, i32 0, i32 -1
14  %a = and i32 %y, %s
15  ret i32 %a
16}
17
18define i32 @select_and2(i32 %x, i32 %y) {
19; CHECK-LABEL: select_and2:
20; CHECK:       # %bb.0:
21; CHECK-NEXT:    xorl %eax, %eax
22; CHECK-NEXT:    cmpl $11, %edi
23; CHECK-NEXT:    cmovgel %esi, %eax
24; CHECK-NEXT:    retq
25  %c = icmp slt i32 %x, 11
26  %s = select i1 %c, i32 0, i32 -1
27  %a = and i32 %s, %y
28  ret i32 %a
29}
30
31define i32 @select_and3(i32 %x, i32 %y) {
32; CHECK-LABEL: select_and3:
33; CHECK:       # %bb.0:
34; CHECK-NEXT:    xorl %eax, %eax
35; CHECK-NEXT:    cmpl $11, %edi
36; CHECK-NEXT:    cmovll %esi, %eax
37; CHECK-NEXT:    retq
38  %c = icmp slt i32 %x, 11
39  %s = select i1 %c, i32 -1, i32 0
40  %a = and i32 %y, %s
41  ret i32 %a
42}
43
44define <4 x i32> @select_and_v4(i32 %x, <4 x i32> %y) {
45; CHECK-LABEL: select_and_v4:
46; CHECK:       # %bb.0:
47; CHECK-NEXT:    cmpl $11, %edi
48; CHECK-NEXT:    xorps %xmm1, %xmm1
49; CHECK-NEXT:    jl .LBB3_2
50; CHECK-NEXT:  # %bb.1:
51; CHECK-NEXT:    movaps %xmm0, %xmm1
52; CHECK-NEXT:  .LBB3_2:
53; CHECK-NEXT:    movaps %xmm1, %xmm0
54; CHECK-NEXT:    retq
55  %c = icmp slt i32 %x, 11
56  %s = select i1 %c, <4 x i32> zeroinitializer, <4 x i32><i32 -1, i32 -1, i32 -1, i32 -1>
57  %a = and <4 x i32> %s, %y
58  ret <4 x i32> %a
59}
60
61define i32 @select_or1(i32 %x, i32 %y) {
62; CHECK-LABEL: select_or1:
63; CHECK:       # %bb.0:
64; CHECK-NEXT:    cmpl $11, %edi
65; CHECK-NEXT:    movl $-1, %eax
66; CHECK-NEXT:    cmovll %esi, %eax
67; CHECK-NEXT:    retq
68  %c = icmp slt i32 %x, 11
69  %s = select i1 %c, i32 0, i32 -1
70  %a = or i32 %y, %s
71  ret i32 %a
72}
73
74define i32 @select_or2(i32 %x, i32 %y) {
75; CHECK-LABEL: select_or2:
76; CHECK:       # %bb.0:
77; CHECK-NEXT:    cmpl $11, %edi
78; CHECK-NEXT:    movl $-1, %eax
79; CHECK-NEXT:    cmovll %esi, %eax
80; CHECK-NEXT:    retq
81  %c = icmp slt i32 %x, 11
82  %s = select i1 %c, i32 0, i32 -1
83  %a = or i32 %s, %y
84  ret i32 %a
85}
86
87define i32 @select_or3(i32 %x, i32 %y) {
88; CHECK-LABEL: select_or3:
89; CHECK:       # %bb.0:
90; CHECK-NEXT:    cmpl $11, %edi
91; CHECK-NEXT:    movl $-1, %eax
92; CHECK-NEXT:    cmovgel %esi, %eax
93; CHECK-NEXT:    retq
94  %c = icmp slt i32 %x, 11
95  %s = select i1 %c, i32 -1, i32 0
96  %a = or i32 %y, %s
97  ret i32 %a
98}
99
100define <4 x i32> @select_or_v4(i32 %x, <4 x i32> %y) {
101; CHECK-LABEL: select_or_v4:
102; CHECK:       # %bb.0:
103; CHECK-NEXT:    cmpl $11, %edi
104; CHECK-NEXT:    jl .LBB7_2
105; CHECK-NEXT:  # %bb.1:
106; CHECK-NEXT:    pcmpeqd %xmm0, %xmm0
107; CHECK-NEXT:  .LBB7_2:
108; CHECK-NEXT:    retq
109  %c = icmp slt i32 %x, 11
110  %s = select i1 %c, <4 x i32> zeroinitializer, <4 x i32><i32 -1, i32 -1, i32 -1, i32 -1>
111  %a = or <4 x i32> %s, %y
112  ret <4 x i32> %a
113}
114
115define i32 @sel_constants_sub_constant_sel_constants(i1 %cond) {
116; CHECK-LABEL: sel_constants_sub_constant_sel_constants:
117; CHECK:       # %bb.0:
118; CHECK-NEXT:    testb $1, %dil
119; CHECK-NEXT:    movl $9, %ecx
120; CHECK-NEXT:    movl $2, %eax
121; CHECK-NEXT:    cmovnel %ecx, %eax
122; CHECK-NEXT:    retq
123  %sel = select i1 %cond, i32 -4, i32 3
124  %bo = sub i32 5, %sel
125  ret i32 %bo
126}
127
128define i32 @sdiv_constant_sel_constants(i1 %cond) {
129; CHECK-LABEL: sdiv_constant_sel_constants:
130; CHECK:       # %bb.0:
131; CHECK-NEXT:    notb %dil
132; CHECK-NEXT:    movzbl %dil, %eax
133; CHECK-NEXT:    andl $1, %eax
134; CHECK-NEXT:    leal (%rax,%rax,4), %eax
135; CHECK-NEXT:    retq
136  %sel = select i1 %cond, i32 121, i32 23
137  %bo = sdiv i32 120, %sel
138  ret i32 %bo
139}
140
141define i32 @udiv_constant_sel_constants(i1 %cond) {
142; CHECK-LABEL: udiv_constant_sel_constants:
143; CHECK:       # %bb.0:
144; CHECK-NEXT:    notb %dil
145; CHECK-NEXT:    movzbl %dil, %eax
146; CHECK-NEXT:    andl $1, %eax
147; CHECK-NEXT:    leal (%rax,%rax,4), %eax
148; CHECK-NEXT:    retq
149  %sel = select i1 %cond, i32 -4, i32 23
150  %bo = udiv i32 120, %sel
151  ret i32 %bo
152}
153
154define i32 @srem_constant_sel_constants(i1 %cond) {
155; CHECK-LABEL: srem_constant_sel_constants:
156; CHECK:       # %bb.0:
157; CHECK-NEXT:    testb $1, %dil
158; CHECK-NEXT:    movl $120, %ecx
159; CHECK-NEXT:    movl $5, %eax
160; CHECK-NEXT:    cmovnel %ecx, %eax
161; CHECK-NEXT:    retq
162  %sel = select i1 %cond, i32 121, i32 23
163  %bo = srem i32 120, %sel
164  ret i32 %bo
165}
166
167define i32 @urem_constant_sel_constants(i1 %cond) {
168; CHECK-LABEL: urem_constant_sel_constants:
169; CHECK:       # %bb.0:
170; CHECK-NEXT:    testb $1, %dil
171; CHECK-NEXT:    movl $120, %ecx
172; CHECK-NEXT:    movl $5, %eax
173; CHECK-NEXT:    cmovnel %ecx, %eax
174; CHECK-NEXT:    retq
175  %sel = select i1 %cond, i32 -4, i32 23
176  %bo = urem i32 120, %sel
177  ret i32 %bo
178}
179
180define i32 @sel_constants_shl_constant(i1 %cond) {
181; CHECK-LABEL: sel_constants_shl_constant:
182; CHECK:       # %bb.0:
183; CHECK-NEXT:    notb %dil
184; CHECK-NEXT:    movzbl %dil, %eax
185; CHECK-NEXT:    andl $1, %eax
186; CHECK-NEXT:    orl $2, %eax
187; CHECK-NEXT:    shll $8, %eax
188; CHECK-NEXT:    retq
189  %sel = select i1 %cond, i32 2, i32 3
190  %bo = shl i32 %sel, 8
191  ret i32 %bo
192}
193
194define i32 @shl_constant_sel_constants(i1 %cond) {
195; CHECK-LABEL: shl_constant_sel_constants:
196; CHECK:       # %bb.0:
197; CHECK-NEXT:    notb %dil
198; CHECK-NEXT:    movzbl %dil, %eax
199; CHECK-NEXT:    andl $1, %eax
200; CHECK-NEXT:    leal 4(,%rax,4), %eax
201; CHECK-NEXT:    retq
202  %sel = select i1 %cond, i32 2, i32 3
203  %bo = shl i32 1, %sel
204  ret i32 %bo
205}
206
207define i32 @shl_constant_sel_setcc(i32 %a) {
208; CHECK-LABEL: shl_constant_sel_setcc:
209; CHECK:       # %bb.0:
210; CHECK-NEXT:    xorl %eax, %eax
211; CHECK-NEXT:    testb $1, %dil
212; CHECK-NEXT:    sete %al
213; CHECK-NEXT:    leal 4(,%rax,4), %eax
214; CHECK-NEXT:    retq
215  %m = and i32 %a, 1
216  %cond = icmp ne i32 %m, 0
217  %sel = select i1 %cond, i32 2, i32 3
218  %bo = shl i32 1, %sel
219  ret i32 %bo
220}
221
222define i32 @lshr_constant_sel_constants(i1 %cond) {
223; CHECK-LABEL: lshr_constant_sel_constants:
224; CHECK:       # %bb.0:
225; CHECK-NEXT:    # kill: def $edi killed $edi def $rdi
226; CHECK-NEXT:    andl $1, %edi
227; CHECK-NEXT:    leal 8(,%rdi,8), %eax
228; CHECK-NEXT:    retq
229  %sel = select i1 %cond, i32 2, i32 3
230  %bo = lshr i32 64, %sel
231  ret i32 %bo
232}
233
234define i32 @lshr_constant_sel_setcc(i32 %a) {
235; CHECK-LABEL: lshr_constant_sel_setcc:
236; CHECK:       # %bb.0:
237; CHECK-NEXT:    # kill: def $edi killed $edi def $rdi
238; CHECK-NEXT:    andl $1, %edi
239; CHECK-NEXT:    leal 8(,%rdi,8), %eax
240; CHECK-NEXT:    retq
241  %m = and i32 %a, 1
242  %cond = icmp ne i32 %m, 0
243  %sel = select i1 %cond, i32 2, i32 3
244  %bo = lshr i32 64, %sel
245  ret i32 %bo
246}
247
248define i32 @ashr_constant_sel_constants(i1 %cond) {
249; CHECK-LABEL: ashr_constant_sel_constants:
250; CHECK:       # %bb.0:
251; CHECK-NEXT:    # kill: def $edi killed $edi def $rdi
252; CHECK-NEXT:    andl $1, %edi
253; CHECK-NEXT:    shll $4, %edi
254; CHECK-NEXT:    leal 16(%rdi), %eax
255; CHECK-NEXT:    retq
256  %sel = select i1 %cond, i32 2, i32 3
257  %bo = ashr i32 128, %sel
258  ret i32 %bo
259}
260
261define i32 @ashr_constant_sel_setcc(i32 %a) {
262; CHECK-LABEL: ashr_constant_sel_setcc:
263; CHECK:       # %bb.0:
264; CHECK-NEXT:    # kill: def $edi killed $edi def $rdi
265; CHECK-NEXT:    andl $1, %edi
266; CHECK-NEXT:    shll $4, %edi
267; CHECK-NEXT:    leal 16(%rdi), %eax
268; CHECK-NEXT:    retq
269  %m = and i32 %a, 1
270  %cond = icmp ne i32 %m, 0
271  %sel = select i1 %cond, i32 2, i32 3
272  %bo = ashr i32 128, %sel
273  ret i32 %bo
274}
275
276define double @fsub_constant_sel_constants(i1 %cond) {
277; CHECK-LABEL: fsub_constant_sel_constants:
278; CHECK:       # %bb.0:
279; CHECK-NEXT:    testb $1, %dil
280; CHECK-NEXT:    jne .LBB20_1
281; CHECK-NEXT:  # %bb.2:
282; CHECK-NEXT:    movsd {{.*#+}} xmm0 = [-1.8200000000000003E+1,0.0E+0]
283; CHECK-NEXT:    retq
284; CHECK-NEXT:  .LBB20_1:
285; CHECK-NEXT:    movsd {{.*#+}} xmm0 = [9.0999999999999996E+0,0.0E+0]
286; CHECK-NEXT:    retq
287  %sel = select i1 %cond, double -4.0, double 23.3
288  %bo = fsub double 5.1, %sel
289  ret double %bo
290}
291
292define double @fdiv_constant_sel_constants(i1 %cond) {
293; CHECK-LABEL: fdiv_constant_sel_constants:
294; CHECK:       # %bb.0:
295; CHECK-NEXT:    testb $1, %dil
296; CHECK-NEXT:    jne .LBB21_1
297; CHECK-NEXT:  # %bb.2:
298; CHECK-NEXT:    movsd {{.*#+}} xmm0 = [2.188841201716738E-1,0.0E+0]
299; CHECK-NEXT:    retq
300; CHECK-NEXT:  .LBB21_1:
301; CHECK-NEXT:    movsd {{.*#+}} xmm0 = [-1.2749999999999999E+0,0.0E+0]
302; CHECK-NEXT:    retq
303  %sel = select i1 %cond, double -4.0, double 23.3
304  %bo = fdiv double 5.1, %sel
305  ret double %bo
306}
307
308define double @frem_constant_sel_constants(i1 %cond) {
309; CHECK-LABEL: frem_constant_sel_constants:
310; CHECK:       # %bb.0:
311; CHECK-NEXT:    testb $1, %dil
312; CHECK-NEXT:    jne .LBB22_1
313; CHECK-NEXT:  # %bb.2:
314; CHECK-NEXT:    movsd {{.*#+}} xmm0 = [5.0999999999999996E+0,0.0E+0]
315; CHECK-NEXT:    retq
316; CHECK-NEXT:  .LBB22_1:
317; CHECK-NEXT:    movsd {{.*#+}} xmm0 = [1.0999999999999996E+0,0.0E+0]
318; CHECK-NEXT:    retq
319  %sel = select i1 %cond, double -4.0, double 23.3
320  %bo = frem double 5.1, %sel
321  ret double %bo
322}
323
324declare i64 @llvm.cttz.i64(i64, i1)
325define i64 @cttz_64_eq_select(i64 %v) nounwind {
326; NOBMI-LABEL: cttz_64_eq_select:
327; NOBMI:       # %bb.0:
328; NOBMI-NEXT:    bsfq %rdi, %rcx
329; NOBMI-NEXT:    movq $-1, %rax
330; NOBMI-NEXT:    cmovneq %rcx, %rax
331; NOBMI-NEXT:    addq $6, %rax
332; NOBMI-NEXT:    retq
333;
334; BMI-LABEL: cttz_64_eq_select:
335; BMI:       # %bb.0:
336; BMI-NEXT:    tzcntq %rdi, %rcx
337; BMI-NEXT:    movq $-1, %rax
338; BMI-NEXT:    cmovaeq %rcx, %rax
339; BMI-NEXT:    addq $6, %rax
340; BMI-NEXT:    retq
341
342  %cnt = tail call i64 @llvm.cttz.i64(i64 %v, i1 true)
343  %tobool = icmp eq i64 %v, 0
344  %.op = add nuw nsw i64 %cnt, 6
345  %add = select i1 %tobool, i64 5, i64 %.op
346  ret i64 %add
347}
348
349define i64 @cttz_64_ne_select(i64 %v) nounwind {
350; NOBMI-LABEL: cttz_64_ne_select:
351; NOBMI:       # %bb.0:
352; NOBMI-NEXT:    bsfq %rdi, %rcx
353; NOBMI-NEXT:    movq $-1, %rax
354; NOBMI-NEXT:    cmovneq %rcx, %rax
355; NOBMI-NEXT:    addq $6, %rax
356; NOBMI-NEXT:    retq
357;
358; BMI-LABEL: cttz_64_ne_select:
359; BMI:       # %bb.0:
360; BMI-NEXT:    tzcntq %rdi, %rcx
361; BMI-NEXT:    movq $-1, %rax
362; BMI-NEXT:    cmovaeq %rcx, %rax
363; BMI-NEXT:    addq $6, %rax
364; BMI-NEXT:    retq
365
366  %cnt = tail call i64 @llvm.cttz.i64(i64 %v, i1 true)
367  %tobool = icmp ne i64 %v, 0
368  %.op = add nuw nsw i64 %cnt, 6
369  %add = select i1 %tobool, i64 %.op, i64 5
370  ret i64 %add
371}
372
373declare i32 @llvm.cttz.i32(i32, i1)
374define i32 @cttz_32_eq_select(i32 %v) nounwind {
375; NOBMI-LABEL: cttz_32_eq_select:
376; NOBMI:       # %bb.0:
377; NOBMI-NEXT:    bsfl %edi, %ecx
378; NOBMI-NEXT:    movl $-1, %eax
379; NOBMI-NEXT:    cmovnel %ecx, %eax
380; NOBMI-NEXT:    addl $6, %eax
381; NOBMI-NEXT:    retq
382;
383; BMI-LABEL: cttz_32_eq_select:
384; BMI:       # %bb.0:
385; BMI-NEXT:    tzcntl %edi, %ecx
386; BMI-NEXT:    movl $-1, %eax
387; BMI-NEXT:    cmovael %ecx, %eax
388; BMI-NEXT:    addl $6, %eax
389; BMI-NEXT:    retq
390
391  %cnt = tail call i32 @llvm.cttz.i32(i32 %v, i1 true)
392  %tobool = icmp eq i32 %v, 0
393  %.op = add nuw nsw i32 %cnt, 6
394  %add = select i1 %tobool, i32 5, i32 %.op
395  ret i32 %add
396}
397
398define i32 @cttz_32_ne_select(i32 %v) nounwind {
399; NOBMI-LABEL: cttz_32_ne_select:
400; NOBMI:       # %bb.0:
401; NOBMI-NEXT:    bsfl %edi, %ecx
402; NOBMI-NEXT:    movl $-1, %eax
403; NOBMI-NEXT:    cmovnel %ecx, %eax
404; NOBMI-NEXT:    addl $6, %eax
405; NOBMI-NEXT:    retq
406;
407; BMI-LABEL: cttz_32_ne_select:
408; BMI:       # %bb.0:
409; BMI-NEXT:    tzcntl %edi, %ecx
410; BMI-NEXT:    movl $-1, %eax
411; BMI-NEXT:    cmovael %ecx, %eax
412; BMI-NEXT:    addl $6, %eax
413; BMI-NEXT:    retq
414
415  %cnt = tail call i32 @llvm.cttz.i32(i32 %v, i1 true)
416  %tobool = icmp ne i32 %v, 0
417  %.op = add nuw nsw i32 %cnt, 6
418  %add = select i1 %tobool, i32 %.op, i32 5
419  ret i32 %add
420}
421
422; This matches the pattern emitted for __builtin_ffs
423define i32 @cttz_32_eq_select_ffs(i32 %v) nounwind {
424; NOBMI-LABEL: cttz_32_eq_select_ffs:
425; NOBMI:       # %bb.0:
426; NOBMI-NEXT:    bsfl %edi, %ecx
427; NOBMI-NEXT:    movl $-1, %eax
428; NOBMI-NEXT:    cmovnel %ecx, %eax
429; NOBMI-NEXT:    incl %eax
430; NOBMI-NEXT:    retq
431;
432; BMI-LABEL: cttz_32_eq_select_ffs:
433; BMI:       # %bb.0:
434; BMI-NEXT:    tzcntl %edi, %ecx
435; BMI-NEXT:    movl $-1, %eax
436; BMI-NEXT:    cmovael %ecx, %eax
437; BMI-NEXT:    incl %eax
438; BMI-NEXT:    retq
439
440  %cnt = tail call i32 @llvm.cttz.i32(i32 %v, i1 true)
441  %tobool = icmp eq i32 %v, 0
442  %.op = add nuw nsw i32 %cnt, 1
443  %add = select i1 %tobool, i32 0, i32 %.op
444  ret i32 %add
445}
446
447define i32 @cttz_32_ne_select_ffs(i32 %v) nounwind {
448; NOBMI-LABEL: cttz_32_ne_select_ffs:
449; NOBMI:       # %bb.0:
450; NOBMI-NEXT:    bsfl %edi, %ecx
451; NOBMI-NEXT:    movl $-1, %eax
452; NOBMI-NEXT:    cmovnel %ecx, %eax
453; NOBMI-NEXT:    incl %eax
454; NOBMI-NEXT:    retq
455;
456; BMI-LABEL: cttz_32_ne_select_ffs:
457; BMI:       # %bb.0:
458; BMI-NEXT:    tzcntl %edi, %ecx
459; BMI-NEXT:    movl $-1, %eax
460; BMI-NEXT:    cmovael %ecx, %eax
461; BMI-NEXT:    incl %eax
462; BMI-NEXT:    retq
463
464  %cnt = tail call i32 @llvm.cttz.i32(i32 %v, i1 true)
465  %tobool = icmp ne i32 %v, 0
466  %.op = add nuw nsw i32 %cnt, 1
467  %add = select i1 %tobool, i32 %.op, i32 0
468  ret i32 %add
469}
470
471; This matches the pattern emitted for __builtin_ffs - 1
472define i32 @cttz_32_eq_select_ffs_m1(i32 %v) nounwind {
473; NOBMI-LABEL: cttz_32_eq_select_ffs_m1:
474; NOBMI:       # %bb.0:
475; NOBMI-NEXT:    bsfl %edi, %ecx
476; NOBMI-NEXT:    movl $-1, %eax
477; NOBMI-NEXT:    cmovnel %ecx, %eax
478; NOBMI-NEXT:    retq
479;
480; BMI-LABEL: cttz_32_eq_select_ffs_m1:
481; BMI:       # %bb.0:
482; BMI-NEXT:    tzcntl %edi, %ecx
483; BMI-NEXT:    movl $-1, %eax
484; BMI-NEXT:    cmovael %ecx, %eax
485; BMI-NEXT:    retq
486
487  %cnt = tail call i32 @llvm.cttz.i32(i32 %v, i1 true)
488  %tobool = icmp eq i32 %v, 0
489  %sel = select i1 %tobool, i32 -1, i32 %cnt
490  ret i32 %sel
491}
492
493define i32 @cttz_32_ne_select_ffs_m1(i32 %v) nounwind {
494; NOBMI-LABEL: cttz_32_ne_select_ffs_m1:
495; NOBMI:       # %bb.0:
496; NOBMI-NEXT:    bsfl %edi, %ecx
497; NOBMI-NEXT:    movl $-1, %eax
498; NOBMI-NEXT:    cmovnel %ecx, %eax
499; NOBMI-NEXT:    retq
500;
501; BMI-LABEL: cttz_32_ne_select_ffs_m1:
502; BMI:       # %bb.0:
503; BMI-NEXT:    tzcntl %edi, %ecx
504; BMI-NEXT:    movl $-1, %eax
505; BMI-NEXT:    cmovael %ecx, %eax
506; BMI-NEXT:    retq
507
508  %cnt = tail call i32 @llvm.cttz.i32(i32 %v, i1 true)
509  %tobool = icmp ne i32 %v, 0
510  %sel = select i1 %tobool, i32 %cnt, i32 -1
511  ret i32 %sel
512}
513