[PATCH] D114917: [LoopInterchange] Enable loop interchange with multiple inner loop indvars

Bardia Mahjour via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Fri Dec 3 14:07:59 PST 2021


bmahjour added inline comments.


================
Comment at: llvm/lib/Transforms/Scalar/LoopInterchange.cpp:338
+  bool isLoopStructureUnderstood(
+      const SmallVectorImpl<PHINode *> &InnerInductionVar);
 
----------------
[nit] InnerInductionVar -> InnerInductionVars


================
Comment at: llvm/lib/Transforms/Scalar/LoopInterchange.cpp:647
 bool LoopInterchangeLegality::isLoopStructureUnderstood(
-    PHINode *InnerInduction) {
-  unsigned Num = InnerInduction->getNumOperands();
+    const SmallVectorImpl<PHINode *> &Inductions) {
   BasicBlock *InnerLoopPreheader = InnerLoop->getLoopPreheader();
----------------
suggestion: Inductions ->InnerInductions


================
Comment at: llvm/lib/Transforms/Scalar/LoopInterchange.cpp:696
     std::function<bool(Value *)> IsPathToIndVar;
-    IsPathToIndVar = [&InnerInduction, &IsPathToIndVar](Value *V) -> bool {
-      if (V == InnerInduction)
+    IsPathToIndVar = [&Inductions, &IsPathToIndVar](Value *V) -> bool {
+      if (std::find(Inductions.begin(), Inductions.end(), V) !=
----------------
suggestion: `Value *V` -> `const Value *V`


================
Comment at: llvm/lib/Transforms/Scalar/LoopInterchange.cpp:697-698
+    IsPathToIndVar = [&Inductions, &IsPathToIndVar](Value *V) -> bool {
+      if (std::find(Inductions.begin(), Inductions.end(), V) !=
+          Inductions.end())
         return true;
----------------
suggestion: use `llvm::is_contained()`


================
Comment at: llvm/lib/Transforms/Scalar/LoopInterchange.cpp:716
+    if (IsPathToIndVar(Op0) && IsPathToIndVar(Op1))
+      return true;
+
----------------
What if we have a loop condition like this:
```
for (...)
  for (; i < j; i++, j--)
```

I'm not sure if this would be legal to interchange (need to think about it more). I would have expected we return false if both left and right are functions of inner-ivs, to be conservatively correct.

Should have a test for this case also.


================
Comment at: llvm/lib/Transforms/Scalar/LoopInterchange.cpp:892
 
-  // TODO: Current limitation: Since we split the inner loop latch at the point
-  // were induction variable is incremented (induction.next); We cannot have
-  // more than 1 user of induction.next since it would result in broken code
-  // after split.
-  // e.g.
-  // for(i=0;i<N;i++) {
-  //    for(j = 0;j<M;j++) {
-  //      A[j+1][i+2] = A[j][i]+k;
-  //  }
-  // }
-  Instruction *InnerIndexVarInc = nullptr;
-  if (InnerInductionVar->getIncomingBlock(0) == InnerLoopPreHeader)
-    InnerIndexVarInc =
-        dyn_cast<Instruction>(InnerInductionVar->getIncomingValue(1));
-  else
-    InnerIndexVarInc =
-        dyn_cast<Instruction>(InnerInductionVar->getIncomingValue(0));
-
-  if (!InnerIndexVarInc) {
-    LLVM_DEBUG(
-        dbgs() << "Did not find an instruction to increment the induction "
-               << "variable.\n");
-    ORE->emit([&]() {
-      return OptimizationRemarkMissed(DEBUG_TYPE, "NoIncrementInInner",
-                                      InnerLoop->getStartLoc(),
-                                      InnerLoop->getHeader())
-             << "The inner loop does not increment the induction variable.";
-    });
-    return true;
+  InnerLoopInductions = Inductions;
+  SmallPtrSet<Instruction *, 8> InnerIndexVarIncs;
----------------
why do we need this copy?


================
Comment at: llvm/lib/Transforms/Scalar/LoopInterchange.cpp:1401
+              UserI->getParent() == NewLatch ||
+              std::find(InductionPHIs.begin(), InductionPHIs.end(), UserI) !=
+                   InductionPHIs.end())
----------------
use `llvm::is_contained()`


================
Comment at: llvm/lib/Transforms/Scalar/LoopInterchange.cpp:1411
               this->LI->getLoopFor(OpI->getParent()) != this->InnerLoop ||
-              OpI == InductionPHI)
+              std::find(InductionPHIs.begin(), InductionPHIs.end(), OpI) !=
+                  InductionPHIs.end())
----------------
use `llvm::is_contained()`


================
Comment at: llvm/lib/Transforms/Scalar/LoopInterchange.cpp:1729
+      continue;
+    InnerLoopPHIs.push_back(cast<PHINode>(&PHI));
+  }
----------------
Why did we need to check `OuterInnerReductions` before and not anymore? 


================
Comment at: llvm/test/Transforms/LoopInterchange/interchangeable-innerloop-multiple-indvars.ll:16
+;;     e = 5;
+;;     for (; d, e; d--, e--)
+;;       a |= b[d][c + 9];
----------------
The loop latch in the IR only uses one IV anyway, so can we simplify this to only use one IV for the condition? 
Please also add a test where more than one IV is used in the latch.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D114917/new/

https://reviews.llvm.org/D114917



More information about the llvm-commits mailing list