aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lib/Transforms/Scalar/InstructionCombining.cpp10
-rw-r--r--test/Transforms/InstCombine/2008-01-21-MulTrunc.ll11
2 files changed, 21 insertions, 0 deletions
diff --git a/lib/Transforms/Scalar/InstructionCombining.cpp b/lib/Transforms/Scalar/InstructionCombining.cpp
index 2ad592a..3e009eb 100644
--- a/lib/Transforms/Scalar/InstructionCombining.cpp
+++ b/lib/Transforms/Scalar/InstructionCombining.cpp
@@ -6512,6 +6512,15 @@ static bool CanEvaluateInDifferentType(Value *V, const IntegerType *Ty,
CanEvaluateInDifferentType(I->getOperand(1), Ty, CastOpc,
NumCastsRemoved);
+ case Instruction::Mul:
+ break;
+ // A multiply can be truncated by truncating its operands.
+ return Ty->getBitWidth() < OrigTy->getBitWidth() &&
+ CanEvaluateInDifferentType(I->getOperand(0), Ty, CastOpc,
+ NumCastsRemoved) &&
+ CanEvaluateInDifferentType(I->getOperand(1), Ty, CastOpc,
+ NumCastsRemoved);
+
case Instruction::Shl:
// If we are truncating the result of this SHL, and if it's a shift of a
// constant amount, we can always perform a SHL in a smaller type.
@@ -6571,6 +6580,7 @@ Value *InstCombiner::EvaluateInDifferentType(Value *V, const Type *Ty,
switch (I->getOpcode()) {
case Instruction::Add:
case Instruction::Sub:
+ case Instruction::Mul:
case Instruction::And:
case Instruction::Or:
case Instruction::Xor:
diff --git a/test/Transforms/InstCombine/2008-01-21-MulTrunc.ll b/test/Transforms/InstCombine/2008-01-21-MulTrunc.ll
new file mode 100644
index 0000000..8de0959
--- /dev/null
+++ b/test/Transforms/InstCombine/2008-01-21-MulTrunc.ll
@@ -0,0 +1,11 @@
+; RUN: llvm-as < %s | opt -instcombine | llvm-dis | notcast
+
+define i16 @test1(i16 %a) {
+ %tmp = zext i16 %a to i32 ; <i32> [#uses=2]
+ %tmp21 = lshr i32 %tmp, 8 ; <i32> [#uses=1]
+ %tmp5 = mul i32 %tmp, 5 ; <i32> [#uses=1]
+ %tmp.upgrd.32 = or i32 %tmp21, %tmp5 ; <i32> [#uses=1]
+ %tmp.upgrd.3 = trunc i32 %tmp.upgrd.32 to i16 ; <i16> [#uses=1]
+ ret i16 %tmp.upgrd.3
+}
+