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.p0i8.i64(i8* %dest, i8 %val, i64 %len, i1 %isvolatile)
8 declare void @llvm.memset.p0i8.i32(i8* %dest, i8 %val, i32 %len, i1 %isvolatile)
9 declare void @llvm.memcpy.p0i8.p0i8.i32(i8* %dest, i8* %src, i32 %len, i1 %isvolatile)
10 declare void @llvm.memmove.p0i8.p0i8.i32(i8* %dest, i8* %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.p0i8.i32(i8* %x1, i8 42, i32 4, i1 false)
21 %x = alloca i32, align 4
22 %x1 = bitcast i32* %x to i8*
23 call void @llvm.memset.p0i8.i32(i8* %x1, i8 42, i32 4, i1 false)
27 ; Volatile does not matter for access bounds.
28 define void @VolatileMemsetInBounds() {
29 ; CHECK-LABEL: VolatileMemsetInBounds dso_preemptable{{$}}
30 ; CHECK-NEXT: args uses:
31 ; CHECK-NEXT: allocas uses:
32 ; CHECK-NEXT: x[4]: [0,4){{$}}
33 ; GLOBAL-NEXT: safe accesses:
34 ; GLOBAL-NEXT: call void @llvm.memset.p0i8.i32(i8* %x1, i8 42, i32 4, i1 true)
37 %x = alloca i32, align 4
38 %x1 = bitcast i32* %x to i8*
39 call void @llvm.memset.p0i8.i32(i8* %x1, i8 42, i32 4, i1 true)
43 define void @MemsetOutOfBounds() {
44 ; CHECK-LABEL: MemsetOutOfBounds dso_preemptable{{$}}
45 ; CHECK-NEXT: args uses:
46 ; CHECK-NEXT: allocas uses:
47 ; CHECK-NEXT: x[4]: [0,5){{$}}
48 ; GLOBAL-NEXT: safe accesses:
51 %x = alloca i32, align 4
52 %x1 = bitcast i32* %x to i8*
53 call void @llvm.memset.p0i8.i32(i8* %x1, i8 42, i32 5, i1 false)
57 define void @MemsetNonConst(i32 %size) {
58 ; CHECK-LABEL: MemsetNonConst dso_preemptable{{$}}
59 ; CHECK-NEXT: args uses:
60 ; CHECK-NEXT: allocas uses:
61 ; CHECK-NEXT: x[4]: [0,4294967295){{$}}
62 ; GLOBAL-NEXT: safe accesses:
65 %x = alloca i32, align 4
66 %x1 = bitcast i32* %x to i8*
67 call void @llvm.memset.p0i8.i32(i8* %x1, i8 42, i32 %size, i1 false)
71 ; FIXME: memintrinsics should look at size range when possible
72 ; Right now we refuse any non-constant size.
73 define void @MemsetNonConstInBounds(i1 zeroext %z) {
74 ; CHECK-LABEL: MemsetNonConstInBounds dso_preemptable{{$}}
75 ; CHECK-NEXT: args uses:
76 ; CHECK-NEXT: allocas uses:
77 ; CHECK-NEXT: x[4]: [0,7){{$}}
78 ; GLOBAL-NEXT: safe accesses:
81 %x = alloca i32, align 4
82 %x1 = bitcast i32* %x to i8*
83 %size = select i1 %z, i32 3, i32 4
84 call void @llvm.memset.p0i8.i32(i8* %x1, i8 42, i32 %size, i1 false)
88 define void @MemsetNonConstSize() {
89 ; CHECK-LABEL: MemsetNonConstSize dso_preemptable{{$}}
90 ; CHECK-NEXT: args uses:
91 ; CHECK-NEXT: allocas uses:
92 ; CHECK-NEXT: x[4]: [0,4294967295){{$}}
93 ; CHECK-NEXT: y[4]: empty-set{{$}}
94 ; GLOBAL-NEXT: safe accesses:
97 %x = alloca i32, align 4
98 %y = alloca i32, align 4
99 %x1 = bitcast i32* %x to i8*
100 %xint = ptrtoint i32* %x to i32
101 %yint = ptrtoint i32* %y to i32
102 %d = sub i32 %xint, %yint
103 call void @llvm.memset.p0i8.i32(i8* %x1, i8 42, i32 %d, i1 false)
107 define void @MemcpyInBounds() {
108 ; CHECK-LABEL: MemcpyInBounds dso_preemptable{{$}}
109 ; CHECK-NEXT: args uses:
110 ; CHECK-NEXT: allocas uses:
111 ; CHECK-NEXT: x[4]: [0,4){{$}}
112 ; CHECK-NEXT: y[4]: [0,4){{$}}
113 ; GLOBAL-NEXT: safe accesses:
114 ; GLOBAL-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* %x1, i8* %y1, i32 4, i1 false)
117 %x = alloca i32, align 4
118 %y = alloca i32, align 4
119 %x1 = bitcast i32* %x to i8*
120 %y1 = bitcast i32* %y to i8*
121 call void @llvm.memcpy.p0i8.p0i8.i32(i8* %x1, i8* %y1, i32 4, i1 false)
125 define void @MemcpySrcOutOfBounds() {
126 ; CHECK-LABEL: MemcpySrcOutOfBounds dso_preemptable{{$}}
127 ; CHECK-NEXT: args uses:
128 ; CHECK-NEXT: allocas uses:
129 ; CHECK-NEXT: x[8]: [0,5){{$}}
130 ; CHECK-NEXT: y[4]: [0,5){{$}}
131 ; GLOBAL-NEXT: safe accesses
134 %x = alloca i64, align 4
135 %y = alloca i32, align 4
136 %x1 = bitcast i64* %x to i8*
137 %y1 = bitcast i32* %y to i8*
138 call void @llvm.memcpy.p0i8.p0i8.i32(i8* %x1, i8* %y1, i32 5, i1 false)
142 define void @MemcpyDstOutOfBounds() {
143 ; CHECK-LABEL: MemcpyDstOutOfBounds dso_preemptable{{$}}
144 ; CHECK-NEXT: args uses:
145 ; CHECK-NEXT: allocas uses:
146 ; CHECK-NEXT: x[4]: [0,5){{$}}
147 ; CHECK-NEXT: y[8]: [0,5){{$}}
148 ; GLOBAL-NEXT: safe accesses
151 %x = alloca i32, align 4
152 %y = alloca i64, align 4
153 %x1 = bitcast i32* %x to i8*
154 %y1 = bitcast i64* %y to i8*
155 call void @llvm.memcpy.p0i8.p0i8.i32(i8* %x1, i8* %y1, i32 5, i1 false)
159 define void @MemcpyBothOutOfBounds() {
160 ; CHECK-LABEL: MemcpyBothOutOfBounds dso_preemptable{{$}}
161 ; CHECK-NEXT: args uses:
162 ; CHECK-NEXT: allocas uses:
163 ; CHECK-NEXT: x[4]: [0,9){{$}}
164 ; CHECK-NEXT: y[8]: [0,9){{$}}
165 ; GLOBAL-NEXT: safe accesses
168 %x = alloca i32, align 4
169 %y = alloca i64, align 4
170 %x1 = bitcast i32* %x to i8*
171 %y1 = bitcast i64* %y to i8*
172 call void @llvm.memcpy.p0i8.p0i8.i32(i8* %x1, i8* %y1, i32 9, i1 false)
176 define void @MemcpySelfInBounds() {
177 ; CHECK-LABEL: MemcpySelfInBounds dso_preemptable{{$}}
178 ; CHECK-NEXT: args uses:
179 ; CHECK-NEXT: allocas uses:
180 ; CHECK-NEXT: x[8]: [0,8){{$}}
181 ; GLOBAL-NEXT: safe accesses
182 ; GLOBAL-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* %x1, i8* %x2, i32 3, i1 false)
185 %x = alloca i64, align 4
186 %x1 = bitcast i64* %x to i8*
187 %x2 = getelementptr i8, i8* %x1, i64 5
188 call void @llvm.memcpy.p0i8.p0i8.i32(i8* %x1, i8* %x2, i32 3, i1 false)
192 define void @MemcpySelfSrcOutOfBounds() {
193 ; CHECK-LABEL: MemcpySelfSrcOutOfBounds dso_preemptable{{$}}
194 ; CHECK-NEXT: args uses:
195 ; CHECK-NEXT: allocas uses:
196 ; CHECK-NEXT: x[8]: [0,9){{$}}
197 ; GLOBAL-NEXT: safe accesses:
200 %x = alloca i64, align 4
201 %x1 = bitcast i64* %x to i8*
202 %x2 = getelementptr i8, i8* %x1, i64 5
203 call void @llvm.memcpy.p0i8.p0i8.i32(i8* %x1, i8* %x2, i32 4, i1 false)
207 define void @MemcpySelfDstOutOfBounds() {
208 ; CHECK-LABEL: MemcpySelfDstOutOfBounds dso_preemptable{{$}}
209 ; CHECK-NEXT: args uses:
210 ; CHECK-NEXT: allocas uses:
211 ; CHECK-NEXT: x[8]: [0,9){{$}}
212 ; GLOBAL-NEXT: safe accesses:
215 %x = alloca i64, align 4
216 %x1 = bitcast i64* %x to i8*
217 %x2 = getelementptr i8, i8* %x1, i64 5
218 call void @llvm.memcpy.p0i8.p0i8.i32(i8* %x2, i8* %x1, i32 4, i1 false)
222 define void @MemmoveSelfBothOutOfBounds() {
223 ; CHECK-LABEL: MemmoveSelfBothOutOfBounds dso_preemptable{{$}}
224 ; CHECK-NEXT: args uses:
225 ; CHECK-NEXT: allocas uses:
226 ; CHECK-NEXT: x[8]: [0,14){{$}}
227 ; GLOBAL-NEXT: safe accesses:
230 %x = alloca i64, align 4
231 %x1 = bitcast i64* %x to i8*
232 %x2 = getelementptr i8, i8* %x1, i64 5
233 call void @llvm.memmove.p0i8.p0i8.i32(i8* %x1, i8* %x2, i32 9, i1 false)
237 define void @MemsetInBoundsCast() {
238 ; CHECK-LABEL: MemsetInBoundsCast dso_preemptable{{$}}
239 ; CHECK-NEXT: args uses:
240 ; CHECK-NEXT: allocas uses:
241 ; CHECK-NEXT: x[4]: [0,4){{$}}
242 ; CHECK-NEXT: y[1]: empty-set{{$}}
243 ; GLOBAL-NEXT: safe accesses:
244 ; GLOBAL-NEXT: call void @llvm.memset.p0i8.i32(i8* %x1, i8 %yint, i32 4, i1 false)
247 %x = alloca i32, align 4
248 %y = alloca i8, align 1
249 %x1 = bitcast i32* %x to i8*
250 %yint = ptrtoint i8* %y to i8
251 call void @llvm.memset.p0i8.i32(i8* %x1, i8 %yint, i32 4, i1 false)
255 define void @MemcpyInBoundsCast2(i8 %zint8) {
256 ; CHECK-LABEL: MemcpyInBoundsCast2 dso_preemptable{{$}}
257 ; CHECK-NEXT: args uses:
258 ; CHECK-NEXT: allocas uses:
259 ; CHECK-NEXT: x[256]: [0,255){{$}}
260 ; CHECK-NEXT: y[256]: [0,255){{$}}
261 ; CHECK-NEXT: z[1]: empty-set{{$}}
262 ; GLOBAL-NEXT: safe accesses:
263 ; GLOBAL-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* %x1, i8* %y1, i32 %zint32, i1 false)
266 %x = alloca [256 x i8], align 4
267 %y = alloca [256 x i8], align 4
268 %z = alloca i8, align 1
269 %x1 = bitcast [256 x i8]* %x to i8*
270 %y1 = bitcast [256 x i8]* %y to i8*
271 %zint32 = zext i8 %zint8 to i32
272 call void @llvm.memcpy.p0i8.p0i8.i32(i8* %x1, i8* %y1, i32 %zint32, i1 false)