aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/Transforms/Scalar/InstructionCombining.cpp19
-rw-r--r--test/Transforms/InstCombine/add2.ll15
2 files changed, 34 insertions, 0 deletions
diff --git a/lib/Transforms/Scalar/InstructionCombining.cpp b/lib/Transforms/Scalar/InstructionCombining.cpp
index 8c5e1369de..3b34124768 100644
--- a/lib/Transforms/Scalar/InstructionCombining.cpp
+++ b/lib/Transforms/Scalar/InstructionCombining.cpp
@@ -2503,6 +2503,25 @@ Instruction *InstCombiner::visitAdd(BinaryOperator &I) {
if (match(RHS, m_And(m_Value(), m_ConstantInt(C2))))
if (Instruction *R = AssociativeOpt(I, AddMaskingAnd(C2)))
return R;
+
+ // A+B --> A|B iff A and B have no bits set in common.
+ if (const IntegerType *IT = dyn_cast<IntegerType>(I.getType())) {
+ APInt Mask = APInt::getAllOnesValue(IT->getBitWidth());
+ APInt LHSKnownOne(IT->getBitWidth(), 0);
+ APInt LHSKnownZero(IT->getBitWidth(), 0);
+ ComputeMaskedBits(LHS, Mask, LHSKnownZero, LHSKnownOne);
+ if (LHSKnownZero != 0) {
+ APInt RHSKnownOne(IT->getBitWidth(), 0);
+ APInt RHSKnownZero(IT->getBitWidth(), 0);
+ ComputeMaskedBits(RHS, Mask, RHSKnownZero, RHSKnownOne);
+
+ // No bits in common -> bitwise or.
+ if ((LHSKnownZero|RHSKnownZero).isAllOnesValue()) {
+ cerr << "HACK\n" << *LHS << *RHS << "\n";
+ return BinaryOperator::CreateOr(LHS, RHS);
+ }
+ }
+ }
// W*X + Y*Z --> W * (X+Z) iff W == Y
if (I.getType()->isIntOrIntVector()) {
diff --git a/test/Transforms/InstCombine/add2.ll b/test/Transforms/InstCombine/add2.ll
index de1bbf41b0..161d56b40b 100644
--- a/test/Transforms/InstCombine/add2.ll
+++ b/test/Transforms/InstCombine/add2.ll
@@ -29,3 +29,18 @@ EntryBlock:
declare i32 @callee(i32)
+
+define i32 @test3(i32 %A) {
+ %B = and i32 %A, 7
+ %C = and i32 %A, 32
+ %F = add i32 %B, %C
+ ret i32 %F
+}
+
+define i32 @test4(i32 %A) {
+ %B = and i32 %A, 128
+ %C = lshr i32 %A, 30
+ %F = add i32 %B, %C
+ ret i32 %F
+}
+