[llvm-branch-commits] [llvm] [LoopInterchange] Fix instorder profitability check (PR #181991)

Ryotaro Kasuga via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Fri Feb 20 06:21:23 PST 2026


================
@@ -1561,53 +1561,62 @@ const DenseMap<const Loop *, unsigned> &CacheCostManager::getCostMap() {
   return CostMap;
 }
 
+/// If \S contains an affine addrec for \p L0, store the step recurrence of the
+/// addrec in \p Coeff0. Same for \p L1 and \p Coeff1. This function assumes \p
+/// S is an nested affine addrec, and it will recursively look through the start
+/// value of the addrec to find the coefficients. If the expression is in a
+/// complex form, e.g., (addrec + addrec), then the coefficients may not be
+/// found.
+static void getAddRecCoefficients(ScalarEvolution &SE, const SCEV *S,
+                                  const Loop *L0,
+                                  std::optional<const SCEV *> &Coeff0,
+                                  const Loop *L1,
+                                  std::optional<const SCEV *> &Coeff1) {
+  const SCEVAddRecExpr *AR = dyn_cast<SCEVAddRecExpr>(S);
+  if (!AR)
+    return;
+  if (!AR->isAffine()) {
+    LLVM_DEBUG(dbgs() << "Unexpected non-affine addrec\n");
+    return;
+  }
+  if (AR->getLoop() == L0)
+    Coeff0 = AR->getStepRecurrence(SE);
+  if (AR->getLoop() == L1)
+    Coeff1 = AR->getStepRecurrence(SE);
+  getAddRecCoefficients(SE, AR->getStart(), L0, Coeff0, L1, Coeff1);
+}
+
 int LoopInterchangeProfitability::getInstrOrderCost() {
   unsigned GoodOrder, BadOrder;
   BadOrder = GoodOrder = 0;
   for (BasicBlock *BB : InnerLoop->blocks()) {
     for (Instruction &Ins : *BB) {
-      if (const GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(&Ins)) {
-        bool FoundInnerInduction = false;
-        bool FoundOuterInduction = false;
-        for (Value *Op : GEP->operands()) {
-          // Skip operands that are not SCEV-able.
-          if (!SE->isSCEVable(Op->getType()))
-            continue;
-
-          const SCEV *OperandVal = SE->getSCEV(Op);
-          const SCEVAddRecExpr *AR = dyn_cast<SCEVAddRecExpr>(OperandVal);
-          if (!AR)
-            continue;
+      if (!isa<LoadInst, StoreInst>(&Ins))
+        continue;
+      const SCEV *Ptr = SE->getSCEV(getLoadStorePointerOperand(&Ins));
+      std::optional<const SCEV *> OuterCoeff, InnerCoeff;
+      getAddRecCoefficients(*SE, Ptr, OuterLoop, OuterCoeff, InnerLoop,
+                            InnerCoeff);
+      if (!InnerCoeff.has_value() || !OuterCoeff.has_value())
+        continue;
 
-          // If we find the inner induction after an outer induction e.g.
-          // for(int i=0;i<N;i++)
-          //   for(int j=0;j<N;j++)
-          //     A[i][j] = A[i-1][j-1]+k;
-          // then it is a good order.
-          if (AR->getLoop() == InnerLoop) {
-            // We found an InnerLoop induction after OuterLoop induction. It is
-            // a good order.
-            FoundInnerInduction = true;
-            if (FoundOuterInduction) {
-              GoodOrder++;
-              break;
-            }
-          }
-          // If we find the outer induction after an inner induction e.g.
-          // for(int i=0;i<N;i++)
-          //   for(int j=0;j<N;j++)
-          //     A[j][i] = A[j-1][i-1]+k;
-          // then it is a bad order.
-          if (AR->getLoop() == OuterLoop) {
-            // We found an OuterLoop induction after InnerLoop induction. It is
-            // a bad order.
-            FoundOuterInduction = true;
-            if (FoundInnerInduction) {
-              BadOrder++;
-              break;
-            }
-          }
-        }
+      const SCEV *OuterStep = SE->getAbsExpr(*OuterCoeff, /*IsNSW=*/false);
+      const SCEV *InnerStep = SE->getAbsExpr(*InnerCoeff, /*IsNSW=*/false);
+      if (SE->isKnownPredicate(ICmpInst::ICMP_SLT, InnerStep, OuterStep)) {
----------------
kasuga-fj wrote:

Added. Does this statement make sense to you?

https://github.com/llvm/llvm-project/pull/181991


More information about the llvm-branch-commits mailing list