diff options
author | Chris Lattner <sabre@nondot.org> | 2009-10-11 22:22:13 +0000 |
---|---|---|
committer | Chris Lattner <sabre@nondot.org> | 2009-10-11 22:22:13 +0000 |
commit | d08831499818771527e2da55eedd0bdfbdc37edb (patch) | |
tree | 158336f18267c0ef4bd47f7972233fbf55d11c72 | |
parent | 7acdf1de0652ea0233825fc32a33013a7a51df19 (diff) |
teach instcombine to simplify xor's harder, catching the
new testcase.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@83799 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/Transforms/Scalar/InstructionCombining.cpp | 27 | ||||
-rw-r--r-- | test/Transforms/InstCombine/xor2.ll | 11 |
2 files changed, 38 insertions, 0 deletions
diff --git a/lib/Transforms/Scalar/InstructionCombining.cpp b/lib/Transforms/Scalar/InstructionCombining.cpp index 6d166664f8..dcb65a8ed9 100644 --- a/lib/Transforms/Scalar/InstructionCombining.cpp +++ b/lib/Transforms/Scalar/InstructionCombining.cpp @@ -1047,6 +1047,33 @@ Value *InstCombiner::SimplifyDemandedUseBits(Value *V, APInt DemandedMask, if (ShrinkDemandedConstant(I, 1, DemandedMask)) return I; + // If our LHS is an 'and' and if it has one use, and if any of the bits we + // are flipping are known to be set, then the xor is just resetting those + // bits to zero. We can just knock out bits from the 'and' and the 'xor', + // simplifying both of them. + if (Instruction *LHSInst = dyn_cast<Instruction>(I->getOperand(0))) + if (LHSInst->getOpcode() == Instruction::And && LHSInst->hasOneUse() && + isa<ConstantInt>(I->getOperand(1)) && + isa<ConstantInt>(LHSInst->getOperand(1)) && + (LHSKnownOne & RHSKnownOne & DemandedMask) != 0) { + ConstantInt *AndRHS = cast<ConstantInt>(LHSInst->getOperand(1)); + ConstantInt *XorRHS = cast<ConstantInt>(I->getOperand(1)); + APInt NewMask = ~(LHSKnownOne & RHSKnownOne & DemandedMask); + + Constant *AndC = + ConstantInt::get(I->getType(), NewMask & AndRHS->getValue()); + Instruction *NewAnd = + BinaryOperator::CreateAnd(I->getOperand(0), AndC, "tmp"); + InsertNewInstBefore(NewAnd, *I); + + Constant *XorC = + ConstantInt::get(I->getType(), NewMask & XorRHS->getValue()); + Instruction *NewXor = + BinaryOperator::CreateXor(NewAnd, XorC, "tmp"); + return InsertNewInstBefore(NewXor, *I); + } + + RHSKnownZero = KnownZeroOut; RHSKnownOne = KnownOneOut; break; diff --git a/test/Transforms/InstCombine/xor2.ll b/test/Transforms/InstCombine/xor2.ll index 94a464c8dc..23a9915813 100644 --- a/test/Transforms/InstCombine/xor2.ll +++ b/test/Transforms/InstCombine/xor2.ll @@ -30,3 +30,14 @@ define i32 @test2(i32 %tmp1) { %ov110 = xor i32 %ov3, 153 ret i32 %ov110 } + +define i32 @test3(i32 %tmp1) { +; CHECK: @test3 +; CHECK-NEXT: or i32 %tmp1, 8 +; CHECK-NEXT: and i32 +; CHECK-NEXT: ret i32 + %ovm = or i32 %tmp1, 145 + %ov31 = and i32 %ovm, 177 + %ov110 = xor i32 %ov31, 153 + ret i32 %ov110 +} |