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