[RISCV][VLOPT] Add vector narrowing integer right shift instructions to isSupportedIn...
[llvm-project.git] / llvm / test / CodeGen / AArch64 / stack-guard-sve.ll
blobe3308e95e46a0555924499cb6d5523553608006c
1 ; RUN: llc -mtriple=aarch64--linux-gnu -mattr=+sve < %s | FileCheck %s
3 declare dso_local void @val_fn(<vscale x 4 x float>)
4 declare dso_local void @ptr_fn(ptr)
6 ; An alloca of a scalable vector shouldn't trigger stack protection.
8 ; CHECK-LABEL: call_value:
9 ; CHECK-NOT: mov x19, sp
10 ; CHECK: addvl sp, sp, #-1
11 ; CHECK-NOT: __stack_chk_guard
12 ; CHECK: st1w { {{z[0-9]+.s}} }, {{p[0-9]+}}, [x29, #-1, mul vl]
13 define void @call_value() #0 {
14 entry:
15   %x = alloca <vscale x 4 x float>, align 16
16   store <vscale x 4 x float> zeroinitializer, ptr %x, align 16
17   %0 = load <vscale x 4 x float>, ptr %x, align 16
18   call void @val_fn(<vscale x 4 x float> %0)
19   ret void
22 ; CHECK-LABEL: call_value_strong:
23 ; CHECK-NOT: mov x19, sp
24 ; CHECK: addvl sp, sp, #-1
25 ; CHECK-NOT: __stack_chk_guard
26 ; CHECK: st1w { {{z[0-9]+.s}} }, {{p[0-9]+}}, [x29, #-1, mul vl]
27 define void @call_value_strong() #1 {
28 entry:
29   %x = alloca <vscale x 4 x float>, align 16
30   store <vscale x 4 x float> zeroinitializer, ptr %x, align 16
31   %0 = load <vscale x 4 x float>, ptr %x, align 16
32   call void @val_fn(<vscale x 4 x float> %0)
33   ret void
36 ; Address-taking of a scalable vector should trigger stack protection only with
37 ; sspstrong, and the scalable vector should be be placed below the stack guard.
39 ; CHECK-LABEL: call_ptr:
40 ; CHECK-NOT: mov x19, sp
41 ; CHECK: addvl sp, sp, #-1
42 ; CHECK-NOT: __stack_chk_guard
43 ; CHECK: addvl x0, x29, #-1
44 ; CHECK: bl ptr_fn
45 define void @call_ptr() #0 {
46 entry:
47   %x = alloca <vscale x 4 x float>, align 16
48   call void @ptr_fn(ptr %x)
49   ret void
52 ; CHECK-LABEL: call_ptr_strong:
53 ; CHECK: mov x29, sp
54 ; CHECK: addvl sp, sp, #-2
55 ; CHECK-DAG: addvl [[ADDR:x[0-9]+]], x29, #-1
56 ; CHECK-DAG: ldr [[VAL:x[0-9]+]], [{{x[0-9]+}}, :lo12:__stack_chk_guard]
57 ; CHECK-DAG: str [[VAL]], [[[ADDR]]]
58 ; CHECK-DAG: addvl x0, x29, #-2
59 ; CHECK: bl ptr_fn
60 define void @call_ptr_strong() #1 {
61 entry:
62   %x = alloca <vscale x 4 x float>, align 16
63   call void @ptr_fn(ptr %x)
64   ret void
67 ; Check that both variables are addressed in the same way
69 ; CHECK-LABEL: call_both:
70 ; CHECK: mov x29, sp
71 ; CHECK: addvl sp, sp, #-2
72 ; CHECK-NOT: __stack_chk_guard
73 ; CHECK: st1w { {{z[0-9]+.s}} }, {{p[0-9]+}}, [x29, #-1, mul vl]
74 ; CHECK: bl val_fn
75 ; CHECK: addvl x0, x29, #-2
76 ; CHECK: bl ptr_fn
77 define void @call_both() #0 {
78 entry:
79   %x = alloca <vscale x 4 x float>, align 16
80   %y = alloca <vscale x 4 x float>, align 16
81   store <vscale x 4 x float> zeroinitializer, ptr %x, align 16
82   %0 = load <vscale x 4 x float>, ptr %x, align 16
83   call void @val_fn(<vscale x 4 x float> %0)
84   call void @ptr_fn(ptr %y)
85   ret void
88 ; CHECK-LABEL: call_both_strong:
89 ; CHECK: mov x29, sp
90 ; CHECK: addvl sp, sp, #-3
91 ; CHECK-DAG: addvl [[ADDR:x[0-9]+]], x29, #-1
92 ; CHECK-DAG: ldr [[VAL:x[0-9]+]], [{{x[0-9]+}}, :lo12:__stack_chk_guard]
93 ; CHECK-DAG: str [[VAL]], [[[ADDR]]]
94 ; CHECK-DAG: st1w { {{z[0-9]+.s}} }, {{p[0-9]+}}, [x29, #-2, mul vl]
95 ; CHECK: bl val_fn
96 ; CHECK: addvl x0, x29, #-3
97 ; CHECK: bl ptr_fn
98 define void @call_both_strong() #1 {
99 entry:
100   %x = alloca <vscale x 4 x float>, align 16
101   %y = alloca <vscale x 4 x float>, align 16
102   store <vscale x 4 x float> zeroinitializer, ptr %x, align 16
103   %0 = load <vscale x 4 x float>, ptr %x, align 16
104   call void @val_fn(<vscale x 4 x float> %0)
105   call void @ptr_fn(ptr %y)
106   ret void
109 ; Pushed callee-saved regs should be above the stack guard
111 ; CHECK-LABEL: callee_save:
112 ; CHECK: mov x29, sp
113 ; CHECK: addvl sp, sp, #-18
114 ; CHECK: str {{z[0-9]+}}, [sp, #{{[0-9]+}}, mul vl]
115 ; CHECK-NOT: mov x29, sp
116 ; CHECK: addvl sp, sp, #-1
117 ; CHECK-NOT: __stack_chk_guard
118 ; CHECK: addvl [[REG:x[0-9]+]], x29, #-11
119 ; CHECK: st1w { {{z[0-9]+.s}} }, {{p[0-9]+}}, [[[REG]], #-8, mul vl]
120 define void @callee_save(<vscale x 4 x float> %x) #0 {
121 entry:
122   %x.addr = alloca <vscale x 4 x float>, align 16
123   store <vscale x 4 x float> %x, ptr %x.addr, align 16
124   call void @ptr_fn(ptr %x.addr)
125   ret void
128 ; CHECK-LABEL: callee_save_strong:
129 ; CHECK: mov x29, sp
130 ; CHECK: addvl sp, sp, #-18
131 ; CHECK: str {{z[0-9]+}}, [sp, #{{[0-9]+}}, mul vl]
132 ; CHECK: addvl sp, sp, #-2
133 ; CHECK-DAG: addvl [[ADDR:x[0-9]+]], x29, #-19
134 ; CHECK-DAG: ldr [[VAL:x[0-9]+]], [{{x[0-9]+}}, :lo12:__stack_chk_guard]
135 ; CHECK-DAG: str [[VAL]], [[[ADDR]]]
136 ; CHECK-DAG: addvl [[ADDR2:x[0-9]+]], x29, #-12
137 ; CHECK-DAG: st1w { z0.s }, p0, [[[ADDR2]], #-8, mul vl]
138 define void @callee_save_strong(<vscale x 4 x float> %x) #1 {
139 entry:
140   %x.addr = alloca <vscale x 4 x float>, align 16
141   store <vscale x 4 x float> %x, ptr %x.addr, align 16
142   call void @ptr_fn(ptr %x.addr)
143   ret void
146 ; Check that local stack allocation works correctly both when we have a stack
147 ; guard but no vulnerable SVE objects, and when we do have such objects.
149 ; CHECK-LABEL: local_stack_alloc:
150 ; CHECK: mov x29, sp
151 ; CHECK: sub sp, sp, #16, lsl #12
152 ; CHECK: sub sp, sp, #16
153 ; CHECK: addvl sp, sp, #-2
155 ; Stack guard is placed below the SVE stack area (and above all fixed-width objects)
156 ; CHECK-DAG: add [[STACK_GUARD_SPILL_PART_LOC:x[0-9]+]], sp, #8, lsl #12
157 ; CHECK-DAG: add [[STACK_GUARD_SPILL_PART_LOC]], [[STACK_GUARD_SPILL_PART_LOC]], #16
158 ; CHECK-DAG: ldr [[STACK_GUARD:x[0-9]+]], [{{x[0-9]+}}, :lo12:__stack_chk_guard]
159 ; CHECK-DAG: str [[STACK_GUARD]], [[[STACK_GUARD_SPILL_PART_LOC]], #32760]
161 ; char_arr is below the stack guard
162 ; CHECK-DAG: add [[CHAR_ARR_LOC:x[0-9]+]], sp, #16, lsl #12
163 ; CHECK-DAG: strb wzr, [[[CHAR_ARR_LOC]]]
165 ; large1 is accessed via a virtual base register
166 ; CHECK-DAG: add [[LARGE1:x[0-9]+]], sp, #8, lsl #12
167 ; CHECK-DAG: stp x0, x0, [[[LARGE1]]]
169 ; large2 is at the bottom of the stack
170 ; CHECK-DAG: stp x0, x0, [sp]
172 ; vec1 and vec2 are in the SVE stack immediately below fp
173 ; CHECK-DAG: addvl x0, x29, #-1
174 ; CHECK-DAG: bl ptr_fn
175 ; CHECK-DAG: addvl x0, x29, #-2
176 ; CHECK-DAG: bl ptr_fn
177 define void @local_stack_alloc(i64 %val) #0 {
178 entry:
179   %char_arr = alloca [8 x i8], align 4
180   %gep0 = getelementptr [8 x i8], ptr %char_arr, i64 0, i64 0
181   store i8 0, ptr %gep0, align 8
182   %large1 = alloca [4096 x i64], align 8
183   %large2 = alloca [4096 x i64], align 8
184   %vec_1 = alloca <vscale x 4 x float>, align 16
185   %vec_2 = alloca <vscale x 4 x float>, align 16
186   %gep1 = getelementptr [4096 x i64], ptr %large1, i64 0, i64 0
187   %gep2 = getelementptr [4096 x i64], ptr %large1, i64 0, i64 1
188   store i64 %val, ptr %gep1, align 8
189   store i64 %val, ptr %gep2, align 8
190   %gep3 = getelementptr [4096 x i64], ptr %large2, i64 0, i64 0
191   %gep4 = getelementptr [4096 x i64], ptr %large2, i64 0, i64 1
192   store i64 %val, ptr %gep3, align 8
193   store i64 %val, ptr %gep4, align 8
194   call void @ptr_fn(ptr %vec_1)
195   call void @ptr_fn(ptr %vec_2)
196   ret void
199 ; CHECK-LABEL: local_stack_alloc_strong:
200 ; CHECK: mov x29, sp
201 ; CHECK: sub sp, sp, #16, lsl #12
202 ; CHECK: sub sp, sp, #16
203 ; CHECK: addvl sp, sp, #-3
205 ; Stack guard is placed at the top of the SVE stack area
206 ; CHECK-DAG: ldr [[STACK_GUARD:x[0-9]+]], [{{x[0-9]+}}, :lo12:__stack_chk_guard]
207 ; CHECK-DAG: addvl [[STACK_GUARD_POS:x[0-9]+]], x29, #-1
208 ; CHECK-DAG: str [[STACK_GUARD]], [[[STACK_GUARD_POS]]]
210 ; char_arr is below the SVE stack area
211 ; CHECK-DAG: add [[CHAR_ARR:x[0-9]+]], sp, #15, lsl #12            // =61440
212 ; CHECK-DAG: add [[CHAR_ARR]], [[CHAR_ARR]], #9
213 ; CHECK-DAG: strb wzr, [[[CHAR_ARR]], #4095]
215 ; large1 is accessed via a virtual base register
216 ; CHECK-DAG: add [[LARGE1:x[0-9]+]], sp, #8, lsl #12
217 ; CHECK-DAG: stp x0, x0, [[[LARGE1]], #8]
219 ; large2 is at the bottom of the stack
220 ; CHECK-DAG: stp x0, x0, [sp, #8]
222 ; vec1 and vec2 are in the SVE stack area below the stack guard
223 ; CHECK-DAG: addvl x0, x29, #-2
224 ; CHECK-DAG: bl ptr_fn
225 ; CHECK-DAG: addvl x0, x29, #-3
226 ; CHECK-DAG: bl ptr_fn
227 define void @local_stack_alloc_strong(i64 %val) #1 {
228 entry:
229   %char_arr = alloca [8 x i8], align 4
230   %gep0 = getelementptr [8 x i8], ptr %char_arr, i64 0, i64 0
231   store i8 0, ptr %gep0, align 8
232   %large1 = alloca [4096 x i64], align 8
233   %large2 = alloca [4096 x i64], align 8
234   %vec_1 = alloca <vscale x 4 x float>, align 16
235   %vec_2 = alloca <vscale x 4 x float>, align 16
236   %gep1 = getelementptr [4096 x i64], ptr %large1, i64 0, i64 0
237   %gep2 = getelementptr [4096 x i64], ptr %large1, i64 0, i64 1
238   store i64 %val, ptr %gep1, align 8
239   store i64 %val, ptr %gep2, align 8
240   %gep3 = getelementptr [4096 x i64], ptr %large2, i64 0, i64 0
241   %gep4 = getelementptr [4096 x i64], ptr %large2, i64 0, i64 1
242   store i64 %val, ptr %gep3, align 8
243   store i64 %val, ptr %gep4, align 8
244   call void @ptr_fn(ptr %vec_1)
245   call void @ptr_fn(ptr %vec_2)
246   ret void
249 ; A GEP addressing into a vector of <vscale x 4 x float> is in-bounds for
250 ; offsets up to 3, but out-of-bounds (and so triggers stack protection with
251 ; sspstrong) after that.
253 ; CHECK-LABEL: vector_gep_3:
254 ; CHECK-NOT: __stack_chk_guard
255 define void @vector_gep_3() #0 {
256 entry:
257   %vec = alloca <vscale x 4 x float>, align 16
258   %gep = getelementptr <vscale x 4 x float>, ptr %vec, i64 0, i64 3
259   store float 0.0, ptr %gep, align 4
260   ret void
263 ; CHECK-LABEL: vector_gep_4:
264 ; CHECK-NOT: __stack_chk_guard
265 define void @vector_gep_4() #0 {
266 entry:
267   %vec = alloca <vscale x 4 x float>, align 16
268   %gep = getelementptr <vscale x 4 x float>, ptr %vec, i64 0, i64 4
269   store float 0.0, ptr %gep, align 4
270   ret void
273 ; CHECK-LABEL: vector_gep_twice:
274 ; CHECK-NOT: __stack_chk_guard
275 define void @vector_gep_twice() #0 {
276 entry:
277   %vec = alloca <vscale x 4 x float>, align 16
278   %gep1 = getelementptr <vscale x 4 x float>, ptr %vec, i64 0, i64 3
279   store float 0.0, ptr %gep1, align 4
280   %gep2 = getelementptr float, ptr %gep1, i64 1
281   store float 0.0, ptr %gep2, align 4
282   ret void
285 ; CHECK-LABEL: vector_gep_n:
286 ; CHECK-NOT: __stack_chk_guard
287 define void @vector_gep_n(i64 %n) #0 {
288 entry:
289   %vec = alloca <vscale x 4 x float>, align 16
290   %gep = getelementptr <vscale x 4 x float>, ptr %vec, i64 0, i64 %n
291   store float 0.0, ptr %gep, align 4
292   ret void
295 ; CHECK-LABEL: vector_gep_3_strong:
296 ; CHECK-NOT: __stack_chk_guard
297 define void @vector_gep_3_strong() #1 {
298 entry:
299   %vec = alloca <vscale x 4 x float>, align 16
300   %gep = getelementptr <vscale x 4 x float>, ptr %vec, i64 0, i64 3
301   store float 0.0, ptr %gep, align 4
302   ret void
305 ; CHECK-LABEL: vector_gep_4_strong:
306 ; CHECK: __stack_chk_guard
307 define void @vector_gep_4_strong(i64 %val) #1 {
308 entry:
309   %vec = alloca <vscale x 4 x float>, align 16
310   %gep = getelementptr <vscale x 4 x float>, ptr %vec, i64 0, i64 4
311   store float 0.0, ptr %gep, align 4
312   ret void
316 ; CHECK-LABEL: vector_gep_twice_strong:
317 ; CHECK: __stack_chk_guard
318 define void @vector_gep_twice_strong() #1 {
319 entry:
320   %vec = alloca <vscale x 4 x float>, align 16
321   %gep1 = getelementptr <vscale x 4 x float>, ptr %vec, i64 0, i64 3
322   store float 0.0, ptr %gep1, align 4
323   %gep2 = getelementptr float, ptr %gep1, i64 1
324   store float 0.0, ptr %gep2, align 4
325   ret void
328 ; CHECK-LABEL: vector_gep_n_strong:
329 ; CHECK: __stack_chk_guard
330 define void @vector_gep_n_strong(i64 %n) #1 {
331 entry:
332   %vec = alloca <vscale x 4 x float>, align 16
333   %gep = getelementptr <vscale x 4 x float>, ptr %vec, i64 0, i64 %n
334   store float 0.0, ptr %gep, align 4
335   ret void
338 attributes #0 = { ssp "frame-pointer"="non-leaf" }
339 attributes #1 = { sspstrong "frame-pointer"="non-leaf" }
341 !llvm.module.flags = !{!0}
342 !0 = !{i32 7, !"direct-access-external-data", i32 1}