summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--llvm/lib/Transforms/Scalar/InstructionCombining.cpp46
-rw-r--r--llvm/test/Transforms/InstCombine/icmp.ll10
-rw-r--r--llvm/test/Transforms/InstCombine/mul.ll11
3 files changed, 34 insertions, 33 deletions
diff --git a/llvm/lib/Transforms/Scalar/InstructionCombining.cpp b/llvm/lib/Transforms/Scalar/InstructionCombining.cpp
index 06a5660f72e..e9ffb730305 100644
--- a/llvm/lib/Transforms/Scalar/InstructionCombining.cpp
+++ b/llvm/lib/Transforms/Scalar/InstructionCombining.cpp
@@ -2783,39 +2783,21 @@ Instruction *InstCombiner::visitMul(BinaryOperator &I) {
// 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.
- CastInst *BoolCast = 0;
- if (ZExtInst *CI = dyn_cast<ZExtInst>(Op0))
- if (CI->getOperand(0)->getType() == Type::getInt1Ty(*Context))
- BoolCast = CI;
- if (!BoolCast)
- if (ZExtInst *CI = dyn_cast<ZExtInst>(I.getOperand(1)))
+ {
+ Value *BoolCast = 0, *OtherOp = 0;
+ if (ZExtInst *CI = dyn_cast<ZExtInst>(Op0))
if (CI->getOperand(0)->getType() == Type::getInt1Ty(*Context))
- BoolCast = CI;
- if (BoolCast) {
- if (ICmpInst *SCI = dyn_cast<ICmpInst>(BoolCast->getOperand(0))) {
- Value *SCIOp0 = SCI->getOperand(0), *SCIOp1 = SCI->getOperand(1);
- const Type *SCOpTy = SCIOp0->getType();
- bool TIS = false;
-
- // If the icmp is true iff the sign bit of X is set, then convert this
- // multiply into a shift/and combination.
- if (isa<ConstantInt>(SCIOp1) &&
- isSignBitCheck(SCI->getPredicate(), cast<ConstantInt>(SCIOp1), TIS) &&
- TIS) {
- // Shift the X value right to turn it into "all signbits".
- Constant *Amt = ConstantInt::get(SCIOp0->getType(),
- SCOpTy->getPrimitiveSizeInBits()-1);
- Value *V = Builder->CreateAShr(SCIOp0, Amt,
- BoolCast->getOperand(0)->getName()+".mask");
-
- // If the multiply type is not the same as the source type, sign extend
- // or truncate to the multiply type.
- if (I.getType() != V->getType())
- V = Builder->CreateIntCast(V, I.getType(), true);
-
- Value *OtherOp = Op0 == BoolCast ? I.getOperand(1) : Op0;
- return BinaryOperator::CreateAnd(V, OtherOp);
- }
+ 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;
+
+ 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/llvm/test/Transforms/InstCombine/icmp.ll b/llvm/test/Transforms/InstCombine/icmp.ll
index 3b6f8c59ce6..64e88c9ae86 100644
--- a/llvm/test/Transforms/InstCombine/icmp.ll
+++ b/llvm/test/Transforms/InstCombine/icmp.ll
@@ -33,4 +33,12 @@ define <2 x i1> @test5(<2 x i64> %x) {
entry:
%V = icmp eq <2 x i64> %x, undef
ret <2 x i1> %V
-} \ No newline at end of file
+}
+
+define i32 @test6(i32 %a, i32 %b) {
+ %c = icmp sle i32 %a, -1
+ %d = zext i1 %c to i32
+ %e = sub i32 0, %d
+ %f = and i32 %e, %b
+ ret i32 %f
+}
diff --git a/llvm/test/Transforms/InstCombine/mul.ll b/llvm/test/Transforms/InstCombine/mul.ll
index e127efb9dcf..d8e623c4834 100644
--- a/llvm/test/Transforms/InstCombine/mul.ll
+++ b/llvm/test/Transforms/InstCombine/mul.ll
@@ -96,3 +96,14 @@ entry:
%m = mul i32 %shl, %A
ret i32 %m
}
+
+; X * Y (when Y is 0 or 1) --> x & (0-Y)
+define i32 @test16(i32 %b, i1 %c) {
+ %d = zext i1 %c to i32 ; <i32> [#uses=1]
+ ; e = b & (a >> 31)
+ %e = mul i32 %d, %b ; <i32> [#uses=1]
+ ret i32 %e
+}
+
+
+
OpenPOWER on IntegriCloud