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 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:
125 %x = alloca i32, align 4
126 call void @Write8(ptr %x)
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:
140 %x = alloca i32, align 4
141 call void @Write1(ptr %x)
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:
155 %x = alloca i32, align 4
156 call void @Write4(ptr %x)
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:
170 %x = alloca i32, align 4
171 %x2 = getelementptr i8, ptr %x, i64 1
172 call void @Write1(ptr %x2)
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:
186 %x = alloca i32, align 4
187 %x2 = getelementptr i8, ptr %x, i64 1
188 call void @Write4(ptr %x2)
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:
202 %x = alloca i32, align 4
203 call void @ExternalCall(ptr %x)
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:
217 %x = alloca i32, align 4
218 call void @PreemptableWrite1(ptr %x)
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:
233 %x = alloca i32, align 4
234 call void @InterposableWrite1(ptr %x)
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:
248 %x = alloca i32, align 4
249 call void @PrivateWrite1(ptr %x)
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
262 store i8 0, ptr %p, align 1
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:
277 %x = alloca i32, align 4
278 %x2 = call ptr @ReturnDependent(ptr %x)
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:
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)
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:
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)
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:
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)
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:
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)
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:
355 %x = alloca i64, align 4
356 %x2 = getelementptr i8, ptr %x, i64 4
357 call void @Write4_2(ptr %x2, ptr %x)
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:
370 %x = alloca i64, align 4
371 %x2 = getelementptr i8, ptr %x, i64 5
372 call void @Write4_2(ptr %x2, ptr %x)
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:
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)
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:
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)
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
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
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:
436 %sum = alloca i32, i64 16, align 4
437 call void @RecursiveWithOffset(i32 %size, ptr %sum)
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:
451 %x = alloca i8, i64 16, align 4
452 %0 = call ptr @WriteAndReturn8(ptr %x)
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:
465 %y = alloca i8, align 4
466 call void @Write1SameModule(ptr %y)
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:
479 %z = alloca i8, align 4
480 call void @Write1DiffModule(ptr %z)
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:
493 %x = alloca i8, align 4
494 call void @Write1Private(ptr %x)
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:
509 %x = alloca i8, align 4
510 call void @Write1Weak(ptr %x)
514 define private dso_local void @Private(ptr %p) #0 {
516 %p1 = getelementptr i8, ptr %p, i64 1
517 store i8 0, ptr %p1, align 1
521 define dso_local void @Write1Module0(ptr %p) #0 {
523 store i8 0, ptr %p, align 1
527 define dso_local void @Weak(ptr %p) #0 {
529 %p1 = getelementptr i8, ptr %p, i64 1
530 store i8 0, ptr %p1, align 1
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
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
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
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
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
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
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
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:
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:
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:
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:
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
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
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:
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: