Index: lld/ELF/ICF.cpp =================================================================== --- lld/ELF/ICF.cpp +++ lld/ELF/ICF.cpp @@ -219,10 +219,12 @@ size_t mid = bound - sections.begin(); // Now we split [Begin, End) into [Begin, Mid) and [Mid, End) by - // updating the sections in [Begin, Mid). We use Mid as an equivalence - // class ID because every group ends with a unique index. + // updating the sections in [Begin, Mid). We use Mid as the basis for + // the equivalence class ID because every group ends with a unique index. + // Set MSB to 1 to avoid equality with unique IDs. + uint32_t eqClass = mid | (1U << 31); for (size_t i = begin; i < mid; ++i) - sections[i]->eqClass[next] = mid; + sections[i]->eqClass[next] = eqClass; // If we created a group, we need to iterate the main loop again. if (mid != end) @@ -443,7 +445,7 @@ if (auto *relSec = dyn_cast_or_null(d->section)) hash += relSec->eqClass[cnt % 2]; } - // Set MSB to 1 to avoid collisions with non-hash IDs. + // Set MSB to 1 to avoid collisions with unique IDs. isec->eqClass[(cnt + 1) % 2] = hash | (1U << 31); } @@ -471,18 +473,24 @@ uint32_t uniqueId = 0; for (Partition &part : partitions) part.ehFrame->iterateFDEWithLSDA( - [&](InputSection &s) { s.eqClass[0] = ++uniqueId; }); + [&](InputSection &s) { s.eqClass[0] = s.eqClass[1] = ++uniqueId; }); // Collect sections to merge. for (InputSectionBase *sec : inputSections) { auto *s = cast(sec); - if (isEligible(s) && s->eqClass[0] == 0) - sections.push_back(s); + if (s->eqClass[0] == 0) { + if (isEligible(s)) + sections.push_back(s); + else + s->eqClass[0] = s->eqClass[1] = ++uniqueId; + } } // Initially, we use hash values to partition sections. - parallelForEach( - sections, [&](InputSection *s) { s->eqClass[0] = xxHash64(s->data()); }); + parallelForEach(sections, [&](InputSection *s) { + // Set MSB to 1 to avoid collisions with unique IDs. + s->eqClass[0] = xxHash64(s->data()) | (1U << 31); + }); // Perform 2 rounds of relocation hash propagation. 2 is an empirical value to // reduce the average sizes of equivalence classes, i.e. segregate() which has @@ -502,7 +510,8 @@ return a->eqClass[0] < b->eqClass[0]; }); - // Compare static contents and assign unique IDs for each static content. + // Compare static contents and assign unique equivalence class IDs for each + // static content. forEachClass([&](size_t begin, size_t end) { segregate(begin, end, true); }); // Split groups by comparing relocations until convergence is obtained. Index: lld/test/ELF/icf18.s =================================================================== --- /dev/null +++ lld/test/ELF/icf18.s @@ -0,0 +1,44 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o +# RUN: ld.lld %t.o -o /dev/null --keep-unique fu --icf=all --print-icf-sections | FileCheck %s + +## Check that ICF is able to merge equivalent sections with relocations to +## different symbols, e.g. aliases, that refer to the same section which is +## ineligible for ICF. + +# CHECK: selected section {{.*}}:(.text.f1) +# CHECK: removing identical section {{.*}}:(.text.f2) +# CHECK: removing identical section {{.*}}:(.text.f3) +# CHECK: selected section {{.*}}:(.text.f4) +# CHECK: removing identical section {{.*}}:(.text.f5) + +.globl d, d_alias, fu, f1, f2, f3, f4, f5 + +.section .data.d,"aw",@progbits +d: +d_alias: +.long 42 + +.section .text.fu,"ax",@progbits +fu: + nop + +.section .text.f1,"ax",@progbits +f1: +.quad d + +.section .text.f2,"ax",@progbits +f2: +.quad d_alias + +.section .text.f3,"ax",@progbits +f3: +.quad .data.d + +.section .text.f4,"ax",@progbits +f4: +.quad fu + +.section .text.f5,"ax",@progbits +f5: +.quad .text.fu