Skip to content

Commit 39c8e87

Browse files
authored
[VPlan] Move recording of Inst->VPValue to VPRecipeBuilder (NFCI). (#84464)
Instead of keeping a mapping of Inst->VPValues (of their corresponding recipes) in VPlan's Value2VPValue mapping, keep it in VPRecipeBuilder instead. After recently replacing the last user of this mapping after initial construction, this mapping is only needed for recipe construction (to map IR operands to VPValue operands). By moving the mapping, VPlan's VPValue tracking can be simplified and limited only to live-ins. It also allows removing disableValue2VPValue and associated machinery & asserts. PR: #84464
1 parent 3a63f73 commit 39c8e87

File tree

4 files changed

+46
-76
lines changed

4 files changed

+46
-76
lines changed

llvm/lib/Transforms/Vectorize/LoopVectorize.cpp

+18-29
Original file line numberDiff line numberDiff line change
@@ -7898,6 +7898,18 @@ void LoopVectorizationPlanner::buildVPlans(ElementCount MinVF,
78987898
}
78997899
}
79007900

7901+
iterator_range<mapped_iterator<Use *, std::function<VPValue *(Value *)>>>
7902+
VPRecipeBuilder::mapToVPValues(User::op_range Operands) {
7903+
std::function<VPValue *(Value *)> Fn = [this](Value *Op) {
7904+
if (auto *I = dyn_cast<Instruction>(Op)) {
7905+
if (auto *R = Ingredient2Recipe.lookup(I))
7906+
return R->getVPSingleValue();
7907+
}
7908+
return Plan.getVPValueOrAddLiveIn(Op);
7909+
};
7910+
return map_range(Operands, Fn);
7911+
}
7912+
79017913
VPValue *VPRecipeBuilder::createEdgeMask(BasicBlock *Src, BasicBlock *Dst) {
79027914
assert(is_contained(predecessors(Dst), Src) && "Invalid edge");
79037915

@@ -7922,7 +7934,7 @@ VPValue *VPRecipeBuilder::createEdgeMask(BasicBlock *Src, BasicBlock *Dst) {
79227934
if (OrigLoop->isLoopExiting(Src))
79237935
return EdgeMaskCache[Edge] = SrcMask;
79247936

7925-
VPValue *EdgeMask = Plan.getVPValueOrAddLiveIn(BI->getCondition());
7937+
VPValue *EdgeMask = getVPValueOrAddLiveIn(BI->getCondition(), Plan);
79267938
assert(EdgeMask && "No Edge Mask found for condition");
79277939

79287940
if (BI->getSuccessor(0) != Dst)
@@ -8383,7 +8395,7 @@ VPReplicateRecipe *VPRecipeBuilder::handleReplication(Instruction *I,
83838395
BlockInMask = getBlockInMask(I->getParent());
83848396
}
83858397

8386-
auto *Recipe = new VPReplicateRecipe(I, Plan.mapToVPValues(I->operands()),
8398+
auto *Recipe = new VPReplicateRecipe(I, mapToVPValues(I->operands()),
83878399
IsUniform, BlockInMask);
83888400
return Recipe;
83898401
}
@@ -8399,10 +8411,6 @@ VPRecipeBuilder::tryToCreateWidenRecipe(Instruction *Instr,
83998411
if (Phi->getParent() != OrigLoop->getHeader())
84008412
return tryToBlend(Phi, Operands);
84018413

8402-
// Always record recipes for header phis. Later first-order recurrence phis
8403-
// can have earlier phis as incoming values.
8404-
recordRecipeOf(Phi);
8405-
84068414
if ((Recipe = tryToOptimizeInductionPHI(Phi, Operands, Range)))
84078415
return Recipe;
84088416

@@ -8427,14 +8435,6 @@ VPRecipeBuilder::tryToCreateWidenRecipe(Instruction *Instr,
84278435
PhiRecipe = new VPFirstOrderRecurrencePHIRecipe(Phi, *StartV);
84288436
}
84298437

8430-
// Record the incoming value from the backedge, so we can add the incoming
8431-
// value from the backedge after all recipes have been created.
8432-
auto *Inc = cast<Instruction>(
8433-
Phi->getIncomingValueForBlock(OrigLoop->getLoopLatch()));
8434-
auto RecipeIter = Ingredient2Recipe.find(Inc);
8435-
if (RecipeIter == Ingredient2Recipe.end())
8436-
recordRecipeOf(Inc);
8437-
84388438
PhisToFix.push_back(PhiRecipe);
84398439
return PhiRecipe;
84408440
}
@@ -8522,7 +8522,7 @@ static void addCanonicalIVRecipes(VPlan &Plan, Type *IdxTy, bool HasNUW,
85228522
// Add exit values to \p Plan. VPLiveOuts are added for each LCSSA phi in the
85238523
// original exit block.
85248524
static void addUsersInExitBlock(VPBasicBlock *HeaderVPBB, Loop *OrigLoop,
8525-
VPlan &Plan) {
8525+
VPRecipeBuilder &Builder, VPlan &Plan) {
85268526
BasicBlock *ExitBB = OrigLoop->getUniqueExitBlock();
85278527
BasicBlock *ExitingBB = OrigLoop->getExitingBlock();
85288528
// Only handle single-exit loops with unique exit blocks for now.
@@ -8533,7 +8533,7 @@ static void addUsersInExitBlock(VPBasicBlock *HeaderVPBB, Loop *OrigLoop,
85338533
for (PHINode &ExitPhi : ExitBB->phis()) {
85348534
Value *IncomingValue =
85358535
ExitPhi.getIncomingValueForBlock(ExitingBB);
8536-
VPValue *V = Plan.getVPValueOrAddLiveIn(IncomingValue);
8536+
VPValue *V = Builder.getVPValueOrAddLiveIn(IncomingValue, Plan);
85378537
Plan.addLiveOut(&ExitPhi, V);
85388538
}
85398539
}
@@ -8603,9 +8603,6 @@ LoopVectorizationPlanner::tryToBuildVPlanWithVPRecipes(VFRange &Range) {
86038603
if (!getDecisionAndClampRange(applyIG, Range))
86048604
continue;
86058605
InterleaveGroups.insert(IG);
8606-
for (unsigned i = 0; i < IG->getFactor(); i++)
8607-
if (Instruction *Member = IG->getMember(i))
8608-
RecipeBuilder.recordRecipeOf(Member);
86098606
};
86108607

86118608
// ---------------------------------------------------------------------------
@@ -8647,7 +8644,7 @@ LoopVectorizationPlanner::tryToBuildVPlanWithVPRecipes(VFRange &Range) {
86478644
Operands.push_back(Plan->getVPValueOrAddLiveIn(
86488645
Phi->getIncomingValueForBlock(OrigLoop->getLoopPreheader())));
86498646
} else {
8650-
auto OpRange = Plan->mapToVPValues(Instr->operands());
8647+
auto OpRange = RecipeBuilder.mapToVPValues(Instr->operands());
86518648
Operands = {OpRange.begin(), OpRange.end()};
86528649
}
86538650

@@ -8662,10 +8659,6 @@ LoopVectorizationPlanner::tryToBuildVPlanWithVPRecipes(VFRange &Range) {
86628659
RecipeBuilder.tryToCreateWidenRecipe(Instr, Operands, Range, VPBB);
86638660
if (!Recipe)
86648661
Recipe = RecipeBuilder.handleReplication(Instr, Range);
8665-
for (auto *Def : Recipe->definedValues()) {
8666-
auto *UV = Def->getUnderlyingValue();
8667-
Plan->addVPValue(UV, Def);
8668-
}
86698662

86708663
RecipeBuilder.setRecipe(Instr, Recipe);
86718664
if (isa<VPHeaderPHIRecipe>(Recipe)) {
@@ -8697,7 +8690,7 @@ LoopVectorizationPlanner::tryToBuildVPlanWithVPRecipes(VFRange &Range) {
86978690
// and there is nothing to fix from vector loop; phis should have incoming
86988691
// from scalar loop only.
86998692
} else
8700-
addUsersInExitBlock(HeaderVPBB, OrigLoop, *Plan);
8693+
addUsersInExitBlock(HeaderVPBB, OrigLoop, RecipeBuilder, *Plan);
87018694

87028695
assert(isa<VPRegionBlock>(Plan->getVectorLoopRegion()) &&
87038696
!Plan->getVectorLoopRegion()->getEntryBasicBlock()->empty() &&
@@ -8765,10 +8758,6 @@ LoopVectorizationPlanner::tryToBuildVPlanWithVPRecipes(VFRange &Range) {
87658758
Plan->getVPValueOrAddLiveIn(StrideV)->replaceAllUsesWith(ConstVPV);
87668759
}
87678760

8768-
// From this point onwards, VPlan-to-VPlan transformations may change the plan
8769-
// in ways that accessing values using original IR values is incorrect.
8770-
Plan->disableValue2VPValue();
8771-
87728761
VPlanTransforms::dropPoisonGeneratingRecipes(*Plan, [this](BasicBlock *BB) {
87738762
return Legal->blockNeedsPredication(BB);
87748763
});

llvm/lib/Transforms/Vectorize/VPRecipeBuilder.h

+18-17
Original file line numberDiff line numberDiff line change
@@ -52,9 +52,8 @@ class VPRecipeBuilder {
5252
EdgeMaskCacheTy EdgeMaskCache;
5353
BlockMaskCacheTy BlockMaskCache;
5454

55-
// VPlan-VPlan transformations support: Hold a mapping from ingredients to
56-
// their recipe. To save on memory, only do so for selected ingredients,
57-
// marked by having a nullptr entry in this map.
55+
// VPlan construction support: Hold a mapping from ingredients to
56+
// their recipe.
5857
DenseMap<Instruction *, VPRecipeBase *> Ingredient2Recipe;
5958

6059
/// Cross-iteration reduction & first-order recurrence phis for which we need
@@ -117,13 +116,10 @@ class VPRecipeBuilder {
117116
ArrayRef<VPValue *> Operands,
118117
VFRange &Range, VPBasicBlock *VPBB);
119118

120-
/// Set the recipe created for given ingredient. This operation is a no-op for
121-
/// ingredients that were not marked using a nullptr entry in the map.
119+
/// Set the recipe created for given ingredient.
122120
void setRecipe(Instruction *I, VPRecipeBase *R) {
123-
if (!Ingredient2Recipe.count(I))
124-
return;
125-
assert(Ingredient2Recipe[I] == nullptr &&
126-
"Recipe already set for ingredient");
121+
assert(!Ingredient2Recipe.contains(I) &&
122+
"Cannot reset recipe for instruction.");
127123
Ingredient2Recipe[I] = R;
128124
}
129125

@@ -146,14 +142,6 @@ class VPRecipeBuilder {
146142
/// between SRC and DST.
147143
VPValue *getEdgeMask(BasicBlock *Src, BasicBlock *Dst) const;
148144

149-
/// Mark given ingredient for recording its recipe once one is created for
150-
/// it.
151-
void recordRecipeOf(Instruction *I) {
152-
assert((!Ingredient2Recipe.count(I) || Ingredient2Recipe[I] == nullptr) &&
153-
"Recipe already set for ingredient");
154-
Ingredient2Recipe[I] = nullptr;
155-
}
156-
157145
/// Return the recipe created for given ingredient.
158146
VPRecipeBase *getRecipe(Instruction *I) {
159147
assert(Ingredient2Recipe.count(I) &&
@@ -171,6 +159,19 @@ class VPRecipeBuilder {
171159
/// Add the incoming values from the backedge to reduction & first-order
172160
/// recurrence cross-iteration phis.
173161
void fixHeaderPhis();
162+
163+
/// Returns a range mapping the values of the range \p Operands to their
164+
/// corresponding VPValues.
165+
iterator_range<mapped_iterator<Use *, std::function<VPValue *(Value *)>>>
166+
mapToVPValues(User::op_range Operands);
167+
168+
VPValue *getVPValueOrAddLiveIn(Value *V, VPlan &Plan) {
169+
if (auto *I = dyn_cast<Instruction>(V)) {
170+
if (auto *R = Ingredient2Recipe.lookup(I))
171+
return R->getVPSingleValue();
172+
}
173+
return Plan.getVPValueOrAddLiveIn(V);
174+
}
174175
};
175176
} // end namespace llvm
176177

llvm/lib/Transforms/Vectorize/VPlan.h

+3-22
Original file line numberDiff line numberDiff line change
@@ -2872,10 +2872,6 @@ class VPlan {
28722872
/// definitions are VPValues that hold a pointer to their underlying IR.
28732873
SmallVector<VPValue *, 16> VPLiveInsToFree;
28742874

2875-
/// Indicates whether it is safe use the Value2VPValue mapping or if the
2876-
/// mapping cannot be used any longer, because it is stale.
2877-
bool Value2VPValueEnabled = true;
2878-
28792875
/// Values used outside the plan.
28802876
MapVector<PHINode *, VPLiveOut *> LiveOuts;
28812877

@@ -2954,10 +2950,6 @@ class VPlan {
29542950
/// Returns VF * UF of the vector loop region.
29552951
VPValue &getVFxUF() { return VFxUF; }
29562952

2957-
/// Mark the plan to indicate that using Value2VPValue is not safe any
2958-
/// longer, because it may be stale.
2959-
void disableValue2VPValue() { Value2VPValueEnabled = false; }
2960-
29612953
void addVF(ElementCount VF) { VFs.insert(VF); }
29622954

29632955
void setVF(ElementCount VF) {
@@ -2987,8 +2979,7 @@ class VPlan {
29872979
void setName(const Twine &newName) { Name = newName.str(); }
29882980

29892981
void addVPValue(Value *V, VPValue *VPV) {
2990-
assert((Value2VPValueEnabled || VPV->isLiveIn()) &&
2991-
"Value2VPValue mapping may be out of date!");
2982+
assert(VPV->isLiveIn() && "VPV must be a live-in.");
29922983
assert(V && "Trying to add a null Value to VPlan");
29932984
assert(!Value2VPValue.count(V) && "Value already exists in VPlan");
29942985
Value2VPValue[V] = VPV;
@@ -2998,8 +2989,8 @@ class VPlan {
29982989
VPValue *getVPValue(Value *V) {
29992990
assert(V && "Trying to get the VPValue of a null Value");
30002991
assert(Value2VPValue.count(V) && "Value does not exist in VPlan");
3001-
assert((Value2VPValueEnabled || Value2VPValue[V]->isLiveIn()) &&
3002-
"Value2VPValue mapping may be out of date!");
2992+
assert(Value2VPValue[V]->isLiveIn() &&
2993+
"Only live-ins should be in mapping");
30032994
return Value2VPValue[V];
30042995
}
30052996

@@ -3030,16 +3021,6 @@ class VPlan {
30303021
LLVM_DUMP_METHOD void dump() const;
30313022
#endif
30323023

3033-
/// Returns a range mapping the values the range \p Operands to their
3034-
/// corresponding VPValues.
3035-
iterator_range<mapped_iterator<Use *, std::function<VPValue *(Value *)>>>
3036-
mapToVPValues(User::op_range Operands) {
3037-
std::function<VPValue *(Value *)> Fn = [this](Value *Op) {
3038-
return getVPValueOrAddLiveIn(Op);
3039-
};
3040-
return map_range(Operands, Fn);
3041-
}
3042-
30433024
/// Returns the VPRegionBlock of the vector loop.
30443025
VPRegionBlock *getVectorLoopRegion() {
30453026
return cast<VPRegionBlock>(getEntry()->getSingleSuccessor());

llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp

+7-8
Original file line numberDiff line numberDiff line change
@@ -48,15 +48,14 @@ void VPlanTransforms::VPInstructionsToVPRecipes(
4848
VPRecipeBase *NewRecipe = nullptr;
4949
if (auto *VPPhi = dyn_cast<VPWidenPHIRecipe>(&Ingredient)) {
5050
auto *Phi = cast<PHINode>(VPPhi->getUnderlyingValue());
51-
if (const auto *II = GetIntOrFpInductionDescriptor(Phi)) {
52-
VPValue *Start = Plan->getVPValueOrAddLiveIn(II->getStartValue());
53-
VPValue *Step =
54-
vputils::getOrCreateVPValueForSCEVExpr(*Plan, II->getStep(), SE);
55-
NewRecipe = new VPWidenIntOrFpInductionRecipe(Phi, Start, Step, *II);
56-
} else {
57-
Plan->addVPValue(Phi, VPPhi);
51+
const auto *II = GetIntOrFpInductionDescriptor(Phi);
52+
if (!II)
5853
continue;
59-
}
54+
55+
VPValue *Start = Plan->getVPValueOrAddLiveIn(II->getStartValue());
56+
VPValue *Step =
57+
vputils::getOrCreateVPValueForSCEVExpr(*Plan, II->getStep(), SE);
58+
NewRecipe = new VPWidenIntOrFpInductionRecipe(Phi, Start, Step, *II);
6059
} else {
6160
assert(isa<VPInstruction>(&Ingredient) &&
6261
"only VPInstructions expected here");

0 commit comments

Comments
 (0)