1
1
mirror of https://github.com/rui314/mold.git synced 2024-11-11 16:58:12 +03:00
This commit is contained in:
Rui Ueyama 2021-01-26 13:27:10 +09:00
parent 50330975fe
commit f28b7fc737

47
icf.cc
View File

@ -1,16 +1,17 @@
#include "mold.h"
#include <tbb/parallel_for_each.h>
#include <tbb/partitioner.h>
#include <tbb/task_arena.h>
static i64 current = 0;
static i64 slot = 0;
static thread_local i64 noneligible_id = 0;
static bool is_eligible(InputSection &x) {
return (x.shdr.sh_flags & SHF_ALLOC) &&
!(x.shdr.sh_flags & SHF_WRITE) &&
!(x.shdr.sh_type == SHT_INIT_ARRAY || x.name == ".init") &&
!(x.shdr.sh_type == SHT_FINI_ARRAY || x.name == ".fini");
static bool is_eligible(InputSection &isec) {
return (isec.shdr.sh_flags & SHF_ALLOC) &&
!(isec.shdr.sh_flags & SHF_WRITE) &&
!(isec.shdr.sh_type == SHT_INIT_ARRAY || isec.name == ".init") &&
!(isec.shdr.sh_type == SHT_FINI_ARRAY || isec.name == ".fini");
}
static u64 hash(u64 x) {
@ -28,13 +29,13 @@ inline void hash_combine(u64 &seed, const T &val) {
seed ^= hash(val) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
}
static u64 hash(InputSection &x) {
static u64 hash(InputSection &isec) {
u64 hv = 0;
hash_combine(hv, x.shdr.sh_flags);
hash_combine(hv, x.rels.size());
hash_combine(hv, x.get_contents());
hash_combine(hv, isec.shdr.sh_flags);
hash_combine(hv, isec.rels.size());
hash_combine(hv, isec.get_contents());
for (ElfRela &rel : x.rels) {
for (ElfRela &rel : isec.rels) {
hash_combine(hv, rel.r_offset);
hash_combine(hv, rel.r_type);
hash_combine(hv, rel.r_addend);
@ -42,6 +43,14 @@ static u64 hash(InputSection &x) {
return hv;
}
static void propagate(InputSection &isec) {
for (ElfRela &rel : isec.rels) {
Symbol &sym = *isec.file->symbols[rel.r_sym];
if (sym.input_section)
sym.input_section->eq_class[slot] += isec.eq_class[slot ^ 1];
}
}
static bool equal(InputSection &x, InputSection &y) {
if (x.shdr.sh_flags != y.shdr.sh_flags)
return false;
@ -79,7 +88,7 @@ static bool equal(InputSection &x, InputSection &y) {
InputSection &isecx = *symx.input_section;
InputSection &isecy = *symy.input_section;
if (isecx.eq_class[current] != isecy.eq_class[current])
if (isecx.eq_class[slot] != isecy.eq_class[slot])
return false;
}
return true;
@ -101,4 +110,18 @@ void icf_sections() {
}
}
});
slot ^= 1;
{
Timer t2("propagate");
for (i64 i = 0; i < 2; i++) {
tbb::parallel_for_each(out::objs, [&](ObjectFile *file) {
for (InputSection *isec : file->sections)
if (isec)
propagate(*isec);
});
slot ^= 1;
}
}
}