[llvm-readobj] - Simplify stack-sizes.test test case.
[llvm-complete.git] / test / Transforms / FunctionAttrs / arg_nocapture.ll
blobc963112947cc7e8812741bfac6efa182782b91b1
1 ; RUN: opt -functionattrs -attributor -attributor-manifest-internal -attributor-disable=false -attributor-max-iterations-verify -attributor-max-iterations=10 -S < %s | FileCheck %s
3 ; Test cases specifically designed for the "no-capture" argument attribute.
4 ; We use FIXME's to indicate problems and missing attributes.
6 target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
8 ; TEST comparison against NULL
10 ; int is_null_return(int *p) {
11 ;   return p == 0;
12 ; }
14 ; FIXME: no-capture missing for %p
15 ; CHECK: define i32 @is_null_return(i32* readnone %p)
16 define i32 @is_null_return(i32* %p) #0 {
17 entry:
18   %cmp = icmp eq i32* %p, null
19   %conv = zext i1 %cmp to i32
20   ret i32 %conv
23 ; TEST comparison against NULL in control flow
25 ; int is_null_control(int *p) {
26 ;   if (p == 0)
27 ;     return 1;
28 ;   if (0 == p)
29 ;     return 1;
30 ;   return 0;
31 ; }
33 ; FIXME: no-capture missing for %p
34 ; CHECK: define i32 @is_null_control(i32* readnone %p)
35 define i32 @is_null_control(i32* %p) #0 {
36 entry:
37   %retval = alloca i32, align 4
38   %cmp = icmp eq i32* %p, null
39   br i1 %cmp, label %if.then, label %if.end
41 if.then:                                          ; preds = %entry
42   store i32 1, i32* %retval, align 4
43   br label %return
45 if.end:                                           ; preds = %entry
46   %cmp1 = icmp eq i32* null, %p
47   br i1 %cmp1, label %if.then2, label %if.end3
49 if.then2:                                         ; preds = %if.end
50   store i32 1, i32* %retval, align 4
51   br label %return
53 if.end3:                                          ; preds = %if.end
54   store i32 0, i32* %retval, align 4
55   br label %return
57 return:                                           ; preds = %if.end3, %if.then2, %if.then
58   %0 = load i32, i32* %retval, align 4
59   ret i32 %0
62 ; TEST singleton SCC
64 ; double *srec0(double *a) {
65 ;   srec0(a);
66 ;   return 0;
67 ; }
69 ; CHECK: define noalias nonnull align 536870912 dereferenceable(4294967295) double* @srec0(double* nocapture readnone %a)
70 define double* @srec0(double* %a) #0 {
71 entry:
72   %call = call double* @srec0(double* %a)
73   ret double* null
76 ; TEST singleton SCC with lots of nested recursive calls
78 ; int* srec16(int* a) {
79 ;   return srec16(srec16(srec16(srec16(
80 ;          srec16(srec16(srec16(srec16(
81 ;          srec16(srec16(srec16(srec16(
82 ;          srec16(srec16(srec16(srec16(
83 ;                        a
84 ;          ))))))))))))))));
85 ; }
87 ; Other arguments are possible here due to the no-return behavior.
89 ; CHECK: define noalias nonnull align 536870912 dereferenceable(4294967295) i32* @srec16(i32* nocapture readnone %a)
90 define i32* @srec16(i32* %a) #0 {
91 entry:
92   %call = call i32* @srec16(i32* %a)
93 ; CHECK:      %call
94 ; CHECK-NEXT: unreachable
95   %call1 = call i32* @srec16(i32* %call)
96   %call2 = call i32* @srec16(i32* %call1)
97   %call3 = call i32* @srec16(i32* %call2)
98   %call4 = call i32* @srec16(i32* %call3)
99   %call5 = call i32* @srec16(i32* %call4)
100   %call6 = call i32* @srec16(i32* %call5)
101   %call7 = call i32* @srec16(i32* %call6)
102   %call8 = call i32* @srec16(i32* %call7)
103   %call9 = call i32* @srec16(i32* %call8)
104   %call10 = call i32* @srec16(i32* %call9)
105   %call11 = call i32* @srec16(i32* %call10)
106   %call12 = call i32* @srec16(i32* %call11)
107   %call13 = call i32* @srec16(i32* %call12)
108   %call14 = call i32* @srec16(i32* %call13)
109   %call15 = call i32* @srec16(i32* %call14)
110   ret i32* %call15
113 ; TEST SCC with various calls, casts, and comparisons agains NULL
115 ; CHECK: define dereferenceable_or_null(4) float* @scc_A(i32* readnone returned dereferenceable_or_null(4) "no-capture-maybe-returned" %a)
117 ; CHECK: define dereferenceable_or_null(8) i64* @scc_B(double* readnone returned dereferenceable_or_null(8) "no-capture-maybe-returned" %a)
119 ; FIXME: readnone missing for %s
120 ; CHECK: define dereferenceable_or_null(2) i8* @scc_C(i16* returned dereferenceable_or_null(2) "no-capture-maybe-returned" %a)
122 ; float *scc_A(int *a) {
123 ;   return (float*)(a ? (int*)scc_A((int*)scc_B((double*)scc_C((short*)a))) : a);
124 ; }
126 ; long *scc_B(double *a) {
127 ;   return (long*)(a ? scc_C((short*)scc_B((double*)scc_A((int*)a))) : a);
128 ; }
130 ; void *scc_C(short *a) {
131 ;   return scc_A((int*)(scc_A(a) ? scc_B((double*)a) : scc_C(a)));
132 ; }
133 define float* @scc_A(i32* dereferenceable_or_null(4) %a) {
134 entry:
135   %tobool = icmp ne i32* %a, null
136   br i1 %tobool, label %cond.true, label %cond.false
138 cond.true:                                        ; preds = %entry
139   %0 = bitcast i32* %a to i16*
140   %call = call i8* @scc_C(i16* %0)
141   %1 = bitcast i8* %call to double*
142   %call1 = call i64* @scc_B(double* %1)
143   %2 = bitcast i64* %call1 to i32*
144   %call2 = call float* @scc_A(i32* %2)
145   %3 = bitcast float* %call2 to i32*
146   br label %cond.end
148 cond.false:                                       ; preds = %entry
149   br label %cond.end
151 cond.end:                                         ; preds = %cond.false, %cond.true
152   %cond = phi i32* [ %3, %cond.true ], [ %a, %cond.false ]
153   %4 = bitcast i32* %cond to float*
154   ret float* %4
157 define i64* @scc_B(double* dereferenceable_or_null(8) %a) {
158 entry:
159   %tobool = icmp ne double* %a, null
160   br i1 %tobool, label %cond.true, label %cond.false
162 cond.true:                                        ; preds = %entry
163   %0 = bitcast double* %a to i32*
164   %call = call float* @scc_A(i32* %0)
165   %1 = bitcast float* %call to double*
166   %call1 = call i64* @scc_B(double* %1)
167   %2 = bitcast i64* %call1 to i16*
168   %call2 = call i8* @scc_C(i16* %2)
169   br label %cond.end
171 cond.false:                                       ; preds = %entry
172   %3 = bitcast double* %a to i8*
173   br label %cond.end
175 cond.end:                                         ; preds = %cond.false, %cond.true
176   %cond = phi i8* [ %call2, %cond.true ], [ %3, %cond.false ]
177   %4 = bitcast i8* %cond to i64*
178   ret i64* %4
181 define i8* @scc_C(i16* dereferenceable_or_null(2) %a) {
182 entry:
183   %bc = bitcast i16* %a to i32*
184   %call = call float* @scc_A(i32* %bc)
185   %bc2 = bitcast float* %call to i8*
186   %tobool = icmp ne i8* %bc2, null
187   br i1 %tobool, label %cond.true, label %cond.false
189 cond.true:                                        ; preds = %entry
190   %0 = bitcast i16* %a to double*
191   %call1 = call i64* @scc_B(double* %0)
192   %1 = bitcast i64* %call1 to i8*
193   br label %cond.end
195 cond.false:                                       ; preds = %entry
196   %call2 = call i8* @scc_C(i16* %a)
197   br label %cond.end
199 cond.end:                                         ; preds = %cond.false, %cond.true
200   %cond = phi i8* [ %1, %cond.true ], [ %call2, %cond.false ]
201   %2 = bitcast i8* %cond to i32*
202   %call3 = call float* @scc_A(i32* %2)
203   %3 = bitcast float* %call3 to i8*
204   ret i8* %3
208 ; TEST call to external function, marked no-capture
210 ; void external_no_capture(int /* no-capture */ *p);
211 ; void test_external_no_capture(int *p) {
212 ;   external_no_capture(p);
213 ; }
215 ; CHECK: define void @test_external_no_capture(i32* nocapture %p)
216 declare void @external_no_capture(i32* nocapture)
218 define void @test_external_no_capture(i32* %p) #0 {
219 entry:
220   call void @external_no_capture(i32* %p)
221   ret void
224 ; TEST call to external var-args function, marked no-capture
226 ; void test_var_arg_call(char *p, int a) {
227 ;   printf(p, a);
228 ; }
230 ; CHECK: define void @test_var_arg_call(i8* nocapture %p, i32 %a)
231 define void @test_var_arg_call(i8* %p, i32 %a) #0 {
232 entry:
233   %call = call i32 (i8*, ...) @printf(i8* %p, i32 %a)
234   ret void
237 declare i32 @printf(i8* nocapture, ...)
240 ; TEST "captured" only through return
242 ; long *not_captured_but_returned_0(long *a) {
243 ;   *a1 = 0;
244 ;   return a;
245 ; }
247 ; There should *not* be a no-capture attribute on %a
248 ; CHECK: define i64* @not_captured_but_returned_0(i64* returned "no-capture-maybe-returned" %a)
249 define i64* @not_captured_but_returned_0(i64* %a) #0 {
250 entry:
251   store i64 0, i64* %a, align 8
252   ret i64* %a
255 ; TEST "captured" only through return
257 ; long *not_captured_but_returned_1(long *a) {
258 ;   *(a+1) = 1;
259 ;   return a + 1;
260 ; }
262 ; There should *not* be a no-capture attribute on %a
263 ; CHECK: define nonnull i64* @not_captured_but_returned_1(i64* "no-capture-maybe-returned" %a)
264 define i64* @not_captured_but_returned_1(i64* %a) #0 {
265 entry:
266   %add.ptr = getelementptr inbounds i64, i64* %a, i64 1
267   store i64 1, i64* %add.ptr, align 8
268   ret i64* %add.ptr
271 ; TEST calls to "captured" only through return functions
273 ; void test_not_captured_but_returned_calls(long *a) {
274 ;   not_captured_but_returned_0(a);
275 ;   not_captured_but_returned_1(a);
276 ; }
278 ; FIXME: no-capture missing for %a
279 ; CHECK: define void @test_not_captured_but_returned_calls(i64* nocapture %a)
280 define void @test_not_captured_but_returned_calls(i64* %a) #0 {
281 entry:
282   %call = call i64* @not_captured_but_returned_0(i64* %a)
283   %call1 = call i64* @not_captured_but_returned_1(i64* %a)
284   ret void
287 ; TEST "captured" only through transitive return
289 ; long* negative_test_not_captured_but_returned_call_0a(long *a) {
290 ;   return not_captured_but_returned_0(a);
291 ; }
293 ; There should *not* be a no-capture attribute on %a
294 ; CHECK: define i64* @negative_test_not_captured_but_returned_call_0a(i64* returned "no-capture-maybe-returned" %a)
295 define i64* @negative_test_not_captured_but_returned_call_0a(i64* %a) #0 {
296 entry:
297   %call = call i64* @not_captured_but_returned_0(i64* %a)
298   ret i64* %call
301 ; TEST captured through write
303 ; void negative_test_not_captured_but_returned_call_0b(long *a) {
304 ;   *a = (long)not_captured_but_returned_0(a);
305 ; }
307 ; There should *not* be a no-capture attribute on %a
308 ; CHECK: define void @negative_test_not_captured_but_returned_call_0b(i64* %a)
309 define void @negative_test_not_captured_but_returned_call_0b(i64* %a) #0 {
310 entry:
311   %call = call i64* @not_captured_but_returned_0(i64* %a)
312   %0 = ptrtoint i64* %call to i64
313   store i64 %0, i64* %a, align 8
314   ret void
317 ; TEST "captured" only through transitive return
319 ; long* negative_test_not_captured_but_returned_call_1a(long *a) {
320 ;   return not_captured_but_returned_1(a);
321 ; }
323 ; There should *not* be a no-capture attribute on %a
324 ; CHECK: define nonnull i64* @negative_test_not_captured_but_returned_call_1a(i64* "no-capture-maybe-returned" %a)
325 define i64* @negative_test_not_captured_but_returned_call_1a(i64* %a) #0 {
326 entry:
327   %call = call i64* @not_captured_but_returned_1(i64* %a)
328   ret i64* %call
331 ; TEST captured through write
333 ; void negative_test_not_captured_but_returned_call_1b(long *a) {
334 ;   *a = (long)not_captured_but_returned_1(a);
335 ; }
337 ; There should *not* be a no-capture attribute on %a
338 ; CHECK: define void @negative_test_not_captured_but_returned_call_1b(i64* %a)
339 define void @negative_test_not_captured_but_returned_call_1b(i64* %a) #0 {
340 entry:
341   %call = call i64* @not_captured_but_returned_1(i64* %a)
342   %0 = ptrtoint i64* %call to i64
343   store i64 %0, i64* %call, align 8
344   ret void
347 ; TEST return argument or unknown call result
349 ; int* ret_arg_or_unknown(int* b) {
350 ;   if (b == 0)
351 ;     return b;
352 ;   return unknown();
353 ; }
355 ; Verify we do *not* assume b is returned or not captured.
357 ; CHECK:     define i32* @ret_arg_or_unknown(i32* readnone %b)
358 ; CHECK:     define i32* @ret_arg_or_unknown_through_phi(i32* readnone %b)
359 declare i32* @unknown()
361 define i32* @ret_arg_or_unknown(i32* %b) #0 {
362 entry:
363   %cmp = icmp eq i32* %b, null
364   br i1 %cmp, label %ret_arg, label %ret_unknown
366 ret_arg:
367   ret i32* %b
369 ret_unknown:
370   %call = call i32* @unknown()
371   ret i32* %call
374 define i32* @ret_arg_or_unknown_through_phi(i32* %b) #0 {
375 entry:
376   %cmp = icmp eq i32* %b, null
377   br i1 %cmp, label %ret_arg, label %ret_unknown
379 ret_arg:
380   br label %r
382 ret_unknown:
383   %call = call i32* @unknown()
384   br label %r
387   %phi = phi i32* [ %b, %ret_arg ], [ %call, %ret_unknown ]
388   ret i32* %phi
392 ; TEST not captured by readonly external function
394 ; CHECK: define void @not_captured_by_readonly_call(i32* nocapture %b)
395 declare i32* @readonly_unknown(i32*, i32*) readonly
397 define void @not_captured_by_readonly_call(i32* %b) #0 {
398 entry:
399   %call = call i32* @readonly_unknown(i32* %b, i32* %b)
400   ret void
404 ; TEST not captured by readonly external function if return chain is known
406 ; Make sure the returned flag on %r is strong enough to justify nocapture on %b but **not** on %r.
408 ; FIXME: The "returned" information is not propagated to the fullest extend causing us to miss "nocapture" on %b in the following:
409 ; CHECK: define i32* @not_captured_by_readonly_call_not_returned_either1(i32* readonly %b, i32* readonly returned %r)
411 ; CHECK: define i32* @not_captured_by_readonly_call_not_returned_either2(i32* readonly %b, i32* readonly returned %r)
412 ; CHECK: define i32* @not_captured_by_readonly_call_not_returned_either3(i32* readonly %b, i32* readonly returned %r)
414 ; FIXME: The "nounwind" information is not derived to the fullest extend causing us to miss "nocapture" on %b in the following:
415 ; CHECK: define i32* @not_captured_by_readonly_call_not_returned_either4(i32* readonly %b, i32* readonly returned %r)
416 define i32* @not_captured_by_readonly_call_not_returned_either1(i32* %b, i32* returned %r) #0 {
417 entry:
418   %call = call i32* @readonly_unknown(i32* %b, i32* %r) nounwind
419   ret i32* %call
422 declare i32* @readonly_unknown_r1a(i32*, i32* returned) readonly
423 define i32* @not_captured_by_readonly_call_not_returned_either2(i32* %b, i32* %r) #0 {
424 entry:
425   %call = call i32* @readonly_unknown_r1a(i32* %b, i32* %r) nounwind
426   ret i32* %call
429 declare i32* @readonly_unknown_r1b(i32*, i32* returned) readonly nounwind
430 define i32* @not_captured_by_readonly_call_not_returned_either3(i32* %b, i32* %r) #0 {
431 entry:
432   %call = call i32* @readonly_unknown_r1b(i32* %b, i32* %r)
433   ret i32* %call
436 define i32* @not_captured_by_readonly_call_not_returned_either4(i32* %b, i32* %r) #0 {
437 entry:
438   %call = call i32* @readonly_unknown_r1a(i32* %b, i32* %r)
439   ret i32* %call
442 attributes #0 = { noinline nounwind uwtable }