diff --git a/icf.cc b/icf.cc index 1365c5df..62d3e1ee 100644 --- a/icf.cc +++ b/icf.cc @@ -1,16 +1,17 @@ #include "mold.h" #include +#include #include -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; + } + } }