[llvm] [DropUnnecessaryAssumes] Add support for operand bundles (PR #160311)
Nikita Popov via llvm-commits
llvm-commits at lists.llvm.org
Wed Sep 24 05:23:43 PDT 2025
https://github.com/nikic updated https://github.com/llvm/llvm-project/pull/160311
>From d5dce36cae15040f4f8a9263db30fe58f5f147a7 Mon Sep 17 00:00:00 2001
From: Nikita Popov <npopov at redhat.com>
Date: Tue, 23 Sep 2025 13:04:47 +0200
Subject: [PATCH 1/7] [DropUnnecessaryAssumes] Add support for operand bundles
This extends the DropUnnecessaryAssumes pass to also handle
operand bundle assumes. For this purpose, export the affected
value analysis for operand bundles from AssumptionCache.
If the bundle only affects ephemeral values, drop it. If all
bundles on an assume are dropped, drop the whole assume.
---
llvm/include/llvm/Analysis/AssumptionCache.h | 6 ++
llvm/lib/Analysis/AssumptionCache.cpp | 31 ++++++----
.../Scalar/DropUnnecessaryAssumes.cpp | 56 ++++++++++++++++---
.../DropUnnecessaryAssumes/basic.ll | 47 ++++++++++++++--
4 files changed, 115 insertions(+), 25 deletions(-)
diff --git a/llvm/include/llvm/Analysis/AssumptionCache.h b/llvm/include/llvm/Analysis/AssumptionCache.h
index be33be3bf2e87..5656729d20366 100644
--- a/llvm/include/llvm/Analysis/AssumptionCache.h
+++ b/llvm/include/llvm/Analysis/AssumptionCache.h
@@ -28,6 +28,7 @@
namespace llvm {
class AssumeInst;
+struct OperandBundleUse;
class Function;
class raw_ostream;
class TargetTransformInfo;
@@ -165,6 +166,11 @@ class AssumptionCache {
return AVI->second;
}
+
+ /// Determine which values are affected by this assume operand bundle.
+ static void
+ findValuesAffectedByOperandBundle(OperandBundleUse Bundle,
+ function_ref<void(Value *)> InsertAffected);
};
/// A function analysis which provides an \c AssumptionCache.
diff --git a/llvm/lib/Analysis/AssumptionCache.cpp b/llvm/lib/Analysis/AssumptionCache.cpp
index 45ff9161db97c..d115aff7ea685 100644
--- a/llvm/lib/Analysis/AssumptionCache.cpp
+++ b/llvm/lib/Analysis/AssumptionCache.cpp
@@ -53,6 +53,22 @@ AssumptionCache::getOrInsertAffectedValues(Value *V) {
return AffectedValues[AffectedValueCallbackVH(V, this)];
}
+void AssumptionCache::findValuesAffectedByOperandBundle(
+ OperandBundleUse Bundle, function_ref<void(Value *)> InsertAffected) {
+ auto AddAffectedVal = [&](Value *V) {
+ if (isa<Argument>(V) || isa<GlobalValue>(V) || isa<Instruction>(V))
+ InsertAffected(V);
+ };
+
+ if (Bundle.getTagName() == "separate_storage") {
+ assert(Bundle.Inputs.size() == 2 && "separate_storage must have two args");
+ AddAffectedVal(getUnderlyingObject(Bundle.Inputs[0]));
+ AddAffectedVal(getUnderlyingObject(Bundle.Inputs[1]));
+ } else if (Bundle.Inputs.size() > ABA_WasOn &&
+ Bundle.getTagName() != IgnoreBundleTag)
+ AddAffectedVal(Bundle.Inputs[ABA_WasOn]);
+}
+
static void
findAffectedValues(CallBase *CI, TargetTransformInfo *TTI,
SmallVectorImpl<AssumptionCache::ResultElem> &Affected) {
@@ -69,17 +85,10 @@ findAffectedValues(CallBase *CI, TargetTransformInfo *TTI,
}
};
- for (unsigned Idx = 0; Idx != CI->getNumOperandBundles(); Idx++) {
- OperandBundleUse Bundle = CI->getOperandBundleAt(Idx);
- if (Bundle.getTagName() == "separate_storage") {
- assert(Bundle.Inputs.size() == 2 &&
- "separate_storage must have two args");
- AddAffectedVal(getUnderlyingObject(Bundle.Inputs[0]), Idx);
- AddAffectedVal(getUnderlyingObject(Bundle.Inputs[1]), Idx);
- } else if (Bundle.Inputs.size() > ABA_WasOn &&
- Bundle.getTagName() != IgnoreBundleTag)
- AddAffectedVal(Bundle.Inputs[ABA_WasOn], Idx);
- }
+ for (unsigned Idx = 0; Idx != CI->getNumOperandBundles(); Idx++)
+ AssumptionCache::findValuesAffectedByOperandBundle(
+ CI->getOperandBundleAt(Idx),
+ [&](Value *V) { Affected.push_back({V, Idx}); });
Value *Cond = CI->getArgOperand(0);
findValuesAffectedByCondition(Cond, /*IsAssume=*/true, InsertAffected);
diff --git a/llvm/lib/Transforms/Scalar/DropUnnecessaryAssumes.cpp b/llvm/lib/Transforms/Scalar/DropUnnecessaryAssumes.cpp
index 8b3bd50a7e53f..f62d9162b4ff7 100644
--- a/llvm/lib/Transforms/Scalar/DropUnnecessaryAssumes.cpp
+++ b/llvm/lib/Transforms/Scalar/DropUnnecessaryAssumes.cpp
@@ -16,6 +16,17 @@
using namespace llvm;
using namespace llvm::PatternMatch;
+static bool
+affectedValuesAreEphemeral(const SmallPtrSetImpl<Value *> &Affected) {
+ // If all the affected uses have only one use (part of the assume), then
+ // the assume does not provide useful information. Note that additional
+ // users may appear as a result of inlining and CSE, so we should only
+ // make this assumption late in the optimization pipeline.
+ // TODO: Handle dead cyclic usages.
+ // TODO: Handle multiple dead assumes on the same value.
+ return all_of(Affected, match_fn(m_OneUse(m_Value())));
+}
+
PreservedAnalyses
DropUnnecessaryAssumesPass::run(Function &F, FunctionAnalysisManager &FAM) {
AssumptionCache &AC = FAM.getResult<AssumptionAnalysis>(F);
@@ -26,8 +37,41 @@ DropUnnecessaryAssumesPass::run(Function &F, FunctionAnalysisManager &FAM) {
if (!Assume)
continue;
- // TODO: Handle assumes with operand bundles.
- if (Assume->hasOperandBundles())
+ SmallVector<WeakTrackingVH> DeadBundleArgs;
+ SmallVector<OperandBundleDef> KeptBundles;
+ unsigned NumBundles = Assume->getNumOperandBundles();
+ for (unsigned I = 0; I != NumBundles; ++I) {
+ // Handle operand bundle assumptions.
+ OperandBundleUse Bundle = Assume->getOperandBundleAt(I);
+ SmallPtrSet<Value *, 8> Affected;
+ AssumptionCache::findValuesAffectedByOperandBundle(
+ Bundle, [&](Value *A) { Affected.insert(A); });
+
+ if (affectedValuesAreEphemeral(Affected))
+ append_range(DeadBundleArgs, Bundle.Inputs);
+ else
+ KeptBundles.emplace_back(Bundle);
+ }
+
+ if (KeptBundles.size() != NumBundles) {
+ if (KeptBundles.size() == 0) {
+ // All operand bundles are dead, remove the whole assume.
+ Assume->eraseFromParent();
+ } else {
+ // Otherwise only drop the dead operand bundles.
+ CallBase *NewAssume =
+ CallBase::Create(Assume, KeptBundles, Assume->getIterator());
+ AC.registerAssumption(cast<AssumeInst>(NewAssume));
+ Assume->eraseFromParent();
+ }
+
+ RecursivelyDeleteTriviallyDeadInstructionsPermissive(DeadBundleArgs);
+ Changed = true;
+ continue;
+ }
+
+ // Ignore condition on assumes with operand bundles.
+ if (NumBundles != 0)
continue;
Value *Cond = Assume->getArgOperand(0);
@@ -39,13 +83,7 @@ DropUnnecessaryAssumesPass::run(Function &F, FunctionAnalysisManager &FAM) {
findValuesAffectedByCondition(Cond, /*IsAssume=*/true,
[&](Value *A) { Affected.insert(A); });
- // If all the affected uses have only one use (part of the assume), then
- // the assume does not provide useful information. Note that additional
- // users may appear as a result of inlining and CSE, so we should only
- // make this assumption late in the optimization pipeline.
- // TODO: Handle dead cyclic usages.
- // TODO: Handle multiple dead assumes on the same value.
- if (!all_of(Affected, match_fn(m_OneUse(m_Value()))))
+ if (!affectedValuesAreEphemeral(Affected))
continue;
Assume->eraseFromParent();
diff --git a/llvm/test/Transforms/DropUnnecessaryAssumes/basic.ll b/llvm/test/Transforms/DropUnnecessaryAssumes/basic.ll
index ea0d5d3fca8ff..f984b3db88337 100644
--- a/llvm/test/Transforms/DropUnnecessaryAssumes/basic.ll
+++ b/llvm/test/Transforms/DropUnnecessaryAssumes/basic.ll
@@ -63,18 +63,17 @@ define i32 @multiple_live2(i32 %x, i32 %y) {
ret i32 %y
}
-define void @operand_bundle_dead(ptr %x) {
-; CHECK-LABEL: define void @operand_bundle_dead(
+define void @operand_bundle_one_dead(ptr %x) {
+; CHECK-LABEL: define void @operand_bundle_one_dead(
; CHECK-SAME: ptr [[X:%.*]]) {
-; CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(ptr [[X]], i64 8) ]
; CHECK-NEXT: ret void
;
call void @llvm.assume(i1 true) ["align"(ptr %x, i64 8)]
ret void
}
-define ptr @operand_bundle_live(ptr %x) {
-; CHECK-LABEL: define ptr @operand_bundle_live(
+define ptr @operand_bundle_one_live(ptr %x) {
+; CHECK-LABEL: define ptr @operand_bundle_one_live(
; CHECK-SAME: ptr [[X:%.*]]) {
; CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(ptr [[X]], i64 8) ]
; CHECK-NEXT: ret ptr [[X]]
@@ -83,6 +82,44 @@ define ptr @operand_bundle_live(ptr %x) {
ret ptr %x
}
+define void @operand_bundle_multiple_dead(ptr %x, ptr %y) {
+; CHECK-LABEL: define void @operand_bundle_multiple_dead(
+; CHECK-SAME: ptr [[X:%.*]], ptr [[Y:%.*]]) {
+; CHECK-NEXT: ret void
+;
+ call void @llvm.assume(i1 true) ["align"(ptr %x, i64 8), "align"(ptr %y, i64 8)]
+ ret void
+}
+
+define ptr @operand_bundle_one_live_one_dead(ptr %x, ptr %y) {
+; CHECK-LABEL: define ptr @operand_bundle_one_live_one_dead(
+; CHECK-SAME: ptr [[X:%.*]], ptr [[Y:%.*]]) {
+; CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(ptr [[Y]], i64 8) ]
+; CHECK-NEXT: ret ptr [[Y]]
+;
+ call void @llvm.assume(i1 true) ["align"(ptr %x, i64 8), "align"(ptr %y, i64 8)]
+ ret ptr %y
+}
+
+define i64 @operand_bundle_ignore_unaffected_operands(ptr %x, i64 %align) {
+; CHECK-LABEL: define i64 @operand_bundle_ignore_unaffected_operands(
+; CHECK-SAME: ptr [[X:%.*]], i64 [[ALIGN:%.*]]) {
+; CHECK-NEXT: ret i64 [[ALIGN]]
+;
+ call void @llvm.assume(i1 true) ["align"(ptr %x, i64 %align)]
+ ret i64 %align
+}
+
+define void @operand_bundle_remove_dead_insts(ptr %x) {
+; CHECK-LABEL: define void @operand_bundle_remove_dead_insts(
+; CHECK-SAME: ptr [[X:%.*]]) {
+; CHECK-NEXT: ret void
+;
+ %gep = getelementptr i8, ptr %x, i64 8
+ call void @llvm.assume(i1 true) ["align"(ptr %gep, i64 8)]
+ ret void
+}
+
define void @type_test(ptr %x) {
; CHECK-LABEL: define void @type_test(
; CHECK-SAME: ptr [[X:%.*]]) {
>From a8630b871e598683afd834f3f5f07f6d11133c51 Mon Sep 17 00:00:00 2001
From: Nikita Popov <npopov at redhat.com>
Date: Wed, 24 Sep 2025 12:49:35 +0200
Subject: [PATCH 2/7] make it clear bundle / condition are mutually exclusive
---
.../Scalar/DropUnnecessaryAssumes.cpp | 58 +++++++++----------
1 file changed, 28 insertions(+), 30 deletions(-)
diff --git a/llvm/lib/Transforms/Scalar/DropUnnecessaryAssumes.cpp b/llvm/lib/Transforms/Scalar/DropUnnecessaryAssumes.cpp
index f62d9162b4ff7..975c5b0eabc52 100644
--- a/llvm/lib/Transforms/Scalar/DropUnnecessaryAssumes.cpp
+++ b/llvm/lib/Transforms/Scalar/DropUnnecessaryAssumes.cpp
@@ -37,42 +37,40 @@ DropUnnecessaryAssumesPass::run(Function &F, FunctionAnalysisManager &FAM) {
if (!Assume)
continue;
- SmallVector<WeakTrackingVH> DeadBundleArgs;
- SmallVector<OperandBundleDef> KeptBundles;
- unsigned NumBundles = Assume->getNumOperandBundles();
- for (unsigned I = 0; I != NumBundles; ++I) {
+ if (Assume->hasOperandBundles()) {
// Handle operand bundle assumptions.
- OperandBundleUse Bundle = Assume->getOperandBundleAt(I);
- SmallPtrSet<Value *, 8> Affected;
- AssumptionCache::findValuesAffectedByOperandBundle(
- Bundle, [&](Value *A) { Affected.insert(A); });
+ SmallVector<WeakTrackingVH> DeadBundleArgs;
+ SmallVector<OperandBundleDef> KeptBundles;
+ unsigned NumBundles = Assume->getNumOperandBundles();
+ for (unsigned I = 0; I != NumBundles; ++I) {
+ OperandBundleUse Bundle = Assume->getOperandBundleAt(I);
+ SmallPtrSet<Value *, 8> Affected;
+ AssumptionCache::findValuesAffectedByOperandBundle(
+ Bundle, [&](Value *A) { Affected.insert(A); });
- if (affectedValuesAreEphemeral(Affected))
- append_range(DeadBundleArgs, Bundle.Inputs);
- else
- KeptBundles.emplace_back(Bundle);
- }
-
- if (KeptBundles.size() != NumBundles) {
- if (KeptBundles.size() == 0) {
- // All operand bundles are dead, remove the whole assume.
- Assume->eraseFromParent();
- } else {
- // Otherwise only drop the dead operand bundles.
- CallBase *NewAssume =
- CallBase::Create(Assume, KeptBundles, Assume->getIterator());
- AC.registerAssumption(cast<AssumeInst>(NewAssume));
- Assume->eraseFromParent();
+ if (affectedValuesAreEphemeral(Affected))
+ append_range(DeadBundleArgs, Bundle.Inputs);
+ else
+ KeptBundles.emplace_back(Bundle);
}
- RecursivelyDeleteTriviallyDeadInstructionsPermissive(DeadBundleArgs);
- Changed = true;
- continue;
- }
+ if (KeptBundles.size() != NumBundles) {
+ if (KeptBundles.size() == 0) {
+ // All operand bundles are dead, remove the whole assume.
+ Assume->eraseFromParent();
+ } else {
+ // Otherwise only drop the dead operand bundles.
+ CallBase *NewAssume =
+ CallBase::Create(Assume, KeptBundles, Assume->getIterator());
+ AC.registerAssumption(cast<AssumeInst>(NewAssume));
+ Assume->eraseFromParent();
+ }
- // Ignore condition on assumes with operand bundles.
- if (NumBundles != 0)
+ RecursivelyDeleteTriviallyDeadInstructionsPermissive(DeadBundleArgs);
+ Changed = true;
+ }
continue;
+ }
Value *Cond = Assume->getArgOperand(0);
// Don't drop type tests, which have special semantics.
>From 175e50fa3e71b73f18e6c18d4609644de4e002f2 Mon Sep 17 00:00:00 2001
From: Nikita Popov <npopov at redhat.com>
Date: Wed, 24 Sep 2025 12:55:13 +0200
Subject: [PATCH 3/7] Keep bundles without arguments
---
.../Scalar/DropUnnecessaryAssumes.cpp | 19 ++++++++++++++-----
.../DropUnnecessaryAssumes/basic.ll | 9 +++++++++
2 files changed, 23 insertions(+), 5 deletions(-)
diff --git a/llvm/lib/Transforms/Scalar/DropUnnecessaryAssumes.cpp b/llvm/lib/Transforms/Scalar/DropUnnecessaryAssumes.cpp
index 975c5b0eabc52..7cffea390ba0c 100644
--- a/llvm/lib/Transforms/Scalar/DropUnnecessaryAssumes.cpp
+++ b/llvm/lib/Transforms/Scalar/DropUnnecessaryAssumes.cpp
@@ -43,12 +43,21 @@ DropUnnecessaryAssumesPass::run(Function &F, FunctionAnalysisManager &FAM) {
SmallVector<OperandBundleDef> KeptBundles;
unsigned NumBundles = Assume->getNumOperandBundles();
for (unsigned I = 0; I != NumBundles; ++I) {
- OperandBundleUse Bundle = Assume->getOperandBundleAt(I);
- SmallPtrSet<Value *, 8> Affected;
- AssumptionCache::findValuesAffectedByOperandBundle(
- Bundle, [&](Value *A) { Affected.insert(A); });
+ auto IsDead = [](OperandBundleUse Bundle) {
+ // Bundles without arguments do not affect any specific values.
+ // Always keep them for now.
+ if (Bundle.Inputs.empty())
+ return false;
+
+ SmallPtrSet<Value *, 8> Affected;
+ AssumptionCache::findValuesAffectedByOperandBundle(
+ Bundle, [&](Value *A) { Affected.insert(A); });
- if (affectedValuesAreEphemeral(Affected))
+ return affectedValuesAreEphemeral(Affected);
+ };
+
+ OperandBundleUse Bundle = Assume->getOperandBundleAt(I);
+ if (IsDead(Bundle))
append_range(DeadBundleArgs, Bundle.Inputs);
else
KeptBundles.emplace_back(Bundle);
diff --git a/llvm/test/Transforms/DropUnnecessaryAssumes/basic.ll b/llvm/test/Transforms/DropUnnecessaryAssumes/basic.ll
index f984b3db88337..4575cbac22873 100644
--- a/llvm/test/Transforms/DropUnnecessaryAssumes/basic.ll
+++ b/llvm/test/Transforms/DropUnnecessaryAssumes/basic.ll
@@ -120,6 +120,15 @@ define void @operand_bundle_remove_dead_insts(ptr %x) {
ret void
}
+define void @operand_bundle_no_args() {
+; CHECK-LABEL: define void @operand_bundle_no_args() {
+; CHECK-NEXT: call void @llvm.assume(i1 true) [ "cold"() ]
+; CHECK-NEXT: ret void
+;
+ call void @llvm.assume(i1 true) ["cold"()]
+ ret void
+}
+
define void @type_test(ptr %x) {
; CHECK-LABEL: define void @type_test(
; CHECK-SAME: ptr [[X:%.*]]) {
>From 613e5621a494059666b6522757c171c22cd332dc Mon Sep 17 00:00:00 2001
From: Nikita Popov <npopov at redhat.com>
Date: Wed, 24 Sep 2025 12:59:58 +0200
Subject: [PATCH 4/7] Drop ignore operand bundles
---
llvm/lib/Transforms/Scalar/DropUnnecessaryAssumes.cpp | 4 ++++
llvm/test/Transforms/DropUnnecessaryAssumes/basic.ll | 11 +++++++++++
2 files changed, 15 insertions(+)
diff --git a/llvm/lib/Transforms/Scalar/DropUnnecessaryAssumes.cpp b/llvm/lib/Transforms/Scalar/DropUnnecessaryAssumes.cpp
index 7cffea390ba0c..28e81ad5b685e 100644
--- a/llvm/lib/Transforms/Scalar/DropUnnecessaryAssumes.cpp
+++ b/llvm/lib/Transforms/Scalar/DropUnnecessaryAssumes.cpp
@@ -44,6 +44,10 @@ DropUnnecessaryAssumesPass::run(Function &F, FunctionAnalysisManager &FAM) {
unsigned NumBundles = Assume->getNumOperandBundles();
for (unsigned I = 0; I != NumBundles; ++I) {
auto IsDead = [](OperandBundleUse Bundle) {
+ // "ignore" operand bundles are always dead.
+ if (Bundle.getTagName() == "ignore")
+ return true;
+
// Bundles without arguments do not affect any specific values.
// Always keep them for now.
if (Bundle.Inputs.empty())
diff --git a/llvm/test/Transforms/DropUnnecessaryAssumes/basic.ll b/llvm/test/Transforms/DropUnnecessaryAssumes/basic.ll
index 4575cbac22873..da6b78c3e168e 100644
--- a/llvm/test/Transforms/DropUnnecessaryAssumes/basic.ll
+++ b/llvm/test/Transforms/DropUnnecessaryAssumes/basic.ll
@@ -129,6 +129,17 @@ define void @operand_bundle_no_args() {
ret void
}
+; Can always drop ignore bundles, regardless of uses.
+define ptr @operand_bundle_ignore(ptr %x) {
+; CHECK-LABEL: define ptr @operand_bundle_ignore(
+; CHECK-SAME: ptr [[X:%.*]]) {
+; CHECK-NEXT: call void @llvm.assume(i1 true) [ "nonnull"(ptr [[X]]) ]
+; CHECK-NEXT: ret ptr [[X]]
+;
+ call void @llvm.assume(i1 true) ["ignore"(), "ignore"(ptr %x), "nonnull"(ptr %x)]
+ ret ptr %x
+}
+
define void @type_test(ptr %x) {
; CHECK-LABEL: define void @type_test(
; CHECK-SAME: ptr [[X:%.*]]) {
>From d6fce5e6d7e4c76123c6eb5f2d556c645a9f864b Mon Sep 17 00:00:00 2001
From: Nikita Popov <npopov at redhat.com>
Date: Wed, 24 Sep 2025 14:08:53 +0200
Subject: [PATCH 5/7] Add tests for separate_storage
---
.../DropUnnecessaryAssumes/basic.ll | 29 +++++++++++++++++++
1 file changed, 29 insertions(+)
diff --git a/llvm/test/Transforms/DropUnnecessaryAssumes/basic.ll b/llvm/test/Transforms/DropUnnecessaryAssumes/basic.ll
index da6b78c3e168e..e2a9b4eea2c7d 100644
--- a/llvm/test/Transforms/DropUnnecessaryAssumes/basic.ll
+++ b/llvm/test/Transforms/DropUnnecessaryAssumes/basic.ll
@@ -140,6 +140,35 @@ define ptr @operand_bundle_ignore(ptr %x) {
ret ptr %x
}
+define void @operand_bundle_separate_storage_both_dead(ptr %x, ptr %y) {
+; CHECK-LABEL: define void @operand_bundle_separate_storage_both_dead(
+; CHECK-SAME: ptr [[X:%.*]], ptr [[Y:%.*]]) {
+; CHECK-NEXT: ret void
+;
+ call void @llvm.assume(i1 true) ["separate_storage"(ptr %x, ptr %y)]
+ ret void
+}
+
+define ptr @operand_bundle_separate_storage_one_live1(ptr %x, ptr %y) {
+; CHECK-LABEL: define ptr @operand_bundle_separate_storage_one_live1(
+; CHECK-SAME: ptr [[X:%.*]], ptr [[Y:%.*]]) {
+; CHECK-NEXT: call void @llvm.assume(i1 true) [ "separate_storage"(ptr [[X]], ptr [[Y]]) ]
+; CHECK-NEXT: ret ptr [[Y]]
+;
+ call void @llvm.assume(i1 true) ["separate_storage"(ptr %x, ptr %y)]
+ ret ptr %y
+}
+
+define ptr @operand_bundle_separate_storage_one_live2(ptr %x, ptr %y) {
+; CHECK-LABEL: define ptr @operand_bundle_separate_storage_one_live2(
+; CHECK-SAME: ptr [[X:%.*]], ptr [[Y:%.*]]) {
+; CHECK-NEXT: call void @llvm.assume(i1 true) [ "separate_storage"(ptr [[X]], ptr [[Y]]) ]
+; CHECK-NEXT: ret ptr [[X]]
+;
+ call void @llvm.assume(i1 true) ["separate_storage"(ptr %x, ptr %y)]
+ ret ptr %x
+}
+
define void @type_test(ptr %x) {
; CHECK-LABEL: define void @type_test(
; CHECK-SAME: ptr [[X:%.*]]) {
>From 9e8670c0912719ccfbbfe74ba2587174fef97851 Mon Sep 17 00:00:00 2001
From: Nikita Popov <npopov at redhat.com>
Date: Wed, 24 Sep 2025 14:11:54 +0200
Subject: [PATCH 6/7] Fix nits
---
llvm/lib/Analysis/AssumptionCache.cpp | 2 +-
llvm/lib/Transforms/Scalar/DropUnnecessaryAssumes.cpp | 11 +++++------
2 files changed, 6 insertions(+), 7 deletions(-)
diff --git a/llvm/lib/Analysis/AssumptionCache.cpp b/llvm/lib/Analysis/AssumptionCache.cpp
index d115aff7ea685..61b7b3fa9e2c4 100644
--- a/llvm/lib/Analysis/AssumptionCache.cpp
+++ b/llvm/lib/Analysis/AssumptionCache.cpp
@@ -56,7 +56,7 @@ AssumptionCache::getOrInsertAffectedValues(Value *V) {
void AssumptionCache::findValuesAffectedByOperandBundle(
OperandBundleUse Bundle, function_ref<void(Value *)> InsertAffected) {
auto AddAffectedVal = [&](Value *V) {
- if (isa<Argument>(V) || isa<GlobalValue>(V) || isa<Instruction>(V))
+ if (isa<Argument, GlobalValue, Instruction>(V))
InsertAffected(V);
};
diff --git a/llvm/lib/Transforms/Scalar/DropUnnecessaryAssumes.cpp b/llvm/lib/Transforms/Scalar/DropUnnecessaryAssumes.cpp
index 28e81ad5b685e..0e7c97d202477 100644
--- a/llvm/lib/Transforms/Scalar/DropUnnecessaryAssumes.cpp
+++ b/llvm/lib/Transforms/Scalar/DropUnnecessaryAssumes.cpp
@@ -16,8 +16,7 @@
using namespace llvm;
using namespace llvm::PatternMatch;
-static bool
-affectedValuesAreEphemeral(const SmallPtrSetImpl<Value *> &Affected) {
+static bool affectedValuesAreEphemeral(ArrayRef<Value *> Affected) {
// If all the affected uses have only one use (part of the assume), then
// the assume does not provide useful information. Note that additional
// users may appear as a result of inlining and CSE, so we should only
@@ -53,9 +52,9 @@ DropUnnecessaryAssumesPass::run(Function &F, FunctionAnalysisManager &FAM) {
if (Bundle.Inputs.empty())
return false;
- SmallPtrSet<Value *, 8> Affected;
+ SmallVector<Value *> Affected;
AssumptionCache::findValuesAffectedByOperandBundle(
- Bundle, [&](Value *A) { Affected.insert(A); });
+ Bundle, [&](Value *A) { Affected.push_back(A); });
return affectedValuesAreEphemeral(Affected);
};
@@ -90,9 +89,9 @@ DropUnnecessaryAssumesPass::run(Function &F, FunctionAnalysisManager &FAM) {
if (match(Cond, m_Intrinsic<Intrinsic::type_test>()))
continue;
- SmallPtrSet<Value *, 8> Affected;
+ SmallVector<Value *> Affected;
findValuesAffectedByCondition(Cond, /*IsAssume=*/true,
- [&](Value *A) { Affected.insert(A); });
+ [&](Value *A) { Affected.push_back(A); });
if (!affectedValuesAreEphemeral(Affected))
continue;
>From a1a3da5443a5839ae8798a618d8d81a4d6f86795 Mon Sep 17 00:00:00 2001
From: Nikita Popov <github at npopov.com>
Date: Wed, 24 Sep 2025 14:23:32 +0200
Subject: [PATCH 7/7] Apply suggestion
Co-authored-by: Ramkumar Ramachandra <r at artagnon.com>
---
llvm/lib/Transforms/Scalar/DropUnnecessaryAssumes.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/llvm/lib/Transforms/Scalar/DropUnnecessaryAssumes.cpp b/llvm/lib/Transforms/Scalar/DropUnnecessaryAssumes.cpp
index 0e7c97d202477..c215228b480d2 100644
--- a/llvm/lib/Transforms/Scalar/DropUnnecessaryAssumes.cpp
+++ b/llvm/lib/Transforms/Scalar/DropUnnecessaryAssumes.cpp
@@ -67,7 +67,7 @@ DropUnnecessaryAssumesPass::run(Function &F, FunctionAnalysisManager &FAM) {
}
if (KeptBundles.size() != NumBundles) {
- if (KeptBundles.size() == 0) {
+ if (KeptBundles.empty()) {
// All operand bundles are dead, remove the whole assume.
Assume->eraseFromParent();
} else {
More information about the llvm-commits
mailing list