aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lib/Transforms/InstCombine/InstCombineCasts.cpp12
-rw-r--r--test/Transforms/InstCombine/cast.ll28
2 files changed, 39 insertions, 1 deletions
diff --git a/lib/Transforms/InstCombine/InstCombineCasts.cpp b/lib/Transforms/InstCombine/InstCombineCasts.cpp
index 2ee1278..361acdd 100644
--- a/lib/Transforms/InstCombine/InstCombineCasts.cpp
+++ b/lib/Transforms/InstCombine/InstCombineCasts.cpp
@@ -677,7 +677,6 @@ static bool CanEvaluateZExtd(Value *V, Type *Ty, unsigned &BitsToClear) {
case Instruction::Add:
case Instruction::Sub:
case Instruction::Mul:
- case Instruction::Shl:
if (!CanEvaluateZExtd(I->getOperand(0), Ty, BitsToClear) ||
!CanEvaluateZExtd(I->getOperand(1), Ty, Tmp))
return false;
@@ -701,6 +700,17 @@ static bool CanEvaluateZExtd(Value *V, Type *Ty, unsigned &BitsToClear) {
// Otherwise, we don't know how to analyze this BitsToClear case yet.
return false;
+ case Instruction::Shl:
+ // We can promote shl(x, cst) if we can promote x. Since shl overwrites the
+ // upper bits we can reduce BitsToClear by the shift amount.
+ if (ConstantInt *Amt = dyn_cast<ConstantInt>(I->getOperand(1))) {
+ if (!CanEvaluateZExtd(I->getOperand(0), Ty, BitsToClear))
+ return false;
+ uint64_t ShiftAmt = Amt->getZExtValue();
+ BitsToClear = ShiftAmt < BitsToClear ? BitsToClear - ShiftAmt : 0;
+ return true;
+ }
+ return false;
case Instruction::LShr:
// We can promote lshr(x, cst) if we can promote x. This requires the
// ultimate 'and' to clear out the high zero bits we're clearing out though.
diff --git a/test/Transforms/InstCombine/cast.ll b/test/Transforms/InstCombine/cast.ll
index de738bb..ff2c0a9 100644
--- a/test/Transforms/InstCombine/cast.ll
+++ b/test/Transforms/InstCombine/cast.ll
@@ -898,3 +898,31 @@ define double @test81(double *%p, float %f) {
%l = load double* %r
ret double %l
}
+
+define i64 @test82(i64 %A) nounwind {
+ %B = trunc i64 %A to i32
+ %C = lshr i32 %B, 8
+ %D = shl i32 %C, 9
+ %E = zext i32 %D to i64
+ ret i64 %E
+
+; CHECK: @test82
+; CHECK-NEXT: [[REG:%[0-9]*]] = shl i64 %A, 1
+; CHECK-NEXT: %E = and i64 [[REG]], 4294966784
+; CHECK-NEXT: ret i64 %E
+}
+
+; PR15959
+define i64 @test83(i16 %a, i64 %k) {
+ %conv = sext i16 %a to i32
+ %sub = add nsw i64 %k, -1
+ %sh_prom = trunc i64 %sub to i32
+ %shl = shl i32 %conv, %sh_prom
+ %sh_prom1 = zext i32 %shl to i64
+ ret i64 %sh_prom1
+
+; CHECK: @test83
+; CHECK: %sub = add nsw i64 %k, 4294967295
+; CHECK: %sh_prom = trunc i64 %sub to i32
+; CHECK: %shl = shl i32 %conv, %sh_prom
+}