Skip to content

Commit fc76569

Browse files
danlark1nikic
authored andcommitted
[ValueTracking] Add tests for non-null check after load/store; NFC
Tests for D71177.
1 parent b01012b commit fc76569

File tree

1 file changed

+110
-17
lines changed

1 file changed

+110
-17
lines changed

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

Lines changed: 110 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ declare void @bar(i8* %a, i8* nonnull %b)
77

88
define i1 @caller1(i8* %x, i8* %y) {
99
; CHECK-LABEL: @caller1(
10-
; CHECK-NEXT: call void @bar(i8* %x, i8* %y)
10+
; CHECK-NEXT: call void @bar(i8* [[X:%.*]], i8* [[Y:%.*]])
1111
; CHECK-NEXT: ret i1 false
1212
;
1313
call void @bar(i8* %x, i8* %y)
@@ -19,8 +19,8 @@ define i1 @caller1(i8* %x, i8* %y) {
1919

2020
define i1 @caller2(i8* %x, i8* %y) {
2121
; CHECK-LABEL: @caller2(
22-
; CHECK-NEXT: call void @bar(i8* %y, i8* %x)
23-
; CHECK-NEXT: [[NULL_CHECK:%.*]] = icmp eq i8* %y, null
22+
; CHECK-NEXT: call void @bar(i8* [[Y:%.*]], i8* [[X:%.*]])
23+
; CHECK-NEXT: [[NULL_CHECK:%.*]] = icmp eq i8* [[Y]], null
2424
; CHECK-NEXT: ret i1 [[NULL_CHECK]]
2525
;
2626
call void @bar(i8* %y, i8* %x)
@@ -32,7 +32,7 @@ define i1 @caller2(i8* %x, i8* %y) {
3232

3333
define i1 @caller3(i8* %x, i8* %y) {
3434
; CHECK-LABEL: @caller3(
35-
; CHECK-NEXT: call void @bar(i8* %x, i8* %y)
35+
; CHECK-NEXT: call void @bar(i8* [[X:%.*]], i8* [[Y:%.*]])
3636
; CHECK-NEXT: ret i1 true
3737
;
3838
call void @bar(i8* %x, i8* %y)
@@ -44,8 +44,8 @@ define i1 @caller3(i8* %x, i8* %y) {
4444

4545
define i1 @caller4(i8* %x, i8* %y) {
4646
; CHECK-LABEL: @caller4(
47-
; CHECK-NEXT: [[NULL_CHECK:%.*]] = icmp ne i8* %y, null
48-
; CHECK-NEXT: call void @bar(i8* %x, i8* %y)
47+
; CHECK-NEXT: [[NULL_CHECK:%.*]] = icmp ne i8* [[Y:%.*]], null
48+
; CHECK-NEXT: call void @bar(i8* [[X:%.*]], i8* [[Y]])
4949
; CHECK-NEXT: ret i1 [[NULL_CHECK]]
5050
;
5151
%null_check = icmp ne i8* %y, null
@@ -57,12 +57,12 @@ define i1 @caller4(i8* %x, i8* %y) {
5757

5858
define i1 @caller5(i8* %x, i8* %y) {
5959
; CHECK-LABEL: @caller5(
60-
; CHECK-NEXT: [[NULL_CHECK:%.*]] = icmp eq i8* %y, null
61-
; CHECK-NEXT: br i1 [[NULL_CHECK]], label %t, label %f
60+
; CHECK-NEXT: [[NULL_CHECK:%.*]] = icmp eq i8* [[Y:%.*]], null
61+
; CHECK-NEXT: br i1 [[NULL_CHECK]], label [[T:%.*]], label [[F:%.*]]
6262
; CHECK: t:
6363
; CHECK-NEXT: ret i1 [[NULL_CHECK]]
6464
; CHECK: f:
65-
; CHECK-NEXT: call void @bar(i8* %x, i8* %y)
65+
; CHECK-NEXT: call void @bar(i8* [[X:%.*]], i8* [[Y]])
6666
; CHECK-NEXT: ret i1 [[NULL_CHECK]]
6767
;
6868
%null_check = icmp eq i8* %y, null
@@ -80,42 +80,135 @@ declare i32 @esfp(...)
8080

8181
define i1 @caller6(i8* %x, i8* %y) personality i8* bitcast (i32 (...)* @esfp to i8*){
8282
; CHECK-LABEL: @caller6(
83-
; CHECK-NEXT: invoke void @bar(i8* %x, i8* nonnull %y)
84-
; CHECK-NEXT: to label %cont unwind label %exc
83+
; CHECK-NEXT: invoke void @bar(i8* [[X:%.*]], i8* nonnull [[Y:%.*]])
84+
; CHECK-NEXT: to label [[CONT:%.*]] unwind label [[EXC:%.*]]
8585
; CHECK: cont:
8686
; CHECK-NEXT: ret i1 false
87+
; CHECK: exc:
88+
; CHECK-NEXT: [[LP:%.*]] = landingpad { i8*, i32 }
89+
; CHECK-NEXT: filter [0 x i8*] zeroinitializer
90+
; CHECK-NEXT: unreachable
8791
;
8892
invoke void @bar(i8* %x, i8* nonnull %y)
89-
to label %cont unwind label %exc
93+
to label %cont unwind label %exc
9094

9195
cont:
9296
%null_check = icmp eq i8* %y, null
9397
ret i1 %null_check
9498

9599
exc:
96100
%lp = landingpad { i8*, i32 }
97-
filter [0 x i8*] zeroinitializer
101+
filter [0 x i8*] zeroinitializer
98102
unreachable
99103
}
100104

101105
declare i8* @returningPtr(i8* returned %p)
102106

103107
define i1 @nonnullReturnTest(i8* nonnull %x) {
104108
; CHECK-LABEL: @nonnullReturnTest(
105-
; CHECK-NEXT: %x2 = call i8* @returningPtr(i8* %x)
109+
; CHECK-NEXT: [[X2:%.*]] = call i8* @returningPtr(i8* [[X:%.*]])
106110
; CHECK-NEXT: ret i1 false
111+
;
107112
%x2 = call i8* @returningPtr(i8* %x)
108113
%null_check = icmp eq i8* %x2, null
109114
ret i1 %null_check
110115
}
111116

112117
define i1 @unknownReturnTest(i8* %x) {
113118
; CHECK-LABEL: @unknownReturnTest(
114-
; CHECK-NEXT: %x2 = call i8* @returningPtr(i8* %x)
115-
; CHECK-NEXT: %null_check = icmp eq i8* %x2, null
116-
; CHECK-NEXT: ret i1 %null_check
119+
; CHECK-NEXT: [[X2:%.*]] = call i8* @returningPtr(i8* [[X:%.*]])
120+
; CHECK-NEXT: [[NULL_CHECK:%.*]] = icmp eq i8* [[X2]], null
121+
; CHECK-NEXT: ret i1 [[NULL_CHECK]]
122+
;
117123
%x2 = call i8* @returningPtr(i8* %x)
118124
%null_check = icmp eq i8* %x2, null
119125
ret i1 %null_check
120126
}
121127

128+
; TODO: Make sure that if load/store happened, the pointer is nonnull.
129+
130+
define i32 @test_null_after_store(i32* %0) {
131+
; CHECK-LABEL: @test_null_after_store(
132+
; CHECK-NEXT: store i32 123, i32* [[TMP0:%.*]], align 4
133+
; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i32* [[TMP0]], null
134+
; CHECK-NEXT: [[TMP3:%.*]] = select i1 [[TMP2]], i32 1, i32 2
135+
; CHECK-NEXT: ret i32 [[TMP3]]
136+
;
137+
store i32 123, i32* %0, align 4
138+
%2 = icmp eq i32* %0, null
139+
%3 = select i1 %2, i32 1, i32 2
140+
ret i32 %3
141+
}
142+
143+
define i32 @test_null_after_load(i32* %0) {
144+
; CHECK-LABEL: @test_null_after_load(
145+
; CHECK-NEXT: [[TMP2:%.*]] = load i32, i32* [[TMP0:%.*]], align 4
146+
; CHECK-NEXT: [[TMP3:%.*]] = icmp eq i32* [[TMP0]], null
147+
; CHECK-NEXT: [[TMP4:%.*]] = select i1 [[TMP3]], i32 [[TMP2]], i32 1
148+
; CHECK-NEXT: ret i32 [[TMP4]]
149+
;
150+
%2 = load i32, i32* %0, align 4
151+
%3 = icmp eq i32* %0, null
152+
%4 = select i1 %3, i32 %2, i32 1
153+
ret i32 %4
154+
}
155+
156+
; Make sure that different address space does not affect null pointer check.
157+
158+
define i32 @test_null_after_store_addrspace(i32 addrspace(1)* %0) {
159+
; CHECK-LABEL: @test_null_after_store_addrspace(
160+
; CHECK-NEXT: store i32 123, i32 addrspace(1)* [[TMP0:%.*]], align 4
161+
; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i32 addrspace(1)* [[TMP0]], null
162+
; CHECK-NEXT: [[TMP3:%.*]] = select i1 [[TMP2]], i32 1, i32 2
163+
; CHECK-NEXT: ret i32 [[TMP3]]
164+
;
165+
store i32 123, i32 addrspace(1)* %0, align 4
166+
%2 = icmp eq i32 addrspace(1)* %0, null
167+
%3 = select i1 %2, i32 1, i32 2
168+
ret i32 %3
169+
}
170+
171+
define i32 @test_null_after_load_addrspace(i32 addrspace(1)* %0) {
172+
; CHECK-LABEL: @test_null_after_load_addrspace(
173+
; CHECK-NEXT: [[TMP2:%.*]] = load i32, i32 addrspace(1)* [[TMP0:%.*]], align 4
174+
; CHECK-NEXT: [[TMP3:%.*]] = icmp eq i32 addrspace(1)* [[TMP0]], null
175+
; CHECK-NEXT: [[TMP4:%.*]] = select i1 [[TMP3]], i32 [[TMP2]], i32 1
176+
; CHECK-NEXT: ret i32 [[TMP4]]
177+
;
178+
; CHECK-NEXT ret i32 %4
179+
%2 = load i32, i32 addrspace(1)* %0, align 4
180+
%3 = icmp eq i32 addrspace(1)* %0, null
181+
%4 = select i1 %3, i32 %2, i32 1
182+
ret i32 %4
183+
}
184+
185+
; Make sure if store happened after the check, nullptr check is not removed.
186+
187+
declare i8* @func(i64)
188+
189+
define i8* @test_load_store_after_check(i8* %0) {
190+
; CHECK-LABEL: @test_load_store_after_check(
191+
; CHECK-NEXT: entry:
192+
; CHECK-NEXT: [[TMP1:%.*]] = call i8* @func(i64 0)
193+
; CHECK-NEXT: [[NULL_CHECK:%.*]] = icmp eq i8* [[TMP1]], null
194+
; CHECK-NEXT: br i1 [[NULL_CHECK]], label [[RETURN:%.*]], label [[IF_END:%.*]]
195+
; CHECK: if.end:
196+
; CHECK-NEXT: store i8 7, i8* [[TMP1]]
197+
; CHECK-NEXT: br label [[RETURN]]
198+
; CHECK: return:
199+
; CHECK-NEXT: [[RETVAL_0:%.*]] = phi i8* [ [[TMP1]], [[IF_END]] ], [ null, [[ENTRY:%.*]] ]
200+
; CHECK-NEXT: ret i8* [[RETVAL_0]]
201+
;
202+
entry:
203+
%1 = call i8* @func(i64 0)
204+
%null_check = icmp eq i8* %1, null
205+
br i1 %null_check, label %return, label %if.end
206+
207+
if.end:
208+
store i8 7, i8* %1
209+
br label %return
210+
211+
return:
212+
%retval.0 = phi i8* [ %1, %if.end ], [ null, %entry ]
213+
ret i8* %retval.0
214+
}

0 commit comments

Comments
 (0)