Skip to content

Commit 175461a

Browse files
authored
[NFC][LoopVectorize] Make replaceVPBBWithIRVPBB more efficient (#111514)
In replaceVPBBWithIRVPBB we spend time erasing and appending predecessors and successors from a list, when all we really have to do is replace the old with the new. Not only is this more efficient, but it also preserves the ordering of successors and predecessors. This is something which may become important for vectorising early exit loops (see PR #88385), since a VPIRInstruction is the wrapper for a live-out phi with extra operands that map to the incoming block according to the block's predecessor.
1 parent 854ded9 commit 175461a

File tree

2 files changed

+36
-7
lines changed

2 files changed

+36
-7
lines changed

llvm/lib/Transforms/Vectorize/VPlan.cpp

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1004,13 +1004,9 @@ static void replaceVPBBWithIRVPBB(VPBasicBlock *VPBB, BasicBlock *IRBB) {
10041004
assert(!R.isPhi() && "Tried to move phi recipe to end of block");
10051005
R.moveBefore(*IRVPBB, IRVPBB->end());
10061006
}
1007-
VPBlockBase *PredVPBB = VPBB->getSinglePredecessor();
1008-
VPBlockUtils::disconnectBlocks(PredVPBB, VPBB);
1009-
VPBlockUtils::connectBlocks(PredVPBB, IRVPBB);
1010-
for (auto *Succ : to_vector(VPBB->getSuccessors())) {
1011-
VPBlockUtils::connectBlocks(IRVPBB, Succ);
1012-
VPBlockUtils::disconnectBlocks(VPBB, Succ);
1013-
}
1007+
1008+
VPBlockUtils::reassociateBlocks(VPBB, IRVPBB);
1009+
10141010
delete VPBB;
10151011
}
10161012

llvm/lib/Transforms/Vectorize/VPlan.h

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -440,6 +440,26 @@ class VPBlockBase {
440440
Successors.erase(Pos);
441441
}
442442

443+
/// This function replaces one predecessor with another, useful when
444+
/// trying to replace an old block in the CFG with a new one.
445+
void replacePredecessor(VPBlockBase *Old, VPBlockBase *New) {
446+
auto I = find(Predecessors, Old);
447+
assert(I != Predecessors.end());
448+
assert(Old->getParent() == New->getParent() &&
449+
"replaced predecessor must have the same parent");
450+
*I = New;
451+
}
452+
453+
/// This function replaces one successor with another, useful when
454+
/// trying to replace an old block in the CFG with a new one.
455+
void replaceSuccessor(VPBlockBase *Old, VPBlockBase *New) {
456+
auto I = find(Successors, Old);
457+
assert(I != Successors.end());
458+
assert(Old->getParent() == New->getParent() &&
459+
"replaced successor must have the same parent");
460+
*I = New;
461+
}
462+
443463
protected:
444464
VPBlockBase(const unsigned char SC, const std::string &N)
445465
: SubclassID(SC), Name(N) {}
@@ -3947,6 +3967,19 @@ class VPBlockUtils {
39473967
To->removePredecessor(From);
39483968
}
39493969

3970+
/// Reassociate all the blocks connected to \p Old so that they now point to
3971+
/// \p New.
3972+
static void reassociateBlocks(VPBlockBase *Old, VPBlockBase *New) {
3973+
for (auto *Pred : to_vector(Old->getPredecessors()))
3974+
Pred->replaceSuccessor(Old, New);
3975+
for (auto *Succ : to_vector(Old->getSuccessors()))
3976+
Succ->replacePredecessor(Old, New);
3977+
New->setPredecessors(Old->getPredecessors());
3978+
New->setSuccessors(Old->getSuccessors());
3979+
Old->clearPredecessors();
3980+
Old->clearSuccessors();
3981+
}
3982+
39503983
/// Return an iterator range over \p Range which only includes \p BlockTy
39513984
/// blocks. The accesses are casted to \p BlockTy.
39523985
template <typename BlockTy, typename T>

0 commit comments

Comments
 (0)