Skip to content

Commit 92e45cd

Browse files
committed
[VPlan] Move predication to VPlanTransform (NFC) (WIP).
This patch moves the logic to predicate and linearize a VPlan to a dedicated VPlan transform. The main logic to perform predication is ready to review, although there are few things to note that should be improved, either directly in the PR or in the future: * Edge and block masks are cached in VPRecipeBuilder, so they can be accessed during recipe construction. A better alternative may be to add mask operands to all VPInstructions that need them and use that during recipe construction * The mask caching in a map also means that this map needs updating each time a new recipe replaces a VPInstruction; this would also be handled by adding mask operands. Currently this is still WIP due to early-exit loop handling not working due to the exit conditions not being available in the initial VPlans. This will be fixed with #128419 and follow-ups All tests except early-exit loops are passing
1 parent 72791fe commit 92e45cd

8 files changed

+339
-311
lines changed

llvm/lib/Transforms/Vectorize/CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ add_llvm_component_library(LLVMVectorize
2323
VPlan.cpp
2424
VPlanAnalysis.cpp
2525
VPlanHCFGBuilder.cpp
26+
VPlanPredicator.cpp
2627
VPlanRecipes.cpp
2728
VPlanSLP.cpp
2829
VPlanTransforms.cpp

llvm/lib/Transforms/Vectorize/LoopVectorize.cpp

+27-259
Large diffs are not rendered by default.

llvm/lib/Transforms/Vectorize/VPRecipeBuilder.h

+18-27
Original file line numberDiff line numberDiff line change
@@ -73,11 +73,14 @@ class VPRecipeBuilder {
7373
/// if-conversion currently takes place during VPlan-construction, so these
7474
/// caches are only used at that stage.
7575
using EdgeMaskCacheTy =
76-
DenseMap<std::pair<BasicBlock *, BasicBlock *>, VPValue *>;
77-
using BlockMaskCacheTy = DenseMap<BasicBlock *, VPValue *>;
76+
DenseMap<std::pair<VPBasicBlock *, VPBasicBlock *>, VPValue *>;
77+
using BlockMaskCacheTy = DenseMap<VPBasicBlock *, VPValue *>;
7878
EdgeMaskCacheTy EdgeMaskCache;
79+
80+
public:
7981
BlockMaskCacheTy BlockMaskCache;
8082

83+
private:
8184
// VPlan construction support: Hold a mapping from ingredients to
8285
// their recipe.
8386
DenseMap<Instruction *, VPRecipeBase *> Ingredient2Recipe;
@@ -114,11 +117,6 @@ class VPRecipeBuilder {
114117
tryToOptimizeInductionTruncate(TruncInst *I, ArrayRef<VPValue *> Operands,
115118
VFRange &Range);
116119

117-
/// Handle non-loop phi nodes. Return a new VPBlendRecipe otherwise. Currently
118-
/// all such phi nodes are turned into a sequence of select instructions as
119-
/// the vectorizer currently performs full if-conversion.
120-
VPBlendRecipe *tryToBlend(PHINode *Phi, ArrayRef<VPValue *> Operands);
121-
122120
/// Handle call instructions. If \p CI can be widened for \p Range.Start,
123121
/// return a new VPWidenCallRecipe or VPWidenIntrinsicRecipe. Range.End may be
124122
/// decreased to ensure same decision from \p Range.Start to \p Range.End.
@@ -187,27 +185,20 @@ class VPRecipeBuilder {
187185
Ingredient2Recipe[I] = R;
188186
}
189187

190-
/// Create the mask for the vector loop header block.
191-
void createHeaderMask();
192-
193-
/// A helper function that computes the predicate of the block BB, assuming
194-
/// that the header block of the loop is set to True or the loop mask when
195-
/// tail folding.
196-
void createBlockInMask(BasicBlock *BB);
197-
188+
void setBlockInMask(VPBasicBlock *BB, VPValue *Mask) {
189+
assert(!BlockMaskCache.contains(BB) && "Mask already set");
190+
BlockMaskCache[BB] = Mask;
191+
}
198192
/// Returns the *entry* mask for the block \p BB.
199-
VPValue *getBlockInMask(BasicBlock *BB) const;
200-
201-
/// Create an edge mask for every destination of cases and/or default.
202-
void createSwitchEdgeMasks(SwitchInst *SI);
203-
204-
/// A helper function that computes the predicate of the edge between SRC
205-
/// and DST.
206-
VPValue *createEdgeMask(BasicBlock *Src, BasicBlock *Dst);
207-
208-
/// A helper that returns the previously computed predicate of the edge
209-
/// between SRC and DST.
210-
VPValue *getEdgeMask(BasicBlock *Src, BasicBlock *Dst) const;
193+
VPValue *getBlockInMask(VPBasicBlock *BB) const {
194+
return BlockMaskCache.lookup(BB);
195+
}
196+
void setEdgeMask(VPBasicBlock *Src, VPBasicBlock *Dst, VPValue *Mask) {
197+
EdgeMaskCache[{Src, Dst}] = Mask;
198+
}
199+
VPValue *getEdgeMask(VPBasicBlock *Src, VPBasicBlock *Dst) const {
200+
return EdgeMaskCache.lookup({Src, Dst});
201+
}
211202

212203
/// Return the recipe created for given ingredient.
213204
VPRecipeBase *getRecipe(Instruction *I) {

llvm/lib/Transforms/Vectorize/VPlanHCFGBuilder.cpp

+13-11
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ class PlainCFGBuilder {
7575
: TheLoop(Lp), LI(LI), Plan(P) {}
7676

7777
/// Build plain CFG for TheLoop and connects it to Plan's entry.
78-
void buildPlainCFG(DenseMap<VPBlockBase *, BasicBlock *> &VPB2IRBB);
78+
void buildPlainCFG();
7979
};
8080
} // anonymous namespace
8181

@@ -340,19 +340,24 @@ void PlainCFGBuilder::createVPInstructionsForVPBB(VPBasicBlock *VPBB,
340340
for (Value *Op : Inst->operands())
341341
VPOperands.push_back(getOrCreateVPOperand(Op));
342342

343-
// Build VPInstruction for any arbitrary Instruction without specific
344-
// representation in VPlan.
345-
NewR = cast<VPInstruction>(
346-
VPIRBuilder.createNaryOp(Inst->getOpcode(), VPOperands, Inst));
343+
if (auto *ICmp = dyn_cast<ICmpInst>(Inst)) {
344+
NewR = cast<VPInstruction>(VPIRBuilder.createICmp(
345+
ICmp->getPredicate(), VPOperands[0], VPOperands[1]));
346+
NewR->setUnderlyingValue(ICmp);
347+
} else {
348+
// Build VPInstruction for any arbitrary Instruction without specific
349+
// representation in VPlan.
350+
NewR = cast<VPInstruction>(
351+
VPIRBuilder.createNaryOp(Inst->getOpcode(), VPOperands, Inst));
352+
}
347353
}
348354

349355
IRDef2VPValue[Inst] = NewR;
350356
}
351357
}
352358

353359
// Main interface to build the plain CFG.
354-
void PlainCFGBuilder::buildPlainCFG(
355-
DenseMap<VPBlockBase *, BasicBlock *> &VPB2IRBB) {
360+
void PlainCFGBuilder::buildPlainCFG() {
356361
// 0. Reuse the top-level region, vector-preheader and exit VPBBs from the
357362
// skeleton. These were created directly rather than via getOrCreateVPBB(),
358363
// revisit them now to update BB2VPBB. Note that header/entry and
@@ -481,14 +486,11 @@ void PlainCFGBuilder::buildPlainCFG(
481486
// have a VPlan counterpart. Fix VPlan header phi by adding their
482487
// corresponding VPlan operands.
483488
fixHeaderPhis();
484-
485-
for (const auto &[IRBB, VPB] : BB2VPBB)
486-
VPB2IRBB[VPB] = IRBB;
487489
}
488490

489491
void VPlanHCFGBuilder::buildPlainCFG() {
490492
PlainCFGBuilder PCFGBuilder(TheLoop, LI, Plan);
491-
PCFGBuilder.buildPlainCFG(VPB2IRBB);
493+
PCFGBuilder.buildPlainCFG();
492494
}
493495

494496
// Public interface to build a H-CFG.

llvm/lib/Transforms/Vectorize/VPlanHCFGBuilder.h

-12
Original file line numberDiff line numberDiff line change
@@ -53,10 +53,6 @@ class VPlanHCFGBuilder {
5353
// are introduced.
5454
VPDominatorTree VPDomTree;
5555

56-
/// Map of create VP blocks to their input IR basic blocks, if they have been
57-
/// created for a input IR basic block.
58-
DenseMap<VPBlockBase *, BasicBlock *> VPB2IRBB;
59-
6056
/// Build plain CFG for TheLoop and connects it to Plan's entry.
6157
void buildPlainCFG();
6258

@@ -66,14 +62,6 @@ class VPlanHCFGBuilder {
6662

6763
/// Build H-CFG for TheLoop and update Plan accordingly.
6864
void buildHierarchicalCFG();
69-
70-
/// Return the input IR BasicBlock corresponding to \p VPB. Returns nullptr if
71-
/// there is no such corresponding block.
72-
/// FIXME: This is a temporary workaround to drive the createBlockInMask.
73-
/// Remove once mask creation is done on VPlan.
74-
BasicBlock *getIRBBForVPB(const VPBlockBase *VPB) const {
75-
return VPB2IRBB.lookup(VPB);
76-
}
7765
};
7866
} // namespace llvm
7967

0 commit comments

Comments
 (0)