-
Notifications
You must be signed in to change notification settings - Fork 15.5k
[MC] [Win64EH] Produce packed unwind for the special case of X19+LR #169697
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[MC] [Win64EH] Produce packed unwind for the special case of X19+LR #169697
Conversation
|
@llvm/pr-subscribers-llvm-binary-utilities @llvm/pr-subscribers-llvm-mc Author: Martin Storsjö (mstorsjo) ChangesFull diff: https://github.com/llvm/llvm-project/pull/169697.diff 4 Files Affected:
diff --git a/llvm/lib/MC/MCWin64EH.cpp b/llvm/lib/MC/MCWin64EH.cpp
index 6d146f6cedd6e..97585fbd5791d 100644
--- a/llvm/lib/MC/MCWin64EH.cpp
+++ b/llvm/lib/MC/MCWin64EH.cpp
@@ -1051,7 +1051,9 @@ static bool tryARM64PackedUnwind(WinEH::FrameInfo *info, uint32_t FuncLength,
// the order - that would work fine when unwinding from within
// functions, but not be exactly right if unwinding happens within
// prologs/epilogs.
- for (const WinEH::Instruction &Inst : info->Instructions) {
+ for (auto It = info->Instructions.begin(), EndIt = info->Instructions.end();
+ It != EndIt; It++) {
+ const WinEH::Instruction &Inst = *It;
switch (Inst.Operation) {
case Win64EH::UOP_End:
if (Location != Start)
@@ -1169,6 +1171,24 @@ static bool tryARM64PackedUnwind(WinEH::FrameInfo *info, uint32_t FuncLength,
Location != FloatRegs && Location != InputArgs &&
Location != StackAdjust)
return false;
+ if (Location == Start2) { // Can't have this at Start3, after PACSignLR
+ auto NextIt = It + 1;
+ if (NextIt != EndIt) {
+ const WinEH::Instruction &NextInst = *NextIt;
+ if (NextInst.Operation == Win64EH::UOP_SaveLRPair &&
+ NextInst.Offset == 0 && NextInst.Register == 19) {
+ assert(Predecrement == 0);
+ assert(RegI == 0);
+ assert(!StandaloneLR);
+ Predecrement = Inst.Offset;
+ RegI = 1;
+ StandaloneLR = true;
+ Location = FloatRegs;
+ It++; // Consume both the Alloc and the SaveLRPair
+ continue;
+ }
+ }
+ }
// Can have either a single decrement, or a pair of decrements with
// 4080 and another decrement.
if (StackOffset == 0)
diff --git a/llvm/test/MC/AArch64/seh-packed-unwind.s b/llvm/test/MC/AArch64/seh-packed-unwind.s
index 5b86ab4bc0d49..89269b864e5e9 100644
--- a/llvm/test/MC/AArch64/seh-packed-unwind.s
+++ b/llvm/test/MC/AArch64/seh-packed-unwind.s
@@ -295,6 +295,24 @@
// CHECK-NEXT: end
// CHECK-NEXT: ]
// CHECK-NEXT: }
+// CHECK-NEXT: RuntimeFunction {
+// CHECK-NEXT: Function: func19 (0x2A8)
+// CHECK-NEXT: Fragment: No
+// CHECK-NEXT: FunctionLength: 48
+// CHECK-NEXT: RegF: 2
+// CHECK-NEXT: RegI: 1
+// CHECK-NEXT: HomedParameters: No
+// CHECK-NEXT: CR: 1
+// CHECK-NEXT: FrameSize: 112
+// CHECK-NEXT: Prologue [
+// CHECK-NEXT: sub sp, sp, #64
+// CHECK-NEXT: str d10, [sp, #32]
+// CHECK-NEXT: stp d8, d9, [sp, #16]
+// CHECK-NEXT: stp x19, lr, [sp]
+// CHECK-NEXT: sub sp, sp, #48
+// CHECK-NEXT: end
+// CHECK-NEXT: ]
+// CHECK-NEXT: }
// CHECK: RuntimeFunction {
// CHECK-NEXT: Function: nonpacked1
// CHECK-NEXT: ExceptionRecord:
@@ -374,6 +392,11 @@
// CHECK-NEXT: Function: nonpacked16
// CHECK-NEXT: ExceptionRecord:
// CHECK-NEXT: ExceptionData {
+// CHECK: EpiloguePacked: Yes
+// CHECK: RuntimeFunction {
+// CHECK-NEXT: Function: nonpacked17
+// CHECK-NEXT: ExceptionRecord:
+// CHECK-NEXT: ExceptionData {
// CHECK: EpiloguePacked: Yes
@@ -809,6 +832,35 @@ func18:
ret
.seh_endproc
+func19:
+ .seh_proc func19
+ sub sp, sp, #48
+ .seh_stackalloc 48
+ stp x19, lr, [sp]
+ .seh_save_lrpair x19, 0
+ stp d8, d9, [sp, #16]
+ .seh_save_fregp d8, 16
+ str d10, [sp, #32]
+ .seh_save_freg d10, 32
+ sub sp, sp, #64
+ .seh_stackalloc 64
+ .seh_endprologue
+ nop
+ .seh_startepilogue
+ add sp, sp, #64
+ .seh_stackalloc 64
+ ldr d10, [sp, #32]
+ .seh_save_freg d10, 32
+ ldp d8, d9, [sp, #16]
+ .seh_save_fregp d8, 16
+ ldp x19, lr, [sp]
+ .seh_save_lrpair x19, 0
+ add sp, sp, #48
+ .seh_stackalloc 48
+ .seh_endepilogue
+ ret
+ .seh_endproc
+
nonpacked1:
.seh_proc nonpacked1
// Can't be packed; can't save integer registers after float registers.
@@ -1157,3 +1209,34 @@ nonpacked16:
.seh_endepilogue
br x9
.seh_endproc
+
+nonpacked17:
+ .seh_proc nonpacked17
+ // Can't be packed; more predecrement for SavSZ than used for
+ // corresponding RegI/RegF/LR saves
+ sub sp, sp, #64
+ .seh_stackalloc 64
+ stp x19, lr, [sp]
+ .seh_save_lrpair x19, 0
+ stp d8, d9, [sp, #16]
+ .seh_save_fregp d8, 16
+ str d10, [sp, #32]
+ .seh_save_freg d10, 32
+ sub sp, sp, #64
+ .seh_stackalloc 64
+ .seh_endprologue
+ nop
+ .seh_startepilogue
+ add sp, sp, #64
+ .seh_stackalloc 64
+ ldr d10, [sp, #32]
+ .seh_save_freg d10, 32
+ ldp d8, d9, [sp, #16]
+ .seh_save_fregp d8, 16
+ ldp x19, lr, [sp]
+ .seh_save_lrpair x19, 0
+ add sp, sp, #64
+ .seh_stackalloc 64
+ .seh_endepilogue
+ ret
+ .seh_endproc
diff --git a/llvm/test/tools/llvm-readobj/COFF/arm64-packed-unwind.s b/llvm/test/tools/llvm-readobj/COFF/arm64-packed-unwind.s
index d9953ccc3f3d8..72e79b77a01ad 100644
--- a/llvm/test/tools/llvm-readobj/COFF/arm64-packed-unwind.s
+++ b/llvm/test/tools/llvm-readobj/COFF/arm64-packed-unwind.s
@@ -139,7 +139,8 @@
// CHECK-NEXT: FrameSize: 32
// CHECK-NEXT: Prologue [
// CHECK-NEXT: sub sp, sp, #16
-// CHECK-NEXT: INVALID!
+// CHECK-NEXT: stp x19, lr, [sp]
+// CHECK-NEXT: sub sp, sp, #16
// CHECK-NEXT: end
// CHECK-NEXT: ]
// CHECK-NEXT: }
diff --git a/llvm/tools/llvm-readobj/ARMWinEHPrinter.cpp b/llvm/tools/llvm-readobj/ARMWinEHPrinter.cpp
index c6e409c63ef3a..eedf6732ad3f4 100644
--- a/llvm/tools/llvm-readobj/ARMWinEHPrinter.cpp
+++ b/llvm/tools/llvm-readobj/ARMWinEHPrinter.cpp
@@ -1457,10 +1457,14 @@ bool Decoder::dumpPackedARM64Entry(const object::COFFObjectFile &COFF,
// The last register, an odd register without a pair
if (RF.CR() == 1) {
if (I == 0) { // If this is the only register pair
- // CR=1 combined with RegI=1 doesn't map to a documented case;
- // it doesn't map to any regular unwind info opcode, and the
- // actual unwinder doesn't support it.
- SW.startLine() << "INVALID!\n";
+ // CR=1 combined with RegI=1 maps to a special case; there's
+ // no unwind info opcode that saves a GPR together with LR
+ // with writeback to sp (no save_lrpair_x).
+ // Instead, this case expands to two instructions; a preceding
+ // (in prologue execution order) "sub sp, sp, #16", followed
+ // by a regular "stp x19, lr, [sp]" (save_lrpair).
+ SW.startLine() << format("stp x%d, lr, [sp]\n", 19);
+ SW.startLine() << format("sub sp, sp, #%d\n", SavSZ);
} else
SW.startLine() << format("stp x%d, lr, [sp, #%d]\n", 19 + 2 * I,
16 * I);
|
efriedma-quic
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM with one minor comment.
c495bde to
3d3c6da
Compare
How often does this pattern get emitted? |
|
I don't think anyone has ever gathered complete stats for prologue forms. If you want to check for yourself, you can scan |
|
(I assumed you're asking for how much benefit we can get. If you're asking how frequently LLVM currently emits the sequence that will actually get compressed, the answer is "never".) |
|
Your assumption is spot on - the question was about how profitable it would be. Basically, trying to ascertain if this is something valuable enough that it would make sense to spend some time to optimise the prologue generation or if it rare enough that we should leave it be for the time being and hope that we get to it some day. |
3d3c6da to
bd1b7ca
Compare
bd1b7ca to
78a4a58
Compare
No description provided.