[llvm] f226cab - [ValueTracking] Handle nonnull attributes at callsite (#124908)
via llvm-commits
llvm-commits at lists.llvm.org
Wed Jan 29 07:14:39 PST 2025
Author: Yingwei Zheng
Date: 2025-01-29T23:14:36+08:00
New Revision: f226cabbb1b9737676536bc4417336bef4808992
URL: https://github.com/llvm/llvm-project/commit/f226cabbb1b9737676536bc4417336bef4808992
DIFF: https://github.com/llvm/llvm-project/commit/f226cabbb1b9737676536bc4417336bef4808992.diff
LOG: [ValueTracking] Handle nonnull attributes at callsite (#124908)
Alive2: https://alive2.llvm.org/ce/z/yJfskv
Closes https://github.com/llvm/llvm-project/issues/124540.
Added:
Modified:
llvm/include/llvm/IR/InstrTypes.h
llvm/lib/Analysis/ValueTracking.cpp
llvm/lib/IR/Instructions.cpp
llvm/test/Analysis/ValueTracking/known-nonnull-at.ll
llvm/test/Transforms/InstCombine/align-addr.ll
llvm/test/Transforms/InstCombine/memset_chk-1.ll
llvm/test/Transforms/InstCombine/sprintf-1.ll
llvm/test/Transforms/InstCombine/stpncpy-1.ll
llvm/test/Transforms/InstCombine/strlcpy-1.ll
llvm/test/Transforms/InstCombine/strncpy-4.ll
llvm/test/Transforms/InstCombine/strstr-1.ll
llvm/test/Transforms/InstSimplify/known-non-zero-opaque-ptrs.ll
Removed:
################################################################################
diff --git a/llvm/include/llvm/IR/InstrTypes.h b/llvm/include/llvm/IR/InstrTypes.h
index 47ddc7555594c57..6ff90e1d095aace 100644
--- a/llvm/include/llvm/IR/InstrTypes.h
+++ b/llvm/include/llvm/IR/InstrTypes.h
@@ -1591,6 +1591,14 @@ class CallBase : public Instruction {
/// Determine whether the argument or parameter has the given attribute.
bool paramHasAttr(unsigned ArgNo, Attribute::AttrKind Kind) const;
+ /// Return true if this argument has the nonnull attribute on either the
+ /// CallBase instruction or the called function. Also returns true if at least
+ /// one byte is known to be dereferenceable and the pointer is in
+ /// addrspace(0). If \p AllowUndefOrPoison is true, respect the semantics of
+ /// nonnull attribute and return true even if the argument can be undef or
+ /// poison.
+ bool paramHasNonNullAttr(unsigned ArgNo, bool AllowUndefOrPoison) const;
+
/// Get the attribute of a given kind at a position.
Attribute getAttributeAtIndex(unsigned i, Attribute::AttrKind Kind) const {
return getAttributes().getAttributeAtIndex(i, Kind);
diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index b63a0a07f7de292..45c3b85ea39fb46 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -2652,40 +2652,42 @@ static bool isKnownNonNullFromDominatingCondition(const Value *V,
return false;
unsigned NumUsesExplored = 0;
- for (const auto *U : V->users()) {
+ for (auto &U : V->uses()) {
// Avoid massive lists
if (NumUsesExplored >= DomConditionsMaxUses)
break;
NumUsesExplored++;
+ const Instruction *UI = cast<Instruction>(U.getUser());
// If the value is used as an argument to a call or invoke, then argument
// attributes may provide an answer about null-ness.
- if (const auto *CB = dyn_cast<CallBase>(U))
- if (auto *CalledFunc = CB->getCalledFunction())
- for (const Argument &Arg : CalledFunc->args())
- if (CB->getArgOperand(Arg.getArgNo()) == V &&
- Arg.hasNonNullAttr(/* AllowUndefOrPoison */ false) &&
- DT->dominates(CB, CtxI))
- return true;
+ if (V->getType()->isPointerTy()) {
+ if (const auto *CB = dyn_cast<CallBase>(UI)) {
+ if (CB->isArgOperand(&U) &&
+ CB->paramHasNonNullAttr(CB->getArgOperandNo(&U),
+ /*AllowUndefOrPoison=*/false) &&
+ DT->dominates(CB, CtxI))
+ return true;
+ }
+ }
// If the value is used as a load/store, then the pointer must be non null.
- if (V == getLoadStorePointerOperand(U)) {
- const Instruction *I = cast<Instruction>(U);
- if (!NullPointerIsDefined(I->getFunction(),
+ if (V == getLoadStorePointerOperand(UI)) {
+ if (!NullPointerIsDefined(UI->getFunction(),
V->getType()->getPointerAddressSpace()) &&
- DT->dominates(I, CtxI))
+ DT->dominates(UI, CtxI))
return true;
}
- if ((match(U, m_IDiv(m_Value(), m_Specific(V))) ||
- match(U, m_IRem(m_Value(), m_Specific(V)))) &&
- isValidAssumeForContext(cast<Instruction>(U), CtxI, DT))
+ if ((match(UI, m_IDiv(m_Value(), m_Specific(V))) ||
+ match(UI, m_IRem(m_Value(), m_Specific(V)))) &&
+ isValidAssumeForContext(UI, CtxI, DT))
return true;
// Consider only compare instructions uniquely controlling a branch
Value *RHS;
CmpPredicate Pred;
- if (!match(U, m_c_ICmp(Pred, m_Specific(V), m_Value(RHS))))
+ if (!match(UI, m_c_ICmp(Pred, m_Specific(V), m_Value(RHS))))
continue;
bool NonNullIfTrue;
@@ -2698,7 +2700,7 @@ static bool isKnownNonNullFromDominatingCondition(const Value *V,
SmallVector<const User *, 4> WorkList;
SmallPtrSet<const User *, 4> Visited;
- for (const auto *CmpU : U->users()) {
+ for (const auto *CmpU : UI->users()) {
assert(WorkList.empty() && "Should be!");
if (Visited.insert(CmpU).second)
WorkList.push_back(CmpU);
diff --git a/llvm/lib/IR/Instructions.cpp b/llvm/lib/IR/Instructions.cpp
index c9f5807765e400f..dd3b79ed6d7d273 100644
--- a/llvm/lib/IR/Instructions.cpp
+++ b/llvm/lib/IR/Instructions.cpp
@@ -432,6 +432,23 @@ bool CallBase::paramHasAttr(unsigned ArgNo, Attribute::AttrKind Kind) const {
}
}
+bool CallBase::paramHasNonNullAttr(unsigned ArgNo,
+ bool AllowUndefOrPoison) const {
+ assert(getArgOperand(ArgNo)->getType()->isPointerTy() &&
+ "Argument must be a pointer");
+ if (paramHasAttr(ArgNo, Attribute::NonNull) &&
+ (AllowUndefOrPoison || paramHasAttr(ArgNo, Attribute::NoUndef)))
+ return true;
+
+ if (getParamDereferenceableBytes(ArgNo) > 0 &&
+ !NullPointerIsDefined(
+ getCaller(),
+ getArgOperand(ArgNo)->getType()->getPointerAddressSpace()))
+ return true;
+
+ return false;
+}
+
bool CallBase::hasFnAttrOnCalledFunction(Attribute::AttrKind Kind) const {
if (auto *F = dyn_cast<Function>(getCalledOperand()))
return F->getAttributes().hasFnAttr(Kind);
diff --git a/llvm/test/Analysis/ValueTracking/known-nonnull-at.ll b/llvm/test/Analysis/ValueTracking/known-nonnull-at.ll
index 79d2653a3a14666..dff7e13b8a2e773 100644
--- a/llvm/test/Analysis/ValueTracking/known-nonnull-at.ll
+++ b/llvm/test/Analysis/ValueTracking/known-nonnull-at.ll
@@ -220,3 +220,70 @@ return:
%retval.0 = phi ptr [ %1, %if.end ], [ null, %entry ]
ret ptr %retval.0
}
+
+define i1 @test_known_nonnull_at_callsite(ptr %src) {
+; CHECK-LABEL: @test_known_nonnull_at_callsite(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: call void @callee(ptr noundef nonnull [[SRC:%.*]])
+; CHECK-NEXT: ret i1 false
+;
+entry:
+ call void @callee(ptr noundef nonnull %src)
+ %nonnull = icmp eq ptr %src, null
+ ret i1 %nonnull
+}
+
+define i1 @test_known_nonnull_mixed(ptr %src) {
+; CHECK-LABEL: @test_known_nonnull_mixed(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: call void @callee2(ptr nonnull [[SRC:%.*]])
+; CHECK-NEXT: ret i1 false
+;
+entry:
+ call void @callee2(ptr nonnull %src)
+ %nonnull = icmp eq ptr %src, null
+ ret i1 %nonnull
+}
+
+define i1 @test_known_nonnull_at_callsite_dereferenceable(ptr %src) {
+; CHECK-LABEL: @test_known_nonnull_at_callsite_dereferenceable(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: call void @callee(ptr dereferenceable(1) [[SRC:%.*]])
+; CHECK-NEXT: ret i1 false
+;
+entry:
+ call void @callee(ptr dereferenceable(1) %src)
+ %nonnull = icmp eq ptr %src, null
+ ret i1 %nonnull
+}
+
+; Negative tests
+
+define i1 @test_known_nonnull_at_callsite_without_noundef(ptr %src) {
+; CHECK-LABEL: @test_known_nonnull_at_callsite_without_noundef(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: call void @callee(ptr nonnull [[SRC:%.*]])
+; CHECK-NEXT: [[NONNULL:%.*]] = icmp eq ptr [[SRC]], null
+; CHECK-NEXT: ret i1 [[NONNULL]]
+;
+entry:
+ call void @callee(ptr nonnull %src)
+ %nonnull = icmp eq ptr %src, null
+ ret i1 %nonnull
+}
+
+define i1 @test_known_nonnull_at_callsite_dereferenceable_null_is_defined(ptr %src) null_pointer_is_valid {
+; CHECK-LABEL: @test_known_nonnull_at_callsite_dereferenceable_null_is_defined(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: call void @callee(ptr dereferenceable(1) [[SRC:%.*]])
+; CHECK-NEXT: [[NONNULL:%.*]] = icmp eq ptr [[SRC]], null
+; CHECK-NEXT: ret i1 [[NONNULL]]
+;
+entry:
+ call void @callee(ptr dereferenceable(1) %src)
+ %nonnull = icmp eq ptr %src, null
+ ret i1 %nonnull
+}
+
+declare void @callee(ptr)
+declare void @callee2(ptr noundef)
diff --git a/llvm/test/Transforms/InstCombine/align-addr.ll b/llvm/test/Transforms/InstCombine/align-addr.ll
index 6ef4d85fe4e4121..b77037e592b54b1 100644
--- a/llvm/test/Transforms/InstCombine/align-addr.ll
+++ b/llvm/test/Transforms/InstCombine/align-addr.ll
@@ -112,7 +112,7 @@ define void @test3(ptr sret(%struct.s) %a4) {
; Check that the alignment is bumped up the alignment of the sret type.
; CHECK-LABEL: @test3(
; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr noundef nonnull align 4 dereferenceable(16) [[A4:%.*]], i8 0, i64 16, i1 false)
-; CHECK-NEXT: call void @use(ptr [[A4]])
+; CHECK-NEXT: call void @use(ptr nonnull [[A4]])
; CHECK-NEXT: ret void
;
call void @llvm.memset.p0.i64(ptr %a4, i8 0, i64 16, i1 false)
diff --git a/llvm/test/Transforms/InstCombine/memset_chk-1.ll b/llvm/test/Transforms/InstCombine/memset_chk-1.ll
index 44b549e400dd857..9020f174fb5b7d7 100644
--- a/llvm/test/Transforms/InstCombine/memset_chk-1.ll
+++ b/llvm/test/Transforms/InstCombine/memset_chk-1.ll
@@ -92,7 +92,7 @@ define i32 @test_rauw(ptr %a, ptr %b, ptr %c) {
; CHECK-NEXT: [[CALL49:%.*]] = call i64 @strlen(ptr noundef nonnull dereferenceable(1) [[A:%.*]])
; CHECK-NEXT: [[ADD180:%.*]] = add i64 [[CALL49]], 1
; CHECK-NEXT: [[YO107:%.*]] = call i64 @llvm.objectsize.i64.p0(ptr [[B:%.*]], i1 false, i1 false, i1 false)
-; CHECK-NEXT: [[CALL50:%.*]] = call ptr @__memmove_chk(ptr [[B]], ptr [[A]], i64 [[ADD180]], i64 [[YO107]])
+; CHECK-NEXT: [[CALL50:%.*]] = call ptr @__memmove_chk(ptr [[B]], ptr nonnull [[A]], i64 [[ADD180]], i64 [[YO107]])
; CHECK-NEXT: [[STRLEN:%.*]] = call i64 @strlen(ptr noundef nonnull dereferenceable(1) [[B]])
; CHECK-NEXT: [[STRCHR1:%.*]] = getelementptr inbounds i8, ptr [[B]], i64 [[STRLEN]]
; CHECK-NEXT: [[D:%.*]] = load ptr, ptr [[C:%.*]], align 8
@@ -100,7 +100,7 @@ define i32 @test_rauw(ptr %a, ptr %b, ptr %c) {
; CHECK-NEXT: [[SUB183:%.*]] = ptrtoint ptr [[B]] to i64
; CHECK-NEXT: [[SUB184:%.*]] = sub i64 [[SUB182]], [[SUB183]]
; CHECK-NEXT: [[ADD52_I_I:%.*]] = add nsw i64 [[SUB184]], 1
-; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 1 [[STRCHR1]], i8 0, i64 [[ADD52_I_I]], i1 false)
+; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr nonnull align 1 [[STRCHR1]], i8 0, i64 [[ADD52_I_I]], i1 false)
; CHECK-NEXT: ret i32 4
;
entry:
diff --git a/llvm/test/Transforms/InstCombine/sprintf-1.ll b/llvm/test/Transforms/InstCombine/sprintf-1.ll
index 0749015059415ca..1d87758340f710e 100644
--- a/llvm/test/Transforms/InstCombine/sprintf-1.ll
+++ b/llvm/test/Transforms/InstCombine/sprintf-1.ll
@@ -103,7 +103,7 @@ define i32 @test_simplify7(ptr %dst, ptr %str) {
; NOSTPCPY-LABEL: @test_simplify7(
; NOSTPCPY-NEXT: [[STRLEN:%.*]] = call i32 @strlen(ptr noundef nonnull dereferenceable(1) [[STR:%.*]])
; NOSTPCPY-NEXT: [[LENINC:%.*]] = add i32 [[STRLEN]], 1
-; NOSTPCPY-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 1 [[DST:%.*]], ptr align 1 [[STR]], i32 [[LENINC]], i1 false)
+; NOSTPCPY-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 1 [[DST:%.*]], ptr nonnull align 1 [[STR]], i32 [[LENINC]], i1 false)
; NOSTPCPY-NEXT: ret i32 [[STRLEN]]
;
%r = call i32 (ptr, ptr, ...) @sprintf(ptr %dst, ptr @percent_s, ptr %str)
@@ -133,7 +133,7 @@ define i32 @test_simplify9(ptr %dst, ptr %str) {
; NOSTPCPY-LABEL: @test_simplify9(
; NOSTPCPY-NEXT: [[STRLEN:%.*]] = call i32 @strlen(ptr noundef nonnull dereferenceable(1) [[STR:%.*]])
; NOSTPCPY-NEXT: [[LENINC:%.*]] = add i32 [[STRLEN]], 1
-; NOSTPCPY-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 1 [[DST:%.*]], ptr align 1 [[STR]], i32 [[LENINC]], i1 false)
+; NOSTPCPY-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 1 [[DST:%.*]], ptr nonnull align 1 [[STR]], i32 [[LENINC]], i1 false)
; NOSTPCPY-NEXT: ret i32 [[STRLEN]]
;
%r = call i32 (ptr, ptr, ...) @sprintf(ptr %dst, ptr @percent_s, ptr %str)
diff --git a/llvm/test/Transforms/InstCombine/stpncpy-1.ll b/llvm/test/Transforms/InstCombine/stpncpy-1.ll
index 87f54918b7d25ed..6ef9b425ae9d937 100644
--- a/llvm/test/Transforms/InstCombine/stpncpy-1.ll
+++ b/llvm/test/Transforms/InstCombine/stpncpy-1.ll
@@ -70,11 +70,11 @@ define void @fold_stpncpy_overlap(ptr %dst, i64 %n) {
define void @call_stpncpy_overlap(ptr %dst, i64 %n) {
; ANY-LABEL: @call_stpncpy_overlap(
; ANY-NEXT: [[ES_2:%.*]] = call ptr @stpncpy(ptr noundef nonnull dereferenceable(1) [[DST:%.*]], ptr noundef nonnull dereferenceable(1) [[DST]], i64 2)
-; ANY-NEXT: call void @sink(ptr [[DST]], ptr [[ES_2]])
+; ANY-NEXT: call void @sink(ptr nonnull [[DST]], ptr [[ES_2]])
; ANY-NEXT: [[ES_3:%.*]] = call ptr @stpncpy(ptr noundef nonnull dereferenceable(1) [[DST]], ptr noundef nonnull dereferenceable(1) [[DST]], i64 3)
-; ANY-NEXT: call void @sink(ptr [[DST]], ptr [[ES_3]])
-; ANY-NEXT: [[ES_N:%.*]] = call ptr @stpncpy(ptr [[DST]], ptr [[DST]], i64 [[N:%.*]])
-; ANY-NEXT: call void @sink(ptr [[DST]], ptr [[ES_N]])
+; ANY-NEXT: call void @sink(ptr nonnull [[DST]], ptr [[ES_3]])
+; ANY-NEXT: [[ES_N:%.*]] = call ptr @stpncpy(ptr nonnull [[DST]], ptr nonnull [[DST]], i64 [[N:%.*]])
+; ANY-NEXT: call void @sink(ptr nonnull [[DST]], ptr [[ES_N]])
; ANY-NEXT: ret void
;
; Do not transform stpncpy(D, D, 2).
@@ -428,9 +428,9 @@ define void @fold_stpncpy_s(ptr %dst, ptr %src) {
define void @call_stpncpy_s(ptr %dst, ptr %src, i64 %n) {
; ANY-LABEL: @call_stpncpy_s(
; ANY-NEXT: [[ES_2:%.*]] = call ptr @stpncpy(ptr noundef nonnull dereferenceable(1) [[DST:%.*]], ptr noundef nonnull dereferenceable(1) [[SRC:%.*]], i64 2)
-; ANY-NEXT: call void @sink(ptr [[DST]], ptr [[ES_2]])
-; ANY-NEXT: [[ES_N:%.*]] = call ptr @stpncpy(ptr [[DST]], ptr [[SRC]], i64 [[N:%.*]])
-; ANY-NEXT: call void @sink(ptr [[DST]], ptr [[ES_N]])
+; ANY-NEXT: call void @sink(ptr nonnull [[DST]], ptr [[ES_2]])
+; ANY-NEXT: [[ES_N:%.*]] = call ptr @stpncpy(ptr nonnull [[DST]], ptr nonnull [[SRC]], i64 [[N:%.*]])
+; ANY-NEXT: call void @sink(ptr nonnull [[DST]], ptr [[ES_N]])
; ANY-NEXT: ret void
;
; Do not transform stpncpy(D, S, 2). Both *D and *S must be derefernceable
diff --git a/llvm/test/Transforms/InstCombine/strlcpy-1.ll b/llvm/test/Transforms/InstCombine/strlcpy-1.ll
index fd9d0580426f0a4..ad538259ae96255 100644
--- a/llvm/test/Transforms/InstCombine/strlcpy-1.ll
+++ b/llvm/test/Transforms/InstCombine/strlcpy-1.ll
@@ -229,18 +229,18 @@ define void @fold_strlcpy_s_0(ptr %dst, ptr %s, i64 %n) {
define void @call_strlcpy_s0_n(ptr %dst, ptr %s, i64 %n) {
; ANY-LABEL: @call_strlcpy_s0_n(
; ANY-NEXT: [[NS_2:%.*]] = call i64 @strlcpy(ptr noundef nonnull dereferenceable(1) [[DST:%.*]], ptr noundef nonnull dereferenceable(1) [[S:%.*]], i64 2)
-; ANY-NEXT: call void @sink(ptr [[DST]], i64 [[NS_2]])
-; ANY-NEXT: [[NS_N:%.*]] = call i64 @strlcpy(ptr [[DST]], ptr noundef nonnull dereferenceable(1) [[S]], i64 [[N:%.*]])
-; ANY-NEXT: call void @sink(ptr [[DST]], i64 [[NS_N]])
+; ANY-NEXT: call void @sink(ptr nonnull [[DST]], i64 [[NS_2]])
+; ANY-NEXT: [[NS_N:%.*]] = call i64 @strlcpy(ptr nonnull [[DST]], ptr noundef nonnull dereferenceable(1) [[S]], i64 [[N:%.*]])
+; ANY-NEXT: call void @sink(ptr nonnull [[DST]], i64 [[NS_N]])
; ANY-NEXT: [[NZ:%.*]] = or i64 [[N]], 1
; ANY-NEXT: [[NS_NZ:%.*]] = call i64 @strlcpy(ptr noundef nonnull dereferenceable(1) [[DST]], ptr noundef nonnull dereferenceable(1) [[S]], i64 [[NZ]])
-; ANY-NEXT: call void @sink(ptr [[DST]], i64 [[NS_NZ]])
-; ANY-NEXT: [[NS0_N:%.*]] = call i64 @strlcpy(ptr [[DST]], ptr noundef nonnull dereferenceable(1) getelementptr inbounds nuw (i8, ptr @s4, i64 4), i64 [[N]])
-; ANY-NEXT: call void @sink(ptr [[DST]], i64 [[NS0_N]])
-; ANY-NEXT: [[NS1_N:%.*]] = call i64 @strlcpy(ptr [[DST]], ptr noundef nonnull dereferenceable(1) getelementptr inbounds nuw (i8, ptr @s4, i64 3), i64 [[N]])
-; ANY-NEXT: call void @sink(ptr [[DST]], i64 [[NS1_N]])
-; ANY-NEXT: [[NS4_N:%.*]] = call i64 @strlcpy(ptr [[DST]], ptr noundef nonnull dereferenceable(1) @s4, i64 [[N]])
-; ANY-NEXT: call void @sink(ptr [[DST]], i64 [[NS4_N]])
+; ANY-NEXT: call void @sink(ptr nonnull [[DST]], i64 [[NS_NZ]])
+; ANY-NEXT: [[NS0_N:%.*]] = call i64 @strlcpy(ptr nonnull [[DST]], ptr noundef nonnull dereferenceable(1) getelementptr inbounds nuw (i8, ptr @s4, i64 4), i64 [[N]])
+; ANY-NEXT: call void @sink(ptr nonnull [[DST]], i64 [[NS0_N]])
+; ANY-NEXT: [[NS1_N:%.*]] = call i64 @strlcpy(ptr nonnull [[DST]], ptr noundef nonnull dereferenceable(1) getelementptr inbounds nuw (i8, ptr @s4, i64 3), i64 [[N]])
+; ANY-NEXT: call void @sink(ptr nonnull [[DST]], i64 [[NS1_N]])
+; ANY-NEXT: [[NS4_N:%.*]] = call i64 @strlcpy(ptr nonnull [[DST]], ptr noundef nonnull dereferenceable(1) @s4, i64 [[N]])
+; ANY-NEXT: call void @sink(ptr nonnull [[DST]], i64 [[NS4_N]])
; ANY-NEXT: ret void
;
%ns_2 = call i64 @strlcpy(ptr %dst, ptr %s, i64 2)
diff --git a/llvm/test/Transforms/InstCombine/strncpy-4.ll b/llvm/test/Transforms/InstCombine/strncpy-4.ll
index aa70e76e20ed909..0e1f800a9a35724 100644
--- a/llvm/test/Transforms/InstCombine/strncpy-4.ll
+++ b/llvm/test/Transforms/InstCombine/strncpy-4.ll
@@ -45,11 +45,11 @@ define void @fold_strncpy_overlap(ptr %dst, i64 %n) {
define void @call_strncpy_overlap(ptr %dst, i64 %n) {
; CHECK-LABEL: @call_strncpy_overlap(
; CHECK-NEXT: [[ED_2:%.*]] = call ptr @strncpy(ptr noundef nonnull dereferenceable(1) [[DST:%.*]], ptr noundef nonnull dereferenceable(1) [[DST]], i64 2)
-; CHECK-NEXT: call void @sink(ptr [[DST]], ptr [[ED_2]])
+; CHECK-NEXT: call void @sink(ptr nonnull [[DST]], ptr [[ED_2]])
; CHECK-NEXT: [[ED_3:%.*]] = call ptr @strncpy(ptr noundef nonnull dereferenceable(1) [[DST]], ptr noundef nonnull dereferenceable(1) [[DST]], i64 3)
-; CHECK-NEXT: call void @sink(ptr [[DST]], ptr [[ED_3]])
-; CHECK-NEXT: [[ED_N:%.*]] = call ptr @strncpy(ptr [[DST]], ptr [[DST]], i64 [[N:%.*]])
-; CHECK-NEXT: call void @sink(ptr [[DST]], ptr [[ED_N]])
+; CHECK-NEXT: call void @sink(ptr nonnull [[DST]], ptr [[ED_3]])
+; CHECK-NEXT: [[ED_N:%.*]] = call ptr @strncpy(ptr nonnull [[DST]], ptr nonnull [[DST]], i64 [[N:%.*]])
+; CHECK-NEXT: call void @sink(ptr nonnull [[DST]], ptr [[ED_N]])
; CHECK-NEXT: ret void
;
@@ -141,11 +141,11 @@ define void @fold_strncpy_s(ptr %dst, ptr %src, i64 %n) {
define void @call_strncpy_s(ptr %dst, ptr %src, i64 %n) {
; CHECK-LABEL: @call_strncpy_s(
; CHECK-NEXT: [[ED_2:%.*]] = call ptr @strncpy(ptr noundef nonnull dereferenceable(1) [[DST:%.*]], ptr noundef nonnull dereferenceable(1) [[SRC:%.*]], i64 2)
-; CHECK-NEXT: call void @sink(ptr [[DST]], ptr [[ED_2]])
+; CHECK-NEXT: call void @sink(ptr nonnull [[DST]], ptr [[ED_2]])
; CHECK-NEXT: [[ED_9:%.*]] = call ptr @strncpy(ptr noundef nonnull dereferenceable(1) [[DST]], ptr noundef nonnull dereferenceable(1) [[SRC]], i64 9)
-; CHECK-NEXT: call void @sink(ptr [[DST]], ptr [[ED_9]])
-; CHECK-NEXT: [[ED_N:%.*]] = call ptr @strncpy(ptr [[DST]], ptr [[SRC]], i64 [[N:%.*]])
-; CHECK-NEXT: call void @sink(ptr [[DST]], ptr [[ED_N]])
+; CHECK-NEXT: call void @sink(ptr nonnull [[DST]], ptr [[ED_9]])
+; CHECK-NEXT: [[ED_N:%.*]] = call ptr @strncpy(ptr nonnull [[DST]], ptr nonnull [[SRC]], i64 [[N:%.*]])
+; CHECK-NEXT: call void @sink(ptr nonnull [[DST]], ptr [[ED_N]])
; CHECK-NEXT: ret void
;
; Do not transform strncpy(D, S, 2) when S is unknown. Both *D and *S must
diff --git a/llvm/test/Transforms/InstCombine/strstr-1.ll b/llvm/test/Transforms/InstCombine/strstr-1.ll
index 68de7614aad2baa..083ee47bb47d1f8 100644
--- a/llvm/test/Transforms/InstCombine/strstr-1.ll
+++ b/llvm/test/Transforms/InstCombine/strstr-1.ll
@@ -58,7 +58,7 @@ define ptr @test_simplify4(ptr %str) {
define i1 @test_simplify5(ptr %str, ptr %pat) {
; CHECK-LABEL: @test_simplify5(
; CHECK-NEXT: [[STRLEN:%.*]] = call i64 @strlen(ptr noundef nonnull dereferenceable(1) [[PAT:%.*]])
-; CHECK-NEXT: [[STRNCMP:%.*]] = call i32 @strncmp(ptr [[STR:%.*]], ptr [[PAT]], i64 [[STRLEN]])
+; CHECK-NEXT: [[STRNCMP:%.*]] = call i32 @strncmp(ptr [[STR:%.*]], ptr nonnull [[PAT]], i64 [[STRLEN]])
; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32 [[STRNCMP]], 0
; CHECK-NEXT: ret i1 [[CMP1]]
;
diff --git a/llvm/test/Transforms/InstSimplify/known-non-zero-opaque-ptrs.ll b/llvm/test/Transforms/InstSimplify/known-non-zero-opaque-ptrs.ll
index 92084196d955326..941b31fd1198cd0 100644
--- a/llvm/test/Transforms/InstSimplify/known-non-zero-opaque-ptrs.ll
+++ b/llvm/test/Transforms/InstSimplify/known-non-zero-opaque-ptrs.ll
@@ -4,12 +4,10 @@
declare void @zero_args()
declare void @two_args(ptr, ptr)
-; TODO: Could be non-null based on call-site attributes.
define i1 @test_zero_args_nonnull(ptr %p) {
; CHECK-LABEL: @test_zero_args_nonnull(
; CHECK-NEXT: call void @zero_args(ptr noundef nonnull [[P:%.*]])
-; CHECK-NEXT: [[C:%.*]] = icmp ne ptr [[P]], null
-; CHECK-NEXT: ret i1 [[C]]
+; CHECK-NEXT: ret i1 true
;
call void @zero_args(ptr nonnull noundef %p)
%c = icmp ne ptr %p, null
@@ -27,12 +25,10 @@ define i1 @test_zero_args_maybe_null(ptr %p) {
ret i1 %c
}
-; TODO: Could be non-null based on call-site attributes.
define i1 @test_two_args_nonnull(ptr %p) {
; CHECK-LABEL: @test_two_args_nonnull(
; CHECK-NEXT: call void @two_args(ptr noundef nonnull [[P:%.*]])
-; CHECK-NEXT: [[C:%.*]] = icmp ne ptr [[P]], null
-; CHECK-NEXT: ret i1 [[C]]
+; CHECK-NEXT: ret i1 true
;
call void @two_args(ptr nonnull noundef %p)
%c = icmp ne ptr %p, null
More information about the llvm-commits
mailing list