Skip to content

Commit 5f21ee2

Browse files
authored
[LLD][ELF] Don't spill to same memory region (llvm#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.
1 parent eaca60d commit 5f21ee2

File tree

2 files changed

+125
-9
lines changed

2 files changed

+125
-9
lines changed

lld/ELF/LinkerScript.cpp

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -563,7 +563,7 @@ LinkerScript::computeInputSections(const InputSectionDescription *cmd,
563563
continue;
564564

565565
if (!cmd->matchesFile(*sec->file) || pat.excludesFile(*sec->file) ||
566-
sec->parent == &outCmd || !flagsMatch(sec))
566+
!flagsMatch(sec))
567567
continue;
568568

569569
if (sec->parent) {
@@ -626,7 +626,7 @@ LinkerScript::computeInputSections(const InputSectionDescription *cmd,
626626

627627
for (InputSectionDescription *isd : scd->sc.commands) {
628628
for (InputSectionBase *sec : isd->sectionBases) {
629-
if (sec->parent == &outCmd || !flagsMatch(sec))
629+
if (!flagsMatch(sec))
630630
continue;
631631
bool isSpill = sec->parent && isa<OutputSection>(sec->parent);
632632
if (!sec->parent || (isSpill && outCmd.name == "/DISCARD/")) {
@@ -1585,16 +1585,32 @@ bool LinkerScript::spillSections() {
15851585
if (isa<PotentialSpillSection>(isec))
15861586
continue;
15871587

1588-
// Find the next potential spill location and remove it from the list.
15891588
auto it = potentialSpillLists.find(isec);
15901589
if (it == potentialSpillLists.end())
1591-
continue;
1590+
break;
1591+
1592+
// Consume spills until finding one that might help, then consume it.
15921593
PotentialSpillList &list = it->second;
1593-
PotentialSpillSection *spill = list.head;
1594-
if (spill->next)
1595-
list.head = spill->next;
1596-
else
1597-
potentialSpillLists.erase(isec);
1594+
PotentialSpillSection *spill;
1595+
for (spill = list.head; spill; spill = spill->next) {
1596+
if (list.head->next)
1597+
list.head = spill->next;
1598+
else
1599+
potentialSpillLists.erase(isec);
1600+
1601+
// Spills to the same region that overflowed cannot help.
1602+
if (hasRegionOverflowed(osec->memRegion) &&
1603+
spill->getParent()->memRegion == osec->memRegion)
1604+
continue;
1605+
if (hasRegionOverflowed(osec->lmaRegion) &&
1606+
spill->getParent()->lmaRegion == osec->lmaRegion)
1607+
continue;
1608+
1609+
// This spill might resolve the overflow.
1610+
break;
1611+
}
1612+
if (!spill)
1613+
continue;
15981614

15991615
// Replace the next spill location with the spilled section and adjust
16001616
// its properties to match the new location. Note that the alignment of

lld/test/ELF/linkerscript/section-class.test

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -450,3 +450,103 @@ SECTIONS {
450450

451451
# TO-DISCARD: error: section '.two_byte_section' cannot spill from/to /DISCARD/
452452
# TO-DISCARD-WARN: warning: section '.two_byte_section' cannot spill from/to /DISCARD/
453+
454+
#--- same-mem-region.lds
455+
## Spills to the same memory region that overflowed do not consume address assignment passes.
456+
MEMORY {
457+
a : ORIGIN = 0, LENGTH = 0
458+
b : ORIGIN = 0, LENGTH = 3
459+
c : ORIGIN = 3, LENGTH = 3
460+
d : ORIGIN = 6, LENGTH = 3
461+
}
462+
SECTIONS {
463+
CLASS(class) { *(.one_byte_section .two_byte_section) }
464+
.a00 : { CLASS(class) } >a AT>c
465+
.a01 : { CLASS(class) } >a AT>d
466+
.a02 : { CLASS(class) } >a AT>d
467+
.a03 : { CLASS(class) } >a AT>d
468+
.a04 : { CLASS(class) } >a AT>d
469+
.a05 : { CLASS(class) } >a AT>d
470+
.a06 : { CLASS(class) } >a AT>d
471+
.a07 : { CLASS(class) } >a AT>d
472+
.a08 : { CLASS(class) } >a AT>d
473+
.a09 : { CLASS(class) } >a AT>d
474+
.a10 : { CLASS(class) } >a AT>d
475+
.a11 : { CLASS(class) } >a AT>d
476+
.a12 : { CLASS(class) } >a AT>d
477+
.a13 : { CLASS(class) } >a AT>d
478+
.a14 : { CLASS(class) } >a AT>d
479+
.a15 : { CLASS(class) } >a AT>d
480+
.a16 : { CLASS(class) } >a AT>d
481+
.a17 : { CLASS(class) } >a AT>d
482+
.a18 : { CLASS(class) } >a AT>d
483+
.a19 : { CLASS(class) } >a AT>d
484+
.a20 : { CLASS(class) } >a AT>d
485+
.a21 : { CLASS(class) } >a AT>d
486+
.a22 : { CLASS(class) } >a AT>d
487+
.a23 : { CLASS(class) } >a AT>d
488+
.a24 : { CLASS(class) } >a AT>d
489+
.a25 : { CLASS(class) } >a AT>d
490+
.a26 : { CLASS(class) } >a AT>d
491+
.a27 : { CLASS(class) } >a AT>d
492+
.a28 : { CLASS(class) } >a AT>d
493+
.a29 : { CLASS(class) } >a AT>d
494+
.a30 : { CLASS(class) } >a AT>d
495+
.b : { CLASS(class) } >b AT>d
496+
}
497+
498+
# RUN: ld.lld -T same-mem-region.lds -o same-mem-region spill.o
499+
# RUN: llvm-readelf -S same-mem-region | FileCheck %s --check-prefix=SAME-MEM-REGION
500+
501+
# SAME-MEM-REGION: Name Type Address Off Size
502+
# SAME-MEM-REGION: .b PROGBITS 0000000000000000 001000 000003
503+
504+
#--- same-lma-region.lds
505+
## Spills to the same load region that overflowed do not consume address assignment passes.
506+
MEMORY {
507+
a : ORIGIN = 0, LENGTH = 0
508+
b : ORIGIN = 0, LENGTH = 3
509+
c : ORIGIN = 3, LENGTH = 3
510+
d : ORIGIN = 6, LENGTH = 3
511+
}
512+
SECTIONS {
513+
CLASS(class) { *(.one_byte_section .two_byte_section) }
514+
.a00 : { CLASS(class) } >c AT>a
515+
.a01 : { CLASS(class) } >d AT>a
516+
.a02 : { CLASS(class) } >d AT>a
517+
.a03 : { CLASS(class) } >d AT>a
518+
.a04 : { CLASS(class) } >d AT>a
519+
.a05 : { CLASS(class) } >d AT>a
520+
.a06 : { CLASS(class) } >d AT>a
521+
.a07 : { CLASS(class) } >d AT>a
522+
.a08 : { CLASS(class) } >d AT>a
523+
.a09 : { CLASS(class) } >d AT>a
524+
.a10 : { CLASS(class) } >d AT>a
525+
.a11 : { CLASS(class) } >d AT>a
526+
.a12 : { CLASS(class) } >d AT>a
527+
.a13 : { CLASS(class) } >d AT>a
528+
.a14 : { CLASS(class) } >d AT>a
529+
.a15 : { CLASS(class) } >d AT>a
530+
.a16 : { CLASS(class) } >d AT>a
531+
.a17 : { CLASS(class) } >d AT>a
532+
.a18 : { CLASS(class) } >d AT>a
533+
.a19 : { CLASS(class) } >d AT>a
534+
.a20 : { CLASS(class) } >d AT>a
535+
.a21 : { CLASS(class) } >d AT>a
536+
.a22 : { CLASS(class) } >d AT>a
537+
.a23 : { CLASS(class) } >d AT>a
538+
.a24 : { CLASS(class) } >d AT>a
539+
.a25 : { CLASS(class) } >d AT>a
540+
.a26 : { CLASS(class) } >d AT>a
541+
.a27 : { CLASS(class) } >d AT>a
542+
.a28 : { CLASS(class) } >d AT>a
543+
.a29 : { CLASS(class) } >d AT>a
544+
.a30 : { CLASS(class) } >d AT>a
545+
.b : { CLASS(class) } >d AT>b
546+
}
547+
548+
# RUN: ld.lld -T same-lma-region.lds -o same-lma-region spill.o
549+
# RUN: llvm-readelf -S same-lma-region | FileCheck %s --check-prefix=SAME-LMA-REGION
550+
551+
# SAME-LMA-REGION: Name Type Address Off Size
552+
# SAME-LMA-REGION: .b PROGBITS 0000000000000006 001006 000003

0 commit comments

Comments
 (0)