diff options
Diffstat (limited to 'test/Transforms/InstCombine')
-rw-r--r-- | test/Transforms/InstCombine/add-sitofp.ll | 124 | ||||
-rw-r--r-- | test/Transforms/InstCombine/amdgcn-intrinsics.ll | 6 | ||||
-rw-r--r-- | test/Transforms/InstCombine/and-or-icmps.ll | 4 | ||||
-rw-r--r-- | test/Transforms/InstCombine/and-or-not.ll | 570 | ||||
-rw-r--r-- | test/Transforms/InstCombine/and.ll | 28 | ||||
-rw-r--r-- | test/Transforms/InstCombine/apint-shift.ll | 7 | ||||
-rw-r--r-- | test/Transforms/InstCombine/debuginfo-dce.ll | 42 | ||||
-rw-r--r-- | test/Transforms/InstCombine/fsub.ll | 44 | ||||
-rw-r--r-- | test/Transforms/InstCombine/intrinsics.ll | 26 | ||||
-rw-r--r-- | test/Transforms/InstCombine/memset-1.ll | 9 | ||||
-rw-r--r-- | test/Transforms/InstCombine/minmax-fold.ll | 6 | ||||
-rw-r--r-- | test/Transforms/InstCombine/or-to-xor.ll | 55 | ||||
-rw-r--r-- | test/Transforms/InstCombine/or.ll | 53 | ||||
-rw-r--r-- | test/Transforms/InstCombine/pr17827.ll | 4 | ||||
-rw-r--r-- | test/Transforms/InstCombine/shift.ll | 30 | ||||
-rw-r--r-- | test/Transforms/InstCombine/xor2.ll | 75 |
16 files changed, 894 insertions, 189 deletions
diff --git a/test/Transforms/InstCombine/add-sitofp.ll b/test/Transforms/InstCombine/add-sitofp.ll index 2abfa436f6d3..105c9efa0893 100644 --- a/test/Transforms/InstCombine/add-sitofp.ll +++ b/test/Transforms/InstCombine/add-sitofp.ll @@ -15,3 +15,127 @@ define double @x(i32 %a, i32 %b) { %p = fadd double %o, 1.0 ret double %p } + +define double @test(i32 %a) { +; CHECK-LABEL: @test( +; CHECK-NEXT: [[A_AND:%.*]] = and i32 [[A:%.*]], 1073741823 +; CHECK-NEXT: [[ADDCONV:%.*]] = add nuw nsw i32 [[A_AND]], 1 +; CHECK-NEXT: [[RES:%.*]] = sitofp i32 [[ADDCONV]] to double +; CHECK-NEXT: ret double [[RES]] +; + ; Drop two highest bits to guarantee that %a + 1 doesn't overflow + %a_and = and i32 %a, 1073741823 + %a_and_fp = sitofp i32 %a_and to double + %res = fadd double %a_and_fp, 1.0 + ret double %res +} + +define float @test_neg(i32 %a) { +; CHECK-LABEL: @test_neg( +; CHECK-NEXT: [[A_AND:%.*]] = and i32 [[A:%.*]], 1073741823 +; CHECK-NEXT: [[A_AND_FP:%.*]] = sitofp i32 [[A_AND]] to float +; CHECK-NEXT: [[RES:%.*]] = fadd float [[A_AND_FP]], 1.000000e+00 +; CHECK-NEXT: ret float [[RES]] +; + ; Drop two highest bits to guarantee that %a + 1 doesn't overflow + %a_and = and i32 %a, 1073741823 + %a_and_fp = sitofp i32 %a_and to float + %res = fadd float %a_and_fp, 1.0 + ret float %res +} + +define double @test_2(i32 %a, i32 %b) { +; CHECK-LABEL: @test_2( +; CHECK-NEXT: [[A_AND:%.*]] = and i32 [[A:%.*]], 1073741823 +; CHECK-NEXT: [[B_AND:%.*]] = and i32 [[B:%.*]], 1073741823 +; CHECK-NEXT: [[ADDCONV:%.*]] = add nuw nsw i32 [[A_AND]], [[B_AND]] +; CHECK-NEXT: [[RES:%.*]] = sitofp i32 [[ADDCONV]] to double +; CHECK-NEXT: ret double [[RES]] +; + ; Drop two highest bits to guarantee that %a + %b doesn't overflow + %a_and = and i32 %a, 1073741823 + %b_and = and i32 %b, 1073741823 + + %a_and_fp = sitofp i32 %a_and to double + %b_and_fp = sitofp i32 %b_and to double + + %res = fadd double %a_and_fp, %b_and_fp + ret double %res +} + +define float @test_2_neg(i32 %a, i32 %b) { +; CHECK-LABEL: @test_2_neg( +; CHECK-NEXT: [[A_AND:%.*]] = and i32 [[A:%.*]], 1073741823 +; CHECK-NEXT: [[B_AND:%.*]] = and i32 [[B:%.*]], 1073741823 +; CHECK-NEXT: [[A_AND_FP:%.*]] = sitofp i32 [[A_AND]] to float +; CHECK-NEXT: [[B_AND_FP:%.*]] = sitofp i32 [[B_AND]] to float +; CHECK-NEXT: [[RES:%.*]] = fadd float [[A_AND_FP]], [[B_AND_FP]] +; CHECK-NEXT: ret float [[RES]] +; + ; Drop two highest bits to guarantee that %a + %b doesn't overflow + %a_and = and i32 %a, 1073741823 + %b_and = and i32 %b, 1073741823 + + %a_and_fp = sitofp i32 %a_and to float + %b_and_fp = sitofp i32 %b_and to float + + %res = fadd float %a_and_fp, %b_and_fp + ret float %res +} + +; This test demonstrates overly conservative legality check. The float addition +; can be replaced with the integer addition because the result of the operation +; can be represented in float, but we don't do that now. +define float @test_3(i32 %a, i32 %b) { +; CHECK-LABEL: @test_3( +; CHECK-NEXT: [[M:%.*]] = lshr i32 [[A:%.*]], 24 +; CHECK-NEXT: [[N:%.*]] = and i32 [[M]], [[B:%.*]] +; CHECK-NEXT: [[O:%.*]] = sitofp i32 [[N]] to float +; CHECK-NEXT: [[P:%.*]] = fadd float [[O]], 1.000000e+00 +; CHECK-NEXT: ret float [[P]] +; + %m = lshr i32 %a, 24 + %n = and i32 %m, %b + %o = sitofp i32 %n to float + %p = fadd float %o, 1.0 + ret float %p +} + +define <4 x double> @test_4(<4 x i32> %a, <4 x i32> %b) { +; CHECK-LABEL: @test_4( +; CHECK-NEXT: [[A_AND:%.*]] = and <4 x i32> [[A:%.*]], <i32 1073741823, i32 1073741823, i32 1073741823, i32 1073741823> +; CHECK-NEXT: [[B_AND:%.*]] = and <4 x i32> [[B:%.*]], <i32 1073741823, i32 1073741823, i32 1073741823, i32 1073741823> +; CHECK-NEXT: [[ADDCONV:%.*]] = add nuw nsw <4 x i32> [[A_AND]], [[B_AND]] +; CHECK-NEXT: [[RES:%.*]] = sitofp <4 x i32> [[ADDCONV]] to <4 x double> +; CHECK-NEXT: ret <4 x double> [[RES]] +; + ; Drop two highest bits to guarantee that %a + %b doesn't overflow + %a_and = and <4 x i32> %a, <i32 1073741823, i32 1073741823, i32 1073741823, i32 1073741823> + %b_and = and <4 x i32> %b, <i32 1073741823, i32 1073741823, i32 1073741823, i32 1073741823> + + %a_and_fp = sitofp <4 x i32> %a_and to <4 x double> + %b_and_fp = sitofp <4 x i32> %b_and to <4 x double> + + %res = fadd <4 x double> %a_and_fp, %b_and_fp + ret <4 x double> %res +} + +define <4 x float> @test_4_neg(<4 x i32> %a, <4 x i32> %b) { +; CHECK-LABEL: @test_4_neg( +; CHECK-NEXT: [[A_AND:%.*]] = and <4 x i32> [[A:%.*]], <i32 1073741823, i32 1073741823, i32 1073741823, i32 1073741823> +; CHECK-NEXT: [[B_AND:%.*]] = and <4 x i32> [[B:%.*]], <i32 1073741823, i32 1073741823, i32 1073741823, i32 1073741823> +; CHECK-NEXT: [[A_AND_FP:%.*]] = sitofp <4 x i32> [[A_AND]] to <4 x float> +; CHECK-NEXT: [[B_AND_FP:%.*]] = sitofp <4 x i32> [[B_AND]] to <4 x float> +; CHECK-NEXT: [[RES:%.*]] = fadd <4 x float> [[A_AND_FP]], [[B_AND_FP]] +; CHECK-NEXT: ret <4 x float> [[RES]] +; + ; Drop two highest bits to guarantee that %a + %b doesn't overflow + %a_and = and <4 x i32> %a, <i32 1073741823, i32 1073741823, i32 1073741823, i32 1073741823> + %b_and = and <4 x i32> %b, <i32 1073741823, i32 1073741823, i32 1073741823, i32 1073741823> + + %a_and_fp = sitofp <4 x i32> %a_and to <4 x float> + %b_and_fp = sitofp <4 x i32> %b_and to <4 x float> + + %res = fadd <4 x float> %a_and_fp, %b_and_fp + ret <4 x float> %res +} diff --git a/test/Transforms/InstCombine/amdgcn-intrinsics.ll b/test/Transforms/InstCombine/amdgcn-intrinsics.ll index deae5502bcdb..357085fd31fe 100644 --- a/test/Transforms/InstCombine/amdgcn-intrinsics.ll +++ b/test/Transforms/InstCombine/amdgcn-intrinsics.ll @@ -1259,7 +1259,7 @@ define i64 @icmp_constant_inputs_false() { } ; CHECK-LABEL: @icmp_constant_inputs_true( -; CHECK: ret i64 -1 +; CHECK: %result = call i64 @llvm.read_register.i64(metadata !0) #4 define i64 @icmp_constant_inputs_true() { %result = call i64 @llvm.amdgcn.icmp.i32(i32 9, i32 8, i32 34) ret i64 %result @@ -1524,7 +1524,7 @@ define i64 @fcmp_constant_inputs_false() { } ; CHECK-LABEL: @fcmp_constant_inputs_true( -; CHECK: ret i64 -1 +; CHECK: %result = call i64 @llvm.read_register.i64(metadata !0) #4 define i64 @fcmp_constant_inputs_true() { %result = call i64 @llvm.amdgcn.fcmp.f32(float 2.0, float 4.0, i32 4) ret i64 %result @@ -1536,3 +1536,5 @@ define i64 @fcmp_constant_to_rhs_olt(float %x) { %result = call i64 @llvm.amdgcn.fcmp.f32(float 4.0, float %x, i32 4) ret i64 %result } + +; CHECK: attributes #4 = { convergent } diff --git a/test/Transforms/InstCombine/and-or-icmps.ll b/test/Transforms/InstCombine/and-or-icmps.ll index e3aeee293139..464f390f988f 100644 --- a/test/Transforms/InstCombine/and-or-icmps.ll +++ b/test/Transforms/InstCombine/and-or-icmps.ll @@ -3,10 +3,8 @@ define i1 @PR1817_1(i32 %X) { ; CHECK-LABEL: @PR1817_1( -; CHECK-NEXT: [[A:%.*]] = icmp slt i32 %X, 10 ; CHECK-NEXT: [[B:%.*]] = icmp ult i32 %X, 10 -; CHECK-NEXT: [[C:%.*]] = and i1 [[A]], [[B]] -; CHECK-NEXT: ret i1 [[C]] +; CHECK-NEXT: ret i1 [[B]] ; %A = icmp slt i32 %X, 10 %B = icmp ult i32 %X, 10 diff --git a/test/Transforms/InstCombine/and-or-not.ll b/test/Transforms/InstCombine/and-or-not.ll index 144e42e74868..a2e8a10735fd 100644 --- a/test/Transforms/InstCombine/and-or-not.ll +++ b/test/Transforms/InstCombine/and-or-not.ll @@ -2,55 +2,525 @@ ; PR1510 -; These are all equivalent to A^B - -define i32 @test1(i32 %a, i32 %b) { - %tmp3 = or i32 %b, %a ; <i32> [#uses=1] - %tmp3not = xor i32 %tmp3, -1 ; <i32> [#uses=1] - %tmp6 = and i32 %b, %a ; <i32> [#uses=1] - %tmp7 = or i32 %tmp6, %tmp3not ; <i32> [#uses=1] - %tmp7not = xor i32 %tmp7, -1 ; <i32> [#uses=1] - ret i32 %tmp7not - -; CHECK-LABEL: @test1( -; CHECK-NEXT: [[TMP7NOT:%.*]] = xor i32 %b, %a -; CHECK-NEXT: ret i32 [[TMP7NOT]] -} - -define i32 @test2(i32 %a, i32 %b) { - %tmp3 = or i32 %b, %a ; <i32> [#uses=1] - %tmp6 = and i32 %b, %a ; <i32> [#uses=1] - %tmp6not = xor i32 %tmp6, -1 ; <i32> [#uses=1] - %tmp7 = and i32 %tmp3, %tmp6not ; <i32> [#uses=1] - ret i32 %tmp7 - -; CHECK-LABEL: @test2( -; CHECK-NEXT: [[TMP7:%.*]] = xor i32 %b, %a -; CHECK-NEXT: ret i32 [[TMP7]] -} - -define <4 x i32> @test3(<4 x i32> %a, <4 x i32> %b) { - %tmp3 = or <4 x i32> %a, %b ; <<4 x i32>> [#uses=1] - %tmp3not = xor <4 x i32> %tmp3, < i32 -1, i32 -1, i32 -1, i32 -1 > ; <<4 x i32>> [#uses=1] - %tmp6 = and <4 x i32> %a, %b ; <<4 x i32>> [#uses=1] - %tmp7 = or <4 x i32> %tmp6, %tmp3not ; <<4 x i32>> [#uses=1] - %tmp7not = xor <4 x i32> %tmp7, < i32 -1, i32 -1, i32 -1, i32 -1 > ; <<4 x i32>> [#uses=1] - ret <4 x i32> %tmp7not - -; CHECK-LABEL: @test3( -; CHECK-NEXT: [[TMP7NOT:%.*]] = xor <4 x i32> %a, %b -; CHECK-NEXT: ret <4 x i32> [[TMP7NOT]] -} - -define <4 x i32> @test4(<4 x i32> %a, <4 x i32> %b) { - %tmp3 = or <4 x i32> %a, %b ; <<4 x i32>> [#uses=1] - %tmp6 = and <4 x i32> %a, %b ; <<4 x i32>> [#uses=1] - %tmp6not = xor <4 x i32> %tmp6, < i32 -1, i32 -1, i32 -1, i32 -1 > ; <<4 x i32>> [#uses=1] - %tmp7 = and <4 x i32> %tmp3, %tmp6not ; <<4 x i32>> [#uses=1] - ret <4 x i32> %tmp7 - -; CHECK-LABEL: @test4( -; CHECK-NEXT: [[TMP7:%.*]] = xor <4 x i32> %a, %b -; CHECK-NEXT: ret <4 x i32> [[TMP7]] +; (a | b) & ~(a & b) --> a ^ b + +define i32 @and_to_xor1(i32 %a, i32 %b) { +; CHECK-LABEL: @and_to_xor1( +; CHECK-NEXT: [[AND2:%.*]] = xor i32 %a, %b +; CHECK-NEXT: ret i32 [[AND2]] +; + %or = or i32 %a, %b + %and = and i32 %a, %b + %not = xor i32 %and, -1 + %and2 = and i32 %or, %not + ret i32 %and2 +} + +; ~(a & b) & (a | b) --> a ^ b + +define i32 @and_to_xor2(i32 %a, i32 %b) { +; CHECK-LABEL: @and_to_xor2( +; CHECK-NEXT: [[AND2:%.*]] = xor i32 %a, %b +; CHECK-NEXT: ret i32 [[AND2]] +; + %or = or i32 %a, %b + %and = and i32 %a, %b + %not = xor i32 %and, -1 + %and2 = and i32 %not, %or + ret i32 %and2 +} + +; (a | b) & ~(b & a) --> a ^ b + +define i32 @and_to_xor3(i32 %a, i32 %b) { +; CHECK-LABEL: @and_to_xor3( +; CHECK-NEXT: [[AND2:%.*]] = xor i32 %a, %b +; CHECK-NEXT: ret i32 [[AND2]] +; + %or = or i32 %a, %b + %and = and i32 %b, %a + %not = xor i32 %and, -1 + %and2 = and i32 %or, %not + ret i32 %and2 +} + +; ~(a & b) & (b | a) --> a ^ b + +define i32 @and_to_xor4(i32 %a, i32 %b) { +; CHECK-LABEL: @and_to_xor4( +; CHECK-NEXT: [[AND2:%.*]] = xor i32 %b, %a +; CHECK-NEXT: ret i32 [[AND2]] +; + %or = or i32 %b, %a + %and = and i32 %a, %b + %not = xor i32 %and, -1 + %and2 = and i32 %not, %or + ret i32 %and2 +} + +define <4 x i32> @and_to_xor1_vec(<4 x i32> %a, <4 x i32> %b) { +; CHECK-LABEL: @and_to_xor1_vec( +; CHECK-NEXT: [[AND2:%.*]] = xor <4 x i32> %a, %b +; CHECK-NEXT: ret <4 x i32> [[AND2]] +; + %or = or <4 x i32> %a, %b + %and = and <4 x i32> %a, %b + %not = xor <4 x i32> %and, < i32 -1, i32 -1, i32 -1, i32 -1 > + %and2 = and <4 x i32> %or, %not + ret <4 x i32> %and2 +} + +; In the next 4 tests, cast instructions are used to thwart operand complexity +; canonicalizations, so we can test all of the commuted patterns. + +; (a | ~b) & (~a | b) --> ~(a ^ b) + +define i32 @and_to_nxor1(float %fa, float %fb) { +; CHECK-LABEL: @and_to_nxor1( +; CHECK-NEXT: [[A:%.*]] = fptosi float %fa to i32 +; CHECK-NEXT: [[B:%.*]] = fptosi float %fb to i32 +; CHECK-NEXT: [[TMP1:%.*]] = xor i32 [[A]], [[B]] +; CHECK-NEXT: [[AND:%.*]] = xor i32 [[TMP1]], -1 +; CHECK-NEXT: ret i32 [[AND]] +; + %a = fptosi float %fa to i32 + %b = fptosi float %fb to i32 + %nota = xor i32 %a, -1 + %notb = xor i32 %b, -1 + %or1 = or i32 %a, %notb + %or2 = or i32 %nota, %b + %and = and i32 %or1, %or2 + ret i32 %and +} + +; (a | ~b) & (b | ~a) --> ~(a ^ b) + +define i32 @and_to_nxor2(float %fa, float %fb) { +; CHECK-LABEL: @and_to_nxor2( +; CHECK-NEXT: [[A:%.*]] = fptosi float %fa to i32 +; CHECK-NEXT: [[B:%.*]] = fptosi float %fb to i32 +; CHECK-NEXT: [[TMP1:%.*]] = xor i32 [[A]], [[B]] +; CHECK-NEXT: [[AND:%.*]] = xor i32 [[TMP1]], -1 +; CHECK-NEXT: ret i32 [[AND]] +; + %a = fptosi float %fa to i32 + %b = fptosi float %fb to i32 + %nota = xor i32 %a, -1 + %notb = xor i32 %b, -1 + %or1 = or i32 %a, %notb + %or2 = or i32 %b, %nota + %and = and i32 %or1, %or2 + ret i32 %and +} + +; (~a | b) & (a | ~b) --> ~(a ^ b) + +define i32 @and_to_nxor3(float %fa, float %fb) { +; CHECK-LABEL: @and_to_nxor3( +; CHECK-NEXT: [[A:%.*]] = fptosi float %fa to i32 +; CHECK-NEXT: [[B:%.*]] = fptosi float %fb to i32 +; CHECK-NEXT: [[TMP1:%.*]] = xor i32 [[B]], [[A]] +; CHECK-NEXT: [[AND:%.*]] = xor i32 [[TMP1]], -1 +; CHECK-NEXT: ret i32 [[AND]] +; + %a = fptosi float %fa to i32 + %b = fptosi float %fb to i32 + %nota = xor i32 %a, -1 + %notb = xor i32 %b, -1 + %or1 = or i32 %nota, %b + %or2 = or i32 %a, %notb + %and = and i32 %or1, %or2 + ret i32 %and +} + +; (~a | b) & (~b | a) --> ~(a ^ b) + +define i32 @and_to_nxor4(float %fa, float %fb) { +; CHECK-LABEL: @and_to_nxor4( +; CHECK-NEXT: [[A:%.*]] = fptosi float %fa to i32 +; CHECK-NEXT: [[B:%.*]] = fptosi float %fb to i32 +; CHECK-NEXT: [[TMP1:%.*]] = xor i32 [[B]], [[A]] +; CHECK-NEXT: [[AND:%.*]] = xor i32 [[TMP1]], -1 +; CHECK-NEXT: ret i32 [[AND]] +; + %a = fptosi float %fa to i32 + %b = fptosi float %fb to i32 + %nota = xor i32 %a, -1 + %notb = xor i32 %b, -1 + %or1 = or i32 %nota, %b + %or2 = or i32 %notb, %a + %and = and i32 %or1, %or2 + ret i32 %and +} + +; (a & ~b) | (~a & b) --> a ^ b + +define i32 @or_to_xor1(float %fa, float %fb) { +; CHECK-LABEL: @or_to_xor1( +; CHECK-NEXT: [[A:%.*]] = fptosi float %fa to i32 +; CHECK-NEXT: [[B:%.*]] = fptosi float %fb to i32 +; CHECK-NEXT: [[OR:%.*]] = xor i32 [[A]], [[B]] +; CHECK-NEXT: ret i32 [[OR]] +; + %a = fptosi float %fa to i32 + %b = fptosi float %fb to i32 + %nota = xor i32 %a, -1 + %notb = xor i32 %b, -1 + %and1 = and i32 %a, %notb + %and2 = and i32 %nota, %b + %or = or i32 %and1, %and2 + ret i32 %or +} + +; (a & ~b) | (b & ~a) --> a ^ b + +define i32 @or_to_xor2(float %fa, float %fb) { +; CHECK-LABEL: @or_to_xor2( +; CHECK-NEXT: [[A:%.*]] = fptosi float %fa to i32 +; CHECK-NEXT: [[B:%.*]] = fptosi float %fb to i32 +; CHECK-NEXT: [[OR:%.*]] = xor i32 [[A]], [[B]] +; CHECK-NEXT: ret i32 [[OR]] +; + %a = fptosi float %fa to i32 + %b = fptosi float %fb to i32 + %nota = xor i32 %a, -1 + %notb = xor i32 %b, -1 + %and1 = and i32 %a, %notb + %and2 = and i32 %b, %nota + %or = or i32 %and1, %and2 + ret i32 %or +} + +; (~a & b) | (~b & a) --> a ^ b + +define i32 @or_to_xor3(float %fa, float %fb) { +; CHECK-LABEL: @or_to_xor3( +; CHECK-NEXT: [[A:%.*]] = fptosi float %fa to i32 +; CHECK-NEXT: [[B:%.*]] = fptosi float %fb to i32 +; CHECK-NEXT: [[OR:%.*]] = xor i32 [[B]], [[A]] +; CHECK-NEXT: ret i32 [[OR]] +; + %a = fptosi float %fa to i32 + %b = fptosi float %fb to i32 + %nota = xor i32 %a, -1 + %notb = xor i32 %b, -1 + %and1 = and i32 %nota, %b + %and2 = and i32 %notb, %a + %or = or i32 %and1, %and2 + ret i32 %or +} + +; (~a & b) | (a & ~b) --> a ^ b + +define i32 @or_to_xor4(float %fa, float %fb) { +; CHECK-LABEL: @or_to_xor4( +; CHECK-NEXT: [[A:%.*]] = fptosi float %fa to i32 +; CHECK-NEXT: [[B:%.*]] = fptosi float %fb to i32 +; CHECK-NEXT: [[OR:%.*]] = xor i32 [[B]], [[A]] +; CHECK-NEXT: ret i32 [[OR]] +; + %a = fptosi float %fa to i32 + %b = fptosi float %fb to i32 + %nota = xor i32 %a, -1 + %notb = xor i32 %b, -1 + %and1 = and i32 %nota, %b + %and2 = and i32 %a, %notb + %or = or i32 %and1, %and2 + ret i32 %or +} + +; (a & b) | ~(a | b) --> ~(a ^ b) + +define i32 @or_to_nxor1(i32 %a, i32 %b) { +; CHECK-LABEL: @or_to_nxor1( +; CHECK-NEXT: [[TMP1:%.*]] = xor i32 %a, %b +; CHECK-NEXT: [[OR2:%.*]] = xor i32 [[TMP1]], -1 +; CHECK-NEXT: ret i32 [[OR2]] +; + %and = and i32 %a, %b + %or = or i32 %a, %b + %notor = xor i32 %or, -1 + %or2 = or i32 %and, %notor + ret i32 %or2 +} + +; (a & b) | ~(b | a) --> ~(a ^ b) + +define i32 @or_to_nxor2(i32 %a, i32 %b) { +; CHECK-LABEL: @or_to_nxor2( +; CHECK-NEXT: [[TMP1:%.*]] = xor i32 %a, %b +; CHECK-NEXT: [[OR2:%.*]] = xor i32 [[TMP1]], -1 +; CHECK-NEXT: ret i32 [[OR2]] +; + %and = and i32 %a, %b + %or = or i32 %b, %a + %notor = xor i32 %or, -1 + %or2 = or i32 %and, %notor + ret i32 %or2 +} + +; ~(a | b) | (a & b) --> ~(a ^ b) + +define i32 @or_to_nxor3(i32 %a, i32 %b) { +; CHECK-LABEL: @or_to_nxor3( +; CHECK-NEXT: [[TMP1:%.*]] = xor i32 %a, %b +; CHECK-NEXT: [[OR2:%.*]] = xor i32 [[TMP1]], -1 +; CHECK-NEXT: ret i32 [[OR2]] +; + %and = and i32 %a, %b + %or = or i32 %a, %b + %notor = xor i32 %or, -1 + %or2 = or i32 %notor, %and + ret i32 %or2 +} + +; ~(a | b) | (b & a) --> ~(a ^ b) + +define i32 @or_to_nxor4(i32 %a, i32 %b) { +; CHECK-LABEL: @or_to_nxor4( +; CHECK-NEXT: [[TMP1:%.*]] = xor i32 %b, %a +; CHECK-NEXT: [[OR2:%.*]] = xor i32 [[TMP1]], -1 +; CHECK-NEXT: ret i32 [[OR2]] +; + %and = and i32 %b, %a + %or = or i32 %a, %b + %notor = xor i32 %or, -1 + %or2 = or i32 %notor, %and + ret i32 %or2 +} + +; (a & b) ^ (a | b) --> a ^ b + +define i32 @xor_to_xor1(i32 %a, i32 %b) { +; CHECK-LABEL: @xor_to_xor1( +; CHECK-NEXT: [[XOR:%.*]] = xor i32 %a, %b +; CHECK-NEXT: ret i32 [[XOR]] +; + %and = and i32 %a, %b + %or = or i32 %a, %b + %xor = xor i32 %and, %or + ret i32 %xor +} + +; (a & b) ^ (b | a) --> a ^ b + +define i32 @xor_to_xor2(i32 %a, i32 %b) { +; CHECK-LABEL: @xor_to_xor2( +; CHECK-NEXT: [[XOR:%.*]] = xor i32 %a, %b +; CHECK-NEXT: ret i32 [[XOR]] +; + %and = and i32 %a, %b + %or = or i32 %b, %a + %xor = xor i32 %and, %or + ret i32 %xor +} + +; (a | b) ^ (a & b) --> a ^ b + +define i32 @xor_to_xor3(i32 %a, i32 %b) { +; CHECK-LABEL: @xor_to_xor3( +; CHECK-NEXT: [[XOR:%.*]] = xor i32 %a, %b +; CHECK-NEXT: ret i32 [[XOR]] +; + %or = or i32 %a, %b + %and = and i32 %a, %b + %xor = xor i32 %or, %and + ret i32 %xor +} + +; (a | b) ^ (b & a) --> a ^ b + +define i32 @xor_to_xor4(i32 %a, i32 %b) { +; CHECK-LABEL: @xor_to_xor4( +; CHECK-NEXT: [[XOR:%.*]] = xor i32 %a, %b +; CHECK-NEXT: ret i32 [[XOR]] +; + %or = or i32 %a, %b + %and = and i32 %b, %a + %xor = xor i32 %or, %and + ret i32 %xor +} + +; (a | ~b) ^ (~a | b) --> a ^ b + +; In the next 8 tests, cast instructions are used to thwart operand complexity +; canonicalizations, so we can test all of the commuted patterns. + +define i32 @xor_to_xor5(float %fa, float %fb) { +; CHECK-LABEL: @xor_to_xor5( +; CHECK-NEXT: [[A:%.*]] = fptosi float %fa to i32 +; CHECK-NEXT: [[B:%.*]] = fptosi float %fb to i32 +; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[A]], [[B]] +; CHECK-NEXT: ret i32 [[XOR]] +; + %a = fptosi float %fa to i32 + %b = fptosi float %fb to i32 + %nota = xor i32 %a, -1 + %notb = xor i32 %b, -1 + %or1 = or i32 %a, %notb + %or2 = or i32 %nota, %b + %xor = xor i32 %or1, %or2 + ret i32 %xor +} + +; (a | ~b) ^ (b | ~a) --> a ^ b + +define i32 @xor_to_xor6(float %fa, float %fb) { +; CHECK-LABEL: @xor_to_xor6( +; CHECK-NEXT: [[A:%.*]] = fptosi float %fa to i32 +; CHECK-NEXT: [[B:%.*]] = fptosi float %fb to i32 +; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[B]], [[A]] +; CHECK-NEXT: ret i32 [[XOR]] +; + %a = fptosi float %fa to i32 + %b = fptosi float %fb to i32 + %nota = xor i32 %a, -1 + %notb = xor i32 %b, -1 + %or1 = or i32 %a, %notb + %or2 = or i32 %b, %nota + %xor = xor i32 %or1, %or2 + ret i32 %xor +} + +; (~a | b) ^ (a | ~b) --> a ^ b + +define i32 @xor_to_xor7(float %fa, float %fb) { +; CHECK-LABEL: @xor_to_xor7( +; CHECK-NEXT: [[A:%.*]] = fptosi float %fa to i32 +; CHECK-NEXT: [[B:%.*]] = fptosi float %fb to i32 +; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[A]], [[B]] +; CHECK-NEXT: ret i32 [[XOR]] +; + %a = fptosi float %fa to i32 + %b = fptosi float %fb to i32 + %nota = xor i32 %a, -1 + %notb = xor i32 %b, -1 + %or1 = or i32 %a, %notb + %or2 = or i32 %nota, %b + %xor = xor i32 %or2, %or1 + ret i32 %xor +} + +; (~a | b) ^ (~b | a) --> a ^ b + +define i32 @xor_to_xor8(float %fa, float %fb) { +; CHECK-LABEL: @xor_to_xor8( +; CHECK-NEXT: [[A:%.*]] = fptosi float %fa to i32 +; CHECK-NEXT: [[B:%.*]] = fptosi float %fb to i32 +; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[B]], [[A]] +; CHECK-NEXT: ret i32 [[XOR]] +; + %a = fptosi float %fa to i32 + %b = fptosi float %fb to i32 + %nota = xor i32 %a, -1 + %notb = xor i32 %b, -1 + %or1 = or i32 %notb, %a + %or2 = or i32 %nota, %b + %xor = xor i32 %or2, %or1 + ret i32 %xor +} + +; (a & ~b) ^ (~a & b) --> a ^ b + +define i32 @xor_to_xor9(float %fa, float %fb) { +; CHECK-LABEL: @xor_to_xor9( +; CHECK-NEXT: [[A:%.*]] = fptosi float %fa to i32 +; CHECK-NEXT: [[B:%.*]] = fptosi float %fb to i32 +; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[A]], [[B]] +; CHECK-NEXT: ret i32 [[XOR]] +; + %a = fptosi float %fa to i32 + %b = fptosi float %fb to i32 + %nota = xor i32 %a, -1 + %notb = xor i32 %b, -1 + %and1 = and i32 %a, %notb + %and2 = and i32 %nota, %b + %xor = xor i32 %and1, %and2 + ret i32 %xor +} + +; (a & ~b) ^ (b & ~a) --> a ^ b + +define i32 @xor_to_xor10(float %fa, float %fb) { +; CHECK-LABEL: @xor_to_xor10( +; CHECK-NEXT: [[A:%.*]] = fptosi float %fa to i32 +; CHECK-NEXT: [[B:%.*]] = fptosi float %fb to i32 +; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[B]], [[A]] +; CHECK-NEXT: ret i32 [[XOR]] +; + %a = fptosi float %fa to i32 + %b = fptosi float %fb to i32 + %nota = xor i32 %a, -1 + %notb = xor i32 %b, -1 + %and1 = and i32 %a, %notb + %and2 = and i32 %b, %nota + %xor = xor i32 %and1, %and2 + ret i32 %xor +} + +; (~a & b) ^ (a & ~b) --> a ^ b + +define i32 @xor_to_xor11(float %fa, float %fb) { +; CHECK-LABEL: @xor_to_xor11( +; CHECK-NEXT: [[A:%.*]] = fptosi float %fa to i32 +; CHECK-NEXT: [[B:%.*]] = fptosi float %fb to i32 +; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[A]], [[B]] +; CHECK-NEXT: ret i32 [[XOR]] +; + %a = fptosi float %fa to i32 + %b = fptosi float %fb to i32 + %nota = xor i32 %a, -1 + %notb = xor i32 %b, -1 + %and1 = and i32 %a, %notb + %and2 = and i32 %nota, %b + %xor = xor i32 %and2, %and1 + ret i32 %xor +} + +; (~a & b) ^ (~b & a) --> a ^ b + +define i32 @xor_to_xor12(float %fa, float %fb) { +; CHECK-LABEL: @xor_to_xor12( +; CHECK-NEXT: [[A:%.*]] = fptosi float %fa to i32 +; CHECK-NEXT: [[B:%.*]] = fptosi float %fb to i32 +; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[B]], [[A]] +; CHECK-NEXT: ret i32 [[XOR]] +; + %a = fptosi float %fa to i32 + %b = fptosi float %fb to i32 + %nota = xor i32 %a, -1 + %notb = xor i32 %b, -1 + %and1 = and i32 %notb, %a + %and2 = and i32 %nota, %b + %xor = xor i32 %and2, %and1 + ret i32 %xor +} + +; ~(~(a | b) | (a & b)) --> (a | b) & ~(a & b) -> a ^ b + +define i32 @demorgan_plus_and_to_xor(i32 %a, i32 %b) { +; CHECK-LABEL: @demorgan_plus_and_to_xor( +; CHECK-NEXT: [[NOT:%.*]] = xor i32 %b, %a +; CHECK-NEXT: ret i32 [[NOT]] +; + %or = or i32 %b, %a + %notor = xor i32 %or, -1 + %and = and i32 %b, %a + %or2 = or i32 %and, %notor + %not = xor i32 %or2, -1 + ret i32 %not +} + +define <4 x i32> @demorgan_plus_and_to_xor_vec(<4 x i32> %a, <4 x i32> %b) { +; CHECK-LABEL: @demorgan_plus_and_to_xor_vec( +; CHECK-NEXT: [[NOT:%.*]] = xor <4 x i32> %a, %b +; CHECK-NEXT: ret <4 x i32> [[NOT]] +; + %or = or <4 x i32> %a, %b + %notor = xor <4 x i32> %or, < i32 -1, i32 -1, i32 -1, i32 -1 > + %and = and <4 x i32> %a, %b + %or2 = or <4 x i32> %and, %notor + %not = xor <4 x i32> %or2, < i32 -1, i32 -1, i32 -1, i32 -1 > + ret <4 x i32> %not } diff --git a/test/Transforms/InstCombine/and.ll b/test/Transforms/InstCombine/and.ll index 9a4d1e5758b3..a2715c12fa88 100644 --- a/test/Transforms/InstCombine/and.ll +++ b/test/Transforms/InstCombine/and.ll @@ -613,3 +613,31 @@ final: %value = and <2 x i32> %A, <i32 123, i32 333> ret <2 x i32> %value } + +define i32 @test42(i32 %a, i32 %c, i32 %d) { +; CHECK-LABEL: @test42( +; CHECK-NEXT: [[FORCE:%.*]] = mul i32 [[C:%.*]], [[D:%.*]] +; CHECK-NEXT: [[AND:%.*]] = and i32 [[FORCE]], [[A:%.*]] +; CHECK-NEXT: ret i32 [[AND]] +; + %force = mul i32 %c, %d ; forces the complexity sorting + %or = or i32 %a, %force + %nota = xor i32 %a, -1 + %xor = xor i32 %nota, %force + %and = and i32 %xor, %or + ret i32 %and +} + +define i32 @test43(i32 %a, i32 %c, i32 %d) { +; CHECK-LABEL: @test43( +; CHECK-NEXT: [[FORCE:%.*]] = mul i32 [[C:%.*]], [[D:%.*]] +; CHECK-NEXT: [[AND:%.*]] = and i32 [[FORCE]], [[A:%.*]] +; CHECK-NEXT: ret i32 [[AND]] +; + %force = mul i32 %c, %d ; forces the complexity sorting + %or = or i32 %a, %force + %nota = xor i32 %a, -1 + %xor = xor i32 %nota, %force + %and = and i32 %or, %xor + ret i32 %and +} diff --git a/test/Transforms/InstCombine/apint-shift.ll b/test/Transforms/InstCombine/apint-shift.ll index f339de35d77c..679a87a7efbc 100644 --- a/test/Transforms/InstCombine/apint-shift.ll +++ b/test/Transforms/InstCombine/apint-shift.ll @@ -287,13 +287,10 @@ define i47 @test12(i47 %X) { ret i47 %sh2 } -; FIXME: Same as above with vectors. - define <2 x i47> @test12_splat_vec(<2 x i47> %X) { ; CHECK-LABEL: @test12_splat_vec( -; CHECK-NEXT: [[SH1:%.*]] = ashr <2 x i47> %X, <i47 8, i47 8> -; CHECK-NEXT: [[SH2:%.*]] = shl nsw <2 x i47> [[SH1]], <i47 8, i47 8> -; CHECK-NEXT: ret <2 x i47> [[SH2]] +; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i47> %X, <i47 -256, i47 -256> +; CHECK-NEXT: ret <2 x i47> [[TMP1]] ; %sh1 = ashr <2 x i47> %X, <i47 8, i47 8> %sh2 = shl <2 x i47> %sh1, <i47 8, i47 8> diff --git a/test/Transforms/InstCombine/debuginfo-dce.ll b/test/Transforms/InstCombine/debuginfo-dce.ll index e23aef7334d5..58e9d7d767e9 100644 --- a/test/Transforms/InstCombine/debuginfo-dce.ll +++ b/test/Transforms/InstCombine/debuginfo-dce.ll @@ -23,7 +23,6 @@ target triple = "x86_64-apple-macosx10.12.0" %struct.entry = type { %struct.entry* } -; Function Attrs: nounwind ssp uwtable define void @salvage_load(%struct.entry** %queue) local_unnamed_addr #0 !dbg !14 { entry: %im_not_dead = alloca %struct.entry* @@ -38,7 +37,6 @@ entry: ret void, !dbg !21 } -; Function Attrs: nounwind ssp uwtable define void @salvage_bitcast(%struct.entry* %queue) local_unnamed_addr #0 !dbg !14 { entry: %im_not_dead = alloca i8* @@ -53,24 +51,54 @@ entry: ret void, !dbg !21 } -; Function Attrs: nounwind ssp uwtable -define void @salvage_gep(%struct.entry* %queue, %struct.entry* %end) local_unnamed_addr #0 !dbg !14 { +define void @salvage_gep0(%struct.entry* %queue, %struct.entry* %end) local_unnamed_addr #0 !dbg !14 { entry: %im_not_dead = alloca %struct.entry** %0 = getelementptr inbounds %struct.entry, %struct.entry* %queue, i32 -1, i32 0, !dbg !19 %1 = getelementptr inbounds %struct.entry, %struct.entry* %queue, i32 -1, i32 0, !dbg !19 call void @llvm.dbg.value(metadata %struct.entry** %1, i64 0, metadata !18, metadata !20), !dbg !19 -; CHECK: define void @salvage_gep +; CHECK: define void @salvage_gep0 ; CHECK-NEXT: entry: ; CHECK-NEXT: call void @llvm.dbg.value(metadata %struct.entry* %queue, i64 0, -; CHECK-SAME: metadata ![[GEP_EXPR:[0-9]+]]) +; CHECK-SAME: metadata ![[GEP0_EXPR:[0-9]+]]) + store %struct.entry** %1, %struct.entry*** %im_not_dead, align 8 + ret void, !dbg !21 +} + +define void @salvage_gep1(%struct.entry* %queue, %struct.entry* %end) local_unnamed_addr #0 !dbg !14 { +entry: + %im_not_dead = alloca %struct.entry** + %0 = getelementptr inbounds %struct.entry, %struct.entry* %queue, i32 -1, i32 0, !dbg !19 + %1 = getelementptr inbounds %struct.entry, %struct.entry* %queue, i32 -1, i32 0, !dbg !19 + call void @llvm.dbg.value(metadata %struct.entry** %1, i64 0, metadata !18, metadata !DIExpression(DW_OP_LLVM_fragment, 0, 32)), !dbg !19 +; CHECK: define void @salvage_gep1 +; CHECK-NEXT: entry: +; CHECK-NEXT: call void @llvm.dbg.value(metadata %struct.entry* %queue, i64 0, +; CHECK-SAME: metadata ![[GEP1_EXPR:[0-9]+]]) + store %struct.entry** %1, %struct.entry*** %im_not_dead, align 8 + ret void, !dbg !21 +} + +define void @salvage_gep2(%struct.entry* %queue, %struct.entry* %end) local_unnamed_addr #0 !dbg !14 { +entry: + %im_not_dead = alloca %struct.entry** + %0 = getelementptr inbounds %struct.entry, %struct.entry* %queue, i32 -1, i32 0, !dbg !19 + %1 = getelementptr inbounds %struct.entry, %struct.entry* %queue, i32 -1, i32 0, !dbg !19 + call void @llvm.dbg.value(metadata %struct.entry** %1, i64 0, metadata !18, metadata !DIExpression(DW_OP_stack_value)), !dbg !19 +; CHECK: define void @salvage_gep2 +; CHECK-NEXT: entry: +; CHECK-NEXT: call void @llvm.dbg.value(metadata %struct.entry* %queue, i64 0, +; CHECK-SAME: metadata ![[GEP2_EXPR:[0-9]+]]) store %struct.entry** %1, %struct.entry*** %im_not_dead, align 8 ret void, !dbg !21 } ; CHECK: ![[LOAD_EXPR]] = !DIExpression(DW_OP_deref, DW_OP_plus, 0) ; CHECK: ![[BITCAST_EXPR]] = !DIExpression(DW_OP_plus, 0) -; CHECK: ![[GEP_EXPR]] = !DIExpression(DW_OP_minus, 8, DW_OP_plus, 0) +; CHECK: ![[GEP0_EXPR]] = !DIExpression(DW_OP_minus, 8, DW_OP_plus, 0, DW_OP_stack_value) +; CHECK: ![[GEP1_EXPR]] = !DIExpression(DW_OP_minus, 8, DW_OP_stack_value, +; CHECK-SAME: DW_OP_LLVM_fragment, 0, 32) +; CHECK: ![[GEP2_EXPR]] = !DIExpression(DW_OP_minus, 8, DW_OP_stack_value) ; Function Attrs: nounwind readnone declare void @llvm.dbg.value(metadata, i64, metadata, metadata) #1 diff --git a/test/Transforms/InstCombine/fsub.ll b/test/Transforms/InstCombine/fsub.ll index af2fadd2867b..6b62f5dd7e38 100644 --- a/test/Transforms/InstCombine/fsub.ll +++ b/test/Transforms/InstCombine/fsub.ll @@ -21,3 +21,47 @@ define double @test2(double %x, double %y) nounwind { ret double %t2 } + +; CHECK-LABEL: @fsub_undef( +; CHECK: %sub = fsub float %val, undef +define float @fsub_undef(float %val) { +bb: + %sub = fsub float %val, undef + ret float %sub +} + +; XXX - Why doesn't this fold to undef? +; CHECK-LABEL: @fsub_fast_undef( +; CHCK: %sub = fsub fast float %val, undef +define float @fsub_fast_undef(float %val) { +bb: + %sub = fsub fast float %val, undef + ret float %sub +} + +; CHECK-LABEL: @fneg_undef( +; CHECK: ret float fsub (float -0.000000e+00, float undef) +define float @fneg_undef(float %val) { +bb: + %sub = fsub float -0.0, undef + ret float %sub +} + +; CHECK-LABEL: @fneg_fast_undef( +; CHECK: ret float fsub (float -0.000000e+00, float undef) +define float @fneg_fast_undef(float %val) { +bb: + %sub = fsub fast float -0.0, undef + ret float %sub +} + +; This folds to a constant expression, which produced 0 instructions +; contrary to the expected one for negation. +; CHECK-LABEL: @inconsistent_numbers_fsub_undef( +; CHECK: ret float fsub (float -0.000000e+00, float undef) +define float @inconsistent_numbers_fsub_undef(float %val) { +bb: + %sub0 = fsub fast float %val, undef + %sub1 = fsub fast float %sub0, %val + ret float %sub1 +} diff --git a/test/Transforms/InstCombine/intrinsics.ll b/test/Transforms/InstCombine/intrinsics.ll index e8f5ddd329ff..b9e208440581 100644 --- a/test/Transforms/InstCombine/intrinsics.ll +++ b/test/Transforms/InstCombine/intrinsics.ll @@ -281,6 +281,19 @@ define i32 @cttz(i32 %a) { ret i32 %count } +define i1 @cttz_knownbits(i32 %arg) { +; CHECK-LABEL: @cttz_knownbits( +; CHECK-NEXT: [[OR:%.*]] = or i32 [[ARG:%.*]], 4 +; CHECK-NEXT: [[CNT:%.*]] = call i32 @llvm.cttz.i32(i32 [[OR]], i1 true) #0 +; CHECK-NEXT: [[RES:%.*]] = icmp eq i32 [[CNT]], 4 +; CHECK-NEXT: ret i1 [[RES]] +; + %or = or i32 %arg, 4 + %cnt = call i32 @llvm.cttz.i32(i32 %or, i1 true) nounwind readnone + %res = icmp eq i32 %cnt, 4 + ret i1 %res +} + define i8 @ctlz(i8 %a) { ; CHECK-LABEL: @ctlz( ; CHECK-NEXT: ret i8 2 @@ -291,6 +304,19 @@ define i8 @ctlz(i8 %a) { ret i8 %count } +define i1 @ctlz_knownbits(i8 %arg) { +; CHECK-LABEL: @ctlz_knownbits( +; CHECK-NEXT: [[OR:%.*]] = or i8 [[ARG:%.*]], 32 +; CHECK-NEXT: [[CNT:%.*]] = call i8 @llvm.ctlz.i8(i8 [[OR]], i1 true) #0 +; CHECK-NEXT: [[RES:%.*]] = icmp eq i8 [[CNT]], 4 +; CHECK-NEXT: ret i1 [[RES]] +; + %or = or i8 %arg, 32 + %cnt = call i8 @llvm.ctlz.i8(i8 %or, i1 true) nounwind readnone + %res = icmp eq i8 %cnt, 4 + ret i1 %res +} + define void @cmp.simplify(i32 %a, i32 %b, i1* %c) { %lz = tail call i32 @llvm.ctlz.i32(i32 %a, i1 false) nounwind readnone %lz.cmp = icmp eq i32 %lz, 32 diff --git a/test/Transforms/InstCombine/memset-1.ll b/test/Transforms/InstCombine/memset-1.ll index 7310e5f4faf8..86f3afdef8dc 100644 --- a/test/Transforms/InstCombine/memset-1.ll +++ b/test/Transforms/InstCombine/memset-1.ll @@ -26,6 +26,15 @@ define i8* @pr25892_lite(i32 %size) #0 { ; CHECK-NEXT: ret i8* %calloc } +; This should not create a calloc and not crash the compiler. +; CHECK-LABEL: @notmalloc_memset +; CHECK-NOT: @calloc +define i8* @notmalloc_memset(i32 %size, i8*(i32)* %notmalloc) { + %call1 = call i8* %notmalloc(i32 %size) #1 + %call2 = call i8* @memset(i8* %call1, i32 0, i32 %size) #1 + ret i8* %call2 +} + ; FIXME: memset(malloc(x), 0, x) -> calloc(1, x) ; This doesn't fire currently because the malloc has more than one use. diff --git a/test/Transforms/InstCombine/minmax-fold.ll b/test/Transforms/InstCombine/minmax-fold.ll index 19a7341fdc28..f0e56426a8da 100644 --- a/test/Transforms/InstCombine/minmax-fold.ll +++ b/test/Transforms/InstCombine/minmax-fold.ll @@ -280,14 +280,10 @@ define i32 @test72(i32 %x) { ret i32 %retval } -; FIXME - vector neglect: FoldAndOfICmps() / FoldOrOfICmps() - define <2 x i32> @test72vec(<2 x i32> %x) { ; CHECK-LABEL: @test72vec( -; CHECK-NEXT: [[TMP1:%.*]] = icmp slt <2 x i32> %x, <i32 92, i32 92> ; CHECK-NEXT: [[TMP2:%.*]] = icmp slt <2 x i32> %x, <i32 11, i32 11> -; CHECK-NEXT: [[TMP3:%.*]] = and <2 x i1> [[TMP1]], [[TMP2]] -; CHECK-NEXT: [[RETVAL:%.*]] = select <2 x i1> [[TMP3]], <2 x i32> %x, <2 x i32> <i32 11, i32 11> +; CHECK-NEXT: [[RETVAL:%.*]] = select <2 x i1> [[TMP2]], <2 x i32> %x, <2 x i32> <i32 11, i32 11> ; CHECK-NEXT: ret <2 x i32> [[RETVAL]] ; %cmp = icmp sgt <2 x i32> %x, <i32 92, i32 92> diff --git a/test/Transforms/InstCombine/or-to-xor.ll b/test/Transforms/InstCombine/or-to-xor.ll deleted file mode 100644 index 84567906f843..000000000000 --- a/test/Transforms/InstCombine/or-to-xor.ll +++ /dev/null @@ -1,55 +0,0 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py -; RUN: opt < %s -instcombine -S | FileCheck %s - -define i32 @func1(i32 %a, i32 %b) { -; CHECK-LABEL: @func1( -; CHECK-NEXT: [[T2:%.*]] = xor i32 %a, %b -; CHECK-NEXT: ret i32 [[T2]] -; - %b_not = xor i32 %b, -1 - %t0 = and i32 %a, %b_not - %a_not = xor i32 %a, -1 - %t1 = and i32 %a_not, %b - %t2 = or i32 %t0, %t1 - ret i32 %t2 -} - -define i32 @func2(i32 %a, i32 %b) { -; CHECK-LABEL: @func2( -; CHECK-NEXT: [[T2:%.*]] = xor i32 %a, %b -; CHECK-NEXT: ret i32 [[T2]] -; - %b_not = xor i32 %b, -1 - %t0 = and i32 %b_not, %a - %a_not = xor i32 %a, -1 - %t1 = and i32 %a_not, %b - %t2 = or i32 %t0, %t1 - ret i32 %t2 -} - -define i32 @func3(i32 %a, i32 %b) { -; CHECK-LABEL: @func3( -; CHECK-NEXT: [[T2:%.*]] = xor i32 %a, %b -; CHECK-NEXT: ret i32 [[T2]] -; - %b_not = xor i32 %b, -1 - %t0 = and i32 %a, %b_not - %a_not = xor i32 %a, -1 - %t1 = and i32 %b, %a_not - %t2 = or i32 %t0, %t1 - ret i32 %t2 -} - -define i32 @func4(i32 %a, i32 %b) { -; CHECK-LABEL: @func4( -; CHECK-NEXT: [[T2:%.*]] = xor i32 %a, %b -; CHECK-NEXT: ret i32 [[T2]] -; - %b_not = xor i32 %b, -1 - %t0 = and i32 %b_not, %a - %a_not = xor i32 %a, -1 - %t1 = and i32 %b, %a_not - %t2 = or i32 %t0, %t1 - ret i32 %t2 -} - diff --git a/test/Transforms/InstCombine/or.ll b/test/Transforms/InstCombine/or.ll index 41e6d2d1f827..9ae5eafdfccf 100644 --- a/test/Transforms/InstCombine/or.ll +++ b/test/Transforms/InstCombine/or.ll @@ -619,59 +619,6 @@ define i32 @test42_commuted_xor(i32 %a, i32 %b) { ret i32 %or } -; (A & ~B) | (A ^ B) -> A ^ B - -define i32 @test43(i32 %a, i32 %b) { -; CHECK-LABEL: @test43( -; CHECK-NEXT: [[OR:%.*]] = xor i32 %a, %b -; CHECK-NEXT: ret i32 [[OR]] -; - %neg = xor i32 %b, -1 - %and = and i32 %a, %neg - %xor = xor i32 %a, %b - %or = or i32 %and, %xor - ret i32 %or -} - -define i32 @test43_commuted_and(i32 %a, i32 %b) { -; CHECK-LABEL: @test43_commuted_and( -; CHECK-NEXT: [[OR:%.*]] = xor i32 %a, %b -; CHECK-NEXT: ret i32 [[OR]] -; - %neg = xor i32 %b, -1 - %and = and i32 %neg, %a - %xor = xor i32 %a, %b - %or = or i32 %and, %xor - ret i32 %or -} - -; Commute operands of the 'or'. -; (A ^ B) | (A & ~B) -> A ^ B - -define i32 @test44(i32 %a, i32 %b) { -; CHECK-LABEL: @test44( -; CHECK-NEXT: [[OR:%.*]] = xor i32 %a, %b -; CHECK-NEXT: ret i32 [[OR]] -; - %xor = xor i32 %a, %b - %neg = xor i32 %b, -1 - %and = and i32 %a, %neg - %or = or i32 %xor, %and - ret i32 %or -} - -define i32 @test44_commuted_and(i32 %a, i32 %b) { -; CHECK-LABEL: @test44_commuted_and( -; CHECK-NEXT: [[OR:%.*]] = xor i32 %a, %b -; CHECK-NEXT: ret i32 [[OR]] -; - %xor = xor i32 %a, %b - %neg = xor i32 %b, -1 - %and = and i32 %neg, %a - %or = or i32 %xor, %and - ret i32 %or -} - define i32 @test45(i32 %x, i32 %y, i32 %z) { ; CHECK-LABEL: @test45( ; CHECK-NEXT: [[TMP1:%.*]] = and i32 %x, %z diff --git a/test/Transforms/InstCombine/pr17827.ll b/test/Transforms/InstCombine/pr17827.ll index ada6edab69c6..c9cbf764d7f5 100644 --- a/test/Transforms/InstCombine/pr17827.ll +++ b/test/Transforms/InstCombine/pr17827.ll @@ -52,9 +52,7 @@ define i1 @test_shift_and_cmp_changed1(i8 %p, i8 %q) { define <2 x i1> @test_shift_and_cmp_changed1_vec(<2 x i8> %p, <2 x i8> %q) { ; CHECK-LABEL: @test_shift_and_cmp_changed1_vec( ; CHECK-NEXT: [[ANDP:%.*]] = and <2 x i8> %p, <i8 6, i8 6> -; CHECK-NEXT: [[ANDQ:%.*]] = and <2 x i8> %q, <i8 8, i8 8> -; CHECK-NEXT: [[OR:%.*]] = or <2 x i8> [[ANDQ]], [[ANDP]] -; CHECK-NEXT: [[SHL:%.*]] = shl <2 x i8> [[OR]], <i8 5, i8 5> +; CHECK-NEXT: [[SHL:%.*]] = shl nuw <2 x i8> [[ANDP]], <i8 5, i8 5> ; CHECK-NEXT: [[CMP:%.*]] = icmp slt <2 x i8> [[SHL]], <i8 32, i8 32> ; CHECK-NEXT: ret <2 x i1> [[CMP]] ; diff --git a/test/Transforms/InstCombine/shift.ll b/test/Transforms/InstCombine/shift.ll index d5f489280a03..ce8e2fcd38b9 100644 --- a/test/Transforms/InstCombine/shift.ll +++ b/test/Transforms/InstCombine/shift.ll @@ -1049,12 +1049,11 @@ define i8 @test53_no_nuw(i8 %x) { } ; (X << C1) >>u C2 --> X << (C1 - C2) & (-1 >> C2) -; FIXME: Demanded bits should change the mask constant as it does for the scalar case. define <2 x i8> @test53_no_nuw_splat_vec(<2 x i8> %x) { ; CHECK-LABEL: @test53_no_nuw_splat_vec( ; CHECK-NEXT: [[TMP1:%.*]] = shl <2 x i8> %x, <i8 2, i8 2> -; CHECK-NEXT: [[B:%.*]] = and <2 x i8> [[TMP1]], <i8 127, i8 127> +; CHECK-NEXT: [[B:%.*]] = and <2 x i8> [[TMP1]], <i8 124, i8 124> ; CHECK-NEXT: ret <2 x i8> [[B]] ; %A = shl <2 x i8> %x, <i8 3, i8 3> @@ -1074,6 +1073,17 @@ define i32 @test54(i32 %x) { ret i32 %and } +define <2 x i32> @test54_splat_vec(<2 x i32> %x) { +; CHECK-LABEL: @test54_splat_vec( +; CHECK-NEXT: [[TMP1:%.*]] = shl <2 x i32> %x, <i32 3, i32 3> +; CHECK-NEXT: [[AND:%.*]] = and <2 x i32> [[TMP1]], <i32 16, i32 16> +; CHECK-NEXT: ret <2 x i32> [[AND]] +; + %shr2 = lshr <2 x i32> %x, <i32 1, i32 1> + %shl = shl <2 x i32> %shr2, <i32 4, i32 4> + %and = and <2 x i32> %shl, <i32 16, i32 16> + ret <2 x i32> %and +} define i32 @test55(i32 %x) { ; CHECK-LABEL: @test55( @@ -1100,7 +1110,6 @@ define i32 @test56(i32 %x) { ret i32 %or } - define i32 @test57(i32 %x) { ; CHECK-LABEL: @test57( ; CHECK-NEXT: [[SHR1:%.*]] = lshr i32 %x, 1 @@ -1114,7 +1123,6 @@ define i32 @test57(i32 %x) { ret i32 %or } - define i32 @test58(i32 %x) { ; CHECK-LABEL: @test58( ; CHECK-NEXT: [[TMP1:%.*]] = ashr i32 %x, 3 @@ -1127,6 +1135,17 @@ define i32 @test58(i32 %x) { ret i32 %or } +define <2 x i32> @test58_splat_vec(<2 x i32> %x) { +; CHECK-LABEL: @test58_splat_vec( +; CHECK-NEXT: [[TMP1:%.*]] = ashr <2 x i32> %x, <i32 3, i32 3> +; CHECK-NEXT: [[OR:%.*]] = or <2 x i32> [[TMP1]], <i32 1, i32 1> +; CHECK-NEXT: ret <2 x i32> [[OR]] +; + %shr = ashr <2 x i32> %x, <i32 4, i32 4> + %shl = shl <2 x i32> %shr, <i32 1, i32 1> + %or = or <2 x i32> %shl, <i32 1, i32 1> + ret <2 x i32> %or +} define i32 @test59(i32 %x) { ; CHECK-LABEL: @test59( @@ -1257,8 +1276,7 @@ define i64 @test_64(i32 %t) { define <2 x i64> @test_64_splat_vec(<2 x i32> %t) { ; CHECK-LABEL: @test_64_splat_vec( -; CHECK-NEXT: [[AND:%.*]] = and <2 x i32> %t, <i32 16777215, i32 16777215> -; CHECK-NEXT: [[TMP1:%.*]] = shl nuw <2 x i32> [[AND]], <i32 8, i32 8> +; CHECK-NEXT: [[TMP1:%.*]] = shl <2 x i32> %t, <i32 8, i32 8> ; CHECK-NEXT: [[SHL:%.*]] = zext <2 x i32> [[TMP1]] to <2 x i64> ; CHECK-NEXT: ret <2 x i64> [[SHL]] ; diff --git a/test/Transforms/InstCombine/xor2.ll b/test/Transforms/InstCombine/xor2.ll index 79e62723f143..f817ac5ca40c 100644 --- a/test/Transforms/InstCombine/xor2.ll +++ b/test/Transforms/InstCombine/xor2.ll @@ -191,6 +191,81 @@ define i32 @test11(i32 %A, i32 %B) { ret i32 %and } +define i32 @test11b(i32 %A, i32 %B) { +; CHECK-LABEL: @test11b( +; CHECK-NEXT: ret i32 0 +; + %xor1 = xor i32 %B, %A + %not = xor i32 %A, -1 + %xor2 = xor i32 %not, %B + %and = and i32 %xor2, %xor1 + ret i32 %and +} + +define i32 @test11c(i32 %A, i32 %B) { +; CHECK-LABEL: @test11c( +; CHECK-NEXT: [[XOR1:%.*]] = xor i32 [[A:%.*]], [[B:%.*]] +; CHECK-NEXT: [[NOT:%.*]] = xor i32 [[A]], -1 +; CHECK-NEXT: [[XOR2:%.*]] = xor i32 [[NOT]], [[B]] +; CHECK-NEXT: [[AND:%.*]] = and i32 [[XOR1]], [[XOR2]] +; CHECK-NEXT: ret i32 [[AND]] +; + %xor1 = xor i32 %A, %B + %not = xor i32 %A, -1 + %xor2 = xor i32 %not, %B + %and = and i32 %xor1, %xor2 + ret i32 %and +} + +define i32 @test11d(i32 %A, i32 %B) { +; CHECK-LABEL: @test11d( +; CHECK-NEXT: [[XOR1:%.*]] = xor i32 [[A:%.*]], [[B:%.*]] +; CHECK-NEXT: [[NOT:%.*]] = xor i32 [[A]], -1 +; CHECK-NEXT: [[XOR2:%.*]] = xor i32 [[NOT]], [[B]] +; CHECK-NEXT: [[AND:%.*]] = and i32 [[XOR2]], [[XOR1]] +; CHECK-NEXT: ret i32 [[AND]] +; + %xor1 = xor i32 %A, %B + %not = xor i32 %A, -1 + %xor2 = xor i32 %not, %B + %and = and i32 %xor2, %xor1 + ret i32 %and +} + +define i32 @test11e(i32 %A, i32 %B, i32 %C) { +; CHECK-LABEL: @test11e( +; CHECK-NEXT: [[FORCE:%.*]] = mul i32 [[B:%.*]], [[C:%.*]] +; CHECK-NEXT: [[XOR1:%.*]] = xor i32 [[FORCE]], [[A:%.*]] +; CHECK-NEXT: [[NOT:%.*]] = xor i32 [[A]], -1 +; CHECK-NEXT: [[XOR2:%.*]] = xor i32 [[FORCE]], [[NOT]] +; CHECK-NEXT: [[AND:%.*]] = and i32 [[XOR1]], [[XOR2]] +; CHECK-NEXT: ret i32 [[AND]] +; + %force = mul i32 %B, %C + %xor1 = xor i32 %force, %A + %not = xor i32 %A, -1 + %xor2 = xor i32 %force, %not + %and = and i32 %xor1, %xor2 + ret i32 %and +} + +define i32 @test11f(i32 %A, i32 %B, i32 %C) { +; CHECK-LABEL: @test11f( +; CHECK-NEXT: [[FORCE:%.*]] = mul i32 [[B:%.*]], [[C:%.*]] +; CHECK-NEXT: [[XOR1:%.*]] = xor i32 [[FORCE]], [[A:%.*]] +; CHECK-NEXT: [[NOT:%.*]] = xor i32 [[A]], -1 +; CHECK-NEXT: [[XOR2:%.*]] = xor i32 [[FORCE]], [[NOT]] +; CHECK-NEXT: [[AND:%.*]] = and i32 [[XOR2]], [[XOR1]] +; CHECK-NEXT: ret i32 [[AND]] +; + %force = mul i32 %B, %C + %xor1 = xor i32 %force, %A + %not = xor i32 %A, -1 + %xor2 = xor i32 %force, %not + %and = and i32 %xor2, %xor1 + ret i32 %and +} + define i32 @test12(i32 %a, i32 %b) { ; CHECK-LABEL: @test12( ; CHECK-NEXT: [[TMP1:%.*]] = and i32 %a, %b |