[PATCH] D142589: [LV] Perform recurrence sinking directly on VPlan.
Ayal Zaks via Phabricator via llvm-commits
llvm-commits at lists.llvm.org
Tue Jan 31 11:42:50 PST 2023
Ayal added a comment.
A very nice step forward! Raises a few thoughts regarding recipes of predicated instructions, arguably independent of the patch.
================
Comment at: llvm/lib/Transforms/Vectorize/LoopVectorize.cpp:8975
- // Introduce a recipe to combine the incoming and previous values of a
- // fixed-order recurrence.
- for (VPRecipeBase &R :
- Plan->getVectorLoopRegion()->getEntryBasicBlock()->phis()) {
- auto *RecurPhi = dyn_cast<VPFirstOrderRecurrencePHIRecipe>(&R);
- if (!RecurPhi)
- continue;
-
- VPRecipeBase *PrevRecipe = &RecurPhi->getBackedgeRecipe();
- // Fixed-order recurrences do not contain cycles, so this loop is guaranteed
- // to terminate.
- while (auto *PrevPhi =
- dyn_cast<VPFirstOrderRecurrencePHIRecipe>(PrevRecipe))
- PrevRecipe = &PrevPhi->getBackedgeRecipe();
- VPBasicBlock *InsertBlock = PrevRecipe->getParent();
- auto *Region = GetReplicateRegion(PrevRecipe);
- if (Region)
- InsertBlock = dyn_cast<VPBasicBlock>(Region->getSingleSuccessor());
- if (!InsertBlock) {
- InsertBlock = new VPBasicBlock(Region->getName() + ".succ");
- VPBlockUtils::insertBlockAfter(InsertBlock, Region);
- }
- if (Region || PrevRecipe->isPhi())
- Builder.setInsertPoint(InsertBlock, InsertBlock->getFirstNonPhi());
- else
- Builder.setInsertPoint(InsertBlock, std::next(PrevRecipe->getIterator()));
-
- auto *RecurSplice = cast<VPInstruction>(
- Builder.createNaryOp(VPInstruction::FirstOrderRecurrenceSplice,
- {RecurPhi, RecurPhi->getBackedgeValue()}));
-
- RecurPhi->replaceAllUsesWith(RecurSplice);
- // Set the first operand of RecurSplice to RecurPhi again, after replacing
- // all users.
- RecurSplice->setOperand(0, RecurPhi);
- }
+ VPlanTransforms::fixFirstOrderRecurrences(*Plan, Builder);
----------------
nit: FOR now stands for FixedOrderRecurrence which leads to fixFixedOrderRecurrences() ... how about addSplicesToFixedOrderRecurrences()?
================
Comment at: llvm/lib/Transforms/Vectorize/LoopVectorize.cpp:8929
// block after applying SinkAfter, which relies on the original
// position of the trunc.
assert(isa<TruncInst>(Instr));
----------------
Comment above deserves update.
================
Comment at: llvm/lib/Transforms/Vectorize/VPlan.h:1262
+ VPValue *getPreviousValue() { return getOperand(1); }
+
----------------
redundant - aka VPHeaderPHIRecipe::getBackedgeValue()?
================
Comment at: llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp:15
#include "VPlanTransforms.h"
+#include "VPRecipeBuilder.h"
#include "VPlanCFG.h"
----------------
nit: lex order?
================
Comment at: llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp:552
+
+static bool recipeComesBefore(const VPRecipeBase *A, const VPRecipeBase *B,
+ VPDominatorTree &VPDT) {
----------------
aka `dominates`?
Note for completeness: a recipe is considered to dominate itself, i.e., returns true if the same recipe is passed as both A and B.
================
Comment at: llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp:579
+ if (RegionA && RegionB)
+ return VPDT.dominates(RegionA, RegionB);
+
----------------
This checking of regions is needed rather than recipeComesBefore()'s checking of parenting basic blocks, because neither basic block dominates the other when they reside in replicate regions? What if only A resides inside a replicate region?
When two recipes belong to the same block, their dominance is clear. Otherwise, if any recipe resides inside a replicate region, should the exit block of the replicate region be considered instead of its parenting basic block? Thereby collapsing the region into a node, or considering a pred-inst-phi instead of its pred-inst.
================
Comment at: llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp:609
+ for (unsigned I = 0; I != WorkList.size(); ++I) {
+ VPRecipeBase *Current = WorkList[I];
+ for (VPUser *User : Current->getVPSingleValue()->users()) {
----------------
nit: assert with an error message that Current has at most a single value?
================
Comment at: llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp:622
+ if (recipeComesBefore(Target, Curr, VPDT))
+ Target = Curr;
+ }
----------------
Clearly SinkCandidate should not be sunk past any of its operands, but this is a bit confusing: Curr dominates SinkCandidate by definition of being its operand, so if Previous=Target dominates Curr it follows that Previous dominates SinkCandidate - however such SinkCandidates are filtered from entering InstrsToSink?
================
Comment at: llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp:700
+ VPBasicBlock *InsertBlock = Previous->getParent();
+ auto *Region = GetReplicateRegion(Previous);
+ if (Region)
----------------
(Independent of this patch) Another way of thinking about this: if Previous resides inside a replicate region, treat its pred-inst-phi as if it were Previous? Indeed, such a predicated instruction does not dominate the latch...
================
Comment at: llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp:703
+ InsertBlock = dyn_cast<VPBasicBlock>(Region->getSingleSuccessor());
+ if (!InsertBlock) {
+ InsertBlock = new VPBasicBlock(Region->getName() + ".succ");
----------------
(Independent of this patch) Should this be under the `if (Region)`? I.e., Previous surely has a VPBasicBlock parent, and Region has a single successor, but the latter could potentially be a region rather than a VPBasicBlock?
================
Comment at: llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp:707
+ }
+ if (Region || Previous->isPhi())
+ Builder.setInsertPoint(InsertBlock, InsertBlock->getFirstNonPhi());
----------------
hmm, could Previous be a header phi (i.e., induction, given that reductions feed only themselves inside the loop, and we exhausted all FOR's), or is this checking for blend/pred-inst-phi's?
================
Comment at: llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp:714
+ Builder.createNaryOp(VPInstruction::FirstOrderRecurrenceSplice,
+ {FOR, FOR->getBackedgeValue()}));
+
----------------
(Independent of this patch) Note that if FOR->getBackedgeValue() differs from Previous then it is a FOR header phi, so in any case it will dominate RecurSplice.
================
Comment at: llvm/lib/Transforms/Vectorize/VPlanTransforms.h:27
class PredicatedScalarEvolution;
+class VPBuilder;
class TargetLibraryInfo;
----------------
nit: place last to try and keep lex order?
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D142589/new/
https://reviews.llvm.org/D142589
More information about the llvm-commits
mailing list