[ARM] Adjust how NEON shifts are lowered
[llvm-core.git] / test / Transforms / FunctionAttrs / arg_nocapture.ll
blob0bc7053f7ad2f903b84800bab9da6f11501fcdaa
1 ; RUN: opt -functionattrs -attributor -attributor-disable=false -S < %s | FileCheck %s
2 ; RUN: opt -functionattrs -attributor -attributor-disable=false -attributor-verify=true -S < %s | FileCheck %s
4 ; Test cases specifically designed for the "no-capture" argument attribute.
5 ; We use FIXME's to indicate problems and missing attributes.
7 target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
9 ; TEST comparison against NULL
11 ; int is_null_return(int *p) {
12 ;   return p == 0;
13 ; }
15 ; FIXME: no-capture missing for %p
16 ; CHECK: define i32 @is_null_return(i32* readnone %p)
17 define i32 @is_null_return(i32* %p) #0 {
18 entry:
19   %cmp = icmp eq i32* %p, null
20   %conv = zext i1 %cmp to i32
21   ret i32 %conv
24 ; TEST comparison against NULL in control flow
26 ; int is_null_control(int *p) {
27 ;   if (p == 0)
28 ;     return 1;
29 ;   if (0 == p)
30 ;     return 1;
31 ;   return 0;
32 ; }
34 ; FIXME: no-capture missing for %p
35 ; CHECK: define i32 @is_null_control(i32* readnone %p)
36 define i32 @is_null_control(i32* %p) #0 {
37 entry:
38   %retval = alloca i32, align 4
39   %cmp = icmp eq i32* %p, null
40   br i1 %cmp, label %if.then, label %if.end
42 if.then:                                          ; preds = %entry
43   store i32 1, i32* %retval, align 4
44   br label %return
46 if.end:                                           ; preds = %entry
47   %cmp1 = icmp eq i32* null, %p
48   br i1 %cmp1, label %if.then2, label %if.end3
50 if.then2:                                         ; preds = %if.end
51   store i32 1, i32* %retval, align 4
52   br label %return
54 if.end3:                                          ; preds = %if.end
55   store i32 0, i32* %retval, align 4
56   br label %return
58 return:                                           ; preds = %if.end3, %if.then2, %if.then
59   %0 = load i32, i32* %retval, align 4
60   ret i32 %0
63 ; TEST singleton SCC
65 ; double *srec0(double *a) {
66 ;   srec0(a);
67 ;   return 0;
68 ; }
70 ; CHECK: define noalias double* @srec0(double* nocapture readnone %a)
71 define double* @srec0(double* %a) #0 {
72 entry:
73   %call = call double* @srec0(double* %a)
74   ret double* null
77 ; TEST singleton SCC with lots of nested recursive calls
79 ; int* srec16(int* a) {
80 ;   return srec16(srec16(srec16(srec16(
81 ;          srec16(srec16(srec16(srec16(
82 ;          srec16(srec16(srec16(srec16(
83 ;          srec16(srec16(srec16(srec16(
84 ;                        a
85 ;          ))))))))))))))));
86 ; }
88 ; Other arguments are possible here due to the no-return behavior.
90 ; FIXME: no-return missing
91 ; CHECK: define noalias nonnull i32* @srec16(i32* nocapture readnone %a)
92 define i32* @srec16(i32* %a) #0 {
93 entry:
94   %call = call i32* @srec16(i32* %a)
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 ; FIXME: no-capture missing for %a
116 ; CHECK: define float* @scc_A(i32* readnone returned %a)
118 ; FIXME: no-capture missing for %a
119 ; CHECK: define i64* @scc_B(double* readnone returned %a)
121 ; FIXME: readnone missing for %s
122 ; FIXME: no-capture missing for %a
123 ; CHECK: define i8* @scc_C(i16* returned %a)
125 ; float *scc_A(int *a) {
126 ;   return (float*)(a ? (int*)scc_A((int*)scc_B((double*)scc_C((short*)a))) : a);
127 ; }
129 ; long *scc_B(double *a) {
130 ;   return (long*)(a ? scc_C((short*)scc_B((double*)scc_A((int*)a))) : a);
131 ; }
133 ; void *scc_C(short *a) {
134 ;   return scc_A((int*)(scc_C(a) ? scc_B((double*)a) : scc_C(a)));
135 ; }
136 define float* @scc_A(i32* %a) {
137 entry:
138   %tobool = icmp ne i32* %a, null
139   br i1 %tobool, label %cond.true, label %cond.false
141 cond.true:                                        ; preds = %entry
142   %0 = bitcast i32* %a to i16*
143   %call = call i8* @scc_C(i16* %0)
144   %1 = bitcast i8* %call to double*
145   %call1 = call i64* @scc_B(double* %1)
146   %2 = bitcast i64* %call1 to i32*
147   %call2 = call float* @scc_A(i32* %2)
148   %3 = bitcast float* %call2 to i32*
149   br label %cond.end
151 cond.false:                                       ; preds = %entry
152   br label %cond.end
154 cond.end:                                         ; preds = %cond.false, %cond.true
155   %cond = phi i32* [ %3, %cond.true ], [ %a, %cond.false ]
156   %4 = bitcast i32* %cond to float*
157   ret float* %4
160 define i64* @scc_B(double* %a) {
161 entry:
162   %tobool = icmp ne double* %a, null
163   br i1 %tobool, label %cond.true, label %cond.false
165 cond.true:                                        ; preds = %entry
166   %0 = bitcast double* %a to i32*
167   %call = call float* @scc_A(i32* %0)
168   %1 = bitcast float* %call to double*
169   %call1 = call i64* @scc_B(double* %1)
170   %2 = bitcast i64* %call1 to i16*
171   %call2 = call i8* @scc_C(i16* %2)
172   br label %cond.end
174 cond.false:                                       ; preds = %entry
175   %3 = bitcast double* %a to i8*
176   br label %cond.end
178 cond.end:                                         ; preds = %cond.false, %cond.true
179   %cond = phi i8* [ %call2, %cond.true ], [ %3, %cond.false ]
180   %4 = bitcast i8* %cond to i64*
181   ret i64* %4
184 define i8* @scc_C(i16* %a) {
185 entry:
186   %call = call i8* @scc_C(i16* %a)
187   %tobool = icmp ne i8* %call, null
188   br i1 %tobool, label %cond.true, label %cond.false
190 cond.true:                                        ; preds = %entry
191   %0 = bitcast i16* %a to double*
192   %call1 = call i64* @scc_B(double* %0)
193   %1 = bitcast i64* %call1 to i8*
194   br label %cond.end
196 cond.false:                                       ; preds = %entry
197   %call2 = call i8* @scc_C(i16* %a)
198   br label %cond.end
200 cond.end:                                         ; preds = %cond.false, %cond.true
201   %cond = phi i8* [ %1, %cond.true ], [ %call2, %cond.false ]
202   %2 = bitcast i8* %cond to i32*
203   %call3 = call float* @scc_A(i32* %2)
204   %3 = bitcast float* %call3 to i8*
205   ret i8* %3
209 ; TEST call to external function, marked no-capture
211 ; void external_no_capture(int /* no-capture */ *p);
212 ; void test_external_no_capture(int *p) {
213 ;   external_no_capture(p);
214 ; }
216 ; CHECK: define void @test_external_no_capture(i32* nocapture %p)
217 declare void @external_no_capture(i32* nocapture)
219 define void @test_external_no_capture(i32* %p) #0 {
220 entry:
221   call void @external_no_capture(i32* %p)
222   ret void
225 ; TEST call to external var-args function, marked no-capture
227 ; void test_var_arg_call(char *p, int a) {
228 ;   printf(p, a);
229 ; }
231 ; CHECK: define void @test_var_arg_call(i8* nocapture %p, i32 %a)
232 define void @test_var_arg_call(i8* %p, i32 %a) #0 {
233 entry:
234   %call = call i32 (i8*, ...) @printf(i8* %p, i32 %a)
235   ret void
238 declare i32 @printf(i8* nocapture, ...)
241 ; TEST "captured" only through return
243 ; long *not_captured_but_returned_0(long *a) {
244 ;   *a1 = 0;
245 ;   return a;
246 ; }
248 ; There should *not* be a no-capture attribute on %a
249 ; CHECK: define i64* @not_captured_but_returned_0(i64* returned %a)
250 define i64* @not_captured_but_returned_0(i64* %a) #0 {
251 entry:
252   store i64 0, i64* %a, align 8
253   ret i64* %a
256 ; TEST "captured" only through return
258 ; long *not_captured_but_returned_1(long *a) {
259 ;   *(a+1) = 1;
260 ;   return a + 1;
261 ; }
263 ; There should *not* be a no-capture attribute on %a
264 ; CHECK: define nonnull i64* @not_captured_but_returned_1(i64* %a)
265 define i64* @not_captured_but_returned_1(i64* %a) #0 {
266 entry:
267   %add.ptr = getelementptr inbounds i64, i64* %a, i64 1
268   store i64 1, i64* %add.ptr, align 8
269   ret i64* %add.ptr
272 ; TEST calls to "captured" only through return functions
274 ; void test_not_captured_but_returned_calls(long *a) {
275 ;   not_captured_but_returned_0(a);
276 ;   not_captured_but_returned_1(a);
277 ; }
279 ; FIXME: no-capture missing for %a
280 ; CHECK: define void @test_not_captured_but_returned_calls(i64* %a)
281 define void @test_not_captured_but_returned_calls(i64* %a) #0 {
282 entry:
283   %call = call i64* @not_captured_but_returned_0(i64* %a)
284   %call1 = call i64* @not_captured_but_returned_1(i64* %a)
285   ret void
288 ; TEST "captured" only through transitive return
290 ; long* negative_test_not_captured_but_returned_call_0a(long *a) {
291 ;   return not_captured_but_returned_0(a);
292 ; }
294 ; There should *not* be a no-capture attribute on %a
295 ; CHECK: define i64* @negative_test_not_captured_but_returned_call_0a(i64* returned %a)
296 define i64* @negative_test_not_captured_but_returned_call_0a(i64* %a) #0 {
297 entry:
298   %call = call i64* @not_captured_but_returned_0(i64* %a)
299   ret i64* %call
302 ; TEST captured through write
304 ; void negative_test_not_captured_but_returned_call_0b(long *a) {
305 ;   *a = (long)not_captured_but_returned_0(a);
306 ; }
308 ; There should *not* be a no-capture attribute on %a
309 ; CHECK: define void @negative_test_not_captured_but_returned_call_0b(i64* %a)
310 define void @negative_test_not_captured_but_returned_call_0b(i64* %a) #0 {
311 entry:
312   %call = call i64* @not_captured_but_returned_0(i64* %a)
313   %0 = ptrtoint i64* %call to i64
314   store i64 %0, i64* %a, align 8
315   ret void
318 ; TEST "captured" only through transitive return
320 ; long* negative_test_not_captured_but_returned_call_1a(long *a) {
321 ;   return not_captured_but_returned_1(a);
322 ; }
324 ; There should *not* be a no-capture attribute on %a
325 ; CHECK: define nonnull i64* @negative_test_not_captured_but_returned_call_1a(i64* %a)
326 define i64* @negative_test_not_captured_but_returned_call_1a(i64* %a) #0 {
327 entry:
328   %call = call i64* @not_captured_but_returned_1(i64* %a)
329   ret i64* %call
332 ; TEST captured through write
334 ; void negative_test_not_captured_but_returned_call_1b(long *a) {
335 ;   *a = (long)not_captured_but_returned_1(a);
336 ; }
338 ; There should *not* be a no-capture attribute on %a
339 ; CHECK: define void @negative_test_not_captured_but_returned_call_1b(i64* %a)
340 define void @negative_test_not_captured_but_returned_call_1b(i64* %a) #0 {
341 entry:
342   %call = call i64* @not_captured_but_returned_1(i64* %a)
343   %0 = ptrtoint i64* %call to i64
344   store i64 %0, i64* %call, align 8
345   ret void
348 ; TEST return argument or unknown call result
350 ; int* ret_arg_or_unknown(int* b) {
351 ;   if (b == 0)
352 ;     return b;
353 ;   return unknown();
354 ; }
356 ; Verify we do *not* assume b is returned or not captured.
358 ; CHECK:     define i32* @ret_arg_or_unknown(i32* readnone %b)
359 ; CHECK:     define i32* @ret_arg_or_unknown_through_phi(i32* readnone %b)
360 declare i32* @unknown()
362 define i32* @ret_arg_or_unknown(i32* %b) #0 {
363 entry:
364   %cmp = icmp eq i32* %b, null
365   br i1 %cmp, label %ret_arg, label %ret_unknown
367 ret_arg:
368   ret i32* %b
370 ret_unknown:
371   %call = call i32* @unknown()
372   ret i32* %call
375 define i32* @ret_arg_or_unknown_through_phi(i32* %b) #0 {
376 entry:
377   %cmp = icmp eq i32* %b, null
378   br i1 %cmp, label %ret_arg, label %ret_unknown
380 ret_arg:
381   br label %r
383 ret_unknown:
384   %call = call i32* @unknown()
385   br label %r
388   %phi = phi i32* [ %b, %ret_arg ], [ %call, %ret_unknown ]
389   ret i32* %phi
393 ; TEST not captured by readonly external function
395 ; CHECK: define void @not_captured_by_readonly_call(i32* nocapture %b)
396 declare i32* @readonly_unknown(i32*, i32*) readonly
398 define void @not_captured_by_readonly_call(i32* %b) #0 {
399 entry:
400   %call = call i32* @readonly_unknown(i32* %b, i32* %b)
401   ret void
405 ; TEST not captured by readonly external function if return chain is known
407 ; Make sure the returned flag on %r is strong enough to justify nocapture on %b but **not** on %r.
409 ; FIXME: The "returned" information is not propagated to the fullest extend causing us to miss "nocapture" on %b in the following:
410 ; CHECK: define i32* @not_captured_by_readonly_call_not_returned_either1(i32* readonly %b, i32* readonly returned %r)
412 ; CHECK: define i32* @not_captured_by_readonly_call_not_returned_either2(i32* readonly %b, i32* readonly returned %r)
413 ; CHECK: define i32* @not_captured_by_readonly_call_not_returned_either3(i32* readonly %b, i32* readonly returned %r)
415 ; FIXME: The "nounwind" information is not derived to the fullest extend causing us to miss "nocapture" on %b in the following:
416 ; CHECK: define i32* @not_captured_by_readonly_call_not_returned_either4(i32* readonly %b, i32* readonly returned %r)
417 define i32* @not_captured_by_readonly_call_not_returned_either1(i32* %b, i32* returned %r) #0 {
418 entry:
419   %call = call i32* @readonly_unknown(i32* %b, i32* %r) nounwind
420   ret i32* %call
423 declare i32* @readonly_unknown_r1a(i32*, i32* returned) readonly
424 define i32* @not_captured_by_readonly_call_not_returned_either2(i32* %b, i32* %r) #0 {
425 entry:
426   %call = call i32* @readonly_unknown_r1a(i32* %b, i32* %r) nounwind
427   ret i32* %call
430 declare i32* @readonly_unknown_r1b(i32*, i32* returned) readonly nounwind
431 define i32* @not_captured_by_readonly_call_not_returned_either3(i32* %b, i32* %r) #0 {
432 entry:
433   %call = call i32* @readonly_unknown_r1b(i32* %b, i32* %r)
434   ret i32* %call
437 define i32* @not_captured_by_readonly_call_not_returned_either4(i32* %b, i32* %r) #0 {
438 entry:
439   %call = call i32* @readonly_unknown_r1a(i32* %b, i32* %r)
440   ret i32* %call
443 attributes #0 = { noinline nounwind uwtable }