From e6c78eafdedfa419d72bc978d124d14bef56ff8e Mon Sep 17 00:00:00 2001 From: Peter Collingbourne Date: Fri, 27 Jul 2018 19:10:44 +0000 Subject: [PATCH] Reland r338088, "ELF: Make --print-icf-sections output deterministic." The xxHash64 function has been made unsigned-char-independent, so we can reland this change now. Original commit message: > The icf-safe.s test currently fails on 32-bit platforms because it uses > the --print-icf-sections flag and depends on the output appearing in > a specific order. However, this flag causes the output to depend on > the order of the sections in the Sections array, which depends on the > hash values returned from hash_combine, which happen to be different > for that test between 32-bit and 64-bit platforms. > > This change makes the output deterministic by using xxHash64 instead of > hash_combine. Differential Revision: https://reviews.llvm.org/D49877 llvm-svn: 338153 --- lld/ELF/ICF.cpp | 11 +++-------- lld/test/ELF/icf-safe.s | 48 ++++++++++++++++++++++++------------------------ 2 files changed, 27 insertions(+), 32 deletions(-) diff --git a/lld/ELF/ICF.cpp b/lld/ELF/ICF.cpp index ba413b13..53569c2 100644 --- a/lld/ELF/ICF.cpp +++ b/lld/ELF/ICF.cpp @@ -80,9 +80,10 @@ #include "SyntheticSections.h" #include "Writer.h" #include "lld/Common/Threads.h" -#include "llvm/ADT/Hashing.h" +#include "llvm/ADT/StringExtras.h" #include "llvm/BinaryFormat/ELF.h" #include "llvm/Object/ELF.h" +#include "llvm/Support/xxhash.h" #include #include @@ -155,12 +156,6 @@ private: }; } -// Returns a hash value for S. Note that the information about -// relocation targets is not included in the hash value. -template static uint32_t getHash(InputSection *S) { - return hash_combine(S->Flags, S->getSize(), S->NumRelocations, S->Data); -} - // Returns true if section S is subject of ICF. static bool isEligible(InputSection *S) { if (!S->Live || S->KeepUnique || !(S->Flags & SHF_ALLOC)) @@ -441,7 +436,7 @@ template void ICF::run() { // Initially, we use hash values to partition sections. parallelForEach(Sections, [&](InputSection *S) { // Set MSB to 1 to avoid collisions with non-hash IDs. - S->Class[0] = getHash(S) | (1U << 31); + S->Class[0] = xxHash64(toStringRef(S->Data)) | (1U << 31); }); // From now on, sections in Sections vector are ordered so that sections diff --git a/lld/test/ELF/icf-safe.s b/lld/test/ELF/icf-safe.s index b001fcc..2ced78f 100644 --- a/lld/test/ELF/icf-safe.s +++ b/lld/test/ELF/icf-safe.s @@ -10,10 +10,6 @@ # 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.l1) -# CHECK: selected section {{.*}}:(.rodata.l3) -# CHECK: removing identical section {{.*}}:(.rodata.l4) - # CHECK-NOT: selected section {{.*}}:(.text.f1) # CHECK: selected section {{.*}}:(.text.f3) # CHECK: removing identical section {{.*}}:(.text.f4) @@ -22,6 +18,10 @@ # 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) + # CHECK-NOT: selected section {{.*}}:(.rodata.g1) # CHECK: selected section {{.*}}:(.rodata.g3) # CHECK: removing identical section {{.*}}:(.rodata.g4) @@ -30,26 +30,26 @@ # With --icf=all address-significance implies keep-unique only for rodata, not # text. -# 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.l1) +# ALL: selected section {{.*}}:(.rodata.l3) +# ALL: removing identical section {{.*}}:(.rodata.l4) + # ALL-NOT: selected section {{.*}}:(.rodata.g1) # ALL: selected section {{.*}}:(.rodata.g3) # ALL: removing identical section {{.*}}:(.rodata.g4) +# 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) + # 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 # symbols (thus nor can anything refer to it via a relocation, making it safe to @@ -58,36 +58,36 @@ # 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 {{.*}}:(.text) # EXPORT: removing identical section {{.*}}:(.text) # EXPORT-NOT: selected section +# EXPORT: selected section {{.*}}:(.rodata.l3) +# EXPORT: removing identical section {{.*}}:(.rodata.l4) +# EXPORT-NOT: selected section # 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.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-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-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.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 # OBJCOPY: --icf=safe is incompatible with object files created using objcopy or ld -r -- 2.7.4