[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