blob: 673df13cc24952bb62e9b60dc79717fa59793c9a [file] [log] [blame]
Johannes Doerfert7516a5e2019-09-03 20:37:24 +00001; RUN: opt -functionattrs -S < %s | FileCheck %s --check-prefixes=FNATTR,EITHER
2; RUN: opt -passes=function-attrs -S < %s | FileCheck %s --check-prefixes=FNATTR,EITHER
3; RUN: opt -attributor -attributor-manifest-internal -attributor-disable=false -S < %s | FileCheck %s --check-prefixes=ATTRIBUTOR,EITHER
4; RUN: opt -passes=attributor -attributor-manifest-internal -attributor-disable=false -S < %s | FileCheck %s --check-prefixes=ATTRIBUTOR,EITHER
Eric Christophercee313d2019-04-17 04:52:47 +00005
6@g = global i32* null ; <i32**> [#uses=1]
7
Johannes Doerfert7516a5e2019-09-03 20:37:24 +00008; FNATTR: define i32* @c1(i32* readnone returned %q)
9; ATTRIBUTOR: define i32* @c1(i32* returned "no-capture-maybe-returned" %q)
Eric Christophercee313d2019-04-17 04:52:47 +000010define i32* @c1(i32* %q) {
11 ret i32* %q
12}
13
Johannes Doerfert7516a5e2019-09-03 20:37:24 +000014; EITHER: define void @c2(i32* %q)
Eric Christophercee313d2019-04-17 04:52:47 +000015; It would also be acceptable to mark %q as readnone. Update @c3 too.
16define void @c2(i32* %q) {
17 store i32* %q, i32** @g
18 ret void
19}
20
Johannes Doerfert7516a5e2019-09-03 20:37:24 +000021; EITHER: define void @c3(i32* %q)
Eric Christophercee313d2019-04-17 04:52:47 +000022define void @c3(i32* %q) {
23 call void @c2(i32* %q)
24 ret void
25}
26
Johannes Doerfert7516a5e2019-09-03 20:37:24 +000027; EITHER: define i1 @c4(i32* %q, i32 %bitno)
Eric Christophercee313d2019-04-17 04:52:47 +000028define i1 @c4(i32* %q, i32 %bitno) {
29 %tmp = ptrtoint i32* %q to i32
30 %tmp2 = lshr i32 %tmp, %bitno
31 %bit = trunc i32 %tmp2 to i1
32 br i1 %bit, label %l1, label %l0
33l0:
34 ret i1 0 ; escaping value not caught by def-use chaining.
35l1:
36 ret i1 1 ; escaping value not caught by def-use chaining.
37}
38
39@lookup_table = global [2 x i1] [ i1 0, i1 1 ]
40
Johannes Doerfert7516a5e2019-09-03 20:37:24 +000041; EITHER: define i1 @c5(i32* %q, i32 %bitno)
Eric Christophercee313d2019-04-17 04:52:47 +000042define i1 @c5(i32* %q, i32 %bitno) {
43 %tmp = ptrtoint i32* %q to i32
44 %tmp2 = lshr i32 %tmp, %bitno
45 %bit = and i32 %tmp2, 1
46 ; subtle escape mechanism follows
47 %lookup = getelementptr [2 x i1], [2 x i1]* @lookup_table, i32 0, i32 %bit
48 %val = load i1, i1* %lookup
49 ret i1 %val
50}
51
52declare void @throw_if_bit_set(i8*, i8) readonly
53
Johannes Doerfert7516a5e2019-09-03 20:37:24 +000054; FNATTR: define i1 @c6(i8* readonly %q, i8 %bit)
55; ATTRIBUTOR: define i1 @c6(i8* %q, i8 %bit)
Eric Christophercee313d2019-04-17 04:52:47 +000056define i1 @c6(i8* %q, i8 %bit) personality i32 (...)* @__gxx_personality_v0 {
57 invoke void @throw_if_bit_set(i8* %q, i8 %bit)
58 to label %ret0 unwind label %ret1
59ret0:
60 ret i1 0
61ret1:
62 %exn = landingpad {i8*, i32}
63 cleanup
64 ret i1 1
65}
66
67declare i32 @__gxx_personality_v0(...)
68
69define i1* @lookup_bit(i32* %q, i32 %bitno) readnone nounwind {
70 %tmp = ptrtoint i32* %q to i32
71 %tmp2 = lshr i32 %tmp, %bitno
72 %bit = and i32 %tmp2, 1
73 %lookup = getelementptr [2 x i1], [2 x i1]* @lookup_table, i32 0, i32 %bit
74 ret i1* %lookup
75}
76
Johannes Doerfert7516a5e2019-09-03 20:37:24 +000077; FNATTR: define i1 @c7(i32* readonly %q, i32 %bitno)
78; ATTRIBUTOR: define i1 @c7(i32* %q, i32 %bitno)
Eric Christophercee313d2019-04-17 04:52:47 +000079define i1 @c7(i32* %q, i32 %bitno) {
80 %ptr = call i1* @lookup_bit(i32* %q, i32 %bitno)
81 %val = load i1, i1* %ptr
82 ret i1 %val
83}
84
85
Johannes Doerfert7516a5e2019-09-03 20:37:24 +000086; EITHER: define i32 @nc1(i32* %q, i32* nocapture %p, i1 %b)
Eric Christophercee313d2019-04-17 04:52:47 +000087define i32 @nc1(i32* %q, i32* %p, i1 %b) {
88e:
89 br label %l
90l:
91 %x = phi i32* [ %p, %e ]
92 %y = phi i32* [ %q, %e ]
93 %tmp = bitcast i32* %x to i32* ; <i32*> [#uses=2]
94 %tmp2 = select i1 %b, i32* %tmp, i32* %y
95 %val = load i32, i32* %tmp2 ; <i32> [#uses=1]
96 store i32 0, i32* %tmp
97 store i32* %y, i32** @g
98 ret i32 %val
99}
100
Johannes Doerfert7516a5e2019-09-03 20:37:24 +0000101; EITHER: define i32 @nc1_addrspace(i32* %q, i32 addrspace(1)* nocapture %p, i1 %b)
Eric Christophercee313d2019-04-17 04:52:47 +0000102define i32 @nc1_addrspace(i32* %q, i32 addrspace(1)* %p, i1 %b) {
103e:
104 br label %l
105l:
106 %x = phi i32 addrspace(1)* [ %p, %e ]
107 %y = phi i32* [ %q, %e ]
108 %tmp = addrspacecast i32 addrspace(1)* %x to i32* ; <i32*> [#uses=2]
109 %tmp2 = select i1 %b, i32* %tmp, i32* %y
110 %val = load i32, i32* %tmp2 ; <i32> [#uses=1]
111 store i32 0, i32* %tmp
112 store i32* %y, i32** @g
113 ret i32 %val
114}
115
Johannes Doerfert7516a5e2019-09-03 20:37:24 +0000116; EITHER: define void @nc2(i32* nocapture %p, i32* %q)
Eric Christophercee313d2019-04-17 04:52:47 +0000117define void @nc2(i32* %p, i32* %q) {
118 %1 = call i32 @nc1(i32* %q, i32* %p, i1 0) ; <i32> [#uses=0]
119 ret void
120}
121
Johannes Doerfert7516a5e2019-09-03 20:37:24 +0000122; EITHER: define void @nc3(void ()* nocapture %p)
Eric Christophercee313d2019-04-17 04:52:47 +0000123define void @nc3(void ()* %p) {
124 call void %p()
125 ret void
126}
127
128declare void @external(i8*) readonly nounwind
Johannes Doerfert7516a5e2019-09-03 20:37:24 +0000129; FNATTR: define void @nc4(i8* nocapture readonly %p)
130; ATTRIBUTOR: define void @nc4(i8* nocapture %p)
Eric Christophercee313d2019-04-17 04:52:47 +0000131define void @nc4(i8* %p) {
132 call void @external(i8* %p)
133 ret void
134}
135
Johannes Doerfert7516a5e2019-09-03 20:37:24 +0000136; EITHER: define void @nc5(void (i8*)* nocapture %f, i8* nocapture %p)
Eric Christophercee313d2019-04-17 04:52:47 +0000137define void @nc5(void (i8*)* %f, i8* %p) {
138 call void %f(i8* %p) readonly nounwind
139 call void %f(i8* nocapture %p)
140 ret void
141}
142
Johannes Doerfert7516a5e2019-09-03 20:37:24 +0000143; FNATTR: define void @test1_1(i8* nocapture readnone %x1_1, i8* %y1_1, i1 %c)
144; ATTRIBUTOR: define void @test1_1(i8* nocapture %x1_1, i8* nocapture %y1_1, i1 %c)
Eric Christophercee313d2019-04-17 04:52:47 +0000145; It would be acceptable to add readnone to %y1_1 and %y1_2.
Johannes Doerfert7516a5e2019-09-03 20:37:24 +0000146define void @test1_1(i8* %x1_1, i8* %y1_1, i1 %c) {
147 call i8* @test1_2(i8* %x1_1, i8* %y1_1, i1 %c)
Eric Christophercee313d2019-04-17 04:52:47 +0000148 store i32* null, i32** @g
149 ret void
150}
151
Johannes Doerfert7516a5e2019-09-03 20:37:24 +0000152; FNATTR: define i8* @test1_2(i8* nocapture readnone %x1_2, i8* returned %y1_2, i1 %c)
153; ATTRIBUTOR: define i8* @test1_2(i8* nocapture %x1_2, i8* returned "no-capture-maybe-returned" %y1_2, i1 %c)
154define i8* @test1_2(i8* %x1_2, i8* %y1_2, i1 %c) {
155 br i1 %c, label %t, label %f
156t:
157 call void @test1_1(i8* %x1_2, i8* %y1_2, i1 %c)
Eric Christophercee313d2019-04-17 04:52:47 +0000158 store i32* null, i32** @g
Johannes Doerfert7516a5e2019-09-03 20:37:24 +0000159 br label %f
160f:
Eric Christophercee313d2019-04-17 04:52:47 +0000161 ret i8* %y1_2
162}
163
Johannes Doerfert7516a5e2019-09-03 20:37:24 +0000164; FNATTR: define void @test2(i8* nocapture readnone %x2)
165; ATTRIBUTOR: define void @test2(i8* nocapture %x2)
Eric Christophercee313d2019-04-17 04:52:47 +0000166define void @test2(i8* %x2) {
167 call void @test2(i8* %x2)
168 store i32* null, i32** @g
169 ret void
170}
171
Johannes Doerfert7516a5e2019-09-03 20:37:24 +0000172; FNATTR: define void @test3(i8* nocapture readnone %x3, i8* nocapture readnone %y3, i8* nocapture readnone %z3)
173; ATTRIBUTOR: define void @test3(i8* nocapture %x3, i8* nocapture %y3, i8* nocapture %z3)
Eric Christophercee313d2019-04-17 04:52:47 +0000174define void @test3(i8* %x3, i8* %y3, i8* %z3) {
175 call void @test3(i8* %z3, i8* %y3, i8* %x3)
176 store i32* null, i32** @g
177 ret void
178}
179
Johannes Doerfert7516a5e2019-09-03 20:37:24 +0000180; FNATTR: define void @test4_1(i8* %x4_1, i1 %c)
181; ATTRIBUTOR: define void @test4_1(i8* nocapture %x4_1, i1 %c)
182define void @test4_1(i8* %x4_1, i1 %c) {
183 call i8* @test4_2(i8* %x4_1, i8* %x4_1, i8* %x4_1, i1 %c)
Eric Christophercee313d2019-04-17 04:52:47 +0000184 store i32* null, i32** @g
185 ret void
186}
187
Johannes Doerfert7516a5e2019-09-03 20:37:24 +0000188; FNATTR: define i8* @test4_2(i8* nocapture readnone %x4_2, i8* readnone returned %y4_2, i8* nocapture readnone %z4_2, i1 %c)
189; ATTRIBUTOR: define i8* @test4_2(i8* nocapture %x4_2, i8* returned "no-capture-maybe-returned" %y4_2, i8* nocapture %z4_2, i1 %c)
190define i8* @test4_2(i8* %x4_2, i8* %y4_2, i8* %z4_2, i1 %c) {
191 br i1 %c, label %t, label %f
192t:
193 call void @test4_1(i8* null, i1 %c)
Eric Christophercee313d2019-04-17 04:52:47 +0000194 store i32* null, i32** @g
Johannes Doerfert7516a5e2019-09-03 20:37:24 +0000195 br label %f
196f:
Eric Christophercee313d2019-04-17 04:52:47 +0000197 ret i8* %y4_2
198}
199
200declare i8* @test5_1(i8* %x5_1)
201
Johannes Doerfert7516a5e2019-09-03 20:37:24 +0000202; EITHER: define void @test5_2(i8* %x5_2)
Eric Christophercee313d2019-04-17 04:52:47 +0000203define void @test5_2(i8* %x5_2) {
204 call i8* @test5_1(i8* %x5_2)
205 store i32* null, i32** @g
206 ret void
207}
208
209declare void @test6_1(i8* %x6_1, i8* nocapture %y6_1, ...)
210
Johannes Doerfert7516a5e2019-09-03 20:37:24 +0000211; EITHER: define void @test6_2(i8* %x6_2, i8* nocapture %y6_2, i8* %z6_2)
Eric Christophercee313d2019-04-17 04:52:47 +0000212define void @test6_2(i8* %x6_2, i8* %y6_2, i8* %z6_2) {
213 call void (i8*, i8*, ...) @test6_1(i8* %x6_2, i8* %y6_2, i8* %z6_2)
214 store i32* null, i32** @g
215 ret void
216}
217
Johannes Doerfert7516a5e2019-09-03 20:37:24 +0000218; EITHER: define void @test_cmpxchg(i32* nocapture %p)
Eric Christophercee313d2019-04-17 04:52:47 +0000219define void @test_cmpxchg(i32* %p) {
220 cmpxchg i32* %p, i32 0, i32 1 acquire monotonic
221 ret void
222}
223
Johannes Doerfert7516a5e2019-09-03 20:37:24 +0000224; EITHER: define void @test_cmpxchg_ptr(i32** nocapture %p, i32* %q)
Eric Christophercee313d2019-04-17 04:52:47 +0000225define void @test_cmpxchg_ptr(i32** %p, i32* %q) {
226 cmpxchg i32** %p, i32* null, i32* %q acquire monotonic
227 ret void
228}
229
Johannes Doerfert7516a5e2019-09-03 20:37:24 +0000230; EITHER: define void @test_atomicrmw(i32* nocapture %p)
Eric Christophercee313d2019-04-17 04:52:47 +0000231define void @test_atomicrmw(i32* %p) {
232 atomicrmw add i32* %p, i32 1 seq_cst
233 ret void
234}
235
Johannes Doerfert7516a5e2019-09-03 20:37:24 +0000236; EITHER: define void @test_volatile(i32* %x)
Eric Christophercee313d2019-04-17 04:52:47 +0000237define void @test_volatile(i32* %x) {
238entry:
239 %gep = getelementptr i32, i32* %x, i64 1
240 store volatile i32 0, i32* %gep, align 4
241 ret void
242}
243
Johannes Doerfert7516a5e2019-09-03 20:37:24 +0000244; EITHER: nocaptureLaunder(i8* nocapture %p)
Eric Christophercee313d2019-04-17 04:52:47 +0000245define void @nocaptureLaunder(i8* %p) {
246entry:
247 %b = call i8* @llvm.launder.invariant.group.p0i8(i8* %p)
248 store i8 42, i8* %b
249 ret void
250}
251
252@g2 = global i8* null
Johannes Doerfert7516a5e2019-09-03 20:37:24 +0000253; EITHER: define void @captureLaunder(i8* %p)
Eric Christophercee313d2019-04-17 04:52:47 +0000254define void @captureLaunder(i8* %p) {
255 %b = call i8* @llvm.launder.invariant.group.p0i8(i8* %p)
256 store i8* %b, i8** @g2
257 ret void
258}
259
Johannes Doerfert7516a5e2019-09-03 20:37:24 +0000260; EITHER: @nocaptureStrip(i8* nocapture %p)
Eric Christophercee313d2019-04-17 04:52:47 +0000261define void @nocaptureStrip(i8* %p) {
262entry:
263 %b = call i8* @llvm.strip.invariant.group.p0i8(i8* %p)
264 store i8 42, i8* %b
265 ret void
266}
267
268@g3 = global i8* null
Johannes Doerfert7516a5e2019-09-03 20:37:24 +0000269; EITHER: define void @captureStrip(i8* %p)
Eric Christophercee313d2019-04-17 04:52:47 +0000270define void @captureStrip(i8* %p) {
271 %b = call i8* @llvm.strip.invariant.group.p0i8(i8* %p)
272 store i8* %b, i8** @g3
273 ret void
274}
275
Johannes Doerfert7516a5e2019-09-03 20:37:24 +0000276; FNATTR: define i1 @captureICmp(i32* readnone %x)
277; ATTRIBUTOR: define i1 @captureICmp(i32* %x)
Ayke van Laethemf18cf232019-06-09 10:20:33 +0000278define i1 @captureICmp(i32* %x) {
279 %1 = icmp eq i32* %x, null
280 ret i1 %1
281}
282
Johannes Doerfert7516a5e2019-09-03 20:37:24 +0000283; FNATTR: define i1 @captureICmpRev(i32* readnone %x)
284; ATTRIBUTOR: define i1 @captureICmpRev(i32* %x)
Johannes Doerfert17cb9182019-08-16 21:53:49 +0000285define i1 @captureICmpRev(i32* %x) {
286 %1 = icmp eq i32* null, %x
287 ret i1 %1
288}
289
Johannes Doerfert7516a5e2019-09-03 20:37:24 +0000290; FNATTR: define i1 @nocaptureInboundsGEPICmp(i32* nocapture readnone %x)
291; ATTRIBUTOR: define i1 @nocaptureInboundsGEPICmp(i32* nocapture %x)
Ayke van Laethemf18cf232019-06-09 10:20:33 +0000292define i1 @nocaptureInboundsGEPICmp(i32* %x) {
293 %1 = getelementptr inbounds i32, i32* %x, i32 5
294 %2 = bitcast i32* %1 to i8*
295 %3 = icmp eq i8* %2, null
296 ret i1 %3
297}
298
Johannes Doerfert7516a5e2019-09-03 20:37:24 +0000299; FNATTR: define i1 @nocaptureInboundsGEPICmpRev(i32* nocapture readnone %x)
300; ATTRIBUTOR: define i1 @nocaptureInboundsGEPICmpRev(i32* nocapture %x)
Johannes Doerfert17cb9182019-08-16 21:53:49 +0000301define i1 @nocaptureInboundsGEPICmpRev(i32* %x) {
302 %1 = getelementptr inbounds i32, i32* %x, i32 5
303 %2 = bitcast i32* %1 to i8*
304 %3 = icmp eq i8* null, %2
305 ret i1 %3
306}
307
Johannes Doerfert7516a5e2019-09-03 20:37:24 +0000308; FNATTR: define i1 @nocaptureDereferenceableOrNullICmp(i32* nocapture readnone dereferenceable_or_null(4) %x)
309; ATTRIBUTOR: define i1 @nocaptureDereferenceableOrNullICmp(i32* nocapture dereferenceable_or_null(4) %x)
Ayke van Laethemf18cf232019-06-09 10:20:33 +0000310define i1 @nocaptureDereferenceableOrNullICmp(i32* dereferenceable_or_null(4) %x) {
311 %1 = bitcast i32* %x to i8*
312 %2 = icmp eq i8* %1, null
313 ret i1 %2
314}
315
Johannes Doerfert7516a5e2019-09-03 20:37:24 +0000316; FNATTR: define i1 @captureDereferenceableOrNullICmp(i32* readnone dereferenceable_or_null(4) %x)
317; ATTRIBUTOR: define i1 @captureDereferenceableOrNullICmp(i32* dereferenceable_or_null(4) %x)
Ayke van Laethemf18cf232019-06-09 10:20:33 +0000318define i1 @captureDereferenceableOrNullICmp(i32* dereferenceable_or_null(4) %x) "null-pointer-is-valid"="true" {
319 %1 = bitcast i32* %x to i8*
320 %2 = icmp eq i8* %1, null
321 ret i1 %2
322}
323
Eric Christophercee313d2019-04-17 04:52:47 +0000324declare i8* @llvm.launder.invariant.group.p0i8(i8*)
325declare i8* @llvm.strip.invariant.group.p0i8(i8*)