-
Notifications
You must be signed in to change notification settings - Fork 14.8k
[VPlan] Move getCanonicalIV to VPRegionBlock (NFC). #163020
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4066,6 +4066,19 @@ class LLVM_ABI_FOR_TEST VPRegionBlock : public VPBlockBase { | |
/// Remove the current region from its VPlan, connecting its predecessor to | ||
/// its entry, and its exiting block to its successor. | ||
void dissolveToCFGLoop(); | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should VPWidenIntOrFpInductionRecipe::isCanonical() also call getCanonicalIV() instead of checking first recipe of header directly? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Updated, thanks |
||
/// Returns the canonical induction recipe of the region. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should VPlanVerifier::verify() (continue to) avoid calling getCanonicalIV() as it would assert rather than return false in case of failure? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yep. |
||
VPCanonicalIVPHIRecipe *getCanonicalIV() { | ||
VPBasicBlock *EntryVPBB = getEntryBasicBlock(); | ||
if (EntryVPBB->empty()) { | ||
// VPlan native path. TODO: Unify both code paths. | ||
EntryVPBB = cast<VPBasicBlock>(EntryVPBB->getSingleSuccessor()); | ||
} | ||
return cast<VPCanonicalIVPHIRecipe>(&*EntryVPBB->begin()); | ||
} | ||
const VPCanonicalIVPHIRecipe *getCanonicalIV() const { | ||
return const_cast<VPRegionBlock *>(this)->getCanonicalIV(); | ||
} | ||
}; | ||
|
||
/// VPlan models a candidate for vectorization, encoding various decisions take | ||
|
@@ -4377,16 +4390,6 @@ class VPlan { | |
LLVM_DUMP_METHOD void dump() const; | ||
#endif | ||
|
||
/// Returns the canonical induction recipe of the vector loop. | ||
VPCanonicalIVPHIRecipe *getCanonicalIV() { | ||
VPBasicBlock *EntryVPBB = getVectorLoopRegion()->getEntryBasicBlock(); | ||
if (EntryVPBB->empty()) { | ||
// VPlan native path. | ||
EntryVPBB = cast<VPBasicBlock>(EntryVPBB->getSingleSuccessor()); | ||
} | ||
return cast<VPCanonicalIVPHIRecipe>(&*EntryVPBB->begin()); | ||
} | ||
|
||
VPValue *getSCEVExpansion(const SCEV *S) const { | ||
return SCEVToExpansion.lookup(S); | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -661,9 +661,11 @@ void VPlanTransforms::attachCheckBlock(VPlan &Plan, Value *Cond, | |
} | ||
|
||
VPIRMetadata VPBranchWeights; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Independent: is VPBranchWeights needed? |
||
auto *Term = VPBuilder(CheckBlockVPBB) | ||
.createNaryOp(VPInstruction::BranchOnCond, {CondVPV}, | ||
Plan.getCanonicalIV()->getDebugLoc()); | ||
auto *Term = | ||
VPBuilder(CheckBlockVPBB) | ||
.createNaryOp( | ||
VPInstruction::BranchOnCond, {CondVPV}, | ||
Plan.getVectorLoopRegion()->getCanonicalIV()->getDebugLoc()); | ||
if (AddBranchWeights) { | ||
MDBuilder MDB(Plan.getContext()); | ||
MDNode *BranchWeights = | ||
|
@@ -925,8 +927,8 @@ bool VPlanTransforms::handleMaxMinNumReductions(VPlan &Plan) { | |
if (auto *DerivedIV = dyn_cast<VPDerivedIVRecipe>(VecV)) { | ||
if (DerivedIV->getNumUsers() == 1 && | ||
DerivedIV->getOperand(1) == &Plan.getVectorTripCount()) { | ||
auto *NewSel = Builder.createSelect(AnyNaN, Plan.getCanonicalIV(), | ||
&Plan.getVectorTripCount()); | ||
auto *NewSel = Builder.createSelect( | ||
AnyNaN, LoopRegion->getCanonicalIV(), &Plan.getVectorTripCount()); | ||
DerivedIV->moveAfter(&*Builder.getInsertPoint()); | ||
DerivedIV->setOperand(1, NewSel); | ||
continue; | ||
|
@@ -939,7 +941,8 @@ bool VPlanTransforms::handleMaxMinNumReductions(VPlan &Plan) { | |
"FMaxNum/FMinNum reduction.\n"); | ||
return false; | ||
} | ||
auto *NewSel = Builder.createSelect(AnyNaN, Plan.getCanonicalIV(), VecV); | ||
auto *NewSel = | ||
Builder.createSelect(AnyNaN, LoopRegion->getCanonicalIV(), VecV); | ||
ResumeR->setOperand(0, NewSel); | ||
} | ||
|
||
|
Original file line number | Diff line number | Diff line change | ||||||||
---|---|---|---|---|---|---|---|---|---|---|
|
@@ -501,7 +501,8 @@ static void removeRedundantInductionCasts(VPlan &Plan) { | |||||||||
/// Try to replace VPWidenCanonicalIVRecipes with a widened canonical IV | ||||||||||
/// recipe, if it exists. | ||||||||||
Comment on lines
501
to
502
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Independent:
Suggested change
only one (the first) VPWidenCanonicalIVRecipe is replaced. Try to replace them all? |
||||||||||
static void removeRedundantCanonicalIVs(VPlan &Plan) { | ||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Independent: shorten name or extend implementation to match it
Suggested change
|
||||||||||
VPCanonicalIVPHIRecipe *CanonicalIV = Plan.getCanonicalIV(); | ||||||||||
VPRegionBlock *LoopRegion = Plan.getVectorLoopRegion(); | ||||||||||
VPCanonicalIVPHIRecipe *CanonicalIV = LoopRegion->getCanonicalIV(); | ||||||||||
VPWidenCanonicalIVRecipe *WidenNewIV = nullptr; | ||||||||||
for (VPUser *U : CanonicalIV->users()) { | ||||||||||
WidenNewIV = dyn_cast<VPWidenCanonicalIVRecipe>(U); | ||||||||||
|
@@ -512,7 +513,7 @@ static void removeRedundantCanonicalIVs(VPlan &Plan) { | |||||||||
if (!WidenNewIV) | ||||||||||
return; | ||||||||||
|
||||||||||
VPBasicBlock *HeaderVPBB = Plan.getVectorLoopRegion()->getEntryBasicBlock(); | ||||||||||
VPBasicBlock *HeaderVPBB = LoopRegion->getEntryBasicBlock(); | ||||||||||
for (VPRecipeBase &Phi : HeaderVPBB->phis()) { | ||||||||||
auto *WidenOriginalIV = dyn_cast<VPWidenIntOrFpInductionRecipe>(&Phi); | ||||||||||
|
||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Independent: if "all users of WidenNewIV demand the first lane only" below - then why is it widened? Holds to recipes generating vectors in general when only their first lane is needed. |
||||||||||
|
@@ -582,8 +583,9 @@ createScalarIVSteps(VPlan &Plan, InductionDescriptor::InductionKind Kind, | |||||||||
FPMathOperator *FPBinOp, Instruction *TruncI, | ||||||||||
VPValue *StartV, VPValue *Step, DebugLoc DL, | ||||||||||
VPBuilder &Builder) { | ||||||||||
VPBasicBlock *HeaderVPBB = Plan.getVectorLoopRegion()->getEntryBasicBlock(); | ||||||||||
VPCanonicalIVPHIRecipe *CanonicalIV = Plan.getCanonicalIV(); | ||||||||||
VPRegionBlock *LoopRegion = Plan.getVectorLoopRegion(); | ||||||||||
VPBasicBlock *HeaderVPBB = LoopRegion->getEntryBasicBlock(); | ||||||||||
VPCanonicalIVPHIRecipe *CanonicalIV = LoopRegion->getCanonicalIV(); | ||||||||||
VPSingleDefRecipe *BaseIV = Builder.createDerivedIV( | ||||||||||
Kind, FPBinOp, StartV, CanonicalIV, Step, "offset.idx"); | ||||||||||
|
||||||||||
|
@@ -800,8 +802,9 @@ static VPValue *optimizeEarlyExitInductionUser(VPlan &Plan, | |||||||||
return nullptr; | ||||||||||
|
||||||||||
// Calculate the final index. | ||||||||||
VPValue *EndValue = Plan.getCanonicalIV(); | ||||||||||
auto CanonicalIVType = Plan.getCanonicalIV()->getScalarType(); | ||||||||||
VPRegionBlock *LoopRegion = Plan.getVectorLoopRegion(); | ||||||||||
auto *CanonicalIV = LoopRegion->getCanonicalIV(); | ||||||||||
Type *CanonicalIVType = CanonicalIV->getScalarType(); | ||||||||||
VPBuilder B(cast<VPBasicBlock>(PredVPBB)); | ||||||||||
|
||||||||||
DebugLoc DL = cast<VPInstruction>(Op)->getDebugLoc(); | ||||||||||
|
@@ -810,7 +813,8 @@ static VPValue *optimizeEarlyExitInductionUser(VPlan &Plan, | |||||||||
Type *FirstActiveLaneType = TypeInfo.inferScalarType(FirstActiveLane); | ||||||||||
FirstActiveLane = B.createScalarZExtOrTrunc(FirstActiveLane, CanonicalIVType, | ||||||||||
FirstActiveLaneType, DL); | ||||||||||
EndValue = B.createNaryOp(Instruction::Add, {EndValue, FirstActiveLane}, DL); | ||||||||||
VPValue *EndValue = | ||||||||||
B.createNaryOp(Instruction::Add, {CanonicalIV, FirstActiveLane}, DL); | ||||||||||
|
||||||||||
// `getOptimizableIVOf()` always returns the pre-incremented IV, so if it | ||||||||||
// changed it means the exit is using the incremented value, so we need to | ||||||||||
|
@@ -1532,7 +1536,7 @@ static bool isConditionTrueViaVFAndUF(VPValue *Cond, VPlan &Plan, | |||||||||
return isConditionTrueViaVFAndUF(C, Plan, BestVF, BestUF, SE); | ||||||||||
}); | ||||||||||
|
||||||||||
auto *CanIV = Plan.getCanonicalIV(); | ||||||||||
auto *CanIV = Plan.getVectorLoopRegion()->getCanonicalIV(); | ||||||||||
if (!match(Cond, m_SpecificICmp(CmpInst::ICMP_EQ, | ||||||||||
m_Specific(CanIV->getBackedgeValue()), | ||||||||||
m_Specific(&Plan.getVectorTripCount())))) | ||||||||||
|
@@ -2316,7 +2320,7 @@ static VPActiveLaneMaskPHIRecipe *addVPLaneMaskPhiAndUpdateExitBranch( | |||||||||
VPlan &Plan, bool DataAndControlFlowWithoutRuntimeCheck) { | ||||||||||
VPRegionBlock *TopRegion = Plan.getVectorLoopRegion(); | ||||||||||
VPBasicBlock *EB = TopRegion->getExitingBasicBlock(); | ||||||||||
auto *CanonicalIVPHI = Plan.getCanonicalIV(); | ||||||||||
auto *CanonicalIVPHI = TopRegion->getCanonicalIV(); | ||||||||||
VPValue *StartV = CanonicalIVPHI->getStartValue(); | ||||||||||
|
||||||||||
auto *CanonicalIVIncrement = | ||||||||||
|
@@ -2355,7 +2359,7 @@ static VPActiveLaneMaskPHIRecipe *addVPLaneMaskPhiAndUpdateExitBranch( | |||||||||
|
||||||||||
// Create the active lane mask instruction in the VPlan preheader. | ||||||||||
VPValue *ALMMultiplier = Plan.getOrAddLiveIn( | ||||||||||
ConstantInt::get(Plan.getCanonicalIV()->getScalarType(), 1)); | ||||||||||
ConstantInt::get(TopRegion->getCanonicalIV()->getScalarType(), 1)); | ||||||||||
auto *EntryALM = Builder.createNaryOp(VPInstruction::ActiveLaneMask, | ||||||||||
{EntryIncrement, TC, ALMMultiplier}, DL, | ||||||||||
"active.lane.mask.entry"); | ||||||||||
|
@@ -2391,21 +2395,23 @@ static VPActiveLaneMaskPHIRecipe *addVPLaneMaskPhiAndUpdateExitBranch( | |||||||||
/// TODO: Introduce explicit recipe for header-mask instead of searching | ||||||||||
/// for the header-mask pattern manually. | ||||||||||
static VPSingleDefRecipe *findHeaderMask(VPlan &Plan) { | ||||||||||
VPRegionBlock *LoopRegion = Plan.getVectorLoopRegion(); | ||||||||||
SmallVector<VPValue *> WideCanonicalIVs; | ||||||||||
auto *FoundWidenCanonicalIVUser = find_if(Plan.getCanonicalIV()->users(), | ||||||||||
IsaPred<VPWidenCanonicalIVRecipe>); | ||||||||||
assert(count_if(Plan.getCanonicalIV()->users(), | ||||||||||
auto *FoundWidenCanonicalIVUser = find_if( | ||||||||||
LoopRegion->getCanonicalIV()->users(), IsaPred<VPWidenCanonicalIVRecipe>); | ||||||||||
assert(count_if(LoopRegion->getCanonicalIV()->users(), | ||||||||||
IsaPred<VPWidenCanonicalIVRecipe>) <= 1 && | ||||||||||
"Must have at most one VPWideCanonicalIVRecipe"); | ||||||||||
if (FoundWidenCanonicalIVUser != Plan.getCanonicalIV()->users().end()) { | ||||||||||
if (FoundWidenCanonicalIVUser != | ||||||||||
LoopRegion->getCanonicalIV()->users().end()) { | ||||||||||
auto *WideCanonicalIV = | ||||||||||
cast<VPWidenCanonicalIVRecipe>(*FoundWidenCanonicalIVUser); | ||||||||||
WideCanonicalIVs.push_back(WideCanonicalIV); | ||||||||||
} | ||||||||||
|
||||||||||
// Also include VPWidenIntOrFpInductionRecipes that represent a widened | ||||||||||
// version of the canonical induction. | ||||||||||
VPBasicBlock *HeaderVPBB = Plan.getVectorLoopRegion()->getEntryBasicBlock(); | ||||||||||
VPBasicBlock *HeaderVPBB = LoopRegion->getEntryBasicBlock(); | ||||||||||
for (VPRecipeBase &Phi : HeaderVPBB->phis()) { | ||||||||||
auto *WidenOriginalIV = dyn_cast<VPWidenIntOrFpInductionRecipe>(&Phi); | ||||||||||
if (WidenOriginalIV && WidenOriginalIV->isCanonical()) | ||||||||||
|
@@ -2438,8 +2444,9 @@ void VPlanTransforms::addActiveLaneMask( | |||||||||
"DataAndControlFlowWithoutRuntimeCheck implies " | ||||||||||
"UseActiveLaneMaskForControlFlow"); | ||||||||||
|
||||||||||
auto *FoundWidenCanonicalIVUser = find_if(Plan.getCanonicalIV()->users(), | ||||||||||
IsaPred<VPWidenCanonicalIVRecipe>); | ||||||||||
VPRegionBlock *LoopRegion = Plan.getVectorLoopRegion(); | ||||||||||
auto *FoundWidenCanonicalIVUser = find_if( | ||||||||||
LoopRegion->getCanonicalIV()->users(), IsaPred<VPWidenCanonicalIVRecipe>); | ||||||||||
assert(FoundWidenCanonicalIVUser && | ||||||||||
"Must have widened canonical IV when tail folding!"); | ||||||||||
VPSingleDefRecipe *HeaderMask = findHeaderMask(Plan); | ||||||||||
|
@@ -2452,7 +2459,7 @@ void VPlanTransforms::addActiveLaneMask( | |||||||||
} else { | ||||||||||
VPBuilder B = VPBuilder::getToInsertAfter(WideCanonicalIV); | ||||||||||
VPValue *ALMMultiplier = Plan.getOrAddLiveIn( | ||||||||||
ConstantInt::get(Plan.getCanonicalIV()->getScalarType(), 1)); | ||||||||||
ConstantInt::get(LoopRegion->getCanonicalIV()->getScalarType(), 1)); | ||||||||||
LaneMask = | ||||||||||
B.createNaryOp(VPInstruction::ActiveLaneMask, | ||||||||||
{WideCanonicalIV, Plan.getTripCount(), ALMMultiplier}, | ||||||||||
|
@@ -2562,9 +2569,10 @@ static void transformRecipestoEVLRecipes(VPlan &Plan, VPValue &EVL) { | |||||||||
}); | ||||||||||
|
||||||||||
assert(all_of(Plan.getVFxUF().users(), | ||||||||||
[&Plan](VPUser *U) { | ||||||||||
return match(U, m_c_Add(m_Specific(Plan.getCanonicalIV()), | ||||||||||
m_Specific(&Plan.getVFxUF()))) || | ||||||||||
[&LoopRegion, &Plan](VPUser *U) { | ||||||||||
return match(U, | ||||||||||
m_c_Add(m_Specific(LoopRegion->getCanonicalIV()), | ||||||||||
m_Specific(&Plan.getVFxUF()))) || | ||||||||||
isa<VPWidenPointerInductionRecipe>(U); | ||||||||||
}) && | ||||||||||
"Only users of VFxUF should be VPWidenPointerInductionRecipe and the " | ||||||||||
|
@@ -2719,9 +2727,10 @@ void VPlanTransforms::addExplicitVectorLength( | |||||||||
VPlan &Plan, const std::optional<unsigned> &MaxSafeElements) { | ||||||||||
if (Plan.hasScalarVFOnly()) | ||||||||||
return; | ||||||||||
VPBasicBlock *Header = Plan.getVectorLoopRegion()->getEntryBasicBlock(); | ||||||||||
VPRegionBlock *LoopRegion = Plan.getVectorLoopRegion(); | ||||||||||
VPBasicBlock *Header = LoopRegion->getEntryBasicBlock(); | ||||||||||
|
||||||||||
auto *CanonicalIVPHI = Plan.getCanonicalIV(); | ||||||||||
auto *CanonicalIVPHI = LoopRegion->getCanonicalIV(); | ||||||||||
auto *CanIVTy = CanonicalIVPHI->getScalarType(); | ||||||||||
VPValue *StartV = CanonicalIVPHI->getStartValue(); | ||||||||||
|
||||||||||
|
@@ -4165,7 +4174,7 @@ void VPlanTransforms::narrowInterleaveGroups(VPlan &Plan, ElementCount VF, | |||||||||
|
||||||||||
// Adjust induction to reflect that the transformed plan only processes one | ||||||||||
// original iteration. | ||||||||||
auto *CanIV = Plan.getCanonicalIV(); | ||||||||||
auto *CanIV = VectorLoop->getCanonicalIV(); | ||||||||||
auto *Inc = cast<VPInstruction>(CanIV->getBackedgeValue()); | ||||||||||
VPBuilder PHBuilder(Plan.getVectorPreheader()); | ||||||||||
|
||||||||||
|
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -69,7 +69,8 @@ class UnrollState { | |||||
VPBasicBlock::iterator InsertPtForPhi); | ||||||
|
||||||
VPValue *getConstantVPV(unsigned Part) { | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Independent:
Suggested change
|
||||||
Type *CanIVIntTy = Plan.getCanonicalIV()->getScalarType(); | ||||||
Type *CanIVIntTy = | ||||||
Plan.getVectorLoopRegion()->getCanonicalIV()->getScalarType(); | ||||||
Comment on lines
+72
to
+73
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Independent: better have TypeInfo supply CanIVIntTy? |
||||||
return Plan.getOrAddLiveIn(ConstantInt::get(CanIVIntTy, Part)); | ||||||
} | ||||||
|
||||||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should dissolveToCFGLoop() also call getCanonicalIV(), possibly asserting that it resides in the-header/its-front/the-region?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Currently getCanonicalIV assumes that the region must have a canonical IV, which may not be the case at the moment (e.g. the inner loop region when vectorizing the outer loop does not have a canonical IV at the moment).