77
77
#include " InputFiles.h"
78
78
#include " LinkerScript.h"
79
79
#include " OutputSections.h"
80
+ #include " Relocations.h"
80
81
#include " SymbolTable.h"
81
82
#include " Symbols.h"
82
83
#include " SyntheticSections.h"
84
+ #include " Target.h"
83
85
#include " llvm/ADT/EquivalenceClasses.h"
84
86
#include " llvm/BinaryFormat/ELF.h"
85
87
#include " llvm/Object/ELF.h"
@@ -105,18 +107,23 @@ template <class ELFT> class ICF {
105
107
void segregate (size_t begin, size_t end, uint32_t eqClassBase, bool constant);
106
108
107
109
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);
110
112
111
113
template <class RelTy >
112
114
bool variableEq (const InputSection *a, Relocs<RelTy> relsA,
113
115
const InputSection *b, Relocs<RelTy> relsB);
114
116
115
- bool equalsConstant (const InputSection *a, const InputSection *b);
117
+ bool equalsConstant (InputSection *a, InputSection *b);
116
118
bool equalsVariable (const InputSection *a, const InputSection *b);
117
119
118
120
size_t findBoundary (size_t begin, size_t end);
119
121
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
+
120
127
void forEachClassRange (size_t begin, size_t end,
121
128
llvm::function_ref<void (size_t , size_t )> fn);
122
129
@@ -235,11 +242,30 @@ void ICF<ELFT>::segregate(size_t begin, size_t end, uint32_t eqClassBase,
235
242
}
236
243
}
237
244
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
+
238
264
// Compare two lists of relocations.
239
265
template <class ELFT >
240
266
template <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) {
243
269
if (ra.size () != rb.size ())
244
270
return false ;
245
271
auto rai = ra.begin (), rae = ra.end (), rbi = rb.begin ();
@@ -287,13 +313,14 @@ bool ICF<ELFT>::constantEq(const InputSection *secA, Relocs<RelTy> ra,
287
313
// Relocations referring to InputSections are constant-equal if their
288
314
// section offsets are equal.
289
315
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 ;
295
322
continue ;
296
- return false ;
323
+ }
297
324
}
298
325
299
326
// Relocations referring to MergeInputSections are constant-equal if their
@@ -319,7 +346,7 @@ bool ICF<ELFT>::constantEq(const InputSection *secA, Relocs<RelTy> ra,
319
346
// Compare "non-moving" part of two InputSections, namely everything
320
347
// except relocation targets.
321
348
template <class ELFT >
322
- bool ICF<ELFT>::equalsConstant(const InputSection *a, const InputSection *b) {
349
+ bool ICF<ELFT>::equalsConstant(InputSection *a, InputSection *b) {
323
350
if (a->flags != b->flags || a->getSize () != b->getSize () ||
324
351
a->content () != b->content ())
325
352
return false ;
@@ -338,26 +365,27 @@ bool ICF<ELFT>::equalsConstant(const InputSection *a, const InputSection *b) {
338
365
: constantEq (a, ra.relas , b, rb.relas );
339
366
}
340
367
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;
345
372
for (auto ri = relocs.begin (), re = relocs.end (); ri != re; ++ri) {
346
373
Symbol &sym = sec->file ->getRelocTargetSym (*ri);
347
- syms.push_back (&sym);
374
+ syms.emplace_back (&sym, getAddend<ELFT>(*ri) );
348
375
}
349
376
return syms;
350
377
}
351
378
352
379
template <class ELFT >
353
- static SmallVector<Symbol *> getRelocTargetSyms (const InputSection *sec) {
380
+ static SmallVector<std::pair<Symbol *, uint64_t >>
381
+ getRelocTargetSyms (const InputSection *sec) {
354
382
const RelsOrRelas<ELFT> rel = sec->template relsOrRelas <ELFT>();
355
383
if (rel.areRelocsCrel ())
356
- return getReloc (sec, rel.crels );
384
+ return getReloc<ELFT> (sec, rel.crels );
357
385
if (rel.areRelocsRel ())
358
- return getReloc (sec, rel.rels );
386
+ return getReloc<ELFT> (sec, rel.rels );
359
387
360
- return getReloc (sec, rel.relas );
388
+ return getReloc<ELFT> (sec, rel.relas );
361
389
}
362
390
363
391
// Compare two lists of relocations. Returns true if all pairs of
@@ -572,19 +600,21 @@ template <class ELFT> void ICF<ELFT>::run() {
572
600
if (end - begin == 1 )
573
601
return ;
574
602
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]);
576
605
for (size_t i = begin + 1 ; i < end; ++i) {
577
606
print () << " removing identical section " << sections[i];
578
607
sections[begin]->replace (sections[i]);
579
- SmallVector<Symbol *> replacedSyms =
608
+ SmallVector<std::pair< Symbol *, uint64_t > > replacedSyms =
580
609
getRelocTargetSyms<ELFT>(sections[i]);
581
610
assert (syms.size () == replacedSyms.size () &&
582
611
" Should have same number of syms!" );
583
612
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 ))
586
616
continue ;
587
- symbolEquivalence.unionSets (syms[i], replacedSyms[i]);
617
+ symbolEquivalence.unionSets (syms[i]. first , replacedSyms[i]. first );
588
618
}
589
619
590
620
// At this point we know sections merged are fully identical and hence
0 commit comments