7777#include " InputFiles.h"
7878#include " LinkerScript.h"
7979#include " OutputSections.h"
80+ #include " Relocations.h"
8081#include " SymbolTable.h"
8182#include " Symbols.h"
8283#include " SyntheticSections.h"
84+ #include " Target.h"
8385#include " llvm/ADT/EquivalenceClasses.h"
8486#include " llvm/BinaryFormat/ELF.h"
8587#include " llvm/Object/ELF.h"
@@ -105,18 +107,23 @@ template <class ELFT> class ICF {
105107 void segregate (size_t begin, size_t end, uint32_t eqClassBase, bool constant);
106108
107109 template <class RelTy >
108- bool constantEq (const InputSection *a, Relocs<RelTy> relsA,
109- const InputSection *b, Relocs<RelTy> relsB);
110+ bool constantEq (InputSection *a, Relocs<RelTy> relsA, InputSection *b ,
111+ Relocs<RelTy> relsB);
110112
111113 template <class RelTy >
112114 bool variableEq (const InputSection *a, Relocs<RelTy> relsA,
113115 const InputSection *b, Relocs<RelTy> relsB);
114116
115- bool equalsConstant (const InputSection *a, const InputSection *b);
117+ bool equalsConstant (InputSection *a, InputSection *b);
116118 bool equalsVariable (const InputSection *a, const InputSection *b);
117119
118120 size_t findBoundary (size_t begin, size_t end);
119121
122+ // A relocation with side-effects is considered non-trivial. Eg: relocation
123+ // creates GOT entry or TLS slot.
124+ template <class RelTy >
125+ bool isTrivialRelocation (InputSection *a, Symbol &s, RelTy reloc);
126+
120127 void forEachClassRange (size_t begin, size_t end,
121128 llvm::function_ref<void (size_t , size_t )> fn);
122129
@@ -235,11 +242,30 @@ void ICF<ELFT>::segregate(size_t begin, size_t end, uint32_t eqClassBase,
235242 }
236243}
237244
245+ template <class ELFT >
246+ template <class RelTy >
247+ bool ICF<ELFT>::isTrivialRelocation(InputSection *a, Symbol &s, RelTy reloc) {
248+ OffsetGetter getter (*a);
249+ uint64_t offset = getter.get (ctx, reloc.r_offset );
250+ RelExpr expr = ctx.target ->getRelExpr (reloc.getType (ctx.arg .isMips64EL ), s,
251+ a->content ().data () + offset);
252+
253+ if (needsGot (expr) || needsTls (s, expr))
254+ return false ;
255+ return true ;
256+ }
257+
258+ // Two symbols referenced by relocations can be merged together safely
259+ // when their addends are same.
260+ static bool canMergeSymbols (uint64_t addA, uint64_t addB) {
261+ return addA == addB;
262+ }
263+
238264// Compare two lists of relocations.
239265template <class ELFT >
240266template <class RelTy >
241- bool ICF<ELFT>::constantEq(const InputSection *secA, Relocs<RelTy> ra,
242- const InputSection *secB, Relocs<RelTy> rb) {
267+ bool ICF<ELFT>::constantEq(InputSection *secA, Relocs<RelTy> ra,
268+ InputSection *secB, Relocs<RelTy> rb) {
243269 if (ra.size () != rb.size ())
244270 return false ;
245271 auto rai = ra.begin (), rae = ra.end (), rbi = rb.begin ();
@@ -287,13 +313,14 @@ bool ICF<ELFT>::constantEq(const InputSection *secA, Relocs<RelTy> ra,
287313 // Relocations referring to InputSections are constant-equal if their
288314 // section offsets are equal.
289315 if (isa<InputSection>(da->section )) {
290- // Our symbol folding logic later merges symbols in two folded sections
291- // We should not merge sections in the first place if their symbols
292- // cannot be merged together.
293- bool canMergeSymbols = addA == addB;
294- if (da->value + addA == db->value + addB && canMergeSymbols)
316+ if (da->value + addA == db->value + addB) {
317+ // For non-trivial relocations, if we cannot merge symbols together,
318+ // we must not merge them.
319+ if (!isTrivialRelocation (secA, sa, *rai) &&
320+ !canMergeSymbols (addA, addB))
321+ return false ;
295322 continue ;
296- return false ;
323+ }
297324 }
298325
299326 // Relocations referring to MergeInputSections are constant-equal if their
@@ -319,7 +346,7 @@ bool ICF<ELFT>::constantEq(const InputSection *secA, Relocs<RelTy> ra,
319346// Compare "non-moving" part of two InputSections, namely everything
320347// except relocation targets.
321348template <class ELFT >
322- bool ICF<ELFT>::equalsConstant(const InputSection *a, const InputSection *b) {
349+ bool ICF<ELFT>::equalsConstant(InputSection *a, InputSection *b) {
323350 if (a->flags != b->flags || a->getSize () != b->getSize () ||
324351 a->content () != b->content ())
325352 return false ;
@@ -338,26 +365,27 @@ bool ICF<ELFT>::equalsConstant(const InputSection *a, const InputSection *b) {
338365 : constantEq (a, ra.relas , b, rb.relas );
339366}
340367
341- template <class RelTy >
342- static SmallVector<Symbol *> getReloc ( const InputSection *sec,
343- Relocs<RelTy> relocs) {
344- SmallVector<Symbol *> syms;
368+ template <class ELFT , class RelTy >
369+ static SmallVector<std::pair< Symbol *, uint64_t >>
370+ getReloc ( const InputSection *sec, Relocs<RelTy> relocs) {
371+ SmallVector<std::pair< Symbol *, uint64_t > > syms;
345372 for (auto ri = relocs.begin (), re = relocs.end (); ri != re; ++ri) {
346373 Symbol &sym = sec->file ->getRelocTargetSym (*ri);
347- syms.push_back (&sym);
374+ syms.emplace_back (&sym, getAddend<ELFT>(*ri) );
348375 }
349376 return syms;
350377}
351378
352379template <class ELFT >
353- static SmallVector<Symbol *> getRelocTargetSyms (const InputSection *sec) {
380+ static SmallVector<std::pair<Symbol *, uint64_t >>
381+ getRelocTargetSyms (const InputSection *sec) {
354382 const RelsOrRelas<ELFT> rel = sec->template relsOrRelas <ELFT>();
355383 if (rel.areRelocsCrel ())
356- return getReloc (sec, rel.crels );
384+ return getReloc<ELFT> (sec, rel.crels );
357385 if (rel.areRelocsRel ())
358- return getReloc (sec, rel.rels );
386+ return getReloc<ELFT> (sec, rel.rels );
359387
360- return getReloc (sec, rel.relas );
388+ return getReloc<ELFT> (sec, rel.relas );
361389}
362390
363391// Compare two lists of relocations. Returns true if all pairs of
@@ -572,19 +600,21 @@ template <class ELFT> void ICF<ELFT>::run() {
572600 if (end - begin == 1 )
573601 return ;
574602 print () << " selected section " << sections[begin];
575- SmallVector<Symbol *> syms = getRelocTargetSyms<ELFT>(sections[begin]);
603+ SmallVector<std::pair<Symbol *, uint64_t >> syms =
604+ getRelocTargetSyms<ELFT>(sections[begin]);
576605 for (size_t i = begin + 1 ; i < end; ++i) {
577606 print () << " removing identical section " << sections[i];
578607 sections[begin]->replace (sections[i]);
579- SmallVector<Symbol *> replacedSyms =
608+ SmallVector<std::pair< Symbol *, uint64_t > > replacedSyms =
580609 getRelocTargetSyms<ELFT>(sections[i]);
581610 assert (syms.size () == replacedSyms.size () &&
582611 " Should have same number of syms!" );
583612 for (size_t i = 0 ; i < syms.size (); i++) {
584- if (syms[i] == replacedSyms[i] || !syms[i]->isGlobal () ||
585- !replacedSyms[i]->isGlobal ())
613+ if (syms[i].first == replacedSyms[i].first ||
614+ !syms[i].first ->isGlobal () || !replacedSyms[i].first ->isGlobal () ||
615+ !canMergeSymbols (syms[i].second , replacedSyms[i].second ))
586616 continue ;
587- symbolEquivalence.unionSets (syms[i], replacedSyms[i]);
617+ symbolEquivalence.unionSets (syms[i]. first , replacedSyms[i]. first );
588618 }
589619
590620 // At this point we know sections merged are fully identical and hence
0 commit comments