[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