[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:54 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);
+ }
+ }
----------------
fhahn wrote:
done thanks
https://github.com/llvm/llvm-project/pull/129402
More information about the llvm-commits
mailing list