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 (#129795)
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:
parent
eaca60d1a9
commit
5f21ee20f8
lld
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user