diff --git a/lib/Transforms/InstCombine/InstCombineCasts.cpp b/lib/Transforms/InstCombine/InstCombineCasts.cpp index 2ee1278d23d..361acdde81f 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(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 de738bb7c06..ff2c0a92898 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 +}