[PATCH] D143938: [VPlan] Compute costs for plans directly after construction.

Ayal Zaks via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Tue May 2 16:14:59 PDT 2023


Ayal added inline comments.


================
Comment at: llvm/lib/Transforms/Vectorize/LoopVectorizationPlanner.h:397
+  /// Determines if we have the infrastructure to vectorize loop \p L and its
+  /// epilogue, assuming the main loop is vectorized by \p VF.
+  bool isCandidateForEpilogueVectorization(const ElementCount VF) const;
----------------
nit (independent of this patch): \p VF is not needed either.


================
Comment at: llvm/lib/Transforms/Vectorize/LoopVectorizationPlanner.h:283
+      std::pair<VPlanPtr, SmallVector<std::pair<VectorizationFactor, bool>>>, 4>
+      VPlans;
 
----------------
fhahn wrote:
> Ayal wrote:
> > fhahn wrote:
> > > fhahn wrote:
> > > > Ayal wrote:
> > > > > Perhaps the following would be better, at-least when first moving VectorizationFactors from CM to LVP: keep `VPlans` as a vector of all VPlanPtrs, as its name suggests; hold all VectorizationFactors in a separate vector or set indexed by their ElementCount Width (as in LVP::plan()'s CandidateVFs)? Can also hold a map associating each VectorizationFactor with its VPlan, if needed; is the reverse mapping useful?
> > > > > 
> > > > > (Independent of this patch): Hold the boolean IsVec as a field inside VectorizationFactor, rename VectorizationFactor more accurately.
> > > > Thanks, I updated the code to use a separate mapping from VPlan->vector of pair<VectorizationFactor, bool>. This ensures that the costs are associated with a specific VPlan. WDYT?
> > > > 
> > > > As for the IsVec field, I am going to investigate if this is actually needed or if we can get the information from the existing VPlan.
> > > > As for the IsVec field, I am going to investigate if this is actually needed or if we can get the information from the existing VPlan.
> > > 
> > > We don't need it at this stage any longer, we can instead just avoid adding such VFs to CandidateVFs. Removed the boolean flag from LVP.
> > >> hold all VectorizationFactors in a separate vector or set indexed by their ElementCount Width (as in LVP::plan()'s CandidateVFs)? Can also hold a map associating each VectorizationFactor with its VPlan, if needed; is the reverse mapping useful?
> > 
> > > Thanks, I updated the code to use a separate mapping from VPlan->vector of pair<VectorizationFactor, bool>. This ensures that the costs are associated with a specific VPlan. WDYT?
> > 
> > A single cost is currently computed and associated with a specific VF as indicated by `expectedCost()`, `select[Epilogue]VectorizationFactor()` and LVP::plan()'s `CandidateVF`s; a single Plan is expected for each VF including 1 and BestVF. So LVP can hold all VectorizationFactors in a vector for now, or in a set indexed by Width, regardless of their Plans.
> > Can revisit this if/when the Plan associated with each VectorizationFactor and/or the set of VectorizationFactors corresponding to a Plan's `VFs` are needed. Sounds reasonable?
> Follow-up patches will break the 1-1 mapping from VFs->Cost e.g. when planning with multiple cost models there may be different plans for the same VFs but with different costs. For that, the VPlan->costs mapping seems to be required; happy to have VF->Cost mapping as intermediate step, but it might lead to less churn to use the Plan->costs mapping in this patch already?
This may indeed lead to less churn, but it would be good to reason about which mapping is needed along with a usage that needs it, such as planning with multiple cost models. Given that CM currently holds ProfitableVFs as a vector of VectorizationFactors, suffice for this patch to focus on moving such a vector to LVP?


================
Comment at: llvm/lib/Transforms/Vectorize/LoopVectorizationPlanner.h:352
+  VectorizationFactor selectVectorizationFactor();
+
+  VectorizationFactor
----------------
fhahn wrote:
> Ayal wrote:
> > /// ... (independent of this patch)
> added comment in 6fa07a87abc96c3b924be07ce446e79691a7f186 and moved it here in the patch.
Thanks!

Replace `::Disabled` with null/`optional`? (Independent of this patch. Along with finding a better name for VectorizationFactor)


================
Comment at: llvm/lib/Transforms/Vectorize/LoopVectorize.cpp:8712
+
+  if (!EnableCondStoresVectorization && CM.hasPredStores()) {
+    reportVectorizationFailure(
----------------
Bailing out of vectorizing a loop due to disallowed conditional stores should better be done by buildVPlansWithVPRecipes() "before" computing their costs / independent of CM? (Independent of this patch).


================
Comment at: llvm/lib/Transforms/Vectorize/LoopVectorize.cpp:5491
+  for (auto &Plan : VPlans) {
+    for (const auto &Candidate : getCandidateVFsFor(*Plan)) {
+      if (Candidate.Width.isScalar())
----------------
fhahn wrote:
> Ayal wrote:
> > Simply traverse all VFCandidates in a single loop as before?
> There's now no single vector condition all candidate VFs and costs. We either need to iterate over the entries in the map or over the plans, the latter seeming slightly preferable, as it will make it easy to return the associated plan as well (instead of later looking it up)
> There's now no single vector condition all candidate VFs and costs. We either need to iterate over the entries in the map or over the plans, the latter seeming slightly preferable, as it will make it easy to return the associated plan as well (instead of later looking it up)

OK, but we currently do look it up later.


================
Comment at: llvm/lib/Transforms/Vectorize/LoopVectorize.cpp:7561
   // Populate the set of Vectorization Factor Candidates.
   ElementCountSet VFCandidates;
   for (auto VF = ElementCount::getFixed(1);
----------------
fhahn wrote:
> Ayal wrote:
> > Worth continuing to pass `VFCandidates` to selectVectorizationFactor()? The former is still initialized to span range of all possible VF's, before trying to build VPlans, which will possibly exclude VF's. Passing VFCandidates to buildVPlansWithVPRecipes() would allow the latter to filter out non candidates (Fixed/Scalable), and then have selectVectorizationFactor() compute costs and select VF from within the remaining candidates? Can also introduce a separate LVP::computeCosts(VFCandidates).
> I am not sure; the main motivation of the patch is to compute the cost on construction and delaying cost computation until selectVectorizationFactor would still mostly retain the original behavior? AFAICT the original selectVectorizationFactor doesn't filter out candidates before computing the cost; Scalable VFs are only added to VFCandidates below depending on MaxFactors.ScalableVF. So if the target doesn't support scalable VFs, no VPlans with scalable VFs should be generated.
Agreed, cost should in the long term be computed as part of VPlan2VPlan transformations, which currently take place inside (the excessive) tryToBuildVPlanWithVPRecipes().


================
Comment at: llvm/lib/Transforms/Vectorize/LoopVectorize.cpp:8061
+    VPlans.emplace_back(buildVPlan(SubRange));
+    CandidateVFs[&*VPlans.back()] = SmallVector<VectorizationFactor>();
     VF = SubRange.End;
----------------
fhahn wrote:
> Ayal wrote:
> > Where/Are CandidateVFs filled when building w/o recipes?
> Do you mean for the native path? In that case selectVectorizationFactor isn't used yet, so CandidateVFs isn't used.
> 
> Once the change is in we could build on top and try to converge the native and ILV paths at this point and create plans for inner and outer loops and associate costs with the outer loop versions as well.
Worth a comment when defining VFCandidates that they serve only 'legacy' path.


================
Comment at: llvm/lib/Transforms/Vectorize/LoopVectorize.cpp:8688
+    if (!Plan) {
+      VF = SubRange.End;
+      continue;
----------------
fhahn wrote:
> Ayal wrote:
> > Could SubRange be excluded from VFCandidates here, for the latter to be traversed subsequently to compute costs independently, rather than fusing it with the construction of each Plan and its SubRange?
> Updated to retain the original loop and then compute the costs by iterating over all plans and computing costs for all VFs associated with them
OK, then worth keeping the original simpler `if (auto Plan = ...` version?

Or perhaps something like
```
  if (auto Plan = tryToBuildVPlanWithVPRecipes(SubRange, DeadInstructions)) {
    VPlans.push_back(std::move(*Plan));
    computePlanCosts(Plan, SubRange, Costs);
  }
```
where the latter may some day turn into `Costs.push_back(Plan->computeCost());`


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D143938/new/

https://reviews.llvm.org/D143938



More information about the llvm-commits mailing list