aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2009-10-11 21:29:45 +0000
committerChris Lattner <sabre@nondot.org>2009-10-11 21:29:45 +0000
commitd2c58366d8d3205f212f026fe373641eebccaebb (patch)
treef29e1be9204f79476578dfd4aa8f30d0a3a57145
parent0036e3a4698d947c455e755faafe5c83a9c3b9c6 (diff)
generalize a transformation even more: we don't care whether the
input the the mul is a zext from bool, just that it is all zeros other than the low bit. This fixes some phase ordering issues that would cause us to miss some xforms in mul.ll when the worklist is visited differently. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@83794 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Transforms/Scalar/InstructionCombining.cpp22
-rw-r--r--test/Transforms/InstCombine/mul.ll7
2 files changed, 17 insertions, 12 deletions
diff --git a/lib/Transforms/Scalar/InstructionCombining.cpp b/lib/Transforms/Scalar/InstructionCombining.cpp
index e9ffb73030..549c57633a 100644
--- a/lib/Transforms/Scalar/InstructionCombining.cpp
+++ b/lib/Transforms/Scalar/InstructionCombining.cpp
@@ -2781,20 +2781,18 @@ Instruction *InstCombiner::visitMul(BinaryOperator &I) {
// If one of the operands of the multiply is a cast from a boolean value, then
// we know the bool is either zero or one, so this is a 'masking' multiply.
- // See if we can simplify things based on how the boolean was originally
- // formed.
- {
- Value *BoolCast = 0, *OtherOp = 0;
- if (ZExtInst *CI = dyn_cast<ZExtInst>(Op0))
- if (CI->getOperand(0)->getType() == Type::getInt1Ty(*Context))
- BoolCast = CI, OtherOp = I.getOperand(1);
- if (!BoolCast)
- if (ZExtInst *CI = dyn_cast<ZExtInst>(I.getOperand(1)))
- if (CI->getOperand(0)->getType() == Type::getInt1Ty(*Context))
- BoolCast = CI, OtherOp = Op0;
+ // X * Y (where Y is 0 or 1) -> X & (0-Y)
+ if (!isa<VectorType>(I.getType())) {
+ // -2 is "-1 << 1" so it is all bits set except the low one.
+ APInt Negative2(I.getType()->getPrimitiveSizeInBits(), -2, true);
+ Value *BoolCast = 0, *OtherOp = 0;
+ if (MaskedValueIsZero(Op0, Negative2))
+ BoolCast = Op0, OtherOp = I.getOperand(1);
+ else if (MaskedValueIsZero(I.getOperand(1), Negative2))
+ BoolCast = I.getOperand(1), OtherOp = Op0;
+
if (BoolCast) {
- // X * Y (where Y is 0 or 1) -> X & (0-Y)
Value *V = Builder->CreateSub(Constant::getNullValue(I.getType()),
BoolCast, "tmp");
return BinaryOperator::CreateAnd(V, OtherOp);
diff --git a/test/Transforms/InstCombine/mul.ll b/test/Transforms/InstCombine/mul.ll
index d8e623c483..53a56434ae 100644
--- a/test/Transforms/InstCombine/mul.ll
+++ b/test/Transforms/InstCombine/mul.ll
@@ -105,5 +105,12 @@ define i32 @test16(i32 %b, i1 %c) {
ret i32 %e
}
+; X * Y (when Y is 0 or 1) --> x & (0-Y)
+define i32 @test17(i32 %a, i32 %b) {
+ %a.lobit = lshr i32 %a, 31
+ %e = mul i32 %a.lobit, %b
+ ret i32 %e
+}
+