[llvm] Add DropArrayBounds option to drop array bounds assumes (PR #178810)
Sebastian Pop via llvm-commits
llvm-commits at lists.llvm.org
Thu Jul 2 09:37:09 PDT 2026
https://github.com/sebpop updated https://github.com/llvm/llvm-project/pull/178810
>From 6061dcc0bed051f129ca4adec1c9c8df00464efd Mon Sep 17 00:00:00 2001
From: Sebastian Pop <spop at nvidia.com>
Date: Wed, 28 Jan 2026 14:12:38 -0600
Subject: [PATCH] [DropUnnecessaryAssumes] Add DropArrayBounds option to drop
array bounds assumes
Add a new DropArrayBounds option to DropUnnecessaryAssumesPass that drops
assumes marked with "llvm.array.bounds" metadata. These are array bounds
assumes from frontends like Flang and Clang that should be dropped before
vectorization to prevent IR bloat and avoid negatively impacting cost
models in later passes like LSR.
---
llvm/docs/LangRef.rst | 25 +++++++++++++++++++
.../Scalar/DropUnnecessaryAssumes.h | 11 ++++++--
llvm/lib/Passes/PassBuilder.cpp | 21 +++++++++++++---
llvm/lib/Passes/PassBuilderPipelines.cpp | 7 ++++++
llvm/lib/Passes/PassRegistry.def | 6 +++--
.../Scalar/DropUnnecessaryAssumes.cpp | 11 ++++++++
llvm/test/Other/new-pm-defaults.ll | 1 +
llvm/test/Other/new-pm-lto-defaults.ll | 1 +
.../Other/new-pm-thinlto-postlink-defaults.ll | 1 +
.../new-pm-thinlto-postlink-pgo-defaults.ll | 1 +
...-pm-thinlto-postlink-samplepgo-defaults.ll | 1 +
.../LoopInterchange/position-in-pipeline.ll | 1 +
12 files changed, 80 insertions(+), 7 deletions(-)
diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst
index 4d880494eb449..58ef58c9ac28d 100644
--- a/llvm/docs/LangRef.rst
+++ b/llvm/docs/LangRef.rst
@@ -8518,6 +8518,31 @@ without pointing to it directly (which is not possible in global
metadata). Currently, the only metadata making use of it is
``llvm.loop.parallel_accesses``.
+'``llvm.array.bounds``' Metadata
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+The ``llvm.array.bounds`` metadata can be attached to ``llvm.assume``
+intrinsic calls to indicate that the assumption originates from array
+bounds information provided by the frontend. This metadata is used by
+the optimizer to identify and remove these assumptions at appropriate
+points in the optimization pipeline.
+
+Frontends like Flang and Clang may generate ``llvm.assume`` calls based
+on array bounds information to help data dependence analysis and other
+optimizations. However, these assumes can cause IR bloat after
+vectorization and may negatively impact cost models in later passes
+like Loop Strength Reduction (LSR). The ``llvm.array.bounds`` metadata
+allows passes to selectively drop these assumptions after their primary
+purpose (aiding loop optimizations) has been fulfilled.
+
+The metadata node can be empty:
+
+.. code-block:: llvm
+
+ call void @llvm.assume(i1 %cmp), !llvm.array.bounds !0
+ ...
+ !0 = !{}
+
'``llvm.loop.parallel_accesses``' Metadata
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/llvm/include/llvm/Transforms/Scalar/DropUnnecessaryAssumes.h b/llvm/include/llvm/Transforms/Scalar/DropUnnecessaryAssumes.h
index e77fb437cf3ff..79eaabaeaa7af 100644
--- a/llvm/include/llvm/Transforms/Scalar/DropUnnecessaryAssumes.h
+++ b/llvm/include/llvm/Transforms/Scalar/DropUnnecessaryAssumes.h
@@ -19,13 +19,20 @@ namespace llvm {
struct DropUnnecessaryAssumesPass
: public OptionalPassInfoMixin<DropUnnecessaryAssumesPass> {
- DropUnnecessaryAssumesPass(bool DropDereferenceable = false)
- : DropDereferenceable(DropDereferenceable) {}
+ DropUnnecessaryAssumesPass(bool DropDereferenceable = false,
+ bool DropArrayBounds = false)
+ : DropDereferenceable(DropDereferenceable),
+ DropArrayBounds(DropArrayBounds) {}
LLVM_ABI PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
private:
bool DropDereferenceable;
+ // When true, drop assumes with "llvm.array.bounds" metadata. These are
+ // array bounds assumes from Fortran/C/C++ that should be dropped before
+ // vectorization to prevent IR bloat and avoid negatively impacting cost
+ // models in later passes like LSR.
+ bool DropArrayBounds;
};
} // end namespace llvm
diff --git a/llvm/lib/Passes/PassBuilder.cpp b/llvm/lib/Passes/PassBuilder.cpp
index 6dd9ab0eec054..ef7c3459f839e 100644
--- a/llvm/lib/Passes/PassBuilder.cpp
+++ b/llvm/lib/Passes/PassBuilder.cpp
@@ -955,9 +955,24 @@ Expected<bool> parseEntryExitInstrumenterPassOptions(StringRef Params) {
"EntryExitInstrumenter");
}
-Expected<bool> parseDropUnnecessaryAssumesPassOptions(StringRef Params) {
- return PassBuilder::parseSinglePassOption(Params, "drop-deref",
- "DropUnnecessaryAssumes");
+Expected<std::pair<bool, bool>>
+parseDropUnnecessaryAssumesPassOptions(StringRef Params) {
+ // {DropDereferenceable, DropArrayBounds}
+ std::pair<bool, bool> Result = {false, false};
+ while (!Params.empty()) {
+ StringRef ParamName;
+ std::tie(ParamName, Params) = Params.split(';');
+ if (ParamName == "drop-deref")
+ Result.first = true;
+ else if (ParamName == "drop-array-bounds")
+ Result.second = true;
+ else
+ return make_error<StringError>(
+ formatv("invalid DropUnnecessaryAssumes option '{0}'", ParamName)
+ .str(),
+ inconvertibleErrorCode());
+ }
+ return Result;
}
Expected<bool> parseLoopExtractorPassOptions(StringRef Params) {
diff --git a/llvm/lib/Passes/PassBuilderPipelines.cpp b/llvm/lib/Passes/PassBuilderPipelines.cpp
index 6b8f3c8806c86..177aa8d9b84e1 100644
--- a/llvm/lib/Passes/PassBuilderPipelines.cpp
+++ b/llvm/lib/Passes/PassBuilderPipelines.cpp
@@ -1345,6 +1345,13 @@ PassBuilder::buildModuleSimplificationPipeline(OptimizationLevel Level,
void PassBuilder::addVectorPasses(OptimizationLevel Level,
FunctionPassManager &FPM,
ThinOrFullLTOPhase LTOPhase) {
+ // Drop array bounds assumes before vectorization to prevent IR bloat from
+ // vectorized assumes and avoid negatively impacting cost models in later
+ // passes like LSR. These assumes are marked with "llvm.array.bounds" metadata
+ // by frontends like Flang and Clang.
+ FPM.addPass(DropUnnecessaryAssumesPass(/*DropDereferenceable=*/false,
+ /*DropArrayBounds=*/true));
+
FPM.addPass(LoopVectorizePass(
LoopVectorizeOptions(!PTO.LoopInterleaving, !PTO.LoopVectorization)));
diff --git a/llvm/lib/Passes/PassRegistry.def b/llvm/lib/Passes/PassRegistry.def
index 64331e04c155b..676e635e24a3c 100644
--- a/llvm/lib/Passes/PassRegistry.def
+++ b/llvm/lib/Passes/PassRegistry.def
@@ -589,8 +589,10 @@ FUNCTION_PASS_WITH_PARAMS(
parseEarlyCSEPassOptions, "memssa")
FUNCTION_PASS_WITH_PARAMS(
"drop-unnecessary-assumes", "DropUnnecessaryAssumesPass",
- [](bool DropDereferenceable) { return DropUnnecessaryAssumesPass(DropDereferenceable); },
- parseDropUnnecessaryAssumesPassOptions, "drop-deref")
+ [](std::pair<bool, bool> Options) {
+ return DropUnnecessaryAssumesPass(Options.first, Options.second);
+ },
+ parseDropUnnecessaryAssumesPassOptions, "drop-deref;drop-array-bounds")
FUNCTION_PASS_WITH_PARAMS(
"ee-instrument", "EntryExitInstrumenterPass",
[](bool PostInlining) { return EntryExitInstrumenterPass(PostInlining); },
diff --git a/llvm/lib/Transforms/Scalar/DropUnnecessaryAssumes.cpp b/llvm/lib/Transforms/Scalar/DropUnnecessaryAssumes.cpp
index f1192db7538ac..d477ae4dcd870 100644
--- a/llvm/lib/Transforms/Scalar/DropUnnecessaryAssumes.cpp
+++ b/llvm/lib/Transforms/Scalar/DropUnnecessaryAssumes.cpp
@@ -72,6 +72,17 @@ DropUnnecessaryAssumesPass::run(Function &F, FunctionAnalysisManager &FAM) {
if (!Assume)
continue;
+ // When DropArrayBounds is set, drop assumes with "llvm.array.bounds"
+ // metadata. These are array bounds assumes from Fortran/C/C++ that should
+ // be dropped before vectorization to prevent IR bloat.
+ if (DropArrayBounds && Assume->getMetadata("llvm.array.bounds")) {
+ Value *Cond = Assume->getArgOperand(0);
+ Assume->eraseFromParent();
+ RecursivelyDeleteTriviallyDeadInstructions(Cond);
+ Changed = true;
+ continue;
+ }
+
if (Assume->hasOperandBundles()) {
// Handle operand bundle assumptions.
SmallVector<WeakTrackingVH> DeadBundleArgs;
diff --git a/llvm/test/Other/new-pm-defaults.ll b/llvm/test/Other/new-pm-defaults.ll
index cbc8680fba706..7536cbb49ab81 100644
--- a/llvm/test/Other/new-pm-defaults.ll
+++ b/llvm/test/Other/new-pm-defaults.ll
@@ -247,6 +247,7 @@
; CHECK-O-NEXT: Running pass: LoopDistributePass
; CHECK-O-NEXT: Running analysis: LoopAccessAnalysis on foo
; CHECK-O-NEXT: Running pass: InjectTLIMappings
+; CHECK-O-NEXT: Running pass: DropUnnecessaryAssumesPass
; CHECK-O-NEXT: Running pass: LoopVectorizePass
; CHECK-DEFAULT-NEXT: Running pass: DropUnnecessaryAssumesPass
; CHECK-O-NEXT: Running pass: InferAlignmentPass
diff --git a/llvm/test/Other/new-pm-lto-defaults.ll b/llvm/test/Other/new-pm-lto-defaults.ll
index 14f189194d0e3..086f32ae3c3b5 100644
--- a/llvm/test/Other/new-pm-lto-defaults.ll
+++ b/llvm/test/Other/new-pm-lto-defaults.ll
@@ -126,6 +126,7 @@
; CHECK-O23-NEXT: Running pass: LoopFullUnrollPass on loop
; CHECK-O23-NEXT: Running pass: LoopDistributePass on foo
; CHECK-O23-NEXT: Running analysis: LoopAccessAnalysis on foo
+; CHECK-O23-NEXT: Running pass: DropUnnecessaryAssumesPass on foo
; CHECK-O23-NEXT: Running pass: LoopVectorizePass on foo
; CHECK-O23-NEXT: Running analysis: DemandedBitsAnalysis on foo
; CHECK-O23-NEXT: Running pass: DropUnnecessaryAssumesPass on foo
diff --git a/llvm/test/Other/new-pm-thinlto-postlink-defaults.ll b/llvm/test/Other/new-pm-thinlto-postlink-defaults.ll
index df712ab7846f8..ef217c9c1758a 100644
--- a/llvm/test/Other/new-pm-thinlto-postlink-defaults.ll
+++ b/llvm/test/Other/new-pm-thinlto-postlink-defaults.ll
@@ -174,6 +174,7 @@
; CHECK-POSTLINK-O-NEXT: Running pass: LoopDistributePass
; CHECK-POSTLINK-O-NEXT: Running analysis: LoopAccessAnalysis on foo
; CHECK-POSTLINK-O-NEXT: Running pass: InjectTLIMappings
+; CHECK-POSTLINK-O-NEXT: Running pass: DropUnnecessaryAssumesPass
; CHECK-POSTLINK-O-NEXT: Running pass: LoopVectorizePass
; CHECK-POSTLINK-O-NEXT: Running pass: DropUnnecessaryAssumesPass
; CHECK-POSTLINK-O-NEXT: Running pass: InferAlignmentPass
diff --git a/llvm/test/Other/new-pm-thinlto-postlink-pgo-defaults.ll b/llvm/test/Other/new-pm-thinlto-postlink-pgo-defaults.ll
index f098951e1403d..9af580ed990c3 100644
--- a/llvm/test/Other/new-pm-thinlto-postlink-pgo-defaults.ll
+++ b/llvm/test/Other/new-pm-thinlto-postlink-pgo-defaults.ll
@@ -159,6 +159,7 @@
; CHECK-O-NEXT: Running pass: LoopDistributePass
; CHECK-O-NEXT: Running analysis: LoopAccessAnalysis on foo
; CHECK-O-NEXT: Running pass: InjectTLIMappings
+; CHECK-O-NEXT: Running pass: DropUnnecessaryAssumesPass
; CHECK-O-NEXT: Running pass: LoopVectorizePass
; CHECK-O-NEXT: Running pass: DropUnnecessaryAssumesPass
; CHECK-O-NEXT: Running pass: InferAlignmentPass
diff --git a/llvm/test/Other/new-pm-thinlto-postlink-samplepgo-defaults.ll b/llvm/test/Other/new-pm-thinlto-postlink-samplepgo-defaults.ll
index 702920e5a6dbf..22dbcb2f675e7 100644
--- a/llvm/test/Other/new-pm-thinlto-postlink-samplepgo-defaults.ll
+++ b/llvm/test/Other/new-pm-thinlto-postlink-samplepgo-defaults.ll
@@ -166,6 +166,7 @@
; CHECK-O-NEXT: Running pass: LoopDistributePass
; CHECK-O-NEXT: Running analysis: LoopAccessAnalysis
; CHECK-O-NEXT: Running pass: InjectTLIMappings
+; CHECK-O-NEXT: Running pass: DropUnnecessaryAssumesPass
; CHECK-O-NEXT: Running pass: LoopVectorizePass
; CHECK-O-NEXT: Running pass: DropUnnecessaryAssumesPass
; CHECK-O-NEXT: Running pass: InferAlignmentPass
diff --git a/llvm/test/Transforms/LoopInterchange/position-in-pipeline.ll b/llvm/test/Transforms/LoopInterchange/position-in-pipeline.ll
index d0b6447d92fe7..a6aedcad4c365 100644
--- a/llvm/test/Transforms/LoopInterchange/position-in-pipeline.ll
+++ b/llvm/test/Transforms/LoopInterchange/position-in-pipeline.ll
@@ -15,6 +15,7 @@
; CHECK-NEXT: Running pass: LoopInterchangePass
; CHECK-NEXT: Running pass: LoopDistributePass
; CHECK-NEXT: Running pass: InjectTLIMappings
+; CHECK-NEXT: Running pass: DropUnnecessaryAssumesPass
; CHECK-NEXT: Running pass: LoopVectorizePass
More information about the llvm-commits
mailing list