Skip to content

Commit 4a2ebd6

Browse files
authored
[LV][NFC] Refactor structures used to maintain uncountable exit info (#123219)
I've removed the HasUncountableEarlyExit variable, since we can already determine whether or not a loop has an early exit by seeing if we found an uncountable exit. I have also deleted the old UncountableExitingBlocks and UncountableExitBlocks lists and replaced them with a single uncountable edge. This means we don't need to worry about keeping the list entries in sync and makes it clear which exiting block corresponds to which exit block.
1 parent 28c819c commit 4a2ebd6

File tree

2 files changed

+34
-46
lines changed

2 files changed

+34
-46
lines changed

llvm/include/llvm/Transforms/Vectorize/LoopVectorizationLegality.h

Lines changed: 17 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -389,27 +389,21 @@ class LoopVectorizationLegality {
389389
return LAI->getDepChecker().getMaxSafeVectorWidthInBits();
390390
}
391391

392-
/// Returns true if the loop has an uncountable early exit, i.e. an
392+
/// Returns true if the loop has exactly one uncountable early exit, i.e. an
393393
/// uncountable exit that isn't the latch block.
394-
bool hasUncountableEarlyExit() const { return HasUncountableEarlyExit; }
394+
bool hasUncountableEarlyExit() const {
395+
return getUncountableEdge().has_value();
396+
}
395397

396-
/// Returns the uncountable early exiting block.
398+
/// Returns the uncountable early exiting block, if there is exactly one.
397399
BasicBlock *getUncountableEarlyExitingBlock() const {
398-
if (!HasUncountableEarlyExit) {
399-
assert(getUncountableExitingBlocks().empty() &&
400-
"Expected no uncountable exiting blocks");
401-
return nullptr;
402-
}
403-
assert(getUncountableExitingBlocks().size() == 1 &&
404-
"Expected only a single uncountable exiting block");
405-
return getUncountableExitingBlocks()[0];
400+
return hasUncountableEarlyExit() ? getUncountableEdge()->first : nullptr;
406401
}
407402

408-
/// Returns the destination of an uncountable early exiting block.
403+
/// Returns the destination of the uncountable early exiting block, if there
404+
/// is exactly one.
409405
BasicBlock *getUncountableEarlyExitBlock() const {
410-
assert(getUncountableExitBlocks().size() == 1 &&
411-
"Expected only a single uncountable exit block");
412-
return getUncountableExitBlocks()[0];
406+
return hasUncountableEarlyExit() ? getUncountableEdge()->second : nullptr;
413407
}
414408

415409
/// Returns true if vector representation of the instruction \p I
@@ -463,14 +457,11 @@ class LoopVectorizationLegality {
463457
return CountableExitingBlocks;
464458
}
465459

466-
/// Returns all the exiting blocks with an uncountable exit.
467-
const SmallVector<BasicBlock *, 4> &getUncountableExitingBlocks() const {
468-
return UncountableExitingBlocks;
469-
}
470-
471-
/// Returns all the exit blocks from uncountable exiting blocks.
472-
SmallVector<BasicBlock *, 4> getUncountableExitBlocks() const {
473-
return UncountableExitBlocks;
460+
/// Returns the loop edge to an uncountable exit, or std::nullopt if there
461+
/// isn't a single such edge.
462+
std::optional<std::pair<BasicBlock *, BasicBlock *>>
463+
getUncountableEdge() const {
464+
return UncountableEdge;
474465
}
475466

476467
private:
@@ -654,18 +645,13 @@ class LoopVectorizationLegality {
654645
/// supported.
655646
bool StructVecCallFound = false;
656647

657-
/// Indicates whether this loop has an uncountable early exit, i.e. an
658-
/// uncountable exiting block that is not the latch.
659-
bool HasUncountableEarlyExit = false;
660-
661648
/// Keep track of all the countable and uncountable exiting blocks if
662649
/// the exact backedge taken count is not computable.
663650
SmallVector<BasicBlock *, 4> CountableExitingBlocks;
664-
SmallVector<BasicBlock *, 4> UncountableExitingBlocks;
665651

666-
/// Keep track of the destinations of all uncountable exits if the
667-
/// exact backedge taken count is not computable.
668-
SmallVector<BasicBlock *, 4> UncountableExitBlocks;
652+
/// Keep track of the loop edge to an uncountable exit, comprising a pair
653+
/// of (Exiting, Exit) blocks, if there is exactly one early exit.
654+
std::optional<std::pair<BasicBlock *, BasicBlock *>> UncountableEdge;
669655
};
670656

671657
} // namespace llvm

llvm/lib/Transforms/Vectorize/LoopVectorizationLegality.cpp

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1631,12 +1631,11 @@ bool LoopVectorizationLegality::isVectorizableEarlyExitLoop() {
16311631

16321632
// Keep a record of all the exiting blocks.
16331633
SmallVector<const SCEVPredicate *, 4> Predicates;
1634+
std::optional<std::pair<BasicBlock *, BasicBlock *>> SingleUncountableEdge;
16341635
for (BasicBlock *BB : ExitingBlocks) {
16351636
const SCEV *EC =
16361637
PSE.getSE()->getPredicatedExitCount(TheLoop, BB, &Predicates);
16371638
if (isa<SCEVCouldNotCompute>(EC)) {
1638-
UncountableExitingBlocks.push_back(BB);
1639-
16401639
SmallVector<BasicBlock *, 2> Succs(successors(BB));
16411640
if (Succs.size() != 2) {
16421641
reportVectorizationFailure(
@@ -1653,7 +1652,16 @@ bool LoopVectorizationLegality::isVectorizableEarlyExitLoop() {
16531652
assert(!TheLoop->contains(Succs[1]));
16541653
ExitBlock = Succs[1];
16551654
}
1656-
UncountableExitBlocks.push_back(ExitBlock);
1655+
1656+
if (SingleUncountableEdge) {
1657+
reportVectorizationFailure(
1658+
"Loop has too many uncountable exits",
1659+
"Cannot vectorize early exit loop with more than one early exit",
1660+
"TooManyUncountableEarlyExits", ORE, TheLoop);
1661+
return false;
1662+
}
1663+
1664+
SingleUncountableEdge = {BB, ExitBlock};
16571665
} else
16581666
CountableExitingBlocks.push_back(BB);
16591667
}
@@ -1663,19 +1671,15 @@ bool LoopVectorizationLegality::isVectorizableEarlyExitLoop() {
16631671
// PSE.getSymbolicMaxBackedgeTakenCount() below.
16641672
Predicates.clear();
16651673

1666-
// We only support one uncountable early exit.
1667-
if (getUncountableExitingBlocks().size() != 1) {
1668-
reportVectorizationFailure(
1669-
"Loop has too many uncountable exits",
1670-
"Cannot vectorize early exit loop with more than one early exit",
1671-
"TooManyUncountableEarlyExits", ORE, TheLoop);
1674+
if (!SingleUncountableEdge) {
1675+
LLVM_DEBUG(dbgs() << "LV: Cound not find any uncountable exits");
16721676
return false;
16731677
}
16741678

16751679
// The only supported early exit loops so far are ones where the early
16761680
// exiting block is a unique predecessor of the latch block.
16771681
BasicBlock *LatchPredBB = LatchBB->getUniquePredecessor();
1678-
if (LatchPredBB != getUncountableEarlyExitingBlock()) {
1682+
if (LatchPredBB != SingleUncountableEdge->first) {
16791683
reportVectorizationFailure("Early exit is not the latch predecessor",
16801684
"Cannot vectorize early exit loop",
16811685
"EarlyExitNotLatchPredecessor", ORE, TheLoop);
@@ -1728,7 +1732,7 @@ bool LoopVectorizationLegality::isVectorizableEarlyExitLoop() {
17281732
}
17291733

17301734
// The vectoriser cannot handle loads that occur after the early exit block.
1731-
assert(LatchBB->getUniquePredecessor() == getUncountableEarlyExitingBlock() &&
1735+
assert(LatchBB->getUniquePredecessor() == SingleUncountableEdge->first &&
17321736
"Expected latch predecessor to be the early exiting block");
17331737

17341738
// TODO: Handle loops that may fault.
@@ -1751,6 +1755,7 @@ bool LoopVectorizationLegality::isVectorizableEarlyExitLoop() {
17511755
LLVM_DEBUG(dbgs() << "LV: Found an early exit loop with symbolic max "
17521756
"backedge taken count: "
17531757
<< *SymbolicMaxBTC << '\n');
1758+
UncountableEdge = SingleUncountableEdge;
17541759
return true;
17551760
}
17561761

@@ -1812,7 +1817,6 @@ bool LoopVectorizationLegality::canVectorize(bool UseVPlanNativePath) {
18121817
return false;
18131818
}
18141819

1815-
HasUncountableEarlyExit = false;
18161820
if (isa<SCEVCouldNotCompute>(PSE.getBackedgeTakenCount())) {
18171821
if (TheLoop->getExitingBlock()) {
18181822
reportVectorizationFailure("Cannot vectorize uncountable loop",
@@ -1822,10 +1826,8 @@ bool LoopVectorizationLegality::canVectorize(bool UseVPlanNativePath) {
18221826
else
18231827
return false;
18241828
} else {
1825-
HasUncountableEarlyExit = true;
18261829
if (!isVectorizableEarlyExitLoop()) {
1827-
UncountableExitingBlocks.clear();
1828-
HasUncountableEarlyExit = false;
1830+
UncountableEdge = std::nullopt;
18291831
if (DoExtraAnalysis)
18301832
Result = false;
18311833
else

0 commit comments

Comments
 (0)