[llvm] [VPlan] Introduce child regions as VPlan transform. (PR #129402)

Florian Hahn via llvm-commits llvm-commits at lists.llvm.org
Wed Apr 16 02:41:55 PDT 2025


================
@@ -14,26 +14,95 @@
 #include "LoopVectorizationPlanner.h"
 #include "VPlan.h"
 #include "VPlanCFG.h"
+#include "VPlanDominatorTree.h"
 #include "VPlanTransforms.h"
 #include "llvm/Analysis/LoopInfo.h"
 #include "llvm/Analysis/ScalarEvolution.h"
 
 using namespace llvm;
 
-void VPlanTransforms::introduceTopLevelVectorLoopRegion(
-    VPlan &Plan, Type *InductionTy, PredicatedScalarEvolution &PSE,
-    bool RequiresScalarEpilogueCheck, bool TailFolded, Loop *TheLoop) {
-  // TODO: Generalize to introduce all loop regions.
-  auto *HeaderVPBB = cast<VPBasicBlock>(Plan.getEntry()->getSingleSuccessor());
-  VPBlockUtils::disconnectBlocks(Plan.getEntry(), HeaderVPBB);
+/// Checks if \p HeaderVPB is a loop header block in the plain CFG; that is, it
+/// has exactly 2 predecessors (preheader and latch), where the block
+/// dominates the latch and the preheader dominates the block. If it is a
+/// header block, returns a pair with the corresponding preheader and latch
+/// blocks. Otherwise return std::nullopt.
+static std::optional<std::pair<VPBasicBlock *, VPBasicBlock *>>
+getPreheaderAndLatch(VPBlockBase *HeaderVPB, const VPDominatorTree &VPDT) {
+  ArrayRef<VPBlockBase *> Preds = HeaderVPB->getPredecessors();
+  if (Preds.size() != 2)
+    return std::nullopt;
 
-  VPBasicBlock *OriginalLatch =
-      cast<VPBasicBlock>(HeaderVPBB->getSinglePredecessor());
-  VPBlockUtils::disconnectBlocks(OriginalLatch, HeaderVPBB);
-  VPBasicBlock *VecPreheader = Plan.createVPBasicBlock("vector.ph");
-  VPBlockUtils::connectBlocks(Plan.getEntry(), VecPreheader);
-  assert(OriginalLatch->getNumSuccessors() == 0 &&
-         "Plan should end at top level latch");
+  auto *PreheaderVPBB = cast<VPBasicBlock>(Preds[0]);
+  auto *LatchVPBB = cast<VPBasicBlock>(Preds[1]);
+  if (VPDT.dominates(PreheaderVPBB, HeaderVPB) &&
+      VPDT.dominates(HeaderVPB, LatchVPBB))
+    return {std::make_pair(PreheaderVPBB, LatchVPBB)};
+
+  std::swap(PreheaderVPBB, LatchVPBB);
+  if (VPDT.dominates(PreheaderVPBB, HeaderVPB) &&
+      VPDT.dominates(HeaderVPB, LatchVPBB))
+    return {std::make_pair(PreheaderVPBB, LatchVPBB)};
+
+  return std::nullopt;
+}
+
+/// Try to create a new VPRegionBlock if there is a loop starting at \p
+/// HeaderVPB.
+static void tryToCreateLoopRegion(VPlan &Plan, VPBlockBase *HeaderVPB,
+                                  VPDominatorTree &VPDT) {
+  auto Res = getPreheaderAndLatch(HeaderVPB, VPDT);
+  if (!Res)
+    return;
+
+  const auto &[PreheaderVPBB, LatchVPBB] = *Res;
+
+  // Swap the operands of header phis if needed. After creating the region, the
+  // incoming value from the preheader must be the first operand and the one
+  // from the latch must be the second operand.
+  if (HeaderVPB->getPredecessors()[0] != PreheaderVPBB) {
+    for (VPRecipeBase &R : cast<VPBasicBlock>(HeaderVPB)->phis()) {
+      VPValue *Inc0 = R.getOperand(0);
+      R.setOperand(0, R.getOperand(1));
+      R.setOperand(1, Inc0);
+    }
+  }
+  VPBlockUtils::disconnectBlocks(PreheaderVPBB, HeaderVPB);
+  VPBlockUtils::disconnectBlocks(LatchVPBB, HeaderVPB);
+  VPBlockBase *Succ = LatchVPBB->getSingleSuccessor();
+  assert(LatchVPBB->getNumSuccessors() <= 1 &&
+         "Latch has more than one successor");
+  if (Succ)
+    VPBlockUtils::disconnectBlocks(LatchVPBB, Succ);
+
+  auto *R = Plan.createVPRegionBlock(HeaderVPB, LatchVPBB, "",
+                                     false /*isReplicator*/);
+  R->setParent(HeaderVPB->getParent());
+  // All VPBB's reachable shallowly from HeaderVPB belong to top level loop,
+  // because VPlan is expected to end at top level latch disconnected above.
+  for (VPBlockBase *VPBB : vp_depth_first_shallow(HeaderVPB))
+    VPBB->setParent(R);
+
+  VPBlockUtils::insertBlockAfter(R, PreheaderVPBB);
+  if (Succ)
+    VPBlockUtils::connectBlocks(R, Succ);
+}
+
+void VPlanTransforms::createLoopRegions(VPlan &Plan, Type *InductionTy,
+                                        PredicatedScalarEvolution &PSE,
+                                        bool RequiresScalarEpilogueCheck,
+                                        bool TailFolded, Loop *TheLoop) {
+  VPDominatorTree VPDT;
+  VPDT.recalculate(Plan);
+  for (VPBlockBase *HeaderVPB : vp_depth_first_shallow(Plan.getEntry()))
+    tryToCreateLoopRegion(Plan, HeaderVPB, VPDT);
----------------
fhahn wrote:

done thanks!

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


More information about the llvm-commits mailing list