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:    andl $1, %edi
47; CHECK-NEXT:    movl %edi, %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:    andb $1, %dil
66; CHECK-NEXT:    movzbl %dil, %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: %EDI<def> %EDI<kill> %RDI<def>
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: %EDI<def> %EDI<kill> %RDI<def>
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:    andb $1, %dil
99; CHECK-NEXT:    movzbl %dil, %eax
100; CHECK-NEXT:    decl %eax
101; CHECK-NEXT:    retq
102  %sel = select i1 %cond, i32 0, i32 -1
103  ret i32 %sel
104}
105
106; select Cond, -1, 0 --> sext (Cond)
107
108define i32 @select_neg1_or_0(i1 %cond) {
109; CHECK-LABEL: select_neg1_or_0:
110; CHECK:       # BB#0:
111; CHECK-NEXT:    andl $1, %edi
112; CHECK-NEXT:    negl %edi
113; CHECK-NEXT:    movl %edi, %eax
114; CHECK-NEXT:    retq
115  %sel = select i1 %cond, i32 -1, i32 0
116  ret i32 %sel
117}
118
119define i32 @select_neg1_or_0_zeroext(i1 zeroext %cond) {
120; CHECK-LABEL: select_neg1_or_0_zeroext:
121; CHECK:       # BB#0:
122; CHECK-NEXT:    negl %edi
123; CHECK-NEXT:    movl %edi, %eax
124; CHECK-NEXT:    retq
125  %sel = select i1 %cond, i32 -1, i32 0
126  ret i32 %sel
127}
128
129define i32 @select_neg1_or_0_signext(i1 signext %cond) {
130; CHECK-LABEL: select_neg1_or_0_signext:
131; CHECK:       # BB#0:
132; CHECK-NEXT:    movsbl %dil, %eax
133; CHECK-NEXT:    retq
134  %sel = select i1 %cond, i32 -1, i32 0
135  ret i32 %sel
136}
137
138; select Cond, C+1, C --> add (zext Cond), C
139
140define i32 @select_Cplus1_C(i1 %cond) {
141; CHECK-LABEL: select_Cplus1_C:
142; CHECK:       # BB#0:
143; CHECK-NEXT:    # kill: %EDI<def> %EDI<kill> %RDI<def>
144; CHECK-NEXT:    andl $1, %edi
145; CHECK-NEXT:    leal 41(%rdi), %eax
146; CHECK-NEXT:    retq
147  %sel = select i1 %cond, i32 42, i32 41
148  ret i32 %sel
149}
150
151define i32 @select_Cplus1_C_zeroext(i1 zeroext %cond) {
152; CHECK-LABEL: select_Cplus1_C_zeroext:
153; CHECK:       # BB#0:
154; CHECK-NEXT:    # kill: %EDI<def> %EDI<kill> %RDI<def>
155; CHECK-NEXT:    leal 41(%rdi), %eax
156; CHECK-NEXT:    retq
157  %sel = select i1 %cond, i32 42, i32 41
158  ret i32 %sel
159}
160
161define i32 @select_Cplus1_C_signext(i1 signext %cond) {
162; CHECK-LABEL: select_Cplus1_C_signext:
163; CHECK:       # BB#0:
164; CHECK-NEXT:    andb $1, %dil
165; CHECK-NEXT:    movzbl %dil, %eax
166; CHECK-NEXT:    addl $41, %eax
167; CHECK-NEXT:    retq
168  %sel = select i1 %cond, i32 42, i32 41
169  ret i32 %sel
170}
171
172; select Cond, C, C+1 --> add (sext Cond), C
173
174define i32 @select_C_Cplus1(i1 %cond) {
175; CHECK-LABEL: select_C_Cplus1:
176; CHECK:       # BB#0:
177; CHECK-NEXT:    andl $1, %edi
178; CHECK-NEXT:    movl $42, %eax
179; CHECK-NEXT:    subl %edi, %eax
180; CHECK-NEXT:    retq
181  %sel = select i1 %cond, i32 41, i32 42
182  ret i32 %sel
183}
184
185define i32 @select_C_Cplus1_zeroext(i1 zeroext %cond) {
186; CHECK-LABEL: select_C_Cplus1_zeroext:
187; CHECK:       # BB#0:
188; CHECK-NEXT:    movl $42, %eax
189; CHECK-NEXT:    subl %edi, %eax
190; CHECK-NEXT:    retq
191  %sel = select i1 %cond, i32 41, i32 42
192  ret i32 %sel
193}
194
195define i32 @select_C_Cplus1_signext(i1 signext %cond) {
196; CHECK-LABEL: select_C_Cplus1_signext:
197; CHECK:       # BB#0:
198; CHECK-NEXT:    andb $1, %dil
199; CHECK-NEXT:    movzbl %dil, %ecx
200; CHECK-NEXT:    movl $42, %eax
201; CHECK-NEXT:    subl %ecx, %eax
202; CHECK-NEXT:    retq
203  %sel = select i1 %cond, i32 41, i32 42
204  ret i32 %sel
205}
206
207; If the constants differ by a small multiplier, use LEA.
208; select Cond, C1, C2 --> add (mul (zext Cond), C1-C2), C2 --> LEA C2(Cond * (C1-C2))
209
210define i32 @select_lea_2(i1 zeroext %cond) {
211; CHECK-LABEL: select_lea_2:
212; CHECK:       # BB#0:
213; CHECK-NEXT:    xorb $1, %dil
214; CHECK-NEXT:    movzbl %dil, %eax
215; CHECK-NEXT:    leal -1(%rax,%rax), %eax
216; CHECK-NEXT:    retq
217  %sel = select i1 %cond, i32 -1, i32 1
218  ret i32 %sel
219}
220
221define i64 @select_lea_3(i1 zeroext %cond) {
222; CHECK-LABEL: select_lea_3:
223; CHECK:       # BB#0:
224; CHECK-NEXT:    xorb $1, %dil
225; CHECK-NEXT:    movzbl %dil, %eax
226; CHECK-NEXT:    leaq -2(%rax,%rax,2), %rax
227; CHECK-NEXT:    retq
228  %sel = select i1 %cond, i64 -2, i64 1
229  ret i64 %sel
230}
231
232define i32 @select_lea_5(i1 zeroext %cond) {
233; CHECK-LABEL: select_lea_5:
234; CHECK:       # BB#0:
235; CHECK-NEXT:    xorb $1, %dil
236; CHECK-NEXT:    movzbl %dil, %eax
237; CHECK-NEXT:    leal -2(%rax,%rax,4), %eax
238; CHECK-NEXT:    retq
239  %sel = select i1 %cond, i32 -2, i32 3
240  ret i32 %sel
241}
242
243define i64 @select_lea_9(i1 zeroext %cond) {
244; CHECK-LABEL: select_lea_9:
245; CHECK:       # BB#0:
246; CHECK-NEXT:    xorb $1, %dil
247; CHECK-NEXT:    movzbl %dil, %eax
248; CHECK-NEXT:    leaq -7(%rax,%rax,8), %rax
249; CHECK-NEXT:    retq
250  %sel = select i1 %cond, i64 -7, i64 2
251  ret i64 %sel
252}
253
254; Should this be 'sbb x,x' or 'sbb 0,x' with simpler LEA or add?
255
256define i64 @sel_1_2(i64 %x, i64 %y) {
257; CHECK-LABEL: sel_1_2:
258; CHECK:       # BB#0:
259; CHECK-NEXT:    cmpq $42, %rdi
260; CHECK-NEXT:    sbbq $0, %rsi
261; CHECK-NEXT:    leaq 2(%rsi), %rax
262; CHECK-NEXT:    retq
263  %cmp = icmp ult i64 %x, 42
264  %sel = select i1 %cmp, i64 1, i64 2
265  %sub = add i64 %sel, %y
266  ret i64 %sub
267}
268
269; No LEA with 8-bit, but this shouldn't need branches or cmov.
270
271define i8 @sel_1_neg1(i32 %x) {
272; CHECK-LABEL: sel_1_neg1:
273; CHECK:       # BB#0:
274; CHECK-NEXT:    cmpl $42, %edi
275; CHECK-NEXT:    setg %al
276; CHECK-NEXT:    shlb $2, %al
277; CHECK-NEXT:    decb %al
278; CHECK-NEXT:    retq
279  %cmp = icmp sgt i32 %x, 42
280  %sel = select i1 %cmp, i8 3, i8 -1
281  ret i8 %sel
282}
283
284; We get an LEA for 16-bit because we ignore the high-bits.
285
286define i16 @sel_neg1_1(i32 %x) {
287; CHECK-LABEL: sel_neg1_1:
288; CHECK:       # BB#0:
289; CHECK-NEXT:    xorl %eax, %eax
290; CHECK-NEXT:    cmpl $43, %edi
291; CHECK-NEXT:    setl %al
292; CHECK-NEXT:    leal -1(,%rax,4), %eax
293; CHECK-NEXT:    # kill: %AX<def> %AX<kill> %EAX<kill>
294; CHECK-NEXT:    retq
295  %cmp = icmp sgt i32 %x, 42
296  %sel = select i1 %cmp, i16 -1, i16 3
297  ret i16 %sel
298}
299
300; If the comparison is available, the predicate can be inverted.
301
302define i32 @sel_1_neg1_32(i32 %x) {
303; CHECK-LABEL: sel_1_neg1_32:
304; CHECK:       # BB#0:
305; CHECK-NEXT:    xorl %eax, %eax
306; CHECK-NEXT:    cmpl $42, %edi
307; CHECK-NEXT:    setg %al
308; CHECK-NEXT:    leal -1(%rax,%rax,8), %eax
309; CHECK-NEXT:    retq
310  %cmp = icmp sgt i32 %x, 42
311  %sel = select i1 %cmp, i32 8, i32 -1
312  ret i32 %sel
313}
314
315define i32 @sel_neg1_1_32(i32 %x) {
316; CHECK-LABEL: sel_neg1_1_32:
317; CHECK:       # BB#0:
318; CHECK-NEXT:    xorl %eax, %eax
319; CHECK-NEXT:    cmpl $43, %edi
320; CHECK-NEXT:    setl %al
321; CHECK-NEXT:    leal -7(%rax,%rax,8), %eax
322; CHECK-NEXT:    retq
323  %cmp = icmp sgt i32 %x, 42
324  %sel = select i1 %cmp, i32 -7, i32 2
325  ret i32 %sel
326}
327
328
329; If the constants differ by a large power-of-2, that can be a shift of the difference plus the smaller constant.
330; select Cond, C1, C2 --> add (mul (zext Cond), C1-C2), C2
331
332define i8 @select_pow2_diff(i1 zeroext %cond) {
333; CHECK-LABEL: select_pow2_diff:
334; CHECK:       # BB#0:
335; CHECK-NEXT:    shlb $4, %dil
336; CHECK-NEXT:    orb $3, %dil
337; CHECK-NEXT:    movl %edi, %eax
338; CHECK-NEXT:    retq
339  %sel = select i1 %cond, i8 19, i8 3
340  ret i8 %sel
341}
342
343define i16 @select_pow2_diff_invert(i1 zeroext %cond) {
344; CHECK-LABEL: select_pow2_diff_invert:
345; CHECK:       # BB#0:
346; CHECK-NEXT:    xorb $1, %dil
347; CHECK-NEXT:    movzbl %dil, %eax
348; CHECK-NEXT:    shll $6, %eax
349; CHECK-NEXT:    orl $7, %eax
350; CHECK-NEXT:    # kill: %AX<def> %AX<kill> %EAX<kill>
351; CHECK-NEXT:    retq
352  %sel = select i1 %cond, i16 7, i16 71
353  ret i16 %sel
354}
355
356define i32 @select_pow2_diff_neg(i1 zeroext %cond) {
357; CHECK-LABEL: select_pow2_diff_neg:
358; CHECK:       # BB#0:
359; CHECK-NEXT:    shlb $4, %dil
360; CHECK-NEXT:    movzbl %dil, %eax
361; CHECK-NEXT:    orl $-25, %eax
362; CHECK-NEXT:    retq
363  %sel = select i1 %cond, i32 -9, i32 -25
364  ret i32 %sel
365}
366
367define i64 @select_pow2_diff_neg_invert(i1 zeroext %cond) {
368; CHECK-LABEL: select_pow2_diff_neg_invert:
369; CHECK:       # BB#0:
370; CHECK-NEXT:    xorb $1, %dil
371; CHECK-NEXT:    movzbl %dil, %eax
372; CHECK-NEXT:    shlq $7, %rax
373; CHECK-NEXT:    addq $-99, %rax
374; CHECK-NEXT:    retq
375  %sel = select i1 %cond, i64 -99, i64 29
376  ret i64 %sel
377}
378
379; This doesn't need a branch, but don't do the wrong thing if subtraction of the constants overflows.
380
381define i8 @sel_67_neg125(i32 %x) {
382; CHECK-LABEL: sel_67_neg125:
383; CHECK:       # BB#0:
384; CHECK-NEXT:    cmpl $42, %edi
385; CHECK-NEXT:    movb $67, %al
386; CHECK-NEXT:    jg .LBB31_2
387; CHECK-NEXT:  # BB#1:
388; CHECK-NEXT:    movb $-125, %al
389; CHECK-NEXT:  .LBB31_2:
390; CHECK-NEXT:    retq
391  %cmp = icmp sgt i32 %x, 42
392  %sel = select i1 %cmp, i8 67, i8 -125
393  ret i8 %sel
394}
395
396
397; In general, select of 2 constants could be:
398; select Cond, C1, C2 --> add (mul (zext Cond), C1-C2), C2 --> add (and (sext Cond), C1-C2), C2
399
400define i32 @select_C1_C2(i1 %cond) {
401; CHECK-LABEL: select_C1_C2:
402; CHECK:       # BB#0:
403; CHECK-NEXT:    testb $1, %dil
404; CHECK-NEXT:    movl $421, %ecx # imm = 0x1A5
405; CHECK-NEXT:    movl $42, %eax
406; CHECK-NEXT:    cmovnel %ecx, %eax
407; CHECK-NEXT:    retq
408  %sel = select i1 %cond, i32 421, i32 42
409  ret i32 %sel
410}
411
412define i32 @select_C1_C2_zeroext(i1 zeroext %cond) {
413; CHECK-LABEL: select_C1_C2_zeroext:
414; CHECK:       # BB#0:
415; CHECK-NEXT:    testl %edi, %edi
416; CHECK-NEXT:    movl $421, %ecx # imm = 0x1A5
417; CHECK-NEXT:    movl $42, %eax
418; CHECK-NEXT:    cmovnel %ecx, %eax
419; CHECK-NEXT:    retq
420  %sel = select i1 %cond, i32 421, i32 42
421  ret i32 %sel
422}
423
424define i32 @select_C1_C2_signext(i1 signext %cond) {
425; CHECK-LABEL: select_C1_C2_signext:
426; CHECK:       # BB#0:
427; CHECK-NEXT:    testb $1, %dil
428; CHECK-NEXT:    movl $421, %ecx # imm = 0x1A5
429; CHECK-NEXT:    movl $42, %eax
430; CHECK-NEXT:    cmovnel %ecx, %eax
431; CHECK-NEXT:    retq
432  %sel = select i1 %cond, i32 421, i32 42
433  ret i32 %sel
434}
435
436; select (x == 2), 2, (x + 1) --> select (x == 2), x, (x + 1)
437
438define i64 @select_2_or_inc(i64 %x) {
439; CHECK-LABEL: select_2_or_inc:
440; CHECK:       # BB#0:
441; CHECK-NEXT:    leaq 1(%rdi), %rax
442; CHECK-NEXT:    cmpq $2, %rdi
443; CHECK-NEXT:    cmoveq %rdi, %rax
444; CHECK-NEXT:    retq
445  %cmp = icmp eq i64 %x, 2
446  %add = add i64 %x, 1
447  %retval.0 = select i1 %cmp, i64 2, i64 %add
448  ret i64 %retval.0
449}
450
451define <4 x i32> @sel_constants_add_constant_vec(i1 %cond) {
452; CHECK-LABEL: sel_constants_add_constant_vec:
453; CHECK:       # BB#0:
454; CHECK-NEXT:    testb $1, %dil
455; CHECK-NEXT:    jne .LBB36_1
456; CHECK-NEXT:  # BB#2:
457; CHECK-NEXT:    movaps {{.*#+}} xmm0 = [12,13,14,15]
458; CHECK-NEXT:    retq
459; CHECK-NEXT:  .LBB36_1:
460; CHECK-NEXT:    movaps {{.*#+}} xmm0 = [4294967293,14,4,4]
461; CHECK-NEXT:    retq
462  %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>
463  %bo = add <4 x i32> %sel, <i32 1, i32 2, i32 3, i32 4>
464  ret <4 x i32> %bo
465}
466
467define <2 x double> @sel_constants_fmul_constant_vec(i1 %cond) {
468; CHECK-LABEL: sel_constants_fmul_constant_vec:
469; CHECK:       # BB#0:
470; CHECK-NEXT:    testb $1, %dil
471; CHECK-NEXT:    jne .LBB37_1
472; CHECK-NEXT:  # BB#2:
473; CHECK-NEXT:    movaps {{.*#+}} xmm0 = [1.188300e+02,3.454000e+01]
474; CHECK-NEXT:    retq
475; CHECK-NEXT:  .LBB37_1:
476; CHECK-NEXT:    movaps {{.*#+}} xmm0 = [-2.040000e+01,3.768000e+01]
477; CHECK-NEXT:    retq
478  %sel = select i1 %cond, <2 x double> <double -4.0, double 12.0>, <2 x double> <double 23.3, double 11.0>
479  %bo = fmul <2 x double> %sel, <double 5.1, double 3.14>
480  ret <2 x double> %bo
481}
482
483; 4294967297 = 0x100000001.
484; This becomes an opaque constant via ConstantHoisting, so we don't fold it into the select.
485
486define i64 @opaque_constant(i1 %cond, i64 %x) {
487; CHECK-LABEL: opaque_constant:
488; CHECK:       # BB#0:
489; CHECK-NEXT:    testb $1, %dil
490; CHECK-NEXT:    movl $23, %ecx
491; CHECK-NEXT:    movq $-4, %rax
492; CHECK-NEXT:    cmoveq %rcx, %rax
493; CHECK-NEXT:    movabsq $4294967297, %rcx # imm = 0x100000001
494; CHECK-NEXT:    andq %rcx, %rax
495; CHECK-NEXT:    xorl %edx, %edx
496; CHECK-NEXT:    cmpq %rcx, %rsi
497; CHECK-NEXT:    sete %dl
498; CHECK-NEXT:    subq %rdx, %rax
499; CHECK-NEXT:    retq
500  %sel = select i1 %cond, i64 -4, i64 23
501  %bo = and i64 %sel, 4294967297
502  %cmp = icmp eq i64 %x, 4294967297
503  %sext = sext i1 %cmp to i64
504  %add = add i64 %bo, %sext
505  ret i64 %add
506}
507
508