diff --git a/llvm/test/CodeGen/X86/known-pow2.ll b/llvm/test/CodeGen/X86/known-pow2.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/X86/known-pow2.ll @@ -0,0 +1,867 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc < %s -mtriple=x86_64-unknown-unknown | FileCheck %s --check-prefix=CHECK + +; Use common transform of: +; (X & Y) == Y -> (X & Y) != 0 iff Y is non-zero power of 2 to test. +; (X & Y) != Y -> (X & Y) == 0 iff Y is non-zero power of 2 to test. + +declare i32 @llvm.umin.i32(i32, i32) +declare i32 @llvm.umax.i32(i32, i32) +declare i32 @llvm.smin.i32(i32, i32) +declare i32 @llvm.smax.i32(i32, i32) +declare i32 @llvm.fshl.i32(i32, i32, i32) +declare i32 @llvm.fshr.i32(i32, i32, i32) + +define <4 x i32> @pow2_non_splat_vec(<4 x i32> %x) { +; CHECK-LABEL: pow2_non_splat_vec: +; CHECK: # %bb.0: +; CHECK-NEXT: andps {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0 +; CHECK-NEXT: retq + %r = urem <4 x i32> %x, + ret <4 x i32> %r +} + +define <4 x i32> @pow2_non_splat_vec_fail0(<4 x i32> %x) { +; CHECK-LABEL: pow2_non_splat_vec_fail0: +; CHECK: # %bb.0: +; CHECK-NEXT: movdqa {{.*#+}} xmm1 = [954437177,1073741824,268435456,67108864] +; CHECK-NEXT: pmuludq %xmm0, %xmm1 +; CHECK-NEXT: pshufd {{.*#+}} xmm1 = xmm1[1,3,2,3] +; CHECK-NEXT: pshufd {{.*#+}} xmm2 = xmm0[1,1,3,3] +; CHECK-NEXT: pmuludq {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm2 +; CHECK-NEXT: pshufd {{.*#+}} xmm3 = xmm2[1,3,2,3] +; CHECK-NEXT: punpckldq {{.*#+}} xmm1 = xmm1[0],xmm3[0],xmm1[1],xmm3[1] +; CHECK-NEXT: movdqa %xmm1, %xmm3 +; CHECK-NEXT: psrld $1, %xmm3 +; CHECK-NEXT: shufps {{.*#+}} xmm3 = xmm3[0,1],xmm1[2,3] +; CHECK-NEXT: pmuludq {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm3 +; CHECK-NEXT: pshufd {{.*#+}} xmm1 = xmm3[0,2,2,3] +; CHECK-NEXT: pshufd {{.*#+}} xmm2 = xmm2[1,1,3,3] +; CHECK-NEXT: pmuludq {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm2 +; CHECK-NEXT: pshufd {{.*#+}} xmm2 = xmm2[0,2,2,3] +; CHECK-NEXT: punpckldq {{.*#+}} xmm1 = xmm1[0],xmm2[0],xmm1[1],xmm2[1] +; CHECK-NEXT: psubd %xmm1, %xmm0 +; CHECK-NEXT: retq + %r = urem <4 x i32> %x, + ret <4 x i32> %r +} + +define i1 @pow2_shl(i32 %x, i32 %y) { +; CHECK-LABEL: pow2_shl: +; CHECK: # %bb.0: +; CHECK-NEXT: movl %esi, %ecx +; CHECK-NEXT: notl %edi +; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx +; CHECK-NEXT: shrl %cl, %edi +; CHECK-NEXT: testb $4, %dil +; CHECK-NEXT: sete %al +; CHECK-NEXT: retq + %d = shl nuw nsw i32 4, %y + %and = and i32 %x, %d + %r = icmp eq i32 %and, %d + ret i1 %r +} + +define i1 @pow2_shl_fail0(i32 %x, i32 %y) { +; CHECK-LABEL: pow2_shl_fail0: +; CHECK: # %bb.0: +; CHECK-NEXT: movl %esi, %ecx +; CHECK-NEXT: notl %edi +; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx +; CHECK-NEXT: shrl %cl, %edi +; CHECK-NEXT: testb $3, %dil +; CHECK-NEXT: sete %al +; CHECK-NEXT: retq + %d = shl i32 3, %y + %and = and i32 %x, %d + %r = icmp eq i32 %and, %d + ret i1 %r +} + +define i1 @pow2_shl_fail1(i32 %x, i32 %y) { +; CHECK-LABEL: pow2_shl_fail1: +; CHECK: # %bb.0: +; CHECK-NEXT: movl %esi, %ecx +; CHECK-NEXT: notl %edi +; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx +; CHECK-NEXT: shrl %cl, %edi +; CHECK-NEXT: testb $4, %dil +; CHECK-NEXT: sete %al +; CHECK-NEXT: retq + %d = shl i32 4, %y + %and = and i32 %x, %d + %r = icmp eq i32 %and, %d + ret i1 %r +} + +define i1 @pow2_srl(i32 %x, i32 %y) { +; CHECK-LABEL: pow2_srl: +; CHECK: # %bb.0: +; CHECK-NEXT: movl %esi, %ecx +; CHECK-NEXT: andb $7, %cl +; CHECK-NEXT: notl %edi +; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx +; CHECK-NEXT: shll %cl, %edi +; CHECK-NEXT: testl $1048576, %edi # imm = 0x100000 +; CHECK-NEXT: sete %al +; CHECK-NEXT: retq + %yy = and i32 %y, 7 + %d = lshr i32 1048576, %yy + %and = and i32 %x, %d + %r = icmp eq i32 %and, %d + ret i1 %r +} + +define i1 @pow2_srl_fail0(i32 %x, i32 %y) { +; CHECK-LABEL: pow2_srl_fail0: +; CHECK: # %bb.0: +; CHECK-NEXT: movl %esi, %ecx +; CHECK-NEXT: andb $30, %cl +; CHECK-NEXT: notl %edi +; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx +; CHECK-NEXT: shll %cl, %edi +; CHECK-NEXT: testl $1048576, %edi # imm = 0x100000 +; CHECK-NEXT: sete %al +; CHECK-NEXT: retq + %yy = and i32 %y, 30 + %d = lshr i32 1048576, %yy + %and = and i32 %x, %d + %r = icmp eq i32 %and, %d + ret i1 %r +} + +define i1 @pow2_srl_fail1(i32 %x, i32 %y) { +; CHECK-LABEL: pow2_srl_fail1: +; CHECK: # %bb.0: +; CHECK-NEXT: movl %esi, %ecx +; CHECK-NEXT: andb $7, %cl +; CHECK-NEXT: notl %edi +; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx +; CHECK-NEXT: shll %cl, %edi +; CHECK-NEXT: testl $1048577, %edi # imm = 0x100001 +; CHECK-NEXT: sete %al +; CHECK-NEXT: retq + %yy = and i32 %y, 7 + %d = lshr i32 1048577, %yy + %and = and i32 %x, %d + %r = icmp eq i32 %and, %d + ret i1 %r +} + +define i1 @pow2_rotl(i32 %x, i32 %y) { +; CHECK-LABEL: pow2_rotl: +; CHECK: # %bb.0: +; CHECK-NEXT: movl %esi, %ecx +; CHECK-NEXT: movl $1048576, %eax # imm = 0x100000 +; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx +; CHECK-NEXT: roll %cl, %eax +; CHECK-NEXT: notl %edi +; CHECK-NEXT: testl %edi, %eax +; CHECK-NEXT: sete %al +; CHECK-NEXT: retq + %d = call i32 @llvm.fshl.i32(i32 1048576, i32 1048576, i32 %y) + %and = and i32 %x, %d + %r = icmp eq i32 %and, %d + ret i1 %r +} + +define i1 @pow2_rotl_fail0(i32 %x, i32 %y) { +; CHECK-LABEL: pow2_rotl_fail0: +; CHECK: # %bb.0: +; CHECK-NEXT: movl %esi, %ecx +; CHECK-NEXT: movl $1048576, %eax # imm = 0x100000 +; CHECK-NEXT: movl $512, %edx # imm = 0x200 +; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx +; CHECK-NEXT: shldl %cl, %eax, %edx +; CHECK-NEXT: notl %edi +; CHECK-NEXT: testl %edi, %edx +; CHECK-NEXT: sete %al +; CHECK-NEXT: retq + %d = call i32 @llvm.fshl.i32(i32 512, i32 1048576, i32 %y) + %and = and i32 %x, %d + %r = icmp eq i32 %and, %d + ret i1 %r +} + +define i1 @pow2_rotl_fail1(i32 %x, i32 %y) { +; CHECK-LABEL: pow2_rotl_fail1: +; CHECK: # %bb.0: +; CHECK-NEXT: movl %esi, %ecx +; CHECK-NEXT: movl $511, %eax # imm = 0x1FF +; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx +; CHECK-NEXT: roll %cl, %eax +; CHECK-NEXT: notl %edi +; CHECK-NEXT: testl %edi, %eax +; CHECK-NEXT: sete %al +; CHECK-NEXT: retq + %d = call i32 @llvm.fshl.i32(i32 511, i32 511, i32 %y) + %and = and i32 %x, %d + %r = icmp eq i32 %and, %d + ret i1 %r +} + +define i1 @pow2_rotr(i32 %x, i32 %y) { +; CHECK-LABEL: pow2_rotr: +; CHECK: # %bb.0: +; CHECK-NEXT: movl %esi, %ecx +; CHECK-NEXT: movl $1048576, %eax # imm = 0x100000 +; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx +; CHECK-NEXT: rorl %cl, %eax +; CHECK-NEXT: notl %edi +; CHECK-NEXT: testl %edi, %eax +; CHECK-NEXT: sete %al +; CHECK-NEXT: retq + %d = call i32 @llvm.fshr.i32(i32 1048576, i32 1048576, i32 %y) + %and = and i32 %x, %d + %r = icmp eq i32 %and, %d + ret i1 %r +} + +define i1 @pow2_rotr_fail0(i32 %x, i32 %y) { +; CHECK-LABEL: pow2_rotr_fail0: +; CHECK: # %bb.0: +; CHECK-NEXT: movl %esi, %ecx +; CHECK-NEXT: movl $512, %eax # imm = 0x200 +; CHECK-NEXT: movl $1048576, %edx # imm = 0x100000 +; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx +; CHECK-NEXT: shrdl %cl, %eax, %edx +; CHECK-NEXT: notl %edi +; CHECK-NEXT: testl %edi, %edx +; CHECK-NEXT: sete %al +; CHECK-NEXT: retq + %d = call i32 @llvm.fshr.i32(i32 512, i32 1048576, i32 %y) + %and = and i32 %x, %d + %r = icmp eq i32 %and, %d + ret i1 %r +} + +define i1 @pow2_rotr_fail1(i32 %x, i32 %y) { +; CHECK-LABEL: pow2_rotr_fail1: +; CHECK: # %bb.0: +; CHECK-NEXT: movl %esi, %ecx +; CHECK-NEXT: movl $511, %eax # imm = 0x1FF +; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx +; CHECK-NEXT: rorl %cl, %eax +; CHECK-NEXT: notl %edi +; CHECK-NEXT: testl %edi, %eax +; CHECK-NEXT: sete %al +; CHECK-NEXT: retq + %d = call i32 @llvm.fshr.i32(i32 511, i32 511, i32 %y) + %and = and i32 %x, %d + %r = icmp eq i32 %and, %d + ret i1 %r +} + +define i1 @pow2_umin(i32 %x, i32 %y) { +; CHECK-LABEL: pow2_umin: +; CHECK: # %bb.0: +; CHECK-NEXT: movl %esi, %ecx +; CHECK-NEXT: movl $1, %eax +; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx +; CHECK-NEXT: shll %cl, %eax +; CHECK-NEXT: cmpl $262144, %eax # imm = 0x40000 +; CHECK-NEXT: movl $262144, %ecx # imm = 0x40000 +; CHECK-NEXT: cmovbl %eax, %ecx +; CHECK-NEXT: notl %edi +; CHECK-NEXT: testl %edi, %ecx +; CHECK-NEXT: sete %al +; CHECK-NEXT: retq + %yy = shl i32 1, %y + %d = call i32 @llvm.umin.i32(i32 %yy, i32 262144) + %and = and i32 %x, %d + %r = icmp eq i32 %and, %d + ret i1 %r +} + +define i1 @pow2_umin_fail0(i32 %x, i32 %y) { +; CHECK-LABEL: pow2_umin_fail0: +; CHECK: # %bb.0: +; CHECK-NEXT: movl %esi, %ecx +; CHECK-NEXT: movl $4, %eax +; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx +; CHECK-NEXT: shll %cl, %eax +; CHECK-NEXT: cmpl $262144, %eax # imm = 0x40000 +; CHECK-NEXT: movl $262144, %ecx # imm = 0x40000 +; CHECK-NEXT: cmovbl %eax, %ecx +; CHECK-NEXT: notl %edi +; CHECK-NEXT: testl %edi, %ecx +; CHECK-NEXT: sete %al +; CHECK-NEXT: retq + %yy = shl i32 4, %y + %d = call i32 @llvm.umin.i32(i32 %yy, i32 262144) + %and = and i32 %x, %d + %r = icmp eq i32 %and, %d + ret i1 %r +} + +define i1 @pow2_umin_fail1(i32 %x, i32 %y) { +; CHECK-LABEL: pow2_umin_fail1: +; CHECK: # %bb.0: +; CHECK-NEXT: movl %esi, %ecx +; CHECK-NEXT: movl $1, %eax +; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx +; CHECK-NEXT: shll %cl, %eax +; CHECK-NEXT: cmpl $12345, %eax # imm = 0x3039 +; CHECK-NEXT: movl $12345, %ecx # imm = 0x3039 +; CHECK-NEXT: cmovbl %eax, %ecx +; CHECK-NEXT: notl %edi +; CHECK-NEXT: testl %edi, %ecx +; CHECK-NEXT: sete %al +; CHECK-NEXT: retq + %yy = shl i32 1, %y + %d = call i32 @llvm.umin.i32(i32 %yy, i32 12345) + %and = and i32 %x, %d + %r = icmp eq i32 %and, %d + ret i1 %r +} + +define i1 @pow2_umax(i32 %x, i32 %y, i32 %z) { +; CHECK-LABEL: pow2_umax: +; CHECK: # %bb.0: +; CHECK-NEXT: movl %esi, %ecx +; CHECK-NEXT: movl $1, %eax +; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx +; CHECK-NEXT: shll %cl, %eax +; CHECK-NEXT: movl $-2147483648, %esi # imm = 0x80000000 +; CHECK-NEXT: movl %edx, %ecx +; CHECK-NEXT: shrl %cl, %esi +; CHECK-NEXT: cmpl %esi, %eax +; CHECK-NEXT: cmoval %eax, %esi +; CHECK-NEXT: notl %edi +; CHECK-NEXT: testl %edi, %esi +; CHECK-NEXT: sete %al +; CHECK-NEXT: retq + %yy = shl i32 1, %y + %zz = lshr i32 2147483648, %z + %d = call i32 @llvm.umax.i32(i32 %yy, i32 %zz) + %and = and i32 %x, %d + %r = icmp eq i32 %and, %d + ret i1 %r +} + +define i1 @pow2_umax_fail0(i32 %x, i32 %y, i32 %z) { +; CHECK-LABEL: pow2_umax_fail0: +; CHECK: # %bb.0: +; CHECK-NEXT: movl %esi, %ecx +; CHECK-NEXT: movl $1, %eax +; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx +; CHECK-NEXT: shll %cl, %eax +; CHECK-NEXT: movl $1073741824, %esi # imm = 0x40000000 +; CHECK-NEXT: movl %edx, %ecx +; CHECK-NEXT: shrl %cl, %esi +; CHECK-NEXT: cmpl %esi, %eax +; CHECK-NEXT: cmoval %eax, %esi +; CHECK-NEXT: notl %edi +; CHECK-NEXT: testl %edi, %esi +; CHECK-NEXT: sete %al +; CHECK-NEXT: retq + %yy = shl i32 1, %y + %zz = lshr i32 1073741824, %z + %d = call i32 @llvm.umax.i32(i32 %yy, i32 %zz) + %and = and i32 %x, %d + %r = icmp eq i32 %and, %d + ret i1 %r +} + +define i1 @pow2_umax_fail1(i32 %x, i32 %y, i32 %z) { +; CHECK-LABEL: pow2_umax_fail1: +; CHECK: # %bb.0: +; CHECK-NEXT: movl %esi, %ecx +; CHECK-NEXT: movl $4, %eax +; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx +; CHECK-NEXT: shll %cl, %eax +; CHECK-NEXT: movl $-2147483648, %esi # imm = 0x80000000 +; CHECK-NEXT: movl %edx, %ecx +; CHECK-NEXT: shrl %cl, %esi +; CHECK-NEXT: cmpl %esi, %eax +; CHECK-NEXT: cmoval %eax, %esi +; CHECK-NEXT: notl %edi +; CHECK-NEXT: testl %edi, %esi +; CHECK-NEXT: sete %al +; CHECK-NEXT: retq + %yy = shl i32 4, %y + %zz = lshr i32 2147483648, %z + %d = call i32 @llvm.umax.i32(i32 %yy, i32 %zz) + %and = and i32 %x, %d + %r = icmp eq i32 %and, %d + ret i1 %r +} + +define i1 @pow2_smin(i32 %x, i32 %y) { +; CHECK-LABEL: pow2_smin: +; CHECK: # %bb.0: +; CHECK-NEXT: movl %esi, %ecx +; CHECK-NEXT: movl $1, %eax +; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx +; CHECK-NEXT: shll %cl, %eax +; CHECK-NEXT: cmpl $262144, %eax # imm = 0x40000 +; CHECK-NEXT: movl $262144, %ecx # imm = 0x40000 +; CHECK-NEXT: cmovll %eax, %ecx +; CHECK-NEXT: notl %edi +; CHECK-NEXT: testl %edi, %ecx +; CHECK-NEXT: sete %al +; CHECK-NEXT: retq + %yy = shl i32 1, %y + %d = call i32 @llvm.smin.i32(i32 %yy, i32 262144) + %and = and i32 %x, %d + %r = icmp eq i32 %and, %d + ret i1 %r +} + +define i1 @pow2_smin_fail0(i32 %x, i32 %y) { +; CHECK-LABEL: pow2_smin_fail0: +; CHECK: # %bb.0: +; CHECK-NEXT: movl %esi, %ecx +; CHECK-NEXT: movl $4, %eax +; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx +; CHECK-NEXT: shll %cl, %eax +; CHECK-NEXT: cmpl $262144, %eax # imm = 0x40000 +; CHECK-NEXT: movl $262144, %ecx # imm = 0x40000 +; CHECK-NEXT: cmovll %eax, %ecx +; CHECK-NEXT: notl %edi +; CHECK-NEXT: testl %edi, %ecx +; CHECK-NEXT: sete %al +; CHECK-NEXT: retq + %yy = shl i32 4, %y + %d = call i32 @llvm.smin.i32(i32 %yy, i32 262144) + %and = and i32 %x, %d + %r = icmp eq i32 %and, %d + ret i1 %r +} + +define i1 @pow2_smin_fail1(i32 %x, i32 %y) { +; CHECK-LABEL: pow2_smin_fail1: +; CHECK: # %bb.0: +; CHECK-NEXT: movl %esi, %ecx +; CHECK-NEXT: movl $1, %eax +; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx +; CHECK-NEXT: shll %cl, %eax +; CHECK-NEXT: cmpl $12345, %eax # imm = 0x3039 +; CHECK-NEXT: movl $12345, %ecx # imm = 0x3039 +; CHECK-NEXT: cmovll %eax, %ecx +; CHECK-NEXT: notl %edi +; CHECK-NEXT: testl %edi, %ecx +; CHECK-NEXT: sete %al +; CHECK-NEXT: retq + %yy = shl i32 1, %y + %d = call i32 @llvm.smin.i32(i32 %yy, i32 12345) + %and = and i32 %x, %d + %r = icmp eq i32 %and, %d + ret i1 %r +} + +define i1 @pow2_smax(i32 %x, i32 %y, i32 %z) { +; CHECK-LABEL: pow2_smax: +; CHECK: # %bb.0: +; CHECK-NEXT: movl %esi, %ecx +; CHECK-NEXT: movl $1, %eax +; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx +; CHECK-NEXT: shll %cl, %eax +; CHECK-NEXT: movl $-2147483648, %esi # imm = 0x80000000 +; CHECK-NEXT: movl %edx, %ecx +; CHECK-NEXT: shrl %cl, %esi +; CHECK-NEXT: cmpl %esi, %eax +; CHECK-NEXT: cmovgl %eax, %esi +; CHECK-NEXT: notl %edi +; CHECK-NEXT: testl %edi, %esi +; CHECK-NEXT: sete %al +; CHECK-NEXT: retq + %yy = shl i32 1, %y + %zz = lshr i32 2147483648, %z + %d = call i32 @llvm.smax.i32(i32 %yy, i32 %zz) + %and = and i32 %x, %d + %r = icmp eq i32 %and, %d + ret i1 %r +} + +define i1 @pow2_smax_fail0(i32 %x, i32 %y, i32 %z) { +; CHECK-LABEL: pow2_smax_fail0: +; CHECK: # %bb.0: +; CHECK-NEXT: movl %esi, %ecx +; CHECK-NEXT: movl $1, %eax +; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx +; CHECK-NEXT: shll %cl, %eax +; CHECK-NEXT: movl $1073741824, %esi # imm = 0x40000000 +; CHECK-NEXT: movl %edx, %ecx +; CHECK-NEXT: shrl %cl, %esi +; CHECK-NEXT: cmpl %esi, %eax +; CHECK-NEXT: cmovgl %eax, %esi +; CHECK-NEXT: notl %edi +; CHECK-NEXT: testl %edi, %esi +; CHECK-NEXT: sete %al +; CHECK-NEXT: retq + %yy = shl i32 1, %y + %zz = lshr i32 1073741824, %z + %d = call i32 @llvm.smax.i32(i32 %yy, i32 %zz) + %and = and i32 %x, %d + %r = icmp eq i32 %and, %d + ret i1 %r +} + +define i1 @pow2_smax_fail1(i32 %x, i32 %y, i32 %z) { +; CHECK-LABEL: pow2_smax_fail1: +; CHECK: # %bb.0: +; CHECK-NEXT: movl %esi, %ecx +; CHECK-NEXT: movl $4, %eax +; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx +; CHECK-NEXT: shll %cl, %eax +; CHECK-NEXT: movl $-2147483648, %esi # imm = 0x80000000 +; CHECK-NEXT: movl %edx, %ecx +; CHECK-NEXT: shrl %cl, %esi +; CHECK-NEXT: cmpl %esi, %eax +; CHECK-NEXT: cmovgl %eax, %esi +; CHECK-NEXT: notl %edi +; CHECK-NEXT: testl %edi, %esi +; CHECK-NEXT: sete %al +; CHECK-NEXT: retq + %yy = shl i32 4, %y + %zz = lshr i32 2147483648, %z + %d = call i32 @llvm.smax.i32(i32 %yy, i32 %zz) + %and = and i32 %x, %d + %r = icmp eq i32 %and, %d + ret i1 %r +} + +define i1 @pow2_select(i1 %c, i32 %x, i32 %y, i32 %z) { +; CHECK-LABEL: pow2_select: +; CHECK: # %bb.0: +; CHECK-NEXT: movl %ecx, %eax +; CHECK-NEXT: movl %edx, %ecx +; CHECK-NEXT: movl $1, %edx +; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx +; CHECK-NEXT: shll %cl, %edx +; CHECK-NEXT: movl $-2147483648, %r8d # imm = 0x80000000 +; CHECK-NEXT: movl %eax, %ecx +; CHECK-NEXT: shrl %cl, %r8d +; CHECK-NEXT: testb $1, %dil +; CHECK-NEXT: cmovnel %edx, %r8d +; CHECK-NEXT: notl %esi +; CHECK-NEXT: testl %esi, %r8d +; CHECK-NEXT: sete %al +; CHECK-NEXT: retq + %yy = shl i32 1, %y + %zz = lshr i32 2147483648, %z + %d = select i1 %c, i32 %yy, i32 %zz + %and = and i32 %x, %d + %r = icmp eq i32 %and, %d + ret i1 %r +} + +define i1 @pow2_select_fail0(i1 %c, i32 %x, i32 %y, i32 %z) { +; CHECK-LABEL: pow2_select_fail0: +; CHECK: # %bb.0: +; CHECK-NEXT: movl %ecx, %eax +; CHECK-NEXT: movl %edx, %ecx +; CHECK-NEXT: movl $1, %edx +; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx +; CHECK-NEXT: shll %cl, %edx +; CHECK-NEXT: movl $1073741824, %r8d # imm = 0x40000000 +; CHECK-NEXT: movl %eax, %ecx +; CHECK-NEXT: shrl %cl, %r8d +; CHECK-NEXT: testb $1, %dil +; CHECK-NEXT: cmovnel %edx, %r8d +; CHECK-NEXT: notl %esi +; CHECK-NEXT: testl %esi, %r8d +; CHECK-NEXT: sete %al +; CHECK-NEXT: retq + %yy = shl i32 1, %y + %zz = lshr i32 1073741824, %z + %d = select i1 %c, i32 %yy, i32 %zz + %and = and i32 %x, %d + %r = icmp eq i32 %and, %d + ret i1 %r +} + +define i1 @pow2_select_fail2(i1 %c, i32 %x, i32 %y, i32 %z) { +; CHECK-LABEL: pow2_select_fail2: +; CHECK: # %bb.0: +; CHECK-NEXT: movl %ecx, %eax +; CHECK-NEXT: movl %edx, %ecx +; CHECK-NEXT: movl $4, %edx +; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx +; CHECK-NEXT: shll %cl, %edx +; CHECK-NEXT: movl $-2147483648, %r8d # imm = 0x80000000 +; CHECK-NEXT: movl %eax, %ecx +; CHECK-NEXT: shrl %cl, %r8d +; CHECK-NEXT: testb $1, %dil +; CHECK-NEXT: cmovnel %edx, %r8d +; CHECK-NEXT: notl %esi +; CHECK-NEXT: testl %esi, %r8d +; CHECK-NEXT: sete %al +; CHECK-NEXT: retq + %yy = shl i32 4, %y + %zz = lshr i32 2147483648, %z + %d = select i1 %c, i32 %yy, i32 %zz + %and = and i32 %x, %d + %r = icmp eq i32 %and, %d + ret i1 %r +} + +define <4 x i1> @pow2_vselect_eq(<4 x i1> %c, <4 x i32> %x, <4 x i32> %y, <4 x i32> %z) { +; CHECK-LABEL: pow2_vselect_eq: +; CHECK: # %bb.0: +; CHECK-NEXT: pslld $31, %xmm0 +; CHECK-NEXT: psrad $31, %xmm0 +; CHECK-NEXT: pslld $23, %xmm2 +; CHECK-NEXT: paddd {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm2 +; CHECK-NEXT: cvttps2dq %xmm2, %xmm2 +; CHECK-NEXT: pshuflw {{.*#+}} xmm4 = xmm3[2,3,3,3,4,5,6,7] +; CHECK-NEXT: movdqa {{.*#+}} xmm5 = [2147483648,2147483648,2147483648,2147483648] +; CHECK-NEXT: movdqa %xmm5, %xmm6 +; CHECK-NEXT: psrld %xmm4, %xmm6 +; CHECK-NEXT: pshuflw {{.*#+}} xmm4 = xmm3[0,1,1,1,4,5,6,7] +; CHECK-NEXT: movdqa %xmm5, %xmm7 +; CHECK-NEXT: psrld %xmm4, %xmm7 +; CHECK-NEXT: punpcklqdq {{.*#+}} xmm7 = xmm7[0],xmm6[0] +; CHECK-NEXT: pshufd {{.*#+}} xmm3 = xmm3[2,3,2,3] +; CHECK-NEXT: pshuflw {{.*#+}} xmm4 = xmm3[2,3,3,3,4,5,6,7] +; CHECK-NEXT: movdqa %xmm5, %xmm6 +; CHECK-NEXT: psrld %xmm4, %xmm6 +; CHECK-NEXT: pshuflw {{.*#+}} xmm3 = xmm3[0,1,1,1,4,5,6,7] +; CHECK-NEXT: psrld %xmm3, %xmm5 +; CHECK-NEXT: punpckhqdq {{.*#+}} xmm5 = xmm5[1],xmm6[1] +; CHECK-NEXT: shufps {{.*#+}} xmm7 = xmm7[0,3],xmm5[0,3] +; CHECK-NEXT: pand %xmm0, %xmm2 +; CHECK-NEXT: pandn %xmm7, %xmm0 +; CHECK-NEXT: por %xmm2, %xmm0 +; CHECK-NEXT: pand %xmm0, %xmm1 +; CHECK-NEXT: pcmpeqd %xmm1, %xmm0 +; CHECK-NEXT: retq + %yy = shl <4 x i32> , %y + %zz = lshr <4 x i32> , %z + %d = select <4 x i1> %c, <4 x i32> %yy, <4 x i32> %zz + %and = and <4 x i32> %x, %d + %r = icmp eq <4 x i32> %and, %d + ret <4 x i1> %r +} + +define <4 x i1> @pow2_vselect_ne(<4 x i1> %c, <4 x i32> %x, <4 x i32> %y, <4 x i32> %z) { +; CHECK-LABEL: pow2_vselect_ne: +; CHECK: # %bb.0: +; CHECK-NEXT: pslld $31, %xmm0 +; CHECK-NEXT: psrad $31, %xmm0 +; CHECK-NEXT: pslld $23, %xmm2 +; CHECK-NEXT: paddd {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm2 +; CHECK-NEXT: cvttps2dq %xmm2, %xmm2 +; CHECK-NEXT: pshuflw {{.*#+}} xmm4 = xmm3[2,3,3,3,4,5,6,7] +; CHECK-NEXT: movdqa {{.*#+}} xmm5 = [2147483648,2147483648,2147483648,2147483648] +; CHECK-NEXT: movdqa %xmm5, %xmm6 +; CHECK-NEXT: psrld %xmm4, %xmm6 +; CHECK-NEXT: pshuflw {{.*#+}} xmm4 = xmm3[0,1,1,1,4,5,6,7] +; CHECK-NEXT: movdqa %xmm5, %xmm7 +; CHECK-NEXT: psrld %xmm4, %xmm7 +; CHECK-NEXT: punpcklqdq {{.*#+}} xmm7 = xmm7[0],xmm6[0] +; CHECK-NEXT: pshufd {{.*#+}} xmm3 = xmm3[2,3,2,3] +; CHECK-NEXT: pshuflw {{.*#+}} xmm4 = xmm3[2,3,3,3,4,5,6,7] +; CHECK-NEXT: movdqa %xmm5, %xmm6 +; CHECK-NEXT: psrld %xmm4, %xmm6 +; CHECK-NEXT: pshuflw {{.*#+}} xmm3 = xmm3[0,1,1,1,4,5,6,7] +; CHECK-NEXT: psrld %xmm3, %xmm5 +; CHECK-NEXT: punpckhqdq {{.*#+}} xmm5 = xmm5[1],xmm6[1] +; CHECK-NEXT: shufps {{.*#+}} xmm7 = xmm7[0,3],xmm5[0,3] +; CHECK-NEXT: pand %xmm0, %xmm2 +; CHECK-NEXT: pandn %xmm7, %xmm0 +; CHECK-NEXT: por %xmm2, %xmm0 +; CHECK-NEXT: pcmpeqd %xmm2, %xmm2 +; CHECK-NEXT: pand %xmm0, %xmm1 +; CHECK-NEXT: pcmpeqd %xmm1, %xmm0 +; CHECK-NEXT: pxor %xmm2, %xmm0 +; CHECK-NEXT: retq + %yy = shl <4 x i32> , %y + %zz = lshr <4 x i32> , %z + %d = select <4 x i1> %c, <4 x i32> %yy, <4 x i32> %zz + %and = and <4 x i32> %x, %d + %r = icmp ne <4 x i32> %and, %d + ret <4 x i1> %r +} + +define <4 x i1> @pow2_vselect_fail0_ne(<4 x i1> %c, <4 x i32> %x, <4 x i32> %y, <4 x i32> %z) { +; CHECK-LABEL: pow2_vselect_fail0_ne: +; CHECK: # %bb.0: +; CHECK-NEXT: pslld $31, %xmm0 +; CHECK-NEXT: psrad $31, %xmm0 +; CHECK-NEXT: pslld $23, %xmm2 +; CHECK-NEXT: paddd {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm2 +; CHECK-NEXT: cvttps2dq %xmm2, %xmm2 +; CHECK-NEXT: pshuflw {{.*#+}} xmm4 = xmm3[2,3,3,3,4,5,6,7] +; CHECK-NEXT: movdqa {{.*#+}} xmm5 = [1073741824,1073741824,1073741824,1073741824] +; CHECK-NEXT: movdqa %xmm5, %xmm6 +; CHECK-NEXT: psrld %xmm4, %xmm6 +; CHECK-NEXT: pshuflw {{.*#+}} xmm4 = xmm3[0,1,1,1,4,5,6,7] +; CHECK-NEXT: movdqa %xmm5, %xmm7 +; CHECK-NEXT: psrld %xmm4, %xmm7 +; CHECK-NEXT: punpcklqdq {{.*#+}} xmm7 = xmm7[0],xmm6[0] +; CHECK-NEXT: pshufd {{.*#+}} xmm3 = xmm3[2,3,2,3] +; CHECK-NEXT: pshuflw {{.*#+}} xmm4 = xmm3[2,3,3,3,4,5,6,7] +; CHECK-NEXT: movdqa %xmm5, %xmm6 +; CHECK-NEXT: psrld %xmm4, %xmm6 +; CHECK-NEXT: pshuflw {{.*#+}} xmm3 = xmm3[0,1,1,1,4,5,6,7] +; CHECK-NEXT: psrld %xmm3, %xmm5 +; CHECK-NEXT: punpckhqdq {{.*#+}} xmm5 = xmm5[1],xmm6[1] +; CHECK-NEXT: shufps {{.*#+}} xmm7 = xmm7[0,3],xmm5[0,3] +; CHECK-NEXT: pand %xmm0, %xmm2 +; CHECK-NEXT: pandn %xmm7, %xmm0 +; CHECK-NEXT: por %xmm2, %xmm0 +; CHECK-NEXT: pcmpeqd %xmm2, %xmm2 +; CHECK-NEXT: pand %xmm0, %xmm1 +; CHECK-NEXT: pcmpeqd %xmm1, %xmm0 +; CHECK-NEXT: pxor %xmm2, %xmm0 +; CHECK-NEXT: retq + %yy = shl <4 x i32> , %y + %zz = lshr <4 x i32> , %z + %d = select <4 x i1> %c, <4 x i32> %yy, <4 x i32> %zz + %and = and <4 x i32> %x, %d + %r = icmp ne <4 x i32> %and, %d + ret <4 x i1> %r +} + +define <4 x i1> @pow2_vselect_fail2_ne(<4 x i1> %c, <4 x i32> %x, <4 x i32> %y, <4 x i32> %z) { +; CHECK-LABEL: pow2_vselect_fail2_ne: +; CHECK: # %bb.0: +; CHECK-NEXT: pslld $31, %xmm0 +; CHECK-NEXT: psrad $31, %xmm0 +; CHECK-NEXT: pslld $23, %xmm2 +; CHECK-NEXT: paddd {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm2 +; CHECK-NEXT: cvttps2dq %xmm2, %xmm2 +; CHECK-NEXT: movdqa {{.*#+}} xmm4 = [4,4,4,4] +; CHECK-NEXT: pshufd {{.*#+}} xmm5 = xmm2[1,1,3,3] +; CHECK-NEXT: pmuludq %xmm4, %xmm2 +; CHECK-NEXT: pshufd {{.*#+}} xmm2 = xmm2[0,2,2,3] +; CHECK-NEXT: pmuludq %xmm4, %xmm5 +; CHECK-NEXT: pshufd {{.*#+}} xmm4 = xmm5[0,2,2,3] +; CHECK-NEXT: punpckldq {{.*#+}} xmm2 = xmm2[0],xmm4[0],xmm2[1],xmm4[1] +; CHECK-NEXT: pshuflw {{.*#+}} xmm4 = xmm3[2,3,3,3,4,5,6,7] +; CHECK-NEXT: movdqa {{.*#+}} xmm5 = [2147483648,2147483648,2147483648,2147483648] +; CHECK-NEXT: movdqa %xmm5, %xmm6 +; CHECK-NEXT: psrld %xmm4, %xmm6 +; CHECK-NEXT: pshuflw {{.*#+}} xmm4 = xmm3[0,1,1,1,4,5,6,7] +; CHECK-NEXT: movdqa %xmm5, %xmm7 +; CHECK-NEXT: psrld %xmm4, %xmm7 +; CHECK-NEXT: punpcklqdq {{.*#+}} xmm7 = xmm7[0],xmm6[0] +; CHECK-NEXT: pshufd {{.*#+}} xmm3 = xmm3[2,3,2,3] +; CHECK-NEXT: pshuflw {{.*#+}} xmm4 = xmm3[2,3,3,3,4,5,6,7] +; CHECK-NEXT: movdqa %xmm5, %xmm6 +; CHECK-NEXT: psrld %xmm4, %xmm6 +; CHECK-NEXT: pshuflw {{.*#+}} xmm3 = xmm3[0,1,1,1,4,5,6,7] +; CHECK-NEXT: psrld %xmm3, %xmm5 +; CHECK-NEXT: punpckhqdq {{.*#+}} xmm5 = xmm5[1],xmm6[1] +; CHECK-NEXT: shufps {{.*#+}} xmm7 = xmm7[0,3],xmm5[0,3] +; CHECK-NEXT: pand %xmm0, %xmm2 +; CHECK-NEXT: pandn %xmm7, %xmm0 +; CHECK-NEXT: por %xmm2, %xmm0 +; CHECK-NEXT: pcmpeqd %xmm2, %xmm2 +; CHECK-NEXT: pand %xmm0, %xmm1 +; CHECK-NEXT: pcmpeqd %xmm1, %xmm0 +; CHECK-NEXT: pxor %xmm2, %xmm0 +; CHECK-NEXT: retq + %yy = shl <4 x i32> , %y + %zz = lshr <4 x i32> , %z + %d = select <4 x i1> %c, <4 x i32> %yy, <4 x i32> %zz + %and = and <4 x i32> %x, %d + %r = icmp ne <4 x i32> %and, %d + ret <4 x i1> %r +} + +define i1 @pow2_and(i32 %x, i32 %y) { +; CHECK-LABEL: pow2_and: +; CHECK: # %bb.0: +; CHECK-NEXT: movl %esi, %ecx +; CHECK-NEXT: movl $4, %eax +; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx +; CHECK-NEXT: shll %cl, %eax +; CHECK-NEXT: movl %eax, %ecx +; CHECK-NEXT: negl %ecx +; CHECK-NEXT: andl %eax, %ecx +; CHECK-NEXT: notl %edi +; CHECK-NEXT: testl %edi, %ecx +; CHECK-NEXT: sete %al +; CHECK-NEXT: retq + %yy = shl nuw nsw i32 4, %y + %nyy = sub i32 0, %yy + %d = and i32 %yy, %nyy + %and = and i32 %x, %d + %r = icmp eq i32 %and, %d + ret i1 %r +} + +define i1 @pow2_and_fail0(i32 %x, i32 %y) { +; CHECK-LABEL: pow2_and_fail0: +; CHECK: # %bb.0: +; CHECK-NEXT: movl %esi, %ecx +; CHECK-NEXT: movl $4, %eax +; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx +; CHECK-NEXT: shll %cl, %eax +; CHECK-NEXT: movl %eax, %ecx +; CHECK-NEXT: negl %ecx +; CHECK-NEXT: andl %eax, %ecx +; CHECK-NEXT: notl %edi +; CHECK-NEXT: testl %edi, %ecx +; CHECK-NEXT: sete %al +; CHECK-NEXT: retq + %yy = shl i32 4, %y + %nyy = sub i32 0, %yy + %d = and i32 %yy, %nyy + %and = and i32 %x, %d + %r = icmp eq i32 %and, %d + ret i1 %r +} + +define i1 @pow2_and_fail1(i32 %x, i32 %y) { +; CHECK-LABEL: pow2_and_fail1: +; CHECK: # %bb.0: +; CHECK-NEXT: movl %esi, %ecx +; CHECK-NEXT: movl $1, %eax +; CHECK-NEXT: movl $1, %edx +; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx +; CHECK-NEXT: shll %cl, %edx +; CHECK-NEXT: subl %edx, %eax +; CHECK-NEXT: andl %edx, %eax +; CHECK-NEXT: notl %edi +; CHECK-NEXT: testl %edi, %eax +; CHECK-NEXT: sete %al +; CHECK-NEXT: retq + %yy = shl i32 1, %y + %nyy = sub i32 1, %yy + %d = and i32 %yy, %nyy + %and = and i32 %x, %d + %r = icmp eq i32 %and, %d + ret i1 %r +} + +define i1 @pow2_and_fail2(i32 %x, i32 %y, i32 %z) { +; CHECK-LABEL: pow2_and_fail2: +; CHECK: # %bb.0: +; CHECK-NEXT: movl %esi, %ecx +; CHECK-NEXT: movl $1, %eax +; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx +; CHECK-NEXT: shll %cl, %eax +; CHECK-NEXT: andl %edx, %eax +; CHECK-NEXT: notl %edi +; CHECK-NEXT: testl %edi, %eax +; CHECK-NEXT: sete %al +; CHECK-NEXT: retq + %yy = shl i32 1, %y + %d = and i32 %yy, %z + %and = and i32 %x, %d + %r = icmp eq i32 %and, %d + ret i1 %r +} + +define i1 @pow2_though_zext(i32 %x, i16 %y) { +; CHECK-LABEL: pow2_though_zext: +; CHECK: # %bb.0: +; CHECK-NEXT: movl %esi, %ecx +; CHECK-NEXT: movl $4, %eax +; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx +; CHECK-NEXT: shll %cl, %eax +; CHECK-NEXT: notl %edi +; CHECK-NEXT: andl %eax, %edi +; CHECK-NEXT: testl $65535, %edi # imm = 0xFFFF +; CHECK-NEXT: sete %al +; CHECK-NEXT: retq + %dd = shl nuw nsw i16 4, %y + %d = zext i16 %dd to i32 + %and = and i32 %x, %d + %r = icmp eq i32 %and, %d + ret i1 %r +}