1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2; RUN: llc < %s -mtriple=x86_64-unknown-unknown | FileCheck %s
3
4; Select of constants: control flow / conditional moves can always be replaced by logic+math (but may not be worth it?).
5; Test the zeroext/signext variants of each pattern to see if that makes a difference.
6
7; select Cond, 0, 1 --> zext (!Cond)
8
9define i32 @select_0_or_1(i1 %cond) {
10; CHECK-LABEL: select_0_or_1:
11; CHECK:       # %bb.0:
12; CHECK-NEXT:    notb %dil
13; CHECK-NEXT:    movzbl %dil, %eax
14; CHECK-NEXT:    andl $1, %eax
15; CHECK-NEXT:    retq
16  %sel = select i1 %cond, i32 0, i32 1
17  ret i32 %sel
18}
19
20define i32 @select_0_or_1_zeroext(i1 zeroext %cond) {
21; CHECK-LABEL: select_0_or_1_zeroext:
22; CHECK:       # %bb.0:
23; CHECK-NEXT:    xorb $1, %dil
24; CHECK-NEXT:    movzbl %dil, %eax
25; CHECK-NEXT:    retq
26  %sel = select i1 %cond, i32 0, i32 1
27  ret i32 %sel
28}
29
30define i32 @select_0_or_1_signext(i1 signext %cond) {
31; CHECK-LABEL: select_0_or_1_signext:
32; CHECK:       # %bb.0:
33; CHECK-NEXT:    notb %dil
34; CHECK-NEXT:    movzbl %dil, %eax
35; CHECK-NEXT:    andl $1, %eax
36; CHECK-NEXT:    retq
37  %sel = select i1 %cond, i32 0, i32 1
38  ret i32 %sel
39}
40
41; select Cond, 1, 0 --> zext (Cond)
42
43define i32 @select_1_or_0(i1 %cond) {
44; CHECK-LABEL: select_1_or_0:
45; CHECK:       # %bb.0:
46; CHECK-NEXT:    movl %edi, %eax
47; CHECK-NEXT:    andl $1, %eax
48; CHECK-NEXT:    retq
49  %sel = select i1 %cond, i32 1, i32 0
50  ret i32 %sel
51}
52
53define i32 @select_1_or_0_zeroext(i1 zeroext %cond) {
54; CHECK-LABEL: select_1_or_0_zeroext:
55; CHECK:       # %bb.0:
56; CHECK-NEXT:    movl %edi, %eax
57; CHECK-NEXT:    retq
58  %sel = select i1 %cond, i32 1, i32 0
59  ret i32 %sel
60}
61
62define i32 @select_1_or_0_signext(i1 signext %cond) {
63; CHECK-LABEL: select_1_or_0_signext:
64; CHECK:       # %bb.0:
65; CHECK-NEXT:    movl %edi, %eax
66; CHECK-NEXT:    andl $1, %eax
67; CHECK-NEXT:    retq
68  %sel = select i1 %cond, i32 1, i32 0
69  ret i32 %sel
70}
71
72; select Cond, 0, -1 --> sext (!Cond)
73
74define i32 @select_0_or_neg1(i1 %cond) {
75; CHECK-LABEL: select_0_or_neg1:
76; CHECK:       # %bb.0:
77; CHECK-NEXT:    # kill: def $edi killed $edi def $rdi
78; CHECK-NEXT:    andl $1, %edi
79; CHECK-NEXT:    leal -1(%rdi), %eax
80; CHECK-NEXT:    retq
81  %sel = select i1 %cond, i32 0, i32 -1
82  ret i32 %sel
83}
84
85define i32 @select_0_or_neg1_zeroext(i1 zeroext %cond) {
86; CHECK-LABEL: select_0_or_neg1_zeroext:
87; CHECK:       # %bb.0:
88; CHECK-NEXT:    # kill: def $edi killed $edi def $rdi
89; CHECK-NEXT:    leal -1(%rdi), %eax
90; CHECK-NEXT:    retq
91  %sel = select i1 %cond, i32 0, i32 -1
92  ret i32 %sel
93}
94
95define i32 @select_0_or_neg1_signext(i1 signext %cond) {
96; CHECK-LABEL: select_0_or_neg1_signext:
97; CHECK:       # %bb.0:
98; CHECK-NEXT:    movl %edi, %eax
99; CHECK-NEXT:    notl %eax
100; CHECK-NEXT:    retq
101  %sel = select i1 %cond, i32 0, i32 -1
102  ret i32 %sel
103}
104
105; select Cond, -1, 0 --> sext (Cond)
106
107define i32 @select_neg1_or_0(i1 %cond) {
108; CHECK-LABEL: select_neg1_or_0:
109; CHECK:       # %bb.0:
110; CHECK-NEXT:    movl %edi, %eax
111; CHECK-NEXT:    andl $1, %eax
112; CHECK-NEXT:    negl %eax
113; CHECK-NEXT:    retq
114  %sel = select i1 %cond, i32 -1, i32 0
115  ret i32 %sel
116}
117
118define i32 @select_neg1_or_0_zeroext(i1 zeroext %cond) {
119; CHECK-LABEL: select_neg1_or_0_zeroext:
120; CHECK:       # %bb.0:
121; CHECK-NEXT:    movl %edi, %eax
122; CHECK-NEXT:    negl %eax
123; CHECK-NEXT:    retq
124  %sel = select i1 %cond, i32 -1, i32 0
125  ret i32 %sel
126}
127
128define i32 @select_neg1_or_0_signext(i1 signext %cond) {
129; CHECK-LABEL: select_neg1_or_0_signext:
130; CHECK:       # %bb.0:
131; CHECK-NEXT:    movl %edi, %eax
132; CHECK-NEXT:    retq
133  %sel = select i1 %cond, i32 -1, i32 0
134  ret i32 %sel
135}
136
137; select Cond, C+1, C --> add (zext Cond), C
138
139define i32 @select_Cplus1_C(i1 %cond) {
140; CHECK-LABEL: select_Cplus1_C:
141; CHECK:       # %bb.0:
142; CHECK-NEXT:    # kill: def $edi killed $edi def $rdi
143; CHECK-NEXT:    andl $1, %edi
144; CHECK-NEXT:    leal 41(%rdi), %eax
145; CHECK-NEXT:    retq
146  %sel = select i1 %cond, i32 42, i32 41
147  ret i32 %sel
148}
149
150define i32 @select_Cplus1_C_zeroext(i1 zeroext %cond) {
151; CHECK-LABEL: select_Cplus1_C_zeroext:
152; CHECK:       # %bb.0:
153; CHECK-NEXT:    # kill: def $edi killed $edi def $rdi
154; CHECK-NEXT:    leal 41(%rdi), %eax
155; CHECK-NEXT:    retq
156  %sel = select i1 %cond, i32 42, i32 41
157  ret i32 %sel
158}
159
160define i32 @select_Cplus1_C_signext(i1 signext %cond) {
161; CHECK-LABEL: select_Cplus1_C_signext:
162; CHECK:       # %bb.0:
163; CHECK-NEXT:    movl $41, %eax
164; CHECK-NEXT:    subl %edi, %eax
165; CHECK-NEXT:    retq
166  %sel = select i1 %cond, i32 42, i32 41
167  ret i32 %sel
168}
169
170; select Cond, C, C+1 --> add (sext Cond), C
171
172define i32 @select_C_Cplus1(i1 %cond) {
173; CHECK-LABEL: select_C_Cplus1:
174; CHECK:       # %bb.0:
175; CHECK-NEXT:    andl $1, %edi
176; CHECK-NEXT:    movl $42, %eax
177; CHECK-NEXT:    subl %edi, %eax
178; CHECK-NEXT:    retq
179  %sel = select i1 %cond, i32 41, i32 42
180  ret i32 %sel
181}
182
183define i32 @select_C_Cplus1_zeroext(i1 zeroext %cond) {
184; CHECK-LABEL: select_C_Cplus1_zeroext:
185; CHECK:       # %bb.0:
186; CHECK-NEXT:    movl $42, %eax
187; CHECK-NEXT:    subl %edi, %eax
188; CHECK-NEXT:    retq
189  %sel = select i1 %cond, i32 41, i32 42
190  ret i32 %sel
191}
192
193define i32 @select_C_Cplus1_signext(i1 signext %cond) {
194; CHECK-LABEL: select_C_Cplus1_signext:
195; CHECK:       # %bb.0:
196; CHECK-NEXT:    # kill: def $edi killed $edi def $rdi
197; CHECK-NEXT:    leal 42(%rdi), %eax
198; CHECK-NEXT:    retq
199  %sel = select i1 %cond, i32 41, i32 42
200  ret i32 %sel
201}
202
203; If the constants differ by a small multiplier, use LEA.
204; select Cond, C1, C2 --> add (mul (zext Cond), C1-C2), C2 --> LEA C2(Cond * (C1-C2))
205
206define i32 @select_lea_2(i1 zeroext %cond) {
207; CHECK-LABEL: select_lea_2:
208; CHECK:       # %bb.0:
209; CHECK-NEXT:    xorb $1, %dil
210; CHECK-NEXT:    movzbl %dil, %eax
211; CHECK-NEXT:    leal -1(%rax,%rax), %eax
212; CHECK-NEXT:    retq
213  %sel = select i1 %cond, i32 -1, i32 1
214  ret i32 %sel
215}
216
217define i64 @select_lea_3(i1 zeroext %cond) {
218; CHECK-LABEL: select_lea_3:
219; CHECK:       # %bb.0:
220; CHECK-NEXT:    xorb $1, %dil
221; CHECK-NEXT:    movzbl %dil, %eax
222; CHECK-NEXT:    leaq -2(%rax,%rax,2), %rax
223; CHECK-NEXT:    retq
224  %sel = select i1 %cond, i64 -2, i64 1
225  ret i64 %sel
226}
227
228define i32 @select_lea_5(i1 zeroext %cond) {
229; CHECK-LABEL: select_lea_5:
230; CHECK:       # %bb.0:
231; CHECK-NEXT:    xorb $1, %dil
232; CHECK-NEXT:    movzbl %dil, %eax
233; CHECK-NEXT:    leal -2(%rax,%rax,4), %eax
234; CHECK-NEXT:    retq
235  %sel = select i1 %cond, i32 -2, i32 3
236  ret i32 %sel
237}
238
239define i64 @select_lea_9(i1 zeroext %cond) {
240; CHECK-LABEL: select_lea_9:
241; CHECK:       # %bb.0:
242; CHECK-NEXT:    xorb $1, %dil
243; CHECK-NEXT:    movzbl %dil, %eax
244; CHECK-NEXT:    leaq -7(%rax,%rax,8), %rax
245; CHECK-NEXT:    retq
246  %sel = select i1 %cond, i64 -7, i64 2
247  ret i64 %sel
248}
249
250; Should this be 'sbb x,x' or 'sbb 0,x' with simpler LEA or add?
251
252define i64 @sel_1_2(i64 %x, i64 %y) {
253; CHECK-LABEL: sel_1_2:
254; CHECK:       # %bb.0:
255; CHECK-NEXT:    cmpq $42, %rdi
256; CHECK-NEXT:    sbbq $0, %rsi
257; CHECK-NEXT:    leaq 2(%rsi), %rax
258; CHECK-NEXT:    retq
259  %cmp = icmp ult i64 %x, 42
260  %sel = select i1 %cmp, i64 1, i64 2
261  %sub = add i64 %sel, %y
262  ret i64 %sub
263}
264
265; No LEA with 8-bit, but this shouldn't need branches or cmov.
266
267define i8 @sel_1_neg1(i32 %x) {
268; CHECK-LABEL: sel_1_neg1:
269; CHECK:       # %bb.0:
270; CHECK-NEXT:    cmpl $43, %edi
271; CHECK-NEXT:    setge %al
272; CHECK-NEXT:    shlb $2, %al
273; CHECK-NEXT:    decb %al
274; CHECK-NEXT:    retq
275  %cmp = icmp sgt i32 %x, 42
276  %sel = select i1 %cmp, i8 3, i8 -1
277  ret i8 %sel
278}
279
280; We get an LEA for 16-bit because we ignore the high-bits.
281
282define i16 @sel_neg1_1(i32 %x) {
283; CHECK-LABEL: sel_neg1_1:
284; CHECK:       # %bb.0:
285; CHECK-NEXT:    xorl %eax, %eax
286; CHECK-NEXT:    cmpl $43, %edi
287; CHECK-NEXT:    setl %al
288; CHECK-NEXT:    leal -1(,%rax,4), %eax
289; CHECK-NEXT:    # kill: def $ax killed $ax killed $eax
290; CHECK-NEXT:    retq
291  %cmp = icmp sgt i32 %x, 42
292  %sel = select i1 %cmp, i16 -1, i16 3
293  ret i16 %sel
294}
295
296; If the comparison is available, the predicate can be inverted.
297
298define i32 @sel_1_neg1_32(i32 %x) {
299; CHECK-LABEL: sel_1_neg1_32:
300; CHECK:       # %bb.0:
301; CHECK-NEXT:    xorl %eax, %eax
302; CHECK-NEXT:    cmpl $43, %edi
303; CHECK-NEXT:    setge %al
304; CHECK-NEXT:    leal -1(%rax,%rax,8), %eax
305; CHECK-NEXT:    retq
306  %cmp = icmp sgt i32 %x, 42
307  %sel = select i1 %cmp, i32 8, i32 -1
308  ret i32 %sel
309}
310
311define i32 @sel_neg1_1_32(i32 %x) {
312; CHECK-LABEL: sel_neg1_1_32:
313; CHECK:       # %bb.0:
314; CHECK-NEXT:    xorl %eax, %eax
315; CHECK-NEXT:    cmpl $43, %edi
316; CHECK-NEXT:    setl %al
317; CHECK-NEXT:    leal -7(%rax,%rax,8), %eax
318; CHECK-NEXT:    retq
319  %cmp = icmp sgt i32 %x, 42
320  %sel = select i1 %cmp, i32 -7, i32 2
321  ret i32 %sel
322}
323
324
325; If the constants differ by a large power-of-2, that can be a shift of the difference plus the smaller constant.
326; select Cond, C1, C2 --> add (mul (zext Cond), C1-C2), C2
327
328define i8 @select_pow2_diff(i1 zeroext %cond) {
329; CHECK-LABEL: select_pow2_diff:
330; CHECK:       # %bb.0:
331; CHECK-NEXT:    # kill: def $edi killed $edi def $rdi
332; CHECK-NEXT:    shlb $4, %dil
333; CHECK-NEXT:    leal 3(%rdi), %eax
334; CHECK-NEXT:    # kill: def $al killed $al killed $eax
335; CHECK-NEXT:    retq
336  %sel = select i1 %cond, i8 19, i8 3
337  ret i8 %sel
338}
339
340define i16 @select_pow2_diff_invert(i1 zeroext %cond) {
341; CHECK-LABEL: select_pow2_diff_invert:
342; CHECK:       # %bb.0:
343; CHECK-NEXT:    xorb $1, %dil
344; CHECK-NEXT:    movzbl %dil, %eax
345; CHECK-NEXT:    shll $6, %eax
346; CHECK-NEXT:    orl $7, %eax
347; CHECK-NEXT:    # kill: def $ax killed $ax killed $eax
348; CHECK-NEXT:    retq
349  %sel = select i1 %cond, i16 7, i16 71
350  ret i16 %sel
351}
352
353define i32 @select_pow2_diff_neg(i1 zeroext %cond) {
354; CHECK-LABEL: select_pow2_diff_neg:
355; CHECK:       # %bb.0:
356; CHECK-NEXT:    # kill: def $edi killed $edi def $rdi
357; CHECK-NEXT:    shll $4, %edi
358; CHECK-NEXT:    leal -25(%rdi), %eax
359; CHECK-NEXT:    retq
360  %sel = select i1 %cond, i32 -9, i32 -25
361  ret i32 %sel
362}
363
364define i64 @select_pow2_diff_neg_invert(i1 zeroext %cond) {
365; CHECK-LABEL: select_pow2_diff_neg_invert:
366; CHECK:       # %bb.0:
367; CHECK-NEXT:    xorb $1, %dil
368; CHECK-NEXT:    movzbl %dil, %eax
369; CHECK-NEXT:    shlq $7, %rax
370; CHECK-NEXT:    addq $-99, %rax
371; CHECK-NEXT:    retq
372  %sel = select i1 %cond, i64 -99, i64 29
373  ret i64 %sel
374}
375
376; This doesn't need a branch, but don't do the wrong thing if subtraction of the constants overflows.
377
378define i8 @sel_67_neg125(i32 %x) {
379; CHECK-LABEL: sel_67_neg125:
380; CHECK:       # %bb.0:
381; CHECK-NEXT:    cmpl $43, %edi
382; CHECK-NEXT:    movl $67, %ecx
383; CHECK-NEXT:    movl $131, %eax
384; CHECK-NEXT:    cmovgel %ecx, %eax
385; CHECK-NEXT:    # kill: def $al killed $al killed $eax
386; CHECK-NEXT:    retq
387  %cmp = icmp sgt i32 %x, 42
388  %sel = select i1 %cmp, i8 67, i8 -125
389  ret i8 %sel
390}
391
392
393; In general, select of 2 constants could be:
394; select Cond, C1, C2 --> add (mul (zext Cond), C1-C2), C2 --> add (and (sext Cond), C1-C2), C2
395
396define i32 @select_C1_C2(i1 %cond) {
397; CHECK-LABEL: select_C1_C2:
398; CHECK:       # %bb.0:
399; CHECK-NEXT:    testb $1, %dil
400; CHECK-NEXT:    movl $421, %ecx # imm = 0x1A5
401; CHECK-NEXT:    movl $42, %eax
402; CHECK-NEXT:    cmovnel %ecx, %eax
403; CHECK-NEXT:    retq
404  %sel = select i1 %cond, i32 421, i32 42
405  ret i32 %sel
406}
407
408define i32 @select_C1_C2_zeroext(i1 zeroext %cond) {
409; CHECK-LABEL: select_C1_C2_zeroext:
410; CHECK:       # %bb.0:
411; CHECK-NEXT:    testl %edi, %edi
412; CHECK-NEXT:    movl $421, %ecx # imm = 0x1A5
413; CHECK-NEXT:    movl $42, %eax
414; CHECK-NEXT:    cmovnel %ecx, %eax
415; CHECK-NEXT:    retq
416  %sel = select i1 %cond, i32 421, i32 42
417  ret i32 %sel
418}
419
420define i32 @select_C1_C2_signext(i1 signext %cond) {
421; CHECK-LABEL: select_C1_C2_signext:
422; CHECK:       # %bb.0:
423; CHECK-NEXT:    testb $1, %dil
424; CHECK-NEXT:    movl $421, %ecx # imm = 0x1A5
425; CHECK-NEXT:    movl $42, %eax
426; CHECK-NEXT:    cmovnel %ecx, %eax
427; CHECK-NEXT:    retq
428  %sel = select i1 %cond, i32 421, i32 42
429  ret i32 %sel
430}
431
432; select (x == 2), 2, (x + 1) --> select (x == 2), x, (x + 1)
433
434define i64 @select_2_or_inc(i64 %x) {
435; CHECK-LABEL: select_2_or_inc:
436; CHECK:       # %bb.0:
437; CHECK-NEXT:    leaq 1(%rdi), %rax
438; CHECK-NEXT:    cmpq $2, %rdi
439; CHECK-NEXT:    cmoveq %rdi, %rax
440; CHECK-NEXT:    retq
441  %cmp = icmp eq i64 %x, 2
442  %add = add i64 %x, 1
443  %retval.0 = select i1 %cmp, i64 2, i64 %add
444  ret i64 %retval.0
445}
446
447define <4 x i32> @sel_constants_add_constant_vec(i1 %cond) {
448; CHECK-LABEL: sel_constants_add_constant_vec:
449; CHECK:       # %bb.0:
450; CHECK-NEXT:    testb $1, %dil
451; CHECK-NEXT:    jne .LBB36_1
452; CHECK-NEXT:  # %bb.2:
453; CHECK-NEXT:    movaps {{.*#+}} xmm0 = [12,13,14,15]
454; CHECK-NEXT:    retq
455; CHECK-NEXT:  .LBB36_1:
456; CHECK-NEXT:    movaps {{.*#+}} xmm0 = [4294967293,14,4,4]
457; CHECK-NEXT:    retq
458  %sel = select i1 %cond, <4 x i32> <i32 -4, i32 12, i32 1, i32 0>, <4 x i32> <i32 11, i32 11, i32 11, i32 11>
459  %bo = add <4 x i32> %sel, <i32 1, i32 2, i32 3, i32 4>
460  ret <4 x i32> %bo
461}
462
463define <2 x double> @sel_constants_fmul_constant_vec(i1 %cond) {
464; CHECK-LABEL: sel_constants_fmul_constant_vec:
465; CHECK:       # %bb.0:
466; CHECK-NEXT:    testb $1, %dil
467; CHECK-NEXT:    jne .LBB37_1
468; CHECK-NEXT:  # %bb.2:
469; CHECK-NEXT:    movaps {{.*#+}} xmm0 = [1.1883E+2,3.4539999999999999E+1]
470; CHECK-NEXT:    retq
471; CHECK-NEXT:  .LBB37_1:
472; CHECK-NEXT:    movaps {{.*#+}} xmm0 = [-2.0399999999999999E+1,3.768E+1]
473; CHECK-NEXT:    retq
474  %sel = select i1 %cond, <2 x double> <double -4.0, double 12.0>, <2 x double> <double 23.3, double 11.0>
475  %bo = fmul <2 x double> %sel, <double 5.1, double 3.14>
476  ret <2 x double> %bo
477}
478
479; 4294967297 = 0x100000001.
480; This becomes an opaque constant via ConstantHoisting, so we don't fold it into the select.
481
482define i64 @opaque_constant(i1 %cond, i64 %x) {
483; CHECK-LABEL: opaque_constant:
484; CHECK:       # %bb.0:
485; CHECK-NEXT:    testb $1, %dil
486; CHECK-NEXT:    movq $-4, %rcx
487; CHECK-NEXT:    movl $23, %eax
488; CHECK-NEXT:    cmovneq %rcx, %rax
489; CHECK-NEXT:    movabsq $4294967297, %rcx # imm = 0x100000001
490; CHECK-NEXT:    andq %rcx, %rax
491; CHECK-NEXT:    xorl %edx, %edx
492; CHECK-NEXT:    cmpq %rcx, %rsi
493; CHECK-NEXT:    sete %dl
494; CHECK-NEXT:    subq %rdx, %rax
495; CHECK-NEXT:    retq
496  %sel = select i1 %cond, i64 -4, i64 23
497  %bo = and i64 %sel, 4294967297
498  %cmp = icmp eq i64 %x, 4294967297
499  %sext = sext i1 %cmp to i64
500  %add = add i64 %bo, %sext
501  ret i64 %add
502}
503
504define float @select_undef_fp(float %x) {
505; CHECK-LABEL: select_undef_fp:
506; CHECK:       # %bb.0:
507; CHECK-NEXT:    movss {{.*#+}} xmm0 = mem[0],zero,zero,zero
508; CHECK-NEXT:    retq
509  %f = select i1 undef, float 4.0, float %x
510  ret float %f
511}
512
513