1 ; RUN: opt -S -passes="print<stack-safety-local>" -disable-output < %s 2>&1 | FileCheck %s
2 ; RUN: opt -S -passes="print-stack-safety" -disable-output < %s 2>&1 | FileCheck %s --check-prefixes=CHECK,GLOBAL
4 target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
5 target triple = "x86_64-unknown-linux-gnu"
7 declare void @llvm.memset.p0.i64(ptr %dest, i8 %val, i64 %len, i1 %isvolatile)
8 declare void @llvm.memset.p0.i32(ptr %dest, i8 %val, i32 %len, i1 %isvolatile)
9 declare void @llvm.memcpy.p0.p0.i32(ptr %dest, ptr %src, i32 %len, i1 %isvolatile)
10 declare void @llvm.memmove.p0.p0.i32(ptr %dest, ptr %src, i32 %len, i1 %isvolatile)
12 define void @MemsetInBounds() {
13 ; CHECK-LABEL: MemsetInBounds dso_preemptable{{$}}
14 ; CHECK-NEXT: args uses:
15 ; CHECK-NEXT: allocas uses:
16 ; CHECK-NEXT: x[4]: [0,4){{$}}
17 ; GLOBAL-NEXT: safe accesses:
18 ; GLOBAL-NEXT: call void @llvm.memset.p0.i32(ptr %x, i8 42, i32 4, i1 false)
21 %x = alloca i32, align 4
22 call void @llvm.memset.p0.i32(ptr %x, i8 42, i32 4, i1 false)
26 ; Volatile does not matter for access bounds.
27 define void @VolatileMemsetInBounds() {
28 ; CHECK-LABEL: VolatileMemsetInBounds dso_preemptable{{$}}
29 ; CHECK-NEXT: args uses:
30 ; CHECK-NEXT: allocas uses:
31 ; CHECK-NEXT: x[4]: [0,4){{$}}
32 ; GLOBAL-NEXT: safe accesses:
33 ; GLOBAL-NEXT: call void @llvm.memset.p0.i32(ptr %x, i8 42, i32 4, i1 true)
36 %x = alloca i32, align 4
37 call void @llvm.memset.p0.i32(ptr %x, i8 42, i32 4, i1 true)
41 define void @MemsetOutOfBounds() {
42 ; CHECK-LABEL: MemsetOutOfBounds dso_preemptable{{$}}
43 ; CHECK-NEXT: args uses:
44 ; CHECK-NEXT: allocas uses:
45 ; CHECK-NEXT: x[4]: [0,5){{$}}
46 ; GLOBAL-NEXT: safe accesses:
49 %x = alloca i32, align 4
50 call void @llvm.memset.p0.i32(ptr %x, i8 42, i32 5, i1 false)
54 define void @MemsetNonConst(i32 %size) {
55 ; CHECK-LABEL: MemsetNonConst dso_preemptable{{$}}
56 ; CHECK-NEXT: args uses:
57 ; CHECK-NEXT: allocas uses:
58 ; CHECK-NEXT: x[4]: [0,4294967295){{$}}
59 ; GLOBAL-NEXT: safe accesses:
62 %x = alloca i32, align 4
63 call void @llvm.memset.p0.i32(ptr %x, i8 42, i32 %size, i1 false)
67 ; FIXME: memintrinsics should look at size range when possible
68 ; Right now we refuse any non-constant size.
69 define void @MemsetNonConstInBounds(i1 zeroext %z) {
70 ; CHECK-LABEL: MemsetNonConstInBounds dso_preemptable{{$}}
71 ; CHECK-NEXT: args uses:
72 ; CHECK-NEXT: allocas uses:
73 ; CHECK-NEXT: x[4]: [0,7){{$}}
74 ; GLOBAL-NEXT: safe accesses:
77 %x = alloca i32, align 4
78 %size = select i1 %z, i32 3, i32 4
79 call void @llvm.memset.p0.i32(ptr %x, i8 42, i32 %size, i1 false)
83 define void @MemsetNonConstSize() {
84 ; CHECK-LABEL: MemsetNonConstSize dso_preemptable{{$}}
85 ; CHECK-NEXT: args uses:
86 ; CHECK-NEXT: allocas uses:
87 ; CHECK-NEXT: x[4]: [0,4294967295){{$}}
88 ; CHECK-NEXT: y[4]: empty-set{{$}}
89 ; GLOBAL-NEXT: safe accesses:
92 %x = alloca i32, align 4
93 %y = alloca i32, align 4
94 %xint = ptrtoint ptr %x to i32
95 %yint = ptrtoint ptr %y to i32
96 %d = sub i32 %xint, %yint
97 call void @llvm.memset.p0.i32(ptr %x, i8 42, i32 %d, i1 false)
101 define void @MemsetHugeUpper_m1(i1 %bool) {
102 ; CHECK-LABEL: MemsetHugeUpper_m1 dso_preemptable{{$}}
103 ; CHECK-NEXT: args uses:
104 ; CHECK-NEXT: allocas uses:
105 ; CHECK-NEXT: x[4]: full-set
107 %x = alloca i32, align 4
108 br i1 %bool, label %if.then, label %if.end
111 call void @llvm.memset.p0.i64(ptr %x, i8 0, i64 -1, i1 false)
118 define void @MemsetHugeUpper_m2(i1 %bool) {
119 ; CHECK-LABEL: MemsetHugeUpper_m2 dso_preemptable{{$}}
120 ; CHECK-NEXT: args uses:
121 ; CHECK-NEXT: allocas uses:
122 ; CHECK-NEXT: x[4]: full-set
124 %x = alloca i32, align 4
125 br i1 %bool, label %if.then, label %if.end
128 call void @llvm.memset.p0.i64(ptr %x, i8 0, i64 -2, i1 false)
135 define void @MemcpyInBounds() {
136 ; CHECK-LABEL: MemcpyInBounds dso_preemptable{{$}}
137 ; CHECK-NEXT: args uses:
138 ; CHECK-NEXT: allocas uses:
139 ; CHECK-NEXT: x[4]: [0,4){{$}}
140 ; CHECK-NEXT: y[4]: [0,4){{$}}
141 ; GLOBAL-NEXT: safe accesses:
142 ; GLOBAL-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr %x, ptr %y, i32 4, i1 false)
145 %x = alloca i32, align 4
146 %y = alloca i32, align 4
147 call void @llvm.memcpy.p0.p0.i32(ptr %x, ptr %y, i32 4, i1 false)
151 define void @MemcpySrcOutOfBounds() {
152 ; CHECK-LABEL: MemcpySrcOutOfBounds dso_preemptable{{$}}
153 ; CHECK-NEXT: args uses:
154 ; CHECK-NEXT: allocas uses:
155 ; CHECK-NEXT: x[8]: [0,5){{$}}
156 ; CHECK-NEXT: y[4]: [0,5){{$}}
157 ; GLOBAL-NEXT: safe accesses
160 %x = alloca i64, align 4
161 %y = alloca i32, align 4
162 call void @llvm.memcpy.p0.p0.i32(ptr %x, ptr %y, i32 5, i1 false)
166 define void @MemcpyDstOutOfBounds() {
167 ; CHECK-LABEL: MemcpyDstOutOfBounds dso_preemptable{{$}}
168 ; CHECK-NEXT: args uses:
169 ; CHECK-NEXT: allocas uses:
170 ; CHECK-NEXT: x[4]: [0,5){{$}}
171 ; CHECK-NEXT: y[8]: [0,5){{$}}
172 ; GLOBAL-NEXT: safe accesses
175 %x = alloca i32, align 4
176 %y = alloca i64, align 4
177 call void @llvm.memcpy.p0.p0.i32(ptr %x, ptr %y, i32 5, i1 false)
181 define void @MemcpyBothOutOfBounds() {
182 ; CHECK-LABEL: MemcpyBothOutOfBounds dso_preemptable{{$}}
183 ; CHECK-NEXT: args uses:
184 ; CHECK-NEXT: allocas uses:
185 ; CHECK-NEXT: x[4]: [0,9){{$}}
186 ; CHECK-NEXT: y[8]: [0,9){{$}}
187 ; GLOBAL-NEXT: safe accesses
190 %x = alloca i32, align 4
191 %y = alloca i64, align 4
192 call void @llvm.memcpy.p0.p0.i32(ptr %x, ptr %y, i32 9, i1 false)
196 define void @MemcpySelfInBounds() {
197 ; CHECK-LABEL: MemcpySelfInBounds dso_preemptable{{$}}
198 ; CHECK-NEXT: args uses:
199 ; CHECK-NEXT: allocas uses:
200 ; CHECK-NEXT: x[8]: [0,8){{$}}
201 ; GLOBAL-NEXT: safe accesses
202 ; GLOBAL-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr %x, ptr %x2, i32 3, i1 false)
205 %x = alloca i64, align 4
206 %x2 = getelementptr i8, ptr %x, i64 5
207 call void @llvm.memcpy.p0.p0.i32(ptr %x, ptr %x2, i32 3, i1 false)
211 define void @MemcpySelfSrcOutOfBounds() {
212 ; CHECK-LABEL: MemcpySelfSrcOutOfBounds dso_preemptable{{$}}
213 ; CHECK-NEXT: args uses:
214 ; CHECK-NEXT: allocas uses:
215 ; CHECK-NEXT: x[8]: [0,9){{$}}
216 ; GLOBAL-NEXT: safe accesses:
219 %x = alloca i64, align 4
220 %x2 = getelementptr i8, ptr %x, i64 5
221 call void @llvm.memcpy.p0.p0.i32(ptr %x, ptr %x2, i32 4, i1 false)
225 define void @MemcpySelfDstOutOfBounds() {
226 ; CHECK-LABEL: MemcpySelfDstOutOfBounds dso_preemptable{{$}}
227 ; CHECK-NEXT: args uses:
228 ; CHECK-NEXT: allocas uses:
229 ; CHECK-NEXT: x[8]: [0,9){{$}}
230 ; GLOBAL-NEXT: safe accesses:
233 %x = alloca i64, align 4
234 %x2 = getelementptr i8, ptr %x, i64 5
235 call void @llvm.memcpy.p0.p0.i32(ptr %x2, ptr %x, i32 4, i1 false)
239 define void @MemmoveSelfBothOutOfBounds() {
240 ; CHECK-LABEL: MemmoveSelfBothOutOfBounds dso_preemptable{{$}}
241 ; CHECK-NEXT: args uses:
242 ; CHECK-NEXT: allocas uses:
243 ; CHECK-NEXT: x[8]: [0,14){{$}}
244 ; GLOBAL-NEXT: safe accesses:
247 %x = alloca i64, align 4
248 %x2 = getelementptr i8, ptr %x, i64 5
249 call void @llvm.memmove.p0.p0.i32(ptr %x, ptr %x2, i32 9, i1 false)
253 define void @MemsetInBoundsCast() {
254 ; CHECK-LABEL: MemsetInBoundsCast dso_preemptable{{$}}
255 ; CHECK-NEXT: args uses:
256 ; CHECK-NEXT: allocas uses:
257 ; CHECK-NEXT: x[4]: [0,4){{$}}
258 ; CHECK-NEXT: y[1]: empty-set{{$}}
259 ; GLOBAL-NEXT: safe accesses:
260 ; GLOBAL-NEXT: call void @llvm.memset.p0.i32(ptr %x, i8 %yint, i32 4, i1 false)
263 %x = alloca i32, align 4
264 %y = alloca i8, align 1
265 %yint = ptrtoint ptr %y to i8
266 call void @llvm.memset.p0.i32(ptr %x, i8 %yint, i32 4, i1 false)
270 define void @MemcpyInBoundsCast2(i8 %zint8) {
271 ; CHECK-LABEL: MemcpyInBoundsCast2 dso_preemptable{{$}}
272 ; CHECK-NEXT: args uses:
273 ; CHECK-NEXT: allocas uses:
274 ; CHECK-NEXT: x[256]: [0,255){{$}}
275 ; CHECK-NEXT: y[256]: [0,255){{$}}
276 ; CHECK-NEXT: z[1]: empty-set{{$}}
277 ; GLOBAL-NEXT: safe accesses:
278 ; GLOBAL-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr %x, ptr %y, i32 %zint32, i1 false)
281 %x = alloca [256 x i8], align 4
282 %y = alloca [256 x i8], align 4
283 %z = alloca i8, align 1
284 %zint32 = zext i8 %zint8 to i32
285 call void @llvm.memcpy.p0.p0.i32(ptr %x, ptr %y, i32 %zint32, i1 false)