xref: /llvm-project/llvm/test/CodeGen/AArch64/arm64ec-entry-thunks.ll (revision 2c9c22c6e295b1176225b63ae4cbbceb216da55e)
1; RUN: llc -mtriple=arm64ec-pc-windows-msvc < %s | FileCheck %s
2
3define void @no_op() nounwind {
4; CHECK-LABEL     .def    $ientry_thunk$cdecl$v$v;
5; CHECK:          .section        .wowthk$aa,"xr",discard,$ientry_thunk$cdecl$v$v
6; CHECK:          // %bb.0:
7; CHECK-NEXT:     stp     q6, q7, [sp, #-176]!            // 32-byte Folded Spill
8; CHECK-NEXT:     .seh_save_any_reg_px    q6, 176
9; CHECK-NEXT:     stp     q8, q9, [sp, #32]               // 32-byte Folded Spill
10; CHECK-NEXT:     .seh_save_any_reg_p     q8, 32
11; CHECK-NEXT:     stp     q10, q11, [sp, #64]             // 32-byte Folded Spill
12; CHECK-NEXT:     .seh_save_any_reg_p     q10, 64
13; CHECK-NEXT:     stp     q12, q13, [sp, #96]             // 32-byte Folded Spill
14; CHECK-NEXT:     .seh_save_any_reg_p     q12, 96
15; CHECK-NEXT:     stp     q14, q15, [sp, #128]            // 32-byte Folded Spill
16; CHECK-NEXT:     .seh_save_any_reg_p     q14, 128
17; CHECK-NEXT:     stp     x29, x30, [sp, #160]            // 16-byte Folded Spill
18; CHECK-NEXT:     .seh_save_fplr  160
19; CHECK-NEXT:     add     x29, sp, #160
20; CHECK-NEXT:     .seh_add_fp     160
21; CHECK-NEXT:     .seh_endprologue
22; CHECK-NEXT:     blr     x9
23; CHECK-NEXT:     adrp    x8, __os_arm64x_dispatch_ret
24; CHECK-NEXT:     ldr     x0, [x8, :lo12:__os_arm64x_dispatch_ret]
25; CHECK-NEXT:     .seh_startepilogue
26; CHECK-NEXT:     ldp     x29, x30, [sp, #160]            // 16-byte Folded Reload
27; CHECK-NEXT:     .seh_save_fplr  160
28; CHECK-NEXT:     ldp     q14, q15, [sp, #128]            // 32-byte Folded Reload
29; CHECK-NEXT:     .seh_save_any_reg_p     q14, 128
30; CHECK-NEXT:     ldp     q12, q13, [sp, #96]             // 32-byte Folded Reload
31; CHECK-NEXT:     .seh_save_any_reg_p     q12, 96
32; CHECK-NEXT:     ldp     q10, q11, [sp, #64]             // 32-byte Folded Reload
33; CHECK-NEXT:     .seh_save_any_reg_p     q10, 64
34; CHECK-NEXT:     ldp     q8, q9, [sp, #32]               // 32-byte Folded Reload
35; CHECK-NEXT:     .seh_save_any_reg_p     q8, 32
36; CHECK-NEXT:     ldp     q6, q7, [sp], #176              // 32-byte Folded Reload
37; CHECK-NEXT:     .seh_save_any_reg_px    q6, 176
38; CHECK-NEXT:     .seh_endepilogue
39; CHECK-NEXT:     br      x0
40; CHECK-NEXT:     .seh_endfunclet
41; CHECK-NEXT:     .seh_endproc
42  ret void
43}
44
45define i64 @simple_integers(i8, i16, i32, i64) nounwind {
46; CHECK-LABEL:    .def    $ientry_thunk$cdecl$i8$i8i8i8i8;
47; CHECK:          .section        .wowthk$aa,"xr",discard,$ientry_thunk$cdecl$i8$i8i8i8i8
48; CHECK:          // %bb.0:
49; CHECK-NEXT:     stp     q6, q7, [sp, #-176]!            // 32-byte Folded Spill
50; CHECK-NEXT:     .seh_save_any_reg_px    q6, 176
51; CHECK-NEXT:     stp     q8, q9, [sp, #32]               // 32-byte Folded Spill
52; CHECK-NEXT:     .seh_save_any_reg_p     q8, 32
53; CHECK-NEXT:     stp     q10, q11, [sp, #64]             // 32-byte Folded Spill
54; CHECK-NEXT:     .seh_save_any_reg_p     q10, 64
55; CHECK-NEXT:     stp     q12, q13, [sp, #96]             // 32-byte Folded Spill
56; CHECK-NEXT:     .seh_save_any_reg_p     q12, 96
57; CHECK-NEXT:     stp     q14, q15, [sp, #128]            // 32-byte Folded Spill
58; CHECK-NEXT:     .seh_save_any_reg_p     q14, 128
59; CHECK-NEXT:     stp     x29, x30, [sp, #160]            // 16-byte Folded Spill
60; CHECK-NEXT:     .seh_save_fplr  160
61; CHECK-NEXT:     add     x29, sp, #160
62; CHECK-NEXT:     .seh_add_fp     160
63; CHECK-NEXT:     .seh_endprologue
64; CHECK-NEXT:     blr     x9
65; CHECK-NEXT:     adrp    x8, __os_arm64x_dispatch_ret
66; CHECK-NEXT:     ldr     x1, [x8, :lo12:__os_arm64x_dispatch_ret]
67; CHECK-NEXT:     mov     x8, x0
68; CHECK-NEXT:     .seh_startepilogue
69; CHECK-NEXT:     ldp     x29, x30, [sp, #160]            // 16-byte Folded Reload
70; CHECK-NEXT:     .seh_save_fplr  160
71; CHECK-NEXT:     ldp     q14, q15, [sp, #128]            // 32-byte Folded Reload
72; CHECK-NEXT:     .seh_save_any_reg_p     q14, 128
73; CHECK-NEXT:     ldp     q12, q13, [sp, #96]             // 32-byte Folded Reload
74; CHECK-NEXT:     .seh_save_any_reg_p     q12, 96
75; CHECK-NEXT:     ldp     q10, q11, [sp, #64]             // 32-byte Folded Reload
76; CHECK-NEXT:     .seh_save_any_reg_p     q10, 64
77; CHECK-NEXT:     ldp     q8, q9, [sp, #32]               // 32-byte Folded Reload
78; CHECK-NEXT:     .seh_save_any_reg_p     q8, 32
79; CHECK-NEXT:     ldp     q6, q7, [sp], #176              // 32-byte Folded Reload
80; CHECK-NEXT:     .seh_save_any_reg_px    q6, 176
81; CHECK-NEXT:     .seh_endepilogue
82; CHECK-NEXT:     br      x1
83; CHECK-NEXT:     .seh_endfunclet
84; CHECK-NEXT:     .seh_endproc
85  ret i64 0
86}
87
88; NOTE: Only float and double are supported.
89define double @simple_floats(float, double) nounwind {
90; CHECK-LABEL:    .def    $ientry_thunk$cdecl$d$fd;
91; CHECK:          .section        .wowthk$aa,"xr",discard,$ientry_thunk$cdecl$d$fd
92; CHECK:          // %bb.0:
93; CHECK-NEXT:     stp     q6, q7, [sp, #-176]!            // 32-byte Folded Spill
94; CHECK-NEXT:     .seh_save_any_reg_px    q6, 176
95; CHECK-NEXT:     stp     q8, q9, [sp, #32]               // 32-byte Folded Spill
96; CHECK-NEXT:     .seh_save_any_reg_p     q8, 32
97; CHECK-NEXT:     stp     q10, q11, [sp, #64]             // 32-byte Folded Spill
98; CHECK-NEXT:     .seh_save_any_reg_p     q10, 64
99; CHECK-NEXT:     stp     q12, q13, [sp, #96]             // 32-byte Folded Spill
100; CHECK-NEXT:     .seh_save_any_reg_p     q12, 96
101; CHECK-NEXT:     stp     q14, q15, [sp, #128]            // 32-byte Folded Spill
102; CHECK-NEXT:     .seh_save_any_reg_p     q14, 128
103; CHECK-NEXT:     stp     x29, x30, [sp, #160]            // 16-byte Folded Spill
104; CHECK-NEXT:     .seh_save_fplr  160
105; CHECK-NEXT:     add     x29, sp, #160
106; CHECK-NEXT:     .seh_add_fp     160
107; CHECK-NEXT:     .seh_endprologue
108; CHECK-NEXT:     blr     x9
109; CHECK-NEXT:     adrp    x8, __os_arm64x_dispatch_ret
110; CHECK-NEXT:     ldr     x0, [x8, :lo12:__os_arm64x_dispatch_ret]
111; CHECK-NEXT:     .seh_startepilogue
112; CHECK-NEXT:     ldp     x29, x30, [sp, #160]            // 16-byte Folded Reload
113; CHECK-NEXT:     .seh_save_fplr  160
114; CHECK-NEXT:     ldp     q14, q15, [sp, #128]            // 32-byte Folded Reload
115; CHECK-NEXT:     .seh_save_any_reg_p     q14, 128
116; CHECK-NEXT:     ldp     q12, q13, [sp, #96]             // 32-byte Folded Reload
117; CHECK-NEXT:     .seh_save_any_reg_p     q12, 96
118; CHECK-NEXT:     ldp     q10, q11, [sp, #64]             // 32-byte Folded Reload
119; CHECK-NEXT:     .seh_save_any_reg_p     q10, 64
120; CHECK-NEXT:     ldp     q8, q9, [sp, #32]               // 32-byte Folded Reload
121; CHECK-NEXT:     .seh_save_any_reg_p     q8, 32
122; CHECK-NEXT:     ldp     q6, q7, [sp], #176              // 32-byte Folded Reload
123; CHECK-NEXT:     .seh_save_any_reg_px    q6, 176
124; CHECK-NEXT:     .seh_endepilogue
125; CHECK-NEXT:     br      x0
126; CHECK-NEXT:     .seh_endfunclet
127; CHECK-NEXT:     .seh_endproc
128  ret double 0.0
129}
130
131define void @has_varargs(...) nounwind {
132; CHECK-LABEL:    .def    $ientry_thunk$cdecl$v$varargs;
133; CHECK:          .section        .wowthk$aa,"xr",discard,$ientry_thunk$cdecl$v$varargs
134; CHECK:          // %bb.0:
135; CHECK-NEXT:     stp     q6, q7, [sp, #-176]!            // 32-byte Folded Spill
136; CHECK-NEXT:     .seh_save_any_reg_px    q6, 176
137; CHECK-NEXT:     stp     q8, q9, [sp, #32]               // 32-byte Folded Spill
138; CHECK-NEXT:     .seh_save_any_reg_p     q8, 32
139; CHECK-NEXT:     stp     q10, q11, [sp, #64]             // 32-byte Folded Spill
140; CHECK-NEXT:     .seh_save_any_reg_p     q10, 64
141; CHECK-NEXT:     stp     q12, q13, [sp, #96]             // 32-byte Folded Spill
142; CHECK-NEXT:     .seh_save_any_reg_p     q12, 96
143; CHECK-NEXT:     stp     q14, q15, [sp, #128]            // 32-byte Folded Spill
144; CHECK-NEXT:     .seh_save_any_reg_p     q14, 128
145; CHECK-NEXT:     stp     x29, x30, [sp, #160]            // 16-byte Folded Spill
146; CHECK-NEXT:     .seh_save_fplr  160
147; CHECK-NEXT:     add     x29, sp, #160
148; CHECK-NEXT:     .seh_add_fp     160
149; CHECK-NEXT:     .seh_endprologue
150; CHECK-NEXT:     add     x4, x4, #32
151; CHECK-NEXT:     mov     x5, xzr
152; CHECK-NEXT:     blr     x9
153; CHECK-NEXT:     adrp    x8, __os_arm64x_dispatch_ret
154; CHECK-NEXT:     ldr     x0, [x8, :lo12:__os_arm64x_dispatch_ret]
155; CHECK-NEXT:     .seh_startepilogue
156; CHECK-NEXT:     ldp     x29, x30, [sp, #160]            // 16-byte Folded Reload
157; CHECK-NEXT:     .seh_save_fplr  160
158; CHECK-NEXT:     ldp     q14, q15, [sp, #128]            // 32-byte Folded Reload
159; CHECK-NEXT:     .seh_save_any_reg_p     q14, 128
160; CHECK-NEXT:     ldp     q12, q13, [sp, #96]             // 32-byte Folded Reload
161; CHECK-NEXT:     .seh_save_any_reg_p     q12, 96
162; CHECK-NEXT:     ldp     q10, q11, [sp, #64]             // 32-byte Folded Reload
163; CHECK-NEXT:     .seh_save_any_reg_p     q10, 64
164; CHECK-NEXT:     ldp     q8, q9, [sp, #32]               // 32-byte Folded Reload
165; CHECK-NEXT:     .seh_save_any_reg_p     q8, 32
166; CHECK-NEXT:     ldp     q6, q7, [sp], #176              // 32-byte Folded Reload
167; CHECK-NEXT:     .seh_save_any_reg_px    q6, 176
168; CHECK-NEXT:     .seh_endepilogue
169; CHECK-NEXT:     br      x0
170; CHECK-NEXT:     .seh_endfunclet
171; CHECK-NEXT:     .seh_endproc
172  ret void
173}
174
175define void @has_sret(ptr sret([100 x i8])) nounwind {
176; CHECK-LABEL:    .def    $ientry_thunk$cdecl$i8$v;
177; CHECK:          .section        .wowthk$aa,"xr",discard,$ientry_thunk$cdecl$i8$v
178; CHECK:          // %bb.0:
179; CHECK-NEXT:     stp     q6, q7, [sp, #-176]!            // 32-byte Folded Spill
180; CHECK-NEXT:     .seh_save_any_reg_px    q6, 176
181; CHECK-NEXT:     stp     q8, q9, [sp, #32]               // 32-byte Folded Spill
182; CHECK-NEXT:     .seh_save_any_reg_p     q8, 32
183; CHECK-NEXT:     stp     q10, q11, [sp, #64]             // 32-byte Folded Spill
184; CHECK-NEXT:     .seh_save_any_reg_p     q10, 64
185; CHECK-NEXT:     stp     q12, q13, [sp, #96]             // 32-byte Folded Spill
186; CHECK-NEXT:     .seh_save_any_reg_p     q12, 96
187; CHECK-NEXT:     stp     q14, q15, [sp, #128]            // 32-byte Folded Spill
188; CHECK-NEXT:     .seh_save_any_reg_p     q14, 128
189; CHECK-NEXT:     stp     x29, x30, [sp, #160]            // 16-byte Folded Spill
190; CHECK-NEXT:     .seh_save_fplr  160
191; CHECK-NEXT:     add     x29, sp, #160
192; CHECK-NEXT:     .seh_add_fp     160
193; CHECK-NEXT:     .seh_endprologue
194; CHECK-NEXT:     blr     x9
195; CHECK-NEXT:     adrp    x8, __os_arm64x_dispatch_ret
196; CHECK-NEXT:     ldr     x1, [x8, :lo12:__os_arm64x_dispatch_ret]
197; CHECK-NEXT:     mov     x8, x0
198; CHECK-NEXT:     .seh_startepilogue
199; CHECK-NEXT:     ldp     x29, x30, [sp, #160]            // 16-byte Folded Reload
200; CHECK-NEXT:     .seh_save_fplr  160
201; CHECK-NEXT:     ldp     q14, q15, [sp, #128]            // 32-byte Folded Reload
202; CHECK-NEXT:     .seh_save_any_reg_p     q14, 128
203; CHECK-NEXT:     ldp     q12, q13, [sp, #96]             // 32-byte Folded Reload
204; CHECK-NEXT:     .seh_save_any_reg_p     q12, 96
205; CHECK-NEXT:     ldp     q10, q11, [sp, #64]             // 32-byte Folded Reload
206; CHECK-NEXT:     .seh_save_any_reg_p     q10, 64
207; CHECK-NEXT:     ldp     q8, q9, [sp, #32]               // 32-byte Folded Reload
208; CHECK-NEXT:     .seh_save_any_reg_p     q8, 32
209; CHECK-NEXT:     ldp     q6, q7, [sp], #176              // 32-byte Folded Reload
210; CHECK-NEXT:     .seh_save_any_reg_px    q6, 176
211; CHECK-NEXT:     .seh_endepilogue
212; CHECK-NEXT:     br      x1
213; CHECK-NEXT:     .seh_endfunclet
214; CHECK-NEXT:     .seh_endproc
215  ret void
216}
217
218define i8 @matches_has_sret() nounwind {
219; Verify that $ientry_thunk$cdecl$i8$v is re-used by a function with matching signature.
220; CHECK-NOT: .def    $ientry_thunk$cdecl$i8$v;
221  ret i8 0
222}
223
224%TSRet = type { i64, i64 }
225define void @has_aligned_sret(ptr align 32 sret(%TSRet), i32) nounwind {
226; CHECK-LABEL:    .def    $ientry_thunk$cdecl$m16$i8;
227; CHECK:          .section        .wowthk$aa,"xr",discard,$ientry_thunk$cdecl$m16$i8
228; CHECK:          // %bb.0:
229; CHECK-NEXT:     stp     q6, q7, [sp, #-192]!            // 32-byte Folded Spill
230; CHECK-NEXT:     .seh_save_any_reg_px    q6, 192
231; CHECK-NEXT:     stp     q8, q9, [sp, #32]               // 32-byte Folded Spill
232; CHECK-NEXT:     .seh_save_any_reg_p     q8, 32
233; CHECK-NEXT:     stp     q10, q11, [sp, #64]             // 32-byte Folded Spill
234; CHECK-NEXT:     .seh_save_any_reg_p     q10, 64
235; CHECK-NEXT:     stp     q12, q13, [sp, #96]             // 32-byte Folded Spill
236; CHECK-NEXT:     .seh_save_any_reg_p     q12, 96
237; CHECK-NEXT:     stp     q14, q15, [sp, #128]            // 32-byte Folded Spill
238; CHECK-NEXT:     .seh_save_any_reg_p     q14, 128
239; CHECK-NEXT:     str     x19, [sp, #160]                 // 8-byte Folded Spill
240; CHECK-NEXT:     .seh_save_reg   x19, 160
241; CHECK-NEXT:     stp     x29, x30, [sp, #168]            // 16-byte Folded Spill
242; CHECK-NEXT:     .seh_save_fplr  168
243; CHECK-NEXT:     add     x29, sp, #168
244; CHECK-NEXT:     .seh_add_fp     168
245; CHECK-NEXT:     .seh_endprologue
246; CHECK-NEXT:     mov     x19, x0
247; CHECK-NEXT:     mov     x8, x0
248; CHECK-NEXT:     mov     x0, x1
249; CHECK-NEXT:     blr     x9
250; CHECK-NEXT:     adrp    x8, __os_arm64x_dispatch_ret
251; CHECK-NEXT:     ldr     x0, [x8, :lo12:__os_arm64x_dispatch_ret]
252; CHECK-NEXT:     mov     x8, x19
253; CHECK-NEXT:     .seh_startepilogue
254; CHECK-NEXT:     ldp     x29, x30, [sp, #168]            // 16-byte Folded Reload
255; CHECK-NEXT:     .seh_save_fplr  168
256; CHECK-NEXT:     ldr     x19, [sp, #160]                 // 8-byte Folded Reload
257; CHECK-NEXT:     .seh_save_reg   x19, 160
258; CHECK-NEXT:     ldp     q14, q15, [sp, #128]            // 32-byte Folded Reload
259; CHECK-NEXT:     .seh_save_any_reg_p     q14, 128
260; CHECK-NEXT:     ldp     q12, q13, [sp, #96]             // 32-byte Folded Reload
261; CHECK-NEXT:     .seh_save_any_reg_p     q12, 96
262; CHECK-NEXT:     ldp     q10, q11, [sp, #64]             // 32-byte Folded Reload
263; CHECK-NEXT:     .seh_save_any_reg_p     q10, 64
264; CHECK-NEXT:     ldp     q8, q9, [sp, #32]               // 32-byte Folded Reload
265; CHECK-NEXT:     .seh_save_any_reg_p     q8, 32
266; CHECK-NEXT:     ldp     q6, q7, [sp], #192              // 32-byte Folded Reload
267; CHECK-NEXT:     .seh_save_any_reg_px    q6, 192
268; CHECK-NEXT:     .seh_endepilogue
269; CHECK-NEXT:     br      x0
270; CHECK-NEXT:     .seh_endfunclet
271; CHECK-NEXT:     .seh_endproc
272  ret void
273}
274
275define [2 x i8] @small_array([2 x i8] %0, [2 x float]) nounwind {
276; CHECK-LABEL:    .def    $ientry_thunk$cdecl$m2$m2F8;
277; CHECK:          .section        .wowthk$aa,"xr",discard,$ientry_thunk$cdecl$m2$m2F8
278; CHECK:          // %bb.0:
279; CHECK-NEXT:     sub     sp, sp, #192
280; CHECK-NEXT:     .seh_stackalloc 192
281; CHECK-NEXT:     stp     q6, q7, [sp, #16]               // 32-byte Folded Spill
282; CHECK-NEXT:     .seh_save_any_reg_p     q6, 16
283; CHECK-NEXT:     stp     q8, q9, [sp, #48]               // 32-byte Folded Spill
284; CHECK-NEXT:     .seh_save_any_reg_p     q8, 48
285; CHECK-NEXT:     stp     q10, q11, [sp, #80]             // 32-byte Folded Spill
286; CHECK-NEXT:     .seh_save_any_reg_p     q10, 80
287; CHECK-NEXT:     stp     q12, q13, [sp, #112]            // 32-byte Folded Spill
288; CHECK-NEXT:     .seh_save_any_reg_p     q12, 112
289; CHECK-NEXT:     stp     q14, q15, [sp, #144]            // 32-byte Folded Spill
290; CHECK-NEXT:     .seh_save_any_reg_p     q14, 144
291; CHECK-NEXT:     stp     x29, x30, [sp, #176]            // 16-byte Folded Spill
292; CHECK-NEXT:     .seh_save_fplr  176
293; CHECK-NEXT:     add     x29, sp, #176
294; CHECK-NEXT:     .seh_add_fp     176
295; CHECK-NEXT:     .seh_endprologue
296; CHECK-NEXT:     stur    x1, [sp, #4]
297; CHECK-NEXT:     ubfx    w1, w0, #8, #8
298; CHECK-NEXT:     ldp     s0, s1, [sp, #4]
299; CHECK-NEXT:     strh    w0, [sp, #14]
300; CHECK-NEXT:     blr     x9
301; CHECK-NEXT:     adrp    x9, __os_arm64x_dispatch_ret
302; CHECK-NEXT:     strb    w0, [sp, #2]
303; CHECK-NEXT:     strb    w1, [sp, #3]
304; CHECK-NEXT:     ldrh    w8, [sp, #2]
305; CHECK-NEXT:     ldr     x0, [x9, :lo12:__os_arm64x_dispatch_ret]
306; CHECK-NEXT:     .seh_startepilogue
307; CHECK-NEXT:     ldp     x29, x30, [sp, #176]            // 16-byte Folded Reload
308; CHECK-NEXT:     .seh_save_fplr  176
309; CHECK-NEXT:     ldp     q14, q15, [sp, #144]            // 32-byte Folded Reload
310; CHECK-NEXT:     .seh_save_any_reg_p     q14, 144
311; CHECK-NEXT:     ldp     q12, q13, [sp, #112]            // 32-byte Folded Reload
312; CHECK-NEXT:     .seh_save_any_reg_p     q12, 112
313; CHECK-NEXT:     ldp     q10, q11, [sp, #80]             // 32-byte Folded Reload
314; CHECK-NEXT:     .seh_save_any_reg_p     q10, 80
315; CHECK-NEXT:     ldp     q8, q9, [sp, #48]               // 32-byte Folded Reload
316; CHECK-NEXT:     .seh_save_any_reg_p     q8, 48
317; CHECK-NEXT:     ldp     q6, q7, [sp, #16]               // 32-byte Folded Reload
318; CHECK-NEXT:     .seh_save_any_reg_p     q6, 16
319; CHECK-NEXT:     add     sp, sp, #192
320; CHECK-NEXT:     .seh_stackalloc 192
321; CHECK-NEXT:     .seh_endepilogue
322; CHECK-NEXT:     br      x0
323; CHECK-NEXT:     .seh_endfunclet
324; CHECK-NEXT:     .seh_endproc
325  ret [2 x i8] %0
326}
327
328define [3 x i64] @large_array([3 x i64] %0, [2 x double], [2 x [2 x i64]]) nounwind {
329; CHECK-LABEL:    .def    $ientry_thunk$cdecl$m24$m24D16m32;
330; CHECK:          .section        .wowthk$aa,"xr",discard,$ientry_thunk$cdecl$m24$m24D16m32
331; CHECK:          // %bb.0:
332; CHECK-NEXT:     stp     q6, q7, [sp, #-192]!            // 32-byte Folded Spill
333; CHECK-NEXT:     .seh_save_any_reg_px    q6, 192
334; CHECK-NEXT:     stp     q8, q9, [sp, #32]               // 32-byte Folded Spill
335; CHECK-NEXT:     .seh_save_any_reg_p     q8, 32
336; CHECK-NEXT:     stp     q10, q11, [sp, #64]             // 32-byte Folded Spill
337; CHECK-NEXT:     .seh_save_any_reg_p     q10, 64
338; CHECK-NEXT:     stp     q12, q13, [sp, #96]             // 32-byte Folded Spill
339; CHECK-NEXT:     .seh_save_any_reg_p     q12, 96
340; CHECK-NEXT:     stp     q14, q15, [sp, #128]            // 32-byte Folded Spill
341; CHECK-NEXT:     .seh_save_any_reg_p     q14, 128
342; CHECK-NEXT:     str     x19, [sp, #160]                 // 8-byte Folded Spill
343; CHECK-NEXT:     .seh_save_reg   x19, 160
344; CHECK-NEXT:     stp     x29, x30, [sp, #168]            // 16-byte Folded Spill
345; CHECK-NEXT:     .seh_save_fplr  168
346; CHECK-NEXT:     add     x29, sp, #168
347; CHECK-NEXT:     .seh_add_fp     168
348; CHECK-NEXT:     .seh_endprologue
349; CHECK-NEXT:     ldp     x10, x8, [x1, #8]
350; CHECK-NEXT:     mov     x19, x0
351; CHECK-NEXT:     ldp     d0, d1, [x2]
352; CHECK-NEXT:     ldr     x0, [x1]
353; CHECK-NEXT:     ldp     x5, x6, [x3, #16]
354; CHECK-NEXT:     ldp     x3, x4, [x3]
355; CHECK-NEXT:     mov     x1, x10
356; CHECK-NEXT:     mov     x2, x8
357; CHECK-NEXT:     blr     x9
358; CHECK-NEXT:     stp     x0, x1, [x19]
359; CHECK-NEXT:     adrp    x8, __os_arm64x_dispatch_ret
360; CHECK-NEXT:     str     x2, [x19, #16]
361; CHECK-NEXT:     ldr     x0, [x8, :lo12:__os_arm64x_dispatch_ret]
362; CHECK-NEXT:     .seh_startepilogue
363; CHECK-NEXT:     ldp     x29, x30, [sp, #168]            // 16-byte Folded Reload
364; CHECK-NEXT:     .seh_save_fplr  168
365; CHECK-NEXT:     ldr     x19, [sp, #160]                 // 8-byte Folded Reload
366; CHECK-NEXT:     .seh_save_reg   x19, 160
367; CHECK-NEXT:     ldp     q14, q15, [sp, #128]            // 32-byte Folded Reload
368; CHECK-NEXT:     .seh_save_any_reg_p     q14, 128
369; CHECK-NEXT:     ldp     q12, q13, [sp, #96]             // 32-byte Folded Reload
370; CHECK-NEXT:     .seh_save_any_reg_p     q12, 96
371; CHECK-NEXT:     ldp     q10, q11, [sp, #64]             // 32-byte Folded Reload
372; CHECK-NEXT:     .seh_save_any_reg_p     q10, 64
373; CHECK-NEXT:     ldp     q8, q9, [sp, #32]               // 32-byte Folded Reload
374; CHECK-NEXT:     .seh_save_any_reg_p     q8, 32
375; CHECK-NEXT:     ldp     q6, q7, [sp], #192              // 32-byte Folded Reload
376; CHECK-NEXT:     .seh_save_any_reg_px    q6, 192
377; CHECK-NEXT:     .seh_endepilogue
378; CHECK-NEXT:     br      x0
379; CHECK-NEXT:     .seh_endfunclet
380; CHECK-NEXT:     .seh_endproc
381  ret [3 x i64] %0
382}
383
384%T1 = type { i16 }
385%T2 = type { i32, float }
386%T3 = type { i64, double }
387%T4 = type { i64, double, i8 }
388define %T2 @simple_struct(%T1 %0, %T2 %1, %T3, %T4) nounwind {
389; CHECK-LABEL:    .def    $ientry_thunk$cdecl$m8$i8m8m16m24;
390; CHECK:          .section        .wowthk$aa,"xr",discard,$ientry_thunk$cdecl$m8$i8m8m16m24
391; CHECK:          // %bb.0:
392; CHECK-NEXT:     sub     sp, sp, #192
393; CHECK-NEXT:     .seh_stackalloc 192
394; CHECK-NEXT:     stp     q6, q7, [sp, #16]               // 32-byte Folded Spill
395; CHECK-NEXT:     .seh_save_any_reg_p     q6, 16
396; CHECK-NEXT:     stp     q8, q9, [sp, #48]               // 32-byte Folded Spill
397; CHECK-NEXT:     .seh_save_any_reg_p     q8, 48
398; CHECK-NEXT:     stp     q10, q11, [sp, #80]             // 32-byte Folded Spill
399; CHECK-NEXT:     .seh_save_any_reg_p     q10, 80
400; CHECK-NEXT:     stp     q12, q13, [sp, #112]            // 32-byte Folded Spill
401; CHECK-NEXT:     .seh_save_any_reg_p     q12, 112
402; CHECK-NEXT:     stp     q14, q15, [sp, #144]            // 32-byte Folded Spill
403; CHECK-NEXT:     .seh_save_any_reg_p     q14, 144
404; CHECK-NEXT:     stp     x29, x30, [sp, #176]            // 16-byte Folded Spill
405; CHECK-NEXT:     .seh_save_fplr  176
406; CHECK-NEXT:     add     x29, sp, #176
407; CHECK-NEXT:     .seh_add_fp     176
408; CHECK-NEXT:     .seh_endprologue
409; CHECK-NEXT:     str     x1, [sp, #8]
410; CHECK-NEXT:     ldr     x8, [x2]
411; CHECK-NEXT:     ldr     x10, [x3]
412; CHECK-NEXT:     ldr     d1, [x2, #8]
413; CHECK-NEXT:                                     // kill: def $w1 killed $w1 killed $x1
414; CHECK-NEXT:     ldr     s0, [sp, #12]
415; CHECK-NEXT:     ldr     d2, [x3, #8]
416; CHECK-NEXT:     mov     x2, x8
417; CHECK-NEXT:     ldrb    w4, [x3, #16]
418; CHECK-NEXT:     mov     x3, x10
419; CHECK-NEXT:     blr     x9
420; CHECK-NEXT:     adrp    x9, __os_arm64x_dispatch_ret
421; CHECK-NEXT:     str     w0, [sp]
422; CHECK-NEXT:     str     s0, [sp, #4]
423; CHECK-NEXT:     ldr     x8, [sp]
424; CHECK-NEXT:     ldr     x0, [x9, :lo12:__os_arm64x_dispatch_ret]
425; CHECK-NEXT:     .seh_startepilogue
426; CHECK-NEXT:     ldp     x29, x30, [sp, #176]            // 16-byte Folded Reload
427; CHECK-NEXT:     .seh_save_fplr  176
428; CHECK-NEXT:     ldp     q14, q15, [sp, #144]            // 32-byte Folded Reload
429; CHECK-NEXT:     .seh_save_any_reg_p     q14, 144
430; CHECK-NEXT:     ldp     q12, q13, [sp, #112]            // 32-byte Folded Reload
431; CHECK-NEXT:     .seh_save_any_reg_p     q12, 112
432; CHECK-NEXT:     ldp     q10, q11, [sp, #80]             // 32-byte Folded Reload
433; CHECK-NEXT:     .seh_save_any_reg_p     q10, 80
434; CHECK-NEXT:     ldp     q8, q9, [sp, #48]               // 32-byte Folded Reload
435; CHECK-NEXT:     .seh_save_any_reg_p     q8, 48
436; CHECK-NEXT:     ldp     q6, q7, [sp, #16]               // 32-byte Folded Reload
437; CHECK-NEXT:     .seh_save_any_reg_p     q6, 16
438; CHECK-NEXT:     add     sp, sp, #192
439; CHECK-NEXT:     .seh_stackalloc 192
440; CHECK-NEXT:     .seh_endepilogue
441; CHECK-NEXT:     br      x0
442; CHECK-NEXT:     .seh_endfunclet
443; CHECK-NEXT:     .seh_endproc
444  ret %T2 %1
445}
446
447define void @cxx_method(ptr noundef nonnull align 8 dereferenceable(8) %0, ptr dead_on_unwind inreg noalias writable sret(i64) align 8 %1) {
448; CHECK-LABEL:    .def    $ientry_thunk$cdecl$i8$i8i8;
449; CHECK: .section        .wowthk$aa,"xr",discard,$ientry_thunk$cdecl$i8$i8i8
450; CHECK:          // %bb.0:
451; CHECK-NEXT:     stp     q6, q7, [sp, #-176]!            // 32-byte Folded Spill
452; CHECK-NEXT:     .seh_save_any_reg_px    q6, 176
453; CHECK-NEXT:     stp     q8, q9, [sp, #32]               // 32-byte Folded Spill
454; CHECK-NEXT:     .seh_save_any_reg_p     q8, 32
455; CHECK-NEXT:     stp     q10, q11, [sp, #64]             // 32-byte Folded Spill
456; CHECK-NEXT:     .seh_save_any_reg_p     q10, 64
457; CHECK-NEXT:     stp     q12, q13, [sp, #96]             // 32-byte Folded Spill
458; CHECK-NEXT:     .seh_save_any_reg_p     q12, 96
459; CHECK-NEXT:     stp     q14, q15, [sp, #128]            // 32-byte Folded Spill
460; CHECK-NEXT:     .seh_save_any_reg_p     q14, 128
461; CHECK-NEXT:     stp     x29, x30, [sp, #160]            // 16-byte Folded Spill
462; CHECK-NEXT:     .seh_save_fplr  160
463; CHECK-NEXT:     add     x29, sp, #160
464; CHECK-NEXT:     .seh_add_fp     160
465; CHECK-NEXT:     .seh_endprologue
466; CHECK-NEXT:     blr     x9
467; CHECK-NEXT:     adrp    x8, __os_arm64x_dispatch_ret
468; CHECK-NEXT:     ldr     x1, [x8, :lo12:__os_arm64x_dispatch_ret]
469; CHECK-NEXT:     mov     x8, x0
470; CHECK-NEXT:     .seh_startepilogue
471; CHECK-NEXT:     ldp     x29, x30, [sp, #160]            // 16-byte Folded Reload
472; CHECK-NEXT:     .seh_save_fplr  160
473; CHECK-NEXT:     ldp     q14, q15, [sp, #128]            // 32-byte Folded Reload
474; CHECK-NEXT:     .seh_save_any_reg_p     q14, 128
475; CHECK-NEXT:     ldp     q12, q13, [sp, #96]             // 32-byte Folded Reload
476; CHECK-NEXT:     .seh_save_any_reg_p     q12, 96
477; CHECK-NEXT:     ldp     q10, q11, [sp, #64]             // 32-byte Folded Reload
478; CHECK-NEXT:     .seh_save_any_reg_p     q10, 64
479; CHECK-NEXT:     ldp     q8, q9, [sp, #32]               // 32-byte Folded Reload
480; CHECK-NEXT:     .seh_save_any_reg_p     q8, 32
481; CHECK-NEXT:     ldp     q6, q7, [sp], #176              // 32-byte Folded Reload
482; CHECK-NEXT:     .seh_save_any_reg_px    q6, 176
483; CHECK-NEXT:     .seh_endepilogue
484; CHECK-NEXT:     br      x1
485; CHECK-NEXT:     .seh_endfunclet
486; CHECK-NEXT:     .seh_endproc
487  ret void
488}
489
490define <4 x i8> @small_vector(<4 x i8> %0) {
491; CHECK-LABEL:    .def	$ientry_thunk$cdecl$m$m;
492; CHECK:          .section	.wowthk$aa,"xr",discard,$ientry_thunk$cdecl$m$m
493; CHECK:          // %bb.0:
494; CHECK-NEXT:     sub	sp, sp, #192
495; CHECK-NEXT:     .seh_stackalloc	192
496; CHECK-NEXT:     stp	q6, q7, [sp, #16]               // 32-byte Folded Spill
497; CHECK-NEXT:     .seh_save_any_reg_p	q6, 16
498; CHECK-NEXT:     stp	q8, q9, [sp, #48]               // 32-byte Folded Spill
499; CHECK-NEXT:     .seh_save_any_reg_p	q8, 48
500; CHECK-NEXT:     stp	q10, q11, [sp, #80]             // 32-byte Folded Spill
501; CHECK-NEXT:     .seh_save_any_reg_p	q10, 80
502; CHECK-NEXT:     stp	q12, q13, [sp, #112]            // 32-byte Folded Spill
503; CHECK-NEXT:     .seh_save_any_reg_p	q12, 112
504; CHECK-NEXT:     stp	q14, q15, [sp, #144]            // 32-byte Folded Spill
505; CHECK-NEXT:     .seh_save_any_reg_p	q14, 144
506; CHECK-NEXT:     stp	x29, x30, [sp, #176]            // 16-byte Folded Spill
507; CHECK-NEXT:     .seh_save_fplr	176
508; CHECK-NEXT:     add	x29, sp, #176
509; CHECK-NEXT:     .seh_add_fp	176
510; CHECK-NEXT:     .seh_endprologue
511; CHECK-NEXT:     str	w0, [sp, #12]
512; CHECK-NEXT:     ldr	s0, [sp, #12]
513; CHECK-NEXT:     ushll	v0.8h, v0.8b, #0
514; CHECK-NEXT:                                           // kill: def $d0 killed $d0 killed $q0
515; CHECK-NEXT:     blr	x9
516; CHECK-NEXT:     uzp1	v0.8b, v0.8b, v0.8b
517; CHECK-NEXT:     adrp	x9, __os_arm64x_dispatch_ret
518; CHECK-NEXT:     str	s0, [sp, #8]
519; CHECK-NEXT:     fmov	w8, s0
520; CHECK-NEXT:     ldr	x0, [x9, :lo12:__os_arm64x_dispatch_ret]
521; CHECK-NEXT:     .seh_startepilogue
522; CHECK-NEXT:     ldp	x29, x30, [sp, #176]            // 16-byte Folded Reload
523; CHECK-NEXT:     .seh_save_fplr	176
524; CHECK-NEXT:     ldp	q14, q15, [sp, #144]            // 32-byte Folded Reload
525; CHECK-NEXT:     .seh_save_any_reg_p	q14, 144
526; CHECK-NEXT:     ldp	q12, q13, [sp, #112]            // 32-byte Folded Reload
527; CHECK-NEXT:     .seh_save_any_reg_p	q12, 112
528; CHECK-NEXT:     ldp	q10, q11, [sp, #80]             // 32-byte Folded Reload
529; CHECK-NEXT:     .seh_save_any_reg_p	q10, 80
530; CHECK-NEXT:     ldp	q8, q9, [sp, #48]               // 32-byte Folded Reload
531; CHECK-NEXT:     .seh_save_any_reg_p	q8, 48
532; CHECK-NEXT:     ldp	q6, q7, [sp, #16]               // 32-byte Folded Reload
533; CHECK-NEXT:     .seh_save_any_reg_p	q6, 16
534; CHECK-NEXT:     add	sp, sp, #192
535; CHECK-NEXT:     .seh_stackalloc	192
536; CHECK-NEXT:     .seh_endepilogue
537; CHECK-NEXT:     br	x0
538; CHECK-NEXT:     .seh_endfunclet
539; CHECK-NEXT:     .seh_endproc
540start:
541  ret <4 x i8> %0
542}
543
544define <8 x i16> @large_vector(<8 x i16> %0) {
545; CHECK-LABEL:    .def	$ientry_thunk$cdecl$m16$m16;
546; CHECK:          .section	.wowthk$aa,"xr",discard,$ientry_thunk$cdecl$m16$m16
547; CHECK:          // %bb.0:
548; CHECK-NEXT:     stp	q6, q7, [sp, #-192]!            // 32-byte Folded Spill
549; CHECK-NEXT:     .seh_save_any_reg_px	q6, 192
550; CHECK-NEXT:     stp	q8, q9, [sp, #32]               // 32-byte Folded Spill
551; CHECK-NEXT:     .seh_save_any_reg_p	q8, 32
552; CHECK-NEXT:     stp	q10, q11, [sp, #64]             // 32-byte Folded Spill
553; CHECK-NEXT:     .seh_save_any_reg_p	q10, 64
554; CHECK-NEXT:     stp	q12, q13, [sp, #96]             // 32-byte Folded Spill
555; CHECK-NEXT:     .seh_save_any_reg_p	q12, 96
556; CHECK-NEXT:     stp	q14, q15, [sp, #128]            // 32-byte Folded Spill
557; CHECK-NEXT:     .seh_save_any_reg_p	q14, 128
558; CHECK-NEXT:     str	x19, [sp, #160]                 // 8-byte Folded Spill
559; CHECK-NEXT:     .seh_save_reg	x19, 160
560; CHECK-NEXT:     stp	x29, x30, [sp, #168]            // 16-byte Folded Spill
561; CHECK-NEXT:     .seh_save_fplr	168
562; CHECK-NEXT:     add	x29, sp, #168
563; CHECK-NEXT:     .seh_add_fp	168
564; CHECK-NEXT:     .seh_endprologue
565; CHECK-NEXT:     ldr	q0, [x1]
566; CHECK-NEXT:     mov	x19, x0
567; CHECK-NEXT:     blr	x9
568; CHECK-NEXT:     adrp	x8, __os_arm64x_dispatch_ret
569; CHECK-NEXT:     str	q0, [x19]
570; CHECK-NEXT:     ldr	x0, [x8, :lo12:__os_arm64x_dispatch_ret]
571; CHECK-NEXT:     .seh_startepilogue
572; CHECK-NEXT:     ldp	x29, x30, [sp, #168]            // 16-byte Folded Reload
573; CHECK-NEXT:     .seh_save_fplr	168
574; CHECK-NEXT:     ldr	x19, [sp, #160]                 // 8-byte Folded Reload
575; CHECK-NEXT:     .seh_save_reg	x19, 160
576; CHECK-NEXT:     ldp	q14, q15, [sp, #128]            // 32-byte Folded Reload
577; CHECK-NEXT:     .seh_save_any_reg_p	q14, 128
578; CHECK-NEXT:     ldp	q12, q13, [sp, #96]             // 32-byte Folded Reload
579; CHECK-NEXT:     .seh_save_any_reg_p	q12, 96
580; CHECK-NEXT:     ldp	q10, q11, [sp, #64]             // 32-byte Folded Reload
581; CHECK-NEXT:     .seh_save_any_reg_p	q10, 64
582; CHECK-NEXT:     ldp	q8, q9, [sp, #32]               // 32-byte Folded Reload
583; CHECK-NEXT:     .seh_save_any_reg_p	q8, 32
584; CHECK-NEXT:     ldp	q6, q7, [sp], #192              // 32-byte Folded Reload
585; CHECK-NEXT:     .seh_save_any_reg_px	q6, 192
586; CHECK-NEXT:     .seh_endepilogue
587; CHECK-NEXT:     br	x0
588; CHECK-NEXT:     .seh_endfunclet
589; CHECK-NEXT:     .seh_endproc
590start:
591  ret <8 x i16> %0
592}
593
594; Verify the hybrid bitmap
595; CHECK-LABEL:    .section        .hybmp$x,"yi"
596; CHECK-NEXT:     .symidx "#no_op"
597; CHECK-NEXT:     .symidx $ientry_thunk$cdecl$v$v
598; CHECK-NEXT:     .word   1
599; CHECK-NEXT:     .symidx "#simple_integers"
600; CHECK-NEXT:     .symidx $ientry_thunk$cdecl$i8$i8i8i8i8
601; CHECK-NEXT:     .word   1
602; CHECK-NEXT:     .symidx "#simple_floats"
603; CHECK-NEXT:     .symidx $ientry_thunk$cdecl$d$fd
604; CHECK-NEXT:     .word   1
605; CHECK-NEXT:     .symidx "#has_varargs"
606; CHECK-NEXT:     .symidx $ientry_thunk$cdecl$v$varargs
607; CHECK-NEXT:     .word   1
608; CHECK-NEXT:     .symidx "#has_sret"
609; CHECK-NEXT:     .symidx $ientry_thunk$cdecl$m100$v
610; CHECK-NEXT:     .word   1
611; CHECK-NEXT:     .symidx "#matches_has_sret"
612; CHECK-NEXT:     .symidx $ientry_thunk$cdecl$i8$v
613; CHECK-NEXT:     .word   1
614; CHECK-NEXT:     .symidx "#has_aligned_sret"
615; CHECK-NEXT:     .symidx $ientry_thunk$cdecl$m16$i8
616; CHECK-NEXT:     .word   1
617; CHECK-NEXT:     .symidx "#small_array"
618; CHECK-NEXT:     .symidx $ientry_thunk$cdecl$m2$m2F8
619; CHECK-NEXT:     .word   1
620; CHECK-NEXT:     .symidx "#large_array"
621; CHECK-NEXT:     .symidx $ientry_thunk$cdecl$m24$m24D16m32
622; CHECK-NEXT:     .word   1
623; CHECK-NEXT:     .symidx "#simple_struct"
624; CHECK-NEXT:     .symidx $ientry_thunk$cdecl$m8$i8m8m16m24
625; CHECK-NEXT:     .word   1
626; CHECK-NEXT:     .symidx "#cxx_method"
627; CHECK-NEXT:     .symidx $ientry_thunk$cdecl$i8$i8i8
628; CHECK-NEXT:     .word   1
629; CHECK-NEXT:     .symidx	"#small_vector"
630; CHECK-NEXT:     .symidx	$ientry_thunk$cdecl$m$m
631; CHECK-NEXT:     .word	1
632; CHECK-NEXT:     .symidx	"#large_vector"
633; CHECK-NEXT:     .symidx	$ientry_thunk$cdecl$m16$m16
634; CHECK-NEXT:     .word	1
635