Skip to content

Commit b263c08

Browse files
authored
[VPlan] Move predication to VPlanTransform (NFC). (#128420)
This patch moves the logic to predicate and linearize a VPlan to a dedicated VPlan transform. It mostly ports the existing logic directly. There are a number of follow-ups planned in the near future to further improve on the implementation: * Edge and block masks are cached in VPPredicator, but the block masks are still made available to VPRecipeBuilder, so they can be accessed during recipe construction. As a follow-up, this should be replaced by adding 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. PR: #128420
1 parent dabc84c commit b263c08

File tree

7 files changed

+375
-333
lines changed

7 files changed

+375
-333
lines changed

llvm/lib/Transforms/Vectorize/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ add_llvm_component_library(LLVMVectorize
2525
VPlan.cpp
2626
VPlanAnalysis.cpp
2727
VPlanConstruction.cpp
28+
VPlanPredicator.cpp
2829
VPlanRecipes.cpp
2930
VPlanSLP.cpp
3031
VPlanTransforms.cpp

llvm/lib/Transforms/Vectorize/LoopVectorize.cpp

Lines changed: 35 additions & 265 deletions
Large diffs are not rendered by default.

llvm/lib/Transforms/Vectorize/VPRecipeBuilder.h

Lines changed: 20 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -68,15 +68,10 @@ class VPRecipeBuilder {
6868

6969
VPBuilder &Builder;
7070

71-
/// When we if-convert we need to create edge masks. We have to cache values
72-
/// so that we don't end up with exponential recursion/IR. Note that
73-
/// if-conversion currently takes place during VPlan-construction, so these
74-
/// caches are only used at that stage.
75-
using EdgeMaskCacheTy =
76-
DenseMap<std::pair<BasicBlock *, BasicBlock *>, VPValue *>;
77-
using BlockMaskCacheTy = DenseMap<BasicBlock *, VPValue *>;
78-
EdgeMaskCacheTy EdgeMaskCache;
79-
BlockMaskCacheTy BlockMaskCache;
71+
/// The mask of each VPBB, generated earlier and used for predicating recipes
72+
/// in VPBB.
73+
/// TODO: remove by applying predication when generating the masks.
74+
DenseMap<VPBasicBlock *, VPValue *> &BlockMaskCache;
8075

8176
// VPlan construction support: Hold a mapping from ingredients to
8277
// their recipe.
@@ -90,10 +85,6 @@ class VPRecipeBuilder {
9085
/// A mapping of partial reduction exit instructions to their scaling factor.
9186
DenseMap<const Instruction *, unsigned> ScaledReductionMap;
9287

93-
/// A mapping from VP blocks to IR blocks, used temporarily while migrating
94-
/// away from IR references.
95-
const DenseMap<const VPBlockBase *, BasicBlock *> &VPB2IRBB;
96-
9788
/// Loop versioning instance for getting noalias metadata guaranteed by
9889
/// runtime checks.
9990
LoopVersioning *LVer;
@@ -122,11 +113,6 @@ class VPRecipeBuilder {
122113
tryToOptimizeInductionTruncate(TruncInst *I, ArrayRef<VPValue *> Operands,
123114
VFRange &Range);
124115

125-
/// Handle non-loop phi nodes, returning a new VPBlendRecipe. Currently
126-
/// all such phi nodes are turned into a sequence of select instructions as
127-
/// the vectorizer currently performs full if-conversion.
128-
VPBlendRecipe *tryToBlend(VPWidenPHIRecipe *PhiR);
129-
130116
/// Handle call instructions. If \p CI can be widened for \p Range.Start,
131117
/// return a new VPWidenCallRecipe or VPWidenIntrinsicRecipe. Range.End may be
132118
/// decreased to ensure same decision from \p Range.Start to \p Range.End.
@@ -164,10 +150,11 @@ class VPRecipeBuilder {
164150
LoopVectorizationLegality *Legal,
165151
LoopVectorizationCostModel &CM,
166152
PredicatedScalarEvolution &PSE, VPBuilder &Builder,
167-
const DenseMap<const VPBlockBase *, BasicBlock *> &VPB2IRBB,
153+
DenseMap<VPBasicBlock *, VPValue *> &BlockMaskCache,
168154
LoopVersioning *LVer)
169155
: Plan(Plan), OrigLoop(OrigLoop), TLI(TLI), TTI(TTI), Legal(Legal),
170-
CM(CM), PSE(PSE), Builder(Builder), VPB2IRBB(VPB2IRBB), LVer(LVer) {}
156+
CM(CM), PSE(PSE), Builder(Builder), BlockMaskCache(BlockMaskCache),
157+
LVer(LVer) {}
171158

172159
std::optional<unsigned> getScalingForReduction(const Instruction *ExitInst) {
173160
auto It = ScaledReductionMap.find(ExitInst);
@@ -196,38 +183,11 @@ class VPRecipeBuilder {
196183
Ingredient2Recipe[I] = R;
197184
}
198185

199-
/// Create the mask for the vector loop header block.
200-
void createHeaderMask();
201-
202-
/// A helper function that computes the predicate of the block BB, assuming
203-
/// that the header block of the loop is set to True or the loop mask when
204-
/// tail folding.
205-
void createBlockInMask(const VPBasicBlock *VPBB) {
206-
return createBlockInMask(VPB2IRBB.lookup(VPBB));
186+
/// Returns the *entry* mask for block \p VPBB or null if the mask is
187+
/// all-true.
188+
VPValue *getBlockInMask(VPBasicBlock *VPBB) const {
189+
return BlockMaskCache.lookup(VPBB);
207190
}
208-
void createBlockInMask(BasicBlock *BB);
209-
210-
/// Returns the *entry* mask for the block \p VPBB.
211-
VPValue *getBlockInMask(const VPBasicBlock *VPBB) const {
212-
return getBlockInMask(VPB2IRBB.lookup(VPBB));
213-
}
214-
215-
/// Returns the *entry* mask for the block \p BB.
216-
VPValue *getBlockInMask(BasicBlock *BB) const;
217-
218-
/// Create an edge mask for every destination of cases and/or default.
219-
void createSwitchEdgeMasks(SwitchInst *SI);
220-
221-
/// A helper function that computes the predicate of the edge between SRC
222-
/// and DST.
223-
VPValue *createEdgeMask(BasicBlock *Src, BasicBlock *Dst);
224-
225-
/// A helper that returns the previously computed predicate of the edge
226-
/// between SRC and DST.
227-
VPValue *getEdgeMask(const VPBasicBlock *Src, const VPBasicBlock *Dst) const {
228-
return getEdgeMask(VPB2IRBB.lookup(Src), VPB2IRBB.lookup(Dst));
229-
}
230-
VPValue *getEdgeMask(BasicBlock *Src, BasicBlock *Dst) const;
231191

232192
/// Return the recipe created for given ingredient.
233193
VPRecipeBase *getRecipe(Instruction *I) {
@@ -252,6 +212,15 @@ class VPRecipeBuilder {
252212
}
253213
return Plan.getOrAddLiveIn(V);
254214
}
215+
216+
void updateBlockMaskCache(DenseMap<VPValue *, VPValue *> &Old2New) {
217+
for (auto &[_, V] : BlockMaskCache) {
218+
if (auto *New = Old2New.lookup(V)) {
219+
V->replaceAllUsesWith(New);
220+
V = New;
221+
}
222+
}
223+
}
255224
};
256225
} // end namespace llvm
257226

llvm/lib/Transforms/Vectorize/VPlanConstruction.cpp

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -65,9 +65,8 @@ class PlainCFGBuilder {
6565
PlainCFGBuilder(Loop *Lp, LoopInfo *LI)
6666
: TheLoop(Lp), LI(LI), Plan(std::make_unique<VPlan>(Lp)) {}
6767

68-
/// Build plain CFG for TheLoop and connects it to Plan's entry.
69-
std::unique_ptr<VPlan>
70-
buildPlainCFG(DenseMap<const VPBlockBase *, BasicBlock *> &VPB2IRBB);
68+
/// Build plain CFG for TheLoop and connect it to Plan's entry.
69+
std::unique_ptr<VPlan> buildPlainCFG();
7170
};
7271
} // anonymous namespace
7372

@@ -242,8 +241,7 @@ void PlainCFGBuilder::createVPInstructionsForVPBB(VPBasicBlock *VPBB,
242241
}
243242

244243
// Main interface to build the plain CFG.
245-
std::unique_ptr<VPlan> PlainCFGBuilder::buildPlainCFG(
246-
DenseMap<const VPBlockBase *, BasicBlock *> &VPB2IRBB) {
244+
std::unique_ptr<VPlan> PlainCFGBuilder::buildPlainCFG() {
247245
VPIRBasicBlock *Entry = cast<VPIRBasicBlock>(Plan->getEntry());
248246
BB2VPBB[Entry->getIRBasicBlock()] = Entry;
249247
for (VPIRBasicBlock *ExitVPBB : Plan->getExitBlocks())
@@ -334,18 +332,14 @@ std::unique_ptr<VPlan> PlainCFGBuilder::buildPlainCFG(
334332
}
335333
}
336334

337-
for (const auto &[IRBB, VPB] : BB2VPBB)
338-
VPB2IRBB[VPB] = IRBB;
339-
340335
LLVM_DEBUG(Plan->setName("Plain CFG\n"); dbgs() << *Plan);
341336
return std::move(Plan);
342337
}
343338

344-
std::unique_ptr<VPlan> VPlanTransforms::buildPlainCFG(
345-
Loop *TheLoop, LoopInfo &LI,
346-
DenseMap<const VPBlockBase *, BasicBlock *> &VPB2IRBB) {
339+
std::unique_ptr<VPlan> VPlanTransforms::buildPlainCFG(Loop *TheLoop,
340+
LoopInfo &LI) {
347341
PlainCFGBuilder Builder(TheLoop, &LI);
348-
return Builder.buildPlainCFG(VPB2IRBB);
342+
return Builder.buildPlainCFG();
349343
}
350344

351345
/// Checks if \p HeaderVPB is a loop header block in the plain CFG; that is, it

0 commit comments

Comments
 (0)