Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

[VPlan] Move predication to VPlanTransform (NFC). #128420

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

Merged
merged 6 commits into from
May 21, 2025
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
!fixup address comments, thanks
  • Loading branch information
fhahn committed May 16, 2025
commit 58c8fc4992731e6f56a9af3aab9cef6f8d2f0a2c
23 changes: 15 additions & 8 deletions 23 llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9254,6 +9254,9 @@ LoopVectorizationPlanner::tryToBuildVPlanWithVPRecipes(VFRange &Range,

auto *MiddleVPBB = Plan->getMiddleBlock();
VPBasicBlock::iterator MBIP = MiddleVPBB->getFirstNonPhi();
// Mapping from VPValues in the initial plan to their widened VPValues. Needed
// temporarily to update created block masks.
DenseMap<VPValue *, VPValue *> Old2New;
for (VPBasicBlock *VPBB : VPBlockUtils::blocksOnly<VPBasicBlock>(RPOT)) {
// Convert input VPInstructions to widened recipes.
for (VPRecipeBase &R : make_early_inc_range(*VPBB)) {
Expand Down Expand Up @@ -9313,19 +9316,23 @@ LoopVectorizationPlanner::tryToBuildVPlanWithVPRecipes(VFRange &Range,
}
if (Recipe->getNumDefinedValues() == 1) {
SingleDef->replaceAllUsesWith(Recipe->getVPSingleValue());
// replaceAllUsesWith may invalidate the block mask cache. Update it.
// TODO: Include the masks as operands in the predicated VPlan directly
// to remove the need to keep a map of masks beyond the predication
// transform.
RecipeBuilder.updateBlockMaskCache(SingleDef,
Recipe->getVPSingleValue());
} else
Old2New[SingleDef] = Recipe->getVPSingleValue();
} else {
assert(Recipe->getNumDefinedValues() == 0 &&
"Unexpected multidef recipe");
R.eraseFromParent();
R.eraseFromParent();
}
}
}

// replaceAllUsesWith above may invalidate the block masks. Update them here.
// TODO: Include the masks as operands in the predicated VPlan directly
// to remove the need to keep a map of masks beyond the predication
// transform.
RecipeBuilder.updateBlockMaskCache(Old2New);
for (const auto &[Old, New] : Old2New)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
for (const auto &[Old, New] : Old2New)
for (const auto &[Old, _] : Old2New)

?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done thanks

Old->getDefiningRecipe()->eraseFromParent();

assert(isa<VPRegionBlock>(Plan->getVectorLoopRegion()) &&
!Plan->getVectorLoopRegion()->getEntryBasicBlock()->empty() &&
"entry block must be set to a VPRegionBlock having a non-empty entry "
Expand Down
6 changes: 4 additions & 2 deletions 6 llvm/lib/Transforms/Vectorize/VPRecipeBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -209,10 +209,12 @@ class VPRecipeBuilder {
return Plan.getOrAddLiveIn(V);
}

void updateBlockMaskCache(VPValue *Old, VPValue *New) {
void updateBlockMaskCache(const DenseMap<VPValue *, VPValue *> &Old2New) {
for (auto &[_, V] : BlockMaskCache) {
if (V == Old)
if (auto *New = Old2New.lookup(V)) {
V->replaceAllUsesWith(New);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: worth removing V from Old2New now?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cannot be done for now, as Old2New is used to erase old recipes after updateBlockMaskCache

V = New;
}
}
}
};
Expand Down
119 changes: 61 additions & 58 deletions 119 llvm/lib/Transforms/Vectorize/VPlanPredicator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,8 @@
using namespace llvm;

namespace {
struct VPPredicator {
class VPPredicator {
using BlockMaskCacheTy = DenseMap<VPBasicBlock *, VPValue *>;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: better define BlockMaskCacheTy below, closer to use, next to EdgeMaskCacheTy.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved thanks

VPPredicator(BlockMaskCacheTy &BlockMaskCache)
: BlockMaskCache(BlockMaskCache) {}

/// Builder to construct recipes to compute masks.
VPBuilder Builder;

Expand All @@ -38,35 +35,45 @@ struct VPPredicator {

BlockMaskCacheTy &BlockMaskCache;

/// Returns the previously computed predicate of the edge between \p Src and
/// \p Dst.
VPValue *getEdgeMask(const VPBasicBlock *Src, const VPBasicBlock *Dst) const {
return EdgeMaskCache.lookup({Src, Dst});
}
/// Create an edge mask for every destination of cases and/or default.
void createSwitchEdgeMasks(VPInstruction *SI);

/// Computes and return the predicate of the edge between \p Src and \p Dst.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
/// Computes and return the predicate of the edge between \p Src and \p Dst.
/// Computes and return the predicate of the edge between \p Src and \p Dst, possibly inserting new recipes at \p Dst (using Builder's insertion point).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done thanks

VPValue *createEdgeMask(VPBasicBlock *Src, VPBasicBlock *Dst);

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add, for completeness and consistency?

Suggested change
void setEdgeMask(const VPBasicBlock *Src, const VPBasicBlock *Dst, VPValue *Mask) {
EdgeMaskCache[{Src, Dst}] = Mask;
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done thanks

/// Returns the *entry* mask for \p VPBB.
VPValue *getBlockInMask(VPBasicBlock *VPBB) const {
return BlockMaskCache.lookup(VPBB);
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
}
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done thanks


void setBlockInMask(VPBasicBlock *VPBB, VPValue *Mask) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
void setBlockInMask(VPBasicBlock *VPBB, VPValue *Mask) {
/// Record \p Mask as the *entry* mask of \p VPBB, which is expected to not already have a mask.
void setBlockInMask(VPBasicBlock *VPBB, VPValue *Mask) {

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

updated, thanks

// TODO: Include the masks as operands in the predicated VPlan directly to
// remove the need to keep a map of masks beyond the predication transform.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// remove the need to keep a map of masks beyond the predication transform.
// avoid keeping the map of masks beyond the predication transform.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated, thanks

assert(!BlockMaskCache.contains(VPBB) && "Mask already set");
assert(!getBlockInMask(VPBB) && "Mask already set");
BlockMaskCache[VPBB] = Mask;
}

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For completeness and consistency?

Suggested change
void setEdgeMask(VPBasicBlock *Src, VPBasicBlock *Dst, VPValue *Mask) {
assert(!getEdgeMask({Src, Dst}) && "Mask already set");
EdgeMaskCache[{Src, Dst}] = Mask;
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doen thanks.

VPValue *setEdgeMask(const VPBasicBlock *Src, const VPBasicBlock *Dst,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
VPValue *setEdgeMask(const VPBasicBlock *Src, const VPBasicBlock *Dst,
/// Record \p Mask as the mask of the edge from \p Src to \p Dst. The edge is expected to not have a mask already.
VPValue *setEdgeMask(const VPBasicBlock *Src, const VPBasicBlock *Dst,

also expecting no parallel edges - worth verifying?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also expecting no parallel edges - worth verifying?

Meaning where Src == Dst? Addaed an assert.

VPValue *Mask) {
assert(!getEdgeMask(Src, Dst) && "Mask already set");
return EdgeMaskCache[{Src, Dst}] = Mask;
}

public:
VPPredicator(BlockMaskCacheTy &BlockMaskCache)
: BlockMaskCache(BlockMaskCache) {}

/// Returns the precomputed predicate of the edge from \p Src to \p Dst.
VPValue *getEdgeMask(const VPBasicBlock *Src, const VPBasicBlock *Dst) const {
return EdgeMaskCache.lookup({Src, Dst});
}

/// Compute and return the mask for the vector loop header block.
void createHeaderMask(VPBasicBlock *HeaderVPBB, bool FoldTail);

/// Compute and return the predicate of \p VPBB, assuming that the header
/// block of the loop is set to True or the loop mask when tail folding.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
/// block of the loop is set to True or the loop mask when tail folding.
/// block of the loop is set to True, or to the loop mask when tail folding.

VPValue *createBlockInMask(VPBasicBlock *VPBB);

/// Computes and return the predicate of the edge between \p Src and \p Dst.
VPValue *createEdgeMask(VPBasicBlock *Src, VPBasicBlock *Dst);

/// Create an edge mask for every destination of cases and/or default.
void createSwitchEdgeMasks(VPInstruction *SI);
};
} // namespace

Expand All @@ -80,40 +87,35 @@ VPValue *VPPredicator::createEdgeMask(VPBasicBlock *Src, VPBasicBlock *Dst) {

VPValue *SrcMask = getBlockInMask(Src);

// The terminator has to be a branch inst!
if (Src->empty() || Src->getNumSuccessors() == 1) {
EdgeMaskCache[{Src, Dst}] = SrcMask;
return SrcMask;
}
// If there's a single successor, there's no terminator recipe.
if (Src->getNumSuccessors() == 1)
return setEdgeMask(Src, Dst, SrcMask);

auto *Term = cast<VPInstruction>(Src->getTerminator());
if (Term->getOpcode() == Instruction::Switch) {
createSwitchEdgeMasks(Term);
return getEdgeMask(Src, Dst);
}

auto *BI = cast<VPInstruction>(Src->getTerminator());
assert(BI->getOpcode() == VPInstruction::BranchOnCond);
if (Src->getSuccessors()[0] == Src->getSuccessors()[1]) {
EdgeMaskCache[{Src, Dst}] = SrcMask;
return SrcMask;
}
assert(Term->getOpcode() == VPInstruction::BranchOnCond &&
"Unsupported terminator");
if (Src->getSuccessors()[0] == Src->getSuccessors()[1])
return setEdgeMask(Src, Dst, SrcMask);

EdgeMask = BI->getOperand(0);
EdgeMask = Term->getOperand(0);
assert(EdgeMask && "No Edge Mask found for condition");

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Insertion point of Builder assumed to be set - to start of Dst - before used below. Better set it here instead?

Can alternatively set it to Term, which retains SSA def/use semantics, but in any case the BlockInMask operations violate them when using edge masks - relying on linearization.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Re-setting here would lead to re-ordering of the mask recipes. I left it as is for now.

if (Src->getSuccessors()[0] != Dst)
EdgeMask = Builder.createNot(EdgeMask, BI->getDebugLoc());
EdgeMask = Builder.createNot(EdgeMask, Term->getDebugLoc());

if (SrcMask) { // Otherwise block in-mask is all-one, no need to AND.
// The bitwise 'And' of SrcMask and EdgeMask introduces new UB if SrcMask
// is false and EdgeMask is poison. Avoid that by using 'LogicalAnd'
// instead which generates 'select i1 SrcMask, i1 EdgeMask, i1 false'.
EdgeMask = Builder.createLogicalAnd(SrcMask, EdgeMask, BI->getDebugLoc());
EdgeMask = Builder.createLogicalAnd(SrcMask, EdgeMask, Term->getDebugLoc());
}

EdgeMaskCache[{Src, Dst}] = EdgeMask;
return EdgeMask;
return setEdgeMask(Src, Dst, EdgeMask);
}

VPValue *VPPredicator::createBlockInMask(VPBasicBlock *VPBB) {
Expand All @@ -131,7 +133,7 @@ VPValue *VPPredicator::createBlockInMask(VPBasicBlock *VPBB) {
return EdgeMask;
}

if (!BlockMask) { // BlockMask has its initialized nullptr value.
if (!BlockMask) { // BlockMask has its initial nullptr value.
BlockMask = EdgeMask;
continue;
}
Expand Down Expand Up @@ -159,11 +161,9 @@ void VPPredicator::createHeaderMask(VPBasicBlock *HeaderVPBB, bool FoldTail) {
auto *IV = new VPWidenCanonicalIVRecipe(Plan.getCanonicalIV());
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This use of the widened canonical IV is fine - it follows the exiting behavior. Wonder going forward predication is applied to widen form, or to scalar form prior to widening, i.e., if the scalar canonical IV should be used here instead - to be widened along with all other recipes per range.

HeaderVPBB->insert(IV, NewInsertionPoint);

VPBuilder::InsertPointGuard Guard(Builder);
Builder.setInsertPoint(HeaderVPBB, NewInsertionPoint);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could Builder be used to insert both IV and the ICmp, reusing NewInsertPoint for both, perhaps by exposing its tryInsertInstruction() or providing an insert(VPRecipeBase*)?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, updated to use Builder.insert, which is already provided, thanks

VPValue *BlockMask = nullptr;
VPValue *BTC = Plan.getOrCreateBackedgeTakenCount();
BlockMask = Builder.createICmp(CmpInst::ICMP_ULE, IV, BTC);
VPValue *BlockMask = Builder.createICmp(CmpInst::ICMP_ULE, IV, BTC);
setBlockInMask(HeaderVPBB, BlockMask);
}

Expand All @@ -179,7 +179,7 @@ void VPPredicator::createSwitchEdgeMasks(VPInstruction *SI) {
for (const auto &[Idx, Succ] :
enumerate(ArrayRef(Src->getSuccessors()).drop_front())) {
VPBasicBlock *Dst = cast<VPBasicBlock>(Succ);
assert(!EdgeMaskCache.contains({Src, Dst}) && "Edge masks already created");
assert(!getEdgeMask(Src, Dst) && "Edge masks already created");
// Cases whose destination is the same as default are redundant and can
// be ignored - they will get there anyhow.
if (Dst == DefaultDst)
Expand All @@ -202,7 +202,7 @@ void VPPredicator::createSwitchEdgeMasks(VPInstruction *SI) {
Mask = Builder.createOr(Mask, V);
if (SrcMask)
Mask = Builder.createLogicalAnd(SrcMask, Mask);
EdgeMaskCache[{Src, Dst}] = Mask;
setEdgeMask(Src, Dst, Mask);

// 2. Create the mask for the default destination, which is reached if
// none of the cases with destination != default destination are taken.
Expand All @@ -216,7 +216,7 @@ void VPPredicator::createSwitchEdgeMasks(VPInstruction *SI) {
if (SrcMask)
DefaultMask = Builder.createLogicalAnd(SrcMask, DefaultMask);
}
EdgeMaskCache[{Src, DefaultDst}] = DefaultMask;
setEdgeMask(Src, DefaultDst, DefaultMask);
}

void VPlanTransforms::predicateAndLinearize(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Works for innermost loop regions only, i.e., non native?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, as before this is inner-loop only for now.

Expand All @@ -229,7 +229,12 @@ void VPlanTransforms::predicateAndLinearize(
ReversePostOrderTraversal<VPBlockShallowTraversalWrapper<VPBlockBase *>> RPOT(
Header);
VPPredicator Predicator(BlockMaskCache);
for (VPBasicBlock *VPBB : VPBlockUtils::blocksOnly<VPBasicBlock>(RPOT)) {
for (VPBlockBase *VPB : RPOT) {
// Only regions with only VPBBs are supported at the moment.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// Only regions with only VPBBs are supported at the moment.
// Non-outer regions with VPBBs only are supported at the moment.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

updated thanks

auto *VPBB = cast<VPBasicBlock>(VPB);
// Introduce the mask for VPBB, which may introduce needed edge masks, and
// convert all phi recipes of VPBB to blend recipes unless VPBB is the
// header.
if (VPBB == Header) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are headers of nested loops handled correctly, i.e., as non-headers?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, for now just header of the current loop; we won't traverse in regions with the shallow iterator. Added an assert

Predicator.createHeaderMask(Header, FoldTail);
continue;
Expand All @@ -241,53 +246,51 @@ void VPlanTransforms::predicateAndLinearize(

Predicator.createBlockInMask(VPBB);

for (VPWidenPHIRecipe *Phi : Phis) {
PHINode *IRPhi = cast<PHINode>(Phi->getUnderlyingValue());

unsigned NumIncoming = IRPhi->getNumIncomingValues();

// We know that all PHIs in non-header blocks are converted into selects,
for (VPWidenPHIRecipe *PhiR : Phis) {
// The non-header Phi is converted into a Blend recipe below,
// so we don't have to worry about the insertion order and we can just use
// the builder. At this point we generate the predication tree. There may
// be duplications since this is a simple recursive scan, but future
// optimizations will clean it up.

SmallVector<VPValue *, 2> OperandsWithMask;
unsigned NumIncoming = PhiR->getNumIncoming();
for (unsigned In = 0; In < NumIncoming; In++) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
for (unsigned In = 0; In < NumIncoming; In++) {
unsigned NumIncoming = PhiR->getNumIncoming();
for (unsigned In = 0; In < NumIncoming; In++) {

or do we still want IRPhi->getNumIncomingValues(); instead?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep updated, thanks

const VPBasicBlock *Pred = Phi->getIncomingBlock(In);
OperandsWithMask.push_back(Phi->getIncomingValue(In));
const VPBasicBlock *Pred = PhiR->getIncomingBlock(In);
OperandsWithMask.push_back(PhiR->getIncomingValue(In));
VPValue *EdgeMask = Predicator.getEdgeMask(Pred, VPBB);
if (!EdgeMask) {
assert(In == 0 && "Both null and non-null edge masks found");
assert(all_equal(Phi->operands()) &&
assert(all_equal(PhiR->operands()) &&
"Distinct incoming values with one having a full mask");
break;
}
OperandsWithMask.push_back(EdgeMask);
}
PHINode *IRPhi = cast<PHINode>(PhiR->getUnderlyingValue());
auto *Blend = new VPBlendRecipe(IRPhi, OperandsWithMask);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
auto *Blend = new VPBlendRecipe(IRPhi, OperandsWithMask);
PHINode *IRPhi = cast<PHINode>(Phi->getUnderlyingValue());
auto *Blend = new VPBlendRecipe(IRPhi, OperandsWithMask);

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved, thanks

Blend->insertBefore(Phi);
Phi->replaceAllUsesWith(Blend);
Phi->eraseFromParent();
Blend->insertBefore(PhiR);
PhiR->replaceAllUsesWith(Blend);
PhiR->eraseFromParent();
}
}

// Linearize the blocks of the loop into one serial chain.
VPBlockBase *PrevVPBB = nullptr;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
VPBlockBase *PrevVPBB = nullptr;
// Linearize the blocks of the loop into one serial chain.
VPBlockBase *PrevVPBB = nullptr;

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done thanks

for (VPBasicBlock *VPBB : VPBlockUtils::blocksOnly<VPBasicBlock>(RPOT)) {
// Handle VPBBs down to the latch.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This "Handle VPBBs down to latch" early-break is needed when traversing CFG to stop RPOT from going out of the loop. Is it still needed here where RPOT traverses the region, shallowly? If so, is it needed in the createBlockMasks/convertPhisToBlends loop above too?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed, thannks

if (PrevVPBB && VPBB == LoopRegion->getExiting()) {
VPBlockUtils::connectBlocks(PrevVPBB, VPBB);
if (VPBB == LoopRegion->getExiting()) {
if (PrevVPBB)
VPBlockUtils::connectBlocks(PrevVPBB, VPBB);
break;
}

auto Successors = to_vector(VPBB->getSuccessors());
if (Successors.size() > 1)
VPBB->getTerminator()->eraseFromParent();

// Flatten the CFG in the loop. Masks for blocks have already been
// generated and added to recipes as needed. To do so, first disconnect
// VPBB from its successors. Then connect VPBB to the previously visited
// VPBB.
// Flatten the CFG in the loop. To do so, first disconnect VPBB from its
// successors. Then connect VPBB to the previously visited VPBB.
for (auto *Succ : Successors)
VPBlockUtils::disconnectBlocks(VPBB, Succ);
if (PrevVPBB)
Expand Down
8 changes: 4 additions & 4 deletions 8 llvm/lib/Transforms/Vectorize/VPlanTransforms.h
Original file line number Diff line number Diff line change
Expand Up @@ -223,12 +223,12 @@ struct VPlanTransforms {
static void narrowInterleaveGroups(VPlan &Plan, ElementCount VF,
unsigned VectorRegWidth);

/// Predicate and linearize the control-flow in the top-level loop region of
/// Predicate and linearize the control-flow in the only loop region of
/// \p Plan. If \p FoldTail is true, also create a mask guarding the loop
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
/// \p Plan. If \p FoldTail is true, also create a mask guarding the loop
/// \p Plan. If \p FoldTail is true, create a mask guarding the loop

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done thanks

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done thanks

/// header, otherwise use all-true for the header mask. Masks for blocks are
/// added to \p BlockMaskCache, which in turn is temporarily used for wide
/// recipe construction. This argument is temporary and will be removed in the
/// future.
/// added to \p BlockMaskCache, which in turn will temporarily be used later
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
/// added to \p BlockMaskCache, which in turn will temporarily be used later
/// added to \p BlockMaskCache in order to be used later

/// for wide recipe construction. This argument is temporary and will be
/// removed in the future.
static void
predicateAndLinearize(VPlan &Plan, bool FoldTail,
DenseMap<VPBasicBlock *, VPValue *> &BlockMaskCache);
Expand Down
Morty Proxy This is a proxified and sanitized view of the page, visit original site.