Index: lld/ELF/ICF.cpp =================================================================== --- lld/ELF/ICF.cpp +++ lld/ELF/ICF.cpp @@ -425,11 +425,6 @@ ++Cnt; } -static void print(const Twine &S) { - if (Config->PrintIcfSections) - message(S); -} - // The main function of ICF. template void ICF::run() { // Collect sections to merge. @@ -463,13 +458,20 @@ log("ICF needed " + Twine(Cnt) + " iterations"); + std::vector Msgs; + if (Config->PrintIcfSections) + Msgs.resize(Sections.size()); + // Merge sections by the equivalence class. forEachClassRange(0, Sections.size(), [&](size_t Begin, size_t End) { if (End - Begin == 1) return; - print("selected section " + toString(Sections[Begin])); + if (Config->PrintIcfSections) + Msgs[Begin] = "selected section " + toString(Sections[Begin]) + "\n"; for (size_t I = Begin + 1; I < End; ++I) { - print(" removing identical section " + toString(Sections[I])); + if (Config->PrintIcfSections) + Msgs[Begin] += + " removing identical section " + toString(Sections[I]) + "\n"; Sections[Begin]->replace(Sections[I]); // At this point we know sections merged are fully identical and hence @@ -479,6 +481,12 @@ IS->Live = false; } }); + + if (Config->PrintIcfSections) { + std::sort(Msgs.begin(), Msgs.end()); + for (std::string &S : Msgs) + llvm::outs() << S; + } } // ICF entry point function. Index: lld/test/ELF/icf-safe.s =================================================================== --- lld/test/ELF/icf-safe.s +++ lld/test/ELF/icf-safe.s @@ -10,6 +10,14 @@ # RUN: ld.lld %t1.o %t2.o -o %t2 --icf=all --print-icf-sections --export-dynamic | FileCheck --check-prefix=ALL-EXPORT %s # RUN: ld.lld %t1copy.o -o %t4 --icf=safe 2>&1 | FileCheck --check-prefix=OBJCOPY %s +# CHECK-NOT: selected section {{.*}}:(.rodata.g1) +# CHECK: selected section {{.*}}:(.rodata.g3) +# CHECK: removing identical section {{.*}}:(.rodata.g4) + +# CHECK-NOT: selected section {{.*}}:(.rodata.h1) +# CHECK: selected section {{.*}}:(.rodata.h3) +# CHECK: removing identical section {{.*}}:(.rodata.h4) + # CHECK-NOT: selected section {{.*}}:(.rodata.l1) # CHECK: selected section {{.*}}:(.rodata.l3) # CHECK: removing identical section {{.*}}:(.rodata.l4) @@ -18,37 +26,29 @@ # CHECK: selected section {{.*}}:(.text.f3) # CHECK: removing identical section {{.*}}:(.text.f4) -# CHECK-NOT: selected section {{.*}}:(.rodata.h1) -# CHECK: selected section {{.*}}:(.rodata.h3) -# CHECK: removing identical section {{.*}}:(.rodata.h4) - -# CHECK-NOT: selected section {{.*}}:(.rodata.g1) -# CHECK: selected section {{.*}}:(.rodata.g3) -# CHECK: removing identical section {{.*}}:(.rodata.g4) - # CHECK-NOT: selected section {{.*}}:(.text.non_addrsig{{.}}) # With --icf=all address-significance implies keep-unique only for rodata, not # text. +# ALL-NOT: selected section {{.*}}:(.rodata.g1) +# ALL: selected section {{.*}}:(.rodata.g3) +# ALL: removing identical section {{.*}}:(.rodata.g4) + +# ALL-NOT: selected section {{.*}}:(.rodata.h1) +# ALL: selected section {{.*}}:(.rodata.h3) +# ALL: removing identical section {{.*}}:(.rodata.h4) + # ALL-NOT: selected section {{.*}}:(.rodata.l1) # ALL: selected section {{.*}}:(.rodata.l3) # ALL: removing identical section {{.*}}:(.rodata.l4) -# ALL: selected section {{.*}}:(.text.f3) -# ALL: removing identical section {{.*}}:(.text.f4) - # ALL: selected section {{.*}}:(.text.f1) # ALL: removing identical section {{.*}}:(.text.f2) # ALL: removing identical section {{.*}}:(.text.non_addrsig1) # ALL: removing identical section {{.*}}:(.text.non_addrsig2) -# ALL-NOT: selected section {{.*}}:(.rodata.h1) -# ALL: selected section {{.*}}:(.rodata.h3) -# ALL: removing identical section {{.*}}:(.rodata.h4) - -# ALL-NOT: selected section {{.*}}:(.rodata.g1) -# ALL: selected section {{.*}}:(.rodata.g3) -# ALL: removing identical section {{.*}}:(.rodata.g4) +# ALL: selected section {{.*}}:(.text.f3) +# ALL: removing identical section {{.*}}:(.text.f4) # llvm-mc normally emits an empty .text section into every object file. Since # nothing actually refers to it via a relocation, it doesn't have any associated @@ -58,12 +58,12 @@ # STB_LOCAL or STV_HIDDEN symbols. The dynsym entries should have prevented # anything else from being merged. # EXPORT-NOT: selected section -# EXPORT: selected section {{.*}}:(.rodata.l3) -# EXPORT: removing identical section {{.*}}:(.rodata.l4) -# EXPORT-NOT: selected section # EXPORT: selected section {{.*}}:(.rodata.h3) # EXPORT: removing identical section {{.*}}:(.rodata.h4) # EXPORT-NOT: selected section +# EXPORT: selected section {{.*}}:(.rodata.l3) +# EXPORT: removing identical section {{.*}}:(.rodata.l4) +# EXPORT-NOT: selected section # EXPORT: selected section {{.*}}:(.text) # EXPORT: removing identical section {{.*}}:(.text) # EXPORT-NOT: selected section @@ -71,22 +71,22 @@ # If --icf=all is specified when exporting we can also merge the exported text # sections, but not the exported rodata. # ALL-EXPORT-NOT: selected section +# ALL-EXPORT: selected section {{.*}}:(.rodata.h3) +# ALL-EXPORT: removing identical section {{.*}}:(.rodata.h4) +# ALL-EXPORT-NOT: selected section # ALL-EXPORT: selected section {{.*}}:(.rodata.l3) # ALL-EXPORT: removing identical section {{.*}}:(.rodata.l4) # ALL-EXPORT-NOT: selected section -# ALL-EXPORT: selected section {{.*}}:(.text.f3) -# ALL-EXPORT: removing identical section {{.*}}:(.text.f4) +# ALL-EXPORT: selected section {{.*}}:(.text) +# ALL-EXPORT: removing identical section {{.*}}:(.text) # ALL-EXPORT-NOT: selected section # ALL-EXPORT: selected section {{.*}}:(.text.f1) # ALL-EXPORT: removing identical section {{.*}}:(.text.f2) # ALL-EXPORT: removing identical section {{.*}}:(.text.non_addrsig1) # ALL-EXPORT: removing identical section {{.*}}:(.text.non_addrsig2) # ALL-EXPORT-NOT: selected section -# ALL-EXPORT: selected section {{.*}}:(.rodata.h3) -# ALL-EXPORT: removing identical section {{.*}}:(.rodata.h4) -# ALL-EXPORT-NOT: selected section -# ALL-EXPORT: selected section {{.*}}:(.text) -# ALL-EXPORT: removing identical section {{.*}}:(.text) +# ALL-EXPORT: selected section {{.*}}:(.text.f3) +# ALL-EXPORT: removing identical section {{.*}}:(.text.f4) # ALL-EXPORT-NOT: selected section # OBJCOPY: --icf=safe is incompatible with object files created using objcopy or ld -r Index: lld/test/ELF/print-icf.s =================================================================== --- lld/test/ELF/print-icf.s +++ lld/test/ELF/print-icf.s @@ -6,13 +6,13 @@ # RUN: ld.lld %t %t1 -o %t2 --icf=all --no-print-icf-sections --print-icf-sections | FileCheck %s # RUN: ld.lld %t %t1 -o %t2 --icf=all --print-icf-sections --no-print-icf-sections | FileCheck -allow-empty -check-prefix=PRINT %s -# CHECK: selected section {{.*}}:(.text.f2) -# CHECK: removing identical section {{.*}}:(.text.f4) -# CHECK: removing identical section {{.*}}:(.text.f7) # CHECK: selected section {{.*}}:(.text.f1) # CHECK: removing identical section {{.*}}:(.text.f3) # CHECK: removing identical section {{.*}}:(.text.f5) # CHECK: removing identical section {{.*}}:(.text.f6) +# CHECK: selected section {{.*}}:(.text.f2) +# CHECK: removing identical section {{.*}}:(.text.f4) +# CHECK: removing identical section {{.*}}:(.text.f7) # PRINT-NOT: selected # PRINT-NOT: removing