[lld] f6017ab - [lld-macho] Support folding of functions with identical LSDAs
Jez Ng via llvm-commits
llvm-commits at lists.llvm.org
Tue Jul 19 10:30:26 PDT 2022
Author: Jez Ng
Date: 2022-07-19T13:29:52-04:00
New Revision: f6017abb602780d81be928c93ec6afe74752f613
URL: https://github.com/llvm/llvm-project/commit/f6017abb602780d81be928c93ec6afe74752f613
DIFF: https://github.com/llvm/llvm-project/commit/f6017abb602780d81be928c93ec6afe74752f613.diff
LOG: [lld-macho] Support folding of functions with identical LSDAs
To do this, we need to slice away the LSDA pointer, just like we are
slicing away the functionAddress pointer.
No observable difference in perf on chromium_framework:
base diff difference (95% CI)
sys_time 1.769 ± 0.068 1.761 ± 0.065 [ -2.7% .. +1.8%]
user_time 9.517 ± 0.110 9.528 ± 0.116 [ -0.6% .. +0.8%]
wall_time 8.291 ± 0.174 8.307 ± 0.183 [ -1.1% .. +1.5%]
samples 21 25
Reviewed By: #lld-macho, thakis
Differential Revision: https://reviews.llvm.org/D129830
Added:
Modified:
lld/MachO/ICF.cpp
lld/MachO/InputFiles.cpp
lld/MachO/InputSection.cpp
lld/MachO/InputSection.h
lld/test/MachO/icf.s
Removed:
################################################################################
diff --git a/lld/MachO/ICF.cpp b/lld/MachO/ICF.cpp
index ad029142681f8..2a927b15edacd 100644
--- a/lld/MachO/ICF.cpp
+++ b/lld/MachO/ICF.cpp
@@ -420,10 +420,11 @@ void macho::foldIdenticalSections() {
uint64_t icfUniqueID = inputSections.size();
for (ConcatInputSection *isec : inputSections) {
// FIXME: consider non-code __text sections as hashable?
- bool isHashable = (isCodeSection(isec) || isCfStringSection(isec) ||
- isClassRefsSection(isec)) &&
- !isec->keepUnique && !isec->shouldOmitFromOutput() &&
- sectionType(isec->getFlags()) == MachO::S_REGULAR;
+ bool isHashable =
+ (isCodeSection(isec) || isCfStringSection(isec) ||
+ isClassRefsSection(isec) || isGccExceptTabSection(isec)) &&
+ !isec->keepUnique && !isec->shouldOmitFromOutput() &&
+ sectionType(isec->getFlags()) == MachO::S_REGULAR;
if (isHashable) {
hashable.push_back(isec);
for (Defined *d : isec->symbols)
diff --git a/lld/MachO/InputFiles.cpp b/lld/MachO/InputFiles.cpp
index 225a7122198a4..1abbc303c5bdb 100644
--- a/lld/MachO/InputFiles.cpp
+++ b/lld/MachO/InputFiles.cpp
@@ -1186,14 +1186,27 @@ ArrayRef<data_in_code_entry> ObjFile::getDataInCode() const {
void ObjFile::registerCompactUnwind(Section &compactUnwindSection) {
for (const Subsection &subsection : compactUnwindSection.subsections) {
ConcatInputSection *isec = cast<ConcatInputSection>(subsection.isec);
- // Hack!! Since each CUE contains a
diff erent function address, if ICF
- // operated naively and compared the entire contents of each CUE, entries
- // with identical unwind info but belonging to
diff erent functions would
- // never be considered equivalent. To work around this problem, we slice
- // away the function address here. (Note that we do not adjust the offsets
- // of the corresponding relocations.) We rely on `relocateCompactUnwind()`
- // to correctly handle these truncated input sections.
- isec->data = isec->data.slice(target->wordSize);
+ // Hack!! Each compact unwind entry (CUE) has its UNSIGNED relocations embed
+ // their addends in its data. Thus if ICF operated naively and compared the
+ // entire contents of each CUE, entries with identical unwind info but e.g.
+ // belonging to
diff erent functions would never be considered equivalent. To
+ // work around this problem, we remove some parts of the data containing the
+ // embedded addends. In particular, we remove the function address and LSDA
+ // pointers. Since these locations are at the start and end of the entry,
+ // we can do this using a simple, efficient slice rather than performing a
+ // copy. We are not losing any information here because the embedded
+ // addends have already been parsed in the corresponding Reloc structs.
+ //
+ // Removing these pointers would not be safe if they were pointers to
+ // absolute symbols. In that case, there would be no corresponding
+ // relocation. However, (AFAIK) MC cannot emit references to absolute
+ // symbols for either the function address or the LSDA. However, it *can* do
+ // so for the personality pointer, so we are not slicing that field away.
+ //
+ // Note that we do not adjust the offsets of the corresponding relocations;
+ // instead, we rely on `relocateCompactUnwind()` to correctly handle these
+ // truncated input sections.
+ isec->data = isec->data.slice(target->wordSize, 8 + target->wordSize);
uint32_t encoding = read32le(isec->data.data() + sizeof(uint32_t));
// llvm-mc omits CU entries for functions that need DWARF encoding, but
// `ld -r` doesn't. We can ignore them because we will re-synthesize these
diff --git a/lld/MachO/InputSection.cpp b/lld/MachO/InputSection.cpp
index df312525df610..76b11d9da4f89 100644
--- a/lld/MachO/InputSection.cpp
+++ b/lld/MachO/InputSection.cpp
@@ -345,6 +345,11 @@ bool macho::isEhFrameSection(const InputSection *isec) {
isec->getSegName() == segment_names::text;
}
+bool macho::isGccExceptTabSection(const InputSection *isec) {
+ return isec->getName() == section_names::gccExceptTab &&
+ isec->getSegName() == segment_names::text;
+}
+
std::string lld::toString(const InputSection *isec) {
return (toString(isec->getFile()) + ":(" + isec->getName() + ")").str();
}
diff --git a/lld/MachO/InputSection.h b/lld/MachO/InputSection.h
index e8710c25f5347..2b98adce9fa02 100644
--- a/lld/MachO/InputSection.h
+++ b/lld/MachO/InputSection.h
@@ -281,6 +281,7 @@ bool isCodeSection(const InputSection *);
bool isCfStringSection(const InputSection *);
bool isClassRefsSection(const InputSection *);
bool isEhFrameSection(const InputSection *);
+bool isGccExceptTabSection(const InputSection *);
extern std::vector<ConcatInputSection *> inputSections;
diff --git a/lld/test/MachO/icf.s b/lld/test/MachO/icf.s
index 417549f2b7573..4325102e97232 100644
--- a/lld/test/MachO/icf.s
+++ b/lld/test/MachO/icf.s
@@ -37,6 +37,9 @@
# CHECK: [[#%x,HAS_UNWIND_2:]] l F __TEXT,__text _has_unwind_1
# CHECK: [[#%x,HAS_UNWIND_2]] l F __TEXT,__text _has_unwind_2
# CHECK: [[#%x,HAS_UNWIND_3:]] l F __TEXT,__text _has_unwind_3
+# CHECK: [[#%x,HAS_UNWIND_4:]] l F __TEXT,__text _has_unwind_4
+# CHECK: [[#%x,HAS_ABS_PERSONALITY_1:]] l F __TEXT,__text _has_abs_personality_1
+# CHECK: [[#%x,HAS_ABS_PERSONALITY_2:]] l F __TEXT,__text _has_abs_personality_2
# CHECK: [[#%x,HAS_EH_FRAME_1:]] l F __TEXT,__text _has_eh_frame_1
# CHECK: [[#%x,HAS_EH_FRAME_2:]] l F __TEXT,__text _has_eh_frame_2
# CHECK: [[#%x,HAS_EH_FRAME_3:]] l F __TEXT,__text _has_eh_frame_3
@@ -48,6 +51,9 @@
### FIXME: Mutually-recursive functions with identical bodies (see below)
# COM: [[#%x,ASYMMETRIC_RECURSIVE_2:]] l F __TEXT,__text _asymmetric_recursive_1
# COM: [[#%x,ASYMMETRIC_RECURSIVE_2]] l F __TEXT,__text _asymmetric_recursive_2
+# CHECK: [[#%x,GCC_EXCEPT_0:]] l O __TEXT,__gcc_except_tab GCC_except_table0
+# CHECK: [[#%x,GCC_EXCEPT_0]] l O __TEXT,__gcc_except_tab GCC_except_table1
+# CHECK: [[#%x,GCC_EXCEPT_2:]] l O __TEXT,__gcc_except_tab GCC_except_table2
## Check that we don't accidentally dedup distinct EH frames.
# CHECK: FDE {{.*}} pc=[[#%x,HAS_EH_FRAME_1]]
@@ -80,6 +86,9 @@
# CHECK: callq 0x[[#%x,HAS_UNWIND_2]] <_has_unwind_2>
# CHECK: callq 0x[[#%x,HAS_UNWIND_2]] <_has_unwind_2>
# CHECK: callq 0x[[#%x,HAS_UNWIND_3]] <_has_unwind_3>
+# CHECK: callq 0x[[#%x,HAS_UNWIND_4]] <_has_unwind_4>
+# CHECK: callq 0x[[#%x,HAS_ABS_PERSONALITY_1]] <_has_abs_personality_1>
+# CHECK: callq 0x[[#%x,HAS_ABS_PERSONALITY_2]] <_has_abs_personality_2>
# CHECK: callq 0x[[#%x,HAS_EH_FRAME_1]] <_has_eh_frame_1>
# CHECK: callq 0x[[#%x,HAS_EH_FRAME_2]] <_has_eh_frame_2>
# CHECK: callq 0x[[#%x,HAS_EH_FRAME_3]] <_has_eh_frame_3>
@@ -200,6 +209,7 @@ _my_personality:
_has_unwind_1:
.cfi_startproc
.cfi_personality 155, _my_personality
+ .cfi_lsda 16, Lexception0
.cfi_def_cfa_offset 16
ret
.cfi_endproc
@@ -207,19 +217,51 @@ _has_unwind_1:
_has_unwind_2:
.cfi_startproc
.cfi_personality 155, _my_personality
+ .cfi_lsda 16, Lexception1
.cfi_def_cfa_offset 16
ret
.cfi_endproc
-## This function has
diff erent unwind info from the preceding two, and therefore
+## This function has a
diff erent cfa_offset from the first two, and therefore
## should not be folded.
_has_unwind_3:
.cfi_startproc
.cfi_personality 155, _my_personality
+ .cfi_lsda 16, Lexception1
.cfi_def_cfa_offset 8
ret
.cfi_endproc
+## This function has a
diff erent LSDA from the first two, and therefore should
+## not be folded.
+_has_unwind_4:
+ .cfi_startproc
+ .cfi_personality 155, _my_personality
+ .cfi_lsda 16, Lexception2
+ .cfi_def_cfa_offset 16
+ ret
+ .cfi_endproc
+
+## The next two functions should not be folded as they refer to personalities
+## at
diff erent absolute addresses. This verifies that we are doing the right
+## thing in our "data slicing hack" for compact unwind.
+_has_abs_personality_1:
+ .cfi_startproc
+ .cfi_personality 155, _abs_personality_1
+ .cfi_def_cfa_offset 16
+ ret
+ .cfi_endproc
+
+_has_abs_personality_2:
+ .cfi_startproc
+ .cfi_personality 155, _abs_personality_2
+ .cfi_def_cfa_offset 16
+ ret
+ .cfi_endproc
+
+_abs_personality_1 = 0x1
+_abs_personality_2 = 0x2
+
## In theory _has_eh_frame_{1, 2} can be dedup'ed, but we don't support this
## yet.
_has_eh_frame_1:
@@ -319,6 +361,9 @@ _main:
callq _has_unwind_1
callq _has_unwind_2
callq _has_unwind_3
+ callq _has_unwind_4
+ callq _has_abs_personality_1
+ callq _has_abs_personality_2
callq _has_eh_frame_1
callq _has_eh_frame_2
callq _has_eh_frame_3
@@ -329,3 +374,16 @@ _main:
callq _init_1
callq _init_2
callq _init_3
+
+.section __TEXT,__gcc_except_tab
+GCC_except_table0:
+Lexception0:
+ .byte 255
+
+GCC_except_table1:
+Lexception1:
+ .byte 255
+
+GCC_except_table2:
+Lexception2:
+ .byte 254
More information about the llvm-commits
mailing list