[AMDGPU] Add True16 register classes.
[llvm-project.git] / llvm / test / Analysis / StackSafetyAnalysis / ipa.ll
blobdd6d714e8e5eab7828e5dfa932bf7fb17f66e59d
1 ; REQUIRES: aarch64-registered-target
2 ; REQUIRES: shell
4 ; RUN: llvm-as %s -o %t0.bc
5 ; RUN: llvm-as %S/Inputs/ipa.ll -o %t1.bc
6 ; RUN: llvm-link -disable-lazy-loading %t0.bc %t1.bc -o %t.combined.bc
8 ; RUN: opt -S -passes="print<stack-safety-local>" -disable-output %t.combined.bc 2>&1 | FileCheck %s --check-prefixes=CHECK,LOCAL
10 ; RUN: opt -S -passes="print-stack-safety" -disable-output %t.combined.bc 2>&1 | FileCheck %s --check-prefixes=CHECK,GLOBAL,NOLTO
12 ; Do an end-to-test using the new LTO API
13 ; TODO: Hideous llvm-lto2 invocation, add a --default-symbol-resolution to llvm-lto2?
14 ; RUN: opt -module-summary %s -o %t.summ0.bc
15 ; RUN: opt -module-summary %S/Inputs/ipa.ll -o %t.summ1.bc
17 ; RUN: llvm-dis %t.summ0.bc -o - > %t.ids.txt
18 ; RUN: llvm-dis %t.summ1.bc -o - >> %t.ids.txt
20 ; RUN: echo > %t.res.txt \
21 ; RUN:  -r %t.summ0.bc,ExternalCall, \
22 ; RUN:  -r %t.summ0.bc,f1,px \
23 ; RUN:  -r %t.summ0.bc,f2,px \
24 ; RUN:  -r %t.summ0.bc,f3,px \
25 ; RUN:  -r %t.summ0.bc,f4,px \
26 ; RUN:  -r %t.summ0.bc,f5,px \
27 ; RUN:  -r %t.summ0.bc,f6,px \
28 ; RUN:  -r %t.summ0.bc,f7,px \
29 ; RUN:  -r %t.summ0.bc,f8left,px \
30 ; RUN:  -r %t.summ0.bc,f8oobleft,px \
31 ; RUN:  -r %t.summ0.bc,f8oobright,px \
32 ; RUN:  -r %t.summ0.bc,f8right,px \
33 ; RUN:  -r %t.summ0.bc,InterposableCall,px \
34 ; RUN:  -r %t.summ0.bc,InterposableWrite1, \
35 ; RUN:  -r %t.summ0.bc,PreemptableCall,px \
36 ; RUN:  -r %t.summ0.bc,PreemptableWrite1, \
37 ; RUN:  -r %t.summ0.bc,PrivateCall,px \
38 ; RUN:  -r %t.summ0.bc,Rec2, \
39 ; RUN:  -r %t.summ0.bc,RecursiveNoOffset, \
40 ; RUN:  -r %t.summ0.bc,RecursiveWithOffset, \
41 ; RUN:  -r %t.summ0.bc,ReturnDependent, \
42 ; RUN:  -r %t.summ0.bc,TestCrossModuleConflict,px \
43 ; RUN:  -r %t.summ0.bc,TestCrossModuleOnce,px \
44 ; RUN:  -r %t.summ0.bc,TestCrossModuleTwice,px \
45 ; RUN:  -r %t.summ0.bc,TestCrossModuleWeak,px \
46 ; RUN:  -r %t.summ0.bc,TestRecursiveNoOffset,px \
47 ; RUN:  -r %t.summ0.bc,TestRecursiveWithOffset,px \
48 ; RUN:  -r %t.summ0.bc,TestUpdateArg,px \
49 ; RUN:  -r %t.summ0.bc,TwoArguments,px \
50 ; RUN:  -r %t.summ0.bc,TwoArgumentsOOBBoth,px \
51 ; RUN:  -r %t.summ0.bc,TwoArgumentsOOBOne,px \
52 ; RUN:  -r %t.summ0.bc,TwoArgumentsOOBOther,px \
53 ; RUN:  -r %t.summ0.bc,Weak,x \
54 ; RUN:  -r %t.summ0.bc,Write1, \
55 ; RUN:  -r %t.summ0.bc,Write1DiffModule,x \
56 ; RUN:  -r %t.summ0.bc,Write1Module0,px \
57 ; RUN:  -r %t.summ0.bc,Write1Private,x \
58 ; RUN:  -r %t.summ0.bc,Write1SameModule,x \
59 ; RUN:  -r %t.summ0.bc,Write1Weak,x \
60 ; RUN:  -r %t.summ0.bc,Write4_2, \
61 ; RUN:  -r %t.summ0.bc,Write4, \
62 ; RUN:  -r %t.summ0.bc,Write8, \
63 ; RUN:  -r %t.summ0.bc,WriteAndReturn8, \
64 ; RUN:  -r %t.summ1.bc,ExternalCall,px \
65 ; RUN:  -r %t.summ1.bc,InterposableWrite1,px \
66 ; RUN:  -r %t.summ1.bc,PreemptableWrite1,px \
67 ; RUN:  -r %t.summ1.bc,Rec0,px \
68 ; RUN:  -r %t.summ1.bc,Rec1,px \
69 ; RUN:  -r %t.summ1.bc,Rec2,px \
70 ; RUN:  -r %t.summ1.bc,RecursiveNoOffset,px \
71 ; RUN:  -r %t.summ1.bc,RecursiveWithOffset,px \
72 ; RUN:  -r %t.summ1.bc,ReturnAlloca,px \
73 ; RUN:  -r %t.summ1.bc,ReturnDependent,px \
74 ; RUN:  -r %t.summ1.bc,Weak,x \
75 ; RUN:  -r %t.summ1.bc,Write1,px \
76 ; RUN:  -r %t.summ1.bc,Write1DiffModule,px \
77 ; RUN:  -r %t.summ1.bc,Write1Module0,x \
78 ; RUN:  -r %t.summ1.bc,Write1Private,px \
79 ; RUN:  -r %t.summ1.bc,Write1SameModule,px \
80 ; RUN:  -r %t.summ1.bc,Write1Weak,px \
81 ; RUN:  -r %t.summ1.bc,Write4_2,px \
82 ; RUN:  -r %t.summ1.bc,Write4,px \
83 ; RUN:  -r %t.summ1.bc,Write8,px \
84 ; RUN:  -r %t.summ1.bc,WriteAndReturn8,px
86 ; RUN: llvm-lto2 run %t.summ0.bc %t.summ1.bc -o %t.lto -stack-safety-print -stack-safety-run -save-temps -thinlto-threads 1 -O0 \
87 ; RUN:  $(cat %t.res.txt) \
88 ; RUN:    2>&1 | FileCheck %s --check-prefixes=CHECK,GLOBAL,LTO
90 ; RUN: llvm-lto2 run %t.summ0.bc %t.summ1.bc -o %t.lto -stack-safety-run -thinlto-distributed-indexes -thinlto-threads 1 -O0 $(cat %t.res.txt)
91 ; RUN: (cat %t.ids.txt ; llvm-dis %t.summ1.bc.thinlto.bc -o -) | FileCheck --check-prefixes=INDEX %s
93 target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
94 target triple = "aarch64-unknown-linux"
96 attributes #0 = { noinline sanitize_memtag "target-features"="+mte,+neon" }
98 declare void @Write1(ptr %p)
99 declare void @Write4(ptr %p)
100 declare void @Write4_2(ptr %p, ptr %q)
101 declare void @Write8(ptr %p)
102 declare dso_local ptr @WriteAndReturn8(ptr %p)
103 declare dso_local void @ExternalCall(ptr %p)
104 declare void @PreemptableWrite1(ptr %p)
105 declare void @InterposableWrite1(ptr %p)
106 declare ptr @ReturnDependent(ptr %p)
107 declare void @Rec2(ptr %p)
108 declare void @RecursiveNoOffset(ptr %p, i32 %size, ptr %acc)
109 declare void @RecursiveWithOffset(i32 %size, ptr %acc)
110 declare void @Write1SameModule(ptr %p)
111 declare void @Write1DiffModule(ptr %p)
112 declare void @Write1Private(ptr %p)
113 declare void @Write1Weak(ptr %p)
115 ; Basic out-of-bounds.
116 define void @f1() #0 {
117 ; CHECK-LABEL: @f1 dso_preemptable{{$}}
118 ; CHECK-NEXT: args uses:
119 ; CHECK-NEXT: allocas uses:
120 ; LOCAL-NEXT: x[4]: empty-set, @Write8(arg0, [0,1)){{$}}
121 ; GLOBAL-NEXT: x[4]: [0,8), @Write8(arg0, [0,1)){{$}}
122 ; GLOBAL-NEXT: safe accesses:
123 ; CHECK-EMPTY:
124 entry:
125   %x = alloca i32, align 4
126   call void @Write8(ptr %x)
127   ret void
130 ; Basic in-bounds.
131 define void @f2() #0 {
132 ; CHECK-LABEL: @f2 dso_preemptable{{$}}
133 ; CHECK-NEXT: args uses:
134 ; CHECK-NEXT: allocas uses:
135 ; LOCAL-NEXT: x[4]: empty-set, @Write1(arg0, [0,1)){{$}}
136 ; GLOBAL-NEXT: x[4]: [0,1), @Write1(arg0, [0,1)){{$}}
137 ; GLOBAL-NEXT: safe accesses:
138 ; CHECK-EMPTY:
139 entry:
140   %x = alloca i32, align 4
141   call void @Write1(ptr %x)
142   ret void
145 ; Another basic in-bounds.
146 define void @f3() #0 {
147 ; CHECK-LABEL: @f3 dso_preemptable{{$}}
148 ; CHECK-NEXT: args uses:
149 ; CHECK-NEXT: allocas uses:
150 ; LOCAL-NEXT: x[4]: empty-set, @Write4(arg0, [0,1)){{$}}
151 ; GLOBAL-NEXT: x[4]: [0,4), @Write4(arg0, [0,1)){{$}}
152 ; GLOBAL-NEXT: safe accesses:
153 ; CHECK-EMPTY:
154 entry:
155   %x = alloca i32, align 4
156   call void @Write4(ptr %x)
157   ret void
160 ; In-bounds with offset.
161 define void @f4() #0 {
162 ; CHECK-LABEL: @f4 dso_preemptable{{$}}
163 ; CHECK-NEXT: args uses:
164 ; CHECK-NEXT: allocas uses:
165 ; LOCAL-NEXT: x[4]: empty-set, @Write1(arg0, [1,2)){{$}}
166 ; GLOBAL-NEXT: x[4]: [1,2), @Write1(arg0, [1,2)){{$}}
167 ; GLOBAL-NEXT: safe accesses:
168 ; CHECK-EMPTY:
169 entry:
170   %x = alloca i32, align 4
171   %x2 = getelementptr i8, ptr %x, i64 1
172   call void @Write1(ptr %x2)
173   ret void
176 ; Out-of-bounds with offset.
177 define void @f5() #0 {
178 ; CHECK-LABEL: @f5 dso_preemptable{{$}}
179 ; CHECK-NEXT: args uses:
180 ; CHECK-NEXT: allocas uses:
181 ; LOCAL-NEXT: empty-set, @Write4(arg0, [1,2)){{$}}
182 ; GLOBAL-NEXT: [1,5), @Write4(arg0, [1,2)){{$}}
183 ; GLOBAL-NEXT: safe accesses:
184 ; CHECK-EMPTY:
185 entry:
186   %x = alloca i32, align 4
187   %x2 = getelementptr i8, ptr %x, i64 1
188   call void @Write4(ptr %x2)
189   ret void
192 ; External call.
193 define void @f6() #0 {
194 ; CHECK-LABEL: @f6 dso_preemptable{{$}}
195 ; CHECK-NEXT: args uses:
196 ; CHECK-NEXT: allocas uses:
197 ; LOCAL-NEXT: x[4]: empty-set, @ExternalCall(arg0, [0,1)){{$}}
198 ; GLOBAL-NEXT: x[4]: full-set, @ExternalCall(arg0, [0,1)){{$}}
199 ; GLOBAL-NEXT: safe accesses:
200 ; CHECK-EMPTY:
201 entry:
202   %x = alloca i32, align 4
203   call void @ExternalCall(ptr %x)
204   ret void
207 ; Call to dso_preemptable function
208 define void @PreemptableCall() #0 {
209 ; CHECK-LABEL: @PreemptableCall dso_preemptable{{$}}
210 ; CHECK-NEXT: args uses:
211 ; CHECK-NEXT: allocas uses:
212 ; LOCAL-NEXT: x[4]: empty-set, @PreemptableWrite1(arg0, [0,1)){{$}}
213 ; GLOBAL-NEXT: x[4]: full-set, @PreemptableWrite1(arg0, [0,1)){{$}}
214 ; GLOBAL-NEXT: safe accesses:
215 ; CHECK-EMPTY:
216 entry:
217   %x = alloca i32, align 4
218   call void @PreemptableWrite1(ptr %x)
219   ret void
222 ; Call to function with interposable linkage
223 define void @InterposableCall() #0 {
224 ; CHECK-LABEL: @InterposableCall dso_preemptable{{$}}
225 ; CHECK-NEXT: args uses:
226 ; CHECK-NEXT: allocas uses:
227 ; LOCAL-NEXT: x[4]: empty-set, @InterposableWrite1(arg0, [0,1)){{$}}
228 ; NOLTO-NEXT: x[4]: full-set, @InterposableWrite1(arg0, [0,1)){{$}}
229 ; LTO-NEXT: x[4]: [0,1), @InterposableWrite1(arg0, [0,1)){{$}}
230 ; GLOBAL-NEXT: safe accesses:
231 ; CHECK-EMPTY:
232 entry:
233   %x = alloca i32, align 4
234   call void @InterposableWrite1(ptr %x)
235   ret void
238 ; Call to function with private linkage
239 define void @PrivateCall() #0 {
240 ; CHECK-LABEL: @PrivateCall dso_preemptable{{$}}
241 ; CHECK-NEXT: args uses:
242 ; CHECK-NEXT: allocas uses:
243 ; LOCAL-NEXT: x[4]: empty-set, @PrivateWrite1(arg0, [0,1)){{$}}
244 ; GLOBAL-NEXT: x[4]: [0,1), @PrivateWrite1(arg0, [0,1)){{$}}
245 ; GLOBAL-NEXT: safe accesses:
246 ; CHECK-EMPTY:
247 entry:
248   %x = alloca i32, align 4
249   call void @PrivateWrite1(ptr %x)
250   ret void
253 define private void @PrivateWrite1(ptr %p) #0 {
254 ; CHECK-LABEL: @PrivateWrite1{{$}}
255 ; CHECK-NEXT: args uses:
256 ; CHECK-NEXT: p[]: [0,1){{$}}
257 ; CHECK-NEXT: allocas uses:
258 ; GLOBAL-NEXT: safe accesses:
259 ; GLOBAL-NEXT: store i8 0, ptr %p, align 1
260 ; CHECK-EMPTY:
261 entry:
262   store i8 0, ptr %p, align 1
263   ret void
266 ; Caller returns a dependent value.
267 ; FIXME: alloca considered unsafe even if the return value is unused.
268 define void @f7() #0 {
269 ; CHECK-LABEL: @f7 dso_preemptable{{$}}
270 ; CHECK-NEXT: args uses:
271 ; CHECK-NEXT: allocas uses:
272 ; LOCAL-NEXT: x[4]: empty-set, @ReturnDependent(arg0, [0,1)){{$}}
273 ; GLOBAL-NEXT: x[4]: full-set, @ReturnDependent(arg0, [0,1)){{$}}
274 ; GLOBAL-NEXT: safe accesses:
275 ; CHECK-EMPTY:
276 entry:
277   %x = alloca i32, align 4
278   %x2 = call ptr @ReturnDependent(ptr %x)
279   ret void
282 define void @f8left() #0 {
283 ; CHECK-LABEL: @f8left dso_preemptable{{$}}
284 ; CHECK-NEXT: args uses:
285 ; CHECK-NEXT: allocas uses:
286 ; LOCAL-NEXT: x[8]: empty-set, @Rec2(arg0, [2,3)){{$}}
287 ; GLOBAL-NEXT: x[8]: [0,4), @Rec2(arg0, [2,3)){{$}}
288 ; GLOBAL-NEXT: safe accesses:
289 ; CHECK-EMPTY:
290 entry:
291   %x = alloca i64, align 4
292   %x2 = getelementptr i8, ptr %x, i64 2
293 ; 2 + [-2, 2) = [0, 4) => OK
294   call void @Rec2(ptr %x2)
295   ret void
298 define void @f8right() #0 {
299 ; CHECK-LABEL: @f8right dso_preemptable{{$}}
300 ; CHECK-NEXT: args uses:
301 ; CHECK-NEXT: allocas uses:
302 ; LOCAL-NEXT: x[8]: empty-set, @Rec2(arg0, [6,7)){{$}}
303 ; GLOBAL-NEXT: x[8]: [4,8), @Rec2(arg0, [6,7)){{$}}
304 ; GLOBAL-NEXT: safe accesses:
305 ; CHECK-EMPTY:
306 entry:
307   %x = alloca i64, align 4
308   %x2 = getelementptr i8, ptr %x, i64 6
309 ; 6 + [-2, 2) = [4, 8) => OK
310   call void @Rec2(ptr %x2)
311   ret void
314 define void @f8oobleft() #0 {
315 ; CHECK-LABEL: @f8oobleft dso_preemptable{{$}}
316 ; CHECK-NEXT: args uses:
317 ; CHECK-NEXT: allocas uses:
318 ; LOCAL-NEXT: x[8]: empty-set, @Rec2(arg0, [1,2)){{$}}
319 ; GLOBAL-NEXT: x[8]: [-1,3), @Rec2(arg0, [1,2)){{$}}
320 ; GLOBAL-NEXT: safe accesses:
321 ; CHECK-EMPTY:
322 entry:
323   %x = alloca i64, align 4
324   %x2 = getelementptr i8, ptr %x, i64 1
325 ; 1 + [-2, 2) = [-1, 3) => NOT OK
326   call void @Rec2(ptr %x2)
327   ret void
330 define void @f8oobright() #0 {
331 ; CHECK-LABEL: @f8oobright dso_preemptable{{$}}
332 ; CHECK-NEXT: args uses:
333 ; CHECK-NEXT: allocas uses:
334 ; LOCAL-NEXT: x[8]: empty-set, @Rec2(arg0, [7,8)){{$}}
335 ; GLOBAL-NEXT: x[8]: [5,9), @Rec2(arg0, [7,8)){{$}}
336 ; GLOBAL-NEXT: safe accesses:
337 ; CHECK-EMPTY:
338 entry:
339   %x = alloca i64, align 4
340   %x2 = getelementptr i8, ptr %x, i64 7
341 ; 7 + [-2, 2) = [5, 9) => NOT OK
342   call void @Rec2(ptr %x2)
343   ret void
346 define void @TwoArguments() #0 {
347 ; CHECK-LABEL: @TwoArguments dso_preemptable{{$}}
348 ; CHECK-NEXT: args uses:
349 ; CHECK-NEXT: allocas uses:
350 ; LOCAL-NEXT: x[8]: empty-set, @Write4_2(arg0, [4,5)), @Write4_2(arg1, [0,1)){{$}}
351 ; GLOBAL-NEXT: x[8]: [0,8), @Write4_2(arg0, [4,5)), @Write4_2(arg1, [0,1)){{$}}
352 ; GLOBAL-NEXT: safe accesses:
353 ; CHECK-EMPTY:
354 entry:
355   %x = alloca i64, align 4
356   %x2 = getelementptr i8, ptr %x, i64 4
357   call void @Write4_2(ptr %x2, ptr %x)
358   ret void
361 define void @TwoArgumentsOOBOne() #0 {
362 ; CHECK-LABEL: @TwoArgumentsOOBOne dso_preemptable{{$}}
363 ; CHECK-NEXT: args uses:
364 ; CHECK-NEXT: allocas uses:
365 ; LOCAL-NEXT: x[8]: empty-set, @Write4_2(arg0, [5,6)), @Write4_2(arg1, [0,1)){{$}}
366 ; GLOBAL-NEXT: x[8]: [0,9), @Write4_2(arg0, [5,6)), @Write4_2(arg1, [0,1)){{$}}
367 ; GLOBAL-NEXT: safe accesses:
368 ; CHECK-EMPTY:
369 entry:
370   %x = alloca i64, align 4
371   %x2 = getelementptr i8, ptr %x, i64 5
372   call void @Write4_2(ptr %x2, ptr %x)
373   ret void
376 define void @TwoArgumentsOOBOther() #0 {
377 ; CHECK-LABEL: @TwoArgumentsOOBOther dso_preemptable{{$}}
378 ; CHECK-NEXT: args uses:
379 ; CHECK-NEXT: allocas uses:
380 ; LOCAL-NEXT: x[8]: empty-set, @Write4_2(arg0, [4,5)), @Write4_2(arg1, [-1,0)){{$}}
381 ; GLOBAL-NEXT: x[8]: [-1,8), @Write4_2(arg0, [4,5)), @Write4_2(arg1, [-1,0)){{$}}
382 ; GLOBAL-NEXT: safe accesses:
383 ; CHECK-EMPTY:
384 entry:
385   %x = alloca i64, align 4
386   %x1 = getelementptr i8, ptr %x, i64 -1
387   %x2 = getelementptr i8, ptr %x, i64 4
388   call void @Write4_2(ptr %x2, ptr %x1)
389   ret void
392 define void @TwoArgumentsOOBBoth() #0 {
393 ; CHECK-LABEL: @TwoArgumentsOOBBoth dso_preemptable{{$}}
394 ; CHECK-NEXT: args uses:
395 ; CHECK-NEXT: allocas uses:
396 ; LOCAL-NEXT: x[8]: empty-set, @Write4_2(arg0, [5,6)), @Write4_2(arg1, [-1,0)){{$}}
397 ; GLOBAL-NEXT: x[8]: [-1,9), @Write4_2(arg0, [5,6)), @Write4_2(arg1, [-1,0)){{$}}
398 ; GLOBAL-NEXT: safe accesses:
399 ; CHECK-EMPTY:
400 entry:
401   %x = alloca i64, align 4
402   %x1 = getelementptr i8, ptr %x, i64 -1
403   %x2 = getelementptr i8, ptr %x, i64 5
404   call void @Write4_2(ptr %x2, ptr %x1)
405   ret void
408 define i32 @TestRecursiveNoOffset(ptr %p, i32 %size) #0 {
409 ; CHECK-LABEL: @TestRecursiveNoOffset dso_preemptable{{$}}
410 ; CHECK-NEXT: args uses:
411 ; LOCAL-NEXT: p[]: empty-set, @RecursiveNoOffset(arg0, [0,1)){{$}}
412 ; GLOBAL-NEXT: p[]: full-set, @RecursiveNoOffset(arg0, [0,1)){{$}}
413 ; CHECK-NEXT: allocas uses:
414 ; CHECK-NEXT: sum[4]: [0,4), @RecursiveNoOffset(arg2, [0,1)){{$}}
415 ; GLOBAL-NEXT: safe accesses:
416 ; GLOBAL-NEXT: store i32 0, ptr %sum, align 4
417 ; GLOBAL-NEXT: %load = load i32, ptr %sum, align 4
418 ; CHECK-EMPTY:
419 entry:
420   %sum = alloca i32, align 4
421   store i32 0, ptr %sum, align 4
422   call void @RecursiveNoOffset(ptr %p, i32 %size, ptr %sum)
423   %load = load i32, ptr %sum, align 4
424   ret i32 %load
427 define void @TestRecursiveWithOffset(i32 %size) #0 {
428 ; CHECK-LABEL: @TestRecursiveWithOffset dso_preemptable{{$}}
429 ; CHECK-NEXT: args uses:
430 ; CHECK-NEXT: allocas uses:
431 ; LOCAL-NEXT: sum[64]: empty-set, @RecursiveWithOffset(arg1, [0,1)){{$}}
432 ; GLOBAL-NEXT: sum[64]: full-set, @RecursiveWithOffset(arg1, [0,1)){{$}}
433 ; GLOBAL-NEXT: safe accesses:
434 ; CHECK-EMPTY:
435 entry:
436   %sum = alloca i32, i64 16, align 4
437   call void @RecursiveWithOffset(i32 %size, ptr %sum)
438   ret void
441 ; FIXME: IPA should detect that access is safe
442 define void @TestUpdateArg() #0 {
443 ; CHECK-LABEL: @TestUpdateArg dso_preemptable{{$}}
444 ; CHECK-NEXT: args uses:
445 ; CHECK-NEXT: allocas uses:
446 ; LOCAL-NEXT: x[16]: empty-set, @WriteAndReturn8(arg0, [0,1)){{$}}
447 ; GLOBAL-NEXT: x[16]: full-set, @WriteAndReturn8(arg0, [0,1)){{$}}
448 ; GLOBAL-NEXT: safe accesses:
449 ; CHECK-EMPTY:
450 entry:
451   %x = alloca i8, i64 16, align 4
452   %0 = call ptr @WriteAndReturn8(ptr %x)
453   ret void
456 define void @TestCrossModuleOnce() #0 {
457 ; CHECK-DAG: @TestCrossModuleOnce dso_preemptable{{$}}
458 ; CHECK-NEXT: args uses:
459 ; CHECK-NEXT: allocas uses:
460 ; LOCAL-NEXT: y[1]: empty-set, @Write1SameModule(arg0, [0,1)){{$}}
461 ; GLOBAL-NEXT: y[1]: [0,1), @Write1SameModule(arg0, [0,1)){{$}}
462 ; GLOBAL-NEXT: safe accesses:
463 ; CHECK-EMPTY:
464 entry:
465   %y = alloca i8, align 4
466   call void @Write1SameModule(ptr %y)
467   ret void
470 define void @TestCrossModuleTwice() #0 {
471 ; CHECK-DAG: @TestCrossModuleTwice dso_preemptable{{$}}
472 ; CHECK-NEXT: args uses:
473 ; CHECK-NEXT: allocas uses:
474 ; LOCAL-NEXT: z[1]: empty-set, @Write1DiffModule(arg0, [0,1)){{$}}
475 ; GLOBAL-NEXT: z[1]: [0,1), @Write1DiffModule(arg0, [0,1)){{$}}
476 ; GLOBAL-NEXT: safe accesses:
477 ; CHECK-EMPTY:
478 entry:
479   %z = alloca i8, align 4
480   call void @Write1DiffModule(ptr %z)
481   ret void
484 define void @TestCrossModuleConflict() #0 {
485 ; CHECK-DAG: @TestCrossModuleConflict dso_preemptable{{$}}
486 ; CHECK-NEXT: args uses:
487 ; CHECK-NEXT: allocas uses:
488 ; LOCAL-NEXT: x[1]: empty-set, @Write1Private(arg0, [0,1)){{$}}
489 ; GLOBAL-NEXT: x[1]: [-1,0), @Write1Private(arg0, [0,1)){{$}}
490 ; GLOBAL-NEXT: safe accesses:
491 ; CHECK-EMPTY:
492 entry:
493   %x = alloca i8, align 4
494   call void @Write1Private(ptr %x)
495   ret void
498 ; FIXME: LTO should match NOLTO
499 define void @TestCrossModuleWeak() #0 {
500 ; CHECK-DAG: @TestCrossModuleWeak dso_preemptable{{$}}
501 ; CHECK-NEXT: args uses:
502 ; CHECK-NEXT: allocas uses:
503 ; LOCAL-NEXT: x[1]: empty-set, @Write1Weak(arg0, [0,1)){{$}}
504 ; NOLTO-NEXT: x[1]: [1,2), @Write1Weak(arg0, [0,1)){{$}}
505 ; LTO-NEXT: x[1]: full-set, @Write1Weak(arg0, [0,1)){{$}}
506 ; GLOBAL-NEXT: safe accesses:
507 ; CHECK-EMPTY:
508 entry:
509   %x = alloca i8, align 4
510   call void @Write1Weak(ptr %x)
511   ret void
514 define private dso_local void @Private(ptr %p) #0 {
515 entry:
516   %p1 = getelementptr i8, ptr %p, i64 1
517   store i8 0, ptr %p1, align 1
518   ret void
521 define dso_local void @Write1Module0(ptr %p) #0 {
522 entry:
523   store i8 0, ptr %p, align 1
524   ret void
527 define dso_local void @Weak(ptr %p) #0 {
528 entry:
529   %p1 = getelementptr i8, ptr %p, i64 1
530   store i8 0, ptr %p1, align 1
531   ret void
534 ; The rest is from Inputs/ipa.ll
536 ; CHECK-LABEL: @Write1{{$}}
537 ; CHECK-NEXT: args uses:
538 ; CHECK-NEXT: p[]: [0,1){{$}}
539 ; CHECK-NEXT: allocas uses:
540 ; GLOBAL-NEXT: safe accesses:
541 ; GLOBAL-NEXT: store i8 0, ptr %p, align 1
542 ; CHECK-EMPTY:
544 ; CHECK-LABEL: @Write4{{$}}
545 ; CHECK-NEXT: args uses:
546 ; CHECK-NEXT: p[]: [0,4){{$}}
547 ; CHECK-NEXT: allocas uses:
548 ; GLOBAL-NEXT: safe accesses:
549 ; GLOBAL-NEXT: store i32 0, ptr %p, align 1
550 ; CHECK-EMPTY:
552 ; CHECK-LABEL: @Write4_2{{$}}
553 ; CHECK-NEXT: args uses:
554 ; CHECK-NEXT: p[]: [0,4){{$}}
555 ; CHECK-NEXT: q[]: [0,4){{$}}
556 ; CHECK-NEXT: allocas uses:
557 ; GLOBAL-NEXT: safe accesses:
558 ; GLOBAL-NEXT: store i32 0, ptr %p, align 1
559 ; GLOBAL-NEXT: store i32 0, ptr %q, align 1
560 ; CHECK-EMPTY:
562 ; CHECK-LABEL: @Write8{{$}}
563 ; CHECK-NEXT: args uses:
564 ; CHECK-NEXT: p[]: [0,8){{$}}
565 ; CHECK-NEXT: allocas uses:
566 ; GLOBAL-NEXT: safe accesses:
567 ; GLOBAL-NEXT: store i64 0, ptr %p, align 1
568 ; CHECK-EMPTY:
570 ; CHECK-LABEL: @WriteAndReturn8{{$}}
571 ; CHECK-NEXT: args uses:
572 ; CHECK-NEXT: p[]: full-set{{$}}
573 ; CHECK-NEXT: allocas uses:
574 ; GLOBAL-NEXT: safe accesses:
575 ; GLOBAL-NEXT: store i8 0, ptr %p, align 1
576 ; CHECK-EMPTY:
578 ; CHECK-LABEL: @PreemptableWrite1 dso_preemptable{{$}}
579 ; CHECK-NEXT: args uses:
580 ; CHECK-NEXT: p[]: [0,1){{$}}
581 ; CHECK-NEXT: allocas uses:
582 ; GLOBAL-NEXT: safe accesses:
583 ; GLOBAL-NEXT: store i8 0, ptr %p, align 1
584 ; CHECK-EMPTY:
586 ; CHECK-LABEL: @InterposableWrite1 interposable{{$}}
587 ; CHECK-NEXT: args uses:
588 ; CHECK-NEXT: p[]: [0,1){{$}}
589 ; CHECK-NEXT: allocas uses:
590 ; GLOBAL-NEXT: safe accesses:
591 ; GLOBAL-NEXT: store i8 0, ptr %p, align 1
592 ; CHECK-EMPTY:
594 ; CHECK-LABEL: @ReturnDependent{{$}}
595 ; CHECK-NEXT: args uses:
596 ; CHECK-NEXT: p[]: full-set{{$}}
597 ; CHECK-NEXT: allocas uses:
598 ; GLOBAL-NEXT: safe accesses:
599 ; CHECK-EMPTY:
601 ; CHECK-LABEL: @Rec0{{$}}
602 ; CHECK-NEXT: args uses:
603 ; LOCAL-NEXT: p[]: empty-set, @Write4(arg0, [2,3)){{$}}
604 ; GLOBAL-NEXT: p[]: [2,6)
605 ; CHECK-NEXT: allocas uses:
606 ; GLOBAL-NEXT: safe accesses:
607 ; CHECK-EMPTY:
609 ; CHECK-LABEL: @Rec1{{$}}
610 ; CHECK-NEXT: args uses:
611 ; LOCAL-NEXT: p[]: empty-set, @Rec0(arg0, [1,2)){{$}}
612 ; GLOBAL-NEXT: p[]: [3,7)
613 ; CHECK-NEXT: allocas uses:
614 ; GLOBAL-NEXT: safe accesses:
615 ; CHECK-EMPTY:
617 ; CHECK-LABEL: @Rec2{{$}}
618 ; CHECK-NEXT: args uses:
619 ; LOCAL-NEXT: p[]: empty-set, @Rec1(arg0, [-5,-4)){{$}}
620 ; GLOBAL-NEXT: p[]: [-2,2)
621 ; CHECK-NEXT: allocas uses:
622 ; GLOBAL-NEXT: safe accesses:
623 ; CHECK-EMPTY:
625 ; CHECK-LABEL: @RecursiveNoOffset{{$}}
626 ; CHECK-NEXT: args uses:
627 ; LOCAL-NEXT: p[]: [0,4), @RecursiveNoOffset(arg0, [4,5)){{$}}
628 ; GLOBAL-NEXT: p[]: full-set, @RecursiveNoOffset(arg0, [4,5)){{$}}
629 ; CHECK-NEXT: acc[]: [0,4), @RecursiveNoOffset(arg2, [0,1)){{$}}
630 ; CHECK-NEXT: allocas uses:
631 ; GLOBAL-NEXT: safe accesses:
632 ; GLOBAL-NEXT: %load0 = load i32, ptr %p, align 4
633 ; GLOBAL-NEXT: %load1 = load i32, ptr %acc, align 4
634 ; GLOBAL-NEXT: store i32 %add, ptr %acc, align 4
635 ; CHECK-EMPTY:
637 ; CHECK-LABEL: @RecursiveWithOffset{{$}}
638 ; CHECK-NEXT: args uses:
639 ; LOCAL-NEXT: acc[]: [0,4), @RecursiveWithOffset(arg1, [4,5)){{$}}
640 ; GLOBAL-NEXT: acc[]: full-set, @RecursiveWithOffset(arg1, [4,5)){{$}}
641 ; CHECK-NEXT: allocas uses:
642 ; GLOBAL-NEXT: safe accesses:
643 ; GLOBAL-NEXT: store i32 0, ptr %acc, align 4
644 ; CHECK-EMPTY:
646 ; CHECK-LABEL: @ReturnAlloca
647 ; CHECK-NEXT: args uses:
648 ; CHECK-NEXT: allocas uses:
649 ; CHECK-NEXT: x[8]: full-set
650 ; GLOBAL-NEXT: safe accesses:
651 ; CHECK-EMPTY:
653 ; INDEX-LABEL: ^0 = module:
654 ; INDEX-DAG: name: "ReturnDependent"{{.*}} guid = [[ReturnDependent:[-0-9]+]]
655 ; INDEX-DAG: name: "Private"{{.*}} guid = [[Private:[-0-9]+]]
656 ; INDEX-DAG: name: "TwoArgumentsOOBOther"{{.*}} guid = [[TwoArgumentsOOBOther:[-0-9]+]]
657 ; INDEX-DAG: name: "Rec2"{{.*}} guid = [[Rec2:[-0-9]+]]
658 ; INDEX-DAG: name: "f1"{{.*}} guid = [[f1:[-0-9]+]]
659 ; INDEX-DAG: name: "PrivateWrite1"{{.*}} guid = [[PrivateWrite1:[-0-9]+]]
660 ; INDEX-DAG: name: "TestRecursiveNoOffset"{{.*}} guid = [[TestRecursiveNoOffset:[-0-9]+]]
661 ; INDEX-DAG: name: "f8left"{{.*}} guid = [[f8left:[-0-9]+]]
662 ; INDEX-DAG: name: "Write4"{{.*}} guid = [[Write4:[-0-9]+]]
663 ; INDEX-DAG: name: "f7"{{.*}} guid = [[f7:[-0-9]+]]
664 ; INDEX-DAG: name: "Write1SameModule"{{.*}} guid = [[Write1SameModule:[-0-9]+]]
665 ; INDEX-DAG: name: "Write8"{{.*}} guid = [[Write8:[-0-9]+]]
666 ; INDEX-DAG: name: "TwoArgumentsOOBOne"{{.*}} guid = [[TwoArgumentsOOBOne:[-0-9]+]]
667 ; INDEX-DAG: name: "f3"{{.*}} guid = [[f3:[-0-9]+]]
668 ; INDEX-DAG: name: "f8right"{{.*}} guid = [[f8right:[-0-9]+]]
669 ; INDEX-DAG: name: "Write4_2"{{.*}} guid = [[Write4_2:[-0-9]+]]
670 ; INDEX-DAG: name: "RecursiveWithOffset"{{.*}} guid = [[RecursiveWithOffset:[-0-9]+]]
671 ; INDEX-DAG: name: "Weak"{{.*}} guid = [[Weak:[-0-9]+]]
672 ; INDEX-DAG: name: "Write1Private"{{.*}} guid = [[Write1Private:[-0-9]+]]
673 ; INDEX-DAG: name: "TestUpdateArg"{{.*}} guid = [[TestUpdateArg:[-0-9]+]]
674 ; INDEX-DAG: name: "TestCrossModuleTwice"{{.*}} guid = [[TestCrossModuleTwice:[-0-9]+]]
675 ; INDEX-DAG: name: "TestCrossModuleWeak"{{.*}} guid = [[TestCrossModuleWeak:[-0-9]+]]
676 ; INDEX-DAG: name: "f2"{{.*}} guid = [[f2:[-0-9]+]]
677 ; INDEX-DAG: name: "PrivateCall"{{.*}} guid = [[PrivateCall:[-0-9]+]]
678 ; INDEX-DAG: name: "TestRecursiveWithOffset"{{.*}} guid = [[TestRecursiveWithOffset:[-0-9]+]]
679 ; INDEX-DAG: name: "f8oobleft"{{.*}} guid = [[f8oobleft:[-0-9]+]]
680 ; INDEX-DAG: name: "InterposableWrite1"{{.*}} guid = [[InterposableWrite1:[-0-9]+]]
681 ; INDEX-DAG: name: "f4"{{.*}} guid = [[f4:[-0-9]+]]
682 ; INDEX-DAG: name: "TestCrossModuleConflict"{{.*}} guid = [[TestCrossModuleConflict:[-0-9]+]]
683 ; INDEX-DAG: name: "RecursiveNoOffset"{{.*}} guid = [[RecursiveNoOffset:[-0-9]+]]
684 ; INDEX-DAG: name: "TwoArgumentsOOBBoth"{{.*}} guid = [[TwoArgumentsOOBBoth:[-0-9]+]]
685 ; INDEX-DAG: name: "f5"{{.*}} guid = [[f5:[-0-9]+]]
686 ; INDEX-DAG: name: "f6"{{.*}} guid = [[f6:[-0-9]+]]
687 ; INDEX-DAG: name: "Write1Weak"{{.*}} guid = [[Write1Weak:[-0-9]+]]
688 ; INDEX-DAG: name: "Write1"{{.*}} guid = [[Write1:[-0-9]+]]
689 ; INDEX-DAG: name: "PreemptableWrite1"{{.*}} guid = [[PreemptableWrite1:[-0-9]+]]
690 ; INDEX-DAG: name: "f8oobright"{{.*}} guid = [[f8oobright:[-0-9]+]]
691 ; INDEX-DAG: name: "InterposableCall"{{.*}} guid = [[InterposableCall:[-0-9]+]]
692 ; INDEX-DAG: name: "TestCrossModuleOnce"{{.*}} guid = [[TestCrossModuleOnce:[-0-9]+]]
693 ; INDEX-DAG: name: "WriteAndReturn8"{{.*}} guid = [[WriteAndReturn8:[-0-9]+]]
694 ; INDEX-DAG: name: "TwoArguments"{{.*}} guid = [[TwoArguments:[-0-9]+]]
695 ; INDEX-DAG: name: "Write1Module0"{{.*}} guid = [[Write1Module0:[-0-9]+]]
696 ; INDEX-DAG: name: "PreemptableCall"{{.*}} guid = [[PreemptableCall:[-0-9]+]]
697 ; INDEX-DAG: name: "Write1DiffModule"{{.*}} guid = [[Write1DiffModule:[-0-9]+]]
698 ; INDEX-DAG: name: "ExternalCall"{{.*}} guid = [[ExternalCall:[-0-9]+]]
699 ; INDEX-LABEL: = blockcount:
701 ; INDEX-LABEL: ^0 = module:
702 ; INDEX-DAG: name: "ReturnDependent"{{.*}} guid = [[ReturnDependent:[-0-9]+]]
703 ; INDEX-DAG: name: "Rec0"{{.*}} guid = [[Rec0:[-0-9]+]]
704 ; INDEX-DAG: name: "Rec2"{{.*}} guid = [[Rec2:[-0-9]+]]
705 ; INDEX-DAG: name: "Write4"{{.*}} guid = [[Write4:[-0-9]+]]
706 ; INDEX-DAG: name: "Write1SameModule"{{.*}} guid = [[Write1SameModule:[-0-9]+]]
707 ; INDEX-DAG: name: "Write8"{{.*}} guid = [[Write8:[-0-9]+]]
708 ; INDEX-DAG: name: "Write4_2"{{.*}} guid = [[Write4_2:[-0-9]+]]
709 ; INDEX-DAG: name: "RecursiveWithOffset"{{.*}} guid = [[RecursiveWithOffset:[-0-9]+]]
710 ; INDEX-DAG: name: "Weak"{{.*}} guid = [[Weak:[-0-9]+]]
711 ; INDEX-DAG: name: "Write1Private"{{.*}} guid = [[Write1Private:[-0-9]+]]
712 ; INDEX-DAG: name: "InterposableWrite1"{{.*}} guid = [[InterposableWrite1:[-0-9]+]]
713 ; INDEX-DAG: name: "Private"{{.*}} guid = [[Private:[-0-9]+]]
714 ; INDEX-DAG: name: "Rec1"{{.*}} guid = [[Rec1:[-0-9]+]]
715 ; INDEX-DAG: name: "RecursiveNoOffset"{{.*}} guid = [[RecursiveNoOffset:[-0-9]+]]
716 ; INDEX-DAG: name: "Write1Weak"{{.*}} guid = [[Write1Weak:[-0-9]+]]
717 ; INDEX-DAG: name: "Write1"{{.*}} guid = [[Write1:[-0-9]+]]
718 ; INDEX-DAG: name: "PreemptableWrite1"{{.*}} guid = [[PreemptableWrite1:[-0-9]+]]
719 ; INDEX-DAG: name: "WriteAndReturn8"{{.*}} guid = [[WriteAndReturn8:[-0-9]+]]
720 ; INDEX-DAG: name: "Write1Module0"{{.*}} guid = [[Write1Module0:[-0-9]+]]
721 ; INDEX-DAG: name: "Write1DiffModule"{{.*}} guid = [[Write1DiffModule:[-0-9]+]]
722 ; INDEX-DAG: name: "ExternalCall"{{.*}} guid = [[ExternalCall:[-0-9]+]]
723 ; INDEX-DAG: name: "ReturnAlloca"{{.*}} guid = [[ReturnAlloca:[-0-9]+]]
724 ; INDEX-LABEL: = blockcount:
726 ; INDEX-LABEL: ^0 = module:
727 ; INDEX-DAG: guid: [[ReturnDependent]], {{.*}}, funcFlags: ({{.*}}))))
728 ; INDEX-DAG: guid: [[Rec0]], {{.*}}, params: ((param: 0, offset: [2, 5])))))
729 ; INDEX-DAG: guid: [[Rec2]], {{.*}}, params: ((param: 0, offset: [-2, 1])))))
730 ; INDEX-DAG: guid: [[Write4]], {{.*}}, params: ((param: 0, offset: [0, 3])))))
731 ; INDEX-DAG: guid: [[Write1SameModule]], {{.*}}, params: ((param: 0, offset: [0, 0])))))
732 ; INDEX-DAG: guid: [[Write8]], {{.*}}, params: ((param: 0, offset: [0, 7])))))
733 ; INDEX-DAG: guid: [[Write4_2]], {{.*}}, params: ((param: 0, offset: [0, 3]), (param: 1, offset: [0, 3])))))
734 ; INDEX-DAG: guid: [[RecursiveWithOffset]], {{.*}}, calls: ((callee: ^{{[0-9]+}})))))
735 ; INDEX-DAG: guid: [[Weak]], {{.*}}, funcFlags: ({{.*}}))))
736 ; INDEX-DAG: guid: [[Write1Private]], {{.*}}, params: ((param: 0, offset: [-1, -1])))))
737 ; INDEX-DAG: guid: [[InterposableWrite1]], {{.*}}, params: ((param: 0, offset: [0, 0])))))
738 ; INDEX-DAG: guid: [[Private]], {{.*}}, params: ((param: 0, offset: [-1, -1])))))
739 ; INDEX-DAG: guid: [[Rec1]], {{.*}}, params: ((param: 0, offset: [3, 6])))))
740 ; INDEX-DAG: guid: [[RecursiveNoOffset]], {{.*}}, params: ((param: 2, offset: [0, 3])))))
741 ; INDEX-DAG: guid: [[Write1Weak]], {{.*}}, calls: ((callee: ^{{[0-9]+}})))))
742 ; INDEX-DAG: guid: [[Write1]], {{.*}}, params: ((param: 0, offset: [0, 0])))))
743 ; INDEX-DAG: guid: [[PreemptableWrite1]], {{.*}}, funcFlags: ({{.*}}))))
744 ; INDEX-DAG: guid: [[WriteAndReturn8]], {{.*}}, funcFlags: ({{.*}}))))
745 ; INDEX-DAG: guid: [[Write1DiffModule]], {{.*}}, funcFlags: ({{.*}}))))
746 ; INDEX-DAG: guid: [[ReturnAlloca]], {{.*}}, insts: 2)))
747 ; INDEX-LABEL: blockcount: