summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/Transforms/InstCombine/InstCombineCasts.cpp20
-rw-r--r--test/Transforms/InstCombine/cast.ll28
2 files changed, 45 insertions, 3 deletions
diff --git a/lib/Transforms/InstCombine/InstCombineCasts.cpp b/lib/Transforms/InstCombine/InstCombineCasts.cpp
index a6833b8825..3ad786b6bd 100644
--- a/lib/Transforms/InstCombine/InstCombineCasts.cpp
+++ b/lib/Transforms/InstCombine/InstCombineCasts.cpp
@@ -643,17 +643,31 @@ static int CanEvaluateZExtd(Value *V, const Type *Ty,unsigned &NumCastsRemoved,
if (Tmp1 == -1) return -1;
Tmp2 = CanEvaluateZExtd(I->getOperand(1), Ty, NumCastsRemoved, TD);
if (Tmp2 == -1) return -1;
+ return 0; // TODO: Could be improved.
+
+ case Instruction::Shl:
+ Tmp1 = CanEvaluateZExtd(I->getOperand(0), Ty, NumCastsRemoved, TD);
+ if (Tmp1 == -1) return -1;
+
+ if (ConstantInt *CI = dyn_cast<ConstantInt>(I->getOperand(1)))
+ return Tmp1 - CI->getZExtValue();
+
+ // Variable shift, no known zext bits.
+ Tmp2 = CanEvaluateZExtd(I->getOperand(1), Ty, NumCastsRemoved, TD);
+ if (Tmp2 == -1) return -1;
return 0;
- //case Instruction::Shl:
//case Instruction::LShr:
case Instruction::ZExt:
// zext(zext(x)) -> zext(x). Since we're replacing it, it isn't eliminated.
Tmp1 = Ty->getScalarSizeInBits()-OrigTy->getScalarSizeInBits();
return GetLeadingZeros(I, TD)+Tmp1;
- //case Instruction::SExt: zext(sext(x)) -> sext(x) with no upper bits known.
- //case Instruction::Trunc:
+ case Instruction::SExt:
+ // zext(sext(x)) -> sext(x) with no upper bits known.
+ return 0;
+ //case Instruction::Trunc: -> Could turn into AND.
+
case Instruction::Select:
Tmp1 = CanEvaluateZExtd(I->getOperand(1), Ty, NumCastsRemoved, TD);
if (Tmp1 == -1) return -1;
diff --git a/test/Transforms/InstCombine/cast.ll b/test/Transforms/InstCombine/cast.ll
index b6dc4642b8..490df8fab6 100644
--- a/test/Transforms/InstCombine/cast.ll
+++ b/test/Transforms/InstCombine/cast.ll
@@ -403,3 +403,31 @@ define i64 @test44(i8 %T) {
; CHECK-NEXT: %B = or i64 %A, 1234
; CHECK-NEXT: ret i64 %B
}
+
+define i64 @test45(i8 %A, i64 %Q) {
+ %D = trunc i64 %Q to i32 ;; should be removed
+ %B = sext i8 %A to i32
+ %C = or i32 %B, %D
+ %E = zext i32 %C to i64
+ ret i64 %E
+; CHECK: @test45
+; CHECK-NEXT: %B = sext i8 %A to i64
+; CHECK-NEXT: %C = or i64 %B, %Q
+; CHECK-NEXT: %E = and i64 %C, 4294967295
+; CHECK-NEXT: ret i64 %E
+}
+
+
+define i64 @test46(i64 %A) {
+ %B = trunc i64 %A to i32
+ %C = and i32 %B, 42
+ %D = shl i32 %C, 8
+ %E = zext i32 %D to i64
+ ret i64 %E
+; CHECK: @test46
+; CHECK-NEXT: %C = shl i64 %A, 8
+; CHECK-NEXT: %D = and i64 %C, 10752
+; CHECK-NEXT: ret i64 %D
+}
+
+