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 @lshr_constant_sel_constants(i1 %cond) {
208; CHECK-LABEL: lshr_constant_sel_constants:
209; CHECK:       # %bb.0:
210; CHECK-NEXT:    # kill: def $edi killed $edi def $rdi
211; CHECK-NEXT:    andl $1, %edi
212; CHECK-NEXT:    leal 8(,%rdi,8), %eax
213; CHECK-NEXT:    retq
214  %sel = select i1 %cond, i32 2, i32 3
215  %bo = lshr i32 64, %sel
216  ret i32 %bo
217}
218
219define i32 @ashr_constant_sel_constants(i1 %cond) {
220; CHECK-LABEL: ashr_constant_sel_constants:
221; CHECK:       # %bb.0:
222; CHECK-NEXT:    # kill: def $edi killed $edi def $rdi
223; CHECK-NEXT:    andl $1, %edi
224; CHECK-NEXT:    shll $4, %edi
225; CHECK-NEXT:    leal 16(%rdi), %eax
226; CHECK-NEXT:    retq
227  %sel = select i1 %cond, i32 2, i32 3
228  %bo = ashr i32 128, %sel
229  ret i32 %bo
230}
231
232define double @fsub_constant_sel_constants(i1 %cond) {
233; CHECK-LABEL: fsub_constant_sel_constants:
234; CHECK:       # %bb.0:
235; CHECK-NEXT:    testb $1, %dil
236; CHECK-NEXT:    jne .LBB17_1
237; CHECK-NEXT:  # %bb.2:
238; CHECK-NEXT:    movsd {{.*#+}} xmm0 = mem[0],zero
239; CHECK-NEXT:    retq
240; CHECK-NEXT:  .LBB17_1:
241; CHECK-NEXT:    movsd {{.*#+}} xmm0 = mem[0],zero
242; CHECK-NEXT:    retq
243  %sel = select i1 %cond, double -4.0, double 23.3
244  %bo = fsub double 5.1, %sel
245  ret double %bo
246}
247
248define double @fdiv_constant_sel_constants(i1 %cond) {
249; CHECK-LABEL: fdiv_constant_sel_constants:
250; CHECK:       # %bb.0:
251; CHECK-NEXT:    testb $1, %dil
252; CHECK-NEXT:    jne .LBB18_1
253; CHECK-NEXT:  # %bb.2:
254; CHECK-NEXT:    movsd {{.*#+}} xmm0 = mem[0],zero
255; CHECK-NEXT:    retq
256; CHECK-NEXT:  .LBB18_1:
257; CHECK-NEXT:    movsd {{.*#+}} xmm0 = mem[0],zero
258; CHECK-NEXT:    retq
259  %sel = select i1 %cond, double -4.0, double 23.3
260  %bo = fdiv double 5.1, %sel
261  ret double %bo
262}
263
264define double @frem_constant_sel_constants(i1 %cond) {
265; CHECK-LABEL: frem_constant_sel_constants:
266; CHECK:       # %bb.0:
267; CHECK-NEXT:    testb $1, %dil
268; CHECK-NEXT:    jne .LBB19_1
269; CHECK-NEXT:  # %bb.2:
270; CHECK-NEXT:    movsd {{.*#+}} xmm0 = mem[0],zero
271; CHECK-NEXT:    retq
272; CHECK-NEXT:  .LBB19_1:
273; CHECK-NEXT:    movsd {{.*#+}} xmm0 = mem[0],zero
274; CHECK-NEXT:    retq
275  %sel = select i1 %cond, double -4.0, double 23.3
276  %bo = frem double 5.1, %sel
277  ret double %bo
278}
279
280declare i64 @llvm.cttz.i64(i64, i1)
281define i64 @cttz_64_eq_select(i64 %v) nounwind {
282; NOBMI-LABEL: cttz_64_eq_select:
283; NOBMI:       # %bb.0:
284; NOBMI-NEXT:    bsfq %rdi, %rcx
285; NOBMI-NEXT:    movq $-1, %rax
286; NOBMI-NEXT:    cmovneq %rcx, %rax
287; NOBMI-NEXT:    addq $6, %rax
288; NOBMI-NEXT:    retq
289;
290; BMI-LABEL: cttz_64_eq_select:
291; BMI:       # %bb.0:
292; BMI-NEXT:    tzcntq %rdi, %rcx
293; BMI-NEXT:    movq $-1, %rax
294; BMI-NEXT:    cmovaeq %rcx, %rax
295; BMI-NEXT:    addq $6, %rax
296; BMI-NEXT:    retq
297
298  %cnt = tail call i64 @llvm.cttz.i64(i64 %v, i1 true)
299  %tobool = icmp eq i64 %v, 0
300  %.op = add nuw nsw i64 %cnt, 6
301  %add = select i1 %tobool, i64 5, i64 %.op
302  ret i64 %add
303}
304
305define i64 @cttz_64_ne_select(i64 %v) nounwind {
306; NOBMI-LABEL: cttz_64_ne_select:
307; NOBMI:       # %bb.0:
308; NOBMI-NEXT:    bsfq %rdi, %rcx
309; NOBMI-NEXT:    movq $-1, %rax
310; NOBMI-NEXT:    cmovneq %rcx, %rax
311; NOBMI-NEXT:    addq $6, %rax
312; NOBMI-NEXT:    retq
313;
314; BMI-LABEL: cttz_64_ne_select:
315; BMI:       # %bb.0:
316; BMI-NEXT:    tzcntq %rdi, %rcx
317; BMI-NEXT:    movq $-1, %rax
318; BMI-NEXT:    cmovaeq %rcx, %rax
319; BMI-NEXT:    addq $6, %rax
320; BMI-NEXT:    retq
321
322  %cnt = tail call i64 @llvm.cttz.i64(i64 %v, i1 true)
323  %tobool = icmp ne i64 %v, 0
324  %.op = add nuw nsw i64 %cnt, 6
325  %add = select i1 %tobool, i64 %.op, i64 5
326  ret i64 %add
327}
328
329declare i32 @llvm.cttz.i32(i32, i1)
330define i32 @cttz_32_eq_select(i32 %v) nounwind {
331; NOBMI-LABEL: cttz_32_eq_select:
332; NOBMI:       # %bb.0:
333; NOBMI-NEXT:    bsfl %edi, %ecx
334; NOBMI-NEXT:    movl $-1, %eax
335; NOBMI-NEXT:    cmovnel %ecx, %eax
336; NOBMI-NEXT:    addl $6, %eax
337; NOBMI-NEXT:    retq
338;
339; BMI-LABEL: cttz_32_eq_select:
340; BMI:       # %bb.0:
341; BMI-NEXT:    tzcntl %edi, %ecx
342; BMI-NEXT:    movl $-1, %eax
343; BMI-NEXT:    cmovael %ecx, %eax
344; BMI-NEXT:    addl $6, %eax
345; BMI-NEXT:    retq
346
347  %cnt = tail call i32 @llvm.cttz.i32(i32 %v, i1 true)
348  %tobool = icmp eq i32 %v, 0
349  %.op = add nuw nsw i32 %cnt, 6
350  %add = select i1 %tobool, i32 5, i32 %.op
351  ret i32 %add
352}
353
354define i32 @cttz_32_ne_select(i32 %v) nounwind {
355; NOBMI-LABEL: cttz_32_ne_select:
356; NOBMI:       # %bb.0:
357; NOBMI-NEXT:    bsfl %edi, %ecx
358; NOBMI-NEXT:    movl $-1, %eax
359; NOBMI-NEXT:    cmovnel %ecx, %eax
360; NOBMI-NEXT:    addl $6, %eax
361; NOBMI-NEXT:    retq
362;
363; BMI-LABEL: cttz_32_ne_select:
364; BMI:       # %bb.0:
365; BMI-NEXT:    tzcntl %edi, %ecx
366; BMI-NEXT:    movl $-1, %eax
367; BMI-NEXT:    cmovael %ecx, %eax
368; BMI-NEXT:    addl $6, %eax
369; BMI-NEXT:    retq
370
371  %cnt = tail call i32 @llvm.cttz.i32(i32 %v, i1 true)
372  %tobool = icmp ne i32 %v, 0
373  %.op = add nuw nsw i32 %cnt, 6
374  %add = select i1 %tobool, i32 %.op, i32 5
375  ret i32 %add
376}
377
378; This matches the pattern emitted for __builtin_ffs
379define i32 @cttz_32_eq_select_ffs(i32 %v) nounwind {
380; NOBMI-LABEL: cttz_32_eq_select_ffs:
381; NOBMI:       # %bb.0:
382; NOBMI-NEXT:    bsfl %edi, %ecx
383; NOBMI-NEXT:    movl $-1, %eax
384; NOBMI-NEXT:    cmovnel %ecx, %eax
385; NOBMI-NEXT:    incl %eax
386; NOBMI-NEXT:    retq
387;
388; BMI-LABEL: cttz_32_eq_select_ffs:
389; BMI:       # %bb.0:
390; BMI-NEXT:    tzcntl %edi, %ecx
391; BMI-NEXT:    movl $-1, %eax
392; BMI-NEXT:    cmovael %ecx, %eax
393; BMI-NEXT:    incl %eax
394; BMI-NEXT:    retq
395
396  %cnt = tail call i32 @llvm.cttz.i32(i32 %v, i1 true)
397  %tobool = icmp eq i32 %v, 0
398  %.op = add nuw nsw i32 %cnt, 1
399  %add = select i1 %tobool, i32 0, i32 %.op
400  ret i32 %add
401}
402
403define i32 @cttz_32_ne_select_ffs(i32 %v) nounwind {
404; NOBMI-LABEL: cttz_32_ne_select_ffs:
405; NOBMI:       # %bb.0:
406; NOBMI-NEXT:    bsfl %edi, %ecx
407; NOBMI-NEXT:    movl $-1, %eax
408; NOBMI-NEXT:    cmovnel %ecx, %eax
409; NOBMI-NEXT:    incl %eax
410; NOBMI-NEXT:    retq
411;
412; BMI-LABEL: cttz_32_ne_select_ffs:
413; BMI:       # %bb.0:
414; BMI-NEXT:    tzcntl %edi, %ecx
415; BMI-NEXT:    movl $-1, %eax
416; BMI-NEXT:    cmovael %ecx, %eax
417; BMI-NEXT:    incl %eax
418; BMI-NEXT:    retq
419
420  %cnt = tail call i32 @llvm.cttz.i32(i32 %v, i1 true)
421  %tobool = icmp ne i32 %v, 0
422  %.op = add nuw nsw i32 %cnt, 1
423  %add = select i1 %tobool, i32 %.op, i32 0
424  ret i32 %add
425}
426
427; This matches the pattern emitted for __builtin_ffs - 1
428define i32 @cttz_32_eq_select_ffs_m1(i32 %v) nounwind {
429; NOBMI-LABEL: cttz_32_eq_select_ffs_m1:
430; NOBMI:       # %bb.0:
431; NOBMI-NEXT:    bsfl %edi, %ecx
432; NOBMI-NEXT:    movl $-1, %eax
433; NOBMI-NEXT:    cmovnel %ecx, %eax
434; NOBMI-NEXT:    retq
435;
436; BMI-LABEL: cttz_32_eq_select_ffs_m1:
437; BMI:       # %bb.0:
438; BMI-NEXT:    tzcntl %edi, %ecx
439; BMI-NEXT:    movl $-1, %eax
440; BMI-NEXT:    cmovael %ecx, %eax
441; BMI-NEXT:    retq
442
443  %cnt = tail call i32 @llvm.cttz.i32(i32 %v, i1 true)
444  %tobool = icmp eq i32 %v, 0
445  %sel = select i1 %tobool, i32 -1, i32 %cnt
446  ret i32 %sel
447}
448
449define i32 @cttz_32_ne_select_ffs_m1(i32 %v) nounwind {
450; NOBMI-LABEL: cttz_32_ne_select_ffs_m1:
451; NOBMI:       # %bb.0:
452; NOBMI-NEXT:    bsfl %edi, %ecx
453; NOBMI-NEXT:    movl $-1, %eax
454; NOBMI-NEXT:    cmovnel %ecx, %eax
455; NOBMI-NEXT:    retq
456;
457; BMI-LABEL: cttz_32_ne_select_ffs_m1:
458; BMI:       # %bb.0:
459; BMI-NEXT:    tzcntl %edi, %ecx
460; BMI-NEXT:    movl $-1, %eax
461; BMI-NEXT:    cmovael %ecx, %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  %sel = select i1 %tobool, i32 %cnt, i32 -1
467  ret i32 %sel
468}
469