[llvm] [LV][NFC] Refactor structures used to maintain uncountable exit info (PR #123219)
David Sherwood via llvm-commits
llvm-commits at lists.llvm.org
Fri Jan 17 07:53:27 PST 2025
https://github.com/david-arm updated https://github.com/llvm/llvm-project/pull/123219
>From 3e474b1d7976026c46949e813596d040e363178e Mon Sep 17 00:00:00 2001
From: David Sherwood <david.sherwood at arm.com>
Date: Thu, 16 Jan 2025 16:45:06 +0000
Subject: [PATCH 1/3] [LV][NFC] Refactor structures used to maintain
uncountable exit info
I've removed the HasUncountableEarlyExit variable, since we can
already determine whether or not a loop has an early exit by seeing
how many uncountable exit blocks we found.
I have also deleted the old UncountableExitingBlocks and
UncountableExitBlocks lists and replaced them with a single list of
edges. 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.
---
.../Vectorize/LoopVectorizationLegality.h | 40 +++++++------------
.../Vectorize/LoopVectorizationLegality.cpp | 11 ++---
2 files changed, 18 insertions(+), 33 deletions(-)
diff --git a/llvm/include/llvm/Transforms/Vectorize/LoopVectorizationLegality.h b/llvm/include/llvm/Transforms/Vectorize/LoopVectorizationLegality.h
index 72fda911962ad2..5764e3a487f3e3 100644
--- a/llvm/include/llvm/Transforms/Vectorize/LoopVectorizationLegality.h
+++ b/llvm/include/llvm/Transforms/Vectorize/LoopVectorizationLegality.h
@@ -391,25 +391,24 @@ class LoopVectorizationLegality {
/// Returns true if the loop has an uncountable early exit, i.e. an
/// uncountable exit that isn't the latch block.
- bool hasUncountableEarlyExit() const { return HasUncountableEarlyExit; }
+ bool hasUncountableEarlyExit() const { return getUncountableEdges().size(); }
/// Returns the uncountable early exiting block.
BasicBlock *getUncountableEarlyExitingBlock() const {
- if (!HasUncountableEarlyExit) {
- assert(getUncountableExitingBlocks().empty() &&
- "Expected no uncountable exiting blocks");
+ if (!hasUncountableEarlyExit())
return nullptr;
- }
- assert(getUncountableExitingBlocks().size() == 1 &&
+ assert(getUncountableEdges().size() == 1 &&
"Expected only a single uncountable exiting block");
- return getUncountableExitingBlocks()[0];
+ return getUncountableEdges()[0].first;
}
/// Returns the destination of an uncountable early exiting block.
BasicBlock *getUncountableEarlyExitBlock() const {
- assert(getUncountableExitBlocks().size() == 1 &&
+ if (!hasUncountableEarlyExit())
+ return nullptr;
+ assert(getUncountableEdges().size() == 1 &&
"Expected only a single uncountable exit block");
- return getUncountableExitBlocks()[0];
+ return getUncountableEdges()[0].second;
}
/// Returns true if vector representation of the instruction \p I
@@ -463,14 +462,10 @@ class LoopVectorizationLegality {
return CountableExitingBlocks;
}
- /// Returns all the exiting blocks with an uncountable exit.
- const SmallVector<BasicBlock *, 4> &getUncountableExitingBlocks() const {
- return UncountableExitingBlocks;
- }
-
- /// Returns all the exit blocks from uncountable exiting blocks.
- SmallVector<BasicBlock *, 4> getUncountableExitBlocks() const {
- return UncountableExitBlocks;
+ /// Returns all the loop edges that have an uncountable exit.
+ const SmallVector<std::pair<BasicBlock *, BasicBlock *>, 4> &
+ getUncountableEdges() const {
+ return UncountableEdges;
}
private:
@@ -654,18 +649,13 @@ class LoopVectorizationLegality {
/// supported.
bool StructVecCallFound = false;
- /// Indicates whether this loop has an uncountable early exit, i.e. an
- /// uncountable exiting block that is not the latch.
- bool HasUncountableEarlyExit = false;
-
/// Keep track of all the countable and uncountable exiting blocks if
/// the exact backedge taken count is not computable.
SmallVector<BasicBlock *, 4> CountableExitingBlocks;
- SmallVector<BasicBlock *, 4> UncountableExitingBlocks;
- /// Keep track of the destinations of all uncountable exits if the
- /// exact backedge taken count is not computable.
- SmallVector<BasicBlock *, 4> UncountableExitBlocks;
+ /// Keep track of all the loop edges with uncountable exits, where each entry
+ /// is a pair of (Exiting, Exit) blocks.
+ SmallVector<std::pair<BasicBlock *, BasicBlock *>, 4> UncountableEdges;
};
} // namespace llvm
diff --git a/llvm/lib/Transforms/Vectorize/LoopVectorizationLegality.cpp b/llvm/lib/Transforms/Vectorize/LoopVectorizationLegality.cpp
index 406864a6793dc8..00bd429a0ef9d5 100644
--- a/llvm/lib/Transforms/Vectorize/LoopVectorizationLegality.cpp
+++ b/llvm/lib/Transforms/Vectorize/LoopVectorizationLegality.cpp
@@ -1635,8 +1635,6 @@ bool LoopVectorizationLegality::isVectorizableEarlyExitLoop() {
const SCEV *EC =
PSE.getSE()->getPredicatedExitCount(TheLoop, BB, &Predicates);
if (isa<SCEVCouldNotCompute>(EC)) {
- UncountableExitingBlocks.push_back(BB);
-
SmallVector<BasicBlock *, 2> Succs(successors(BB));
if (Succs.size() != 2) {
reportVectorizationFailure(
@@ -1653,7 +1651,7 @@ bool LoopVectorizationLegality::isVectorizableEarlyExitLoop() {
assert(!TheLoop->contains(Succs[1]));
ExitBlock = Succs[1];
}
- UncountableExitBlocks.push_back(ExitBlock);
+ UncountableEdges.push_back({BB, ExitBlock});
} else
CountableExitingBlocks.push_back(BB);
}
@@ -1664,7 +1662,7 @@ bool LoopVectorizationLegality::isVectorizableEarlyExitLoop() {
Predicates.clear();
// We only support one uncountable early exit.
- if (getUncountableExitingBlocks().size() != 1) {
+ if (getUncountableEdges().size() != 1) {
reportVectorizationFailure(
"Loop has too many uncountable exits",
"Cannot vectorize early exit loop with more than one early exit",
@@ -1812,7 +1810,6 @@ bool LoopVectorizationLegality::canVectorize(bool UseVPlanNativePath) {
return false;
}
- HasUncountableEarlyExit = false;
if (isa<SCEVCouldNotCompute>(PSE.getBackedgeTakenCount())) {
if (TheLoop->getExitingBlock()) {
reportVectorizationFailure("Cannot vectorize uncountable loop",
@@ -1822,10 +1819,8 @@ bool LoopVectorizationLegality::canVectorize(bool UseVPlanNativePath) {
else
return false;
} else {
- HasUncountableEarlyExit = true;
if (!isVectorizableEarlyExitLoop()) {
- UncountableExitingBlocks.clear();
- HasUncountableEarlyExit = false;
+ UncountableEdges.clear();
if (DoExtraAnalysis)
Result = false;
else
>From 1323c0671e44f6a7c410c350c0f3169437636372 Mon Sep 17 00:00:00 2001
From: David Sherwood <david.sherwood at arm.com>
Date: Fri, 17 Jan 2025 09:47:20 +0000
Subject: [PATCH 2/3] Address review comments
---
.../Vectorize/LoopVectorizationLegality.h | 26 +++++++++----------
.../Vectorize/LoopVectorizationLegality.cpp | 10 ++++---
2 files changed, 18 insertions(+), 18 deletions(-)
diff --git a/llvm/include/llvm/Transforms/Vectorize/LoopVectorizationLegality.h b/llvm/include/llvm/Transforms/Vectorize/LoopVectorizationLegality.h
index 5764e3a487f3e3..a8a2695b5169ae 100644
--- a/llvm/include/llvm/Transforms/Vectorize/LoopVectorizationLegality.h
+++ b/llvm/include/llvm/Transforms/Vectorize/LoopVectorizationLegality.h
@@ -391,24 +391,22 @@ class LoopVectorizationLegality {
/// Returns true if the loop has an uncountable early exit, i.e. an
/// uncountable exit that isn't the latch block.
- bool hasUncountableEarlyExit() const { return getUncountableEdges().size(); }
+ bool hasUncountableEarlyExit() const {
+ return getUncountableEdge().has_value();
+ }
/// Returns the uncountable early exiting block.
BasicBlock *getUncountableEarlyExitingBlock() const {
if (!hasUncountableEarlyExit())
return nullptr;
- assert(getUncountableEdges().size() == 1 &&
- "Expected only a single uncountable exiting block");
- return getUncountableEdges()[0].first;
+ return (*getUncountableEdge()).first;
}
/// Returns the destination of an uncountable early exiting block.
BasicBlock *getUncountableEarlyExitBlock() const {
if (!hasUncountableEarlyExit())
return nullptr;
- assert(getUncountableEdges().size() == 1 &&
- "Expected only a single uncountable exit block");
- return getUncountableEdges()[0].second;
+ return (*getUncountableEdge()).second;
}
/// Returns true if vector representation of the instruction \p I
@@ -462,10 +460,10 @@ class LoopVectorizationLegality {
return CountableExitingBlocks;
}
- /// Returns all the loop edges that have an uncountable exit.
- const SmallVector<std::pair<BasicBlock *, BasicBlock *>, 4> &
- getUncountableEdges() const {
- return UncountableEdges;
+ /// Returns the loop edge with an uncountable exit.
+ std::optional<std::pair<BasicBlock *, BasicBlock *>>
+ getUncountableEdge() const {
+ return UncountableEdge;
}
private:
@@ -653,9 +651,9 @@ class LoopVectorizationLegality {
/// the exact backedge taken count is not computable.
SmallVector<BasicBlock *, 4> CountableExitingBlocks;
- /// Keep track of all the loop edges with uncountable exits, where each entry
- /// is a pair of (Exiting, Exit) blocks.
- SmallVector<std::pair<BasicBlock *, BasicBlock *>, 4> UncountableEdges;
+ /// Keep track of the loop edge with an uncountable exit, comprising a pair
+ /// of (Exiting, Exit) blocks.
+ std::optional<std::pair<BasicBlock *, BasicBlock *>> UncountableEdge;
};
} // namespace llvm
diff --git a/llvm/lib/Transforms/Vectorize/LoopVectorizationLegality.cpp b/llvm/lib/Transforms/Vectorize/LoopVectorizationLegality.cpp
index 00bd429a0ef9d5..f3a44a0414985e 100644
--- a/llvm/lib/Transforms/Vectorize/LoopVectorizationLegality.cpp
+++ b/llvm/lib/Transforms/Vectorize/LoopVectorizationLegality.cpp
@@ -1631,6 +1631,7 @@ bool LoopVectorizationLegality::isVectorizableEarlyExitLoop() {
// Keep a record of all the exiting blocks.
SmallVector<const SCEVPredicate *, 4> Predicates;
+ SmallVector<std::pair<BasicBlock *, BasicBlock *>, 4> UncountableEdges;
for (BasicBlock *BB : ExitingBlocks) {
const SCEV *EC =
PSE.getSE()->getPredicatedExitCount(TheLoop, BB, &Predicates);
@@ -1662,7 +1663,7 @@ bool LoopVectorizationLegality::isVectorizableEarlyExitLoop() {
Predicates.clear();
// We only support one uncountable early exit.
- if (getUncountableEdges().size() != 1) {
+ if (UncountableEdges.size() != 1) {
reportVectorizationFailure(
"Loop has too many uncountable exits",
"Cannot vectorize early exit loop with more than one early exit",
@@ -1673,7 +1674,7 @@ bool LoopVectorizationLegality::isVectorizableEarlyExitLoop() {
// The only supported early exit loops so far are ones where the early
// exiting block is a unique predecessor of the latch block.
BasicBlock *LatchPredBB = LatchBB->getUniquePredecessor();
- if (LatchPredBB != getUncountableEarlyExitingBlock()) {
+ if (LatchPredBB != UncountableEdges[0].first) {
reportVectorizationFailure("Early exit is not the latch predecessor",
"Cannot vectorize early exit loop",
"EarlyExitNotLatchPredecessor", ORE, TheLoop);
@@ -1726,7 +1727,7 @@ bool LoopVectorizationLegality::isVectorizableEarlyExitLoop() {
}
// The vectoriser cannot handle loads that occur after the early exit block.
- assert(LatchBB->getUniquePredecessor() == getUncountableEarlyExitingBlock() &&
+ assert(LatchBB->getUniquePredecessor() == UncountableEdges[0].first &&
"Expected latch predecessor to be the early exiting block");
// TODO: Handle loops that may fault.
@@ -1749,6 +1750,7 @@ bool LoopVectorizationLegality::isVectorizableEarlyExitLoop() {
LLVM_DEBUG(dbgs() << "LV: Found an early exit loop with symbolic max "
"backedge taken count: "
<< *SymbolicMaxBTC << '\n');
+ UncountableEdge = UncountableEdges[0];
return true;
}
@@ -1820,7 +1822,7 @@ bool LoopVectorizationLegality::canVectorize(bool UseVPlanNativePath) {
return false;
} else {
if (!isVectorizableEarlyExitLoop()) {
- UncountableEdges.clear();
+ UncountableEdge = std::nullopt;
if (DoExtraAnalysis)
Result = false;
else
>From b6d7019bb57baea6cb286a7577018d5c3f447c2f Mon Sep 17 00:00:00 2001
From: David Sherwood <david.sherwood at arm.com>
Date: Fri, 17 Jan 2025 15:52:52 +0000
Subject: [PATCH 3/3] Address review comments
---
.../Vectorize/LoopVectorizationLegality.h | 20 +++++++++----------
1 file changed, 9 insertions(+), 11 deletions(-)
diff --git a/llvm/include/llvm/Transforms/Vectorize/LoopVectorizationLegality.h b/llvm/include/llvm/Transforms/Vectorize/LoopVectorizationLegality.h
index a8a2695b5169ae..721e5c72f44e66 100644
--- a/llvm/include/llvm/Transforms/Vectorize/LoopVectorizationLegality.h
+++ b/llvm/include/llvm/Transforms/Vectorize/LoopVectorizationLegality.h
@@ -389,24 +389,21 @@ class LoopVectorizationLegality {
return LAI->getDepChecker().getMaxSafeVectorWidthInBits();
}
- /// Returns true if the loop has an uncountable early exit, i.e. an
+ /// Returns true if the loop has exactly one uncountable early exit, i.e. an
/// uncountable exit that isn't the latch block.
bool hasUncountableEarlyExit() const {
return getUncountableEdge().has_value();
}
- /// Returns the uncountable early exiting block.
+ /// Returns the uncountable early exiting block, if there is exactly one.
BasicBlock *getUncountableEarlyExitingBlock() const {
- if (!hasUncountableEarlyExit())
- return nullptr;
- return (*getUncountableEdge()).first;
+ return hasUncountableEarlyExit() ? getUncountableEdge()->first : nullptr;
}
- /// Returns the destination of an uncountable early exiting block.
+ /// Returns the destination of the uncountable early exiting block, if there
+ /// is exactly one.
BasicBlock *getUncountableEarlyExitBlock() const {
- if (!hasUncountableEarlyExit())
- return nullptr;
- return (*getUncountableEdge()).second;
+ return hasUncountableEarlyExit() ? getUncountableEdge()->second : nullptr;
}
/// Returns true if vector representation of the instruction \p I
@@ -460,7 +457,8 @@ class LoopVectorizationLegality {
return CountableExitingBlocks;
}
- /// Returns the loop edge with an uncountable exit.
+ /// Returns the loop edge with an uncountable exit, or std::nullopt if there
+ /// isn't a single such edge.
std::optional<std::pair<BasicBlock *, BasicBlock *>>
getUncountableEdge() const {
return UncountableEdge;
@@ -652,7 +650,7 @@ class LoopVectorizationLegality {
SmallVector<BasicBlock *, 4> CountableExitingBlocks;
/// Keep track of the loop edge with an uncountable exit, comprising a pair
- /// of (Exiting, Exit) blocks.
+ /// of (Exiting, Exit) blocks, if there is exactly one early exit.
std::optional<std::pair<BasicBlock *, BasicBlock *>> UncountableEdge;
};
More information about the llvm-commits
mailing list