Index: llvm/lib/Analysis/ScalarEvolution.cpp =================================================================== --- llvm/lib/Analysis/ScalarEvolution.cpp +++ llvm/lib/Analysis/ScalarEvolution.cpp @@ -1778,6 +1778,33 @@ Ops.push_back(getZeroExtendExpr(Op, Ty, Depth + 1)); return getMulExpr(Ops, SCEV::FlagNUW, Depth + 1); } + + // zext(2^K * (trunc X to iN)) to iM -> + // 2^K * (zext(trunc X to i{N-K}) to iM) + // + // Proof: + // + // zext(2^K * (trunc X to iN)) to iM + // = zext((trunc X to iN) << K) to iM + // = zext((trunc X to i{N-K}) << K) to iM + // (because shl removes the top K bits) + // = zext((2^K * (trunc X to i{N-K}))) to iM + // = (2^K * (zext(trunc X to i{N-K}) to iM)). + // + if (SA->getNumOperands() == 2) + if (auto *MulLHS = dyn_cast(SA->getOperand(0))) + if (MulLHS->getAPInt().isPowerOf2()) + if (auto *TruncRHS = dyn_cast(SA->getOperand(1))) { + int NewTruncBits = getTypeSizeInBits(TruncRHS->getType()) - + MulLHS->getAPInt().logBase2(); + Type *TruncTy = IntegerType::get(getContext(), NewTruncBits); + assert(NewTruncBits > 0 && "Can't represent 2^N in 2^(N-1) bits."); + return getMulExpr( + getZeroExtendExpr(MulLHS, Ty), + getZeroExtendExpr( + getTruncateExpr(TruncRHS->getOperand(), TruncTy), Ty), + SCEV::FlagNUW, Depth + 1); + } } // The cast wasn't folded; create an explicit cast node. Index: llvm/test/Analysis/LoopAccessAnalysis/wrapping-pointer-versioning.ll =================================================================== --- llvm/test/Analysis/LoopAccessAnalysis/wrapping-pointer-versioning.ll +++ llvm/test/Analysis/LoopAccessAnalysis/wrapping-pointer-versioning.ll @@ -122,7 +122,7 @@ ; LAA: Memory dependences are safe{{$}} ; LAA: SCEV assumptions: ; LAA-NEXT: {(2 * (trunc i64 %N to i32)),+,-2}<%for.body> Added Flags: -; LAA-NEXT: {((2 * (zext i32 (2 * (trunc i64 %N to i32)) to i64)) + %a),+,-4}<%for.body> Added Flags: +; LAA-NEXT: {((4 * (zext i31 (trunc i64 %N to i31) to i64)) + %a),+,-4}<%for.body> Added Flags: ; The expression for %mul_ext as analyzed by SCEV is ; (zext i32 {(2 * (trunc i64 %N to i32)),+,-2}<%for.body> to i64) @@ -131,7 +131,7 @@ ; LAA: [PSE] %arrayidxA = getelementptr i16, i16* %a, i64 %mul_ext: ; LAA-NEXT: ((2 * (zext i32 {(2 * (trunc i64 %N to i32)),+,-2}<%for.body> to i64)) + %a) -; LAA-NEXT: --> {((2 * (zext i32 (2 * (trunc i64 %N to i32)) to i64)) + %a),+,-4}<%for.body> +; LAA-NEXT: --> {((4 * (zext i31 (trunc i64 %N to i31) to i64)) + %a),+,-4}<%for.body> ; LV-LABEL: f2 ; LV-LABEL: for.body.lver.check Index: llvm/test/Analysis/ScalarEvolution/and-xor.ll =================================================================== --- llvm/test/Analysis/ScalarEvolution/and-xor.ll +++ llvm/test/Analysis/ScalarEvolution/and-xor.ll @@ -25,3 +25,17 @@ %z = xor i64 %t, 8 ret i64 %z } + +; Check that we transform the naive lowering of the sequence below, +; (4 * (zext i5 (2 * (trunc i32 %x to i5)) to i32)), +; to +; (8 * (zext i4 (trunc i32 %x to i4) to i32)) +; +; CHECK-LABEL: @test3 +define i32 @test3(i32 %x) { + %a = mul i32 %x, 8 +; CHECK: %b +; CHECK-NEXT: --> (8 * (zext i4 (trunc i32 %x to i4) to i32)) + %b = and i32 %a, 124 + ret i32 %b +}