Skip to content

Commit f226cab

Browse files
authored
[ValueTracking] Handle nonnull attributes at callsite (#124908)
Alive2: https://alive2.llvm.org/ce/z/yJfskv Closes #124540.
1 parent 39a72be commit f226cab

File tree

12 files changed

+144
-54
lines changed

12 files changed

+144
-54
lines changed

llvm/include/llvm/IR/InstrTypes.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1591,6 +1591,14 @@ class CallBase : public Instruction {
15911591
/// Determine whether the argument or parameter has the given attribute.
15921592
bool paramHasAttr(unsigned ArgNo, Attribute::AttrKind Kind) const;
15931593

1594+
/// Return true if this argument has the nonnull attribute on either the
1595+
/// CallBase instruction or the called function. Also returns true if at least
1596+
/// one byte is known to be dereferenceable and the pointer is in
1597+
/// addrspace(0). If \p AllowUndefOrPoison is true, respect the semantics of
1598+
/// nonnull attribute and return true even if the argument can be undef or
1599+
/// poison.
1600+
bool paramHasNonNullAttr(unsigned ArgNo, bool AllowUndefOrPoison) const;
1601+
15941602
/// Get the attribute of a given kind at a position.
15951603
Attribute getAttributeAtIndex(unsigned i, Attribute::AttrKind Kind) const {
15961604
return getAttributes().getAttributeAtIndex(i, Kind);

llvm/lib/Analysis/ValueTracking.cpp

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2652,40 +2652,42 @@ static bool isKnownNonNullFromDominatingCondition(const Value *V,
26522652
return false;
26532653

26542654
unsigned NumUsesExplored = 0;
2655-
for (const auto *U : V->users()) {
2655+
for (auto &U : V->uses()) {
26562656
// Avoid massive lists
26572657
if (NumUsesExplored >= DomConditionsMaxUses)
26582658
break;
26592659
NumUsesExplored++;
26602660

2661+
const Instruction *UI = cast<Instruction>(U.getUser());
26612662
// If the value is used as an argument to a call or invoke, then argument
26622663
// attributes may provide an answer about null-ness.
2663-
if (const auto *CB = dyn_cast<CallBase>(U))
2664-
if (auto *CalledFunc = CB->getCalledFunction())
2665-
for (const Argument &Arg : CalledFunc->args())
2666-
if (CB->getArgOperand(Arg.getArgNo()) == V &&
2667-
Arg.hasNonNullAttr(/* AllowUndefOrPoison */ false) &&
2668-
DT->dominates(CB, CtxI))
2669-
return true;
2664+
if (V->getType()->isPointerTy()) {
2665+
if (const auto *CB = dyn_cast<CallBase>(UI)) {
2666+
if (CB->isArgOperand(&U) &&
2667+
CB->paramHasNonNullAttr(CB->getArgOperandNo(&U),
2668+
/*AllowUndefOrPoison=*/false) &&
2669+
DT->dominates(CB, CtxI))
2670+
return true;
2671+
}
2672+
}
26702673

26712674
// If the value is used as a load/store, then the pointer must be non null.
2672-
if (V == getLoadStorePointerOperand(U)) {
2673-
const Instruction *I = cast<Instruction>(U);
2674-
if (!NullPointerIsDefined(I->getFunction(),
2675+
if (V == getLoadStorePointerOperand(UI)) {
2676+
if (!NullPointerIsDefined(UI->getFunction(),
26752677
V->getType()->getPointerAddressSpace()) &&
2676-
DT->dominates(I, CtxI))
2678+
DT->dominates(UI, CtxI))
26772679
return true;
26782680
}
26792681

2680-
if ((match(U, m_IDiv(m_Value(), m_Specific(V))) ||
2681-
match(U, m_IRem(m_Value(), m_Specific(V)))) &&
2682-
isValidAssumeForContext(cast<Instruction>(U), CtxI, DT))
2682+
if ((match(UI, m_IDiv(m_Value(), m_Specific(V))) ||
2683+
match(UI, m_IRem(m_Value(), m_Specific(V)))) &&
2684+
isValidAssumeForContext(UI, CtxI, DT))
26832685
return true;
26842686

26852687
// Consider only compare instructions uniquely controlling a branch
26862688
Value *RHS;
26872689
CmpPredicate Pred;
2688-
if (!match(U, m_c_ICmp(Pred, m_Specific(V), m_Value(RHS))))
2690+
if (!match(UI, m_c_ICmp(Pred, m_Specific(V), m_Value(RHS))))
26892691
continue;
26902692

26912693
bool NonNullIfTrue;
@@ -2698,7 +2700,7 @@ static bool isKnownNonNullFromDominatingCondition(const Value *V,
26982700

26992701
SmallVector<const User *, 4> WorkList;
27002702
SmallPtrSet<const User *, 4> Visited;
2701-
for (const auto *CmpU : U->users()) {
2703+
for (const auto *CmpU : UI->users()) {
27022704
assert(WorkList.empty() && "Should be!");
27032705
if (Visited.insert(CmpU).second)
27042706
WorkList.push_back(CmpU);

llvm/lib/IR/Instructions.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -432,6 +432,23 @@ bool CallBase::paramHasAttr(unsigned ArgNo, Attribute::AttrKind Kind) const {
432432
}
433433
}
434434

435+
bool CallBase::paramHasNonNullAttr(unsigned ArgNo,
436+
bool AllowUndefOrPoison) const {
437+
assert(getArgOperand(ArgNo)->getType()->isPointerTy() &&
438+
"Argument must be a pointer");
439+
if (paramHasAttr(ArgNo, Attribute::NonNull) &&
440+
(AllowUndefOrPoison || paramHasAttr(ArgNo, Attribute::NoUndef)))
441+
return true;
442+
443+
if (getParamDereferenceableBytes(ArgNo) > 0 &&
444+
!NullPointerIsDefined(
445+
getCaller(),
446+
getArgOperand(ArgNo)->getType()->getPointerAddressSpace()))
447+
return true;
448+
449+
return false;
450+
}
451+
435452
bool CallBase::hasFnAttrOnCalledFunction(Attribute::AttrKind Kind) const {
436453
if (auto *F = dyn_cast<Function>(getCalledOperand()))
437454
return F->getAttributes().hasFnAttr(Kind);

llvm/test/Analysis/ValueTracking/known-nonnull-at.ll

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,3 +220,70 @@ return:
220220
%retval.0 = phi ptr [ %1, %if.end ], [ null, %entry ]
221221
ret ptr %retval.0
222222
}
223+
224+
define i1 @test_known_nonnull_at_callsite(ptr %src) {
225+
; CHECK-LABEL: @test_known_nonnull_at_callsite(
226+
; CHECK-NEXT: entry:
227+
; CHECK-NEXT: call void @callee(ptr noundef nonnull [[SRC:%.*]])
228+
; CHECK-NEXT: ret i1 false
229+
;
230+
entry:
231+
call void @callee(ptr noundef nonnull %src)
232+
%nonnull = icmp eq ptr %src, null
233+
ret i1 %nonnull
234+
}
235+
236+
define i1 @test_known_nonnull_mixed(ptr %src) {
237+
; CHECK-LABEL: @test_known_nonnull_mixed(
238+
; CHECK-NEXT: entry:
239+
; CHECK-NEXT: call void @callee2(ptr nonnull [[SRC:%.*]])
240+
; CHECK-NEXT: ret i1 false
241+
;
242+
entry:
243+
call void @callee2(ptr nonnull %src)
244+
%nonnull = icmp eq ptr %src, null
245+
ret i1 %nonnull
246+
}
247+
248+
define i1 @test_known_nonnull_at_callsite_dereferenceable(ptr %src) {
249+
; CHECK-LABEL: @test_known_nonnull_at_callsite_dereferenceable(
250+
; CHECK-NEXT: entry:
251+
; CHECK-NEXT: call void @callee(ptr dereferenceable(1) [[SRC:%.*]])
252+
; CHECK-NEXT: ret i1 false
253+
;
254+
entry:
255+
call void @callee(ptr dereferenceable(1) %src)
256+
%nonnull = icmp eq ptr %src, null
257+
ret i1 %nonnull
258+
}
259+
260+
; Negative tests
261+
262+
define i1 @test_known_nonnull_at_callsite_without_noundef(ptr %src) {
263+
; CHECK-LABEL: @test_known_nonnull_at_callsite_without_noundef(
264+
; CHECK-NEXT: entry:
265+
; CHECK-NEXT: call void @callee(ptr nonnull [[SRC:%.*]])
266+
; CHECK-NEXT: [[NONNULL:%.*]] = icmp eq ptr [[SRC]], null
267+
; CHECK-NEXT: ret i1 [[NONNULL]]
268+
;
269+
entry:
270+
call void @callee(ptr nonnull %src)
271+
%nonnull = icmp eq ptr %src, null
272+
ret i1 %nonnull
273+
}
274+
275+
define i1 @test_known_nonnull_at_callsite_dereferenceable_null_is_defined(ptr %src) null_pointer_is_valid {
276+
; CHECK-LABEL: @test_known_nonnull_at_callsite_dereferenceable_null_is_defined(
277+
; CHECK-NEXT: entry:
278+
; CHECK-NEXT: call void @callee(ptr dereferenceable(1) [[SRC:%.*]])
279+
; CHECK-NEXT: [[NONNULL:%.*]] = icmp eq ptr [[SRC]], null
280+
; CHECK-NEXT: ret i1 [[NONNULL]]
281+
;
282+
entry:
283+
call void @callee(ptr dereferenceable(1) %src)
284+
%nonnull = icmp eq ptr %src, null
285+
ret i1 %nonnull
286+
}
287+
288+
declare void @callee(ptr)
289+
declare void @callee2(ptr noundef)

llvm/test/Transforms/InstCombine/align-addr.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ define void @test3(ptr sret(%struct.s) %a4) {
112112
; Check that the alignment is bumped up the alignment of the sret type.
113113
; CHECK-LABEL: @test3(
114114
; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr noundef nonnull align 4 dereferenceable(16) [[A4:%.*]], i8 0, i64 16, i1 false)
115-
; CHECK-NEXT: call void @use(ptr [[A4]])
115+
; CHECK-NEXT: call void @use(ptr nonnull [[A4]])
116116
; CHECK-NEXT: ret void
117117
;
118118
call void @llvm.memset.p0.i64(ptr %a4, i8 0, i64 16, i1 false)

llvm/test/Transforms/InstCombine/memset_chk-1.ll

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -92,15 +92,15 @@ define i32 @test_rauw(ptr %a, ptr %b, ptr %c) {
9292
; CHECK-NEXT: [[CALL49:%.*]] = call i64 @strlen(ptr noundef nonnull dereferenceable(1) [[A:%.*]])
9393
; CHECK-NEXT: [[ADD180:%.*]] = add i64 [[CALL49]], 1
9494
; CHECK-NEXT: [[YO107:%.*]] = call i64 @llvm.objectsize.i64.p0(ptr [[B:%.*]], i1 false, i1 false, i1 false)
95-
; CHECK-NEXT: [[CALL50:%.*]] = call ptr @__memmove_chk(ptr [[B]], ptr [[A]], i64 [[ADD180]], i64 [[YO107]])
95+
; CHECK-NEXT: [[CALL50:%.*]] = call ptr @__memmove_chk(ptr [[B]], ptr nonnull [[A]], i64 [[ADD180]], i64 [[YO107]])
9696
; CHECK-NEXT: [[STRLEN:%.*]] = call i64 @strlen(ptr noundef nonnull dereferenceable(1) [[B]])
9797
; CHECK-NEXT: [[STRCHR1:%.*]] = getelementptr inbounds i8, ptr [[B]], i64 [[STRLEN]]
9898
; CHECK-NEXT: [[D:%.*]] = load ptr, ptr [[C:%.*]], align 8
9999
; CHECK-NEXT: [[SUB182:%.*]] = ptrtoint ptr [[D]] to i64
100100
; CHECK-NEXT: [[SUB183:%.*]] = ptrtoint ptr [[B]] to i64
101101
; CHECK-NEXT: [[SUB184:%.*]] = sub i64 [[SUB182]], [[SUB183]]
102102
; CHECK-NEXT: [[ADD52_I_I:%.*]] = add nsw i64 [[SUB184]], 1
103-
; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 1 [[STRCHR1]], i8 0, i64 [[ADD52_I_I]], i1 false)
103+
; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr nonnull align 1 [[STRCHR1]], i8 0, i64 [[ADD52_I_I]], i1 false)
104104
; CHECK-NEXT: ret i32 4
105105
;
106106
entry:

llvm/test/Transforms/InstCombine/sprintf-1.ll

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ define i32 @test_simplify7(ptr %dst, ptr %str) {
103103
; NOSTPCPY-LABEL: @test_simplify7(
104104
; NOSTPCPY-NEXT: [[STRLEN:%.*]] = call i32 @strlen(ptr noundef nonnull dereferenceable(1) [[STR:%.*]])
105105
; NOSTPCPY-NEXT: [[LENINC:%.*]] = add i32 [[STRLEN]], 1
106-
; NOSTPCPY-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 1 [[DST:%.*]], ptr align 1 [[STR]], i32 [[LENINC]], i1 false)
106+
; NOSTPCPY-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 1 [[DST:%.*]], ptr nonnull align 1 [[STR]], i32 [[LENINC]], i1 false)
107107
; NOSTPCPY-NEXT: ret i32 [[STRLEN]]
108108
;
109109
%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) {
133133
; NOSTPCPY-LABEL: @test_simplify9(
134134
; NOSTPCPY-NEXT: [[STRLEN:%.*]] = call i32 @strlen(ptr noundef nonnull dereferenceable(1) [[STR:%.*]])
135135
; NOSTPCPY-NEXT: [[LENINC:%.*]] = add i32 [[STRLEN]], 1
136-
; NOSTPCPY-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 1 [[DST:%.*]], ptr align 1 [[STR]], i32 [[LENINC]], i1 false)
136+
; NOSTPCPY-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 1 [[DST:%.*]], ptr nonnull align 1 [[STR]], i32 [[LENINC]], i1 false)
137137
; NOSTPCPY-NEXT: ret i32 [[STRLEN]]
138138
;
139139
%r = call i32 (ptr, ptr, ...) @sprintf(ptr %dst, ptr @percent_s, ptr %str)

llvm/test/Transforms/InstCombine/stpncpy-1.ll

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -70,11 +70,11 @@ define void @fold_stpncpy_overlap(ptr %dst, i64 %n) {
7070
define void @call_stpncpy_overlap(ptr %dst, i64 %n) {
7171
; ANY-LABEL: @call_stpncpy_overlap(
7272
; ANY-NEXT: [[ES_2:%.*]] = call ptr @stpncpy(ptr noundef nonnull dereferenceable(1) [[DST:%.*]], ptr noundef nonnull dereferenceable(1) [[DST]], i64 2)
73-
; ANY-NEXT: call void @sink(ptr [[DST]], ptr [[ES_2]])
73+
; ANY-NEXT: call void @sink(ptr nonnull [[DST]], ptr [[ES_2]])
7474
; ANY-NEXT: [[ES_3:%.*]] = call ptr @stpncpy(ptr noundef nonnull dereferenceable(1) [[DST]], ptr noundef nonnull dereferenceable(1) [[DST]], i64 3)
75-
; ANY-NEXT: call void @sink(ptr [[DST]], ptr [[ES_3]])
76-
; ANY-NEXT: [[ES_N:%.*]] = call ptr @stpncpy(ptr [[DST]], ptr [[DST]], i64 [[N:%.*]])
77-
; ANY-NEXT: call void @sink(ptr [[DST]], ptr [[ES_N]])
75+
; ANY-NEXT: call void @sink(ptr nonnull [[DST]], ptr [[ES_3]])
76+
; ANY-NEXT: [[ES_N:%.*]] = call ptr @stpncpy(ptr nonnull [[DST]], ptr nonnull [[DST]], i64 [[N:%.*]])
77+
; ANY-NEXT: call void @sink(ptr nonnull [[DST]], ptr [[ES_N]])
7878
; ANY-NEXT: ret void
7979
;
8080
; Do not transform stpncpy(D, D, 2).
@@ -428,9 +428,9 @@ define void @fold_stpncpy_s(ptr %dst, ptr %src) {
428428
define void @call_stpncpy_s(ptr %dst, ptr %src, i64 %n) {
429429
; ANY-LABEL: @call_stpncpy_s(
430430
; ANY-NEXT: [[ES_2:%.*]] = call ptr @stpncpy(ptr noundef nonnull dereferenceable(1) [[DST:%.*]], ptr noundef nonnull dereferenceable(1) [[SRC:%.*]], i64 2)
431-
; ANY-NEXT: call void @sink(ptr [[DST]], ptr [[ES_2]])
432-
; ANY-NEXT: [[ES_N:%.*]] = call ptr @stpncpy(ptr [[DST]], ptr [[SRC]], i64 [[N:%.*]])
433-
; ANY-NEXT: call void @sink(ptr [[DST]], ptr [[ES_N]])
431+
; ANY-NEXT: call void @sink(ptr nonnull [[DST]], ptr [[ES_2]])
432+
; ANY-NEXT: [[ES_N:%.*]] = call ptr @stpncpy(ptr nonnull [[DST]], ptr nonnull [[SRC]], i64 [[N:%.*]])
433+
; ANY-NEXT: call void @sink(ptr nonnull [[DST]], ptr [[ES_N]])
434434
; ANY-NEXT: ret void
435435
;
436436
; Do not transform stpncpy(D, S, 2). Both *D and *S must be derefernceable

llvm/test/Transforms/InstCombine/strlcpy-1.ll

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -229,18 +229,18 @@ define void @fold_strlcpy_s_0(ptr %dst, ptr %s, i64 %n) {
229229
define void @call_strlcpy_s0_n(ptr %dst, ptr %s, i64 %n) {
230230
; ANY-LABEL: @call_strlcpy_s0_n(
231231
; ANY-NEXT: [[NS_2:%.*]] = call i64 @strlcpy(ptr noundef nonnull dereferenceable(1) [[DST:%.*]], ptr noundef nonnull dereferenceable(1) [[S:%.*]], i64 2)
232-
; ANY-NEXT: call void @sink(ptr [[DST]], i64 [[NS_2]])
233-
; ANY-NEXT: [[NS_N:%.*]] = call i64 @strlcpy(ptr [[DST]], ptr noundef nonnull dereferenceable(1) [[S]], i64 [[N:%.*]])
234-
; ANY-NEXT: call void @sink(ptr [[DST]], i64 [[NS_N]])
232+
; ANY-NEXT: call void @sink(ptr nonnull [[DST]], i64 [[NS_2]])
233+
; ANY-NEXT: [[NS_N:%.*]] = call i64 @strlcpy(ptr nonnull [[DST]], ptr noundef nonnull dereferenceable(1) [[S]], i64 [[N:%.*]])
234+
; ANY-NEXT: call void @sink(ptr nonnull [[DST]], i64 [[NS_N]])
235235
; ANY-NEXT: [[NZ:%.*]] = or i64 [[N]], 1
236236
; ANY-NEXT: [[NS_NZ:%.*]] = call i64 @strlcpy(ptr noundef nonnull dereferenceable(1) [[DST]], ptr noundef nonnull dereferenceable(1) [[S]], i64 [[NZ]])
237-
; ANY-NEXT: call void @sink(ptr [[DST]], i64 [[NS_NZ]])
238-
; ANY-NEXT: [[NS0_N:%.*]] = call i64 @strlcpy(ptr [[DST]], ptr noundef nonnull dereferenceable(1) getelementptr inbounds nuw (i8, ptr @s4, i64 4), i64 [[N]])
239-
; ANY-NEXT: call void @sink(ptr [[DST]], i64 [[NS0_N]])
240-
; ANY-NEXT: [[NS1_N:%.*]] = call i64 @strlcpy(ptr [[DST]], ptr noundef nonnull dereferenceable(1) getelementptr inbounds nuw (i8, ptr @s4, i64 3), i64 [[N]])
241-
; ANY-NEXT: call void @sink(ptr [[DST]], i64 [[NS1_N]])
242-
; ANY-NEXT: [[NS4_N:%.*]] = call i64 @strlcpy(ptr [[DST]], ptr noundef nonnull dereferenceable(1) @s4, i64 [[N]])
243-
; ANY-NEXT: call void @sink(ptr [[DST]], i64 [[NS4_N]])
237+
; ANY-NEXT: call void @sink(ptr nonnull [[DST]], i64 [[NS_NZ]])
238+
; 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]])
239+
; ANY-NEXT: call void @sink(ptr nonnull [[DST]], i64 [[NS0_N]])
240+
; 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]])
241+
; ANY-NEXT: call void @sink(ptr nonnull [[DST]], i64 [[NS1_N]])
242+
; ANY-NEXT: [[NS4_N:%.*]] = call i64 @strlcpy(ptr nonnull [[DST]], ptr noundef nonnull dereferenceable(1) @s4, i64 [[N]])
243+
; ANY-NEXT: call void @sink(ptr nonnull [[DST]], i64 [[NS4_N]])
244244
; ANY-NEXT: ret void
245245
;
246246
%ns_2 = call i64 @strlcpy(ptr %dst, ptr %s, i64 2)

llvm/test/Transforms/InstCombine/strncpy-4.ll

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -45,11 +45,11 @@ define void @fold_strncpy_overlap(ptr %dst, i64 %n) {
4545
define void @call_strncpy_overlap(ptr %dst, i64 %n) {
4646
; CHECK-LABEL: @call_strncpy_overlap(
4747
; CHECK-NEXT: [[ED_2:%.*]] = call ptr @strncpy(ptr noundef nonnull dereferenceable(1) [[DST:%.*]], ptr noundef nonnull dereferenceable(1) [[DST]], i64 2)
48-
; CHECK-NEXT: call void @sink(ptr [[DST]], ptr [[ED_2]])
48+
; CHECK-NEXT: call void @sink(ptr nonnull [[DST]], ptr [[ED_2]])
4949
; CHECK-NEXT: [[ED_3:%.*]] = call ptr @strncpy(ptr noundef nonnull dereferenceable(1) [[DST]], ptr noundef nonnull dereferenceable(1) [[DST]], i64 3)
50-
; CHECK-NEXT: call void @sink(ptr [[DST]], ptr [[ED_3]])
51-
; CHECK-NEXT: [[ED_N:%.*]] = call ptr @strncpy(ptr [[DST]], ptr [[DST]], i64 [[N:%.*]])
52-
; CHECK-NEXT: call void @sink(ptr [[DST]], ptr [[ED_N]])
50+
; CHECK-NEXT: call void @sink(ptr nonnull [[DST]], ptr [[ED_3]])
51+
; CHECK-NEXT: [[ED_N:%.*]] = call ptr @strncpy(ptr nonnull [[DST]], ptr nonnull [[DST]], i64 [[N:%.*]])
52+
; CHECK-NEXT: call void @sink(ptr nonnull [[DST]], ptr [[ED_N]])
5353
; CHECK-NEXT: ret void
5454
;
5555

@@ -141,11 +141,11 @@ define void @fold_strncpy_s(ptr %dst, ptr %src, i64 %n) {
141141
define void @call_strncpy_s(ptr %dst, ptr %src, i64 %n) {
142142
; CHECK-LABEL: @call_strncpy_s(
143143
; CHECK-NEXT: [[ED_2:%.*]] = call ptr @strncpy(ptr noundef nonnull dereferenceable(1) [[DST:%.*]], ptr noundef nonnull dereferenceable(1) [[SRC:%.*]], i64 2)
144-
; CHECK-NEXT: call void @sink(ptr [[DST]], ptr [[ED_2]])
144+
; CHECK-NEXT: call void @sink(ptr nonnull [[DST]], ptr [[ED_2]])
145145
; CHECK-NEXT: [[ED_9:%.*]] = call ptr @strncpy(ptr noundef nonnull dereferenceable(1) [[DST]], ptr noundef nonnull dereferenceable(1) [[SRC]], i64 9)
146-
; CHECK-NEXT: call void @sink(ptr [[DST]], ptr [[ED_9]])
147-
; CHECK-NEXT: [[ED_N:%.*]] = call ptr @strncpy(ptr [[DST]], ptr [[SRC]], i64 [[N:%.*]])
148-
; CHECK-NEXT: call void @sink(ptr [[DST]], ptr [[ED_N]])
146+
; CHECK-NEXT: call void @sink(ptr nonnull [[DST]], ptr [[ED_9]])
147+
; CHECK-NEXT: [[ED_N:%.*]] = call ptr @strncpy(ptr nonnull [[DST]], ptr nonnull [[SRC]], i64 [[N:%.*]])
148+
; CHECK-NEXT: call void @sink(ptr nonnull [[DST]], ptr [[ED_N]])
149149
; CHECK-NEXT: ret void
150150
;
151151
; Do not transform strncpy(D, S, 2) when S is unknown. Both *D and *S must

llvm/test/Transforms/InstCombine/strstr-1.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ define ptr @test_simplify4(ptr %str) {
5858
define i1 @test_simplify5(ptr %str, ptr %pat) {
5959
; CHECK-LABEL: @test_simplify5(
6060
; CHECK-NEXT: [[STRLEN:%.*]] = call i64 @strlen(ptr noundef nonnull dereferenceable(1) [[PAT:%.*]])
61-
; CHECK-NEXT: [[STRNCMP:%.*]] = call i32 @strncmp(ptr [[STR:%.*]], ptr [[PAT]], i64 [[STRLEN]])
61+
; CHECK-NEXT: [[STRNCMP:%.*]] = call i32 @strncmp(ptr [[STR:%.*]], ptr nonnull [[PAT]], i64 [[STRLEN]])
6262
; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32 [[STRNCMP]], 0
6363
; CHECK-NEXT: ret i1 [[CMP1]]
6464
;

llvm/test/Transforms/InstSimplify/known-non-zero-opaque-ptrs.ll

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,10 @@
44
declare void @zero_args()
55
declare void @two_args(ptr, ptr)
66

7-
; TODO: Could be non-null based on call-site attributes.
87
define i1 @test_zero_args_nonnull(ptr %p) {
98
; CHECK-LABEL: @test_zero_args_nonnull(
109
; CHECK-NEXT: call void @zero_args(ptr noundef nonnull [[P:%.*]])
11-
; CHECK-NEXT: [[C:%.*]] = icmp ne ptr [[P]], null
12-
; CHECK-NEXT: ret i1 [[C]]
10+
; CHECK-NEXT: ret i1 true
1311
;
1412
call void @zero_args(ptr nonnull noundef %p)
1513
%c = icmp ne ptr %p, null
@@ -27,12 +25,10 @@ define i1 @test_zero_args_maybe_null(ptr %p) {
2725
ret i1 %c
2826
}
2927

30-
; TODO: Could be non-null based on call-site attributes.
3128
define i1 @test_two_args_nonnull(ptr %p) {
3229
; CHECK-LABEL: @test_two_args_nonnull(
3330
; CHECK-NEXT: call void @two_args(ptr noundef nonnull [[P:%.*]])
34-
; CHECK-NEXT: [[C:%.*]] = icmp ne ptr [[P]], null
35-
; CHECK-NEXT: ret i1 [[C]]
31+
; CHECK-NEXT: ret i1 true
3632
;
3733
call void @two_args(ptr nonnull noundef %p)
3834
%c = icmp ne ptr %p, null

0 commit comments

Comments
 (0)