[llvm] 64a3c63 - [MC] [Win64EH] Check for matches between epilogs and the prolog on ARM64
Martin Storsjö via llvm-commits
llvm-commits at lists.llvm.org
Mon May 16 14:41:50 PDT 2022
Author: Martin Storsjö
Date: 2022-05-17T00:41:39+03:00
New Revision: 64a3c63e01c5f71659797acb511f18628f41d0d8
URL: https://github.com/llvm/llvm-project/commit/64a3c63e01c5f71659797acb511f18628f41d0d8
DIFF: https://github.com/llvm/llvm-project/commit/64a3c63e01c5f71659797acb511f18628f41d0d8.diff
LOG: [MC] [Win64EH] Check for matches between epilogs and the prolog on ARM64
This allows sharing opcodes between prolog and epilog even when there
is more than one epilog.
I didn't make any handcrafted special MC level testcases for this (yet
at least), but it does seem to have the expected effect on two existing
CodeGen level testcases.
Differential Revision: https://reviews.llvm.org/D125619
Added:
Modified:
llvm/lib/MC/MCWin64EH.cpp
llvm/test/CodeGen/AArch64/wineh4.mir
llvm/test/CodeGen/AArch64/wineh8.mir
Removed:
################################################################################
diff --git a/llvm/lib/MC/MCWin64EH.cpp b/llvm/lib/MC/MCWin64EH.cpp
index 73d3a53605c8..b0e8ecd8999e 100644
--- a/llvm/lib/MC/MCWin64EH.cpp
+++ b/llvm/lib/MC/MCWin64EH.cpp
@@ -605,6 +605,27 @@ static void simplifyOpcodes(std::vector<WinEH::Instruction> &Instructions,
}
}
+// Check if an epilog exists as a subset of the end of a prolog (backwards).
+static int getOffsetInProlog(const std::vector<WinEH::Instruction> &Prolog,
+ const std::vector<WinEH::Instruction> &Epilog) {
+ // Can't find an epilog as a subset if it is longer than the prolog.
+ if (Epilog.size() > Prolog.size())
+ return -1;
+
+ // Check that the epilog actually is a perfect match for the end (backwrds)
+ // of the prolog.
+ for (int I = Epilog.size() - 1; I >= 0; I--) {
+ if (Prolog[I] != Epilog[Epilog.size() - 1 - I])
+ return -1;
+ }
+
+ // If the epilog was a subset of the prolog, find its offset.
+ if (Epilog.size() == Prolog.size())
+ return 0;
+ return ARM64CountOfUnwindCodes(ArrayRef<WinEH::Instruction>(
+ &Prolog[Epilog.size()], Prolog.size() - Epilog.size()));
+}
+
static int checkPackedEpilog(MCStreamer &streamer, WinEH::FrameInfo *info,
int PrologCodeBytes) {
// Can only pack if there's one single epilog
@@ -630,23 +651,10 @@ static int checkPackedEpilog(MCStreamer &streamer, WinEH::FrameInfo *info,
PrologCodeBytes + ARM64CountOfUnwindCodes(Epilog) <= 124)
RetVal = PrologCodeBytes;
- // Can pack if the epilog is a subset of the prolog but not vice versa
- if (Epilog.size() > info->Instructions.size())
+ int Offset = getOffsetInProlog(info->Instructions, Epilog);
+ if (Offset < 0)
return RetVal;
- // Check that the epilog actually is a perfect match for the end (backwrds)
- // of the prolog.
- for (int I = Epilog.size() - 1; I >= 0; I--) {
- if (info->Instructions[I] != Epilog[Epilog.size() - 1 - I])
- return RetVal;
- }
-
- int Offset = Epilog.size() == info->Instructions.size()
- ? 0
- : ARM64CountOfUnwindCodes(ArrayRef<WinEH::Instruction>(
- &info->Instructions[Epilog.size()],
- info->Instructions.size() - Epilog.size()));
-
// Check that the offset and prolog size fits in the first word; it's
// unclear whether the epilog count in the extension word can be taken
// as packed epilog offset.
@@ -990,6 +998,7 @@ static void ARM64EmitUnwindInfo(MCStreamer &streamer, WinEH::FrameInfo *info,
MCSymbol* MatchingEpilog =
FindMatchingEpilog(EpilogInstrs, AddedEpilogs, info);
+ int PrologOffset;
if (MatchingEpilog) {
assert(EpilogInfo.find(MatchingEpilog) != EpilogInfo.end() &&
"Duplicate epilog not found");
@@ -997,6 +1006,12 @@ static void ARM64EmitUnwindInfo(MCStreamer &streamer, WinEH::FrameInfo *info,
// Clear the unwind codes in the EpilogMap, so that they don't get output
// in the logic below.
EpilogInstrs.clear();
+ } else if ((PrologOffset =
+ getOffsetInProlog(info->Instructions, EpilogInstrs)) >= 0) {
+ EpilogInfo[EpilogStart] = PrologOffset;
+ // Clear the unwind codes in the EpilogMap, so that they don't get output
+ // in the logic below.
+ EpilogInstrs.clear();
} else {
EpilogInfo[EpilogStart] = TotalCodeBytes;
TotalCodeBytes += CodeBytes;
@@ -1027,8 +1042,6 @@ static void ARM64EmitUnwindInfo(MCStreamer &streamer, WinEH::FrameInfo *info,
// Extended Code Words, Extended Epilog Count
if (ExtensionWord) {
// FIXME: We should be able to split unwind info into multiple sections.
- // FIXME: We should share epilog codes across epilogs, where possible,
- // which would make this issue show up less frequently.
if (CodeWords > 0xFF || EpilogCount > 0xFFFF)
report_fatal_error("SEH unwind data splitting not yet implemented");
uint32_t row2 = 0x0;
diff --git a/llvm/test/CodeGen/AArch64/wineh4.mir b/llvm/test/CodeGen/AArch64/wineh4.mir
index a281bb246a3a..1fb71bb9316b 100644
--- a/llvm/test/CodeGen/AArch64/wineh4.mir
+++ b/llvm/test/CodeGen/AArch64/wineh4.mir
@@ -9,7 +9,7 @@
# CHECK-NEXT: ExceptionData: No
# CHECK-NEXT: EpiloguePacked: No
# CHECK-NEXT: EpilogueScopes: 2
-# CHECK-NEXT: ByteCodeLength: 32
+# CHECK-NEXT: ByteCodeLength: 16
# CHECK-NEXT: Prologue [
# CHECK-NEXT: 0xc80c ; stp x19, x20, [sp, #96]
# CHECK-NEXT: 0xc88a ; stp x21, x22, [sp, #80]
@@ -23,7 +23,7 @@
# CHECK-NEXT: EpilogueScopes [
# CHECK-NEXT: EpilogueScope {
# CHECK-NEXT: StartOffset: 16
-# CHECK-NEXT: EpilogueStartIndex: 15
+# CHECK-NEXT: EpilogueStartIndex: 0
# CHECK-NEXT: Opcodes [
# CHECK-NEXT: 0xc80c ; ldp x19, x20, [sp, #96]
# CHECK-NEXT: 0xc88a ; ldp x21, x22, [sp, #80]
@@ -37,7 +37,7 @@
# CHECK-NEXT: }
# CHECK-NEXT: EpilogueScope {
# CHECK-NEXT: StartOffset: 33
-# CHECK-NEXT: EpilogueStartIndex: 15
+# CHECK-NEXT: EpilogueStartIndex: 0
# CHECK-NEXT: Opcodes [
# CHECK-NEXT: 0xc80c ; ldp x19, x20, [sp, #96]
# CHECK-NEXT: 0xc88a ; ldp x21, x22, [sp, #80]
diff --git a/llvm/test/CodeGen/AArch64/wineh8.mir b/llvm/test/CodeGen/AArch64/wineh8.mir
index 38853e7d8d8b..12233fa8e723 100644
--- a/llvm/test/CodeGen/AArch64/wineh8.mir
+++ b/llvm/test/CodeGen/AArch64/wineh8.mir
@@ -9,7 +9,7 @@
# CHECK-NEXT: ExceptionData: No
# CHECK-NEXT: EpiloguePacked: No
# CHECK-NEXT: EpilogueScopes: 2
-# CHECK-NEXT: ByteCodeLength: 44
+# CHECK-NEXT: ByteCodeLength: 28
# CHECK-NEXT: Prologue [
# CHECK-NEXT: 0xc80c ; stp x19, x20, [sp, #96]
# CHECK-NEXT: 0xc88a ; stp x21, x22, [sp, #80]
@@ -36,7 +36,7 @@
# CHECK-NEXT: }
# CHECK-NEXT: EpilogueScope {
# CHECK-NEXT: StartOffset: 32
-# CHECK-NEXT: EpilogueStartIndex: 28
+# CHECK-NEXT: EpilogueStartIndex: 0
# CHECK-NEXT: Opcodes [
# CHECK-NEXT: 0xc80c ; ldp x19, x20, [sp, #96]
# CHECK-NEXT: 0xc88a ; ldp x21, x22, [sp, #80]
More information about the llvm-commits
mailing list