1 ; REQUIRES: aarch64-registered-target
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 ; RUN: llvm-lto2 run %t.summ0.bc %t.summ1.bc -o %t-newpm.lto -use-new-pm -stack-safety-print -stack-safety-run -save-temps -thinlto-threads 1 -O0 \
94 ; RUN: $(cat %t.res.txt) \
95 ; RUN: 2>&1 | FileCheck %s --check-prefixes=CHECK,GLOBAL,LTO
97 ; RUN: llvm-lto2 run %t.summ0.bc %t.summ1.bc -o %t-newpm.lto -stack-safety-run -thinlto-distributed-indexes -thinlto-threads 1 -O0 $(cat %t.res.txt)
98 ; RUN: (cat %t.ids.txt ; llvm-dis %t.summ1.bc.thinlto.bc -o -) | FileCheck --check-prefixes=INDEX %s
100 target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
101 target triple = "aarch64-unknown-linux"
103 attributes #0 = { noinline sanitize_memtag "target-features"="+mte,+neon" }
105 declare void @Write1(i8* %p)
106 declare void @Write4(i8* %p)
107 declare void @Write4_2(i8* %p, i8* %q)
108 declare void @Write8(i8* %p)
109 declare dso_local i8* @WriteAndReturn8(i8* %p)
110 declare dso_local void @ExternalCall(i8* %p)
111 declare void @PreemptableWrite1(i8* %p)
112 declare void @InterposableWrite1(i8* %p)
113 declare i8* @ReturnDependent(i8* %p)
114 declare void @Rec2(i8* %p)
115 declare void @RecursiveNoOffset(i32* %p, i32 %size, i32* %acc)
116 declare void @RecursiveWithOffset(i32 %size, i32* %acc)
117 declare void @Write1SameModule(i8* %p)
118 declare void @Write1DiffModule(i8* %p)
119 declare void @Write1Private(i8* %p)
120 declare void @Write1Weak(i8* %p)
122 ; Basic out-of-bounds.
123 define void @f1() #0 {
124 ; CHECK-LABEL: @f1 dso_preemptable{{$}}
125 ; CHECK-NEXT: args uses:
126 ; CHECK-NEXT: allocas uses:
127 ; LOCAL-NEXT: x[4]: empty-set, @Write8(arg0, [0,1)){{$}}
128 ; GLOBAL-NEXT: x[4]: [0,8), @Write8(arg0, [0,1)){{$}}
129 ; GLOBAL-NEXT: safe accesses:
132 %x = alloca i32, align 4
133 %x1 = bitcast i32* %x to i8*
134 call void @Write8(i8* %x1)
139 define void @f2() #0 {
140 ; CHECK-LABEL: @f2 dso_preemptable{{$}}
141 ; CHECK-NEXT: args uses:
142 ; CHECK-NEXT: allocas uses:
143 ; LOCAL-NEXT: x[4]: empty-set, @Write1(arg0, [0,1)){{$}}
144 ; GLOBAL-NEXT: x[4]: [0,1), @Write1(arg0, [0,1)){{$}}
145 ; GLOBAL-NEXT: safe accesses:
148 %x = alloca i32, align 4
149 %x1 = bitcast i32* %x to i8*
150 call void @Write1(i8* %x1)
154 ; Another basic in-bounds.
155 define void @f3() #0 {
156 ; CHECK-LABEL: @f3 dso_preemptable{{$}}
157 ; CHECK-NEXT: args uses:
158 ; CHECK-NEXT: allocas uses:
159 ; LOCAL-NEXT: x[4]: empty-set, @Write4(arg0, [0,1)){{$}}
160 ; GLOBAL-NEXT: x[4]: [0,4), @Write4(arg0, [0,1)){{$}}
161 ; GLOBAL-NEXT: safe accesses:
164 %x = alloca i32, align 4
165 %x1 = bitcast i32* %x to i8*
166 call void @Write4(i8* %x1)
170 ; In-bounds with offset.
171 define void @f4() #0 {
172 ; CHECK-LABEL: @f4 dso_preemptable{{$}}
173 ; CHECK-NEXT: args uses:
174 ; CHECK-NEXT: allocas uses:
175 ; LOCAL-NEXT: x[4]: empty-set, @Write1(arg0, [1,2)){{$}}
176 ; GLOBAL-NEXT: x[4]: [1,2), @Write1(arg0, [1,2)){{$}}
177 ; GLOBAL-NEXT: safe accesses:
180 %x = alloca i32, align 4
181 %x1 = bitcast i32* %x to i8*
182 %x2 = getelementptr i8, i8* %x1, i64 1
183 call void @Write1(i8* %x2)
187 ; Out-of-bounds with offset.
188 define void @f5() #0 {
189 ; CHECK-LABEL: @f5 dso_preemptable{{$}}
190 ; CHECK-NEXT: args uses:
191 ; CHECK-NEXT: allocas uses:
192 ; LOCAL-NEXT: empty-set, @Write4(arg0, [1,2)){{$}}
193 ; GLOBAL-NEXT: [1,5), @Write4(arg0, [1,2)){{$}}
194 ; GLOBAL-NEXT: safe accesses:
197 %x = alloca i32, align 4
198 %x1 = bitcast i32* %x to i8*
199 %x2 = getelementptr i8, i8* %x1, i64 1
200 call void @Write4(i8* %x2)
205 define void @f6() #0 {
206 ; CHECK-LABEL: @f6 dso_preemptable{{$}}
207 ; CHECK-NEXT: args uses:
208 ; CHECK-NEXT: allocas uses:
209 ; LOCAL-NEXT: x[4]: empty-set, @ExternalCall(arg0, [0,1)){{$}}
210 ; GLOBAL-NEXT: x[4]: full-set, @ExternalCall(arg0, [0,1)){{$}}
211 ; GLOBAL-NEXT: safe accesses:
214 %x = alloca i32, align 4
215 %x1 = bitcast i32* %x to i8*
216 call void @ExternalCall(i8* %x1)
220 ; Call to dso_preemptable function
221 define void @PreemptableCall() #0 {
222 ; CHECK-LABEL: @PreemptableCall dso_preemptable{{$}}
223 ; CHECK-NEXT: args uses:
224 ; CHECK-NEXT: allocas uses:
225 ; LOCAL-NEXT: x[4]: empty-set, @PreemptableWrite1(arg0, [0,1)){{$}}
226 ; GLOBAL-NEXT: x[4]: full-set, @PreemptableWrite1(arg0, [0,1)){{$}}
227 ; GLOBAL-NEXT: safe accesses:
230 %x = alloca i32, align 4
231 %x1 = bitcast i32* %x to i8*
232 call void @PreemptableWrite1(i8* %x1)
236 ; Call to function with interposable linkage
237 define void @InterposableCall() #0 {
238 ; CHECK-LABEL: @InterposableCall dso_preemptable{{$}}
239 ; CHECK-NEXT: args uses:
240 ; CHECK-NEXT: allocas uses:
241 ; LOCAL-NEXT: x[4]: empty-set, @InterposableWrite1(arg0, [0,1)){{$}}
242 ; NOLTO-NEXT: x[4]: full-set, @InterposableWrite1(arg0, [0,1)){{$}}
243 ; LTO-NEXT: x[4]: [0,1), @InterposableWrite1(arg0, [0,1)){{$}}
244 ; GLOBAL-NEXT: safe accesses:
247 %x = alloca i32, align 4
248 %x1 = bitcast i32* %x to i8*
249 call void @InterposableWrite1(i8* %x1)
253 ; Call to function with private linkage
254 define void @PrivateCall() #0 {
255 ; CHECK-LABEL: @PrivateCall dso_preemptable{{$}}
256 ; CHECK-NEXT: args uses:
257 ; CHECK-NEXT: allocas uses:
258 ; LOCAL-NEXT: x[4]: empty-set, @PrivateWrite1(arg0, [0,1)){{$}}
259 ; GLOBAL-NEXT: x[4]: [0,1), @PrivateWrite1(arg0, [0,1)){{$}}
260 ; GLOBAL-NEXT: safe accesses:
263 %x = alloca i32, align 4
264 %x1 = bitcast i32* %x to i8*
265 call void @PrivateWrite1(i8* %x1)
269 define private void @PrivateWrite1(i8* %p) #0 {
270 ; CHECK-LABEL: @PrivateWrite1{{$}}
271 ; CHECK-NEXT: args uses:
272 ; CHECK-NEXT: p[]: [0,1){{$}}
273 ; CHECK-NEXT: allocas uses:
274 ; GLOBAL-NEXT: safe accesses:
275 ; GLOBAL-NEXT: store i8 0, i8* %p, align 1
278 store i8 0, i8* %p, align 1
282 ; Caller returns a dependent value.
283 ; FIXME: alloca considered unsafe even if the return value is unused.
284 define void @f7() #0 {
285 ; CHECK-LABEL: @f7 dso_preemptable{{$}}
286 ; CHECK-NEXT: args uses:
287 ; CHECK-NEXT: allocas uses:
288 ; LOCAL-NEXT: x[4]: empty-set, @ReturnDependent(arg0, [0,1)){{$}}
289 ; GLOBAL-NEXT: x[4]: full-set, @ReturnDependent(arg0, [0,1)){{$}}
290 ; GLOBAL-NEXT: safe accesses:
293 %x = alloca i32, align 4
294 %x1 = bitcast i32* %x to i8*
295 %x2 = call i8* @ReturnDependent(i8* %x1)
299 define void @f8left() #0 {
300 ; CHECK-LABEL: @f8left dso_preemptable{{$}}
301 ; CHECK-NEXT: args uses:
302 ; CHECK-NEXT: allocas uses:
303 ; LOCAL-NEXT: x[8]: empty-set, @Rec2(arg0, [2,3)){{$}}
304 ; GLOBAL-NEXT: x[8]: [0,4), @Rec2(arg0, [2,3)){{$}}
305 ; GLOBAL-NEXT: safe accesses:
308 %x = alloca i64, align 4
309 %x1 = bitcast i64* %x to i8*
310 %x2 = getelementptr i8, i8* %x1, i64 2
311 ; 2 + [-2, 2) = [0, 4) => OK
312 call void @Rec2(i8* %x2)
316 define void @f8right() #0 {
317 ; CHECK-LABEL: @f8right dso_preemptable{{$}}
318 ; CHECK-NEXT: args uses:
319 ; CHECK-NEXT: allocas uses:
320 ; LOCAL-NEXT: x[8]: empty-set, @Rec2(arg0, [6,7)){{$}}
321 ; GLOBAL-NEXT: x[8]: [4,8), @Rec2(arg0, [6,7)){{$}}
322 ; GLOBAL-NEXT: safe accesses:
325 %x = alloca i64, align 4
326 %x1 = bitcast i64* %x to i8*
327 %x2 = getelementptr i8, i8* %x1, i64 6
328 ; 6 + [-2, 2) = [4, 8) => OK
329 call void @Rec2(i8* %x2)
333 define void @f8oobleft() #0 {
334 ; CHECK-LABEL: @f8oobleft dso_preemptable{{$}}
335 ; CHECK-NEXT: args uses:
336 ; CHECK-NEXT: allocas uses:
337 ; LOCAL-NEXT: x[8]: empty-set, @Rec2(arg0, [1,2)){{$}}
338 ; GLOBAL-NEXT: x[8]: [-1,3), @Rec2(arg0, [1,2)){{$}}
339 ; GLOBAL-NEXT: safe accesses:
342 %x = alloca i64, align 4
343 %x1 = bitcast i64* %x to i8*
344 %x2 = getelementptr i8, i8* %x1, i64 1
345 ; 1 + [-2, 2) = [-1, 3) => NOT OK
346 call void @Rec2(i8* %x2)
350 define void @f8oobright() #0 {
351 ; CHECK-LABEL: @f8oobright dso_preemptable{{$}}
352 ; CHECK-NEXT: args uses:
353 ; CHECK-NEXT: allocas uses:
354 ; LOCAL-NEXT: x[8]: empty-set, @Rec2(arg0, [7,8)){{$}}
355 ; GLOBAL-NEXT: x[8]: [5,9), @Rec2(arg0, [7,8)){{$}}
356 ; GLOBAL-NEXT: safe accesses:
359 %x = alloca i64, align 4
360 %x1 = bitcast i64* %x to i8*
361 %x2 = getelementptr i8, i8* %x1, i64 7
362 ; 7 + [-2, 2) = [5, 9) => NOT OK
363 call void @Rec2(i8* %x2)
367 define void @TwoArguments() #0 {
368 ; CHECK-LABEL: @TwoArguments dso_preemptable{{$}}
369 ; CHECK-NEXT: args uses:
370 ; CHECK-NEXT: allocas uses:
371 ; LOCAL-NEXT: x[8]: empty-set, @Write4_2(arg0, [4,5)), @Write4_2(arg1, [0,1)){{$}}
372 ; GLOBAL-NEXT: x[8]: [0,8), @Write4_2(arg0, [4,5)), @Write4_2(arg1, [0,1)){{$}}
373 ; GLOBAL-NEXT: safe accesses:
376 %x = alloca i64, align 4
377 %x1 = bitcast i64* %x to i8*
378 %x2 = getelementptr i8, i8* %x1, i64 4
379 call void @Write4_2(i8* %x2, i8* %x1)
383 define void @TwoArgumentsOOBOne() #0 {
384 ; CHECK-LABEL: @TwoArgumentsOOBOne dso_preemptable{{$}}
385 ; CHECK-NEXT: args uses:
386 ; CHECK-NEXT: allocas uses:
387 ; LOCAL-NEXT: x[8]: empty-set, @Write4_2(arg0, [5,6)), @Write4_2(arg1, [0,1)){{$}}
388 ; GLOBAL-NEXT: x[8]: [0,9), @Write4_2(arg0, [5,6)), @Write4_2(arg1, [0,1)){{$}}
389 ; GLOBAL-NEXT: safe accesses:
392 %x = alloca i64, align 4
393 %x1 = bitcast i64* %x to i8*
394 %x2 = getelementptr i8, i8* %x1, i64 5
395 call void @Write4_2(i8* %x2, i8* %x1)
399 define void @TwoArgumentsOOBOther() #0 {
400 ; CHECK-LABEL: @TwoArgumentsOOBOther dso_preemptable{{$}}
401 ; CHECK-NEXT: args uses:
402 ; CHECK-NEXT: allocas uses:
403 ; LOCAL-NEXT: x[8]: empty-set, @Write4_2(arg0, [4,5)), @Write4_2(arg1, [-1,0)){{$}}
404 ; GLOBAL-NEXT: x[8]: [-1,8), @Write4_2(arg0, [4,5)), @Write4_2(arg1, [-1,0)){{$}}
405 ; GLOBAL-NEXT: safe accesses:
408 %x = alloca i64, align 4
409 %x0 = bitcast i64* %x to i8*
410 %x1 = getelementptr i8, i8* %x0, i64 -1
411 %x2 = getelementptr i8, i8* %x0, i64 4
412 call void @Write4_2(i8* %x2, i8* %x1)
416 define void @TwoArgumentsOOBBoth() #0 {
417 ; CHECK-LABEL: @TwoArgumentsOOBBoth dso_preemptable{{$}}
418 ; CHECK-NEXT: args uses:
419 ; CHECK-NEXT: allocas uses:
420 ; LOCAL-NEXT: x[8]: empty-set, @Write4_2(arg0, [5,6)), @Write4_2(arg1, [-1,0)){{$}}
421 ; GLOBAL-NEXT: x[8]: [-1,9), @Write4_2(arg0, [5,6)), @Write4_2(arg1, [-1,0)){{$}}
422 ; GLOBAL-NEXT: safe accesses:
425 %x = alloca i64, align 4
426 %x0 = bitcast i64* %x to i8*
427 %x1 = getelementptr i8, i8* %x0, i64 -1
428 %x2 = getelementptr i8, i8* %x0, i64 5
429 call void @Write4_2(i8* %x2, i8* %x1)
433 define i32 @TestRecursiveNoOffset(i32* %p, i32 %size) #0 {
434 ; CHECK-LABEL: @TestRecursiveNoOffset dso_preemptable{{$}}
435 ; CHECK-NEXT: args uses:
436 ; LOCAL-NEXT: p[]: empty-set, @RecursiveNoOffset(arg0, [0,1)){{$}}
437 ; GLOBAL-NEXT: p[]: full-set, @RecursiveNoOffset(arg0, [0,1)){{$}}
438 ; CHECK-NEXT: allocas uses:
439 ; CHECK-NEXT: sum[4]: [0,4), @RecursiveNoOffset(arg2, [0,1)){{$}}
440 ; GLOBAL-NEXT: safe accesses:
441 ; GLOBAL-NEXT: store i32 0, i32* %sum, align 4
442 ; GLOBAL-NEXT: %1 = load i32, i32* %sum, align 4
445 %sum = alloca i32, align 4
446 %0 = bitcast i32* %sum to i8*
447 store i32 0, i32* %sum, align 4
448 call void @RecursiveNoOffset(i32* %p, i32 %size, i32* %sum)
449 %1 = load i32, i32* %sum, align 4
453 define void @TestRecursiveWithOffset(i32 %size) #0 {
454 ; CHECK-LABEL: @TestRecursiveWithOffset dso_preemptable{{$}}
455 ; CHECK-NEXT: args uses:
456 ; CHECK-NEXT: allocas uses:
457 ; LOCAL-NEXT: sum[64]: empty-set, @RecursiveWithOffset(arg1, [0,1)){{$}}
458 ; GLOBAL-NEXT: sum[64]: full-set, @RecursiveWithOffset(arg1, [0,1)){{$}}
459 ; GLOBAL-NEXT: safe accesses:
462 %sum = alloca i32, i64 16, align 4
463 call void @RecursiveWithOffset(i32 %size, i32* %sum)
467 ; FIXME: IPA should detect that access is safe
468 define void @TestUpdateArg() #0 {
469 ; CHECK-LABEL: @TestUpdateArg dso_preemptable{{$}}
470 ; CHECK-NEXT: args uses:
471 ; CHECK-NEXT: allocas uses:
472 ; LOCAL-NEXT: x[16]: empty-set, @WriteAndReturn8(arg0, [0,1)){{$}}
473 ; GLOBAL-NEXT: x[16]: full-set, @WriteAndReturn8(arg0, [0,1)){{$}}
474 ; GLOBAL-NEXT: safe accesses:
477 %x = alloca i8, i64 16, align 4
478 %0 = call i8* @WriteAndReturn8(i8* %x)
482 define void @TestCrossModuleOnce() #0 {
483 ; CHECK-DAG: @TestCrossModuleOnce dso_preemptable{{$}}
484 ; CHECK-NEXT: args uses:
485 ; CHECK-NEXT: allocas uses:
486 ; LOCAL-NEXT: y[1]: empty-set, @Write1SameModule(arg0, [0,1)){{$}}
487 ; GLOBAL-NEXT: y[1]: [0,1), @Write1SameModule(arg0, [0,1)){{$}}
488 ; GLOBAL-NEXT: safe accesses:
491 %y = alloca i8, align 4
492 call void @Write1SameModule(i8* %y)
496 define void @TestCrossModuleTwice() #0 {
497 ; CHECK-DAG: @TestCrossModuleTwice dso_preemptable{{$}}
498 ; CHECK-NEXT: args uses:
499 ; CHECK-NEXT: allocas uses:
500 ; LOCAL-NEXT: z[1]: empty-set, @Write1DiffModule(arg0, [0,1)){{$}}
501 ; GLOBAL-NEXT: z[1]: [0,1), @Write1DiffModule(arg0, [0,1)){{$}}
502 ; GLOBAL-NEXT: safe accesses:
505 %z = alloca i8, align 4
506 call void @Write1DiffModule(i8* %z)
510 define void @TestCrossModuleConflict() #0 {
511 ; CHECK-DAG: @TestCrossModuleConflict dso_preemptable{{$}}
512 ; CHECK-NEXT: args uses:
513 ; CHECK-NEXT: allocas uses:
514 ; LOCAL-NEXT: x[1]: empty-set, @Write1Private(arg0, [0,1)){{$}}
515 ; GLOBAL-NEXT: x[1]: [-1,0), @Write1Private(arg0, [0,1)){{$}}
516 ; GLOBAL-NEXT: safe accesses:
519 %x = alloca i8, align 4
520 call void @Write1Private(i8* %x)
524 ; FIXME: LTO should match NOLTO
525 define void @TestCrossModuleWeak() #0 {
526 ; CHECK-DAG: @TestCrossModuleWeak dso_preemptable{{$}}
527 ; CHECK-NEXT: args uses:
528 ; CHECK-NEXT: allocas uses:
529 ; LOCAL-NEXT: x[1]: empty-set, @Write1Weak(arg0, [0,1)){{$}}
530 ; NOLTO-NEXT: x[1]: [1,2), @Write1Weak(arg0, [0,1)){{$}}
531 ; LTO-NEXT: x[1]: full-set, @Write1Weak(arg0, [0,1)){{$}}
532 ; GLOBAL-NEXT: safe accesses:
535 %x = alloca i8, align 4
536 call void @Write1Weak(i8* %x)
540 define private dso_local void @Private(i8* %p) #0 {
542 %p1 = getelementptr i8, i8* %p, i64 1
543 store i8 0, i8* %p1, align 1
547 define dso_local void @Write1Module0(i8* %p) #0 {
549 store i8 0, i8* %p, align 1
553 define dso_local void @Weak(i8* %p) #0 {
555 %p1 = getelementptr i8, i8* %p, i64 1
556 store i8 0, i8* %p1, align 1
560 ; The rest is from Inputs/ipa.ll
562 ; CHECK-LABEL: @Write1{{$}}
563 ; CHECK-NEXT: args uses:
564 ; CHECK-NEXT: p[]: [0,1){{$}}
565 ; CHECK-NEXT: allocas uses:
566 ; GLOBAL-NEXT: safe accesses:
567 ; GLOBAL-NEXT: store i8 0, i8* %p, align 1
570 ; CHECK-LABEL: @Write4{{$}}
571 ; CHECK-NEXT: args uses:
572 ; CHECK-NEXT: p[]: [0,4){{$}}
573 ; CHECK-NEXT: allocas uses:
574 ; GLOBAL-NEXT: safe accesses:
575 ; GLOBAL-NEXT: store i32 0, i32* %0, align 1
578 ; CHECK-LABEL: @Write4_2{{$}}
579 ; CHECK-NEXT: args uses:
580 ; CHECK-NEXT: p[]: [0,4){{$}}
581 ; CHECK-NEXT: q[]: [0,4){{$}}
582 ; CHECK-NEXT: allocas uses:
583 ; GLOBAL-NEXT: safe accesses:
584 ; GLOBAL-NEXT: store i32 0, i32* %0, align 1
585 ; GLOBAL-NEXT: store i32 0, i32* %1, align 1
588 ; CHECK-LABEL: @Write8{{$}}
589 ; CHECK-NEXT: args uses:
590 ; CHECK-NEXT: p[]: [0,8){{$}}
591 ; CHECK-NEXT: allocas uses:
592 ; GLOBAL-NEXT: safe accesses:
593 ; GLOBAL-NEXT: store i64 0, i64* %0, align 1
596 ; CHECK-LABEL: @WriteAndReturn8{{$}}
597 ; CHECK-NEXT: args uses:
598 ; CHECK-NEXT: p[]: full-set{{$}}
599 ; CHECK-NEXT: allocas uses:
600 ; GLOBAL-NEXT: safe accesses:
601 ; GLOBAL-NEXT: store i8 0, i8* %p, align 1
604 ; CHECK-LABEL: @PreemptableWrite1 dso_preemptable{{$}}
605 ; CHECK-NEXT: args uses:
606 ; CHECK-NEXT: p[]: [0,1){{$}}
607 ; CHECK-NEXT: allocas uses:
608 ; GLOBAL-NEXT: safe accesses:
609 ; GLOBAL-NEXT: store i8 0, i8* %p, align 1
612 ; CHECK-LABEL: @InterposableWrite1 interposable{{$}}
613 ; CHECK-NEXT: args uses:
614 ; CHECK-NEXT: p[]: [0,1){{$}}
615 ; CHECK-NEXT: allocas uses:
616 ; GLOBAL-NEXT: safe accesses:
617 ; GLOBAL-NEXT: store i8 0, i8* %p, align 1
620 ; CHECK-LABEL: @ReturnDependent{{$}}
621 ; CHECK-NEXT: args uses:
622 ; CHECK-NEXT: p[]: full-set{{$}}
623 ; CHECK-NEXT: allocas uses:
624 ; GLOBAL-NEXT: safe accesses:
627 ; CHECK-LABEL: @Rec0{{$}}
628 ; CHECK-NEXT: args uses:
629 ; LOCAL-NEXT: p[]: empty-set, @Write4(arg0, [2,3)){{$}}
630 ; GLOBAL-NEXT: p[]: [2,6)
631 ; CHECK-NEXT: allocas uses:
632 ; GLOBAL-NEXT: safe accesses:
635 ; CHECK-LABEL: @Rec1{{$}}
636 ; CHECK-NEXT: args uses:
637 ; LOCAL-NEXT: p[]: empty-set, @Rec0(arg0, [1,2)){{$}}
638 ; GLOBAL-NEXT: p[]: [3,7)
639 ; CHECK-NEXT: allocas uses:
640 ; GLOBAL-NEXT: safe accesses:
643 ; CHECK-LABEL: @Rec2{{$}}
644 ; CHECK-NEXT: args uses:
645 ; LOCAL-NEXT: p[]: empty-set, @Rec1(arg0, [-5,-4)){{$}}
646 ; GLOBAL-NEXT: p[]: [-2,2)
647 ; CHECK-NEXT: allocas uses:
648 ; GLOBAL-NEXT: safe accesses:
651 ; CHECK-LABEL: @RecursiveNoOffset{{$}}
652 ; CHECK-NEXT: args uses:
653 ; LOCAL-NEXT: p[]: [0,4), @RecursiveNoOffset(arg0, [4,5)){{$}}
654 ; GLOBAL-NEXT: p[]: full-set, @RecursiveNoOffset(arg0, [4,5)){{$}}
655 ; CHECK-NEXT: acc[]: [0,4), @RecursiveNoOffset(arg2, [0,1)){{$}}
656 ; CHECK-NEXT: allocas uses:
657 ; GLOBAL-NEXT: safe accesses:
658 ; GLOBAL-NEXT: %0 = load i32, i32* %p, align 4
659 ; GLOBAL-NEXT: %1 = load i32, i32* %acc, align 4
660 ; GLOBAL-NEXT: store i32 %add, i32* %acc, align 4
663 ; CHECK-LABEL: @RecursiveWithOffset{{$}}
664 ; CHECK-NEXT: args uses:
665 ; LOCAL-NEXT: acc[]: [0,4), @RecursiveWithOffset(arg1, [4,5)){{$}}
666 ; GLOBAL-NEXT: acc[]: full-set, @RecursiveWithOffset(arg1, [4,5)){{$}}
667 ; CHECK-NEXT: allocas uses:
668 ; GLOBAL-NEXT: safe accesses:
669 ; GLOBAL-NEXT: store i32 0, i32* %acc, align 4
672 ; CHECK-LABEL: @ReturnAlloca
673 ; CHECK-NEXT: args uses:
674 ; CHECK-NEXT: allocas uses:
675 ; CHECK-NEXT: x[8]: full-set
676 ; GLOBAL-NEXT: safe accesses:
679 ; INDEX-LABEL: ^0 = module:
680 ; INDEX-DAG: name: "ReturnDependent"{{.*}} guid = [[ReturnDependent:[-0-9]+]]
681 ; INDEX-DAG: name: "Private"{{.*}} guid = [[Private:[-0-9]+]]
682 ; INDEX-DAG: name: "TwoArgumentsOOBOther"{{.*}} guid = [[TwoArgumentsOOBOther:[-0-9]+]]
683 ; INDEX-DAG: name: "Rec2"{{.*}} guid = [[Rec2:[-0-9]+]]
684 ; INDEX-DAG: name: "f1"{{.*}} guid = [[f1:[-0-9]+]]
685 ; INDEX-DAG: name: "PrivateWrite1"{{.*}} guid = [[PrivateWrite1:[-0-9]+]]
686 ; INDEX-DAG: name: "TestRecursiveNoOffset"{{.*}} guid = [[TestRecursiveNoOffset:[-0-9]+]]
687 ; INDEX-DAG: name: "f8left"{{.*}} guid = [[f8left:[-0-9]+]]
688 ; INDEX-DAG: name: "Write4"{{.*}} guid = [[Write4:[-0-9]+]]
689 ; INDEX-DAG: name: "f7"{{.*}} guid = [[f7:[-0-9]+]]
690 ; INDEX-DAG: name: "Write1SameModule"{{.*}} guid = [[Write1SameModule:[-0-9]+]]
691 ; INDEX-DAG: name: "Write8"{{.*}} guid = [[Write8:[-0-9]+]]
692 ; INDEX-DAG: name: "TwoArgumentsOOBOne"{{.*}} guid = [[TwoArgumentsOOBOne:[-0-9]+]]
693 ; INDEX-DAG: name: "f3"{{.*}} guid = [[f3:[-0-9]+]]
694 ; INDEX-DAG: name: "f8right"{{.*}} guid = [[f8right:[-0-9]+]]
695 ; INDEX-DAG: name: "Write4_2"{{.*}} guid = [[Write4_2:[-0-9]+]]
696 ; INDEX-DAG: name: "RecursiveWithOffset"{{.*}} guid = [[RecursiveWithOffset:[-0-9]+]]
697 ; INDEX-DAG: name: "Weak"{{.*}} guid = [[Weak:[-0-9]+]]
698 ; INDEX-DAG: name: "Write1Private"{{.*}} guid = [[Write1Private:[-0-9]+]]
699 ; INDEX-DAG: name: "TestUpdateArg"{{.*}} guid = [[TestUpdateArg:[-0-9]+]]
700 ; INDEX-DAG: name: "TestCrossModuleTwice"{{.*}} guid = [[TestCrossModuleTwice:[-0-9]+]]
701 ; INDEX-DAG: name: "TestCrossModuleWeak"{{.*}} guid = [[TestCrossModuleWeak:[-0-9]+]]
702 ; INDEX-DAG: name: "f2"{{.*}} guid = [[f2:[-0-9]+]]
703 ; INDEX-DAG: name: "PrivateCall"{{.*}} guid = [[PrivateCall:[-0-9]+]]
704 ; INDEX-DAG: name: "TestRecursiveWithOffset"{{.*}} guid = [[TestRecursiveWithOffset:[-0-9]+]]
705 ; INDEX-DAG: name: "f8oobleft"{{.*}} guid = [[f8oobleft:[-0-9]+]]
706 ; INDEX-DAG: name: "InterposableWrite1"{{.*}} guid = [[InterposableWrite1:[-0-9]+]]
707 ; INDEX-DAG: name: "f4"{{.*}} guid = [[f4:[-0-9]+]]
708 ; INDEX-DAG: name: "TestCrossModuleConflict"{{.*}} guid = [[TestCrossModuleConflict:[-0-9]+]]
709 ; INDEX-DAG: name: "RecursiveNoOffset"{{.*}} guid = [[RecursiveNoOffset:[-0-9]+]]
710 ; INDEX-DAG: name: "TwoArgumentsOOBBoth"{{.*}} guid = [[TwoArgumentsOOBBoth:[-0-9]+]]
711 ; INDEX-DAG: name: "f5"{{.*}} guid = [[f5:[-0-9]+]]
712 ; INDEX-DAG: name: "f6"{{.*}} guid = [[f6:[-0-9]+]]
713 ; INDEX-DAG: name: "Write1Weak"{{.*}} guid = [[Write1Weak:[-0-9]+]]
714 ; INDEX-DAG: name: "Write1"{{.*}} guid = [[Write1:[-0-9]+]]
715 ; INDEX-DAG: name: "PreemptableWrite1"{{.*}} guid = [[PreemptableWrite1:[-0-9]+]]
716 ; INDEX-DAG: name: "f8oobright"{{.*}} guid = [[f8oobright:[-0-9]+]]
717 ; INDEX-DAG: name: "InterposableCall"{{.*}} guid = [[InterposableCall:[-0-9]+]]
718 ; INDEX-DAG: name: "TestCrossModuleOnce"{{.*}} guid = [[TestCrossModuleOnce:[-0-9]+]]
719 ; INDEX-DAG: name: "WriteAndReturn8"{{.*}} guid = [[WriteAndReturn8:[-0-9]+]]
720 ; INDEX-DAG: name: "TwoArguments"{{.*}} guid = [[TwoArguments:[-0-9]+]]
721 ; INDEX-DAG: name: "Write1Module0"{{.*}} guid = [[Write1Module0:[-0-9]+]]
722 ; INDEX-DAG: name: "PreemptableCall"{{.*}} guid = [[PreemptableCall:[-0-9]+]]
723 ; INDEX-DAG: name: "Write1DiffModule"{{.*}} guid = [[Write1DiffModule:[-0-9]+]]
724 ; INDEX-DAG: name: "ExternalCall"{{.*}} guid = [[ExternalCall:[-0-9]+]]
725 ; INDEX-LABEL: = blockcount:
727 ; INDEX-LABEL: ^0 = module:
728 ; INDEX-DAG: name: "ReturnDependent"{{.*}} guid = [[ReturnDependent:[-0-9]+]]
729 ; INDEX-DAG: name: "Rec0"{{.*}} guid = [[Rec0:[-0-9]+]]
730 ; INDEX-DAG: name: "Rec2"{{.*}} guid = [[Rec2:[-0-9]+]]
731 ; INDEX-DAG: name: "Write4"{{.*}} guid = [[Write4:[-0-9]+]]
732 ; INDEX-DAG: name: "Write1SameModule"{{.*}} guid = [[Write1SameModule:[-0-9]+]]
733 ; INDEX-DAG: name: "Write8"{{.*}} guid = [[Write8:[-0-9]+]]
734 ; INDEX-DAG: name: "Write4_2"{{.*}} guid = [[Write4_2:[-0-9]+]]
735 ; INDEX-DAG: name: "RecursiveWithOffset"{{.*}} guid = [[RecursiveWithOffset:[-0-9]+]]
736 ; INDEX-DAG: name: "Weak"{{.*}} guid = [[Weak:[-0-9]+]]
737 ; INDEX-DAG: name: "Write1Private"{{.*}} guid = [[Write1Private:[-0-9]+]]
738 ; INDEX-DAG: name: "InterposableWrite1"{{.*}} guid = [[InterposableWrite1:[-0-9]+]]
739 ; INDEX-DAG: name: "Private"{{.*}} guid = [[Private:[-0-9]+]]
740 ; INDEX-DAG: name: "Rec1"{{.*}} guid = [[Rec1:[-0-9]+]]
741 ; INDEX-DAG: name: "RecursiveNoOffset"{{.*}} guid = [[RecursiveNoOffset:[-0-9]+]]
742 ; INDEX-DAG: name: "Write1Weak"{{.*}} guid = [[Write1Weak:[-0-9]+]]
743 ; INDEX-DAG: name: "Write1"{{.*}} guid = [[Write1:[-0-9]+]]
744 ; INDEX-DAG: name: "PreemptableWrite1"{{.*}} guid = [[PreemptableWrite1:[-0-9]+]]
745 ; INDEX-DAG: name: "WriteAndReturn8"{{.*}} guid = [[WriteAndReturn8:[-0-9]+]]
746 ; INDEX-DAG: name: "Write1Module0"{{.*}} guid = [[Write1Module0:[-0-9]+]]
747 ; INDEX-DAG: name: "Write1DiffModule"{{.*}} guid = [[Write1DiffModule:[-0-9]+]]
748 ; INDEX-DAG: name: "ExternalCall"{{.*}} guid = [[ExternalCall:[-0-9]+]]
749 ; INDEX-DAG: name: "ReturnAlloca"{{.*}} guid = [[ReturnAlloca:[-0-9]+]]
750 ; INDEX-LABEL: = blockcount:
752 ; INDEX-LABEL: ^0 = module:
753 ; INDEX-DAG: guid: [[ReturnDependent]], {{.*}}, funcFlags: ({{.*}}))))
754 ; INDEX-DAG: guid: [[Rec0]], {{.*}}, params: ((param: 0, offset: [2, 5])))))
755 ; INDEX-DAG: guid: [[Rec2]], {{.*}}, params: ((param: 0, offset: [-2, 1])))))
756 ; INDEX-DAG: guid: [[Write4]], {{.*}}, params: ((param: 0, offset: [0, 3])))))
757 ; INDEX-DAG: guid: [[Write1SameModule]], {{.*}}, params: ((param: 0, offset: [0, 0])))))
758 ; INDEX-DAG: guid: [[Write8]], {{.*}}, params: ((param: 0, offset: [0, 7])))))
759 ; INDEX-DAG: guid: [[Write4_2]], {{.*}}, params: ((param: 0, offset: [0, 3]), (param: 1, offset: [0, 3])))))
760 ; INDEX-DAG: guid: [[RecursiveWithOffset]], {{.*}}, calls: ((callee: ^{{[0-9]+}})))))
761 ; INDEX-DAG: guid: [[Weak]], {{.*}}, funcFlags: ({{.*}}))))
762 ; INDEX-DAG: guid: [[Write1Private]], {{.*}}, params: ((param: 0, offset: [-1, -1])))))
763 ; INDEX-DAG: guid: [[InterposableWrite1]], {{.*}}, params: ((param: 0, offset: [0, 0])))))
764 ; INDEX-DAG: guid: [[Private]], {{.*}}, params: ((param: 0, offset: [-1, -1])))))
765 ; INDEX-DAG: guid: [[Rec1]], {{.*}}, params: ((param: 0, offset: [3, 6])))))
766 ; INDEX-DAG: guid: [[RecursiveNoOffset]], {{.*}}, params: ((param: 2, offset: [0, 3])))))
767 ; INDEX-DAG: guid: [[Write1Weak]], {{.*}}, calls: ((callee: ^{{[0-9]+}})))))
768 ; INDEX-DAG: guid: [[Write1]], {{.*}}, params: ((param: 0, offset: [0, 0])))))
769 ; INDEX-DAG: guid: [[PreemptableWrite1]], {{.*}}, funcFlags: ({{.*}}))))
770 ; INDEX-DAG: guid: [[WriteAndReturn8]], {{.*}}, funcFlags: ({{.*}}))))
771 ; INDEX-DAG: guid: [[Write1DiffModule]], {{.*}}, funcFlags: ({{.*}}))))
772 ; INDEX-DAG: guid: [[ReturnAlloca]], {{.*}}, insts: 2)))
773 ; INDEX-LABEL: blockcount: