aboutsummaryrefslogtreecommitdiff
path: root/test/Transforms/InstCombine
diff options
context:
space:
mode:
Diffstat (limited to 'test/Transforms/InstCombine')
-rw-r--r--test/Transforms/InstCombine/add-sitofp.ll124
-rw-r--r--test/Transforms/InstCombine/amdgcn-intrinsics.ll6
-rw-r--r--test/Transforms/InstCombine/and-or-icmps.ll4
-rw-r--r--test/Transforms/InstCombine/and-or-not.ll570
-rw-r--r--test/Transforms/InstCombine/and.ll28
-rw-r--r--test/Transforms/InstCombine/apint-shift.ll7
-rw-r--r--test/Transforms/InstCombine/debuginfo-dce.ll42
-rw-r--r--test/Transforms/InstCombine/fsub.ll44
-rw-r--r--test/Transforms/InstCombine/intrinsics.ll26
-rw-r--r--test/Transforms/InstCombine/memset-1.ll9
-rw-r--r--test/Transforms/InstCombine/minmax-fold.ll6
-rw-r--r--test/Transforms/InstCombine/or-to-xor.ll55
-rw-r--r--test/Transforms/InstCombine/or.ll53
-rw-r--r--test/Transforms/InstCombine/pr17827.ll4
-rw-r--r--test/Transforms/InstCombine/shift.ll30
-rw-r--r--test/Transforms/InstCombine/xor2.ll75
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