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
diff --git a/lib/Transforms/Scalar/InstructionCombining.cpp b/lib/Transforms/Scalar/InstructionCombining.cpp
index 6d16666..dcb65a8 100644
--- a/lib/Transforms/Scalar/InstructionCombining.cpp
+++ b/lib/Transforms/Scalar/InstructionCombining.cpp
@@ -1047,6 +1047,33 @@
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 94a464c..23a9915 100644
--- a/test/Transforms/InstCombine/xor2.ll
+++ b/test/Transforms/InstCombine/xor2.ll
@@ -30,3 +30,14 @@
%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
+}