-
Notifications
You must be signed in to change notification settings - Fork 14.8k
[SCEV] Use APInt for DividesBy when collecting loop guard info (NFC). #163017
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
@llvm/pr-subscribers-llvm-analysis Author: Florian Hahn (fhahn) ChangesFollow-up as suggested in #162617. Just use an APInt for DividesBy, as the existing code already operates on APInt and thus handles the case of DividesBy being 1. Full diff: https://github.com/llvm/llvm-project/pull/163017.diff 1 Files Affected:
diff --git a/llvm/lib/Analysis/ScalarEvolution.cpp b/llvm/lib/Analysis/ScalarEvolution.cpp
index 30bcff7c14923..08b37ed16cdeb 100644
--- a/llvm/lib/Analysis/ScalarEvolution.cpp
+++ b/llvm/lib/Analysis/ScalarEvolution.cpp
@@ -15633,47 +15633,32 @@ void ScalarEvolution::LoopGuards::collectFromBlock(
return false;
};
- // Checks whether Expr is a non-negative constant, and Divisor is a positive
- // constant, and returns their APInt in ExprVal and in DivisorVal.
- auto GetNonNegExprAndPosDivisor = [&](const SCEV *Expr, const SCEV *Divisor,
- APInt &ExprVal, APInt &DivisorVal) {
- auto *ConstExpr = dyn_cast<SCEVConstant>(Expr);
- auto *ConstDivisor = dyn_cast<SCEVConstant>(Divisor);
- if (!ConstExpr || !ConstDivisor)
- return false;
- ExprVal = ConstExpr->getAPInt();
- DivisorVal = ConstDivisor->getAPInt();
- return ExprVal.isNonNegative() && !DivisorVal.isNonPositive();
- };
-
// Return a new SCEV that modifies \p Expr to the closest number divides by
// \p Divisor and greater or equal than Expr.
- // For now, only handle constant Expr and Divisor.
+ // For now, only handle constant Expr.
auto GetNextSCEVDividesByDivisor = [&](const SCEV *Expr,
- const SCEV *Divisor) {
- APInt ExprVal;
- APInt DivisorVal;
- if (!GetNonNegExprAndPosDivisor(Expr, Divisor, ExprVal, DivisorVal))
+ const APInt &DivisorVal) {
+ const APInt *ExprVal;
+ if (!match(Expr, m_scev_APInt(ExprVal)) || ExprVal->isNegative())
return Expr;
- APInt Rem = ExprVal.urem(DivisorVal);
- if (!Rem.isZero())
- // return the SCEV: Expr + Divisor - Expr % Divisor
- return SE.getConstant(ExprVal + DivisorVal - Rem);
- return Expr;
+ APInt Rem = ExprVal->urem(DivisorVal);
+ if (Rem.isZero())
+ return Expr;
+ // return the SCEV: Expr + Divisor - Expr % Divisor
+ return SE.getConstant(*ExprVal + DivisorVal - Rem);
};
// Return a new SCEV that modifies \p Expr to the closest number divides by
// \p Divisor and less or equal than Expr.
- // For now, only handle constant Expr and Divisor.
+ // For now, only handle constant Expr.
auto GetPreviousSCEVDividesByDivisor = [&](const SCEV *Expr,
- const SCEV *Divisor) {
- APInt ExprVal;
- APInt DivisorVal;
- if (!GetNonNegExprAndPosDivisor(Expr, Divisor, ExprVal, DivisorVal))
+ const APInt &DivisorVal) {
+ const APInt *ExprVal;
+ if (!match(Expr, m_scev_APInt(ExprVal)) || ExprVal->isNegative())
return Expr;
- APInt Rem = ExprVal.urem(DivisorVal);
+ APInt Rem = ExprVal->urem(DivisorVal);
// return the SCEV: Expr - Expr % Divisor
- return SE.getConstant(ExprVal - Rem);
+ return SE.getConstant(*ExprVal - Rem);
};
// Apply divisibilty by \p Divisor on MinMaxExpr with constant values,
@@ -15682,6 +15667,11 @@ void ScalarEvolution::LoopGuards::collectFromBlock(
std::function<const SCEV *(const SCEV *, const SCEV *)>
ApplyDivisibiltyOnMinMaxExpr = [&](const SCEV *MinMaxExpr,
const SCEV *Divisor) {
+ auto *ConstDivisor = dyn_cast<SCEVConstant>(Divisor);
+ if (!ConstDivisor)
+ return MinMaxExpr;
+ const APInt &DivisorVal = ConstDivisor->getAPInt();
+
const SCEV *MinMaxLHS = nullptr, *MinMaxRHS = nullptr;
SCEVTypes SCTy;
if (!IsMinMaxSCEVWithNonNegativeConstant(MinMaxExpr, SCTy, MinMaxLHS,
@@ -15692,8 +15682,8 @@ void ScalarEvolution::LoopGuards::collectFromBlock(
assert(SE.isKnownNonNegative(MinMaxLHS) &&
"Expected non-negative operand!");
auto *DivisibleExpr =
- IsMin ? GetPreviousSCEVDividesByDivisor(MinMaxLHS, Divisor)
- : GetNextSCEVDividesByDivisor(MinMaxLHS, Divisor);
+ IsMin ? GetPreviousSCEVDividesByDivisor(MinMaxLHS, DivisorVal)
+ : GetNextSCEVDividesByDivisor(MinMaxLHS, DivisorVal);
SmallVector<const SCEV *> Ops = {
ApplyDivisibiltyOnMinMaxExpr(MinMaxRHS, Divisor), DivisibleExpr};
return SE.getMinMaxExpr(SCTy, Ops);
@@ -15750,10 +15740,7 @@ void ScalarEvolution::LoopGuards::collectFromBlock(
};
const SCEV *RewrittenLHS = GetMaybeRewritten(LHS);
- const SCEV *DividesBy = nullptr;
- const APInt &Multiple = SE.getConstantMultiple(RewrittenLHS);
- if (!Multiple.isOne())
- DividesBy = SE.getConstant(Multiple);
+ const APInt &DividesBy = SE.getConstantMultiple(RewrittenLHS);
// Collect rewrites for LHS and its transitive operands based on the
// condition.
@@ -15775,21 +15762,21 @@ void ScalarEvolution::LoopGuards::collectFromBlock(
[[fallthrough]];
case CmpInst::ICMP_SLT: {
RHS = SE.getMinusSCEV(RHS, One);
- RHS = DividesBy ? GetPreviousSCEVDividesByDivisor(RHS, DividesBy) : RHS;
+ RHS = GetPreviousSCEVDividesByDivisor(RHS, DividesBy);
break;
}
case CmpInst::ICMP_UGT:
case CmpInst::ICMP_SGT:
RHS = SE.getAddExpr(RHS, One);
- RHS = DividesBy ? GetNextSCEVDividesByDivisor(RHS, DividesBy) : RHS;
+ RHS = GetNextSCEVDividesByDivisor(RHS, DividesBy);
break;
case CmpInst::ICMP_ULE:
case CmpInst::ICMP_SLE:
- RHS = DividesBy ? GetPreviousSCEVDividesByDivisor(RHS, DividesBy) : RHS;
+ RHS = GetPreviousSCEVDividesByDivisor(RHS, DividesBy);
break;
case CmpInst::ICMP_UGE:
case CmpInst::ICMP_SGE:
- RHS = DividesBy ? GetNextSCEVDividesByDivisor(RHS, DividesBy) : RHS;
+ RHS = GetNextSCEVDividesByDivisor(RHS, DividesBy);
break;
default:
break;
@@ -15843,7 +15830,7 @@ void ScalarEvolution::LoopGuards::collectFromBlock(
case CmpInst::ICMP_NE:
if (match(RHS, m_scev_Zero())) {
const SCEV *OneAlignedUp =
- DividesBy ? GetNextSCEVDividesByDivisor(One, DividesBy) : One;
+ GetNextSCEVDividesByDivisor(One, DividesBy);
To = SE.getUMaxExpr(FromRewritten, OneAlignedUp);
}
break;
|
7b597b4
to
8430fd7
Compare
✅ With the latest revision this PR passed the C/C++ code formatter. |
const APInt &DivisorVal) { | ||
const APInt *ExprVal; | ||
if (!match(Expr, m_scev_APInt(ExprVal)) || | ||
DivisorVal.isNonPositive()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This drops the ExprVal.isNonNegative()
check. Is that intentional? (I haven't checked this carefully, but presumably negative values would need special handling for signed min/max?)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep, added the check back, thanks! Looks like this isn't covered by any existing tests in a way that exposes a mis-compile unfortuantely, and I couldn't find a case via llvm-opt-benchmarks and another corpus.
Follow-up as suggested in llvm#162617. Just use an APInt for DividesBy, as the existing code already operates on APInt and thus handles the case of DividesBy being 1.
8430fd7
to
85aba68
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
…info (NFC). (#163017) Follow-up as suggested in llvm/llvm-project#162617. Just use an APInt for DividesBy, as the existing code already operates on APInt and thus handles the case of DividesBy being 1. PR: llvm/llvm-project#163017
LLVM Buildbot has detected a new failure on builder Full details are available at: https://lab.llvm.org/buildbot/#/builders/186/builds/13122 Here is the relevant piece of the build log for the reference
|
…llvm#163017) Follow-up as suggested in llvm#162617. Just use an APInt for DividesBy, as the existing code already operates on APInt and thus handles the case of DividesBy being 1. PR: llvm#163017
Follow-up as suggested in #162617.
Just use an APInt for DividesBy, as the existing code already operates on APInt and thus handles the case of DividesBy being 1.