blob: b580cdcea7edc87d72f53ea348bccec9bded344e [file] [log] [blame]
Eric Christophercee313d2019-04-17 04:52:47 +00001; RUN: opt < %s -functionattrs -S | FileCheck %s
2; RUN: opt < %s -passes=function-attrs -S | FileCheck %s
3
4@g = global i32* null ; <i32**> [#uses=1]
5
6; CHECK: define i32* @c1(i32* readnone returned %q)
7define i32* @c1(i32* %q) {
8 ret i32* %q
9}
10
11; CHECK: define void @c2(i32* %q)
12; It would also be acceptable to mark %q as readnone. Update @c3 too.
13define void @c2(i32* %q) {
14 store i32* %q, i32** @g
15 ret void
16}
17
18; CHECK: define void @c3(i32* %q)
19define void @c3(i32* %q) {
20 call void @c2(i32* %q)
21 ret void
22}
23
24; CHECK: define i1 @c4(i32* %q, i32 %bitno)
25define i1 @c4(i32* %q, i32 %bitno) {
26 %tmp = ptrtoint i32* %q to i32
27 %tmp2 = lshr i32 %tmp, %bitno
28 %bit = trunc i32 %tmp2 to i1
29 br i1 %bit, label %l1, label %l0
30l0:
31 ret i1 0 ; escaping value not caught by def-use chaining.
32l1:
33 ret i1 1 ; escaping value not caught by def-use chaining.
34}
35
36@lookup_table = global [2 x i1] [ i1 0, i1 1 ]
37
38; CHECK: define i1 @c5(i32* %q, i32 %bitno)
39define i1 @c5(i32* %q, i32 %bitno) {
40 %tmp = ptrtoint i32* %q to i32
41 %tmp2 = lshr i32 %tmp, %bitno
42 %bit = and i32 %tmp2, 1
43 ; subtle escape mechanism follows
44 %lookup = getelementptr [2 x i1], [2 x i1]* @lookup_table, i32 0, i32 %bit
45 %val = load i1, i1* %lookup
46 ret i1 %val
47}
48
49declare void @throw_if_bit_set(i8*, i8) readonly
50
51; CHECK: define i1 @c6(i8* readonly %q, i8 %bit)
52define i1 @c6(i8* %q, i8 %bit) personality i32 (...)* @__gxx_personality_v0 {
53 invoke void @throw_if_bit_set(i8* %q, i8 %bit)
54 to label %ret0 unwind label %ret1
55ret0:
56 ret i1 0
57ret1:
58 %exn = landingpad {i8*, i32}
59 cleanup
60 ret i1 1
61}
62
63declare i32 @__gxx_personality_v0(...)
64
65define i1* @lookup_bit(i32* %q, i32 %bitno) readnone nounwind {
66 %tmp = ptrtoint i32* %q to i32
67 %tmp2 = lshr i32 %tmp, %bitno
68 %bit = and i32 %tmp2, 1
69 %lookup = getelementptr [2 x i1], [2 x i1]* @lookup_table, i32 0, i32 %bit
70 ret i1* %lookup
71}
72
73; CHECK: define i1 @c7(i32* readonly %q, i32 %bitno)
74define i1 @c7(i32* %q, i32 %bitno) {
75 %ptr = call i1* @lookup_bit(i32* %q, i32 %bitno)
76 %val = load i1, i1* %ptr
77 ret i1 %val
78}
79
80
81; CHECK: define i32 @nc1(i32* %q, i32* nocapture %p, i1 %b)
82define i32 @nc1(i32* %q, i32* %p, i1 %b) {
83e:
84 br label %l
85l:
86 %x = phi i32* [ %p, %e ]
87 %y = phi i32* [ %q, %e ]
88 %tmp = bitcast i32* %x to i32* ; <i32*> [#uses=2]
89 %tmp2 = select i1 %b, i32* %tmp, i32* %y
90 %val = load i32, i32* %tmp2 ; <i32> [#uses=1]
91 store i32 0, i32* %tmp
92 store i32* %y, i32** @g
93 ret i32 %val
94}
95
96; CHECK: define i32 @nc1_addrspace(i32* %q, i32 addrspace(1)* nocapture %p, i1 %b)
97define i32 @nc1_addrspace(i32* %q, i32 addrspace(1)* %p, i1 %b) {
98e:
99 br label %l
100l:
101 %x = phi i32 addrspace(1)* [ %p, %e ]
102 %y = phi i32* [ %q, %e ]
103 %tmp = addrspacecast i32 addrspace(1)* %x to i32* ; <i32*> [#uses=2]
104 %tmp2 = select i1 %b, i32* %tmp, i32* %y
105 %val = load i32, i32* %tmp2 ; <i32> [#uses=1]
106 store i32 0, i32* %tmp
107 store i32* %y, i32** @g
108 ret i32 %val
109}
110
111; CHECK: define void @nc2(i32* nocapture %p, i32* %q)
112define void @nc2(i32* %p, i32* %q) {
113 %1 = call i32 @nc1(i32* %q, i32* %p, i1 0) ; <i32> [#uses=0]
114 ret void
115}
116
117; CHECK: define void @nc3(void ()* nocapture %p)
118define void @nc3(void ()* %p) {
119 call void %p()
120 ret void
121}
122
123declare void @external(i8*) readonly nounwind
124; CHECK: define void @nc4(i8* nocapture readonly %p)
125define void @nc4(i8* %p) {
126 call void @external(i8* %p)
127 ret void
128}
129
130; CHECK: define void @nc5(void (i8*)* nocapture %f, i8* nocapture %p)
131define void @nc5(void (i8*)* %f, i8* %p) {
132 call void %f(i8* %p) readonly nounwind
133 call void %f(i8* nocapture %p)
134 ret void
135}
136
137; CHECK: define void @test1_1(i8* nocapture readnone %x1_1, i8* %y1_1)
138; It would be acceptable to add readnone to %y1_1 and %y1_2.
139define void @test1_1(i8* %x1_1, i8* %y1_1) {
140 call i8* @test1_2(i8* %x1_1, i8* %y1_1)
141 store i32* null, i32** @g
142 ret void
143}
144
145; CHECK: define i8* @test1_2(i8* nocapture readnone %x1_2, i8* returned %y1_2)
146define i8* @test1_2(i8* %x1_2, i8* %y1_2) {
147 call void @test1_1(i8* %x1_2, i8* %y1_2)
148 store i32* null, i32** @g
149 ret i8* %y1_2
150}
151
152; CHECK: define void @test2(i8* nocapture readnone %x2)
153define void @test2(i8* %x2) {
154 call void @test2(i8* %x2)
155 store i32* null, i32** @g
156 ret void
157}
158
159; CHECK: define void @test3(i8* nocapture readnone %x3, i8* nocapture readnone %y3, i8* nocapture readnone %z3)
160define void @test3(i8* %x3, i8* %y3, i8* %z3) {
161 call void @test3(i8* %z3, i8* %y3, i8* %x3)
162 store i32* null, i32** @g
163 ret void
164}
165
166; CHECK: define void @test4_1(i8* %x4_1)
167define void @test4_1(i8* %x4_1) {
168 call i8* @test4_2(i8* %x4_1, i8* %x4_1, i8* %x4_1)
169 store i32* null, i32** @g
170 ret void
171}
172
173; CHECK: define i8* @test4_2(i8* nocapture readnone %x4_2, i8* readnone returned %y4_2, i8* nocapture readnone %z4_2)
174define i8* @test4_2(i8* %x4_2, i8* %y4_2, i8* %z4_2) {
175 call void @test4_1(i8* null)
176 store i32* null, i32** @g
177 ret i8* %y4_2
178}
179
180declare i8* @test5_1(i8* %x5_1)
181
182; CHECK: define void @test5_2(i8* %x5_2)
183define void @test5_2(i8* %x5_2) {
184 call i8* @test5_1(i8* %x5_2)
185 store i32* null, i32** @g
186 ret void
187}
188
189declare void @test6_1(i8* %x6_1, i8* nocapture %y6_1, ...)
190
191; CHECK: define void @test6_2(i8* %x6_2, i8* nocapture %y6_2, i8* %z6_2)
192define void @test6_2(i8* %x6_2, i8* %y6_2, i8* %z6_2) {
193 call void (i8*, i8*, ...) @test6_1(i8* %x6_2, i8* %y6_2, i8* %z6_2)
194 store i32* null, i32** @g
195 ret void
196}
197
198; CHECK: define void @test_cmpxchg(i32* nocapture %p)
199define void @test_cmpxchg(i32* %p) {
200 cmpxchg i32* %p, i32 0, i32 1 acquire monotonic
201 ret void
202}
203
204; CHECK: define void @test_cmpxchg_ptr(i32** nocapture %p, i32* %q)
205define void @test_cmpxchg_ptr(i32** %p, i32* %q) {
206 cmpxchg i32** %p, i32* null, i32* %q acquire monotonic
207 ret void
208}
209
210; CHECK: define void @test_atomicrmw(i32* nocapture %p)
211define void @test_atomicrmw(i32* %p) {
212 atomicrmw add i32* %p, i32 1 seq_cst
213 ret void
214}
215
216; CHECK: define void @test_volatile(i32* %x)
217define void @test_volatile(i32* %x) {
218entry:
219 %gep = getelementptr i32, i32* %x, i64 1
220 store volatile i32 0, i32* %gep, align 4
221 ret void
222}
223
224; CHECK: nocaptureLaunder(i8* nocapture %p)
225define void @nocaptureLaunder(i8* %p) {
226entry:
227 %b = call i8* @llvm.launder.invariant.group.p0i8(i8* %p)
228 store i8 42, i8* %b
229 ret void
230}
231
232@g2 = global i8* null
233; CHECK: define void @captureLaunder(i8* %p)
234define void @captureLaunder(i8* %p) {
235 %b = call i8* @llvm.launder.invariant.group.p0i8(i8* %p)
236 store i8* %b, i8** @g2
237 ret void
238}
239
240; CHECK: @nocaptureStrip(i8* nocapture %p)
241define void @nocaptureStrip(i8* %p) {
242entry:
243 %b = call i8* @llvm.strip.invariant.group.p0i8(i8* %p)
244 store i8 42, i8* %b
245 ret void
246}
247
248@g3 = global i8* null
249; CHECK: define void @captureStrip(i8* %p)
250define void @captureStrip(i8* %p) {
251 %b = call i8* @llvm.strip.invariant.group.p0i8(i8* %p)
252 store i8* %b, i8** @g3
253 ret void
254}
255
Ayke van Laethemf18cf232019-06-09 10:20:33 +0000256; CHECK: define i1 @captureICmp(i32* readnone %x)
257define i1 @captureICmp(i32* %x) {
258 %1 = icmp eq i32* %x, null
259 ret i1 %1
260}
261
Johannes Doerfert17cb9182019-08-16 21:53:49 +0000262; CHECK: define i1 @captureICmpRev(i32* readnone %x)
263define i1 @captureICmpRev(i32* %x) {
264 %1 = icmp eq i32* null, %x
265 ret i1 %1
266}
267
Ayke van Laethemf18cf232019-06-09 10:20:33 +0000268; CHECK: define i1 @nocaptureInboundsGEPICmp(i32* nocapture readnone %x)
269define i1 @nocaptureInboundsGEPICmp(i32* %x) {
270 %1 = getelementptr inbounds i32, i32* %x, i32 5
271 %2 = bitcast i32* %1 to i8*
272 %3 = icmp eq i8* %2, null
273 ret i1 %3
274}
275
Johannes Doerfert17cb9182019-08-16 21:53:49 +0000276; CHECK: define i1 @nocaptureInboundsGEPICmpRev(i32* nocapture readnone %x)
277define i1 @nocaptureInboundsGEPICmpRev(i32* %x) {
278 %1 = getelementptr inbounds i32, i32* %x, i32 5
279 %2 = bitcast i32* %1 to i8*
280 %3 = icmp eq i8* null, %2
281 ret i1 %3
282}
283
Ayke van Laethemf18cf232019-06-09 10:20:33 +0000284; CHECK: define i1 @nocaptureDereferenceableOrNullICmp(i32* nocapture readnone dereferenceable_or_null(4) %x)
285define i1 @nocaptureDereferenceableOrNullICmp(i32* dereferenceable_or_null(4) %x) {
286 %1 = bitcast i32* %x to i8*
287 %2 = icmp eq i8* %1, null
288 ret i1 %2
289}
290
291; CHECK: define i1 @captureDereferenceableOrNullICmp(i32* readnone dereferenceable_or_null(4) %x)
292define i1 @captureDereferenceableOrNullICmp(i32* dereferenceable_or_null(4) %x) "null-pointer-is-valid"="true" {
293 %1 = bitcast i32* %x to i8*
294 %2 = icmp eq i8* %1, null
295 ret i1 %2
296}
297
Eric Christophercee313d2019-04-17 04:52:47 +0000298declare i8* @llvm.launder.invariant.group.p0i8(i8*)
299declare i8* @llvm.strip.invariant.group.p0i8(i8*)