Skip to content

Commit d77a36e

Browse files
authored
[LoopVectorize] Use new getUniqueLatchExitBlock routine (#108231)
With PR #88385 I am introducing support for vectorising more loops with early exits that don't require a scalar epilogue. As such, if a loop doesn't have a unique exit block it will not automatically imply we require a scalar epilogue. Also, in all places in the code today where we use the variable LoopExitBlock we actually mean the exit block from the latch. Therefore, it seemed reasonable to add a new getUniqueLatchExitBlock that allows the caller to determine the exit block taken from the latch and use this instead of getUniqueExitBlock. I also renamed LoopExitBlock to be LatchExitBlock. I feel this not only better reflects how the variable is used today, but also prepares the code for PR #88385. While doing this I also noticed that one of the comments in requiresScalarEpilogue is wrong when we require a scalar epilogue, i.e. when we're not exiting from the latch block. This doesn't always imply we have multiple exits, e.g. see the test in Transforms/LoopVectorize/unroll_nonlatch.ll where the latch unconditionally branches back to the only exiting block.
1 parent f363f9d commit d77a36e

File tree

3 files changed

+22
-12
lines changed

3 files changed

+22
-12
lines changed

llvm/include/llvm/Support/GenericLoopInfo.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,10 @@ template <class BlockT, class LoopT> class LoopBase {
294294
/// Otherwise return null.
295295
BlockT *getUniqueExitBlock() const;
296296

297+
/// Return the unique exit block for the latch, or null if there are multiple
298+
/// different exit blocks or the latch is not exiting.
299+
BlockT *getUniqueLatchExitBlock() const;
300+
297301
/// Return true if this loop does not have any exit blocks.
298302
bool hasNoExitBlocks() const;
299303

llvm/include/llvm/Support/GenericLoopInfoImpl.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,17 @@ BlockT *LoopBase<BlockT, LoopT>::getUniqueExitBlock() const {
159159
return getExitBlockHelper(this, true).first;
160160
}
161161

162+
template <class BlockT, class LoopT>
163+
BlockT *LoopBase<BlockT, LoopT>::getUniqueLatchExitBlock() const {
164+
BlockT *Latch = getLoopLatch();
165+
assert(Latch && "Latch block must exists");
166+
auto IsExitBlock = [this](BlockT *BB, bool AllowRepeats) -> BlockT * {
167+
assert(!AllowRepeats && "Unexpected parameter value.");
168+
return !contains(BB) ? BB : nullptr;
169+
};
170+
return find_singleton<BlockT>(children<BlockT *>(Latch), IsExitBlock);
171+
}
172+
162173
/// getExitEdges - Return all pairs of (_inside_block_,_outside_block_).
163174
template <class BlockT, class LoopT>
164175
void LoopBase<BlockT, LoopT>::getExitEdges(

llvm/lib/Transforms/Vectorize/LoopVectorize.cpp

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -630,10 +630,6 @@ class InnerLoopVectorizer {
630630
/// Middle Block between the vector and the scalar.
631631
BasicBlock *LoopMiddleBlock;
632632

633-
/// The unique ExitBlock of the scalar loop if one exists. Note that
634-
/// there can be multiple exiting edges reaching this block.
635-
BasicBlock *LoopExitBlock;
636-
637633
/// A list of all bypass blocks. The first block is the entry of the loop.
638634
SmallVector<BasicBlock *, 4> LoopBypassBlocks;
639635

@@ -1361,8 +1357,8 @@ class LoopVectorizationCostModel {
13611357
// If we might exit from anywhere but the latch, must run the exiting
13621358
// iteration in scalar form.
13631359
if (TheLoop->getExitingBlock() != TheLoop->getLoopLatch()) {
1364-
LLVM_DEBUG(
1365-
dbgs() << "LV: Loop requires scalar epilogue: multiple exits\n");
1360+
LLVM_DEBUG(dbgs() << "LV: Loop requires scalar epilogue: not exiting "
1361+
"from latch block\n");
13661362
return true;
13671363
}
13681364
if (IsVectorizing && InterleaveInfo.requiresScalarEpilogue()) {
@@ -2033,8 +2029,7 @@ class GeneratedRTChecks {
20332029
/// adjusts the branches to branch to the vector preheader or \p Bypass,
20342030
/// depending on the generated condition.
20352031
BasicBlock *emitSCEVChecks(BasicBlock *Bypass,
2036-
BasicBlock *LoopVectorPreHeader,
2037-
BasicBlock *LoopExitBlock) {
2032+
BasicBlock *LoopVectorPreHeader) {
20382033
if (!SCEVCheckCond)
20392034
return nullptr;
20402035

@@ -2530,7 +2525,7 @@ void InnerLoopVectorizer::emitIterationCountCheck(BasicBlock *Bypass) {
25302525

25312526
BasicBlock *InnerLoopVectorizer::emitSCEVChecks(BasicBlock *Bypass) {
25322527
BasicBlock *const SCEVCheckBlock =
2533-
RTChecks.emitSCEVChecks(Bypass, LoopVectorPreHeader, LoopExitBlock);
2528+
RTChecks.emitSCEVChecks(Bypass, LoopVectorPreHeader);
25342529
if (!SCEVCheckBlock)
25352530
return nullptr;
25362531

@@ -2584,8 +2579,8 @@ BasicBlock *InnerLoopVectorizer::emitMemRuntimeChecks(BasicBlock *Bypass) {
25842579
void InnerLoopVectorizer::createVectorLoopSkeleton(StringRef Prefix) {
25852580
LoopVectorPreHeader = OrigLoop->getLoopPreheader();
25862581
assert(LoopVectorPreHeader && "Invalid loop structure");
2587-
LoopExitBlock = OrigLoop->getUniqueExitBlock(); // may be nullptr
2588-
assert((LoopExitBlock || Cost->requiresScalarEpilogue(VF.isVector())) &&
2582+
assert((OrigLoop->getUniqueExitBlock() ||
2583+
Cost->requiresScalarEpilogue(VF.isVector())) &&
25892584
"multiple exit loop without required epilogue?");
25902585

25912586
LoopMiddleBlock =
@@ -7936,7 +7931,7 @@ EpilogueVectorizerEpilogueLoop::createEpilogueVectorizedLoopSkeleton(
79367931
// If there is an epilogue which must run, there's no edge from the
79377932
// middle block to exit blocks and thus no need to update the immediate
79387933
// dominator of the exit blocks.
7939-
DT->changeImmediateDominator(LoopExitBlock,
7934+
DT->changeImmediateDominator(OrigLoop->getUniqueLatchExitBlock(),
79407935
EPI.EpilogueIterationCountCheck);
79417936

79427937
// Keep track of bypass blocks, as they feed start values to the induction and

0 commit comments

Comments
 (0)