1 # RUN: llc -mtriple=aarch64-linux-gnu -run-pass=prologepilog %s -o - | FileCheck %s
3 # The tests below test the allocation of 128bit callee-saves
4 # on the stack, specifically their offsets.
6 # Padding of GPR64-registers is needed to ensure 16 byte alignment of
7 # the stack pointer after the GPR64/FPR64 block (which is also needed
8 # for the FPR128 saves when present).
10 # This file also tests whether an emergency stack slot is allocated
11 # when the stack frame is over a given size, caused by a series of
12 # FPR128 saves. The alignment can leave a gap that can be scavenged
13 # for stack slot scavenging, so it is important that the stack size
14 # is properly estimated.
19 ; ModuleID = '<stdin>'
20 source_filename = "<stdin>"
21 target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
22 target triple = "aarch64-unknown-linux-gnu"
24 ; Function Attrs: nounwind
25 define aarch64_vector_pcs void @test_q10_q11_x19() nounwind { entry: unreachable }
27 ; Function Attrs: nounwind
28 define aarch64_vector_pcs void @test_q10_q11_x19_x20() nounwind { entry: unreachable }
30 ; Function Attrs: nounwind
31 define aarch64_vector_pcs void @test_q10_q11_x19_x20_x21() nounwind { entry: unreachable }
33 ; Function Attrs: nounwind
34 define aarch64_vector_pcs void @test_q8_to_q23_x19_to_x30() nounwind { entry: unreachable }
36 ; Function Attrs: nounwind
37 define aarch64_vector_pcs void @test_q8_to_q23_x19_to_x30_preinc() nounwind { entry: unreachable }
41 name: test_q10_q11_x19
42 tracksRegLiveness: true
49 ; Check that the alignment gap for the 8-byte x19 is padded
50 ; with another 8 bytes. The CSR region will look like this:
51 ; +-------------------+
52 ; |/////padding///////| (8 bytes)
54 ; +-------------------+ <- SP -16
55 ; | Q10, Q11 | (32 bytes)
56 ; +-------------------+ <- SP -48
58 ; CHECK-LABEL: test_q10_q11_x19{{[[:space:]]}}
59 ; CHECK-DAG: $sp = frame-setup STPQpre killed $q11, killed $q10, $sp, -3 :: (store (s128) into %stack.[[Q11:[0-9]+]]), (store (s128) into %stack.[[Q10:[0-9]+]])
60 ; CHECK-DAG: - { id: [[Q11]], {{.*}}, offset: -48, size: 16, alignment: 16
61 ; CHECK-DAG: - { id: [[Q10]], {{.*}}, offset: -32, size: 16, alignment: 16
62 ; CHECK-DAG: frame-setup STRXui killed $x19, $sp, 4 :: (store (s64) into %stack.[[X19:[0-9]+]])
63 ; CHECK-DAG: - { id: [[X19]], {{.*}}, offset: -16, size: 8, alignment: 16
67 name: test_q10_q11_x19_x20
69 tracksRegLiveness: true
77 ; +-------------------+
78 ; | X19, X20 | (16 bytes)
79 ; +-------------------+ <- SP -16
80 ; | Q10, Q11 | (32 bytes)
81 ; +-------------------+ <- SP -48
83 ; CHECK-LABEL: test_q10_q11_x19_x20{{[[:space:]]}}
84 ; CHECK-DAG: $sp = frame-setup STPQpre killed $q11, killed $q10, $sp, -3 :: (store (s128) into %stack.[[Q11:[0-9]+]]), (store (s128) into %stack.[[Q10:[0-9]+]])
85 ; CHECK-DAG: frame-setup STPXi killed $x20, killed $x19, $sp, 4 :: (store (s64) into %stack.[[X20:[0-9]+]]), (store (s64) into %stack.[[X19:[0-9]+]])
86 ; CHECK-DAG: - { id: [[Q11]], {{.*}}, offset: -48, size: 16, alignment: 16
87 ; CHECK-DAG: - { id: [[Q10]], {{.*}}, offset: -32, size: 16, alignment: 16
88 ; CHECK-DAG: - { id: [[X20]], {{.*}}, offset: -16, size: 8, alignment: 8
89 ; CHECK-DAG: - { id: [[X19]], {{.*}}, offset: -8, size: 8, alignment: 8
93 name: test_q10_q11_x19_x20_x21
94 tracksRegLiveness: true
103 ; Check that the alignment gap is padded with another 8 bytes.
104 ; The CSR region will look like this:
105 ; +-------------------+
106 ; | X19, X20 | (16 bytes)
107 ; +-------------------+ <- SP -16
108 ; |/////padding///////| (8 bytes)
110 ; +-------------------+ <- SP -32
111 ; | Q10, Q11 | (32 bytes)
112 ; +-------------------+ <- SP -64
114 ; CHECK-LABEL: test_q10_q11_x19_x20_x21
115 ; CHECK-DAG: $sp = frame-setup STPQpre killed $q11, killed $q10, $sp, -4 :: (store (s128) into %stack.[[Q11:[0-9]+]]), (store (s128) into %stack.[[Q10:[0-9]+]])
116 ; CHECK-DAG: frame-setup STRXui killed $x21, $sp, 4 :: (store (s64) into %stack.[[X21:[0-9]+]])
117 ; CHECK-DAG: frame-setup STPXi killed $x20, killed $x19, $sp, 6
118 ; CHECK-DAG: - { id: [[Q11]], {{.*}}, offset: -64, size: 16, alignment: 16
119 ; CHECK-DAG: - { id: [[Q10]], {{.*}}, offset: -48, size: 16, alignment: 16
120 ; CHECK-DAG: - { id: [[X21]], {{.*}}, offset: -32, size: 8, alignment: 16
124 name: test_q8_to_q23_x19_to_x30
125 tracksRegLiveness: true
157 ; Test with more callee saves, which triggers 'BigStack' in
158 ; AArch64FrameLowering which in turn causes an emergency spill
159 ; slot to be allocated. The emergency spill slot is allocated
160 ; as close as possible to SP, so at SP + 0.
161 ; +-------------------+
162 ; | X19..X30 | (96 bytes)
163 ; +-------------------+ <- SP -96
164 ; | Q8..Q23 | (256 bytes)
165 ; +-------------------+ <- SP -352
166 ; | emergency slot | (16 bytes)
167 ; +-------------------+ <- SP -368
169 ; CHECK-LABEL: test_q8_to_q23_x19_to_x30
170 ; CHECK: $sp = frame-setup SUBXri $sp, 368, 0
171 ; CHECK-NEXT: frame-setup STPQi killed $q23, killed $q22, $sp, 1 :: (store (s128) into %stack.{{[0-9]+}}), (store (s128) into %stack.{{[0-9]+}})
172 ; CHECK-NEXT: frame-setup STPQi killed $q21, killed $q20, $sp, 3
173 ; CHECK-NEXT: frame-setup STPQi killed $q19, killed $q18, $sp, 5
174 ; CHECK-NEXT: frame-setup STPQi killed $q17, killed $q16, $sp, 7
175 ; CHECK-NEXT: frame-setup STPQi killed $q15, killed $q14, $sp, 9
176 ; CHECK-NEXT: frame-setup STPQi killed $q13, killed $q12, $sp, 11
177 ; CHECK-NEXT: frame-setup STPQi killed $q11, killed $q10, $sp, 13
178 ; CHECK-NEXT: frame-setup STPQi killed $q9, killed $q8, $sp, 15
179 ; CHECK-NEXT: frame-setup STPXi killed $fp, killed $lr, $sp, 34 :: (store (s64) into %stack.{{[0-9]+}}), (store (s64) into %stack.{{[0-9]+}})
180 ; CHECK-NEXT: frame-setup STPXi killed $x28, killed $x27, $sp, 36
181 ; CHECK-NEXT: frame-setup STPXi killed $x26, killed $x25, $sp, 38
182 ; CHECK-NEXT: frame-setup STPXi killed $x24, killed $x23, $sp, 40
183 ; CHECK-NEXT: frame-setup STPXi killed $x22, killed $x21, $sp, 42
184 ; CHECK-NEXT: frame-setup STPXi killed $x20, killed $x19, $sp, 44
188 name: test_q8_to_q23_x19_to_x30_preinc
189 tracksRegLiveness: true
191 - { id: 0, size: 160, alignment: 4, local-offset: 0 }
224 ; When the total stack size >= 512, it will use the pre-increment
225 ; rather than the 'sub sp, sp, <size>'.
226 ; +-------------------+
227 ; | X19..X30 | (96 bytes)
228 ; +-------------------+ <- SP -96
229 ; | Q8..Q23 | (256 bytes)
230 ; +-------------------+ <- SP -352
231 ; | 'obj' | (32 bytes)
232 ; +-------------------+ <- SP -384
233 ; | emergency slot | (16 bytes)
234 ; +-------------------+ <- SP -400
236 ; CHECK-LABEL: test_q8_to_q23_x19_to_x30_preinc
237 ; CHECK: $sp = frame-setup STPQpre killed $q23, killed $q22, $sp, -22 :: (store (s128) into %stack.{{[0-9]+}}), (store (s128) into %stack.{{[0-9]+}})
238 ; CHECK-NEXT: frame-setup STPQi killed $q21, killed $q20, $sp, 2
239 ; CHECK-NEXT: frame-setup STPQi killed $q19, killed $q18, $sp, 4
240 ; CHECK-NEXT: frame-setup STPQi killed $q17, killed $q16, $sp, 6
241 ; CHECK-NEXT: frame-setup STPQi killed $q15, killed $q14, $sp, 8
242 ; CHECK-NEXT: frame-setup STPQi killed $q13, killed $q12, $sp, 10
243 ; CHECK-NEXT: frame-setup STPQi killed $q11, killed $q10, $sp, 12
244 ; CHECK-NEXT: frame-setup STPQi killed $q9, killed $q8, $sp, 14
245 ; CHECK-NEXT: frame-setup STPXi killed $fp, killed $lr, $sp, 32 :: (store (s64) into %stack.{{[0-9]+}}), (store (s64) into %stack.{{[0-9]+}})
246 ; CHECK-NEXT: frame-setup STPXi killed $x28, killed $x27, $sp, 34
247 ; CHECK-NEXT: frame-setup STPXi killed $x26, killed $x25, $sp, 36
248 ; CHECK-NEXT: frame-setup STPXi killed $x24, killed $x23, $sp, 38
249 ; CHECK-NEXT: frame-setup STPXi killed $x22, killed $x21, $sp, 40
250 ; CHECK-NEXT: frame-setup STPXi killed $x20, killed $x19, $sp, 42
251 ; CHECK-NEXT: $sp = frame-setup SUBXri $sp, 176, 0