summaryrefslogtreecommitdiff
path: root/ELF/ICF.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'ELF/ICF.cpp')
-rw-r--r--ELF/ICF.cpp32
1 files changed, 28 insertions, 4 deletions
diff --git a/ELF/ICF.cpp b/ELF/ICF.cpp
index 075938bd16b91..e917ae76a689e 100644
--- a/ELF/ICF.cpp
+++ b/ELF/ICF.cpp
@@ -252,7 +252,10 @@ bool ICF<ELFT>::constantEq(const InputSection *SecA, ArrayRef<RelTy> RA,
auto *DA = dyn_cast<Defined>(&SA);
auto *DB = dyn_cast<Defined>(&SB);
- if (!DA || !DB)
+
+ // Placeholder symbols generated by linker scripts look the same now but
+ // may have different values later.
+ if (!DA || !DB || DA->ScriptDefined || DB->ScriptDefined)
return false;
// Relocations referring to absolute symbols are constant-equal if their
@@ -298,7 +301,7 @@ bool ICF<ELFT>::constantEq(const InputSection *SecA, ArrayRef<RelTy> RA,
template <class ELFT>
bool ICF<ELFT>::equalsConstant(const InputSection *A, const InputSection *B) {
if (A->NumRelocations != B->NumRelocations || A->Flags != B->Flags ||
- A->getSize() != B->getSize() || A->Data != B->Data)
+ A->getSize() != B->getSize() || A->data() != B->data())
return false;
// If two sections have different output sections, we cannot merge them.
@@ -420,6 +423,21 @@ void ICF<ELFT>::forEachClass(llvm::function_ref<void(size_t, size_t)> Fn) {
++Cnt;
}
+// Combine the hashes of the sections referenced by the given section into its
+// hash.
+template <class ELFT, class RelTy>
+static void combineRelocHashes(InputSection *IS, ArrayRef<RelTy> Rels) {
+ uint32_t Hash = IS->Class[1];
+ for (RelTy Rel : Rels) {
+ Symbol &S = IS->template getFile<ELFT>()->getRelocTargetSym(Rel);
+ if (auto *D = dyn_cast<Defined>(&S))
+ if (auto *RelSec = dyn_cast_or_null<InputSection>(D->Section))
+ Hash ^= RelSec->Class[1];
+ }
+ // Set MSB to 1 to avoid collisions with non-hash IDs.
+ IS->Class[0] = Hash | (1U << 31);
+}
+
static void print(const Twine &S) {
if (Config->PrintIcfSections)
message(S);
@@ -435,8 +453,14 @@ template <class ELFT> void ICF<ELFT>::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] = xxHash64(S->Data) | (1U << 31);
+ S->Class[1] = xxHash64(S->data());
+ });
+
+ parallelForEach(Sections, [&](InputSection *S) {
+ if (S->AreRelocsRela)
+ combineRelocHashes<ELFT>(S, S->template relas<ELFT>());
+ else
+ combineRelocHashes<ELFT>(S, S->template rels<ELFT>());
});
// From now on, sections in Sections vector are ordered so that sections