Skip to content

Commit fa3258e

Browse files
authored
[VPlan] Sink retrieving legacy costs to more specific computeCost impls. (#109708)
Make legacy cost retrieval independent of getInstructionForCost by sinking it to more specific ::computeCost implementation (specifically VPInterleaveRecipe::computeCost and VPSingleDefRecipe::computeCost). Inline getInstructionForCost to VPRecipeBase::cost(), as it is now only used to decide which recipes to skip during cost computation and when to apply forced costs. PR: #109708
1 parent 5b03efb commit fa3258e

File tree

2 files changed

+65
-31
lines changed

2 files changed

+65
-31
lines changed

llvm/lib/Transforms/Vectorize/VPlan.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -930,6 +930,10 @@ class VPSingleDefRecipe : public VPRecipeBase, public VPValue {
930930
const Instruction *getUnderlyingInstr() const {
931931
return cast<Instruction>(getUnderlyingValue());
932932
}
933+
934+
/// Return the cost of this VPSingleDefRecipe.
935+
InstructionCost computeCost(ElementCount VF,
936+
VPCostContext &Ctx) const override;
933937
};
934938

935939
/// Class to record LLVM IR flag for a recipe along with it.
@@ -1411,6 +1415,10 @@ class VPIRInstruction : public VPRecipeBase {
14111415

14121416
void execute(VPTransformState &State) override;
14131417

1418+
/// Return the cost of this VPIRInstruction.
1419+
InstructionCost computeCost(ElementCount VF,
1420+
VPCostContext &Ctx) const override;
1421+
14141422
Instruction &getInstruction() { return I; }
14151423

14161424
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
@@ -2391,6 +2399,10 @@ class VPInterleaveRecipe : public VPRecipeBase {
23912399
/// Generate the wide load or store, and shuffles.
23922400
void execute(VPTransformState &State) override;
23932401

2402+
/// Return the cost of this VPInterleaveRecipe.
2403+
InstructionCost computeCost(ElementCount VF,
2404+
VPCostContext &Ctx) const override;
2405+
23942406
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
23952407
/// Print the recipe.
23962408
void print(raw_ostream &O, const Twine &Indent,
@@ -2624,6 +2636,10 @@ class VPBranchOnMaskRecipe : public VPRecipeBase {
26242636
/// conditional branch.
26252637
void execute(VPTransformState &State) override;
26262638

2639+
/// Return the cost of this VPBranchOnMaskRecipe.
2640+
InstructionCost computeCost(ElementCount VF,
2641+
VPCostContext &Ctx) const override;
2642+
26272643
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
26282644
/// Print the recipe.
26292645
void print(raw_ostream &O, const Twine &Indent,

llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp

Lines changed: 49 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -280,33 +280,28 @@ void VPRecipeBase::moveBefore(VPBasicBlock &BB,
280280
insertBefore(BB, I);
281281
}
282282

283-
/// Return the underlying instruction to be used for computing \p R's cost via
284-
/// the legacy cost model. Return nullptr if there's no suitable instruction.
285-
static Instruction *getInstructionForCost(const VPRecipeBase *R) {
286-
if (auto *S = dyn_cast<VPSingleDefRecipe>(R))
287-
return dyn_cast_or_null<Instruction>(S->getUnderlyingValue());
288-
if (auto *IG = dyn_cast<VPInterleaveRecipe>(R))
289-
return IG->getInsertPos();
290-
// Currently the legacy cost model only calculates the instruction cost with
291-
// underlying instruction. Removing the WidenMem here will prevent
292-
// force-target-instruction-cost overwriting the cost of recipe with
293-
// underlying instruction which is inconsistent with the legacy model.
294-
// TODO: Remove WidenMem from this function when we don't need to compare to
295-
// the legacy model.
296-
if (auto *WidenMem = dyn_cast<VPWidenMemoryRecipe>(R))
297-
return &WidenMem->getIngredient();
298-
return nullptr;
299-
}
300-
301283
InstructionCost VPRecipeBase::cost(ElementCount VF, VPCostContext &Ctx) {
302-
auto *UI = getInstructionForCost(this);
303-
if (UI && Ctx.skipCostComputation(UI, VF.isVector()))
304-
return 0;
305-
306-
InstructionCost RecipeCost = computeCost(VF, Ctx);
307-
if (UI && ForceTargetInstructionCost.getNumOccurrences() > 0 &&
308-
RecipeCost.isValid())
309-
RecipeCost = InstructionCost(ForceTargetInstructionCost);
284+
// Get the underlying instruction for the recipe, if there is one. It is used
285+
// to
286+
// * decide if cost computation should be skipped for this recipe,
287+
// * apply forced target instruction cost.
288+
Instruction *UI = nullptr;
289+
if (auto *S = dyn_cast<VPSingleDefRecipe>(this))
290+
UI = dyn_cast_or_null<Instruction>(S->getUnderlyingValue());
291+
else if (auto *IG = dyn_cast<VPInterleaveRecipe>(this))
292+
UI = IG->getInsertPos();
293+
else if (auto *WidenMem = dyn_cast<VPWidenMemoryRecipe>(this))
294+
UI = &WidenMem->getIngredient();
295+
296+
InstructionCost RecipeCost;
297+
if (UI && Ctx.skipCostComputation(UI, VF.isVector())) {
298+
RecipeCost = 0;
299+
} else {
300+
RecipeCost = computeCost(VF, Ctx);
301+
if (UI && ForceTargetInstructionCost.getNumOccurrences() > 0 &&
302+
RecipeCost.isValid())
303+
RecipeCost = InstructionCost(ForceTargetInstructionCost);
304+
}
310305

311306
LLVM_DEBUG({
312307
dbgs() << "Cost of " << RecipeCost << " for VF " << VF << ": ";
@@ -317,11 +312,14 @@ InstructionCost VPRecipeBase::cost(ElementCount VF, VPCostContext &Ctx) {
317312

318313
InstructionCost VPRecipeBase::computeCost(ElementCount VF,
319314
VPCostContext &Ctx) const {
320-
// Compute the cost for the recipe falling back to the legacy cost model using
321-
// the underlying instruction. If there is no underlying instruction, returns
322-
// 0.
323-
Instruction *UI = getInstructionForCost(this);
324-
if (UI && isa<VPReplicateRecipe>(this)) {
315+
llvm_unreachable("subclasses should implement computeCost");
316+
}
317+
318+
InstructionCost VPSingleDefRecipe::computeCost(ElementCount VF,
319+
VPCostContext &Ctx) const {
320+
Instruction *UI = dyn_cast_or_null<Instruction>(getUnderlyingValue());
321+
if (isa<VPReplicateRecipe>(this)) {
322+
assert(UI && "VPReplicateRecipe must have an underlying instruction");
325323
// VPReplicateRecipe may be cloned as part of an existing VPlan-to-VPlan
326324
// transform, avoid computing their cost multiple times for now.
327325
Ctx.SkipCostComputation.insert(UI);
@@ -870,6 +868,13 @@ void VPIRInstruction::execute(VPTransformState &State) {
870868
State.Builder.SetInsertPoint(I.getParent(), std::next(I.getIterator()));
871869
}
872870

871+
InstructionCost VPIRInstruction::computeCost(ElementCount VF,
872+
VPCostContext &Ctx) const {
873+
// The recipe wraps an existing IR instruction on the border of VPlan's scope,
874+
// hence it does not contribute to the cost-modeling for the VPlan.
875+
return 0;
876+
}
877+
873878
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
874879
void VPIRInstruction::print(raw_ostream &O, const Twine &Indent,
875880
VPSlotTracker &SlotTracker) const {
@@ -2210,6 +2215,14 @@ void VPBranchOnMaskRecipe::execute(VPTransformState &State) {
22102215
ReplaceInstWithInst(CurrentTerminator, CondBr);
22112216
}
22122217

2218+
InstructionCost VPBranchOnMaskRecipe::computeCost(ElementCount VF,
2219+
VPCostContext &Ctx) const {
2220+
// The legacy cost model doesn't assign costs to branches for individual
2221+
// replicate regions. Match the current behavior in the VPlan cost model for
2222+
// now.
2223+
return 0;
2224+
}
2225+
22132226
void VPPredInstPHIRecipe::execute(VPTransformState &State) {
22142227
assert(State.Lane && "Predicated instruction PHI works per instance.");
22152228
Instruction *ScalarPredInst =
@@ -2892,6 +2905,11 @@ void VPInterleaveRecipe::print(raw_ostream &O, const Twine &Indent,
28922905
}
28932906
#endif
28942907

2908+
InstructionCost VPInterleaveRecipe::computeCost(ElementCount VF,
2909+
VPCostContext &Ctx) const {
2910+
return Ctx.getLegacyCost(IG->getInsertPos(), VF);
2911+
}
2912+
28952913
void VPCanonicalIVPHIRecipe::execute(VPTransformState &State) {
28962914
Value *Start = getStartValue()->getLiveInIRValue();
28972915
PHINode *Phi = PHINode::Create(Start->getType(), 2, "index");

0 commit comments

Comments
 (0)