1 # RUN: llc -mtriple=aarch64-none-linux-gnu -run-pass=prologepilog %s -o - | FileCheck %s
3 # Test allocation and deallocation of SVE objects on the stack,
4 # as well as using a combination of scalable and non-scalable
5 # offsets to access the SVE on the stack.
7 # SVE objects are allocated below the (scalar) callee saves,
8 # and above spills/locals and the alignment gap, e.g.
12 # +-------------+ <- SP before call
14 # | Frame record| (if available)
15 # |-------------| <- FP (if available)
18 # |/////////////| alignment gap.
22 # +-------------+ <- SP after call and frame-setup
26 define void @test_allocate_sve() nounwind { entry: unreachable }
27 define void @test_allocate_sve_gpr_callee_saves() nounwind { entry: unreachable }
28 define void @test_allocate_sve_gpr_realigned() nounwind { entry: unreachable }
29 define void @test_address_sve() nounwind { entry: unreachable }
30 define void @test_address_sve_fp() nounwind { entry: unreachable }
31 define void @test_stack_arg_sve() nounwind { entry: unreachable }
32 define void @test_address_sve_out_of_range() nounwind { entry: unreachable }
36 # |scratchreg| // x29 is used as scratch reg.
38 # | %fixed- | // scalable SVE object of n * 18 bytes, aligned to 16 bytes,
39 # | stack.0 | // to be materialized with 2*ADDVL (<=> 2 * n * 16bytes)
41 # | %stack.0 | // not scalable
44 # CHECK-LABEL: name: test_allocate_sve
45 # CHECK: stackSize: 32
48 # CHECK-NEXT: $sp = frame-setup STRXpre killed $[[SCRATCH:[a-z0-9]+]], $sp, -16
49 # CHECK-NEXT: $sp = frame-setup ADDVL_XXI $sp, -2
50 # CHECK-NEXT: $sp = frame-setup SUBXri $sp, 16, 0
52 # CHECK-NEXT: $sp = frame-destroy ADDVL_XXI $sp, 2
53 # CHECK-NEXT: $sp = frame-destroy ADDXri $sp, 16, 0
54 # CHECK-NEXT: $sp, $[[SCRATCH]] = frame-destroy LDRXpost $sp, 16
55 # CHECK-NEXT: RET_ReallyLR
56 name: test_allocate_sve
58 - { id: 0, stack-id: sve-vec, size: 18, alignment: 2, offset: -18 }
60 - { id: 0, stack-id: default, size: 16, alignment: 8 }
67 # | x20, x21 | // callee saves
68 # |scratchreg| // x29 is used as scratch reg.
70 # | %fixed- | // scalable objects
73 # | %stack.0 | // not scalable
76 # CHECK-LABEL: name: test_allocate_sve_gpr_callee_saves
77 # CHECK: stackSize: 48
80 # CHECK-NEXT: $sp = frame-setup STRXpre killed $[[SCRATCH:[a-z0-9]+]], $sp, -32
81 # CHECK-NEXT: frame-setup STPXi killed $x21, killed $x20, $sp, 2
82 # CHECK-NEXT: $sp = frame-setup ADDVL_XXI $sp, -2
83 # CHECK-NEXT: $sp = frame-setup SUBXri $sp, 16, 0
84 # CHECK-NEXT: $x20 = IMPLICIT_DEF
85 # CHECK-NEXT: $x21 = IMPLICIT_DEF
86 # CHECK-NEXT: $sp = frame-destroy ADDVL_XXI $sp, 2
87 # CHECK-NEXT: $sp = frame-destroy ADDXri $sp, 16, 0
88 # CHECK-NEXT: $x21, $x20 = frame-destroy LDPXi $sp, 2
89 # CHECK-NEXT: $sp, $[[SCRATCH]] = frame-destroy LDRXpost $sp, 32
90 # CHECK-NEXT: RET_ReallyLR
91 name: test_allocate_sve_gpr_callee_saves
93 - { id: 0, stack-id: sve-vec, size: 18, alignment: 2, offset: -18 }
95 - { id: 0, stack-id: default, size: 16, alignment: 8 }
104 # | lr, fp | // frame record
106 # | %fixed- | // scalable objects
109 # |//////////| // alignment gap
110 # | %stack.0 | // not scalable
112 # CHECK-LABEL: name: test_allocate_sve_gpr_realigned
113 # CHECK: stackSize: 32
116 # CHECK-NEXT: $sp = frame-setup STPXpre killed $fp, killed $lr, $sp, -2
117 # CHECK-NEXT: $fp = frame-setup ADDXri $sp, 0, 0
118 # CHECK-NEXT: $sp = frame-setup ADDVL_XXI $sp, -2
119 # CHECK-NEXT: $[[TMP:x[0-9]+]] = frame-setup SUBXri $sp, 16, 0
120 # CHECK-NEXT: $sp = ANDXri killed $[[TMP]]
121 # CHECK-NEXT: $sp = frame-destroy ADDXri $fp, 0, 0
122 # CHECK-NEXT: $sp, $fp, $lr = frame-destroy LDPXpost $sp, 2
123 # CHECK-NEXT: RET_ReallyLR
124 name: test_allocate_sve_gpr_realigned
126 - { id: 0, stack-id: sve-vec, size: 18, alignment: 2, offset: -18 }
128 - { id: 0, stack-id: default, size: 16, alignment: 32 }
135 # | x20, x21 | // callee saves
137 # | %stack.0 | // scalable @ SP + 16b + 32 scalable bytes
138 # | %stack.1 | // scalable @ SP + 16b + 16 scalable bytes
139 # | %stack.2 | // scalable @ SP + 16b + 14 scalable bytes
141 # | %stack.0 | // not scalable
144 # CHECK-LABEL: name: test_address_sve
145 # CHECK: stackSize: 32
148 # CHECK-NEXT: $sp = frame-setup STRXpre killed $[[SCRATCH:[a-z0-9]+]], $sp, -16
149 # CHECK-NEXT: $sp = frame-setup ADDVL_XXI $sp, -3
150 # CHECK-NEXT: $sp = frame-setup SUBXri $sp, 16, 0
152 # CHECK-NEXT: $[[TMP:x[0-9]+]] = ADDXri $sp, 16
153 # CHECK-NEXT: STR_ZXI $z0, killed $[[TMP]], 2
154 # CHECK-NEXT: $[[TMP:x[0-9]+]] = ADDXri $sp, 16
155 # CHECK-NEXT: STR_ZXI $z1, killed $[[TMP]], 1
156 # CHECK-NEXT: $[[TMP:x[0-9]+]] = ADDXri $sp, 16
157 # CHECK-NEXT: STR_PXI $p0, killed $[[TMP]], 7
159 # CHECK-NEXT: $sp = frame-destroy ADDVL_XXI $sp, 3
160 # CHECK-NEXT: $sp = frame-destroy ADDXri $sp, 16, 0
161 # CHECK-NEXT: $sp, $[[SCRATCH]] = frame-destroy LDRXpost $sp, 16
162 # CHECK-NEXT: RET_ReallyLR
163 name: test_address_sve
167 - { id: 0, stack-id: sve-vec, size: 16, alignment: 8, offset: -16 }
168 - { id: 1, stack-id: sve-vec, size: 16, alignment: 8, offset: -32 }
169 - { id: 2, stack-id: sve-vec, size: 2, alignment: 2, offset: -34 }
171 - { id: 0, stack-id: default, size: 16, alignment: 8 }
174 liveins: $z0, $z1, $p0
176 STR_ZXI $z0, %fixed-stack.0, 0
177 STR_ZXI $z1, %fixed-stack.1, 0
178 STR_PXI $p0, %fixed-stack.2, 0
184 # | x20, x21 | // callee saves
185 # | lr, fp | // frame record
186 # +-----------+ <- FP
187 # | %fstack.0 | // scalable @ FP - 16 scalable bytes
188 # | %fstack.1 | // scalable @ FP - 32 scalable bytes
189 # | %fstack.2 | // scalable @ FP - 34 scalable bytes
191 # | %stack.0 | // not scalable
192 # +-----------+ <- SP
194 # CHECK-LABEL: name: test_address_sve_fp
195 # CHECK: stackSize: 32
198 # CHECK-NEXT: $sp = frame-setup STPXpre killed $fp, killed $lr, $sp, -2
199 # CHECK-NEXT: $fp = frame-setup ADDXri $sp, 0, 0
200 # CHECK-NEXT: $sp = frame-setup ADDVL_XXI $sp, -3
201 # CHECK-NEXT: $sp = frame-setup SUBXri $sp, 16, 0
203 # CHECK-NEXT: STR_ZXI $z0, $fp, -1
204 # CHECK-NEXT: STR_ZXI $z1, $fp, -2
205 # CHECK-NEXT: STR_PXI $p0, $fp, -17
207 # CHECK-NEXT: $sp = frame-destroy ADDVL_XXI $sp, 3
208 # CHECK: $sp = frame-destroy ADDXri $sp, 16, 0
209 # CHECK-NEXT: $sp, $fp, $lr = frame-destroy LDPXpost $sp, 2
210 # CHECK-NEXT: RET_ReallyLR
211 name: test_address_sve_fp
214 isFrameAddressTaken: true
216 - { id: 0, stack-id: sve-vec, size: 16, alignment: 8, offset: -16 }
217 - { id: 1, stack-id: sve-vec, size: 16, alignment: 8, offset: -32 }
218 - { id: 2, stack-id: sve-vec, size: 2, alignment: 2, offset: -34 }
220 - { id: 0, stack-id: default, size: 16, alignment: 8 }
223 liveins: $z0, $z1, $p0
225 STR_ZXI $z0, %fixed-stack.0, 0
226 STR_ZXI $z1, %fixed-stack.1, 0
227 STR_PXI $p0, %fixed-stack.2, 0
233 # | %fstack.1 | // stack arg @ SP + 16 scalable bytes + 32 bytes.
235 # |callee save| // register saved as scratch reg.
237 # | %fstack.1 | // vector of 16 scalable bytes
239 # | %stack.0 | // not scalable, 16 bytes
240 # +-----------+ <- SP
241 # CHECK-LABEL: name: test_stack_arg_sve
242 # CHECK: stackSize: 32
245 # CHECK-NEXT: $sp = frame-setup STRXpre killed $[[SCRATCH:[a-z0-9]+]], $sp, -16
246 # CHECK-NEXT: $sp = frame-setup ADDVL_XXI $sp, -1
247 # CHECK-NEXT: $sp = frame-setup SUBXri $sp, 16, 0
249 # CHECK: $[[TMP:x[0-9]+]] = ADDVL_XXI $sp, 1
250 # CHECK-NEXT: $x0 = LDRXui killed $[[TMP]], 4
252 # CHECK-NEXT: $sp = frame-destroy ADDVL_XXI $sp, 1
253 # CHECK-NEXT: $sp = frame-destroy ADDXri $sp, 16, 0
254 # CHECK-NEXT: $sp, $[[SCRATCH]] = frame-destroy LDRXpost $sp, 16
255 # CHECK-NEXT: RET_ReallyLR
256 name: test_stack_arg_sve
258 - { id: 0, stack-id: default, size: 16, alignment: 16, offset: 0 }
259 - { id: 1, stack-id: sve-vec, size: 16, alignment: 16, offset: -16 }
261 - { id: 0, stack-id: default, size: 16, alignment: 16 }
266 $x0 = LDRXui %fixed-stack.0, 0
270 # Test that the address to access an SVE data vector at an offset that
271 # does not fit its immediate, is correctly materialized.
273 # |calleesave| // register saved as scratch reg.
275 # | %stack.0 | // one SVE data object @ SP + 256 scalable bytes.
278 # |:%stack.1:| // Large object
282 # CHECK-LABEL: name: test_address_sve_out_of_range
283 # CHECK: stackSize: 16
286 # CHECK-NEXT: $sp = frame-setup STRXpre killed $[[SCRATCH:[a-z0-9]+]], $sp, -16
287 # CHECK-NEXT: $sp = frame-setup ADDVL_XXI $sp, -32
288 # CHECK-NEXT: $sp = frame-setup ADDVL_XXI $sp, -32
289 # CHECK-NEXT: $sp = frame-setup ADDVL_XXI $sp, -32
290 # CHECK-NEXT: $sp = frame-setup ADDVL_XXI $sp, -32
291 # CHECK-NEXT: $sp = frame-setup ADDVL_XXI $sp, -32
292 # CHECK-NEXT: $sp = frame-setup ADDVL_XXI $sp, -32
293 # CHECK-NEXT: $sp = frame-setup ADDVL_XXI $sp, -32
294 # CHECK-NEXT: $sp = frame-setup ADDVL_XXI $sp, -32
295 # CHECK-NEXT: $sp = frame-setup ADDVL_XXI $sp, -1
297 # CHECK-NEXT: $[[TMP2:x[0-9]+]] = ADDVL_XXI $sp, 1
298 # CHECK-NEXT: STR_ZXI $z0, killed $[[TMP2]], 255
300 # CHECK-NEXT: $[[TMP2:x[0-9]+]] = ADDPL_XXI $sp, 1
301 # CHECK-NEXT: STR_PXI $p0, killed $[[TMP2]], 255
303 # CHECK: $sp = frame-destroy ADDVL_XXI $sp, 31
304 # CHECK-NEXT: $sp = frame-destroy ADDVL_XXI $sp, 31
305 # CHECK-NEXT: $sp = frame-destroy ADDVL_XXI $sp, 31
306 # CHECK-NEXT: $sp = frame-destroy ADDVL_XXI $sp, 31
307 # CHECK-NEXT: $sp = frame-destroy ADDVL_XXI $sp, 31
308 # CHECK-NEXT: $sp = frame-destroy ADDVL_XXI $sp, 31
309 # CHECK-NEXT: $sp = frame-destroy ADDVL_XXI $sp, 31
310 # CHECK-NEXT: $sp = frame-destroy ADDVL_XXI $sp, 31
311 # CHECK-NEXT: $sp = frame-destroy ADDVL_XXI $sp, 9
312 # CHECK-NEXT: $sp, $[[SCRATCH]] = frame-destroy LDRXpost $sp, 16
313 # CHECK-NEXT: RET_ReallyLR
314 name: test_address_sve_out_of_range
318 - { id: 0, stack-id: sve-vec, size: 16, alignment: 16, offset: -16 }
319 - { id: 1, stack-id: sve-vec, size: 3584, alignment: 16, offset: -3600 }
320 - { id: 2, stack-id: sve-vec, size: 512, alignment: 16, offset: -4112 }
326 STR_ZXI $z0, %fixed-stack.0, 0
327 STR_PXI $p0, %fixed-stack.1, 0