[docs] Add LICENSE.txt to the root of the mono-repo
[llvm-project.git] / llvm / test / Analysis / ValueTracking / known-nonnull-at.ll
blob41613136f89f8281c24feb5625769fa2ac026b3d
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)
7 ; 'y' must be nonnull.
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
16   ret i1 %null_check
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
29   ret i1 %null_check
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
42   ret i1 %null_check
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
54   ret i1 %null_check
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)
67   ret i1 %null_check
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:%.*]]
76 ; CHECK:       t:
77 ; CHECK-NEXT:    ret i1 [[NULL_CHECK]]
78 ; CHECK:       f:
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
85   ret i1 %null_check
87   call void @bar(i8* %x, i8* %y)
88   ret i1 %null_check
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:%.*]]
99 ; CHECK:       cont:
100 ; CHECK-NEXT:    ret i1 false
101 ; CHECK:       exc:
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
109 cont:
110   %null_check = icmp eq i8* %y, null
111   ret i1 %null_check
113 exc:
114   %lp = landingpad { i8*, i32 }
115   filter [0 x i8*] zeroinitializer
116   unreachable
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
128   ret i1 %null_check
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
139   ret i1 %null_check
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
152   ret i32 %3
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
162   ret i32 %4
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
177   ret i32 %3
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
190   ret i32 %4
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(
199 ; CHECK-NEXT:  entry:
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:%.*]]
203 ; CHECK:       if.end:
204 ; CHECK-NEXT:    store i8 7, i8* [[TMP1]], align 1
205 ; CHECK-NEXT:    br label [[RETURN]]
206 ; CHECK:       return:
207 ; CHECK-NEXT:    [[RETVAL_0:%.*]] = phi i8* [ [[TMP1]], [[IF_END]] ], [ null, [[ENTRY:%.*]] ]
208 ; CHECK-NEXT:    ret i8* [[RETVAL_0]]
210 entry:
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
215 if.end:
216   store i8 7, i8* %1
217   br label %return
219 return:
220   %retval.0 = phi i8* [ %1, %if.end ], [ null, %entry ]
221   ret i8* %retval.0