[llvm] 19250eb - [InstCombine] Drop zero size dereferenceable assumptions (#202411)

via llvm-commits llvm-commits at lists.llvm.org
Tue Jun 9 01:00:08 PDT 2026


Author: Nikolas Klauser
Date: 2026-06-09T10:00:02+02:00
New Revision: 19250eb71a32aafd540b5f9b03eea6be8121b2d2

URL: https://github.com/llvm/llvm-project/commit/19250eb71a32aafd540b5f9b03eea6be8121b2d2
DIFF: https://github.com/llvm/llvm-project/commit/19250eb71a32aafd540b5f9b03eea6be8121b2d2.diff

LOG: [InstCombine] Drop zero size dereferenceable assumptions (#202411)

Added: 
    

Modified: 
    llvm/include/llvm/IR/BundleAttributes.h
    llvm/lib/Analysis/LazyValueInfo.cpp
    llvm/lib/Analysis/ValueTracking.cpp
    llvm/lib/IR/BundleAttributes.cpp
    llvm/lib/IR/Verifier.cpp
    llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
    llvm/test/Analysis/ValueTracking/assume.ll
    llvm/test/Transforms/InstCombine/assume.ll
    llvm/test/Verifier/assume-bundles.ll

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/IR/BundleAttributes.h b/llvm/include/llvm/IR/BundleAttributes.h
index ee6e5b4bc1ef6..9b1b42607a515 100644
--- a/llvm/include/llvm/IR/BundleAttributes.h
+++ b/llvm/include/llvm/IR/BundleAttributes.h
@@ -39,6 +39,7 @@ LLVM_ABI AssumeAlignInfo getAssumeAlignInfo(OperandBundleUse);
 struct AssumeDereferenceableInfo {
   const Use &Ptr;
   const Use &Count;
+  std::optional<uint64_t> CountVal;
 };
 
 LLVM_ABI

diff  --git a/llvm/lib/Analysis/LazyValueInfo.cpp b/llvm/lib/Analysis/LazyValueInfo.cpp
index 7a56a278c5e1e..b052352b51eec 100644
--- a/llvm/lib/Analysis/LazyValueInfo.cpp
+++ b/llvm/lib/Analysis/LazyValueInfo.cpp
@@ -866,12 +866,11 @@ void LazyValueInfoImpl::intersectAssumeOrGuardBlockValueConstantRange(
         break;
 
       case BundleAttr::Dereferenceable: {
-        auto [Ptr, Count] = getAssumeDereferenceableInfo(OBU);
-        if (Ptr != Val)
+        auto [Ptr, _, Count] = getAssumeDereferenceableInfo(OBU);
+        if (Ptr != Val || !Count || *Count == 0)
           break;
-        if (auto *CI = dyn_cast<ConstantInt>(Count); CI && !CI->isZero())
-          BBLV = BBLV.intersect(ValueLatticeElement::getNot(
-              Constant::getNullValue(Val->getType())));
+        BBLV = BBLV.intersect(ValueLatticeElement::getNot(
+            Constant::getNullValue(Val->getType())));
       } break;
 
       default:

diff  --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index 04def11136d35..f8d9d0e2c3934 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -838,14 +838,10 @@ static bool isKnownNonZeroFromAssume(const Value *V, const SimplifyQuery &Q) {
         auto OBU = I->getOperandBundleAt(Elem.Index);
         switch (getBundleAttrFromOBU(OBU)) {
         case BundleAttr::Dereferenceable: {
-          auto [Ptr, Count] = getAssumeDereferenceableInfo(OBU);
-          if (Ptr != V ||
-              NullPointerIsDefined(Q.CxtI->getFunction(),
-                                   V->getType()->getPointerAddressSpace()))
-            return false;
-
-          auto *CI = dyn_cast<ConstantInt>(Count);
-          return CI && !CI->isZero();
+          auto [Ptr, _, Count] = getAssumeDereferenceableInfo(OBU);
+          return Ptr == V && Count && *Count != 0 &&
+                 !NullPointerIsDefined(Q.CxtI->getFunction(),
+                                       V->getType()->getPointerAddressSpace());
         }
 
         case BundleAttr::NonNull:

diff  --git a/llvm/lib/IR/BundleAttributes.cpp b/llvm/lib/IR/BundleAttributes.cpp
index 3e4e65e8fd3d1..a6aee2acc6811 100644
--- a/llvm/lib/IR/BundleAttributes.cpp
+++ b/llvm/lib/IR/BundleAttributes.cpp
@@ -60,5 +60,9 @@ AssumeNonNullInfo llvm::getAssumeNonNullInfo(OperandBundleUse OBU) {
 AssumeDereferenceableInfo
 llvm::getAssumeDereferenceableInfo(OperandBundleUse OBU) {
   assert(OBU.getTagName() == "dereferenceable" && OBU.Inputs.size() == 2);
-  return {OBU.Inputs[0], OBU.Inputs[1]};
+  AssumeDereferenceableInfo Ret{OBU.Inputs[0], OBU.Inputs[1], std::nullopt};
+
+  if (auto *Size = dyn_cast<ConstantInt>(OBU.Inputs[1]))
+    Ret.CountVal = Size->getZExtValue();
+  return Ret;
 }

diff  --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp
index cb28ff5c633f3..f0363b6553440 100644
--- a/llvm/lib/IR/Verifier.cpp
+++ b/llvm/lib/IR/Verifier.cpp
@@ -6117,8 +6117,11 @@ void Verifier::visitIntrinsicCall(Intrinsic::ID ID, CallBase &Call) {
               "dereferenceable assumptions should have 2 arguments", Call);
         Check(GetTypeAt(0)->isPointerTy(), "first argument should be a pointer",
               Call);
-        Check(GetTypeAt(1)->isIntegerTy(),
-              "second argument should be an integer", Call);
+        Check(GetTypeAt(1)->isIntegerTy() &&
+                  GetTypeAt(1)->getIntegerBitWidth() <= 64,
+              "second argument should be an integer with a maximum width of 64 "
+              "bits",
+              Call);
         break;
       case BundleAttr::Ignore:
         break;

diff  --git a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
index 35c60e6eb3753..4d6c5840bb868 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
@@ -3679,6 +3679,14 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
         return CallBase::removeOperandBundleAt(II, Idx);
       }
 
+      case BundleAttr::Dereferenceable: {
+        auto [Ptr, _, Count] = getAssumeDereferenceableInfo(OBU);
+
+        if (Count && *Count == 0)
+          return CallBase::removeOperandBundleAt(II, Idx);
+        break;
+      }
+
       case BundleAttr::NonNull: {
         auto [Ptr] = llvm::getAssumeNonNullInfo(OBU);
 
@@ -3719,7 +3727,6 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
       } break;
 
       // TODO: Drop these assumes when they are redundant
-      case BundleAttr::Dereferenceable:
       case BundleAttr::DereferenceableOrNull:
       case BundleAttr::Ignore:
       case BundleAttr::NoUndef:

diff  --git a/llvm/test/Analysis/ValueTracking/assume.ll b/llvm/test/Analysis/ValueTracking/assume.ll
index c5fe253634716..09efbdac20cf4 100644
--- a/llvm/test/Analysis/ValueTracking/assume.ll
+++ b/llvm/test/Analysis/ValueTracking/assume.ll
@@ -173,8 +173,7 @@ define i1 @test_dereferenceable_unknown_size_not_nonnull(ptr %ptr, i32 %bytes) {
 
 define i1 @test_dereferenceable_zero_size_not_nonnull(ptr %ptr) {
 ; CHECK-LABEL: @test_dereferenceable_zero_size_not_nonnull(
-; CHECK-NEXT:    call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[TMP0:%.*]], i32 0) ]
-; CHECK-NEXT:    [[TMP2:%.*]] = icmp eq ptr [[TMP0]], null
+; CHECK-NEXT:    [[TMP2:%.*]] = icmp eq ptr [[TMP0:%.*]], null
 ; CHECK-NEXT:    ret i1 [[TMP2]]
 ;
   call void @llvm.assume(i1 true) ["dereferenceable"(ptr %ptr, i32 0)]

diff  --git a/llvm/test/Transforms/InstCombine/assume.ll b/llvm/test/Transforms/InstCombine/assume.ll
index ffc477228e53b..d1298effa0c58 100644
--- a/llvm/test/Transforms/InstCombine/assume.ll
+++ b/llvm/test/Transforms/InstCombine/assume.ll
@@ -1219,6 +1219,41 @@ define i1 @neg_assume_trunc_eq_one(i8 %x) {
   ret i1 %q
 }
 
+define void @assume_dereferenceable_0(ptr %ptr) {
+; CHECK-LABEL: @assume_dereferenceable_0(
+; CHECK-NEXT:    ret void
+;
+  call void @llvm.assume(i1 true) [ "dereferenceable"(ptr %ptr, i64 0) ]
+  ret void
+}
+
+define void @assume_dereferenceable_1(ptr %ptr) {
+; CHECK-LABEL: @assume_dereferenceable_1(
+; CHECK-NEXT:    call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[PTR:%.*]], i64 1) ]
+; CHECK-NEXT:    ret void
+;
+  call void @llvm.assume(i1 true) [ "dereferenceable"(ptr %ptr, i64 1) ]
+  ret void
+}
+
+define void @assume_dereferenceable_variable(ptr %ptr, i64 %count) {
+; CHECK-LABEL: @assume_dereferenceable_variable(
+; CHECK-NEXT:    call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[PTR:%.*]], i64 [[COUNT:%.*]]) ]
+; CHECK-NEXT:    ret void
+;
+  call void @llvm.assume(i1 true) [ "dereferenceable"(ptr %ptr, i64 %count) ]
+  ret void
+}
+
+define void @assume_dereferenceable_variable_on_nullptr(i64 %count) {
+; CHECK-LABEL: @assume_dereferenceable_variable_on_nullptr(
+; CHECK-NEXT:    call void @llvm.assume(i1 true) [ "dereferenceable"(ptr null, i64 [[COUNT:%.*]]) ]
+; CHECK-NEXT:    ret void
+;
+  call void @llvm.assume(i1 true) [ "dereferenceable"(ptr null, i64 %count) ]
+  ret void
+}
+
 declare void @use(i1)
 declare void @llvm.dbg.value(metadata, metadata, metadata)
 

diff  --git a/llvm/test/Verifier/assume-bundles.ll b/llvm/test/Verifier/assume-bundles.ll
index efba13dd7c7c5..dd8d31031c4f9 100644
--- a/llvm/test/Verifier/assume-bundles.ll
+++ b/llvm/test/Verifier/assume-bundles.ll
@@ -42,7 +42,9 @@ define void @func(ptr %P, i32 %P1, ptr %P2, ptr %P3, i1 %cond) {
   call void @llvm.assume(i1 true) ["dereferenceable"(ptr %P, i32 %P1)]
 ; CHECK: first argument should be a pointer
   call void @llvm.assume(i1 true) ["dereferenceable"(i32 %P1, i32 %P1)]
-; CHECK: second argument should be an integer
+; CHECK: second argument should be an integer with a maximum width of 64 bits
+  call void @llvm.assume(i1 true) ["dereferenceable"(ptr %P, i65 0)]
+; CHECK: second argument should be an integer with a maximum width of 64 bits
   call void @llvm.assume(i1 true) ["dereferenceable"(ptr %P, float 1.5)]
 ; CHECK: dereferenceable assumptions should have 2 arguments
   call void @llvm.assume(i1 true) ["dereferenceable"(ptr %P, i32 8, i32 8)]
@@ -53,7 +55,9 @@ define void @func(ptr %P, i32 %P1, ptr %P2, ptr %P3, i1 %cond) {
   call void @llvm.assume(i1 true) ["dereferenceable_or_null"(ptr %P, i32 %P1)]
 ; CHECK: first argument should be a pointer
   call void @llvm.assume(i1 true) ["dereferenceable_or_null"(i32 %P1, i32 %P1)]
-; CHECK: second argument should be an integer
+; CHECK: second argument should be an integer with a maximum width of 64 bits
+  call void @llvm.assume(i1 true) ["dereferenceable_or_null"(ptr %P, i65 0)]
+; CHECK: second argument should be an integer with a maximum width of 64 bits
   call void @llvm.assume(i1 true) ["dereferenceable_or_null"(ptr %P, float 1.5)]
 ; CHECK: dereferenceable assumptions should have 2 arguments
   call void @llvm.assume(i1 true) ["dereferenceable_or_null"(ptr %P, i32 8, i32 8)]


        


More information about the llvm-commits mailing list