[llvm] [VPlan] First step towards VPlan cost modeling (LegacyCM in CostCtx) (PR #92555)
via llvm-commits
llvm-commits at lists.llvm.org
Thu May 23 05:04:47 PDT 2024
================
@@ -7396,6 +7397,118 @@ LoopVectorizationPlanner::plan(ElementCount UserVF, unsigned UserIC) {
return VF;
}
+InstructionCost VPCostContext::getLegacyCost(Instruction *UI, ElementCount VF) {
+ return CM.getInstructionCost(UI, VF).first;
+}
+
+bool VPCostContext::skipForCostComputation(Instruction *UI) const {
+ return CM.VecValuesToIgnore.contains(UI) || SkipCostComputation.contains(UI);
+}
+
+InstructionCost LoopVectorizationPlanner::computeCost(VPlan &Plan,
+ ElementCount VF) const {
+ InstructionCost Cost = 0;
+ LLVMContext &Ctx = OrigLoop->getHeader()->getContext();
+ VPCostContext CostCtx(CM.TTI, Legal->getWidestInductionType(), Ctx, CM);
+
+ // Cost modeling for inductions is inaccurate in the legacy cost model
+ // compared to the recipes that are generated. To match here initially during
+ // VPlan cost model bring up directly use the induction costs from the legacy
+ // cost model and skip induction recipes. Note that we do this as
+ // pre-processing; the VPlan may not have any recipes associated with the
+ // original induction increment instruction.
+ // TODO: Switch to more accurate costing based on VPlan.
+ for (const auto &[IV, _] : Legal->getInductionVars()) {
+ Instruction *IVInc = cast<Instruction>(
+ IV->getIncomingValueForBlock(OrigLoop->getLoopLatch()));
+ InstructionCost InductionCost = CM.getInstructionCost(IVInc, VF).first;
+ LLVM_DEBUG({
+ dbgs() << "Cost of " << InductionCost << " for VF " << VF
+ << ":\n induction increment " << *IVInc << "\n";
+ IVInc->dump();
+ });
+ Cost += InductionCost;
+ CostCtx.SkipCostComputation.insert(IVInc);
+ }
+
+ // The legacy cost model has special logic to compute the cost of in-loop
+ // reductions, which may be smaller than the sum of all instructions involved
+ // in the reduction. Pre-compute the cost for now.
+ // TODO: Switch to costing based on VPlan once the logic has been ported.
+ for (const auto &[RedPhi, RdxDesc] : Legal->getReductionVars()) {
+ if (!CM.isInLoopReduction(RedPhi))
+ continue;
+
+ SmallVector<Instruction *, 4> ReductionOperations =
+ RdxDesc.getReductionOpChain(RedPhi, OrigLoop);
+ // Also include the operands of instructions in the chain, as the cost-model
+ // may mark extends as free.
+ for (unsigned I = 0, E = ReductionOperations.size(); I != E; ++I) {
+ for (Value *Op : ReductionOperations[I]->operands()) {
+ if (auto *I = dyn_cast<Instruction>(Op))
+ ReductionOperations.push_back(I);
+ }
+ }
+ for (Instruction *I : ReductionOperations) {
+ auto ReductionCost = CM.getReductionPatternCost(
+ I, VF, ToVectorTy(I->getType(), VF), TTI::TCK_RecipThroughput);
+ if (!ReductionCost)
+ continue;
+
+ if (!CostCtx.SkipCostComputation.insert(I).second)
+ continue;
+ LLVM_DEBUG(dbgs() << "Cost of " << ReductionCost << " for VF " << VF
+ << ":\n in-loop reduction " << *I << "\n");
+ Cost += *ReductionCost;
+ }
+ }
+
+ Cost += Plan.computeCost(VF, CostCtx);
+ // Add the cost for the backedge.
+ Cost += 1;
+ LLVM_DEBUG(dbgs() << "Cost for VF " << VF << ": " << Cost << "\n");
+ return Cost;
+}
+
+VPlan &LoopVectorizationPlanner::getBestPlan() const {
+ // If there is a single VPlan with a single VF, return it directly.
+ VPlan &FirstPlan = *VPlans[0];
+ if (VPlans.size() == 1 && size(FirstPlan.vectorFactors()) == 1)
+ return FirstPlan;
+
+ VPlan *BestPlan = &FirstPlan;
+ ElementCount ScalarVF = ElementCount::getFixed(1);
+ assert(hasPlanWithVF(ScalarVF) &&
+ "More than a single plan/VF w/o any plan having scalar VF");
+
+ InstructionCost ScalarCost = computeCost(
+ getBestPlanFor(ElementCount::getFixed(1)), ElementCount::getFixed(1));
----------------
ayalz wrote:
```suggestion
InstructionCost ScalarCost = computeCost(getBestPlanFor(ScalarVF), ScalarVF);
```
https://github.com/llvm/llvm-project/pull/92555
More information about the llvm-commits
mailing list