Skip to content

[DA] Extract duplicated logic from gcdMIVtest (NFCI) #152688

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

Merged
merged 1 commit into from
Aug 13, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions llvm/include/llvm/Analysis/DependenceAnalysis.h
Original file line number Diff line number Diff line change
Expand Up @@ -765,6 +765,25 @@ class DependenceInfo {
CoefficientInfo *collectCoeffInfo(const SCEV *Subscript, bool SrcFlag,
const SCEV *&Constant) const;

/// Given \p Expr of the form
///
/// c_0*X_0*i_0 + c_1*X_1*i_1 + ...c_n*X_n*i_n + C
///
/// compute
///
/// RunningGCD = gcd(RunningGCD, c_0, c_1, ..., c_n)
///
/// where c_0, c_1, ..., and c_n are the constant values. The result is stored
/// in \p RunningGCD. Also, the initial value of \p RunningGCD affects the
/// result. If we find a term like (c_k * X_k * i_k), where i_k is the
/// induction variable of \p CurLoop, c_k is stored in \p CurLoopCoeff and not
/// included in the GCD computation. Returns false if we fail to find a
/// constant coefficient for some loop, e.g., when a term like (X+Y)*i is
/// present. Otherwise returns true.
bool accumulateCoefficientsGCD(const SCEV *Expr, const Loop *CurLoop,
const SCEV *&CurLoopCoeff,
APInt &RunningGCD) const;

/// getPositivePart - X^+ = max(X, 0).
const SCEV *getPositivePart(const SCEV *X) const;

Expand Down
76 changes: 42 additions & 34 deletions llvm/lib/Analysis/DependenceAnalysis.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2345,6 +2345,43 @@ static std::optional<APInt> getConstantPart(const SCEV *Expr) {
return std::nullopt;
}

bool DependenceInfo::accumulateCoefficientsGCD(const SCEV *Expr,
const Loop *CurLoop,
const SCEV *&CurLoopCoeff,
APInt &RunningGCD) const {
// If RunningGCD is already 1, exit early.
// TODO: It might be better to continue the recursion to find CurLoopCoeff.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems pretty buggy. Considering that DstCoeff is initialized to something like zero, we may not be able to distinguish between the case where Dst is invariant in CurLoop and the case where Dst is NOT invariant but the GCD is 1.

if (RunningGCD == 1)
return true;

const SCEVAddRecExpr *AddRec = dyn_cast<SCEVAddRecExpr>(Expr);
if (!AddRec) {
assert(isLoopInvariant(Expr, CurLoop) &&
"Expected loop invariant expression");
return true;
}

assert(AddRec->isAffine() && "Unexpected Expr");
const SCEV *Start = AddRec->getStart();
const SCEV *Step = AddRec->getStepRecurrence(*SE);
if (AddRec->getLoop() == CurLoop) {
CurLoopCoeff = Step;
} else {
std::optional<APInt> ConstCoeff = getConstantPart(Step);

// If the coefficient is the product of a constant and other stuff, we can
// use the constant in the GCD computation.
if (!ConstCoeff)
return false;

// TODO: What happens if ConstCoeff is the "most negative" signed number
// (e.g. -128 for 8 bit wide APInt)?
RunningGCD = APIntOps::GreatestCommonDivisor(RunningGCD, ConstCoeff->abs());
}

return accumulateCoefficientsGCD(Start, CurLoop, CurLoopCoeff, RunningGCD);
}

//===----------------------------------------------------------------------===//
// gcdMIVtest -
// Tests an MIV subscript pair for dependence.
Expand Down Expand Up @@ -2464,40 +2501,11 @@ bool DependenceInfo::gcdMIVtest(const SCEV *Src, const SCEV *Dst,
RunningGCD = ExtraGCD;
const SCEV *SrcCoeff = AddRec->getStepRecurrence(*SE);
const SCEV *DstCoeff = SE->getMinusSCEV(SrcCoeff, SrcCoeff);
const SCEV *Inner = Src;
while (RunningGCD != 1 && isa<SCEVAddRecExpr>(Inner)) {
AddRec = cast<SCEVAddRecExpr>(Inner);
const SCEV *Coeff = AddRec->getStepRecurrence(*SE);
if (CurLoop == AddRec->getLoop())
; // SrcCoeff == Coeff
else {
// If the coefficient is the product of a constant and other stuff,
// we can use the constant in the GCD computation.
std::optional<APInt> ConstCoeff = getConstantPart(Coeff);
if (!ConstCoeff)
return false;
RunningGCD =
APIntOps::GreatestCommonDivisor(RunningGCD, ConstCoeff->abs());
}
Inner = AddRec->getStart();
}
Inner = Dst;
while (RunningGCD != 1 && isa<SCEVAddRecExpr>(Inner)) {
AddRec = cast<SCEVAddRecExpr>(Inner);
const SCEV *Coeff = AddRec->getStepRecurrence(*SE);
if (CurLoop == AddRec->getLoop())
DstCoeff = Coeff;
else {
// If the coefficient is the product of a constant and other stuff,
// we can use the constant in the GCD computation.
std::optional<APInt> ConstCoeff = getConstantPart(Coeff);
if (!ConstCoeff)
return false;
RunningGCD =
APIntOps::GreatestCommonDivisor(RunningGCD, ConstCoeff->abs());
}
Inner = AddRec->getStart();
}

if (!accumulateCoefficientsGCD(Src, CurLoop, SrcCoeff, RunningGCD) ||
!accumulateCoefficientsGCD(Dst, CurLoop, DstCoeff, RunningGCD))
return false;

Delta = SE->getMinusSCEV(SrcCoeff, DstCoeff);
// If the coefficient is the product of a constant and other stuff,
// we can use the constant in the GCD computation.
Expand Down