[LoongArch][ISel] Check the number of sign bits in `PatGprGpr_32` (#107432)
[llvm-project.git] / llvm / test / CodeGen / AArch64 / stack-probing-dynamic.ll
blobd9ad1045506c93050ce17cca48972c03c8919537
1 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2 ; RUN: llc -mtriple=aarch64 < %s -verify-machineinstrs                                   | FileCheck %s
3 ; RUN: llc -mtriple=aarch64 < %s -verify-machineinstrs -global-isel -global-isel-abort=2 | FileCheck %s
5 ; Dynamically-sized allocation, needs a loop which can handle any size at
6 ; runtime. The final iteration of the loop will temporarily put SP below the
7 ; target address, but this doesn't break any of the ABI constraints on the
8 ; stack, and also doesn't probe below the target SP value.
9 define void @dynamic(i64 %size, ptr %out) #0 {
10 ; CHECK-LABEL: dynamic:
11 ; CHECK:       // %bb.0:
12 ; CHECK-NEXT:    stp x29, x30, [sp, #-16]! // 16-byte Folded Spill
13 ; CHECK-NEXT:    .cfi_def_cfa_offset 16
14 ; CHECK-NEXT:    mov x29, sp
15 ; CHECK-NEXT:    .cfi_def_cfa w29, 16
16 ; CHECK-NEXT:    .cfi_offset w30, -8
17 ; CHECK-NEXT:    .cfi_offset w29, -16
18 ; CHECK-NEXT:    add x9, x0, #15
19 ; CHECK-NEXT:    mov x8, sp
20 ; CHECK-NEXT:    and x9, x9, #0xfffffffffffffff0
21 ; CHECK-NEXT:    sub x8, x8, x9
22 ; CHECK-NEXT:  .LBB0_1: // =>This Inner Loop Header: Depth=1
23 ; CHECK-NEXT:    sub sp, sp, #1, lsl #12 // =4096
24 ; CHECK-NEXT:    cmp sp, x8
25 ; CHECK-NEXT:    b.le .LBB0_3
26 ; CHECK-NEXT:  // %bb.2: // in Loop: Header=BB0_1 Depth=1
27 ; CHECK-NEXT:    str xzr, [sp]
28 ; CHECK-NEXT:    b .LBB0_1
29 ; CHECK-NEXT:  .LBB0_3:
30 ; CHECK-NEXT:    mov sp, x8
31 ; CHECK-NEXT:    ldr xzr, [sp]
32 ; CHECK-NEXT:    str x8, [x1]
33 ; CHECK-NEXT:    mov sp, x29
34 ; CHECK-NEXT:    .cfi_def_cfa wsp, 16
35 ; CHECK-NEXT:    ldp x29, x30, [sp], #16 // 16-byte Folded Reload
36 ; CHECK-NEXT:    .cfi_def_cfa_offset 0
37 ; CHECK-NEXT:    .cfi_restore w30
38 ; CHECK-NEXT:    .cfi_restore w29
39 ; CHECK-NEXT:    ret
40   %v = alloca i8, i64 %size, align 1
41   store ptr %v, ptr %out, align 8
42   ret void
45 ; This function has a fixed-size stack slot and a dynamic one. The fixed size
46 ; slot isn't large enough that we would normally probe it, but we need to do so
47 ; here otherwise the gap between the CSR save and the first probe of the
48 ; dynamic allocation could be too far apart when the size of the dynamic
49 ; allocation is close to the guard size.
50 define void @dynamic_fixed(i64 %size, ptr %out1, ptr %out2) #0 {
51 ; CHECK-LABEL: dynamic_fixed:
52 ; CHECK:       // %bb.0:
53 ; CHECK-NEXT:    stp x29, x30, [sp, #-16]! // 16-byte Folded Spill
54 ; CHECK-NEXT:    .cfi_def_cfa_offset 16
55 ; CHECK-NEXT:    mov x29, sp
56 ; CHECK-NEXT:    .cfi_def_cfa w29, 16
57 ; CHECK-NEXT:    .cfi_offset w30, -8
58 ; CHECK-NEXT:    .cfi_offset w29, -16
59 ; CHECK-NEXT:    str xzr, [sp, #-64]!
60 ; CHECK-NEXT:    add x9, x0, #15
61 ; CHECK-NEXT:    mov x8, sp
62 ; CHECK-NEXT:    sub x10, x29, #64
63 ; CHECK-NEXT:    and x9, x9, #0xfffffffffffffff0
64 ; CHECK-NEXT:    str x10, [x1]
65 ; CHECK-NEXT:    sub x8, x8, x9
66 ; CHECK-NEXT:  .LBB1_1: // =>This Inner Loop Header: Depth=1
67 ; CHECK-NEXT:    sub sp, sp, #1, lsl #12 // =4096
68 ; CHECK-NEXT:    cmp sp, x8
69 ; CHECK-NEXT:    b.le .LBB1_3
70 ; CHECK-NEXT:  // %bb.2: // in Loop: Header=BB1_1 Depth=1
71 ; CHECK-NEXT:    str xzr, [sp]
72 ; CHECK-NEXT:    b .LBB1_1
73 ; CHECK-NEXT:  .LBB1_3:
74 ; CHECK-NEXT:    mov sp, x8
75 ; CHECK-NEXT:    ldr xzr, [sp]
76 ; CHECK-NEXT:    str x8, [x2]
77 ; CHECK-NEXT:    mov sp, x29
78 ; CHECK-NEXT:    .cfi_def_cfa wsp, 16
79 ; CHECK-NEXT:    ldp x29, x30, [sp], #16 // 16-byte Folded Reload
80 ; CHECK-NEXT:    .cfi_def_cfa_offset 0
81 ; CHECK-NEXT:    .cfi_restore w30
82 ; CHECK-NEXT:    .cfi_restore w29
83 ; CHECK-NEXT:    ret
84   %v1 = alloca i8, i64 64, align 1
85   store ptr %v1, ptr %out1, align 8
86   %v2 = alloca i8, i64 %size, align 1
87   store ptr %v2, ptr %out2, align 8
88   ret void
91 ; Dynamic allocation, with an alignment requirement greater than the alignment
92 ; of SP. Done by ANDing the target SP with a constant to align it down, then
93 ; doing the loop as normal. Note that we also re-align the stack in the prolog,
94 ; which isn't actually needed because the only aligned allocations are dynamic,
95 ; this is done even without stack probing.
96 define void @dynamic_align_64(i64 %size, ptr %out) #0 {
97 ; CHECK-LABEL: dynamic_align_64:
98 ; CHECK:       // %bb.0:
99 ; CHECK-NEXT:    stp x29, x30, [sp, #-32]! // 16-byte Folded Spill
100 ; CHECK-NEXT:    .cfi_def_cfa_offset 32
101 ; CHECK-NEXT:    str x19, [sp, #16] // 8-byte Folded Spill
102 ; CHECK-NEXT:    mov x29, sp
103 ; CHECK-NEXT:    .cfi_def_cfa w29, 32
104 ; CHECK-NEXT:    .cfi_offset w19, -16
105 ; CHECK-NEXT:    .cfi_offset w30, -24
106 ; CHECK-NEXT:    .cfi_offset w29, -32
107 ; CHECK-NEXT:    sub x9, sp, #32
108 ; CHECK-NEXT:    and sp, x9, #0xffffffffffffffc0
109 ; CHECK-NEXT:    add x9, x0, #15
110 ; CHECK-NEXT:    mov x8, sp
111 ; CHECK-NEXT:    str xzr, [sp]
112 ; CHECK-NEXT:    and x9, x9, #0xfffffffffffffff0
113 ; CHECK-NEXT:    mov x19, sp
114 ; CHECK-NEXT:    sub x8, x8, x9
115 ; CHECK-NEXT:    and x8, x8, #0xffffffffffffffc0
116 ; CHECK-NEXT:  .LBB2_1: // =>This Inner Loop Header: Depth=1
117 ; CHECK-NEXT:    sub sp, sp, #1, lsl #12 // =4096
118 ; CHECK-NEXT:    cmp sp, x8
119 ; CHECK-NEXT:    b.le .LBB2_3
120 ; CHECK-NEXT:  // %bb.2: // in Loop: Header=BB2_1 Depth=1
121 ; CHECK-NEXT:    str xzr, [sp]
122 ; CHECK-NEXT:    b .LBB2_1
123 ; CHECK-NEXT:  .LBB2_3:
124 ; CHECK-NEXT:    mov sp, x8
125 ; CHECK-NEXT:    ldr xzr, [sp]
126 ; CHECK-NEXT:    str x8, [x1]
127 ; CHECK-NEXT:    mov sp, x29
128 ; CHECK-NEXT:    .cfi_def_cfa wsp, 32
129 ; CHECK-NEXT:    ldr x19, [sp, #16] // 8-byte Folded Reload
130 ; CHECK-NEXT:    ldp x29, x30, [sp], #32 // 16-byte Folded Reload
131 ; CHECK-NEXT:    .cfi_def_cfa_offset 0
132 ; CHECK-NEXT:    .cfi_restore w19
133 ; CHECK-NEXT:    .cfi_restore w30
134 ; CHECK-NEXT:    .cfi_restore w29
135 ; CHECK-NEXT:    ret
136   %v = alloca i8, i64 %size, align 64
137   store ptr %v, ptr %out, align 8
138   ret void
141 ; Dynamic allocation, with an alignment greater than the stack guard size. The
142 ; only difference to the dynamic allocation is the constant used for aligning
143 ; the target SP, the loop will probe the whole allocation without needing to
144 ; know about the alignment padding.
145 define void @dynamic_align_8192(i64 %size, ptr %out) #0 {
146 ; CHECK-LABEL: dynamic_align_8192:
147 ; CHECK:       // %bb.0:
148 ; CHECK-NEXT:    stp x29, x30, [sp, #-32]! // 16-byte Folded Spill
149 ; CHECK-NEXT:    .cfi_def_cfa_offset 32
150 ; CHECK-NEXT:    str x19, [sp, #16] // 8-byte Folded Spill
151 ; CHECK-NEXT:    mov x29, sp
152 ; CHECK-NEXT:    .cfi_def_cfa w29, 32
153 ; CHECK-NEXT:    .cfi_offset w19, -16
154 ; CHECK-NEXT:    .cfi_offset w30, -24
155 ; CHECK-NEXT:    .cfi_offset w29, -32
156 ; CHECK-NEXT:    sub x9, sp, #1, lsl #12 // =4096
157 ; CHECK-NEXT:    sub x9, x9, #4064
158 ; CHECK-NEXT:    and x9, x9, #0xffffffffffffe000
159 ; CHECK-NEXT:  .LBB3_1: // =>This Inner Loop Header: Depth=1
160 ; CHECK-NEXT:    sub sp, sp, #1, lsl #12 // =4096
161 ; CHECK-NEXT:    cmp sp, x9
162 ; CHECK-NEXT:    b.le .LBB3_3
163 ; CHECK-NEXT:  // %bb.2: // in Loop: Header=BB3_1 Depth=1
164 ; CHECK-NEXT:    str xzr, [sp]
165 ; CHECK-NEXT:    b .LBB3_1
166 ; CHECK-NEXT:  .LBB3_3:
167 ; CHECK-NEXT:    mov sp, x9
168 ; CHECK-NEXT:    add x9, x0, #15
169 ; CHECK-NEXT:    mov x8, sp
170 ; CHECK-NEXT:    ldr xzr, [sp]
171 ; CHECK-NEXT:    and x9, x9, #0xfffffffffffffff0
172 ; CHECK-NEXT:    mov x19, sp
173 ; CHECK-NEXT:    sub x8, x8, x9
174 ; CHECK-NEXT:    and x8, x8, #0xffffffffffffe000
175 ; CHECK-NEXT:  .LBB3_4: // =>This Inner Loop Header: Depth=1
176 ; CHECK-NEXT:    sub sp, sp, #1, lsl #12 // =4096
177 ; CHECK-NEXT:    cmp sp, x8
178 ; CHECK-NEXT:    b.le .LBB3_6
179 ; CHECK-NEXT:  // %bb.5: // in Loop: Header=BB3_4 Depth=1
180 ; CHECK-NEXT:    str xzr, [sp]
181 ; CHECK-NEXT:    b .LBB3_4
182 ; CHECK-NEXT:  .LBB3_6:
183 ; CHECK-NEXT:    mov sp, x8
184 ; CHECK-NEXT:    ldr xzr, [sp]
185 ; CHECK-NEXT:    str x8, [x1]
186 ; CHECK-NEXT:    mov sp, x29
187 ; CHECK-NEXT:    .cfi_def_cfa wsp, 32
188 ; CHECK-NEXT:    ldr x19, [sp, #16] // 8-byte Folded Reload
189 ; CHECK-NEXT:    ldp x29, x30, [sp], #32 // 16-byte Folded Reload
190 ; CHECK-NEXT:    .cfi_def_cfa_offset 0
191 ; CHECK-NEXT:    .cfi_restore w19
192 ; CHECK-NEXT:    .cfi_restore w30
193 ; CHECK-NEXT:    .cfi_restore w29
194 ; CHECK-NEXT:    ret
195   %v = alloca i8, i64 %size, align 8192
196   store ptr %v, ptr %out, align 8
197   ret void
200 ; For 64k guard pages, the only difference is the constant subtracted from SP
201 ; in the loop.
202 define void @dynamic_64k_guard(i64 %size, ptr %out) #0 "stack-probe-size"="65536" {
203 ; CHECK-LABEL: dynamic_64k_guard:
204 ; CHECK:       // %bb.0:
205 ; CHECK-NEXT:    stp x29, x30, [sp, #-16]! // 16-byte Folded Spill
206 ; CHECK-NEXT:    .cfi_def_cfa_offset 16
207 ; CHECK-NEXT:    mov x29, sp
208 ; CHECK-NEXT:    .cfi_def_cfa w29, 16
209 ; CHECK-NEXT:    .cfi_offset w30, -8
210 ; CHECK-NEXT:    .cfi_offset w29, -16
211 ; CHECK-NEXT:    add x9, x0, #15
212 ; CHECK-NEXT:    mov x8, sp
213 ; CHECK-NEXT:    and x9, x9, #0xfffffffffffffff0
214 ; CHECK-NEXT:    sub x8, x8, x9
215 ; CHECK-NEXT:  .LBB4_1: // =>This Inner Loop Header: Depth=1
216 ; CHECK-NEXT:    sub sp, sp, #16, lsl #12 // =65536
217 ; CHECK-NEXT:    cmp sp, x8
218 ; CHECK-NEXT:    b.le .LBB4_3
219 ; CHECK-NEXT:  // %bb.2: // in Loop: Header=BB4_1 Depth=1
220 ; CHECK-NEXT:    str xzr, [sp]
221 ; CHECK-NEXT:    b .LBB4_1
222 ; CHECK-NEXT:  .LBB4_3:
223 ; CHECK-NEXT:    mov sp, x8
224 ; CHECK-NEXT:    ldr xzr, [sp]
225 ; CHECK-NEXT:    str x8, [x1]
226 ; CHECK-NEXT:    mov sp, x29
227 ; CHECK-NEXT:    .cfi_def_cfa wsp, 16
228 ; CHECK-NEXT:    ldp x29, x30, [sp], #16 // 16-byte Folded Reload
229 ; CHECK-NEXT:    .cfi_def_cfa_offset 0
230 ; CHECK-NEXT:    .cfi_restore w30
231 ; CHECK-NEXT:    .cfi_restore w29
232 ; CHECK-NEXT:    ret
233   %v = alloca i8, i64 %size, align 1
234   store ptr %v, ptr %out, align 8
235   ret void
238 ; If a function has variable-sized stack objects, then any function calls which
239 ; need to pass arguments on the stack must allocate the stack space for them
240 ; dynamically, to ensure they are at the bottom of the frame. We need to probe
241 ; that space when it is larger than the unprobed space allowed by the ABI (1024
242 ; bytes), so this needs a very large number of arguments.
243 define void @no_reserved_call_frame(i64 %n) #0 {
244 ; CHECK-LABEL: no_reserved_call_frame:
245 ; CHECK:       // %bb.0: // %entry
246 ; CHECK-NEXT:    stp x29, x30, [sp, #-16]! // 16-byte Folded Spill
247 ; CHECK-NEXT:    .cfi_def_cfa_offset 16
248 ; CHECK-NEXT:    mov x29, sp
249 ; CHECK-NEXT:    .cfi_def_cfa w29, 16
250 ; CHECK-NEXT:    .cfi_offset w30, -8
251 ; CHECK-NEXT:    .cfi_offset w29, -16
252 ; CHECK-NEXT:    lsl x9, x0, #2
253 ; CHECK-NEXT:    mov x8, sp
254 ; CHECK-NEXT:    add x9, x9, #15
255 ; CHECK-NEXT:    and x9, x9, #0xfffffffffffffff0
256 ; CHECK-NEXT:    sub x0, x8, x9
257 ; CHECK-NEXT:  .LBB5_1: // %entry
258 ; CHECK-NEXT:    // =>This Inner Loop Header: Depth=1
259 ; CHECK-NEXT:    sub sp, sp, #1, lsl #12 // =4096
260 ; CHECK-NEXT:    cmp sp, x0
261 ; CHECK-NEXT:    b.le .LBB5_3
262 ; CHECK-NEXT:  // %bb.2: // %entry
263 ; CHECK-NEXT:    // in Loop: Header=BB5_1 Depth=1
264 ; CHECK-NEXT:    str xzr, [sp]
265 ; CHECK-NEXT:    b .LBB5_1
266 ; CHECK-NEXT:  .LBB5_3: // %entry
267 ; CHECK-NEXT:    mov sp, x0
268 ; CHECK-NEXT:    ldr xzr, [sp]
269 ; CHECK-NEXT:    sub sp, sp, #1104
270 ; CHECK-NEXT:    str xzr, [sp]
271 ; CHECK-NEXT:    bl callee_stack_args
272 ; CHECK-NEXT:    add sp, sp, #1104
273 ; CHECK-NEXT:    mov sp, x29
274 ; CHECK-NEXT:    .cfi_def_cfa wsp, 16
275 ; CHECK-NEXT:    ldp x29, x30, [sp], #16 // 16-byte Folded Reload
276 ; CHECK-NEXT:    .cfi_def_cfa_offset 0
277 ; CHECK-NEXT:    .cfi_restore w30
278 ; CHECK-NEXT:    .cfi_restore w29
279 ; CHECK-NEXT:    ret
280 entry:
281   %v = alloca i32, i64 %n
282   call void @callee_stack_args(ptr %v, [138 x i64] undef)
283   ret void
286 ; Same as above but without a variable-sized allocation, so the reserved call
287 ; frame can be folded into the fixed-size allocation in the prologue.
288 define void @reserved_call_frame(i64 %n) #0 {
289 ; CHECK-LABEL: reserved_call_frame:
290 ; CHECK:       // %bb.0: // %entry
291 ; CHECK-NEXT:    stp x29, x30, [sp, #-32]! // 16-byte Folded Spill
292 ; CHECK-NEXT:    .cfi_def_cfa_offset 32
293 ; CHECK-NEXT:    str x28, [sp, #16] // 8-byte Folded Spill
294 ; CHECK-NEXT:    mov x29, sp
295 ; CHECK-NEXT:    .cfi_def_cfa w29, 32
296 ; CHECK-NEXT:    .cfi_offset w28, -16
297 ; CHECK-NEXT:    .cfi_offset w30, -24
298 ; CHECK-NEXT:    .cfi_offset w29, -32
299 ; CHECK-NEXT:    sub sp, sp, #1504
300 ; CHECK-NEXT:    add x0, sp, #1104
301 ; CHECK-NEXT:    str xzr, [sp]
302 ; CHECK-NEXT:    bl callee_stack_args
303 ; CHECK-NEXT:    add sp, sp, #1504
304 ; CHECK-NEXT:    .cfi_def_cfa wsp, 32
305 ; CHECK-NEXT:    ldr x28, [sp, #16] // 8-byte Folded Reload
306 ; CHECK-NEXT:    ldp x29, x30, [sp], #32 // 16-byte Folded Reload
307 ; CHECK-NEXT:    .cfi_def_cfa_offset 0
308 ; CHECK-NEXT:    .cfi_restore w28
309 ; CHECK-NEXT:    .cfi_restore w30
310 ; CHECK-NEXT:    .cfi_restore w29
311 ; CHECK-NEXT:    ret
312 entry:
313   %v = alloca i32, i64 100
314   call void @callee_stack_args(ptr %v, [138 x i64] undef)
315   ret void
318 declare void @callee_stack_args(ptr, [138 x i64])
320 ; Dynamic allocation of SVE vectors
321 define void @dynamic_sve(i64 %size, ptr %out) #0 "target-features"="+sve" {
322 ; CHECK-LABEL: dynamic_sve:
323 ; CHECK:       // %bb.0:
324 ; CHECK-NEXT:    stp x29, x30, [sp, #-32]! // 16-byte Folded Spill
325 ; CHECK-NEXT:    .cfi_def_cfa_offset 32
326 ; CHECK-NEXT:    str x19, [sp, #16] // 8-byte Folded Spill
327 ; CHECK-NEXT:    mov x29, sp
328 ; CHECK-NEXT:    .cfi_def_cfa w29, 32
329 ; CHECK-NEXT:    .cfi_offset w19, -16
330 ; CHECK-NEXT:    .cfi_offset w30, -24
331 ; CHECK-NEXT:    .cfi_offset w29, -32
332 ; CHECK-NEXT:    rdvl x9, #1
333 ; CHECK-NEXT:    mov x10, #15 // =0xf
334 ; CHECK-NEXT:    mov x8, sp
335 ; CHECK-NEXT:    madd x9, x0, x9, x10
336 ; CHECK-NEXT:    and x9, x9, #0xfffffffffffffff0
337 ; CHECK-NEXT:    sub x8, x8, x9
338 ; CHECK-NEXT:  .LBB7_1: // =>This Inner Loop Header: Depth=1
339 ; CHECK-NEXT:    sub sp, sp, #1, lsl #12 // =4096
340 ; CHECK-NEXT:    cmp sp, x8
341 ; CHECK-NEXT:    b.le .LBB7_3
342 ; CHECK-NEXT:  // %bb.2: // in Loop: Header=BB7_1 Depth=1
343 ; CHECK-NEXT:    str xzr, [sp]
344 ; CHECK-NEXT:    b .LBB7_1
345 ; CHECK-NEXT:  .LBB7_3:
346 ; CHECK-NEXT:    mov sp, x8
347 ; CHECK-NEXT:    ldr xzr, [sp]
348 ; CHECK-NEXT:    str x8, [x1]
349 ; CHECK-NEXT:    mov sp, x29
350 ; CHECK-NEXT:    .cfi_def_cfa wsp, 32
351 ; CHECK-NEXT:    ldr x19, [sp, #16] // 8-byte Folded Reload
352 ; CHECK-NEXT:    ldp x29, x30, [sp], #32 // 16-byte Folded Reload
353 ; CHECK-NEXT:    .cfi_def_cfa_offset 0
354 ; CHECK-NEXT:    .cfi_restore w19
355 ; CHECK-NEXT:    .cfi_restore w30
356 ; CHECK-NEXT:    .cfi_restore w29
357 ; CHECK-NEXT:    ret
358   %v = alloca <vscale x 4 x float>, i64 %size, align 16
359   store ptr %v, ptr %out, align 8
360   ret void
363 attributes #0 = { uwtable(async) "probe-stack"="inline-asm" "frame-pointer"="none" }