https://github.com/adelejjeh created https://github.com/llvm/llvm-project/pull/185895
Move loop unroll pragma query helpers (`getUnrollMetadataForLoop`,
`hasUnrollFullPragma`, `hasUnrollEnablePragma`,
`hasRuntimeUnrollDisablePragma`, `unrollCountPragmaValue`) from
`LoopUnrollPass.cpp` and `LoopUnrollAndJamPass.cpp` into
`LoopUnroll.cpp`, and declare them in `UnrollLoop.h`.
These functions were duplicated as `static` helpers in both
`LoopUnrollPass.cpp` and `LoopUnrollAndJamPass.cpp`. Making them
available in `UnrollLoop.h` eliminates the duplication and allows
target-specific code (e.g. TTI implementations) to query unroll
pragma metadata when setting unrolling preferences.
This is in preparation for an upcoming AMDGPU-specific change that
enables `AllowExpensiveTripCount` for pragma-unrolled loops in
AMDGPU's `getUnrollingPreferences()` (see #181267), while
discussions on changing the default behavior for all targets continue.
No functional change.
>From 2a53f07759580d1b5d8a55dcdea2c4d40b374a53 Mon Sep 17 00:00:00 2001
From: Adel Ejjeh <adel.ejjeh at amd.com>
Date: Wed, 11 Mar 2026 09:54:47 -0500
Subject: [PATCH] [NFC] refactor shared loop-unrolling functions in preperation
for AMDGPU TTI changes
---
.../llvm/Transforms/Utils/UnrollLoop.h | 19 +++++++++
.../Scalar/LoopUnrollAndJamPass.cpp | 9 -----
llvm/lib/Transforms/Scalar/LoopUnrollPass.cpp | 40 -------------------
llvm/lib/Transforms/Utils/LoopUnroll.cpp | 40 +++++++++++++++++++
4 files changed, 59 insertions(+), 49 deletions(-)
diff --git a/llvm/include/llvm/Transforms/Utils/UnrollLoop.h b/llvm/include/llvm/Transforms/Utils/UnrollLoop.h
index c6c691e683b22..3cff29629207e 100644
--- a/llvm/include/llvm/Transforms/Utils/UnrollLoop.h
+++ b/llvm/include/llvm/Transforms/Utils/UnrollLoop.h
@@ -119,6 +119,25 @@ LLVM_ABI void simplifyLoopAfterUnroll(Loop *L, bool SimplifyIVs, LoopInfo *LI,
LLVM_ABI MDNode *GetUnrollMetadata(MDNode *LoopID, StringRef Name);
+// Returns the loop hint metadata node with the given name (for example,
+// "llvm.loop.unroll.count"). If no such metadata node exists, then nullptr is
+// returned.
+LLVM_ABI MDNode *getUnrollMetadataForLoop(const Loop *L, StringRef Name);
+
+// Returns true if the loop has an unroll(full) pragma.
+LLVM_ABI bool hasUnrollFullPragma(const Loop *L);
+
+// Returns true if the loop has an unroll(enable) pragma. This metadata is used
+// for both "#pragma unroll" and "#pragma clang loop unroll(enable)" directives.
+LLVM_ABI bool hasUnrollEnablePragma(const Loop *L);
+
+// Returns true if the loop has an runtime unroll(disable) pragma.
+LLVM_ABI bool hasRuntimeUnrollDisablePragma(const Loop *L);
+
+// If loop has an unroll_count pragma return the (necessarily
+// positive) value from the pragma. Otherwise return 0.
+LLVM_ABI unsigned unrollCountPragmaValue(const Loop *L);
+
LLVM_ABI TargetTransformInfo::UnrollingPreferences gatherUnrollingPreferences(
Loop *L, ScalarEvolution &SE, const TargetTransformInfo &TTI,
BlockFrequencyInfo *BFI, ProfileSummaryInfo *PSI,
diff --git a/llvm/lib/Transforms/Scalar/LoopUnrollAndJamPass.cpp b/llvm/lib/Transforms/Scalar/LoopUnrollAndJamPass.cpp
index 1121690dbbb69..a382bf03b0a8d 100644
--- a/llvm/lib/Transforms/Scalar/LoopUnrollAndJamPass.cpp
+++ b/llvm/lib/Transforms/Scalar/LoopUnrollAndJamPass.cpp
@@ -84,15 +84,6 @@ static cl::opt<unsigned> PragmaUnrollAndJamThreshold(
cl::desc("Unrolled size limit for loops with an unroll_and_jam(full) or "
"unroll_count pragma."));
-// Returns the loop hint metadata node with the given name (for example,
-// "llvm.loop.unroll.count"). If no such metadata node exists, then nullptr is
-// returned.
-static MDNode *getUnrollMetadataForLoop(const Loop *L, StringRef Name) {
- if (MDNode *LoopID = L->getLoopID())
- return GetUnrollMetadata(LoopID, Name);
- return nullptr;
-}
-
// Returns true if the loop has any metadata starting with Prefix. For example a
// Prefix of "llvm.loop.unroll." returns true if we have any unroll metadata.
static bool hasAnyUnrollPragma(const Loop *L, StringRef Prefix) {
diff --git a/llvm/lib/Transforms/Scalar/LoopUnrollPass.cpp b/llvm/lib/Transforms/Scalar/LoopUnrollPass.cpp
index 4acd5aa27f61a..ec3a61c1ba276 100644
--- a/llvm/lib/Transforms/Scalar/LoopUnrollPass.cpp
+++ b/llvm/lib/Transforms/Scalar/LoopUnrollPass.cpp
@@ -746,46 +746,6 @@ uint64_t UnrollCostEstimator::getUnrolledLoopSize(
return static_cast<uint64_t>(LS - UP.BEInsns) * UP.Count + UP.BEInsns;
}
-// Returns the loop hint metadata node with the given name (for example,
-// "llvm.loop.unroll.count"). If no such metadata node exists, then nullptr is
-// returned.
-static MDNode *getUnrollMetadataForLoop(const Loop *L, StringRef Name) {
- if (MDNode *LoopID = L->getLoopID())
- return GetUnrollMetadata(LoopID, Name);
- return nullptr;
-}
-
-// Returns true if the loop has an unroll(full) pragma.
-static bool hasUnrollFullPragma(const Loop *L) {
- return getUnrollMetadataForLoop(L, "llvm.loop.unroll.full");
-}
-
-// Returns true if the loop has an unroll(enable) pragma. This metadata is used
-// for both "#pragma unroll" and "#pragma clang loop unroll(enable)" directives.
-static bool hasUnrollEnablePragma(const Loop *L) {
- return getUnrollMetadataForLoop(L, "llvm.loop.unroll.enable");
-}
-
-// Returns true if the loop has an runtime unroll(disable) pragma.
-static bool hasRuntimeUnrollDisablePragma(const Loop *L) {
- return getUnrollMetadataForLoop(L, "llvm.loop.unroll.runtime.disable");
-}
-
-// If loop has an unroll_count pragma return the (necessarily
-// positive) value from the pragma. Otherwise return 0.
-static unsigned unrollCountPragmaValue(const Loop *L) {
- MDNode *MD = getUnrollMetadataForLoop(L, "llvm.loop.unroll.count");
- if (MD) {
- assert(MD->getNumOperands() == 2 &&
- "Unroll count hint metadata should have two operands.");
- unsigned Count =
- mdconst::extract<ConstantInt>(MD->getOperand(1))->getZExtValue();
- assert(Count >= 1 && "Unroll count must be positive.");
- return Count;
- }
- return 0;
-}
-
// Computes the boosting factor for complete unrolling.
// If fully unrolling the loop would save a lot of RolledDynamicCost, it would
// be beneficial to fully unroll the loop even if unrolledcost is large. We
diff --git a/llvm/lib/Transforms/Utils/LoopUnroll.cpp b/llvm/lib/Transforms/Utils/LoopUnroll.cpp
index d9422afe5e82a..d699f1eb7e786 100644
--- a/llvm/lib/Transforms/Utils/LoopUnroll.cpp
+++ b/llvm/lib/Transforms/Utils/LoopUnroll.cpp
@@ -1252,6 +1252,46 @@ MDNode *llvm::GetUnrollMetadata(MDNode *LoopID, StringRef Name) {
return nullptr;
}
+// Returns the loop hint metadata node with the given name (for example,
+// "llvm.loop.unroll.count"). If no such metadata node exists, then nullptr is
+// returned.
+MDNode *llvm::getUnrollMetadataForLoop(const Loop *L, StringRef Name) {
+ if (MDNode *LoopID = L->getLoopID())
+ return GetUnrollMetadata(LoopID, Name);
+ return nullptr;
+}
+
+// Returns true if the loop has an unroll(full) pragma.
+bool llvm::hasUnrollFullPragma(const Loop *L) {
+ return getUnrollMetadataForLoop(L, "llvm.loop.unroll.full");
+}
+
+// Returns true if the loop has an unroll(enable) pragma. This metadata is used
+// for both "#pragma unroll" and "#pragma clang loop unroll(enable)" directives.
+bool llvm::hasUnrollEnablePragma(const Loop *L) {
+ return getUnrollMetadataForLoop(L, "llvm.loop.unroll.enable");
+}
+
+// Returns true if the loop has an runtime unroll(disable) pragma.
+bool llvm::hasRuntimeUnrollDisablePragma(const Loop *L) {
+ return getUnrollMetadataForLoop(L, "llvm.loop.unroll.runtime.disable");
+}
+
+// If loop has an unroll_count pragma return the (necessarily
+// positive) value from the pragma. Otherwise return 0.
+unsigned llvm::unrollCountPragmaValue(const Loop *L) {
+ MDNode *MD = getUnrollMetadataForLoop(L, "llvm.loop.unroll.count");
+ if (MD) {
+ assert(MD->getNumOperands() == 2 &&
+ "Unroll count hint metadata should have two operands.");
+ unsigned Count =
+ mdconst::extract<ConstantInt>(MD->getOperand(1))->getZExtValue();
+ assert(Count >= 1 && "Unroll count must be positive.");
+ return Count;
+ }
+ return 0;
+}
+
std::optional<RecurrenceDescriptor>
llvm::canParallelizeReductionWhenUnrolling(PHINode &Phi, Loop *L,
ScalarEvolution *SE) {