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
5 define i32 @select_and1(i32 %x, i32 %y) {
6 ; CHECK-LABEL: select_and1:
8 ; CHECK-NEXT: xorl %eax, %eax
9 ; CHECK-NEXT: cmpl $11, %edi
10 ; CHECK-NEXT: cmovgel %esi, %eax
12 %c = icmp slt i32 %x, 11
13 %s = select i1 %c, i32 0, i32 -1
18 define i32 @select_and2(i32 %x, i32 %y) {
19 ; CHECK-LABEL: select_and2:
21 ; CHECK-NEXT: xorl %eax, %eax
22 ; CHECK-NEXT: cmpl $11, %edi
23 ; CHECK-NEXT: cmovgel %esi, %eax
25 %c = icmp slt i32 %x, 11
26 %s = select i1 %c, i32 0, i32 -1
31 define i32 @select_and3(i32 %x, i32 %y) {
32 ; CHECK-LABEL: select_and3:
34 ; CHECK-NEXT: xorl %eax, %eax
35 ; CHECK-NEXT: cmpl $11, %edi
36 ; CHECK-NEXT: cmovll %esi, %eax
38 %c = icmp slt i32 %x, 11
39 %s = select i1 %c, i32 -1, i32 0
44 define <4 x i32> @select_and_v4(i32 %x, <4 x i32> %y) {
45 ; CHECK-LABEL: select_and_v4:
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
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
61 define i32 @select_or1(i32 %x, i32 %y) {
62 ; CHECK-LABEL: select_or1:
64 ; CHECK-NEXT: cmpl $11, %edi
65 ; CHECK-NEXT: movl $-1, %eax
66 ; CHECK-NEXT: cmovll %esi, %eax
68 %c = icmp slt i32 %x, 11
69 %s = select i1 %c, i32 0, i32 -1
74 define i32 @select_or2(i32 %x, i32 %y) {
75 ; CHECK-LABEL: select_or2:
77 ; CHECK-NEXT: cmpl $11, %edi
78 ; CHECK-NEXT: movl $-1, %eax
79 ; CHECK-NEXT: cmovll %esi, %eax
81 %c = icmp slt i32 %x, 11
82 %s = select i1 %c, i32 0, i32 -1
87 define i32 @select_or3(i32 %x, i32 %y) {
88 ; CHECK-LABEL: select_or3:
90 ; CHECK-NEXT: cmpl $11, %edi
91 ; CHECK-NEXT: movl $-1, %eax
92 ; CHECK-NEXT: cmovgel %esi, %eax
94 %c = icmp slt i32 %x, 11
95 %s = select i1 %c, i32 -1, i32 0
100 define <4 x i32> @select_or_v4(i32 %x, <4 x i32> %y) {
101 ; CHECK-LABEL: select_or_v4:
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:
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
115 define i32 @sel_constants_sub_constant_sel_constants(i1 %cond) {
116 ; CHECK-LABEL: sel_constants_sub_constant_sel_constants:
118 ; CHECK-NEXT: testb $1, %dil
119 ; CHECK-NEXT: movl $9, %ecx
120 ; CHECK-NEXT: movl $2, %eax
121 ; CHECK-NEXT: cmovnel %ecx, %eax
123 %sel = select i1 %cond, i32 -4, i32 3
124 %bo = sub i32 5, %sel
128 define i32 @sdiv_constant_sel_constants(i1 %cond) {
129 ; CHECK-LABEL: sdiv_constant_sel_constants:
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
136 %sel = select i1 %cond, i32 121, i32 23
137 %bo = sdiv i32 120, %sel
141 define i32 @udiv_constant_sel_constants(i1 %cond) {
142 ; CHECK-LABEL: udiv_constant_sel_constants:
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
149 %sel = select i1 %cond, i32 -4, i32 23
150 %bo = udiv i32 120, %sel
154 define i32 @srem_constant_sel_constants(i1 %cond) {
155 ; CHECK-LABEL: srem_constant_sel_constants:
157 ; CHECK-NEXT: testb $1, %dil
158 ; CHECK-NEXT: movl $120, %ecx
159 ; CHECK-NEXT: movl $5, %eax
160 ; CHECK-NEXT: cmovnel %ecx, %eax
162 %sel = select i1 %cond, i32 121, i32 23
163 %bo = srem i32 120, %sel
167 define i32 @urem_constant_sel_constants(i1 %cond) {
168 ; CHECK-LABEL: urem_constant_sel_constants:
170 ; CHECK-NEXT: testb $1, %dil
171 ; CHECK-NEXT: movl $120, %ecx
172 ; CHECK-NEXT: movl $5, %eax
173 ; CHECK-NEXT: cmovnel %ecx, %eax
175 %sel = select i1 %cond, i32 -4, i32 23
176 %bo = urem i32 120, %sel
180 define i32 @sel_constants_shl_constant(i1 %cond) {
181 ; CHECK-LABEL: sel_constants_shl_constant:
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
189 %sel = select i1 %cond, i32 2, i32 3
190 %bo = shl i32 %sel, 8
194 define i32 @shl_constant_sel_constants(i1 %cond) {
195 ; CHECK-LABEL: shl_constant_sel_constants:
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
202 %sel = select i1 %cond, i32 2, i32 3
203 %bo = shl i32 1, %sel
207 define i32 @lshr_constant_sel_constants(i1 %cond) {
208 ; CHECK-LABEL: lshr_constant_sel_constants:
210 ; CHECK-NEXT: # kill: def $edi killed $edi def $rdi
211 ; CHECK-NEXT: andl $1, %edi
212 ; CHECK-NEXT: leal 8(,%rdi,8), %eax
214 %sel = select i1 %cond, i32 2, i32 3
215 %bo = lshr i32 64, %sel
219 define i32 @ashr_constant_sel_constants(i1 %cond) {
220 ; CHECK-LABEL: ashr_constant_sel_constants:
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
227 %sel = select i1 %cond, i32 2, i32 3
228 %bo = ashr i32 128, %sel
232 define double @fsub_constant_sel_constants(i1 %cond) {
233 ; CHECK-LABEL: fsub_constant_sel_constants:
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
240 ; CHECK-NEXT: .LBB17_1:
241 ; CHECK-NEXT: movsd {{.*#+}} xmm0 = mem[0],zero
243 %sel = select i1 %cond, double -4.0, double 23.3
244 %bo = fsub double 5.1, %sel
248 define double @fdiv_constant_sel_constants(i1 %cond) {
249 ; CHECK-LABEL: fdiv_constant_sel_constants:
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
256 ; CHECK-NEXT: .LBB18_1:
257 ; CHECK-NEXT: movsd {{.*#+}} xmm0 = mem[0],zero
259 %sel = select i1 %cond, double -4.0, double 23.3
260 %bo = fdiv double 5.1, %sel
264 define double @frem_constant_sel_constants(i1 %cond) {
265 ; CHECK-LABEL: frem_constant_sel_constants:
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
272 ; CHECK-NEXT: .LBB19_1:
273 ; CHECK-NEXT: movsd {{.*#+}} xmm0 = mem[0],zero
275 %sel = select i1 %cond, double -4.0, double 23.3
276 %bo = frem double 5.1, %sel
280 declare i64 @llvm.cttz.i64(i64, i1)
281 define i64 @cttz_64_eq_select(i64 %v) nounwind {
282 ; NOBMI-LABEL: cttz_64_eq_select:
284 ; NOBMI-NEXT: bsfq %rdi, %rcx
285 ; NOBMI-NEXT: movq $-1, %rax
286 ; NOBMI-NEXT: cmovneq %rcx, %rax
287 ; NOBMI-NEXT: addq $6, %rax
290 ; BMI-LABEL: cttz_64_eq_select:
292 ; BMI-NEXT: tzcntq %rdi, %rcx
293 ; BMI-NEXT: movq $-1, %rax
294 ; BMI-NEXT: cmovaeq %rcx, %rax
295 ; BMI-NEXT: addq $6, %rax
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
305 define i64 @cttz_64_ne_select(i64 %v) nounwind {
306 ; NOBMI-LABEL: cttz_64_ne_select:
308 ; NOBMI-NEXT: bsfq %rdi, %rcx
309 ; NOBMI-NEXT: movq $-1, %rax
310 ; NOBMI-NEXT: cmovneq %rcx, %rax
311 ; NOBMI-NEXT: addq $6, %rax
314 ; BMI-LABEL: cttz_64_ne_select:
316 ; BMI-NEXT: tzcntq %rdi, %rcx
317 ; BMI-NEXT: movq $-1, %rax
318 ; BMI-NEXT: cmovaeq %rcx, %rax
319 ; BMI-NEXT: addq $6, %rax
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
329 declare i32 @llvm.cttz.i32(i32, i1)
330 define i32 @cttz_32_eq_select(i32 %v) nounwind {
331 ; NOBMI-LABEL: cttz_32_eq_select:
333 ; NOBMI-NEXT: bsfl %edi, %ecx
334 ; NOBMI-NEXT: movl $-1, %eax
335 ; NOBMI-NEXT: cmovnel %ecx, %eax
336 ; NOBMI-NEXT: addl $6, %eax
339 ; BMI-LABEL: cttz_32_eq_select:
341 ; BMI-NEXT: tzcntl %edi, %ecx
342 ; BMI-NEXT: movl $-1, %eax
343 ; BMI-NEXT: cmovael %ecx, %eax
344 ; BMI-NEXT: addl $6, %eax
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
354 define i32 @cttz_32_ne_select(i32 %v) nounwind {
355 ; NOBMI-LABEL: cttz_32_ne_select:
357 ; NOBMI-NEXT: bsfl %edi, %ecx
358 ; NOBMI-NEXT: movl $-1, %eax
359 ; NOBMI-NEXT: cmovnel %ecx, %eax
360 ; NOBMI-NEXT: addl $6, %eax
363 ; BMI-LABEL: cttz_32_ne_select:
365 ; BMI-NEXT: tzcntl %edi, %ecx
366 ; BMI-NEXT: movl $-1, %eax
367 ; BMI-NEXT: cmovael %ecx, %eax
368 ; BMI-NEXT: addl $6, %eax
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
378 ; This matches the pattern emitted for __builtin_ffs
379 define i32 @cttz_32_eq_select_ffs(i32 %v) nounwind {
380 ; NOBMI-LABEL: cttz_32_eq_select_ffs:
382 ; NOBMI-NEXT: bsfl %edi, %ecx
383 ; NOBMI-NEXT: movl $-1, %eax
384 ; NOBMI-NEXT: cmovnel %ecx, %eax
385 ; NOBMI-NEXT: incl %eax
388 ; BMI-LABEL: cttz_32_eq_select_ffs:
390 ; BMI-NEXT: tzcntl %edi, %ecx
391 ; BMI-NEXT: movl $-1, %eax
392 ; BMI-NEXT: cmovael %ecx, %eax
393 ; BMI-NEXT: incl %eax
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
403 define i32 @cttz_32_ne_select_ffs(i32 %v) nounwind {
404 ; NOBMI-LABEL: cttz_32_ne_select_ffs:
406 ; NOBMI-NEXT: bsfl %edi, %ecx
407 ; NOBMI-NEXT: movl $-1, %eax
408 ; NOBMI-NEXT: cmovnel %ecx, %eax
409 ; NOBMI-NEXT: incl %eax
412 ; BMI-LABEL: cttz_32_ne_select_ffs:
414 ; BMI-NEXT: tzcntl %edi, %ecx
415 ; BMI-NEXT: movl $-1, %eax
416 ; BMI-NEXT: cmovael %ecx, %eax
417 ; BMI-NEXT: incl %eax
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
427 ; This matches the pattern emitted for __builtin_ffs - 1
428 define i32 @cttz_32_eq_select_ffs_m1(i32 %v) nounwind {
429 ; NOBMI-LABEL: cttz_32_eq_select_ffs_m1:
431 ; NOBMI-NEXT: bsfl %edi, %ecx
432 ; NOBMI-NEXT: movl $-1, %eax
433 ; NOBMI-NEXT: cmovnel %ecx, %eax
436 ; BMI-LABEL: cttz_32_eq_select_ffs_m1:
438 ; BMI-NEXT: tzcntl %edi, %ecx
439 ; BMI-NEXT: movl $-1, %eax
440 ; BMI-NEXT: cmovael %ecx, %eax
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
449 define i32 @cttz_32_ne_select_ffs_m1(i32 %v) nounwind {
450 ; NOBMI-LABEL: cttz_32_ne_select_ffs_m1:
452 ; NOBMI-NEXT: bsfl %edi, %ecx
453 ; NOBMI-NEXT: movl $-1, %eax
454 ; NOBMI-NEXT: cmovnel %ecx, %eax
457 ; BMI-LABEL: cttz_32_ne_select_ffs_m1:
459 ; BMI-NEXT: tzcntl %edi, %ecx
460 ; BMI-NEXT: movl $-1, %eax
461 ; BMI-NEXT: cmovael %ecx, %eax
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