[ARM] Better OR's for MVE compares
[llvm-core.git] / test / Analysis / StackSafetyAnalysis / local.ll
blob814b97d29638493eeba1b728da03a55b3c0bae06
1 ; RUN: opt -S -analyze -stack-safety-local < %s | FileCheck %s --check-prefixes=CHECK,LOCAL
2 ; RUN: opt -S -passes="print<stack-safety-local>" -disable-output < %s 2>&1 | FileCheck %s --check-prefixes=CHECK,LOCAL
3 ; RUN: opt -S -analyze -stack-safety < %s | FileCheck %s --check-prefixes=CHECK,GLOBAL
4 ; RUN: opt -S -passes="print-stack-safety" -disable-output < %s 2>&1 | FileCheck %s --check-prefixes=CHECK,GLOBAL
6 target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
7 target triple = "x86_64-unknown-linux-gnu"
9 @sink = global i8* null, align 8
11 declare void @llvm.memset.p0i8.i32(i8* %dest, i8 %val, i32 %len, i1 %isvolatile)
12 declare void @llvm.memcpy.p0i8.p0i8.i32(i8* %dest, i8* %src, i32 %len, i1 %isvolatile)
13 declare void @llvm.memmove.p0i8.p0i8.i32(i8* %dest, i8* %src, i32 %len, i1 %isvolatile)
15 ; Address leaked.
16 define void @LeakAddress() {
17 ; CHECK-LABEL: @LeakAddress dso_preemptable{{$}}
18 ; CHECK-NEXT: args uses:
19 ; CHECK-NEXT: allocas uses:
20 ; CHECK-NEXT: x[4]: full-set{{$}}
21 ; CHECK-NOT: ]:
22 entry:
23   %x = alloca i32, align 4
24   %x1 = bitcast i32* %x to i8*
25   store i8* %x1, i8** @sink, align 8
26   ret void
29 define void @StoreInBounds() {
30 ; CHECK-LABEL: @StoreInBounds dso_preemptable{{$}}
31 ; CHECK-NEXT: args uses:
32 ; CHECK-NEXT: allocas uses:
33 ; CHECK-NEXT: x[4]: [0,1){{$}}
34 ; CHECK-NOT: ]:
35 entry:
36   %x = alloca i32, align 4
37   %x1 = bitcast i32* %x to i8*
38   store i8 0, i8* %x1, align 1
39   ret void
42 define void @StoreInBounds2() {
43 ; CHECK-LABEL: @StoreInBounds2 dso_preemptable{{$}}
44 ; CHECK-NEXT: args uses:
45 ; CHECK-NEXT: allocas uses:
46 ; CHECK-NEXT: x[4]: [0,4){{$}}
47 ; CHECK-NOT: ]:
48 entry:
49   %x = alloca i32, align 4
50   store i32 0, i32* %x, align 4
51   ret void
54 define void @StoreInBounds3() {
55 ; CHECK-LABEL: @StoreInBounds3 dso_preemptable{{$}}
56 ; CHECK-NEXT: args uses:
57 ; CHECK-NEXT: allocas uses:
58 ; CHECK-NEXT: x[4]: [2,3){{$}}
59 ; CHECK-NOT: ]:
60 entry:
61   %x = alloca i32, align 4
62   %x1 = bitcast i32* %x to i8*
63   %x2 = getelementptr i8, i8* %x1, i64 2
64   store i8 0, i8* %x2, align 1
65   ret void
68 ; FIXME: ScalarEvolution does not look through ptrtoint/inttoptr.
69 define void @StoreInBounds4() {
70 ; CHECK-LABEL: @StoreInBounds4 dso_preemptable{{$}}
71 ; CHECK-NEXT: args uses:
72 ; CHECK-NEXT: allocas uses:
73 ; CHECK-NEXT: x[4]: [2,-1){{$}}
74 ; CHECK-NOT: ]:
75 entry:
76   %x = alloca i32, align 4
77   %x1 = ptrtoint i32* %x to i64
78   %x2 = add i64 %x1, 2
79   %x3 = inttoptr i64 %x2 to i8*
80   store i8 0, i8* %x3, align 1
81   ret void
84 define void @StoreOutOfBounds() {
85 ; CHECK-LABEL: @StoreOutOfBounds dso_preemptable{{$}}
86 ; CHECK-NEXT: args uses:
87 ; CHECK-NEXT: allocas uses:
88 ; CHECK-NEXT: x[4]: [2,6){{$}}
89 ; CHECK-NOT: ]:
90 entry:
91   %x = alloca i32, align 4
92   %x1 = bitcast i32* %x to i8*
93   %x2 = getelementptr i8, i8* %x1, i64 2
94   %x3 = bitcast i8* %x2 to i32*
95   store i32 0, i32* %x3, align 1
96   ret void
99 ; There is no difference in load vs store handling.
100 define void @LoadInBounds() {
101 ; CHECK-LABEL: @LoadInBounds dso_preemptable{{$}}
102 ; CHECK-NEXT: args uses:
103 ; CHECK-NEXT: allocas uses:
104 ; CHECK-NEXT: x[4]: [0,1){{$}}
105 ; CHECK-NOT: ]:
106 entry:
107   %x = alloca i32, align 4
108   %x1 = bitcast i32* %x to i8*
109   %v = load i8, i8* %x1, align 1
110   ret void
113 define void @LoadOutOfBounds() {
114 ; CHECK-LABEL: @LoadOutOfBounds dso_preemptable{{$}}
115 ; CHECK-NEXT: args uses:
116 ; CHECK-NEXT: allocas uses:
117 ; CHECK-NEXT: x[4]: [2,6){{$}}
118 ; CHECK-NOT: ]:
119 entry:
120   %x = alloca i32, align 4
121   %x1 = bitcast i32* %x to i8*
122   %x2 = getelementptr i8, i8* %x1, i64 2
123   %x3 = bitcast i8* %x2 to i32*
124   %v = load i32, i32* %x3, align 1
125   ret void
128 ; Leak through ret.
129 define i8* @Ret() {
130 ; CHECK-LABEL: @Ret dso_preemptable{{$}}
131 ; CHECK-NEXT: args uses:
132 ; CHECK-NEXT: allocas uses:
133 ; CHECK-NEXT: x[4]: full-set{{$}}
134 ; CHECK-NOT: ]:
135 entry:
136   %x = alloca i32, align 4
137   %x1 = bitcast i32* %x to i8*
138   %x2 = getelementptr i8, i8* %x1, i64 2
139   ret i8* %x2
142 declare void @Foo(i16* %p)
144 define void @DirectCall() {
145 ; CHECK-LABEL: @DirectCall dso_preemptable{{$}}
146 ; CHECK-NEXT: args uses:
147 ; CHECK-NEXT: allocas uses:
148 ; LOCAL-NEXT: x[8]: empty-set, @Foo(arg0, [2,3)){{$}}
149 ; GLOBAL-NEXT: x[8]: full-set, @Foo(arg0, [2,3)){{$}}
150 ; CHECK-NOT: ]:
151 entry:
152   %x = alloca i64, align 4
153   %x1 = bitcast i64* %x to i16*
154   %x2 = getelementptr i16, i16* %x1, i64 1
155   call void @Foo(i16* %x2);
156   ret void
159 ; Indirect calls can not be analyzed (yet).
160 ; FIXME: %p[]: full-set looks invalid
161 define void @IndirectCall(void (i8*)* %p) {
162 ; CHECK-LABEL: @IndirectCall dso_preemptable{{$}}
163 ; CHECK-NEXT: args uses:
164 ; CHECK-NEXT: p[]: full-set{{$}}
165 ; CHECK-NEXT: allocas uses:
166 ; CHECK-NEXT: x[4]: full-set{{$}}
167 ; CHECK-NOT: ]:
168 entry:
169   %x = alloca i32, align 4
170   %x1 = bitcast i32* %x to i8*
171   call void %p(i8* %x1);
172   ret void
175 define void @NonConstantOffset(i1 zeroext %z) {
176 ; CHECK-LABEL: @NonConstantOffset dso_preemptable{{$}}
177 ; CHECK-NEXT: args uses:
178 ; CHECK-NEXT: z[]: full-set{{$}}
179 ; CHECK-NEXT: allocas uses:
180 ; CHECK-NEXT: x[4]: [0,4){{$}}
181 ; CHECK-NOT: ]:
182 entry:
183   %x = alloca i32, align 4
184   %x1 = bitcast i32* %x to i8*
185   %idx = select i1 %z, i64 1, i64 2
186   %x2 = getelementptr i8, i8* %x1, i64 %idx
187   store i8 0, i8* %x2, align 1
188   ret void
191 define void @NonConstantOffsetOOB(i1 zeroext %z) {
192 ; CHECK-LABEL: @NonConstantOffsetOOB dso_preemptable{{$}}
193 ; CHECK-NEXT: args uses:
194 ; CHECK-NEXT: z[]: full-set{{$}}
195 ; CHECK-NEXT: allocas uses:
196 ; CHECK-NEXT: x[4]: [0,6){{$}}
197 ; CHECK-NOT: ]:
198 entry:
199   %x = alloca i32, align 4
200   %x1 = bitcast i32* %x to i8*
201   %idx = select i1 %z, i64 1, i64 4
202   %x2 = getelementptr i8, i8* %x1, i64 %idx
203   store i8 0, i8* %x2, align 1
204   ret void
207 define void @ArrayAlloca() {
208 ; CHECK-LABEL: @ArrayAlloca dso_preemptable{{$}}
209 ; CHECK-NEXT: args uses:
210 ; CHECK-NEXT: allocas uses:
211 ; CHECK-NEXT: x[40]: [36,40){{$}}
212 ; CHECK-NOT: ]:
213 entry:
214   %x = alloca i32, i32 10, align 4
215   %x1 = bitcast i32* %x to i8*
216   %x2 = getelementptr i8, i8* %x1, i64 36
217   %x3 = bitcast i8* %x2 to i32*
218   store i32 0, i32* %x3, align 1
219   ret void
222 define void @ArrayAllocaOOB() {
223 ; CHECK-LABEL: @ArrayAllocaOOB dso_preemptable{{$}}
224 ; CHECK-NEXT: args uses:
225 ; CHECK-NEXT: allocas uses:
226 ; CHECK-NEXT: x[40]: [37,41){{$}}
227 ; CHECK-NOT: ]:
228 entry:
229   %x = alloca i32, i32 10, align 4
230   %x1 = bitcast i32* %x to i8*
231   %x2 = getelementptr i8, i8* %x1, i64 37
232   %x3 = bitcast i8* %x2 to i32*
233   store i32 0, i32* %x3, align 1
234   ret void
237 define void @DynamicAllocaUnused(i64 %size) {
238 ; CHECK-LABEL: @DynamicAllocaUnused dso_preemptable{{$}}
239 ; CHECK-NEXT: args uses:
240 ; CHECK-NEXT: size[]: empty-set{{$}}
241 ; CHECK-NEXT: allocas uses:
242 ; CHECK-NEXT: x[0]: empty-set{{$}}
243 ; CHECK-NOT: ]:
244 entry:
245   %x = alloca i32, i64 %size, align 16
246   ret void
249 ; Dynamic alloca with unknown size.
250 define void @DynamicAlloca(i64 %size) {
251 ; CHECK-LABEL: @DynamicAlloca dso_preemptable{{$}}
252 ; CHECK-NEXT: args uses:
253 ; CHECK-NEXT: size[]: [0,-12){{$}}
254 ; CHECK-NEXT: allocas uses:
255 ; CHECK-NEXT: x[0]: [0,4){{$}}
256 ; CHECK-NOT: ]:
257 entry:
258   %x = alloca i32, i64 %size, align 16
259   store i32 0, i32* %x, align 1
260   ret void
263 ; Dynamic alloca with limited size.
264 ; FIXME: could be proved safe. Implement.
265 define void @DynamicAllocaFiniteSizeRange(i1 zeroext %z) {
266 ; CHECK-LABEL: @DynamicAllocaFiniteSizeRange dso_preemptable{{$}}
267 ; CHECK-NEXT: args uses:
268 ; CHECK-NEXT: z[]: [0,-12){{$}}
269 ; CHECK-NEXT: allocas uses:
270 ; CHECK-NEXT: x[0]: [0,4){{$}}
271 ; CHECK-NOT: ]:
272 entry:
273   %size = select i1 %z, i64 3, i64 5
274   %x = alloca i32, i64 %size, align 16
275   store i32 0, i32* %x, align 1
276   ret void
279 define signext i8 @SimpleLoop() {
280 ; CHECK-LABEL: @SimpleLoop dso_preemptable{{$}}
281 ; CHECK-NEXT: args uses:
282 ; CHECK-NEXT: allocas uses:
283 ; CHECK-NEXT: x[10]: [0,10){{$}}
284 ; CHECK-NOT: ]:
285 entry:
286   %x = alloca [10 x i8], align 1
287   %0 = getelementptr inbounds [10 x i8], [10 x i8]* %x, i64 0, i64 0
288   %lftr.limit = getelementptr inbounds [10 x i8], [10 x i8]* %x, i64 0, i64 10
289   br label %for.body
291 for.body:
292   %sum.010 = phi i8 [ 0, %entry ], [ %add, %for.body ]
293   %p.09 = phi i8* [ %0, %entry ], [ %incdec.ptr, %for.body ]
294   %incdec.ptr = getelementptr inbounds i8, i8* %p.09, i64 1
295   %1 = load volatile i8, i8* %p.09, align 1
296   %add = add i8 %1, %sum.010
297   %exitcond = icmp eq i8* %incdec.ptr, %lftr.limit
298   br i1 %exitcond, label %for.cond.cleanup, label %for.body
300 for.cond.cleanup:
301   ret i8 %add
304 ; OOB in a loop.
305 define signext i8 @SimpleLoopOOB() {
306 ; CHECK-LABEL: @SimpleLoopOOB dso_preemptable{{$}}
307 ; CHECK-NEXT: args uses:
308 ; CHECK-NEXT: allocas uses:
309 ; CHECK-NEXT: x[10]: [0,11){{$}}
310 ; CHECK-NOT: ]:
311 entry:
312   %x = alloca [10 x i8], align 1
313   %0 = getelementptr inbounds [10 x i8], [10 x i8]* %x, i64 0, i64 0
314  ; 11 iterations
315   %lftr.limit = getelementptr inbounds [10 x i8], [10 x i8]* %x, i64 0, i64 11
316   br label %for.body
318 for.body:
319   %sum.010 = phi i8 [ 0, %entry ], [ %add, %for.body ]
320   %p.09 = phi i8* [ %0, %entry ], [ %incdec.ptr, %for.body ]
321   %incdec.ptr = getelementptr inbounds i8, i8* %p.09, i64 1
322   %1 = load volatile i8, i8* %p.09, align 1
323   %add = add i8 %1, %sum.010
324   %exitcond = icmp eq i8* %incdec.ptr, %lftr.limit
325   br i1 %exitcond, label %for.cond.cleanup, label %for.body
327 for.cond.cleanup:
328   ret i8 %add
331 ; FIXME: we don't understand that %sz in the memset call is limited to 128 by the preceding check.
332 define dso_local void @SizeCheck(i32 %sz) {
333 ; CHECK-LABEL: @SizeCheck{{$}}
334 ; CHECK-NEXT: args uses:
335 ; CHECK-NEXT: sz[]: [0,1){{$}}
336 ; CHECK-NEXT: allocas uses:
337 ; CHECK-NEXT: x1[128]: full-set{{$}}
338 ; CHECK-NOT: ]:
339 entry:
340   %x1 = alloca [128 x i8], align 16
341   %x1.sub = getelementptr inbounds [128 x i8], [128 x i8]* %x1, i64 0, i64 0
342   %cmp = icmp slt i32 %sz, 129
343   br i1 %cmp, label %if.then, label %if.end
345 if.then:
346   call void @llvm.memset.p0i8.i32(i8* nonnull align 16 %x1.sub, i8 0, i32 %sz, i1 false)
347   br label %if.end
349 if.end:
350   ret void