0
0
mirror of https://github.com/llvm/llvm-project.git synced 2025-04-21 12:56:52 +00:00

[LLD][ELF] Don't spill to same memory region ()

This prevents useless spills to the same memory region from causing
spilling to take too many passes to converge.

Handling this at spilling time allows us to relax the generation of
spill sections; specifically, multiple spills can now be generated per
output section. This should be fairly benign for performance, and it
would eventually allow linker scripts to express things like holes or
minimum addresses for parts of output sections. The linker could then
spill within an output section whenever address constraints are
violated.
This commit is contained in:
Daniel Thornburgh 2025-03-11 10:46:10 -07:00 committed by GitHub
parent eaca60d1a9
commit 5f21ee20f8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 125 additions and 9 deletions
lld
ELF
test/ELF/linkerscript

@ -563,7 +563,7 @@ LinkerScript::computeInputSections(const InputSectionDescription *cmd,
continue;
if (!cmd->matchesFile(*sec->file) || pat.excludesFile(*sec->file) ||
sec->parent == &outCmd || !flagsMatch(sec))
!flagsMatch(sec))
continue;
if (sec->parent) {
@ -626,7 +626,7 @@ LinkerScript::computeInputSections(const InputSectionDescription *cmd,
for (InputSectionDescription *isd : scd->sc.commands) {
for (InputSectionBase *sec : isd->sectionBases) {
if (sec->parent == &outCmd || !flagsMatch(sec))
if (!flagsMatch(sec))
continue;
bool isSpill = sec->parent && isa<OutputSection>(sec->parent);
if (!sec->parent || (isSpill && outCmd.name == "/DISCARD/")) {
@ -1585,16 +1585,32 @@ bool LinkerScript::spillSections() {
if (isa<PotentialSpillSection>(isec))
continue;
// Find the next potential spill location and remove it from the list.
auto it = potentialSpillLists.find(isec);
if (it == potentialSpillLists.end())
continue;
break;
// Consume spills until finding one that might help, then consume it.
PotentialSpillList &list = it->second;
PotentialSpillSection *spill = list.head;
if (spill->next)
list.head = spill->next;
else
potentialSpillLists.erase(isec);
PotentialSpillSection *spill;
for (spill = list.head; spill; spill = spill->next) {
if (list.head->next)
list.head = spill->next;
else
potentialSpillLists.erase(isec);
// Spills to the same region that overflowed cannot help.
if (hasRegionOverflowed(osec->memRegion) &&
spill->getParent()->memRegion == osec->memRegion)
continue;
if (hasRegionOverflowed(osec->lmaRegion) &&
spill->getParent()->lmaRegion == osec->lmaRegion)
continue;
// This spill might resolve the overflow.
break;
}
if (!spill)
continue;
// Replace the next spill location with the spilled section and adjust
// its properties to match the new location. Note that the alignment of

@ -450,3 +450,103 @@ SECTIONS {
# TO-DISCARD: error: section '.two_byte_section' cannot spill from/to /DISCARD/
# TO-DISCARD-WARN: warning: section '.two_byte_section' cannot spill from/to /DISCARD/
#--- same-mem-region.lds
## Spills to the same memory region that overflowed do not consume address assignment passes.
MEMORY {
a : ORIGIN = 0, LENGTH = 0
b : ORIGIN = 0, LENGTH = 3
c : ORIGIN = 3, LENGTH = 3
d : ORIGIN = 6, LENGTH = 3
}
SECTIONS {
CLASS(class) { *(.one_byte_section .two_byte_section) }
.a00 : { CLASS(class) } >a AT>c
.a01 : { CLASS(class) } >a AT>d
.a02 : { CLASS(class) } >a AT>d
.a03 : { CLASS(class) } >a AT>d
.a04 : { CLASS(class) } >a AT>d
.a05 : { CLASS(class) } >a AT>d
.a06 : { CLASS(class) } >a AT>d
.a07 : { CLASS(class) } >a AT>d
.a08 : { CLASS(class) } >a AT>d
.a09 : { CLASS(class) } >a AT>d
.a10 : { CLASS(class) } >a AT>d
.a11 : { CLASS(class) } >a AT>d
.a12 : { CLASS(class) } >a AT>d
.a13 : { CLASS(class) } >a AT>d
.a14 : { CLASS(class) } >a AT>d
.a15 : { CLASS(class) } >a AT>d
.a16 : { CLASS(class) } >a AT>d
.a17 : { CLASS(class) } >a AT>d
.a18 : { CLASS(class) } >a AT>d
.a19 : { CLASS(class) } >a AT>d
.a20 : { CLASS(class) } >a AT>d
.a21 : { CLASS(class) } >a AT>d
.a22 : { CLASS(class) } >a AT>d
.a23 : { CLASS(class) } >a AT>d
.a24 : { CLASS(class) } >a AT>d
.a25 : { CLASS(class) } >a AT>d
.a26 : { CLASS(class) } >a AT>d
.a27 : { CLASS(class) } >a AT>d
.a28 : { CLASS(class) } >a AT>d
.a29 : { CLASS(class) } >a AT>d
.a30 : { CLASS(class) } >a AT>d
.b : { CLASS(class) } >b AT>d
}
# RUN: ld.lld -T same-mem-region.lds -o same-mem-region spill.o
# RUN: llvm-readelf -S same-mem-region | FileCheck %s --check-prefix=SAME-MEM-REGION
# SAME-MEM-REGION: Name Type Address Off Size
# SAME-MEM-REGION: .b PROGBITS 0000000000000000 001000 000003
#--- same-lma-region.lds
## Spills to the same load region that overflowed do not consume address assignment passes.
MEMORY {
a : ORIGIN = 0, LENGTH = 0
b : ORIGIN = 0, LENGTH = 3
c : ORIGIN = 3, LENGTH = 3
d : ORIGIN = 6, LENGTH = 3
}
SECTIONS {
CLASS(class) { *(.one_byte_section .two_byte_section) }
.a00 : { CLASS(class) } >c AT>a
.a01 : { CLASS(class) } >d AT>a
.a02 : { CLASS(class) } >d AT>a
.a03 : { CLASS(class) } >d AT>a
.a04 : { CLASS(class) } >d AT>a
.a05 : { CLASS(class) } >d AT>a
.a06 : { CLASS(class) } >d AT>a
.a07 : { CLASS(class) } >d AT>a
.a08 : { CLASS(class) } >d AT>a
.a09 : { CLASS(class) } >d AT>a
.a10 : { CLASS(class) } >d AT>a
.a11 : { CLASS(class) } >d AT>a
.a12 : { CLASS(class) } >d AT>a
.a13 : { CLASS(class) } >d AT>a
.a14 : { CLASS(class) } >d AT>a
.a15 : { CLASS(class) } >d AT>a
.a16 : { CLASS(class) } >d AT>a
.a17 : { CLASS(class) } >d AT>a
.a18 : { CLASS(class) } >d AT>a
.a19 : { CLASS(class) } >d AT>a
.a20 : { CLASS(class) } >d AT>a
.a21 : { CLASS(class) } >d AT>a
.a22 : { CLASS(class) } >d AT>a
.a23 : { CLASS(class) } >d AT>a
.a24 : { CLASS(class) } >d AT>a
.a25 : { CLASS(class) } >d AT>a
.a26 : { CLASS(class) } >d AT>a
.a27 : { CLASS(class) } >d AT>a
.a28 : { CLASS(class) } >d AT>a
.a29 : { CLASS(class) } >d AT>a
.a30 : { CLASS(class) } >d AT>a
.b : { CLASS(class) } >d AT>b
}
# RUN: ld.lld -T same-lma-region.lds -o same-lma-region spill.o
# RUN: llvm-readelf -S same-lma-region | FileCheck %s --check-prefix=SAME-LMA-REGION
# SAME-LMA-REGION: Name Type Address Off Size
# SAME-LMA-REGION: .b PROGBITS 0000000000000006 001006 000003