aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Analysis/ScalarEvolution.cpp
diff options
context:
space:
mode:
authorFlorian Hahn <flo@fhahn.com>2025-09-17 14:28:29 +0100
committerFlorian Hahn <flo@fhahn.com>2025-09-17 14:28:30 +0100
commitf78150d2d477b31b46d1afdd255020689f2ddccf (patch)
tree8901161c48fb0d717807a60fa28433f25333fa8d /llvm/lib/Analysis/ScalarEvolution.cpp
parente969bd71221bd45b5a64aaed5ae1d227b7242c0f (diff)
downloadllvm-f78150d2d477b31b46d1afdd255020689f2ddccf.zip
llvm-f78150d2d477b31b46d1afdd255020689f2ddccf.tar.gz
llvm-f78150d2d477b31b46d1afdd255020689f2ddccf.tar.bz2
Reapply "[SCEV] Fold (C1 * A /u C2) -> A /u (C2 /u C1), if C2 > C1." (#158328)
This reverts commit fd58f235f8c5bd40d98acfd8e7fb11d41de301c7. The recommit contains an extra check to make sure that D is a multiple of C2, if C2 > C1. This fixes the issue causing the revert fd58f235f8c. Tests have been added in 6a726e9a4d3d0. Original message: If C2 >u C1 and C1 >u 1, fold to A /u (C2 /u C1). Depends on https://github.com/llvm/llvm-project/pull/157555. Alive2 Proof: https://alive2.llvm.org/ce/z/BWvQYN PR: https://github.com/llvm/llvm-project/pull/157656
Diffstat (limited to 'llvm/lib/Analysis/ScalarEvolution.cpp')
-rw-r--r--llvm/lib/Analysis/ScalarEvolution.cpp21
1 files changed, 15 insertions, 6 deletions
diff --git a/llvm/lib/Analysis/ScalarEvolution.cpp b/llvm/lib/Analysis/ScalarEvolution.cpp
index 9698ed8..079d7da 100644
--- a/llvm/lib/Analysis/ScalarEvolution.cpp
+++ b/llvm/lib/Analysis/ScalarEvolution.cpp
@@ -3217,19 +3217,28 @@ const SCEV *ScalarEvolution::getMulExpr(SmallVectorImpl<const SCEV *> &Ops,
}
// Try to fold (C1 * D /u C2) -> C1/C2 * D, if C1 and C2 are powers-of-2,
- // D is a multiple of C2, and C1 is a multiple of C2.
+ // D is a multiple of C2, and C1 is a multiple of C2. If C2 is a multiple
+ // of C1, fold to (D /u (C2 /u C1)).
const SCEV *D;
APInt C1V = LHSC->getAPInt();
- // (C1 * D /u C2) == -1 * -C1 * D /u C2 when C1 != INT_MIN.
- if (C1V.isNegative() && !C1V.isMinSignedValue())
+ // (C1 * D /u C2) == -1 * -C1 * D /u C2 when C1 != INT_MIN. Don't treat -1
+ // as -1 * 1, as it won't enable additional folds.
+ if (C1V.isNegative() && !C1V.isMinSignedValue() && !C1V.isAllOnes())
C1V = C1V.abs();
const SCEVConstant *C2;
if (C1V.isPowerOf2() &&
match(Ops[1], m_scev_UDiv(m_SCEV(D), m_SCEVConstant(C2))) &&
- C2->getAPInt().isPowerOf2() && C1V.uge(C2->getAPInt()) &&
+ C2->getAPInt().isPowerOf2() &&
C1V.logBase2() <= getMinTrailingZeros(D)) {
- const SCEV *NewMul = getMulExpr(getUDivExpr(getConstant(C1V), C2), D);
- return C1V == LHSC->getAPInt() ? NewMul : getNegativeSCEV(NewMul);
+ const SCEV *NewMul = nullptr;
+ if (C1V.uge(C2->getAPInt())) {
+ NewMul = getMulExpr(getUDivExpr(getConstant(C1V), C2), D);
+ } else if (C2->getAPInt().logBase2() <= getMinTrailingZeros(D)) {
+ assert(C1V.ugt(1) && "C1 <= 1 should have been folded earlier");
+ NewMul = getUDivExpr(D, getUDivExpr(C2, getConstant(C1V)));
+ }
+ if (NewMul)
+ return C1V == LHSC->getAPInt() ? NewMul : getNegativeSCEV(NewMul);
}
}
}