forked from OSchip/llvm-project
[COFF] Simplify ICF associated comdat handling
This is a different approach from D98993 that should achieve most of the same benefit. The two changes are: 1. Sort the list of associated child sections by section name 2. Do not consider associated sections to have children themselves This fixes the main issue, which was that we sometimes considered an .xdata section to have a child .pdata section. That lead to slow links and larger binaries (less xdata folding). Otherwise, this should be NFC: we go back to ignoring .debug/.gljmp and other metadata sections rather than only looking at pdata/xdata. We discovered that we do care about other associated sections, like ASan global registration metadata.
This commit is contained in:
parent
0d91075f77
commit
18a9b18087
|
@ -454,11 +454,21 @@ void SectionChunk::writeAndRelocateSubsection(ArrayRef<uint8_t> sec,
|
|||
}
|
||||
|
||||
void SectionChunk::addAssociative(SectionChunk *child) {
|
||||
// Insert this child at the head of the list.
|
||||
// Insert the child section into the list of associated children. Keep the
|
||||
// list ordered by section name so that ICF does not depend on section order.
|
||||
assert(child->assocChildren == nullptr &&
|
||||
"associated sections cannot have their own associated children");
|
||||
child->assocChildren = assocChildren;
|
||||
assocChildren = child;
|
||||
SectionChunk *prev = this;
|
||||
SectionChunk *next = assocChildren;
|
||||
for (; next != nullptr; prev = next, next = next->assocChildren) {
|
||||
if (next->getSectionName() <= child->getSectionName())
|
||||
break;
|
||||
}
|
||||
|
||||
// Insert child between prev and next.
|
||||
assert(prev->assocChildren == next);
|
||||
prev->assocChildren = child;
|
||||
child->assocChildren = next;
|
||||
}
|
||||
|
||||
static uint8_t getBaserelType(const coff_relocation &rel) {
|
||||
|
|
|
@ -293,8 +293,12 @@ public:
|
|||
|
||||
// Allow iteration over the associated child chunks for this section.
|
||||
llvm::iterator_range<AssociatedIterator> children() const {
|
||||
return llvm::make_range(AssociatedIterator(assocChildren),
|
||||
AssociatedIterator(nullptr));
|
||||
// Associated sections do not have children. The assocChildren field is
|
||||
// part of the parent's list of children.
|
||||
bool isAssoc = selection == llvm::COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE;
|
||||
return llvm::make_range(
|
||||
AssociatedIterator(isAssoc ? nullptr : assocChildren),
|
||||
AssociatedIterator(nullptr));
|
||||
}
|
||||
|
||||
// The section ID this chunk belongs to in its Obj.
|
||||
|
|
|
@ -0,0 +1,52 @@
|
|||
# REQUIRES: x86
|
||||
# RUN: llvm-mc %s -filetype=obj -triple=x86_64-windows-msvc -o %t.obj
|
||||
# RUN: lld-link %t.obj -export:foo -export:bar -dll -noentry -out:%t.dll -verbose 2>&1 | FileCheck %s
|
||||
# RUN: llvm-readobj --sections %t.dll | FileCheck %s --check-prefix=TEXT
|
||||
|
||||
# The order of the pdata and xdata sections here shouldn't matter. We should
|
||||
# still replace bar with foo.
|
||||
|
||||
# CHECK: ICF needed {{.*}} iterations
|
||||
# CHECK: Selected foo
|
||||
# CHECK: Removed bar
|
||||
|
||||
# We should only have five bytes of text.
|
||||
# TEXT: Name: .text
|
||||
# TEXT-NEXT: Size: 0x5
|
||||
|
||||
.section .text,"xr",discard,foo
|
||||
.globl foo
|
||||
foo:
|
||||
pushq %rbx
|
||||
pushq %rdi
|
||||
popq %rdi
|
||||
popq %rbx
|
||||
retq
|
||||
|
||||
|
||||
.section .pdata,"r",associative,foo
|
||||
.long foo
|
||||
.long 5
|
||||
.long foo_xdata@IMGREL
|
||||
|
||||
.section .xdata,"r",associative,foo
|
||||
foo_xdata:
|
||||
.long 42
|
||||
|
||||
.section .text,"xr",discard,bar
|
||||
.globl bar
|
||||
bar:
|
||||
pushq %rbx
|
||||
pushq %rdi
|
||||
popq %rdi
|
||||
popq %rbx
|
||||
retq
|
||||
|
||||
.section .xdata,"r",associative,bar
|
||||
bar_xdata:
|
||||
.long 42
|
||||
|
||||
.section .pdata,"r",associative,bar
|
||||
.long bar
|
||||
.long 5
|
||||
.long bar_xdata@IMGREL
|
|
@ -0,0 +1,48 @@
|
|||
# REQUIRES: x86
|
||||
# RUN: llvm-mc %s -filetype=obj -triple=x86_64-windows-msvc -o %t.obj
|
||||
# RUN: lld-link %t.obj -export:foo -export:bar -dll -noentry -out:%t.dll -merge:.xdata=.xdata -verbose 2>&1 | FileCheck %s
|
||||
# RUN: llvm-readobj --sections %t.dll | FileCheck %s --check-prefix=XDATA
|
||||
|
||||
# Test xdata can be merged when text and pdata differ. This test is structured
|
||||
# so that xdata comes after pdata, which makes xdata come before pdata in the
|
||||
# assocChildren linked list.
|
||||
|
||||
# CHECK: ICF needed {{.*}} iterations
|
||||
# CHECK: Selected
|
||||
# CHECK: Removed
|
||||
|
||||
# XDATA: Name: .xdata
|
||||
# XDATA-NEXT: VirtualSize: 0x4
|
||||
|
||||
.section .text,"xr",discard,foo
|
||||
.globl foo
|
||||
foo:
|
||||
pushq %rax
|
||||
popq %rax
|
||||
retq
|
||||
|
||||
.section .pdata,"r",associative,foo
|
||||
.long foo
|
||||
.long 5
|
||||
.long foo_xdata@IMGREL
|
||||
|
||||
|
||||
.section .xdata,"r",associative,foo
|
||||
foo_xdata:
|
||||
.long 42
|
||||
|
||||
.section .text,"xr",discard,bar
|
||||
.globl bar
|
||||
bar:
|
||||
pushq %rcx
|
||||
popq %rcx
|
||||
retq
|
||||
|
||||
.section .pdata,"r",associative,bar
|
||||
.long bar
|
||||
.long 5
|
||||
.long bar_xdata@IMGREL
|
||||
|
||||
.section .xdata,"r",associative,bar
|
||||
bar_xdata:
|
||||
.long 42
|
Loading…
Reference in New Issue