Files
clang-p2996/llvm/test/Analysis/StackSafetyAnalysis/ipa.ll
Vitaly Buka c1e47b47f8 [StackSafety] Run ThinLTO
Summary:
ThinLTO linking runs dataflow processing on collected
function parameters. Then StackSafetyGlobalInfoWrapperPass
in ThinLTO backend will run as usual looking up to external
symbol in the summary if needed.

Depends on D80985.

Reviewers: eugenis, pcc

Reviewed By: eugenis

Subscribers: inglorion, hiraditya, steven_wu, dexonsmith, cfe-commits, llvm-commits

Tags: #clang, #llvm

Differential Revision: https://reviews.llvm.org/D81242
2020-06-12 18:11:29 -07:00

563 lines
17 KiB
LLVM

; REQUIRES: aarch64-registered-target
; RUN: llvm-as %s -o %t0.bc
; RUN: llvm-as %S/Inputs/ipa.ll -o %t1.bc
; RUN: llvm-link -disable-lazy-loading %t0.bc %t1.bc -o %t.combined.bc
; RUN: opt -S -analyze -stack-safety-local %t.combined.bc | FileCheck %s --check-prefixes=CHECK,LOCAL
; RUN: opt -S -passes="print<stack-safety-local>" -disable-output %t.combined.bc 2>&1 | FileCheck %s --check-prefixes=CHECK,LOCAL
; RUN: opt -S -analyze -stack-safety %t.combined.bc | FileCheck %s --check-prefixes=CHECK,GLOBAL,NOLTO
; RUN: opt -S -passes="print-stack-safety" -disable-output %t.combined.bc 2>&1 | FileCheck %s --check-prefixes=CHECK,GLOBAL,NOLTO
; Do an end-to-test using the new LTO API
; TODO: Hideous llvm-lto2 invocation, add a --default-symbol-resolution to llvm-lto2?
; RUN: opt -module-summary %s -o %t.summ0.bc
; RUN: opt -module-summary %S/Inputs/ipa.ll -o %t.summ1.bc
; 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 \
; RUN: -r %t.summ0.bc,Write1, \
; RUN: -r %t.summ0.bc,Write4, \
; RUN: -r %t.summ0.bc,Write4_2, \
; RUN: -r %t.summ0.bc,Write8, \
; RUN: -r %t.summ0.bc,WriteAndReturn8, \
; RUN: -r %t.summ0.bc,TestUpdateArg,px \
; RUN: -r %t.summ0.bc,ExternalCall, \
; RUN: -r %t.summ0.bc,PreemptableWrite1, \
; RUN: -r %t.summ0.bc,InterposableWrite1, \
; RUN: -r %t.summ0.bc,ReturnDependent, \
; RUN: -r %t.summ0.bc,Rec2, \
; RUN: -r %t.summ0.bc,RecursiveNoOffset, \
; RUN: -r %t.summ0.bc,RecursiveWithOffset, \
; RUN: -r %t.summ0.bc,f1,px \
; RUN: -r %t.summ0.bc,f2,px \
; RUN: -r %t.summ0.bc,f3,px \
; RUN: -r %t.summ0.bc,f4,px \
; RUN: -r %t.summ0.bc,f5,px \
; RUN: -r %t.summ0.bc,f6,px \
; RUN: -r %t.summ0.bc,PreemptableCall,px \
; RUN: -r %t.summ0.bc,InterposableCall,px \
; RUN: -r %t.summ0.bc,PrivateCall,px \
; RUN: -r %t.summ0.bc,f7,px \
; RUN: -r %t.summ0.bc,f8left,px \
; RUN: -r %t.summ0.bc,f8right,px \
; RUN: -r %t.summ0.bc,f8oobleft,px \
; RUN: -r %t.summ0.bc,f8oobright,px \
; RUN: -r %t.summ0.bc,TwoArguments,px \
; RUN: -r %t.summ0.bc,TwoArgumentsOOBOne,px \
; RUN: -r %t.summ0.bc,TwoArgumentsOOBOther,px \
; RUN: -r %t.summ0.bc,TwoArgumentsOOBBoth,px \
; RUN: -r %t.summ0.bc,TestRecursiveNoOffset,px \
; RUN: -r %t.summ0.bc,TestRecursiveWithOffset,px \
; RUN: -r %t.summ1.bc,Write1,px \
; RUN: -r %t.summ1.bc,Write4,px \
; RUN: -r %t.summ1.bc,Write4_2,px \
; RUN: -r %t.summ1.bc,Write8,px \
; RUN: -r %t.summ1.bc,WriteAndReturn8,px \
; RUN: -r %t.summ1.bc,ExternalCall,px \
; RUN: -r %t.summ1.bc,PreemptableWrite1,px \
; RUN: -r %t.summ1.bc,InterposableWrite1,px \
; RUN: -r %t.summ1.bc,ReturnDependent,px \
; RUN: -r %t.summ1.bc,Rec0,px \
; RUN: -r %t.summ1.bc,Rec1,px \
; RUN: -r %t.summ1.bc,Rec2,px \
; RUN: -r %t.summ1.bc,RecursiveNoOffset,px \
; RUN: -r %t.summ1.bc,RecursiveWithOffset,px \
; RUN: -r %t.summ1.bc,ReturnAlloca,px 2>&1 | FileCheck %s --check-prefixes=CHECK,GLOBAL,LTO
; 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 \
; RUN: -r %t.summ0.bc,Write1, \
; RUN: -r %t.summ0.bc,Write4, \
; RUN: -r %t.summ0.bc,Write4_2, \
; RUN: -r %t.summ0.bc,Write8, \
; RUN: -r %t.summ0.bc,WriteAndReturn8, \
; RUN: -r %t.summ0.bc,TestUpdateArg,px \
; RUN: -r %t.summ0.bc,ExternalCall, \
; RUN: -r %t.summ0.bc,PreemptableWrite1, \
; RUN: -r %t.summ0.bc,InterposableWrite1, \
; RUN: -r %t.summ0.bc,ReturnDependent, \
; RUN: -r %t.summ0.bc,Rec2, \
; RUN: -r %t.summ0.bc,RecursiveNoOffset, \
; RUN: -r %t.summ0.bc,RecursiveWithOffset, \
; RUN: -r %t.summ0.bc,f1,px \
; RUN: -r %t.summ0.bc,f2,px \
; RUN: -r %t.summ0.bc,f3,px \
; RUN: -r %t.summ0.bc,f4,px \
; RUN: -r %t.summ0.bc,f5,px \
; RUN: -r %t.summ0.bc,f6,px \
; RUN: -r %t.summ0.bc,PreemptableCall,px \
; RUN: -r %t.summ0.bc,InterposableCall,px \
; RUN: -r %t.summ0.bc,PrivateCall,px \
; RUN: -r %t.summ0.bc,f7,px \
; RUN: -r %t.summ0.bc,f8left,px \
; RUN: -r %t.summ0.bc,f8right,px \
; RUN: -r %t.summ0.bc,f8oobleft,px \
; RUN: -r %t.summ0.bc,f8oobright,px \
; RUN: -r %t.summ0.bc,TwoArguments,px \
; RUN: -r %t.summ0.bc,TwoArgumentsOOBOne,px \
; RUN: -r %t.summ0.bc,TwoArgumentsOOBOther,px \
; RUN: -r %t.summ0.bc,TwoArgumentsOOBBoth,px \
; RUN: -r %t.summ0.bc,TestRecursiveNoOffset,px \
; RUN: -r %t.summ0.bc,TestRecursiveWithOffset,px \
; RUN: -r %t.summ1.bc,Write1,px \
; RUN: -r %t.summ1.bc,Write4,px \
; RUN: -r %t.summ1.bc,Write4_2,px \
; RUN: -r %t.summ1.bc,Write8,px \
; RUN: -r %t.summ1.bc,WriteAndReturn8,px \
; RUN: -r %t.summ1.bc,ExternalCall,px \
; RUN: -r %t.summ1.bc,PreemptableWrite1,px \
; RUN: -r %t.summ1.bc,InterposableWrite1,px \
; RUN: -r %t.summ1.bc,ReturnDependent,px \
; RUN: -r %t.summ1.bc,Rec0,px \
; RUN: -r %t.summ1.bc,Rec1,px \
; RUN: -r %t.summ1.bc,Rec2,px \
; RUN: -r %t.summ1.bc,RecursiveNoOffset,px \
; RUN: -r %t.summ1.bc,RecursiveWithOffset,px \
; RUN: -r %t.summ1.bc,ReturnAlloca,px 2>&1 | FileCheck %s --check-prefixes=CHECK,GLOBAL,LTO
target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
target triple = "aarch64-unknown-linux"
attributes #0 = { noinline sanitize_memtag "target-features"="+mte,+neon" }
declare void @Write1(i8* %p)
declare void @Write4(i8* %p)
declare void @Write4_2(i8* %p, i8* %q)
declare void @Write8(i8* %p)
declare dso_local i8* @WriteAndReturn8(i8* %p)
declare dso_local void @ExternalCall(i8* %p)
declare void @PreemptableWrite1(i8* %p)
declare void @InterposableWrite1(i8* %p)
declare i8* @ReturnDependent(i8* %p)
declare void @Rec2(i8* %p)
declare void @RecursiveNoOffset(i32* %p, i32 %size, i32* %acc)
declare void @RecursiveWithOffset(i32 %size, i32* %acc)
; Basic out-of-bounds.
define void @f1() #0 {
; CHECK-LABEL: @f1 dso_preemptable{{$}}
; CHECK-NEXT: args uses:
; CHECK-NEXT: allocas uses:
; LOCAL-NEXT: x[4]: empty-set, @Write8(arg0, [0,1)){{$}}
; GLOBAL-NEXT: x[4]: [0,8), @Write8(arg0, [0,1)){{$}}
; CHECK-NOT: ]:
entry:
%x = alloca i32, align 4
%x1 = bitcast i32* %x to i8*
call void @Write8(i8* %x1)
ret void
}
; Basic in-bounds.
define void @f2() #0 {
; CHECK-LABEL: @f2 dso_preemptable{{$}}
; CHECK-NEXT: args uses:
; CHECK-NEXT: allocas uses:
; LOCAL-NEXT: x[4]: empty-set, @Write1(arg0, [0,1)){{$}}
; GLOBAL-NEXT: x[4]: [0,1), @Write1(arg0, [0,1)){{$}}
; CHECK-NOT: ]:
entry:
%x = alloca i32, align 4
%x1 = bitcast i32* %x to i8*
call void @Write1(i8* %x1)
ret void
}
; Another basic in-bounds.
define void @f3() #0 {
; CHECK-LABEL: @f3 dso_preemptable{{$}}
; CHECK-NEXT: args uses:
; CHECK-NEXT: allocas uses:
; LOCAL-NEXT: x[4]: empty-set, @Write4(arg0, [0,1)){{$}}
; GLOBAL-NEXT: x[4]: [0,4), @Write4(arg0, [0,1)){{$}}
; CHECK-NOT: ]:
entry:
%x = alloca i32, align 4
%x1 = bitcast i32* %x to i8*
call void @Write4(i8* %x1)
ret void
}
; In-bounds with offset.
define void @f4() #0 {
; CHECK-LABEL: @f4 dso_preemptable{{$}}
; CHECK-NEXT: args uses:
; CHECK-NEXT: allocas uses:
; LOCAL-NEXT: x[4]: empty-set, @Write1(arg0, [1,2)){{$}}
; GLOBAL-NEXT: x[4]: [1,2), @Write1(arg0, [1,2)){{$}}
; CHECK-NOT: ]:
entry:
%x = alloca i32, align 4
%x1 = bitcast i32* %x to i8*
%x2 = getelementptr i8, i8* %x1, i64 1
call void @Write1(i8* %x2)
ret void
}
; Out-of-bounds with offset.
define void @f5() #0 {
; CHECK-LABEL: @f5 dso_preemptable{{$}}
; CHECK-NEXT: args uses:
; CHECK-NEXT: allocas uses:
; LOCAL-NEXT: empty-set, @Write4(arg0, [1,2)){{$}}
; GLOBAL-NEXT: [1,5), @Write4(arg0, [1,2)){{$}}
; CHECK-NOT: ]:
entry:
%x = alloca i32, align 4
%x1 = bitcast i32* %x to i8*
%x2 = getelementptr i8, i8* %x1, i64 1
call void @Write4(i8* %x2)
ret void
}
; External call.
define void @f6() #0 {
; CHECK-LABEL: @f6 dso_preemptable{{$}}
; CHECK-NEXT: args uses:
; CHECK-NEXT: allocas uses:
; LOCAL-NEXT: x[4]: empty-set, @ExternalCall(arg0, [0,1)){{$}}
; GLOBAL-NEXT: x[4]: full-set, @ExternalCall(arg0, [0,1)){{$}}
; CHECK-NOT: ]:
entry:
%x = alloca i32, align 4
%x1 = bitcast i32* %x to i8*
call void @ExternalCall(i8* %x1)
ret void
}
; Call to dso_preemptable function
define void @PreemptableCall() #0 {
; CHECK-LABEL: @PreemptableCall dso_preemptable{{$}}
; CHECK-NEXT: args uses:
; CHECK-NEXT: allocas uses:
; LOCAL-NEXT: x[4]: empty-set, @PreemptableWrite1(arg0, [0,1)){{$}}
; GLOBAL-NEXT: x[4]: full-set, @PreemptableWrite1(arg0, [0,1)){{$}}
; CHECK-NOT: ]:
entry:
%x = alloca i32, align 4
%x1 = bitcast i32* %x to i8*
call void @PreemptableWrite1(i8* %x1)
ret void
}
; Call to function with interposable linkage
define void @InterposableCall() #0 {
; CHECK-LABEL: @InterposableCall dso_preemptable{{$}}
; CHECK-NEXT: args uses:
; CHECK-NEXT: allocas uses:
; LOCAL-NEXT: x[4]: empty-set, @InterposableWrite1(arg0, [0,1)){{$}}
; NOLTO-NEXT: x[4]: full-set, @InterposableWrite1(arg0, [0,1)){{$}}
; LTO-NEXT: x[4]: [0,1), @InterposableWrite1(arg0, [0,1)){{$}}
; CHECK-NOT: ]:
entry:
%x = alloca i32, align 4
%x1 = bitcast i32* %x to i8*
call void @InterposableWrite1(i8* %x1)
ret void
}
; Call to function with private linkage
define void @PrivateCall() #0 {
; CHECK-LABEL: @PrivateCall dso_preemptable{{$}}
; CHECK-NEXT: args uses:
; CHECK-NEXT: allocas uses:
; LOCAL-NEXT: x[4]: empty-set, @PrivateWrite1(arg0, [0,1)){{$}}
; GLOBAL-NEXT: x[4]: [0,1), @PrivateWrite1(arg0, [0,1)){{$}}
; CHECK-NOT: ]:
entry:
%x = alloca i32, align 4
%x1 = bitcast i32* %x to i8*
call void @PrivateWrite1(i8* %x1)
ret void
}
define private void @PrivateWrite1(i8* %p) #0 {
; CHECK-LABEL: @PrivateWrite1{{$}}
; CHECK-NEXT: args uses:
; CHECK-NEXT: p[]: [0,1){{$}}
; CHECK-NEXT: allocas uses:
; CHECK-NOT: ]:
entry:
store i8 0, i8* %p, align 1
ret void
}
; Caller returns a dependent value.
; FIXME: alloca considered unsafe even if the return value is unused.
define void @f7() #0 {
; CHECK-LABEL: @f7 dso_preemptable{{$}}
; CHECK-NEXT: args uses:
; CHECK-NEXT: allocas uses:
; LOCAL-NEXT: x[4]: empty-set, @ReturnDependent(arg0, [0,1)){{$}}
; GLOBAL-NEXT: x[4]: full-set, @ReturnDependent(arg0, [0,1)){{$}}
; CHECK-NOT: ]:
entry:
%x = alloca i32, align 4
%x1 = bitcast i32* %x to i8*
%x2 = call i8* @ReturnDependent(i8* %x1)
ret void
}
define void @f8left() #0 {
; CHECK-LABEL: @f8left dso_preemptable{{$}}
; CHECK-NEXT: args uses:
; CHECK-NEXT: allocas uses:
; LOCAL-NEXT: x[8]: empty-set, @Rec2(arg0, [2,3)){{$}}
; GLOBAL-NEXT: x[8]: [0,4), @Rec2(arg0, [2,3)){{$}}
; CHECK-NOT: ]:
entry:
%x = alloca i64, align 4
%x1 = bitcast i64* %x to i8*
%x2 = getelementptr i8, i8* %x1, i64 2
; 2 + [-2, 2) = [0, 4) => OK
call void @Rec2(i8* %x2)
ret void
}
define void @f8right() #0 {
; CHECK-LABEL: @f8right dso_preemptable{{$}}
; CHECK-NEXT: args uses:
; CHECK-NEXT: allocas uses:
; LOCAL-NEXT: x[8]: empty-set, @Rec2(arg0, [6,7)){{$}}
; GLOBAL-NEXT: x[8]: [4,8), @Rec2(arg0, [6,7)){{$}}
; CHECK-NOT: ]:
entry:
%x = alloca i64, align 4
%x1 = bitcast i64* %x to i8*
%x2 = getelementptr i8, i8* %x1, i64 6
; 6 + [-2, 2) = [4, 8) => OK
call void @Rec2(i8* %x2)
ret void
}
define void @f8oobleft() #0 {
; CHECK-LABEL: @f8oobleft dso_preemptable{{$}}
; CHECK-NEXT: args uses:
; CHECK-NEXT: allocas uses:
; LOCAL-NEXT: x[8]: empty-set, @Rec2(arg0, [1,2)){{$}}
; GLOBAL-NEXT: x[8]: [-1,3), @Rec2(arg0, [1,2)){{$}}
; CHECK-NOT: ]:
entry:
%x = alloca i64, align 4
%x1 = bitcast i64* %x to i8*
%x2 = getelementptr i8, i8* %x1, i64 1
; 1 + [-2, 2) = [-1, 3) => NOT OK
call void @Rec2(i8* %x2)
ret void
}
define void @f8oobright() #0 {
; CHECK-LABEL: @f8oobright dso_preemptable{{$}}
; CHECK-NEXT: args uses:
; CHECK-NEXT: allocas uses:
; LOCAL-NEXT: x[8]: empty-set, @Rec2(arg0, [7,8)){{$}}
; GLOBAL-NEXT: x[8]: [5,9), @Rec2(arg0, [7,8)){{$}}
; CHECK-NOT: ]:
entry:
%x = alloca i64, align 4
%x1 = bitcast i64* %x to i8*
%x2 = getelementptr i8, i8* %x1, i64 7
; 7 + [-2, 2) = [5, 9) => NOT OK
call void @Rec2(i8* %x2)
ret void
}
define void @TwoArguments() #0 {
; CHECK-LABEL: @TwoArguments dso_preemptable{{$}}
; CHECK-NEXT: args uses:
; CHECK-NEXT: allocas uses:
; LOCAL-NEXT: x[8]: empty-set, @Write4_2(arg1, [0,1)), @Write4_2(arg0, [4,5)){{$}}
; GLOBAL-NEXT: x[8]: [0,8), @Write4_2(arg1, [0,1)), @Write4_2(arg0, [4,5)){{$}}
; CHECK-NOT: ]:
entry:
%x = alloca i64, align 4
%x1 = bitcast i64* %x to i8*
%x2 = getelementptr i8, i8* %x1, i64 4
call void @Write4_2(i8* %x2, i8* %x1)
ret void
}
define void @TwoArgumentsOOBOne() #0 {
; CHECK-LABEL: @TwoArgumentsOOBOne dso_preemptable{{$}}
; CHECK-NEXT: args uses:
; CHECK-NEXT: allocas uses:
; LOCAL-NEXT: x[8]: empty-set, @Write4_2(arg1, [0,1)), @Write4_2(arg0, [5,6)){{$}}
; GLOBAL-NEXT: x[8]: [0,9), @Write4_2(arg1, [0,1)), @Write4_2(arg0, [5,6)){{$}}
; CHECK-NOT: ]:
entry:
%x = alloca i64, align 4
%x1 = bitcast i64* %x to i8*
%x2 = getelementptr i8, i8* %x1, i64 5
call void @Write4_2(i8* %x2, i8* %x1)
ret void
}
define void @TwoArgumentsOOBOther() #0 {
; CHECK-LABEL: @TwoArgumentsOOBOther dso_preemptable{{$}}
; CHECK-NEXT: args uses:
; CHECK-NEXT: allocas uses:
; LOCAL-NEXT: x[8]: empty-set, @Write4_2(arg1, [-1,0)), @Write4_2(arg0, [4,5)){{$}}
; GLOBAL-NEXT: x[8]: [-1,8), @Write4_2(arg1, [-1,0)), @Write4_2(arg0, [4,5)){{$}}
; CHECK-NOT: ]:
entry:
%x = alloca i64, align 4
%x0 = bitcast i64* %x to i8*
%x1 = getelementptr i8, i8* %x0, i64 -1
%x2 = getelementptr i8, i8* %x0, i64 4
call void @Write4_2(i8* %x2, i8* %x1)
ret void
}
define void @TwoArgumentsOOBBoth() #0 {
; CHECK-LABEL: @TwoArgumentsOOBBoth dso_preemptable{{$}}
; CHECK-NEXT: args uses:
; CHECK-NEXT: allocas uses:
; LOCAL-NEXT: x[8]: empty-set, @Write4_2(arg1, [-1,0)), @Write4_2(arg0, [5,6)){{$}}
; GLOBAL-NEXT: x[8]: [-1,9), @Write4_2(arg1, [-1,0)), @Write4_2(arg0, [5,6)){{$}}
; CHECK-NOT: ]:
entry:
%x = alloca i64, align 4
%x0 = bitcast i64* %x to i8*
%x1 = getelementptr i8, i8* %x0, i64 -1
%x2 = getelementptr i8, i8* %x0, i64 5
call void @Write4_2(i8* %x2, i8* %x1)
ret void
}
define i32 @TestRecursiveNoOffset(i32* %p, i32 %size) #0 {
; CHECK-LABEL: @TestRecursiveNoOffset dso_preemptable{{$}}
; CHECK-NEXT: args uses:
; LOCAL-NEXT: p[]: empty-set, @RecursiveNoOffset(arg0, [0,1)){{$}}
; GLOBAL-NEXT: p[]: full-set, @RecursiveNoOffset(arg0, [0,1)){{$}}
; CHECK-NEXT: allocas uses:
; CHECK-NEXT: sum[4]: [0,4), @RecursiveNoOffset(arg2, [0,1)){{$}}
; CHECK-NOT: ]:
entry:
%sum = alloca i32, align 4
%0 = bitcast i32* %sum to i8*
store i32 0, i32* %sum, align 4
call void @RecursiveNoOffset(i32* %p, i32 %size, i32* %sum)
%1 = load i32, i32* %sum, align 4
ret i32 %1
}
define void @TestRecursiveWithOffset(i32 %size) #0 {
; CHECK-LABEL: @TestRecursiveWithOffset dso_preemptable{{$}}
; CHECK-NEXT: args uses:
; CHECK-NEXT: allocas uses:
; LOCAL-NEXT: sum[64]: empty-set, @RecursiveWithOffset(arg1, [0,1)){{$}}
; GLOBAL-NEXT: sum[64]: full-set, @RecursiveWithOffset(arg1, [0,1)){{$}}
; CHECK-NOT: ]:
entry:
%sum = alloca i32, i64 16, align 4
call void @RecursiveWithOffset(i32 %size, i32* %sum)
ret void
}
; FIXME: IPA should detect that access is safe
define void @TestUpdateArg() #0 {
; CHECK-LABEL: @TestUpdateArg dso_preemptable{{$}}
; CHECK-NEXT: args uses:
; CHECK-NEXT: allocas uses:
; LOCAL-NEXT: x[16]: empty-set, @WriteAndReturn8(arg0, [0,1)){{$}}
; GLOBAL-NEXT: x[16]: full-set, @WriteAndReturn8(arg0, [0,1)){{$}}
; CHECK-NOT: ]:
entry:
%x = alloca i8, i64 16, align 4
%0 = call i8* @WriteAndReturn8(i8* %x)
ret void
}
; The rest is from Inputs/ipa.ll
; CHECK-LABEL: @Write1{{$}}
; CHECK-NEXT: args uses:
; CHECK-NEXT: p[]: [0,1){{$}}
; CHECK-NEXT: allocas uses:
; CHECK-NOT: ]:
; CHECK-LABEL: @Write4{{$}}
; CHECK-NEXT: args uses:
; CHECK-NEXT: p[]: [0,4){{$}}
; CHECK-NEXT: allocas uses:
; CHECK-NOT: ]:
; CHECK-LABEL: @Write4_2{{$}}
; CHECK-NEXT: args uses:
; CHECK-NEXT: p[]: [0,4){{$}}
; CHECK-NEXT: q[]: [0,4){{$}}
; CHECK-NEXT: allocas uses:
; CHECK-NOT: ]:
; CHECK-LABEL: @Write8{{$}}
; CHECK-NEXT: args uses:
; CHECK-NEXT: p[]: [0,8){{$}}
; CHECK-NEXT: allocas uses:
; CHECK-NOT: ]:
; CHECK-LABEL: @WriteAndReturn8{{$}}
; CHECK-NEXT: args uses:
; CHECK-NEXT: p[]: full-set{{$}}
; CHECK-NEXT: allocas uses:
; CHECK-NOT: ]:
; CHECK-LABEL: @PreemptableWrite1 dso_preemptable{{$}}
; CHECK-NEXT: args uses:
; CHECK-NEXT: p[]: [0,1){{$}}
; CHECK-NEXT: allocas uses:
; CHECK-NOT: ]:
; CHECK-LABEL: @InterposableWrite1 interposable{{$}}
; CHECK-NEXT: args uses:
; CHECK-NEXT: p[]: [0,1){{$}}
; CHECK-NEXT: allocas uses:
; CHECK-NOT: ]:
; CHECK-LABEL: @ReturnDependent{{$}}
; CHECK-NEXT: args uses:
; CHECK-NEXT: p[]: full-set{{$}}
; CHECK-NEXT: allocas uses:
; CHECK-NOT: ]:
; CHECK-LABEL: @Rec0{{$}}
; CHECK-NEXT: args uses:
; LOCAL-NEXT: p[]: empty-set, @Write4(arg0, [2,3)){{$}}
; GLOBAL-NEXT: p[]: [2,6)
; CHECK-NEXT: allocas uses:
; CHECK-NOT: ]:
; CHECK-LABEL: @Rec1{{$}}
; CHECK-NEXT: args uses:
; LOCAL-NEXT: p[]: empty-set, @Rec0(arg0, [1,2)){{$}}
; GLOBAL-NEXT: p[]: [3,7)
; CHECK-NEXT: allocas uses:
; CHECK-NOT: ]:
; CHECK-LABEL: @Rec2{{$}}
; CHECK-NEXT: args uses:
; LOCAL-NEXT: p[]: empty-set, @Rec1(arg0, [-5,-4)){{$}}
; GLOBAL-NEXT: p[]: [-2,2)
; CHECK-NEXT: allocas uses:
; CHECK-NOT: ]:
; CHECK-LABEL: @RecursiveNoOffset{{$}}
; CHECK-NEXT: args uses:
; LOCAL-NEXT: p[]: [0,4), @RecursiveNoOffset(arg0, [4,5)){{$}}
; GLOBAL-NEXT: p[]: full-set, @RecursiveNoOffset(arg0, [4,5)){{$}}
; CHECK-NEXT: acc[]: [0,4), @RecursiveNoOffset(arg2, [0,1)){{$}}
; CHECK-NEXT: allocas uses:
; CHECK-NOT: ]:
; CHECK-LABEL: @RecursiveWithOffset{{$}}
; CHECK-NEXT: args uses:
; LOCAL-NEXT: acc[]: [0,4), @RecursiveWithOffset(arg1, [4,5)){{$}}
; GLOBAL-NEXT: acc[]: full-set, @RecursiveWithOffset(arg1, [4,5)){{$}}
; CHECK-NEXT: allocas uses:
; CHECK-NOT: ]:
; CHECK-LABEL: @ReturnAlloca
; CHECK-NEXT: args uses:
; CHECK-NEXT: allocas uses:
; CHECK-NEXT: x[8]: full-set
; CHECK-NOT: ]: