[VPlan] Split up attachCheckBlock in distinct helpers for re-use (NFC).

Split up attachCheckBlock into its distinct operations:
* inserting the check block in the CFG + updating phis, and
* adding the branch VPInstruction.

Those helpers can be re-used in follow-up changes.
This commit is contained in:
Florian Hahn 2026-01-31 20:19:29 +00:00
parent 1731c59192
commit d43e7351c1
No known key found for this signature in database
GPG Key ID: C8B0D7090F9127E6

View File

@ -966,38 +966,37 @@ void VPlanTransforms::createLoopRegions(VPlan &Plan) {
TopRegion->getEntryBasicBlock()->setName("vector.body");
}
// Likelyhood of bypassing the vectorized loop due to a runtime check block,
// including memory overlap checks block and wrapping/unit-stride checks block.
static constexpr uint32_t CheckBypassWeights[] = {1, 127};
void VPlanTransforms::attachCheckBlock(VPlan &Plan, Value *Cond,
BasicBlock *CheckBlock,
bool AddBranchWeights) {
VPValue *CondVPV = Plan.getOrAddLiveIn(Cond);
VPBasicBlock *CheckBlockVPBB = Plan.createVPIRBasicBlock(CheckBlock);
/// Insert \p CheckBlockVPBB on the edge leading to the vector preheader,
/// connecting it to both vector and scalar preheaders. Updates scalar
/// preheader phis to account for the new predecessor.
static void insertCheckBlockBeforeVectorLoop(VPlan &Plan,
VPBasicBlock *CheckBlockVPBB) {
VPBlockBase *VectorPH = Plan.getVectorPreheader();
VPBlockBase *ScalarPH = Plan.getScalarPreheader();
auto *ScalarPH = cast<VPBasicBlock>(Plan.getScalarPreheader());
VPBlockBase *PreVectorPH = VectorPH->getSinglePredecessor();
VPBlockUtils::insertOnEdge(PreVectorPH, VectorPH, CheckBlockVPBB);
VPBlockUtils::connectBlocks(CheckBlockVPBB, ScalarPH);
CheckBlockVPBB->swapSuccessors();
// We just connected a new block to the scalar preheader. Update all
// VPPhis by adding an incoming value for it, replicating the last value.
unsigned NumPredecessors = ScalarPH->getNumPredecessors();
for (VPRecipeBase &R : cast<VPBasicBlock>(ScalarPH)->phis()) {
assert(isa<VPPhi>(&R) && "Phi expected to be VPPhi");
assert(cast<VPPhi>(&R)->getNumIncoming() == NumPredecessors - 1 &&
"must have incoming values for all operands");
R.addOperand(R.getOperand(NumPredecessors - 2));
unsigned NumPreds = ScalarPH->getNumPredecessors();
for (VPRecipeBase &R : ScalarPH->phis()) {
auto *Phi = cast<VPPhi>(&R);
assert(Phi->getNumIncoming() == NumPreds - 1 &&
"must have incoming values for all predecessors");
Phi->addOperand(Phi->getOperand(NumPreds - 2));
}
}
VPIRMetadata VPBranchWeights;
auto *Term =
VPBuilder(CheckBlockVPBB)
.createNaryOp(
VPInstruction::BranchOnCond, {CondVPV},
Plan.getVectorLoopRegion()->getCanonicalIV()->getDebugLoc());
// Likelyhood of bypassing the vectorized loop due to a runtime check block,
// including memory overlap checks block and wrapping/unit-stride checks block.
static constexpr uint32_t CheckBypassWeights[] = {1, 127};
/// Create a BranchOnCond terminator in \p CheckBlockVPBB. Optionally adds
/// branch weights.
static void addBypassBranch(VPlan &Plan, VPBasicBlock *CheckBlockVPBB,
VPValue *Cond, bool AddBranchWeights) {
DebugLoc DL = Plan.getVectorLoopRegion()->getCanonicalIV()->getDebugLoc();
auto *Term = VPBuilder(CheckBlockVPBB)
.createNaryOp(VPInstruction::BranchOnCond, {Cond}, DL);
if (AddBranchWeights) {
MDBuilder MDB(Plan.getContext());
MDNode *BranchWeights =
@ -1006,6 +1005,15 @@ void VPlanTransforms::attachCheckBlock(VPlan &Plan, Value *Cond,
}
}
void VPlanTransforms::attachCheckBlock(VPlan &Plan, Value *Cond,
BasicBlock *CheckBlock,
bool AddBranchWeights) {
VPValue *CondVPV = Plan.getOrAddLiveIn(Cond);
VPBasicBlock *CheckBlockVPBB = Plan.createVPIRBasicBlock(CheckBlock);
insertCheckBlockBeforeVectorLoop(Plan, CheckBlockVPBB);
addBypassBranch(Plan, CheckBlockVPBB, CondVPV, AddBranchWeights);
}
void VPlanTransforms::addMinimumIterationCheck(
VPlan &Plan, ElementCount VF, unsigned UF,
ElementCount MinProfitableTripCount, bool RequiresScalarEpilogue,