[LV] Iterate over recipes in VPlan to fix PHI (NFC).

As we gradually move more elements of LV to VPlan, we are trying to
reduce the number of places that still has to check IR of the original
loop.

This patch adjusts the code to fix cross iteration phis to get the PHIs
to fix directly from the VPlan that is executed. We still need the
original PHI to check for first-order recurrences, but we can get rid of
that once we model that explicitly in VPlan as well.

Reviewed By: Ayal

Differential Revision: https://reviews.llvm.org/D99293
This commit is contained in:
Florian Hahn 2021-05-03 12:13:17 +01:00
parent 895ba21401
commit 2b7fa7f744
2 changed files with 26 additions and 18 deletions

View File

@ -599,7 +599,7 @@ protected:
/// Fix a reduction cross-iteration phi. This is the second phase of /// Fix a reduction cross-iteration phi. This is the second phase of
/// vectorizing this phi node. /// vectorizing this phi node.
void fixReduction(PHINode *Phi, VPTransformState &State); void fixReduction(VPWidenPHIRecipe *Phi, VPTransformState &State);
/// Clear NSW/NUW flags from reduction instructions if necessary. /// Clear NSW/NUW flags from reduction instructions if necessary.
void clearReductionWrapFlags(RecurrenceDescriptor &RdxDesc, void clearReductionWrapFlags(RecurrenceDescriptor &RdxDesc,
@ -4065,12 +4065,16 @@ void InnerLoopVectorizer::fixCrossIterationPHIs(VPTransformState &State) {
// the currently empty PHI nodes. At this point every instruction in the // the currently empty PHI nodes. At this point every instruction in the
// original loop is widened to a vector form so we can use them to construct // original loop is widened to a vector form so we can use them to construct
// the incoming edges. // the incoming edges.
for (PHINode &Phi : OrigLoop->getHeader()->phis()) { VPBasicBlock *Header = State.Plan->getEntry()->getEntryBasicBlock();
// Handle first-order recurrences and reductions that need to be fixed. for (VPRecipeBase &R : Header->phis()) {
if (Legal->isFirstOrderRecurrence(&Phi)) auto *PhiR = dyn_cast<VPWidenPHIRecipe>(&R);
fixFirstOrderRecurrence(&Phi, State); if (!PhiR)
else if (Legal->isReductionVariable(&Phi)) continue;
fixReduction(&Phi, State); auto *OrigPhi = cast<PHINode>(PhiR->getUnderlyingValue());
if (PhiR->getRecurrenceDescriptor()) {
fixReduction(PhiR, State);
} else if (Legal->isFirstOrderRecurrence(OrigPhi))
fixFirstOrderRecurrence(OrigPhi, State);
} }
} }
@ -4265,17 +4269,19 @@ static bool useOrderedReductions(RecurrenceDescriptor &RdxDesc) {
return EnableStrictReductions && RdxDesc.isOrdered(); return EnableStrictReductions && RdxDesc.isOrdered();
} }
void InnerLoopVectorizer::fixReduction(PHINode *Phi, VPTransformState &State) { void InnerLoopVectorizer::fixReduction(VPWidenPHIRecipe *PhiR,
VPTransformState &State) {
PHINode *OrigPhi = cast<PHINode>(PhiR->getUnderlyingValue());
// Get it's reduction variable descriptor. // Get it's reduction variable descriptor.
assert(Legal->isReductionVariable(Phi) && assert(Legal->isReductionVariable(OrigPhi) &&
"Unable to find the reduction variable"); "Unable to find the reduction variable");
RecurrenceDescriptor RdxDesc = Legal->getReductionVars()[Phi]; RecurrenceDescriptor RdxDesc = *PhiR->getRecurrenceDescriptor();
RecurKind RK = RdxDesc.getRecurrenceKind(); RecurKind RK = RdxDesc.getRecurrenceKind();
TrackingVH<Value> ReductionStartValue = RdxDesc.getRecurrenceStartValue(); TrackingVH<Value> ReductionStartValue = RdxDesc.getRecurrenceStartValue();
Instruction *LoopExitInst = RdxDesc.getLoopExitInstr(); Instruction *LoopExitInst = RdxDesc.getLoopExitInstr();
setDebugLocFromInst(Builder, ReductionStartValue); setDebugLocFromInst(Builder, ReductionStartValue);
bool IsInLoopReductionPhi = Cost->isInLoopReduction(Phi); bool IsInLoopReductionPhi = Cost->isInLoopReduction(OrigPhi);
VPValue *LoopExitInstDef = State.Plan->getVPValue(LoopExitInst); VPValue *LoopExitInstDef = State.Plan->getVPValue(LoopExitInst);
// This is the vector-clone of the value that leaves the loop. // This is the vector-clone of the value that leaves the loop.
@ -4289,7 +4295,7 @@ void InnerLoopVectorizer::fixReduction(PHINode *Phi, VPTransformState &State) {
// Reductions do not have to start at zero. They can start with // Reductions do not have to start at zero. They can start with
// any loop invariant values. // any loop invariant values.
BasicBlock *OrigLatch = OrigLoop->getLoopLatch(); BasicBlock *OrigLatch = OrigLoop->getLoopLatch();
Value *OrigLoopVal = Phi->getIncomingValueForBlock(OrigLatch); Value *OrigLoopVal = OrigPhi->getIncomingValueForBlock(OrigLatch);
BasicBlock *VectorLoopLatch = LI->getLoopFor(LoopVectorBody)->getLoopLatch(); BasicBlock *VectorLoopLatch = LI->getLoopFor(LoopVectorBody)->getLoopLatch();
bool IsOrdered = State.VF.isVector() && IsInLoopReductionPhi && bool IsOrdered = State.VF.isVector() && IsInLoopReductionPhi &&
@ -4298,7 +4304,7 @@ void InnerLoopVectorizer::fixReduction(PHINode *Phi, VPTransformState &State) {
for (unsigned Part = 0; Part < UF; ++Part) { for (unsigned Part = 0; Part < UF; ++Part) {
if (IsOrdered && Part > 0) if (IsOrdered && Part > 0)
break; break;
Value *VecRdxPhi = State.get(State.Plan->getVPValue(Phi), Part); Value *VecRdxPhi = State.get(PhiR->getVPSingleValue(), Part);
Value *Val = State.get(State.Plan->getVPValue(OrigLoopVal), Part); Value *Val = State.get(State.Plan->getVPValue(OrigLoopVal), Part);
if (IsOrdered) if (IsOrdered)
Val = State.get(State.Plan->getVPValue(OrigLoopVal), UF - 1); Val = State.get(State.Plan->getVPValue(OrigLoopVal), UF - 1);
@ -4313,7 +4319,7 @@ void InnerLoopVectorizer::fixReduction(PHINode *Phi, VPTransformState &State) {
setDebugLocFromInst(Builder, LoopExitInst); setDebugLocFromInst(Builder, LoopExitInst);
Type *PhiTy = Phi->getType(); Type *PhiTy = OrigPhi->getType();
// If tail is folded by masking, the vector value to leave the loop should be // If tail is folded by masking, the vector value to leave the loop should be
// a Select choosing between the vectorized LoopExitInst and vectorized Phi, // a Select choosing between the vectorized LoopExitInst and vectorized Phi,
// instead of the former. For an inloop reduction the reduction will already // instead of the former. For an inloop reduction the reduction will already
@ -4342,7 +4348,7 @@ void InnerLoopVectorizer::fixReduction(PHINode *Phi, VPTransformState &State) {
RdxDesc.getOpcode(), PhiTy, RdxDesc.getOpcode(), PhiTy,
TargetTransformInfo::ReductionFlags())) { TargetTransformInfo::ReductionFlags())) {
auto *VecRdxPhi = auto *VecRdxPhi =
cast<PHINode>(State.get(State.Plan->getVPValue(Phi), Part)); cast<PHINode>(State.get(PhiR->getVPSingleValue(), Part));
VecRdxPhi->setIncomingValueForBlock( VecRdxPhi->setIncomingValueForBlock(
LI->getLoopFor(LoopVectorBody)->getLoopLatch(), Sel); LI->getLoopFor(LoopVectorBody)->getLoopLatch(), Sel);
} }
@ -4444,12 +4450,12 @@ void InnerLoopVectorizer::fixReduction(PHINode *Phi, VPTransformState &State) {
// Fix the scalar loop reduction variable with the incoming reduction sum // Fix the scalar loop reduction variable with the incoming reduction sum
// from the vector body and from the backedge value. // from the vector body and from the backedge value.
int IncomingEdgeBlockIdx = int IncomingEdgeBlockIdx =
Phi->getBasicBlockIndex(OrigLoop->getLoopLatch()); OrigPhi->getBasicBlockIndex(OrigLoop->getLoopLatch());
assert(IncomingEdgeBlockIdx >= 0 && "Invalid block index"); assert(IncomingEdgeBlockIdx >= 0 && "Invalid block index");
// Pick the other block. // Pick the other block.
int SelfEdgeBlockIdx = (IncomingEdgeBlockIdx ? 0 : 1); int SelfEdgeBlockIdx = (IncomingEdgeBlockIdx ? 0 : 1);
Phi->setIncomingValue(SelfEdgeBlockIdx, BCBlockPhi); OrigPhi->setIncomingValue(SelfEdgeBlockIdx, BCBlockPhi);
Phi->setIncomingValue(IncomingEdgeBlockIdx, LoopExitInst); OrigPhi->setIncomingValue(IncomingEdgeBlockIdx, LoopExitInst);
} }
void InnerLoopVectorizer::clearReductionWrapFlags(RecurrenceDescriptor &RdxDesc, void InnerLoopVectorizer::clearReductionWrapFlags(RecurrenceDescriptor &RdxDesc,

View File

@ -1051,6 +1051,8 @@ public:
/// Returns the \p I th incoming VPBasicBlock. /// Returns the \p I th incoming VPBasicBlock.
VPBasicBlock *getIncomingBlock(unsigned I) { return IncomingBlocks[I]; } VPBasicBlock *getIncomingBlock(unsigned I) { return IncomingBlocks[I]; }
RecurrenceDescriptor *getRecurrenceDescriptor() { return RdxDesc; }
}; };
/// A recipe for vectorizing a phi-node as a sequence of mask-based select /// A recipe for vectorizing a phi-node as a sequence of mask-based select