xref: /llvm-project/llvm/test/CodeGen/X86/select_const.ll (revision ffeef7599af94694191458a0e2a131e122181a13)
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2; RUN: llc < %s -mtriple=i686-unknown-unknown | FileCheck %s --check-prefixes=X86
3; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=-slow-incdec | FileCheck %s --check-prefixes=X64,X64-FASTINC
4; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+slow-incdec | FileCheck %s --check-prefixes=X64,X64-SLOWINC
5
6; Select of constants: control flow / conditional moves can always be replaced by logic+math (but may not be worth it?).
7; Test the zeroext/signext variants of each pattern to see if that makes a difference.
8
9; select Cond, 0, 1 --> zext (!Cond)
10
11define i32 @select_0_or_1(i1 %cond) {
12; X86-LABEL: select_0_or_1:
13; X86:       # %bb.0:
14; X86-NEXT:    movzbl {{[0-9]+}}(%esp), %eax
15; X86-NEXT:    notb %al
16; X86-NEXT:    movzbl %al, %eax
17; X86-NEXT:    andl $1, %eax
18; X86-NEXT:    retl
19;
20; X64-LABEL: select_0_or_1:
21; X64:       # %bb.0:
22; X64-NEXT:    notb %dil
23; X64-NEXT:    movzbl %dil, %eax
24; X64-NEXT:    andl $1, %eax
25; X64-NEXT:    retq
26  %sel = select i1 %cond, i32 0, i32 1
27  ret i32 %sel
28}
29
30define i32 @select_0_or_1_zeroext(i1 zeroext %cond) {
31; X86-LABEL: select_0_or_1_zeroext:
32; X86:       # %bb.0:
33; X86-NEXT:    movzbl {{[0-9]+}}(%esp), %eax
34; X86-NEXT:    xorb $1, %al
35; X86-NEXT:    movzbl %al, %eax
36; X86-NEXT:    retl
37;
38; X64-LABEL: select_0_or_1_zeroext:
39; X64:       # %bb.0:
40; X64-NEXT:    xorb $1, %dil
41; X64-NEXT:    movzbl %dil, %eax
42; X64-NEXT:    retq
43  %sel = select i1 %cond, i32 0, i32 1
44  ret i32 %sel
45}
46
47define i32 @select_0_or_1_signext(i1 signext %cond) {
48; X86-LABEL: select_0_or_1_signext:
49; X86:       # %bb.0:
50; X86-NEXT:    movzbl {{[0-9]+}}(%esp), %eax
51; X86-NEXT:    notb %al
52; X86-NEXT:    movzbl %al, %eax
53; X86-NEXT:    andl $1, %eax
54; X86-NEXT:    retl
55;
56; X64-LABEL: select_0_or_1_signext:
57; X64:       # %bb.0:
58; X64-NEXT:    notb %dil
59; X64-NEXT:    movzbl %dil, %eax
60; X64-NEXT:    andl $1, %eax
61; X64-NEXT:    retq
62  %sel = select i1 %cond, i32 0, i32 1
63  ret i32 %sel
64}
65
66; select Cond, 1, 0 --> zext (Cond)
67
68define i32 @select_1_or_0(i1 %cond) {
69; X86-LABEL: select_1_or_0:
70; X86:       # %bb.0:
71; X86-NEXT:    movzbl {{[0-9]+}}(%esp), %eax
72; X86-NEXT:    andl $1, %eax
73; X86-NEXT:    retl
74;
75; X64-LABEL: select_1_or_0:
76; X64:       # %bb.0:
77; X64-NEXT:    movl %edi, %eax
78; X64-NEXT:    andl $1, %eax
79; X64-NEXT:    retq
80  %sel = select i1 %cond, i32 1, i32 0
81  ret i32 %sel
82}
83
84define i32 @select_1_or_0_zeroext(i1 zeroext %cond) {
85; X86-LABEL: select_1_or_0_zeroext:
86; X86:       # %bb.0:
87; X86-NEXT:    movzbl {{[0-9]+}}(%esp), %eax
88; X86-NEXT:    retl
89;
90; X64-LABEL: select_1_or_0_zeroext:
91; X64:       # %bb.0:
92; X64-NEXT:    movl %edi, %eax
93; X64-NEXT:    retq
94  %sel = select i1 %cond, i32 1, i32 0
95  ret i32 %sel
96}
97
98define i32 @select_1_or_0_signext(i1 signext %cond) {
99; X86-LABEL: select_1_or_0_signext:
100; X86:       # %bb.0:
101; X86-NEXT:    movzbl {{[0-9]+}}(%esp), %eax
102; X86-NEXT:    andl $1, %eax
103; X86-NEXT:    retl
104;
105; X64-LABEL: select_1_or_0_signext:
106; X64:       # %bb.0:
107; X64-NEXT:    movl %edi, %eax
108; X64-NEXT:    andl $1, %eax
109; X64-NEXT:    retq
110  %sel = select i1 %cond, i32 1, i32 0
111  ret i32 %sel
112}
113
114; select Cond, 0, -1 --> sext (!Cond)
115
116define i32 @select_0_or_neg1(i1 %cond) {
117; X86-LABEL: select_0_or_neg1:
118; X86:       # %bb.0:
119; X86-NEXT:    movzbl {{[0-9]+}}(%esp), %eax
120; X86-NEXT:    andl $1, %eax
121; X86-NEXT:    decl %eax
122; X86-NEXT:    retl
123;
124; X64-LABEL: select_0_or_neg1:
125; X64:       # %bb.0:
126; X64-NEXT:    # kill: def $edi killed $edi def $rdi
127; X64-NEXT:    andl $1, %edi
128; X64-NEXT:    leal -1(%rdi), %eax
129; X64-NEXT:    retq
130  %sel = select i1 %cond, i32 0, i32 -1
131  ret i32 %sel
132}
133
134define i32 @select_0_or_neg1_zeroext(i1 zeroext %cond) {
135; X86-LABEL: select_0_or_neg1_zeroext:
136; X86:       # %bb.0:
137; X86-NEXT:    movzbl {{[0-9]+}}(%esp), %eax
138; X86-NEXT:    decl %eax
139; X86-NEXT:    retl
140;
141; X64-LABEL: select_0_or_neg1_zeroext:
142; X64:       # %bb.0:
143; X64-NEXT:    # kill: def $edi killed $edi def $rdi
144; X64-NEXT:    leal -1(%rdi), %eax
145; X64-NEXT:    retq
146  %sel = select i1 %cond, i32 0, i32 -1
147  ret i32 %sel
148}
149
150define i32 @select_0_or_neg1_signext(i1 signext %cond) {
151; X86-LABEL: select_0_or_neg1_signext:
152; X86:       # %bb.0:
153; X86-NEXT:    movzbl {{[0-9]+}}(%esp), %eax
154; X86-NEXT:    andl $1, %eax
155; X86-NEXT:    decl %eax
156; X86-NEXT:    retl
157;
158; X64-LABEL: select_0_or_neg1_signext:
159; X64:       # %bb.0:
160; X64-NEXT:    movl %edi, %eax
161; X64-NEXT:    notl %eax
162; X64-NEXT:    retq
163  %sel = select i1 %cond, i32 0, i32 -1
164  ret i32 %sel
165}
166
167; select Cond, -1, 0 --> sext (Cond)
168
169define i32 @select_neg1_or_0(i1 %cond) {
170; X86-LABEL: select_neg1_or_0:
171; X86:       # %bb.0:
172; X86-NEXT:    movzbl {{[0-9]+}}(%esp), %eax
173; X86-NEXT:    andl $1, %eax
174; X86-NEXT:    negl %eax
175; X86-NEXT:    retl
176;
177; X64-LABEL: select_neg1_or_0:
178; X64:       # %bb.0:
179; X64-NEXT:    movl %edi, %eax
180; X64-NEXT:    andl $1, %eax
181; X64-NEXT:    negl %eax
182; X64-NEXT:    retq
183  %sel = select i1 %cond, i32 -1, i32 0
184  ret i32 %sel
185}
186
187define i32 @select_neg1_or_0_zeroext(i1 zeroext %cond) {
188; X86-LABEL: select_neg1_or_0_zeroext:
189; X86:       # %bb.0:
190; X86-NEXT:    movzbl {{[0-9]+}}(%esp), %eax
191; X86-NEXT:    negl %eax
192; X86-NEXT:    retl
193;
194; X64-LABEL: select_neg1_or_0_zeroext:
195; X64:       # %bb.0:
196; X64-NEXT:    movl %edi, %eax
197; X64-NEXT:    negl %eax
198; X64-NEXT:    retq
199  %sel = select i1 %cond, i32 -1, i32 0
200  ret i32 %sel
201}
202
203define i32 @select_neg1_or_0_signext(i1 signext %cond) {
204; X86-LABEL: select_neg1_or_0_signext:
205; X86:       # %bb.0:
206; X86-NEXT:    movsbl {{[0-9]+}}(%esp), %eax
207; X86-NEXT:    retl
208;
209; X64-LABEL: select_neg1_or_0_signext:
210; X64:       # %bb.0:
211; X64-NEXT:    movl %edi, %eax
212; X64-NEXT:    retq
213  %sel = select i1 %cond, i32 -1, i32 0
214  ret i32 %sel
215}
216
217; select Cond, C+1, C --> add (zext Cond), C
218
219define i32 @select_Cplus1_C(i1 %cond) {
220; X86-LABEL: select_Cplus1_C:
221; X86:       # %bb.0:
222; X86-NEXT:    movzbl {{[0-9]+}}(%esp), %eax
223; X86-NEXT:    andl $1, %eax
224; X86-NEXT:    addl $41, %eax
225; X86-NEXT:    retl
226;
227; X64-LABEL: select_Cplus1_C:
228; X64:       # %bb.0:
229; X64-NEXT:    # kill: def $edi killed $edi def $rdi
230; X64-NEXT:    andl $1, %edi
231; X64-NEXT:    leal 41(%rdi), %eax
232; X64-NEXT:    retq
233  %sel = select i1 %cond, i32 42, i32 41
234  ret i32 %sel
235}
236
237define i32 @select_Cplus1_C_zeroext(i1 zeroext %cond) {
238; X86-LABEL: select_Cplus1_C_zeroext:
239; X86:       # %bb.0:
240; X86-NEXT:    movzbl {{[0-9]+}}(%esp), %eax
241; X86-NEXT:    addl $41, %eax
242; X86-NEXT:    retl
243;
244; X64-LABEL: select_Cplus1_C_zeroext:
245; X64:       # %bb.0:
246; X64-NEXT:    # kill: def $edi killed $edi def $rdi
247; X64-NEXT:    leal 41(%rdi), %eax
248; X64-NEXT:    retq
249  %sel = select i1 %cond, i32 42, i32 41
250  ret i32 %sel
251}
252
253define i32 @select_Cplus1_C_signext(i1 signext %cond) {
254; X86-LABEL: select_Cplus1_C_signext:
255; X86:       # %bb.0:
256; X86-NEXT:    movzbl {{[0-9]+}}(%esp), %eax
257; X86-NEXT:    andl $1, %eax
258; X86-NEXT:    addl $41, %eax
259; X86-NEXT:    retl
260;
261; X64-LABEL: select_Cplus1_C_signext:
262; X64:       # %bb.0:
263; X64-NEXT:    movl $41, %eax
264; X64-NEXT:    subl %edi, %eax
265; X64-NEXT:    retq
266  %sel = select i1 %cond, i32 42, i32 41
267  ret i32 %sel
268}
269
270; select Cond, C, C+1 --> add (sext Cond), C
271
272define i32 @select_C_Cplus1(i1 %cond) {
273; X86-LABEL: select_C_Cplus1:
274; X86:       # %bb.0:
275; X86-NEXT:    movzbl {{[0-9]+}}(%esp), %ecx
276; X86-NEXT:    andl $1, %ecx
277; X86-NEXT:    movl $42, %eax
278; X86-NEXT:    subl %ecx, %eax
279; X86-NEXT:    retl
280;
281; X64-LABEL: select_C_Cplus1:
282; X64:       # %bb.0:
283; X64-NEXT:    andl $1, %edi
284; X64-NEXT:    movl $42, %eax
285; X64-NEXT:    subl %edi, %eax
286; X64-NEXT:    retq
287  %sel = select i1 %cond, i32 41, i32 42
288  ret i32 %sel
289}
290
291define i32 @select_C_Cplus1_zeroext(i1 zeroext %cond) {
292; X86-LABEL: select_C_Cplus1_zeroext:
293; X86:       # %bb.0:
294; X86-NEXT:    movzbl {{[0-9]+}}(%esp), %ecx
295; X86-NEXT:    movl $42, %eax
296; X86-NEXT:    subl %ecx, %eax
297; X86-NEXT:    retl
298;
299; X64-LABEL: select_C_Cplus1_zeroext:
300; X64:       # %bb.0:
301; X64-NEXT:    movl $42, %eax
302; X64-NEXT:    subl %edi, %eax
303; X64-NEXT:    retq
304  %sel = select i1 %cond, i32 41, i32 42
305  ret i32 %sel
306}
307
308define i32 @select_C_Cplus1_signext(i1 signext %cond) {
309; X86-LABEL: select_C_Cplus1_signext:
310; X86:       # %bb.0:
311; X86-NEXT:    movzbl {{[0-9]+}}(%esp), %ecx
312; X86-NEXT:    andl $1, %ecx
313; X86-NEXT:    movl $42, %eax
314; X86-NEXT:    subl %ecx, %eax
315; X86-NEXT:    retl
316;
317; X64-LABEL: select_C_Cplus1_signext:
318; X64:       # %bb.0:
319; X64-NEXT:    # kill: def $edi killed $edi def $rdi
320; X64-NEXT:    leal 42(%rdi), %eax
321; X64-NEXT:    retq
322  %sel = select i1 %cond, i32 41, i32 42
323  ret i32 %sel
324}
325
326; If the constants differ by a small multiplier, use LEA.
327; select Cond, C1, C2 --> add (mul (zext Cond), C1-C2), C2 --> LEA C2(Cond * (C1-C2))
328
329define i32 @select_lea_2(i1 zeroext %cond) {
330; X86-LABEL: select_lea_2:
331; X86:       # %bb.0:
332; X86-NEXT:    movzbl {{[0-9]+}}(%esp), %eax
333; X86-NEXT:    negl %eax
334; X86-NEXT:    orl $1, %eax
335; X86-NEXT:    retl
336;
337; X64-LABEL: select_lea_2:
338; X64:       # %bb.0:
339; X64-NEXT:    movl %edi, %eax
340; X64-NEXT:    negl %eax
341; X64-NEXT:    orl $1, %eax
342; X64-NEXT:    retq
343  %sel = select i1 %cond, i32 -1, i32 1
344  ret i32 %sel
345}
346
347define i64 @select_lea_3(i1 zeroext %cond) {
348; X86-LABEL: select_lea_3:
349; X86:       # %bb.0:
350; X86-NEXT:    cmpb $0, {{[0-9]+}}(%esp)
351; X86-NEXT:    movl $-2, %eax
352; X86-NEXT:    je .LBB19_1
353; X86-NEXT:  # %bb.2:
354; X86-NEXT:    movl $-1, %edx
355; X86-NEXT:    je .LBB19_3
356; X86-NEXT:  .LBB19_4:
357; X86-NEXT:    retl
358; X86-NEXT:  .LBB19_1:
359; X86-NEXT:    movl $1, %eax
360; X86-NEXT:    movl $-1, %edx
361; X86-NEXT:    jne .LBB19_4
362; X86-NEXT:  .LBB19_3:
363; X86-NEXT:    xorl %edx, %edx
364; X86-NEXT:    retl
365;
366; X64-LABEL: select_lea_3:
367; X64:       # %bb.0:
368; X64-NEXT:    xorb $1, %dil
369; X64-NEXT:    movzbl %dil, %eax
370; X64-NEXT:    leaq -2(%rax,%rax,2), %rax
371; X64-NEXT:    retq
372  %sel = select i1 %cond, i64 -2, i64 1
373  ret i64 %sel
374}
375
376define i32 @select_lea_5(i1 zeroext %cond) {
377; X86-LABEL: select_lea_5:
378; X86:       # %bb.0:
379; X86-NEXT:    movzbl {{[0-9]+}}(%esp), %eax
380; X86-NEXT:    xorb $1, %al
381; X86-NEXT:    movzbl %al, %eax
382; X86-NEXT:    leal -2(%eax,%eax,4), %eax
383; X86-NEXT:    retl
384;
385; X64-LABEL: select_lea_5:
386; X64:       # %bb.0:
387; X64-NEXT:    xorb $1, %dil
388; X64-NEXT:    movzbl %dil, %eax
389; X64-NEXT:    leal -2(%rax,%rax,4), %eax
390; X64-NEXT:    retq
391  %sel = select i1 %cond, i32 -2, i32 3
392  ret i32 %sel
393}
394
395define i64 @select_lea_9(i1 zeroext %cond) {
396; X86-LABEL: select_lea_9:
397; X86:       # %bb.0:
398; X86-NEXT:    cmpb $0, {{[0-9]+}}(%esp)
399; X86-NEXT:    movl $-7, %eax
400; X86-NEXT:    je .LBB21_1
401; X86-NEXT:  # %bb.2:
402; X86-NEXT:    movl $-1, %edx
403; X86-NEXT:    je .LBB21_3
404; X86-NEXT:  .LBB21_4:
405; X86-NEXT:    retl
406; X86-NEXT:  .LBB21_1:
407; X86-NEXT:    movl $2, %eax
408; X86-NEXT:    movl $-1, %edx
409; X86-NEXT:    jne .LBB21_4
410; X86-NEXT:  .LBB21_3:
411; X86-NEXT:    xorl %edx, %edx
412; X86-NEXT:    retl
413;
414; X64-LABEL: select_lea_9:
415; X64:       # %bb.0:
416; X64-NEXT:    xorb $1, %dil
417; X64-NEXT:    movzbl %dil, %eax
418; X64-NEXT:    leaq -7(%rax,%rax,8), %rax
419; X64-NEXT:    retq
420  %sel = select i1 %cond, i64 -7, i64 2
421  ret i64 %sel
422}
423
424; Should this be 'sbb x,x' or 'sbb 0,x' with simpler LEA or add?
425
426define i64 @sel_1_2(i64 %x, i64 %y) {
427; X86-LABEL: sel_1_2:
428; X86:       # %bb.0:
429; X86-NEXT:    movl {{[0-9]+}}(%esp), %eax
430; X86-NEXT:    movl {{[0-9]+}}(%esp), %edx
431; X86-NEXT:    movl {{[0-9]+}}(%esp), %ecx
432; X86-NEXT:    cmpl $42, {{[0-9]+}}(%esp)
433; X86-NEXT:    sbbl $0, %ecx
434; X86-NEXT:    sbbl $0, %eax
435; X86-NEXT:    sbbl $0, %edx
436; X86-NEXT:    addl $2, %eax
437; X86-NEXT:    adcl $0, %edx
438; X86-NEXT:    retl
439;
440; X64-LABEL: sel_1_2:
441; X64:       # %bb.0:
442; X64-NEXT:    cmpq $42, %rdi
443; X64-NEXT:    sbbq $0, %rsi
444; X64-NEXT:    leaq 2(%rsi), %rax
445; X64-NEXT:    retq
446  %cmp = icmp ult i64 %x, 42
447  %sel = select i1 %cmp, i64 1, i64 2
448  %sub = add i64 %sel, %y
449  ret i64 %sub
450}
451
452; No LEA with 8-bit, but this shouldn't need branches or cmov.
453
454define i8 @sel_1_neg1(i32 %x) {
455; X86-LABEL: sel_1_neg1:
456; X86:       # %bb.0:
457; X86-NEXT:    cmpl $43, {{[0-9]+}}(%esp)
458; X86-NEXT:    setl %al
459; X86-NEXT:    negb %al
460; X86-NEXT:    orb $3, %al
461; X86-NEXT:    retl
462;
463; X64-LABEL: sel_1_neg1:
464; X64:       # %bb.0:
465; X64-NEXT:    cmpl $43, %edi
466; X64-NEXT:    setl %al
467; X64-NEXT:    negb %al
468; X64-NEXT:    orb $3, %al
469; X64-NEXT:    retq
470  %cmp = icmp sgt i32 %x, 42
471  %sel = select i1 %cmp, i8 3, i8 -1
472  ret i8 %sel
473}
474
475; We get an LEA for 16-bit because we ignore the high-bits.
476
477define i16 @sel_neg1_1(i32 %x) {
478; X86-LABEL: sel_neg1_1:
479; X86:       # %bb.0:
480; X86-NEXT:    xorl %eax, %eax
481; X86-NEXT:    cmpl $43, {{[0-9]+}}(%esp)
482; X86-NEXT:    setl %al
483; X86-NEXT:    leal -1(,%eax,4), %eax
484; X86-NEXT:    # kill: def $ax killed $ax killed $eax
485; X86-NEXT:    retl
486;
487; X64-LABEL: sel_neg1_1:
488; X64:       # %bb.0:
489; X64-NEXT:    xorl %eax, %eax
490; X64-NEXT:    cmpl $43, %edi
491; X64-NEXT:    setl %al
492; X64-NEXT:    leal -1(,%rax,4), %eax
493; X64-NEXT:    # kill: def $ax killed $ax killed $eax
494; X64-NEXT:    retq
495  %cmp = icmp sgt i32 %x, 42
496  %sel = select i1 %cmp, i16 -1, i16 3
497  ret i16 %sel
498}
499
500; If the comparison is available, the predicate can be inverted.
501
502define i32 @sel_1_neg1_32(i32 %x) {
503; X86-LABEL: sel_1_neg1_32:
504; X86:       # %bb.0:
505; X86-NEXT:    xorl %eax, %eax
506; X86-NEXT:    cmpl $43, {{[0-9]+}}(%esp)
507; X86-NEXT:    setge %al
508; X86-NEXT:    leal -1(%eax,%eax,8), %eax
509; X86-NEXT:    retl
510;
511; X64-LABEL: sel_1_neg1_32:
512; X64:       # %bb.0:
513; X64-NEXT:    xorl %eax, %eax
514; X64-NEXT:    cmpl $43, %edi
515; X64-NEXT:    setge %al
516; X64-NEXT:    leal -1(%rax,%rax,8), %eax
517; X64-NEXT:    retq
518  %cmp = icmp sgt i32 %x, 42
519  %sel = select i1 %cmp, i32 8, i32 -1
520  ret i32 %sel
521}
522
523define i32 @sel_neg1_1_32(i32 %x) {
524; X86-LABEL: sel_neg1_1_32:
525; X86:       # %bb.0:
526; X86-NEXT:    xorl %eax, %eax
527; X86-NEXT:    cmpl $43, {{[0-9]+}}(%esp)
528; X86-NEXT:    setl %al
529; X86-NEXT:    leal -7(%eax,%eax,8), %eax
530; X86-NEXT:    retl
531;
532; X64-LABEL: sel_neg1_1_32:
533; X64:       # %bb.0:
534; X64-NEXT:    xorl %eax, %eax
535; X64-NEXT:    cmpl $43, %edi
536; X64-NEXT:    setl %al
537; X64-NEXT:    leal -7(%rax,%rax,8), %eax
538; X64-NEXT:    retq
539  %cmp = icmp sgt i32 %x, 42
540  %sel = select i1 %cmp, i32 -7, i32 2
541  ret i32 %sel
542}
543
544
545; If the constants differ by a large power-of-2, that can be a shift of the difference plus the smaller constant.
546; select Cond, C1, C2 --> add (mul (zext Cond), C1-C2), C2
547
548define i8 @select_pow2_diff(i1 zeroext %cond) {
549; X86-LABEL: select_pow2_diff:
550; X86:       # %bb.0:
551; X86-NEXT:    movzbl {{[0-9]+}}(%esp), %eax
552; X86-NEXT:    shlb $4, %al
553; X86-NEXT:    orb $3, %al
554; X86-NEXT:    retl
555;
556; X64-LABEL: select_pow2_diff:
557; X64:       # %bb.0:
558; X64-NEXT:    # kill: def $edi killed $edi def $rdi
559; X64-NEXT:    shlb $4, %dil
560; X64-NEXT:    leal 3(%rdi), %eax
561; X64-NEXT:    # kill: def $al killed $al killed $eax
562; X64-NEXT:    retq
563  %sel = select i1 %cond, i8 19, i8 3
564  ret i8 %sel
565}
566
567define i16 @select_pow2_diff_invert(i1 zeroext %cond) {
568; X86-LABEL: select_pow2_diff_invert:
569; X86:       # %bb.0:
570; X86-NEXT:    movzbl {{[0-9]+}}(%esp), %eax
571; X86-NEXT:    xorb $1, %al
572; X86-NEXT:    movzbl %al, %eax
573; X86-NEXT:    shll $6, %eax
574; X86-NEXT:    orl $7, %eax
575; X86-NEXT:    # kill: def $ax killed $ax killed $eax
576; X86-NEXT:    retl
577;
578; X64-LABEL: select_pow2_diff_invert:
579; X64:       # %bb.0:
580; X64-NEXT:    xorb $1, %dil
581; X64-NEXT:    movzbl %dil, %eax
582; X64-NEXT:    shll $6, %eax
583; X64-NEXT:    orl $7, %eax
584; X64-NEXT:    # kill: def $ax killed $ax killed $eax
585; X64-NEXT:    retq
586  %sel = select i1 %cond, i16 7, i16 71
587  ret i16 %sel
588}
589
590define i32 @select_pow2_diff_neg(i1 zeroext %cond) {
591; X86-LABEL: select_pow2_diff_neg:
592; X86:       # %bb.0:
593; X86-NEXT:    movzbl {{[0-9]+}}(%esp), %eax
594; X86-NEXT:    shll $4, %eax
595; X86-NEXT:    orl $-25, %eax
596; X86-NEXT:    retl
597;
598; X64-LABEL: select_pow2_diff_neg:
599; X64:       # %bb.0:
600; X64-NEXT:    # kill: def $edi killed $edi def $rdi
601; X64-NEXT:    shll $4, %edi
602; X64-NEXT:    leal -25(%rdi), %eax
603; X64-NEXT:    retq
604  %sel = select i1 %cond, i32 -9, i32 -25
605  ret i32 %sel
606}
607
608define i64 @select_pow2_diff_neg_invert(i1 zeroext %cond) {
609; X86-LABEL: select_pow2_diff_neg_invert:
610; X86:       # %bb.0:
611; X86-NEXT:    cmpb $0, {{[0-9]+}}(%esp)
612; X86-NEXT:    movl $-99, %eax
613; X86-NEXT:    je .LBB30_1
614; X86-NEXT:  # %bb.2:
615; X86-NEXT:    movl $-1, %edx
616; X86-NEXT:    je .LBB30_3
617; X86-NEXT:  .LBB30_4:
618; X86-NEXT:    retl
619; X86-NEXT:  .LBB30_1:
620; X86-NEXT:    movl $29, %eax
621; X86-NEXT:    movl $-1, %edx
622; X86-NEXT:    jne .LBB30_4
623; X86-NEXT:  .LBB30_3:
624; X86-NEXT:    xorl %edx, %edx
625; X86-NEXT:    retl
626;
627; X64-LABEL: select_pow2_diff_neg_invert:
628; X64:       # %bb.0:
629; X64-NEXT:    xorb $1, %dil
630; X64-NEXT:    movzbl %dil, %eax
631; X64-NEXT:    shll $7, %eax
632; X64-NEXT:    addq $-99, %rax
633; X64-NEXT:    retq
634  %sel = select i1 %cond, i64 -99, i64 29
635  ret i64 %sel
636}
637
638; This doesn't need a branch, but don't do the wrong thing if subtraction of the constants overflows.
639
640define i8 @sel_67_neg125(i32 %x) {
641; X86-LABEL: sel_67_neg125:
642; X86:       # %bb.0:
643; X86-NEXT:    cmpl $43, {{[0-9]+}}(%esp)
644; X86-NEXT:    movb $67, %al
645; X86-NEXT:    jge .LBB31_2
646; X86-NEXT:  # %bb.1:
647; X86-NEXT:    movb $-125, %al
648; X86-NEXT:  .LBB31_2:
649; X86-NEXT:    retl
650;
651; X64-LABEL: sel_67_neg125:
652; X64:       # %bb.0:
653; X64-NEXT:    cmpl $43, %edi
654; X64-NEXT:    movl $67, %ecx
655; X64-NEXT:    movl $131, %eax
656; X64-NEXT:    cmovgel %ecx, %eax
657; X64-NEXT:    # kill: def $al killed $al killed $eax
658; X64-NEXT:    retq
659  %cmp = icmp sgt i32 %x, 42
660  %sel = select i1 %cmp, i8 67, i8 -125
661  ret i8 %sel
662}
663
664
665; In general, select of 2 constants could be:
666; select Cond, C1, C2 --> add (mul (zext Cond), C1-C2), C2 --> add (and (sext Cond), C1-C2), C2
667
668define i32 @select_C1_C2(i1 %cond) {
669; X86-LABEL: select_C1_C2:
670; X86:       # %bb.0:
671; X86-NEXT:    movzbl {{[0-9]+}}(%esp), %eax
672; X86-NEXT:    andl $1, %eax
673; X86-NEXT:    negl %eax
674; X86-NEXT:    andl $399, %eax # imm = 0x18F
675; X86-NEXT:    xorl $42, %eax
676; X86-NEXT:    retl
677;
678; X64-LABEL: select_C1_C2:
679; X64:       # %bb.0:
680; X64-NEXT:    testb $1, %dil
681; X64-NEXT:    movl $421, %ecx # imm = 0x1A5
682; X64-NEXT:    movl $42, %eax
683; X64-NEXT:    cmovnel %ecx, %eax
684; X64-NEXT:    retq
685  %sel = select i1 %cond, i32 421, i32 42
686  ret i32 %sel
687}
688
689define i32 @select_C1_C2_zeroext(i1 zeroext %cond) {
690; X86-LABEL: select_C1_C2_zeroext:
691; X86:       # %bb.0:
692; X86-NEXT:    cmpb $0, {{[0-9]+}}(%esp)
693; X86-NEXT:    movl $421, %eax # imm = 0x1A5
694; X86-NEXT:    jne .LBB33_2
695; X86-NEXT:  # %bb.1:
696; X86-NEXT:    movl $42, %eax
697; X86-NEXT:  .LBB33_2:
698; X86-NEXT:    retl
699;
700; X64-LABEL: select_C1_C2_zeroext:
701; X64:       # %bb.0:
702; X64-NEXT:    testl %edi, %edi
703; X64-NEXT:    movl $421, %ecx # imm = 0x1A5
704; X64-NEXT:    movl $42, %eax
705; X64-NEXT:    cmovnel %ecx, %eax
706; X64-NEXT:    retq
707  %sel = select i1 %cond, i32 421, i32 42
708  ret i32 %sel
709}
710
711define i32 @select_C1_C2_signext(i1 signext %cond) {
712; X86-LABEL: select_C1_C2_signext:
713; X86:       # %bb.0:
714; X86-NEXT:    movzbl {{[0-9]+}}(%esp), %eax
715; X86-NEXT:    andl $1, %eax
716; X86-NEXT:    negl %eax
717; X86-NEXT:    andl $399, %eax # imm = 0x18F
718; X86-NEXT:    xorl $42, %eax
719; X86-NEXT:    retl
720;
721; X64-LABEL: select_C1_C2_signext:
722; X64:       # %bb.0:
723; X64-NEXT:    testb $1, %dil
724; X64-NEXT:    movl $421, %ecx # imm = 0x1A5
725; X64-NEXT:    movl $42, %eax
726; X64-NEXT:    cmovnel %ecx, %eax
727; X64-NEXT:    retq
728  %sel = select i1 %cond, i32 421, i32 42
729  ret i32 %sel
730}
731
732define i32 @select_n_or_minus1(i1 signext %cond) {
733; X86-LABEL: select_n_or_minus1:
734; X86:       # %bb.0:
735; X86-NEXT:    movzbl {{[0-9]+}}(%esp), %eax
736; X86-NEXT:    andl $1, %eax
737; X86-NEXT:    decl %eax
738; X86-NEXT:    orl $12414, %eax # imm = 0x307E
739; X86-NEXT:    retl
740;
741; X64-LABEL: select_n_or_minus1:
742; X64:       # %bb.0:
743; X64-NEXT:    movl %edi, %eax
744; X64-NEXT:    notl %eax
745; X64-NEXT:    orl $12414, %eax # imm = 0x307E
746; X64-NEXT:    retq
747  %sel = select i1 %cond, i32 12414, i32 -1
748  ret i32 %sel
749}
750
751; select (x == 2), 2, (x + 1) --> select (x == 2), x, (x + 1)
752
753define i64 @select_2_or_inc(i64 %x) {
754; X86-LABEL: select_2_or_inc:
755; X86:       # %bb.0:
756; X86-NEXT:    pushl %edi
757; X86-NEXT:    .cfi_def_cfa_offset 8
758; X86-NEXT:    pushl %esi
759; X86-NEXT:    .cfi_def_cfa_offset 12
760; X86-NEXT:    .cfi_offset %esi, -12
761; X86-NEXT:    .cfi_offset %edi, -8
762; X86-NEXT:    movl {{[0-9]+}}(%esp), %ecx
763; X86-NEXT:    movl {{[0-9]+}}(%esp), %esi
764; X86-NEXT:    movl %ecx, %edi
765; X86-NEXT:    xorl $2, %edi
766; X86-NEXT:    addl $1, %ecx
767; X86-NEXT:    movl %esi, %eax
768; X86-NEXT:    adcl $0, %eax
769; X86-NEXT:    xorl %edx, %edx
770; X86-NEXT:    orl %esi, %edi
771; X86-NEXT:    je .LBB36_2
772; X86-NEXT:  # %bb.1:
773; X86-NEXT:    movl %eax, %edx
774; X86-NEXT:  .LBB36_2:
775; X86-NEXT:    movl $2, %eax
776; X86-NEXT:    je .LBB36_4
777; X86-NEXT:  # %bb.3:
778; X86-NEXT:    movl %ecx, %eax
779; X86-NEXT:  .LBB36_4:
780; X86-NEXT:    popl %esi
781; X86-NEXT:    .cfi_def_cfa_offset 8
782; X86-NEXT:    popl %edi
783; X86-NEXT:    .cfi_def_cfa_offset 4
784; X86-NEXT:    retl
785;
786; X64-LABEL: select_2_or_inc:
787; X64:       # %bb.0:
788; X64-NEXT:    leaq 1(%rdi), %rax
789; X64-NEXT:    cmpq $2, %rdi
790; X64-NEXT:    cmoveq %rdi, %rax
791; X64-NEXT:    retq
792  %cmp = icmp eq i64 %x, 2
793  %add = add i64 %x, 1
794  %retval.0 = select i1 %cmp, i64 2, i64 %add
795  ret i64 %retval.0
796}
797
798define <4 x i32> @sel_constants_add_constant_vec(i1 %cond) {
799; X86-LABEL: sel_constants_add_constant_vec:
800; X86:       # %bb.0:
801; X86-NEXT:    pushl %edi
802; X86-NEXT:    .cfi_def_cfa_offset 8
803; X86-NEXT:    pushl %esi
804; X86-NEXT:    .cfi_def_cfa_offset 12
805; X86-NEXT:    .cfi_offset %esi, -12
806; X86-NEXT:    .cfi_offset %edi, -8
807; X86-NEXT:    movl {{[0-9]+}}(%esp), %eax
808; X86-NEXT:    movzbl {{[0-9]+}}(%esp), %ecx
809; X86-NEXT:    andl $1, %ecx
810; X86-NEXT:    negl %ecx
811; X86-NEXT:    movl %ecx, %edx
812; X86-NEXT:    andl $-15, %edx
813; X86-NEXT:    orl $12, %edx
814; X86-NEXT:    movl %ecx, %esi
815; X86-NEXT:    andl $3, %esi
816; X86-NEXT:    xorl $13, %esi
817; X86-NEXT:    movl %ecx, %edi
818; X86-NEXT:    andl $10, %edi
819; X86-NEXT:    xorl $14, %edi
820; X86-NEXT:    andl $11, %ecx
821; X86-NEXT:    xorl $15, %ecx
822; X86-NEXT:    movl %ecx, 12(%eax)
823; X86-NEXT:    movl %edi, 8(%eax)
824; X86-NEXT:    movl %esi, 4(%eax)
825; X86-NEXT:    movl %edx, (%eax)
826; X86-NEXT:    popl %esi
827; X86-NEXT:    .cfi_def_cfa_offset 8
828; X86-NEXT:    popl %edi
829; X86-NEXT:    .cfi_def_cfa_offset 4
830; X86-NEXT:    retl $4
831;
832; X64-LABEL: sel_constants_add_constant_vec:
833; X64:       # %bb.0:
834; X64-NEXT:    testb $1, %dil
835; X64-NEXT:    jne .LBB37_1
836; X64-NEXT:  # %bb.2:
837; X64-NEXT:    movaps {{.*#+}} xmm0 = [12,13,14,15]
838; X64-NEXT:    retq
839; X64-NEXT:  .LBB37_1:
840; X64-NEXT:    movaps {{.*#+}} xmm0 = [4294967293,14,4,4]
841; X64-NEXT:    retq
842  %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>
843  %bo = add <4 x i32> %sel, <i32 1, i32 2, i32 3, i32 4>
844  ret <4 x i32> %bo
845}
846
847define <2 x double> @sel_constants_fmul_constant_vec(i1 %cond) {
848; X86-LABEL: sel_constants_fmul_constant_vec:
849; X86:       # %bb.0:
850; X86-NEXT:    testb $1, {{[0-9]+}}(%esp)
851; X86-NEXT:    fldl {{\.?LCPI[0-9]+_[0-9]+}}
852; X86-NEXT:    fldl {{\.?LCPI[0-9]+_[0-9]+}}
853; X86-NEXT:    jne .LBB38_2
854; X86-NEXT:  # %bb.1:
855; X86-NEXT:    fstp %st(1)
856; X86-NEXT:    fldz
857; X86-NEXT:  .LBB38_2:
858; X86-NEXT:    fstp %st(0)
859; X86-NEXT:    fldl {{\.?LCPI[0-9]+_[0-9]+}}
860; X86-NEXT:    fldl {{\.?LCPI[0-9]+_[0-9]+}}
861; X86-NEXT:    jne .LBB38_4
862; X86-NEXT:  # %bb.3:
863; X86-NEXT:    fstp %st(1)
864; X86-NEXT:    fldz
865; X86-NEXT:  .LBB38_4:
866; X86-NEXT:    fstp %st(0)
867; X86-NEXT:    retl
868;
869; X64-LABEL: sel_constants_fmul_constant_vec:
870; X64:       # %bb.0:
871; X64-NEXT:    testb $1, %dil
872; X64-NEXT:    jne .LBB38_1
873; X64-NEXT:  # %bb.2:
874; X64-NEXT:    movaps {{.*#+}} xmm0 = [1.1883E+2,3.4539999999999999E+1]
875; X64-NEXT:    retq
876; X64-NEXT:  .LBB38_1:
877; X64-NEXT:    movaps {{.*#+}} xmm0 = [-2.0399999999999999E+1,3.768E+1]
878; X64-NEXT:    retq
879  %sel = select i1 %cond, <2 x double> <double -4.0, double 12.0>, <2 x double> <double 23.3, double 11.0>
880  %bo = fmul <2 x double> %sel, <double 5.1, double 3.14>
881  ret <2 x double> %bo
882}
883
884; 4294967297 = 0x100000001.
885; This becomes an opaque constant via ConstantHoisting, so we don't fold it into the select.
886
887define i64 @opaque_constant(i1 %cond, i64 %x) {
888; X86-LABEL: opaque_constant:
889; X86:       # %bb.0:
890; X86-NEXT:    pushl %ebx
891; X86-NEXT:    .cfi_def_cfa_offset 8
892; X86-NEXT:    pushl %esi
893; X86-NEXT:    .cfi_def_cfa_offset 12
894; X86-NEXT:    .cfi_offset %esi, -12
895; X86-NEXT:    .cfi_offset %ebx, -8
896; X86-NEXT:    movl {{[0-9]+}}(%esp), %ecx
897; X86-NEXT:    movl {{[0-9]+}}(%esp), %esi
898; X86-NEXT:    movzbl {{[0-9]+}}(%esp), %eax
899; X86-NEXT:    movl %eax, %edx
900; X86-NEXT:    andl $1, %edx
901; X86-NEXT:    negl %edx
902; X86-NEXT:    andl $1, %edx
903; X86-NEXT:    decl %eax
904; X86-NEXT:    andl $1, %eax
905; X86-NEXT:    xorl $1, %esi
906; X86-NEXT:    xorl $1, %ecx
907; X86-NEXT:    xorl %ebx, %ebx
908; X86-NEXT:    orl %esi, %ecx
909; X86-NEXT:    sete %bl
910; X86-NEXT:    subl %ebx, %eax
911; X86-NEXT:    sbbl $0, %edx
912; X86-NEXT:    popl %esi
913; X86-NEXT:    .cfi_def_cfa_offset 8
914; X86-NEXT:    popl %ebx
915; X86-NEXT:    .cfi_def_cfa_offset 4
916; X86-NEXT:    retl
917;
918; X64-LABEL: opaque_constant:
919; X64:       # %bb.0:
920; X64-NEXT:    testb $1, %dil
921; X64-NEXT:    movq $-4, %rcx
922; X64-NEXT:    movl $23, %eax
923; X64-NEXT:    cmovneq %rcx, %rax
924; X64-NEXT:    movabsq $4294967297, %rcx # imm = 0x100000001
925; X64-NEXT:    andq %rcx, %rax
926; X64-NEXT:    xorl %edx, %edx
927; X64-NEXT:    cmpq %rcx, %rsi
928; X64-NEXT:    sete %dl
929; X64-NEXT:    subq %rdx, %rax
930; X64-NEXT:    retq
931  %sel = select i1 %cond, i64 -4, i64 23
932  %bo = and i64 %sel, 4294967297
933  %cmp = icmp eq i64 %x, 4294967297
934  %sext = sext i1 %cmp to i64
935  %add = add i64 %bo, %sext
936  ret i64 %add
937}
938
939define float @select_undef_fp(float %x) {
940; X86-LABEL: select_undef_fp:
941; X86:       # %bb.0:
942; X86-NEXT:    flds {{\.?LCPI[0-9]+_[0-9]+}}
943; X86-NEXT:    retl
944;
945; X64-LABEL: select_undef_fp:
946; X64:       # %bb.0:
947; X64-NEXT:    movss {{.*#+}} xmm0 = [4.0E+0,0.0E+0,0.0E+0,0.0E+0]
948; X64-NEXT:    retq
949  %f = select i1 undef, float 4.0, float %x
950  ret float %f
951}
952
953define i32 @select_eq0_3_2(i32 %X) {
954; X86-LABEL: select_eq0_3_2:
955; X86:       # %bb.0:
956; X86-NEXT:    xorl %eax, %eax
957; X86-NEXT:    cmpl $1, {{[0-9]+}}(%esp)
958; X86-NEXT:    adcl $2, %eax
959; X86-NEXT:    retl
960;
961; X64-LABEL: select_eq0_3_2:
962; X64:       # %bb.0:
963; X64-NEXT:    xorl %eax, %eax
964; X64-NEXT:    cmpl $1, %edi
965; X64-NEXT:    adcl $2, %eax
966; X64-NEXT:    retq
967  %cmp = icmp eq i32 %X, 0
968  %sel = select i1 %cmp, i32 3, i32 2
969  ret i32 %sel
970}
971
972define i32 @select_ugt3_2_3(i32 %X) {
973; X86-LABEL: select_ugt3_2_3:
974; X86:       # %bb.0:
975; X86-NEXT:    xorl %eax, %eax
976; X86-NEXT:    cmpl $4, {{[0-9]+}}(%esp)
977; X86-NEXT:    adcl $2, %eax
978; X86-NEXT:    retl
979;
980; X64-LABEL: select_ugt3_2_3:
981; X64:       # %bb.0:
982; X64-NEXT:    xorl %eax, %eax
983; X64-NEXT:    cmpl $4, %edi
984; X64-NEXT:    adcl $2, %eax
985; X64-NEXT:    retq
986  %cmp = icmp ugt i32 %X, 3
987  %sel = select i1 %cmp, i32 2, i32 3
988  ret i32 %sel
989}
990
991define i32 @select_ult9_7_6(i32 %X) {
992; X86-LABEL: select_ult9_7_6:
993; X86:       # %bb.0:
994; X86-NEXT:    xorl %eax, %eax
995; X86-NEXT:    cmpl $9, {{[0-9]+}}(%esp)
996; X86-NEXT:    adcl $6, %eax
997; X86-NEXT:    retl
998;
999; X64-LABEL: select_ult9_7_6:
1000; X64:       # %bb.0:
1001; X64-NEXT:    xorl %eax, %eax
1002; X64-NEXT:    cmpl $9, %edi
1003; X64-NEXT:    adcl $6, %eax
1004; X64-NEXT:    retq
1005  %cmp = icmp ult i32 %X, 9
1006  %sel = select i1 %cmp, i32 7, i32 6
1007  ret i32 %sel
1008}
1009
1010define i32 @select_ult2_2_3(i32 %X) {
1011; X86-LABEL: select_ult2_2_3:
1012; X86:       # %bb.0:
1013; X86-NEXT:    cmpl $2, {{[0-9]+}}(%esp)
1014; X86-NEXT:    movl $3, %eax
1015; X86-NEXT:    sbbl $0, %eax
1016; X86-NEXT:    retl
1017;
1018; X64-LABEL: select_ult2_2_3:
1019; X64:       # %bb.0:
1020; X64-NEXT:    cmpl $2, %edi
1021; X64-NEXT:    movl $3, %eax
1022; X64-NEXT:    sbbl $0, %eax
1023; X64-NEXT:    retq
1024  %cmp = icmp ult i32 %X, 2
1025  %cond = select i1 %cmp, i32 2, i32 3
1026  ret i32 %cond
1027}
1028
1029define i32 @select_ugt3_3_2(i32 %X) {
1030; X86-LABEL: select_ugt3_3_2:
1031; X86:       # %bb.0:
1032; X86-NEXT:    cmpl $4, {{[0-9]+}}(%esp)
1033; X86-NEXT:    movl $2, %eax
1034; X86-NEXT:    sbbl $-1, %eax
1035; X86-NEXT:    retl
1036;
1037; X64-LABEL: select_ugt3_3_2:
1038; X64:       # %bb.0:
1039; X64-NEXT:    cmpl $4, %edi
1040; X64-NEXT:    movl $2, %eax
1041; X64-NEXT:    sbbl $-1, %eax
1042; X64-NEXT:    retq
1043  %cmp.inv = icmp ugt i32 %X, 3
1044  %cond = select i1 %cmp.inv, i32 3, i32 2
1045  ret i32 %cond
1046}
1047
1048define i32 @select_eq_1_2(i32 %a, i32 %b) {
1049; X86-LABEL: select_eq_1_2:
1050; X86:       # %bb.0:
1051; X86-NEXT:    movl {{[0-9]+}}(%esp), %ecx
1052; X86-NEXT:    xorl %eax, %eax
1053; X86-NEXT:    cmpl {{[0-9]+}}(%esp), %ecx
1054; X86-NEXT:    setne %al
1055; X86-NEXT:    incl %eax
1056; X86-NEXT:    retl
1057;
1058; X64-FASTINC-LABEL: select_eq_1_2:
1059; X64-FASTINC:       # %bb.0:
1060; X64-FASTINC-NEXT:    xorl %eax, %eax
1061; X64-FASTINC-NEXT:    cmpl %esi, %edi
1062; X64-FASTINC-NEXT:    setne %al
1063; X64-FASTINC-NEXT:    incl %eax
1064; X64-FASTINC-NEXT:    retq
1065;
1066; X64-SLOWINC-LABEL: select_eq_1_2:
1067; X64-SLOWINC:       # %bb.0:
1068; X64-SLOWINC-NEXT:    xorl %eax, %eax
1069; X64-SLOWINC-NEXT:    cmpl %esi, %edi
1070; X64-SLOWINC-NEXT:    setne %al
1071; X64-SLOWINC-NEXT:    addl $1, %eax
1072; X64-SLOWINC-NEXT:    retq
1073
1074  %cmp = icmp eq i32 %a, %b
1075  %cond = select i1 %cmp, i32 1, i32 2
1076  ret i32 %cond
1077}
1078