Run DCE after a LoopFlatten test to reduce spurious output [nfc]
[llvm-project.git] / llvm / test / MC / AArch64 / seh-packed-epilog.s
blob85ac8e80dbdda792a17f8ed995a56fc3fc505dce
1 // This test checks that the epilogue is packed where possible.
3 // RUN: llvm-mc -triple aarch64-pc-win32 -filetype=obj %s -o %t.o
4 // RUN: llvm-readobj -u %t.o | FileCheck %s
6 // CHECK: UnwindInformation [
7 // CHECK-NEXT: RuntimeFunction {
8 // CHECK-NEXT: Function: func
9 // CHECK-NEXT: ExceptionRecord: .xdata
10 // CHECK-NEXT: ExceptionData {
11 // CHECK-NEXT: FunctionLength:
12 // CHECK-NEXT: Version:
13 // CHECK-NEXT: ExceptionData:
14 // CHECK-NEXT: EpiloguePacked: Yes
15 // CHECK-NEXT: EpilogueOffset: 2
16 // CHECK-NEXT: ByteCodeLength:
17 // CHECK-NEXT: Prologue [
18 // CHECK-NEXT: 0xdc04 ; str d8, [sp, #32]
19 // CHECK-NEXT: 0xe1 ; mov fp, sp
20 // CHECK-NEXT: 0x42 ; stp x29, x30, [sp, #16]
21 // CHECK-NEXT: 0x85 ; stp x29, x30, [sp, #-48]!
22 // CHECK-NEXT: 0xe6 ; save next
23 // CHECK-NEXT: 0x24 ; stp x19, x20, [sp, #-32]!
24 // CHECK-NEXT: 0xc842 ; stp x20, x21, [sp, #16]
25 // CHECK-NEXT: 0x03 ; sub sp, #48
26 // CHECK-NEXT: 0xe4 ; end
27 // CHECK-NEXT: ]
28 // CHECK-NEXT: Epilogue [
29 // CHECK-NEXT: 0xe1 ; mov sp, fp
30 // CHECK-NEXT: 0x42 ; ldp x29, x30, [sp, #16]
31 // CHECK-NEXT: 0x85 ; ldp x29, x30, [sp], #48
32 // CHECK-NEXT: 0xe6 ; restore next
33 // CHECK-NEXT: 0x24 ; ldp x19, x20, [sp], #32
34 // CHECK-NEXT: 0xc842 ; ldp x20, x21, [sp, #16]
35 // CHECK-NEXT: 0x03 ; add sp, #48
36 // CHECK-NEXT: 0xe4 ; end
37 // CHECK-NEXT: ]
38 // CHECK-NEXT: }
39 // CHECK-NEXT: }
40 // CHECK: RuntimeFunction {
41 // CHECK-NEXT: Function: packed2
42 // CHECK-NEXT: ExceptionRecord:
43 // CHECK-NEXT: ExceptionData {
44 // CHECK: ExceptionData:
45 // CHECK-NEXT: EpiloguePacked: Yes
46 // CHECK-NEXT: EpilogueOffset: 0
47 // CHECK-NEXT: ByteCodeLength: 4
48 // CHECK-NEXT: Prologue [
49 // CHECK-NEXT: 0x83 ; stp x29, x30, [sp, #-32]!
50 // CHECK-NEXT: 0x03 ; sub sp, #48
51 // CHECK-NEXT: 0xe4 ; end
52 // CHECK-NEXT: ]
53 // CHECK: RuntimeFunction {
54 // CHECK-NEXT: Function: nonpacked1
55 // CHECK-NEXT: ExceptionRecord:
56 // CHECK-NEXT: ExceptionData {
57 // CHECK: ExceptionData:
58 // CHECK-NEXT: EpiloguePacked: No
59 // CHECK: RuntimeFunction {
60 // CHECK-NEXT: Function: nonshared2
61 // CHECK-NEXT: ExceptionRecord:
62 // CHECK-NEXT: ExceptionData {
63 // CHECK: ExceptionData:
64 // CHECK-NEXT: EpiloguePacked: Yes
65 // CHECK-NEXT: EpilogueOffset: 3
66 // CHECK-NEXT: ByteCodeLength: 8
67 // CHECK-NEXT: Prologue [
68 // CHECK-NEXT: 0x02 ; sub sp, #32
69 // CHECK-NEXT: 0x03 ; sub sp, #48
70 // CHECK-NEXT: 0xe4 ; end
71 // CHECK-NEXT: ]
72 // CHECK-NEXT: Epilogue [
73 // CHECK-NEXT: 0x01 ; add sp, #16
74 // CHECK-NEXT: 0x03 ; add sp, #48
75 // CHECK-NEXT: 0xe4 ; end
76 // CHECK-NEXT: ]
77 // CHECK: RuntimeFunction {
78 // CHECK-NEXT: Function: nonshared3
79 // CHECK-NEXT: ExceptionRecord:
80 // CHECK-NEXT: ExceptionData {
81 // CHECK: ExceptionData:
82 // CHECK-NEXT: EpiloguePacked: Yes
83 // CHECK-NEXT: EpilogueOffset: 3
84 // CHECK-NEXT: ByteCodeLength: 8
85 // CHECK-NEXT: Prologue [
86 // CHECK-NEXT: 0x02 ; sub sp, #32
87 // CHECK-NEXT: 0x03 ; sub sp, #48
88 // CHECK-NEXT: 0xe4 ; end
89 // CHECK-NEXT: ]
90 // CHECK-NEXT: Epilogue [
91 // CHECK-NEXT: 0xe1 ; mov sp, fp
92 // CHECK-NEXT: 0x02 ; add sp, #32
93 // CHECK-NEXT: 0x03 ; add sp, #48
94 // CHECK-NEXT: 0xe4 ; end
95 // CHECK-NEXT: ]
97 .text
98 .globl func
99 .seh_proc func
100 func:
101 sub sp, sp, #48
102 .seh_stackalloc 48
103 // Check that canonical opcode forms (r19r20_x, fplr, fplr_x, save_next,
104 // set_fp) are treated as a match even if one (in prologue or epilogue)
105 // was simplified from the more generic opcodes.
106 stp x20, x21, [sp, #16]
107 .seh_save_regp x20, 16
108 stp x19, x20, [sp, #-32]!
109 .seh_save_r19r20_x 32
110 stp x21, x22, [sp, #16]
111 .seh_save_regp x21, 16
112 stp x29, x30, [sp, #-48]!
113 .seh_save_regp_x x29, 48
114 stp x29, x30, [sp, #16]
115 .seh_save_regp x29, 16
116 add x29, sp, #0
117 .seh_add_fp 0
118 str d8, [sp, #32]
119 .seh_save_freg d8, 32
120 .seh_endprologue
124 .seh_startepilogue
125 mov sp, x29
126 .seh_set_fp
127 ldp x29, x30, [sp, #16]
128 .seh_save_fplr 16
129 ldp x29, x30, [sp, #-48]!
130 .seh_save_fplr_x 48
131 ldp x21, x22, [sp, #16]
132 .seh_save_next
133 ldp x19, x20, [sp], #32
134 .seh_save_regp_x x19, 32
135 ldp x20, x21, [sp, #16]
136 .seh_save_regp x20, 16
137 add sp, sp, #48
138 .seh_stackalloc 48
139 .seh_endepilogue
141 .seh_endproc
144 // Test a perfectly matching epilog with no offset.
145 .seh_proc packed2
146 packed2:
147 sub sp, sp, #48
148 .seh_stackalloc 48
149 stp x29, lr, [sp, #-32]!
150 .seh_save_fplr_x 32
151 .seh_endprologue
153 .seh_startepilogue
154 ldp x29, lr, [sp], #32
155 .seh_save_fplr_x 32
156 add sp, sp, #48
157 .seh_stackalloc 48
158 .seh_endepilogue
160 .seh_endproc
163 .seh_proc nonpacked1
164 nonpacked1:
165 sub sp, sp, #48
166 .seh_stackalloc 48
167 .seh_endprologue
170 .seh_startepilogue
171 add sp, sp, #48
172 .seh_stackalloc 48
173 .seh_endepilogue
174 // This epilogue isn't packed with the prologue, as it doesn't align with
175 // the end of the function (one extra nop before the ret).
178 .seh_endproc
181 .seh_proc nonshared2
182 nonshared2:
183 sub sp, sp, #48
184 .seh_stackalloc 48
185 sub sp, sp, #32
186 .seh_stackalloc 32
187 .seh_endprologue
190 .seh_startepilogue
191 // Not shared; the epilogue mismatches at the second opcode.
192 add sp, sp, #16
193 .seh_stackalloc 16
194 add sp, sp, #48
195 .seh_stackalloc 48
196 .seh_endepilogue
198 .seh_endproc
200 .seh_proc nonshared3
201 nonshared3:
202 sub sp, sp, #48
203 .seh_stackalloc 48
204 sub sp, sp, #32
205 .seh_stackalloc 32
206 .seh_endprologue
209 .seh_startepilogue
210 // Not shared; the epilogue is longer than the prologue.
211 mov sp, x29
212 .seh_set_fp
213 add sp, sp, #32
214 .seh_stackalloc 32
215 add sp, sp, #48
216 .seh_stackalloc 48
217 .seh_endepilogue
219 .seh_endproc