[llvm] Redesign Straight-Line Strength Reduction (SLSR) (PR #162930)
Drew Kersnar via llvm-commits
llvm-commits at lists.llvm.org
Mon Oct 20 13:43:39 PDT 2025
================
@@ -177,22 +203,164 @@ class StraightLineStrengthReduce {
// Points to the immediate basis of this candidate, or nullptr if we cannot
// find any basis for this candidate.
Candidate *Basis = nullptr;
+
+ DKind DeltaKind = InvalidDelta;
+
+ // Store SCEV of Stride to compute delta from different strides
+ const SCEV *StrideSCEV = nullptr;
+
+ // Points to (Y - X) that will be used to rewrite this candidate.
+ Value *Delta = nullptr;
+
+ /// Cost model: Evaluate the computational efficiency of the candidate.
+ ///
+ /// Efficiency levels (higher is better):
+ /// ZeroInst (5) - [Variable] or [Const]
+ /// OneInstOneVar (4) - [Variable + Const] or [Variable * Const]
+ /// OneInstTwoVar (3) - [Variable + Variable] or [Variable * Variable]
+ /// TwoInstOneVar (2) - [Const + Const * Variable]
+ /// TwoInstTwoVar (1) - [Variable + Const * Variable]
+ enum EfficiencyLevel : unsigned {
+ Unknown = 0,
+ TwoInstTwoVar = 1,
+ TwoInstOneVar = 2,
+ OneInstTwoVar = 3,
+ OneInstOneVar = 4,
+ ZeroInst = 5
+ };
+
+ static EfficiencyLevel
+ getComputationEfficiency(Kind CandidateKind, const ConstantInt *Index,
+ const Value *Stride, const SCEV *Base = nullptr) {
+ bool IsConstantBase = false;
+ bool IsZeroBase = false;
+ // When evaluating the efficiency of a rewrite, if the Basis's SCEV is
+ // not available, conservatively assume the base is not constant.
+ if (auto *ConstBase = dyn_cast_or_null<SCEVConstant>(Base)) {
+ IsConstantBase = true;
+ IsZeroBase = ConstBase->getValue()->isZero();
+ }
+
+ bool IsConstantStride = isa<ConstantInt>(Stride);
+ bool IsZeroStride =
+ IsConstantStride && cast<ConstantInt>(Stride)->isZero();
+ // All constants
+ if (IsConstantBase && IsConstantStride)
+ return ZeroInst;
+
+ // [(Base + Index) * Stride]
+ if (CandidateKind == Mul) {
+ if (IsZeroStride)
+ return ZeroInst;
+ if (Index->isZero())
+ return (IsConstantStride || IsConstantBase) ? OneInstOneVar
+ : OneInstTwoVar;
+
+ if (IsConstantBase)
+ return IsZeroBase && (Index->isOne() || Index->isMinusOne())
+ ? ZeroInst
+ : OneInstOneVar;
+
+ if (IsConstantStride) {
+ auto *CI = cast<ConstantInt>(Stride);
+ return (CI->isOne() || CI->isMinusOne()) ? OneInstOneVar
+ : TwoInstOneVar;
+ }
+ return TwoInstTwoVar;
+ }
+
+ // Base + Index * Stride
+ assert(CandidateKind == Add || CandidateKind == GEP);
+ if (Index->isZero() || IsZeroStride)
+ return ZeroInst;
+
+ bool IsSimpleIndex = Index->isOne() || Index->isMinusOne();
+
+ if (IsConstantBase)
+ return IsZeroBase ? (IsSimpleIndex ? ZeroInst : OneInstOneVar)
+ : (IsSimpleIndex ? OneInstOneVar : TwoInstOneVar);
+
+ if (IsConstantStride)
+ return IsZeroStride ? ZeroInst : OneInstOneVar;
+
+ if (IsSimpleIndex)
+ return OneInstTwoVar;
+
+ return TwoInstTwoVar;
+ }
+
+ // Evaluate if the given delta is profitable to rewrite this candidate.
+ bool isProfitableRewrite(const Value *Delta, const DKind DeltaKind) const {
+ // This function cannot accurately evaluate the profit of whole expression
+ // with context. A candidate (B + I * S) cannot express whether this
+ // instruction needs to compute on its own (I * S), which may be shared
+ // with other candidates or may need instructions to compute.
+ // If the rewritten form has the same strength, still rewrite to
+ // (X + Delta) since it may expose more CSE opportunities on Delta, as
+ // unrolled loops usually have identical Delta for each unrolled body.
+ //
+ // Note, this function should only be used on Index Delta rewrite.
+ // Base and Stride delta need context info to evaluate the register
+ // pressure impact from variable delta.
+ return getComputationEfficiency(CandidateKind, Index, Stride, Base) <=
+ getRewriteProfit(Delta, DeltaKind);
+ }
+
+ // Evaluate the rewrite profit of this candidate with its Basis
+ EfficiencyLevel getRewriteProfit() const {
----------------
dakersnar wrote:
nit: Maybe rename these to `getRewriteEfficiency`? "Profit" feels like should represents the _difference_ between the current computation efficiency and the rewrite computation efficiency.
https://github.com/llvm/llvm-project/pull/162930
More information about the llvm-commits
mailing list