[llvm] [InstCombine] Drop the correct assume when working on assume bundles (PR #198404)
Nikolas Klauser via llvm-commits
llvm-commits at lists.llvm.org
Thu May 28 03:52:13 PDT 2026
https://github.com/philnik777 updated https://github.com/llvm/llvm-project/pull/198404
>From 0e3185b5319dd7159bd440713c3f3b7d0e387834 Mon Sep 17 00:00:00 2001
From: Nikolas Klauser <nikolasklauser at berlin.de>
Date: Mon, 18 May 2026 23:18:56 +0200
Subject: [PATCH 1/2] [InstCombine] Drop the correct assume when working on
assume bundles
---
llvm/include/llvm/IR/InstrTypes.h | 4 ++++
llvm/lib/IR/Instructions.cpp | 16 ++++++++++++++++
.../Transforms/InstCombine/InstCombineCalls.cpp | 8 ++++----
llvm/test/Transforms/InstCombine/assume.ll | 11 +++++++++++
4 files changed, 35 insertions(+), 4 deletions(-)
diff --git a/llvm/include/llvm/IR/InstrTypes.h b/llvm/include/llvm/IR/InstrTypes.h
index 61dc5ebef1b1d..7f2f0c12a7e77 100644
--- a/llvm/include/llvm/IR/InstrTypes.h
+++ b/llvm/include/llvm/IR/InstrTypes.h
@@ -1187,6 +1187,10 @@ class CallBase : public Instruction {
removeOperandBundle(CallBase *CB, uint32_t ID,
InsertPosition InsertPt = nullptr);
+ LLVM_ABI static CallBase *
+ removeOperandBundleAt(CallBase *CB, size_t Offset,
+ InsertPosition InsertPtr = nullptr);
+
/// Return the convergence control token for this call, if it exists.
Value *getConvergenceControlToken() const {
if (auto Bundle = getOperandBundle(llvm::LLVMContext::OB_convergencectrl)) {
diff --git a/llvm/lib/IR/Instructions.cpp b/llvm/lib/IR/Instructions.cpp
index 93ec59846d360..c9d9d9d8a989e 100644
--- a/llvm/lib/IR/Instructions.cpp
+++ b/llvm/lib/IR/Instructions.cpp
@@ -609,6 +609,22 @@ CallBase *CallBase::removeOperandBundle(CallBase *CB, uint32_t ID,
return CreateNew ? Create(CB, Bundles, InsertPt) : CB;
}
+CallBase *CallBase::removeOperandBundleAt(CallBase *CB, size_t Offset,
+ InsertPosition InsertPt) {
+ auto OpBundleCount = CB->getNumOperandBundles();
+ assert(Offset < OpBundleCount &&
+ "Trying to remove non-existant operand bundle");
+ SmallVector<OperandBundleDef, 1> Bundles;
+ Bundles.reserve(OpBundleCount - 1);
+ size_t I = 0;
+ for (; I != Offset; ++I)
+ Bundles.emplace_back(CB->getOperandBundleAt(I));
+ ++I;
+ for (; I != OpBundleCount; ++I)
+ Bundles.emplace_back(CB->getOperandBundleAt(I));
+ return Create(CB, Bundles, InsertPt);
+}
+
bool CallBase::hasReadingOperandBundles() const {
// Implementation note: this is a conservative implementation of operand
// bundle semantics, where *any* non-assume operand bundle (other than
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
index 2a8bf3ffecd6f..7da8eebcad1fe 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
@@ -3652,7 +3652,7 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
// Remove align 1 bundles; they don't add any useful information.
if (RK.ArgValue == 1)
- return CallBase::removeOperandBundle(II, OBU.getTagID());
+ return CallBase::removeOperandBundleAt(II, Idx);
// Don't try to remove align assumptions for pointers derived from
// arguments. We might lose information if the function gets inline and
@@ -3666,7 +3666,7 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
if ((1ULL << computeKnownBits(RK.WasOn, II).countMinTrailingZeros()) <
RK.ArgValue)
continue;
- return CallBase::removeOperandBundle(II, OBU.getTagID());
+ return CallBase::removeOperandBundleAt(II, Idx);
}
if (OBU.getTagName() == "nonnull" && OBU.Inputs.size() == 1) {
@@ -3677,7 +3677,7 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
// Drop assume if we can prove nonnull without it
if (isKnownNonZero(RK.WasOn, getSimplifyQuery().getWithInstruction(II)))
- return CallBase::removeOperandBundle(II, OBU.getTagID());
+ return CallBase::removeOperandBundleAt(II, Idx);
// Fold the assume into metadata if it's valid at the load
if (auto *LI = dyn_cast<LoadInst>(RK.WasOn);
@@ -3686,7 +3686,7 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
MDNode *MD = MDNode::get(II->getContext(), {});
LI->setMetadata(LLVMContext::MD_nonnull, MD);
LI->setMetadata(LLVMContext::MD_noundef, MD);
- return CallBase::removeOperandBundle(II, OBU.getTagID());
+ return CallBase::removeOperandBundleAt(II, Idx);
}
// TODO: apply nonnull return attributes to calls and invokes
diff --git a/llvm/test/Transforms/InstCombine/assume.ll b/llvm/test/Transforms/InstCombine/assume.ll
index c39f606382650..18571498df5a3 100644
--- a/llvm/test/Transforms/InstCombine/assume.ll
+++ b/llvm/test/Transforms/InstCombine/assume.ll
@@ -490,6 +490,17 @@ define void @redundant_nonnull3(ptr %ptr) {
ret void
}
+define void @partially_redundant(ptr %ptr, ptr %ptr2, ptr %ptr3) {
+; CHECK-LABEL: @partially_redundant(
+; CHECK-NEXT: call void @llvm.assume(i1 true) [ "nonnull"(ptr [[PTR2:%.*]]) ]
+; CHECK-NEXT: call void @llvm.assume(i1 true) [ "nonnull"(ptr [[PTR:%.*]]), "nonnull"(ptr [[PTR3:%.*]]) ]
+; CHECK-NEXT: ret void
+;
+ call void @llvm.assume(i1 true) [ "nonnull"(ptr %ptr), "nonnull"(ptr %ptr2) ]
+ call void @llvm.assume(i1 true) [ "nonnull"(ptr %ptr), "nonnull"(ptr %ptr3) ]
+ ret void
+}
+
; PR35846 - https://bugs.llvm.org/show_bug.cgi?id=35846
define i32 @assumption_conflicts_with_known_bits(i32 %a, i32 %b) {
>From a11853e741cb69964bd9fce48e3f0ca277b8b707 Mon Sep 17 00:00:00 2001
From: Nikolas Klauser <nikolasklauser at berlin.de>
Date: Thu, 28 May 2026 12:52:00 +0200
Subject: [PATCH 2/2] Address comments
---
llvm/lib/IR/Instructions.cpp | 2 +-
llvm/test/Transforms/InstCombine/assume.ll | 8 ++++++--
2 files changed, 7 insertions(+), 3 deletions(-)
diff --git a/llvm/lib/IR/Instructions.cpp b/llvm/lib/IR/Instructions.cpp
index c9d9d9d8a989e..52f1326797a77 100644
--- a/llvm/lib/IR/Instructions.cpp
+++ b/llvm/lib/IR/Instructions.cpp
@@ -614,7 +614,7 @@ CallBase *CallBase::removeOperandBundleAt(CallBase *CB, size_t Offset,
auto OpBundleCount = CB->getNumOperandBundles();
assert(Offset < OpBundleCount &&
"Trying to remove non-existant operand bundle");
- SmallVector<OperandBundleDef, 1> Bundles;
+ SmallVector<OperandBundleDef> Bundles;
Bundles.reserve(OpBundleCount - 1);
size_t I = 0;
for (; I != Offset; ++I)
diff --git a/llvm/test/Transforms/InstCombine/assume.ll b/llvm/test/Transforms/InstCombine/assume.ll
index 18571498df5a3..a154e254c138e 100644
--- a/llvm/test/Transforms/InstCombine/assume.ll
+++ b/llvm/test/Transforms/InstCombine/assume.ll
@@ -490,14 +490,18 @@ define void @redundant_nonnull3(ptr %ptr) {
ret void
}
-define void @partially_redundant(ptr %ptr, ptr %ptr2, ptr %ptr3) {
+define void @partially_redundant(ptr %ptr, ptr %ptr2, ptr %ptr3, ptr %ptr4, ptr %ptr5) {
; CHECK-LABEL: @partially_redundant(
; CHECK-NEXT: call void @llvm.assume(i1 true) [ "nonnull"(ptr [[PTR2:%.*]]) ]
-; CHECK-NEXT: call void @llvm.assume(i1 true) [ "nonnull"(ptr [[PTR:%.*]]), "nonnull"(ptr [[PTR3:%.*]]) ]
+; CHECK-NEXT: call void @llvm.assume(i1 true) [ "nonnull"(ptr [[PTR:%.*]]) ]
+; CHECK-NEXT: call void @llvm.assume(i1 true) [ "nonnull"(ptr [[PTR4:%.*]]), "nonnull"(ptr [[PTR3:%.*]]) ]
+; CHECK-NEXT: call void @llvm.assume(i1 true) [ "nonnull"(ptr [[PTR5:%.*]]) ]
; CHECK-NEXT: ret void
;
call void @llvm.assume(i1 true) [ "nonnull"(ptr %ptr), "nonnull"(ptr %ptr2) ]
call void @llvm.assume(i1 true) [ "nonnull"(ptr %ptr), "nonnull"(ptr %ptr3) ]
+ call void @llvm.assume(i1 true) [ "nonnull"(ptr %ptr4), "nonnull"(ptr %ptr5), "nonnull"(ptr %ptr3) ]
+ call void @llvm.assume(i1 true) [ "nonnull"(ptr %ptr5) ]
ret void
}
More information about the llvm-commits
mailing list