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:    andl $1, %edi
197; CHECK-NEXT:    movl $42, %eax
198; CHECK-NEXT:    subl %edi, %eax
199; CHECK-NEXT:    retq
200  %sel = select i1 %cond, i32 41, i32 42
201  ret i32 %sel
202}
203
204; If the constants differ by a small multiplier, use LEA.
205; select Cond, C1, C2 --> add (mul (zext Cond), C1-C2), C2 --> LEA C2(Cond * (C1-C2))
206
207define i32 @select_lea_2(i1 zeroext %cond) {
208; CHECK-LABEL: select_lea_2:
209; CHECK:       # %bb.0:
210; CHECK-NEXT:    xorb $1, %dil
211; CHECK-NEXT:    movzbl %dil, %eax
212; CHECK-NEXT:    leal -1(%rax,%rax), %eax
213; CHECK-NEXT:    retq
214  %sel = select i1 %cond, i32 -1, i32 1
215  ret i32 %sel
216}
217
218define i64 @select_lea_3(i1 zeroext %cond) {
219; CHECK-LABEL: select_lea_3:
220; CHECK:       # %bb.0:
221; CHECK-NEXT:    xorb $1, %dil
222; CHECK-NEXT:    movzbl %dil, %eax
223; CHECK-NEXT:    leaq -2(%rax,%rax,2), %rax
224; CHECK-NEXT:    retq
225  %sel = select i1 %cond, i64 -2, i64 1
226  ret i64 %sel
227}
228
229define i32 @select_lea_5(i1 zeroext %cond) {
230; CHECK-LABEL: select_lea_5:
231; CHECK:       # %bb.0:
232; CHECK-NEXT:    xorb $1, %dil
233; CHECK-NEXT:    movzbl %dil, %eax
234; CHECK-NEXT:    leal -2(%rax,%rax,4), %eax
235; CHECK-NEXT:    retq
236  %sel = select i1 %cond, i32 -2, i32 3
237  ret i32 %sel
238}
239
240define i64 @select_lea_9(i1 zeroext %cond) {
241; CHECK-LABEL: select_lea_9:
242; CHECK:       # %bb.0:
243; CHECK-NEXT:    xorb $1, %dil
244; CHECK-NEXT:    movzbl %dil, %eax
245; CHECK-NEXT:    leaq -7(%rax,%rax,8), %rax
246; CHECK-NEXT:    retq
247  %sel = select i1 %cond, i64 -7, i64 2
248  ret i64 %sel
249}
250
251; Should this be 'sbb x,x' or 'sbb 0,x' with simpler LEA or add?
252
253define i64 @sel_1_2(i64 %x, i64 %y) {
254; CHECK-LABEL: sel_1_2:
255; CHECK:       # %bb.0:
256; CHECK-NEXT:    cmpq $42, %rdi
257; CHECK-NEXT:    sbbq $0, %rsi
258; CHECK-NEXT:    leaq 2(%rsi), %rax
259; CHECK-NEXT:    retq
260  %cmp = icmp ult i64 %x, 42
261  %sel = select i1 %cmp, i64 1, i64 2
262  %sub = add i64 %sel, %y
263  ret i64 %sub
264}
265
266; No LEA with 8-bit, but this shouldn't need branches or cmov.
267
268define i8 @sel_1_neg1(i32 %x) {
269; CHECK-LABEL: sel_1_neg1:
270; CHECK:       # %bb.0:
271; CHECK-NEXT:    cmpl $42, %edi
272; CHECK-NEXT:    setg %al
273; CHECK-NEXT:    shlb $2, %al
274; CHECK-NEXT:    decb %al
275; CHECK-NEXT:    retq
276  %cmp = icmp sgt i32 %x, 42
277  %sel = select i1 %cmp, i8 3, i8 -1
278  ret i8 %sel
279}
280
281; We get an LEA for 16-bit because we ignore the high-bits.
282
283define i16 @sel_neg1_1(i32 %x) {
284; CHECK-LABEL: sel_neg1_1:
285; CHECK:       # %bb.0:
286; CHECK-NEXT:    xorl %eax, %eax
287; CHECK-NEXT:    cmpl $43, %edi
288; CHECK-NEXT:    setl %al
289; CHECK-NEXT:    leal -1(,%rax,4), %eax
290; CHECK-NEXT:    # kill: def $ax killed $ax killed $eax
291; CHECK-NEXT:    retq
292  %cmp = icmp sgt i32 %x, 42
293  %sel = select i1 %cmp, i16 -1, i16 3
294  ret i16 %sel
295}
296
297; If the comparison is available, the predicate can be inverted.
298
299define i32 @sel_1_neg1_32(i32 %x) {
300; CHECK-LABEL: sel_1_neg1_32:
301; CHECK:       # %bb.0:
302; CHECK-NEXT:    xorl %eax, %eax
303; CHECK-NEXT:    cmpl $42, %edi
304; CHECK-NEXT:    setg %al
305; CHECK-NEXT:    leal -1(%rax,%rax,8), %eax
306; CHECK-NEXT:    retq
307  %cmp = icmp sgt i32 %x, 42
308  %sel = select i1 %cmp, i32 8, i32 -1
309  ret i32 %sel
310}
311
312define i32 @sel_neg1_1_32(i32 %x) {
313; CHECK-LABEL: sel_neg1_1_32:
314; CHECK:       # %bb.0:
315; CHECK-NEXT:    xorl %eax, %eax
316; CHECK-NEXT:    cmpl $43, %edi
317; CHECK-NEXT:    setl %al
318; CHECK-NEXT:    leal -7(%rax,%rax,8), %eax
319; CHECK-NEXT:    retq
320  %cmp = icmp sgt i32 %x, 42
321  %sel = select i1 %cmp, i32 -7, i32 2
322  ret i32 %sel
323}
324
325
326; If the constants differ by a large power-of-2, that can be a shift of the difference plus the smaller constant.
327; select Cond, C1, C2 --> add (mul (zext Cond), C1-C2), C2
328
329define i8 @select_pow2_diff(i1 zeroext %cond) {
330; CHECK-LABEL: select_pow2_diff:
331; CHECK:       # %bb.0:
332; CHECK-NEXT:    movl %edi, %eax
333; CHECK-NEXT:    shlb $4, %al
334; CHECK-NEXT:    orb $3, %al
335; CHECK-NEXT:    # kill: def $al killed $al killed $eax
336; CHECK-NEXT:    retq
337  %sel = select i1 %cond, i8 19, i8 3
338  ret i8 %sel
339}
340
341define i16 @select_pow2_diff_invert(i1 zeroext %cond) {
342; CHECK-LABEL: select_pow2_diff_invert:
343; CHECK:       # %bb.0:
344; CHECK-NEXT:    xorb $1, %dil
345; CHECK-NEXT:    movzbl %dil, %eax
346; CHECK-NEXT:    shll $6, %eax
347; CHECK-NEXT:    orl $7, %eax
348; CHECK-NEXT:    # kill: def $ax killed $ax killed $eax
349; CHECK-NEXT:    retq
350  %sel = select i1 %cond, i16 7, i16 71
351  ret i16 %sel
352}
353
354define i32 @select_pow2_diff_neg(i1 zeroext %cond) {
355; CHECK-LABEL: select_pow2_diff_neg:
356; CHECK:       # %bb.0:
357; CHECK-NEXT:    shlb $4, %dil
358; CHECK-NEXT:    movzbl %dil, %eax
359; CHECK-NEXT:    orl $-25, %eax
360; CHECK-NEXT:    retq
361  %sel = select i1 %cond, i32 -9, i32 -25
362  ret i32 %sel
363}
364
365define i64 @select_pow2_diff_neg_invert(i1 zeroext %cond) {
366; CHECK-LABEL: select_pow2_diff_neg_invert:
367; CHECK:       # %bb.0:
368; CHECK-NEXT:    xorb $1, %dil
369; CHECK-NEXT:    movzbl %dil, %eax
370; CHECK-NEXT:    shlq $7, %rax
371; CHECK-NEXT:    addq $-99, %rax
372; CHECK-NEXT:    retq
373  %sel = select i1 %cond, i64 -99, i64 29
374  ret i64 %sel
375}
376
377; This doesn't need a branch, but don't do the wrong thing if subtraction of the constants overflows.
378
379define i8 @sel_67_neg125(i32 %x) {
380; CHECK-LABEL: sel_67_neg125:
381; CHECK:       # %bb.0:
382; CHECK-NEXT:    cmpl $42, %edi
383; CHECK-NEXT:    movb $67, %al
384; CHECK-NEXT:    jg .LBB31_2
385; CHECK-NEXT:  # %bb.1:
386; CHECK-NEXT:    movb $-125, %al
387; CHECK-NEXT:  .LBB31_2:
388; CHECK-NEXT:    retq
389  %cmp = icmp sgt i32 %x, 42
390  %sel = select i1 %cmp, i8 67, i8 -125
391  ret i8 %sel
392}
393
394
395; In general, select of 2 constants could be:
396; select Cond, C1, C2 --> add (mul (zext Cond), C1-C2), C2 --> add (and (sext Cond), C1-C2), C2
397
398define i32 @select_C1_C2(i1 %cond) {
399; CHECK-LABEL: select_C1_C2:
400; CHECK:       # %bb.0:
401; CHECK-NEXT:    testb $1, %dil
402; CHECK-NEXT:    movl $421, %ecx # imm = 0x1A5
403; CHECK-NEXT:    movl $42, %eax
404; CHECK-NEXT:    cmovnel %ecx, %eax
405; CHECK-NEXT:    retq
406  %sel = select i1 %cond, i32 421, i32 42
407  ret i32 %sel
408}
409
410define i32 @select_C1_C2_zeroext(i1 zeroext %cond) {
411; CHECK-LABEL: select_C1_C2_zeroext:
412; CHECK:       # %bb.0:
413; CHECK-NEXT:    testl %edi, %edi
414; CHECK-NEXT:    movl $421, %ecx # imm = 0x1A5
415; CHECK-NEXT:    movl $42, %eax
416; CHECK-NEXT:    cmovnel %ecx, %eax
417; CHECK-NEXT:    retq
418  %sel = select i1 %cond, i32 421, i32 42
419  ret i32 %sel
420}
421
422define i32 @select_C1_C2_signext(i1 signext %cond) {
423; CHECK-LABEL: select_C1_C2_signext:
424; CHECK:       # %bb.0:
425; CHECK-NEXT:    testb $1, %dil
426; CHECK-NEXT:    movl $421, %ecx # imm = 0x1A5
427; CHECK-NEXT:    movl $42, %eax
428; CHECK-NEXT:    cmovnel %ecx, %eax
429; CHECK-NEXT:    retq
430  %sel = select i1 %cond, i32 421, i32 42
431  ret i32 %sel
432}
433
434; select (x == 2), 2, (x + 1) --> select (x == 2), x, (x + 1)
435
436define i64 @select_2_or_inc(i64 %x) {
437; CHECK-LABEL: select_2_or_inc:
438; CHECK:       # %bb.0:
439; CHECK-NEXT:    leaq 1(%rdi), %rax
440; CHECK-NEXT:    cmpq $2, %rdi
441; CHECK-NEXT:    cmoveq %rdi, %rax
442; CHECK-NEXT:    retq
443  %cmp = icmp eq i64 %x, 2
444  %add = add i64 %x, 1
445  %retval.0 = select i1 %cmp, i64 2, i64 %add
446  ret i64 %retval.0
447}
448
449define <4 x i32> @sel_constants_add_constant_vec(i1 %cond) {
450; CHECK-LABEL: sel_constants_add_constant_vec:
451; CHECK:       # %bb.0:
452; CHECK-NEXT:    testb $1, %dil
453; CHECK-NEXT:    jne .LBB36_1
454; CHECK-NEXT:  # %bb.2:
455; CHECK-NEXT:    movaps {{.*#+}} xmm0 = [12,13,14,15]
456; CHECK-NEXT:    retq
457; CHECK-NEXT:  .LBB36_1:
458; CHECK-NEXT:    movaps {{.*#+}} xmm0 = [4294967293,14,4,4]
459; CHECK-NEXT:    retq
460  %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>
461  %bo = add <4 x i32> %sel, <i32 1, i32 2, i32 3, i32 4>
462  ret <4 x i32> %bo
463}
464
465define <2 x double> @sel_constants_fmul_constant_vec(i1 %cond) {
466; CHECK-LABEL: sel_constants_fmul_constant_vec:
467; CHECK:       # %bb.0:
468; CHECK-NEXT:    testb $1, %dil
469; CHECK-NEXT:    jne .LBB37_1
470; CHECK-NEXT:  # %bb.2:
471; CHECK-NEXT:    movaps {{.*#+}} xmm0 = [1.1883E+2,3.4539999999999999E+1]
472; CHECK-NEXT:    retq
473; CHECK-NEXT:  .LBB37_1:
474; CHECK-NEXT:    movaps {{.*#+}} xmm0 = [-2.0399999999999999E+1,3.768E+1]
475; CHECK-NEXT:    retq
476  %sel = select i1 %cond, <2 x double> <double -4.0, double 12.0>, <2 x double> <double 23.3, double 11.0>
477  %bo = fmul <2 x double> %sel, <double 5.1, double 3.14>
478  ret <2 x double> %bo
479}
480
481; 4294967297 = 0x100000001.
482; This becomes an opaque constant via ConstantHoisting, so we don't fold it into the select.
483
484define i64 @opaque_constant(i1 %cond, i64 %x) {
485; CHECK-LABEL: opaque_constant:
486; CHECK:       # %bb.0:
487; CHECK-NEXT:    testb $1, %dil
488; CHECK-NEXT:    movq $-4, %rcx
489; CHECK-NEXT:    movl $23, %eax
490; CHECK-NEXT:    cmovneq %rcx, %rax
491; CHECK-NEXT:    movabsq $4294967297, %rcx # imm = 0x100000001
492; CHECK-NEXT:    andq %rcx, %rax
493; CHECK-NEXT:    xorl %edx, %edx
494; CHECK-NEXT:    cmpq %rcx, %rsi
495; CHECK-NEXT:    sete %dl
496; CHECK-NEXT:    subq %rdx, %rax
497; CHECK-NEXT:    retq
498  %sel = select i1 %cond, i64 -4, i64 23
499  %bo = and i64 %sel, 4294967297
500  %cmp = icmp eq i64 %x, 4294967297
501  %sext = sext i1 %cmp to i64
502  %add = add i64 %bo, %sext
503  ret i64 %add
504}
505
506define float @select_undef_fp(float %x) {
507; CHECK-LABEL: select_undef_fp:
508; CHECK:       # %bb.0:
509; CHECK-NEXT:    movss {{.*#+}} xmm0 = mem[0],zero,zero,zero
510; CHECK-NEXT:    retq
511  %f = select i1 undef, float 4.0, float %x
512  ret float %f
513}
514
515