aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib
diff options
context:
space:
mode:
authorNikita Popov <npopov@redhat.com>2024-08-14 09:37:38 +0200
committerGitHub <noreply@github.com>2024-08-14 09:37:38 +0200
commit6da3361f504495cef71caa4de4297234b6ea7fc7 (patch)
treed36749532614d52e1ebc635ab6698f1ca540f392 /llvm/lib
parent241f9e7492dae1920778ef4fe72db6073b6275b1 (diff)
downloadllvm-6da3361f504495cef71caa4de4297234b6ea7fc7.zip
llvm-6da3361f504495cef71caa4de4297234b6ea7fc7.tar.gz
llvm-6da3361f504495cef71caa4de4297234b6ea7fc7.tar.bz2
[SCEV] Look through multiply in computeConstantDifference() (#103051)
Inside computeConstantDifference(), handle the case where both sides are of the form `C * %x`, in which case we can strip off the common multiplication (as long as we remember to multiply by it for the following difference calculation). There is an obvious alternative implementation here, which would be to directly decompose multiplies inside the "Multiplicity" accumulation. This does work, but I've found this to be both significantly slower (because everything has to work on APInt) and more complex in implementation (e.g. because we now need to match back the new More/Less with an arbitrary factor) without providing more power in practice. As such, I went for the simpler variant here. This is the last step to make computeConstantDifference() sufficiently powerful to replace existing uses of `cast<SCEVConstant>(getMinusSCEV())` with it.
Diffstat (limited to 'llvm/lib')
-rw-r--r--llvm/lib/Analysis/ScalarEvolution.cpp28
1 files changed, 25 insertions, 3 deletions
diff --git a/llvm/lib/Analysis/ScalarEvolution.cpp b/llvm/lib/Analysis/ScalarEvolution.cpp
index 9a568a2..af341c5 100644
--- a/llvm/lib/Analysis/ScalarEvolution.cpp
+++ b/llvm/lib/Analysis/ScalarEvolution.cpp
@@ -11953,9 +11953,10 @@ ScalarEvolution::computeConstantDifference(const SCEV *More, const SCEV *Less) {
unsigned BW = getTypeSizeInBits(More->getType());
APInt Diff(BW, 0);
+ APInt DiffMul(BW, 1);
// Try various simplifications to reduce the difference to a constant. Limit
// the number of allowed simplifications to keep compile-time low.
- for (unsigned I = 0; I < 4; ++I) {
+ for (unsigned I = 0; I < 5; ++I) {
if (More == Less)
return Diff;
@@ -11980,15 +11981,36 @@ ScalarEvolution::computeConstantDifference(const SCEV *More, const SCEV *Less) {
continue;
}
+ // Try to match a common constant multiply.
+ auto MatchConstMul =
+ [](const SCEV *S) -> std::optional<std::pair<const SCEV *, APInt>> {
+ auto *M = dyn_cast<SCEVMulExpr>(S);
+ if (!M || M->getNumOperands() != 2 ||
+ !isa<SCEVConstant>(M->getOperand(0)))
+ return std::nullopt;
+ return {
+ {M->getOperand(1), cast<SCEVConstant>(M->getOperand(0))->getAPInt()}};
+ };
+ if (auto MatchedMore = MatchConstMul(More)) {
+ if (auto MatchedLess = MatchConstMul(Less)) {
+ if (MatchedMore->second == MatchedLess->second) {
+ More = MatchedMore->first;
+ Less = MatchedLess->first;
+ DiffMul *= MatchedMore->second;
+ continue;
+ }
+ }
+ }
+
// Try to cancel out common factors in two add expressions.
SmallDenseMap<const SCEV *, int, 8> Multiplicity;
auto Add = [&](const SCEV *S, int Mul) {
if (auto *C = dyn_cast<SCEVConstant>(S)) {
if (Mul == 1) {
- Diff += C->getAPInt();
+ Diff += C->getAPInt() * DiffMul;
} else {
assert(Mul == -1);
- Diff -= C->getAPInt();
+ Diff -= C->getAPInt() * DiffMul;
}
} else
Multiplicity[S] += Mul;