diff --git a/lib/Transforms/Scalar/InstructionCombining.cpp b/lib/Transforms/Scalar/InstructionCombining.cpp index 8c5e1369ded..3b341247688 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(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 de1bbf41b09..161d56b40b5 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 +} +