1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt -S -instsimplify < %s | FileCheck %s
4 declare void @bar(i8* %a, i8* nonnull noundef %b)
5 declare void @bar_without_noundef(i8* %a, i8* nonnull %b)
9 define i1 @caller1(i8* %x, i8* %y) {
10 ; CHECK-LABEL: @caller1(
11 ; CHECK-NEXT: call void @bar(i8* [[X:%.*]], i8* [[Y:%.*]])
12 ; CHECK-NEXT: ret i1 false
14 call void @bar(i8* %x, i8* %y)
15 %null_check = icmp eq i8* %y, null
19 ; Don't know anything about 'y'.
21 define i1 @caller1_maybepoison(i8* %x, i8* %y) {
22 ; CHECK-LABEL: @caller1_maybepoison(
23 ; CHECK-NEXT: call void @bar_without_noundef(i8* [[X:%.*]], i8* [[Y:%.*]])
24 ; CHECK-NEXT: [[NULL_CHECK:%.*]] = icmp eq i8* [[Y]], null
25 ; CHECK-NEXT: ret i1 [[NULL_CHECK]]
27 call void @bar_without_noundef(i8* %x, i8* %y)
28 %null_check = icmp eq i8* %y, null
32 ; Don't know anything about 'y'.
34 define i1 @caller2(i8* %x, i8* %y) {
35 ; CHECK-LABEL: @caller2(
36 ; CHECK-NEXT: call void @bar(i8* [[Y:%.*]], i8* [[X:%.*]])
37 ; CHECK-NEXT: [[NULL_CHECK:%.*]] = icmp eq i8* [[Y]], null
38 ; CHECK-NEXT: ret i1 [[NULL_CHECK]]
40 call void @bar(i8* %y, i8* %x)
41 %null_check = icmp eq i8* %y, null
45 ; 'y' must be nonnull.
47 define i1 @caller3(i8* %x, i8* %y) {
48 ; CHECK-LABEL: @caller3(
49 ; CHECK-NEXT: call void @bar(i8* [[X:%.*]], i8* [[Y:%.*]])
50 ; CHECK-NEXT: ret i1 true
52 call void @bar(i8* %x, i8* %y)
53 %null_check = icmp ne i8* %y, null
57 ; FIXME: The call is guaranteed to execute, so 'y' must be nonnull throughout.
59 define i1 @caller4(i8* %x, i8* %y) {
60 ; CHECK-LABEL: @caller4(
61 ; CHECK-NEXT: [[NULL_CHECK:%.*]] = icmp ne i8* [[Y:%.*]], null
62 ; CHECK-NEXT: call void @bar(i8* [[X:%.*]], i8* [[Y]])
63 ; CHECK-NEXT: ret i1 [[NULL_CHECK]]
65 %null_check = icmp ne i8* %y, null
66 call void @bar(i8* %x, i8* %y)
70 ; The call to bar() does not dominate the null check, so no change.
72 define i1 @caller5(i8* %x, i8* %y) {
73 ; CHECK-LABEL: @caller5(
74 ; CHECK-NEXT: [[NULL_CHECK:%.*]] = icmp eq i8* [[Y:%.*]], null
75 ; CHECK-NEXT: br i1 [[NULL_CHECK]], label [[T:%.*]], label [[F:%.*]]
77 ; CHECK-NEXT: ret i1 [[NULL_CHECK]]
79 ; CHECK-NEXT: call void @bar(i8* [[X:%.*]], i8* [[Y]])
80 ; CHECK-NEXT: ret i1 [[NULL_CHECK]]
82 %null_check = icmp eq i8* %y, null
83 br i1 %null_check, label %t, label %f
87 call void @bar(i8* %x, i8* %y)
91 ; Make sure that an invoke works similarly to a call.
93 declare i32 @esfp(...)
95 define i1 @caller6(i8* %x, i8* %y) personality i8* bitcast (i32 (...)* @esfp to i8*){
96 ; CHECK-LABEL: @caller6(
97 ; CHECK-NEXT: invoke void @bar(i8* [[X:%.*]], i8* nonnull [[Y:%.*]])
98 ; CHECK-NEXT: to label [[CONT:%.*]] unwind label [[EXC:%.*]]
100 ; CHECK-NEXT: ret i1 false
102 ; CHECK-NEXT: [[LP:%.*]] = landingpad { i8*, i32 }
103 ; CHECK-NEXT: filter [0 x i8*] zeroinitializer
104 ; CHECK-NEXT: unreachable
106 invoke void @bar(i8* %x, i8* nonnull %y)
107 to label %cont unwind label %exc
110 %null_check = icmp eq i8* %y, null
114 %lp = landingpad { i8*, i32 }
115 filter [0 x i8*] zeroinitializer
119 declare i8* @returningPtr(i8* returned %p)
121 define i1 @nonnullReturnTest(i8* nonnull %x) {
122 ; CHECK-LABEL: @nonnullReturnTest(
123 ; CHECK-NEXT: [[X2:%.*]] = call i8* @returningPtr(i8* [[X:%.*]])
124 ; CHECK-NEXT: ret i1 false
126 %x2 = call i8* @returningPtr(i8* %x)
127 %null_check = icmp eq i8* %x2, null
131 define i1 @unknownReturnTest(i8* %x) {
132 ; CHECK-LABEL: @unknownReturnTest(
133 ; CHECK-NEXT: [[X2:%.*]] = call i8* @returningPtr(i8* [[X:%.*]])
134 ; CHECK-NEXT: [[NULL_CHECK:%.*]] = icmp eq i8* [[X2]], null
135 ; CHECK-NEXT: ret i1 [[NULL_CHECK]]
137 %x2 = call i8* @returningPtr(i8* %x)
138 %null_check = icmp eq i8* %x2, null
142 ; Make sure that if load/store happened, the pointer is nonnull.
144 define i32 @test_null_after_store(i32* %0) {
145 ; CHECK-LABEL: @test_null_after_store(
146 ; CHECK-NEXT: store i32 123, i32* [[TMP0:%.*]], align 4
147 ; CHECK-NEXT: ret i32 2
149 store i32 123, i32* %0, align 4
150 %2 = icmp eq i32* %0, null
151 %3 = select i1 %2, i32 1, i32 2
155 define i32 @test_null_after_load(i32* %0) {
156 ; CHECK-LABEL: @test_null_after_load(
157 ; CHECK-NEXT: ret i32 1
159 %2 = load i32, i32* %0, align 4
160 %3 = icmp eq i32* %0, null
161 %4 = select i1 %3, i32 %2, i32 1
165 ; Make sure that different address space does not affect null pointer check.
167 define i32 @test_null_after_store_addrspace(i32 addrspace(1)* %0) {
168 ; CHECK-LABEL: @test_null_after_store_addrspace(
169 ; CHECK-NEXT: store i32 123, i32 addrspace(1)* [[TMP0:%.*]], align 4
170 ; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i32 addrspace(1)* [[TMP0]], null
171 ; CHECK-NEXT: [[TMP3:%.*]] = select i1 [[TMP2]], i32 1, i32 2
172 ; CHECK-NEXT: ret i32 [[TMP3]]
174 store i32 123, i32 addrspace(1)* %0, align 4
175 %2 = icmp eq i32 addrspace(1)* %0, null
176 %3 = select i1 %2, i32 1, i32 2
180 define i32 @test_null_after_load_addrspace(i32 addrspace(1)* %0) {
181 ; CHECK-LABEL: @test_null_after_load_addrspace(
182 ; CHECK-NEXT: [[TMP2:%.*]] = load i32, i32 addrspace(1)* [[TMP0:%.*]], align 4
183 ; CHECK-NEXT: [[TMP3:%.*]] = icmp eq i32 addrspace(1)* [[TMP0]], null
184 ; CHECK-NEXT: [[TMP4:%.*]] = select i1 [[TMP3]], i32 [[TMP2]], i32 1
185 ; CHECK-NEXT: ret i32 [[TMP4]]
187 %2 = load i32, i32 addrspace(1)* %0, align 4
188 %3 = icmp eq i32 addrspace(1)* %0, null
189 %4 = select i1 %3, i32 %2, i32 1
193 ; Make sure if store happened after the check, nullptr check is not removed.
195 declare i8* @func(i64)
197 define i8* @test_load_store_after_check(i8* %0) {
198 ; CHECK-LABEL: @test_load_store_after_check(
200 ; CHECK-NEXT: [[TMP1:%.*]] = call i8* @func(i64 0)
201 ; CHECK-NEXT: [[NULL_CHECK:%.*]] = icmp eq i8* [[TMP1]], null
202 ; CHECK-NEXT: br i1 [[NULL_CHECK]], label [[RETURN:%.*]], label [[IF_END:%.*]]
204 ; CHECK-NEXT: store i8 7, i8* [[TMP1]], align 1
205 ; CHECK-NEXT: br label [[RETURN]]
207 ; CHECK-NEXT: [[RETVAL_0:%.*]] = phi i8* [ [[TMP1]], [[IF_END]] ], [ null, [[ENTRY:%.*]] ]
208 ; CHECK-NEXT: ret i8* [[RETVAL_0]]
211 %1 = call i8* @func(i64 0)
212 %null_check = icmp eq i8* %1, null
213 br i1 %null_check, label %return, label %if.end
220 %retval.0 = phi i8* [ %1, %if.end ], [ null, %entry ]