diff --git a/lld/MachO/ICF.cpp b/lld/MachO/ICF.cpp --- a/lld/MachO/ICF.cpp +++ b/lld/MachO/ICF.cpp @@ -105,6 +105,9 @@ return false; InputSection *isecA, *isecB; + + uint64_t valueA = 0; + uint64_t valueB = 0; if (ra.referent.is<Symbol *>()) { const auto *sa = ra.referent.get<Symbol *>(); const auto *sb = rb.referent.get<Symbol *>(); @@ -121,7 +124,9 @@ return da->value == db->value; } isecA = da->isec; + valueA = da->value; isecB = db->isec; + valueB = db->value; } else { isecA = ra.referent.get<InputSection *>(); isecB = rb.referent.get<InputSection *>(); @@ -136,7 +141,8 @@ return true; // Else we have two literal sections. References to them are equal iff their // offsets in the output section are equal. - return isecA->getOffset(ra.addend) == isecB->getOffset(rb.addend); + return isecA->getOffset(valueA + ra.addend) == + isecB->getOffset(valueB + rb.addend); }; return std::equal(ia->relocs.begin(), ia->relocs.end(), ib->relocs.begin(), f); diff --git a/lld/test/MachO/icf-literals.s b/lld/test/MachO/icf-literals.s --- a/lld/test/MachO/icf-literals.s +++ b/lld/test/MachO/icf-literals.s @@ -13,6 +13,10 @@ # CHECK-NEXT: callq _baz2_ref # CHECK-NEXT: callq _qux2_ref # CHECK-NEXT: callq _qux2_ref +# CHECK-NEXT: callq _sub_str_a_b +# CHECK-NEXT: callq _sub_str_b_a +# CHECK-NEXT: callq _sub_lit_a_b +# CHECK-NEXT: callq _sub_lit_b_a # CHECK: [[#%.16x,FOO:]] l O __TEXT,__cstring _foo1 # CHECK-NEXT: [[#%.16x,FOO:]] l O __TEXT,__cstring _foo2 @@ -56,21 +60,42 @@ .text _foo1_ref: - mov _foo1@GOTPCREL(%rip), %rax + leaq _foo1(%rip), %rax _foo2_ref: - mov _foo2@GOTPCREL(%rip), %rax + leaq _foo2(%rip), %rax _bar1_ref: - mov _bar1@GOTPCREL(%rip), %rax + leaq _bar1(%rip), %rax _bar2_ref: - mov _bar2@GOTPCREL(%rip), %rax + leaq _bar2(%rip), %rax _baz1_ref: - mov _baz1@GOTPCREL(%rip), %rax + movq _baz1(%rip), %rax _baz2_ref: - mov _baz2@GOTPCREL(%rip), %rax + movq _baz2(%rip), %rax _qux1_ref: - mov _qux1@GOTPCREL(%rip), %rax + movq _qux1(%rip), %rax _qux2_ref: - mov _qux2@GOTPCREL(%rip), %rax + movq _qux2(%rip), %rax + +## _sub_str_a_b and _sub_str_b_a should not be folded: They contain relocations +## against the same string symbols, but in a different order and hence +## return different numbers. +_sub_str_a_b: + leaq _foo2(%rip), %rdx + leaq _bar2(%rip), %rax + subq %rdx, %rax +_sub_str_b_a: + leaq _bar2(%rip), %rdx + leaq _foo2(%rip), %rax + subq %rdx, %rax + +## Same with literals instead of strings. +_sub_lit_a_b: + movq _baz2(%rip), %rax + subq _qux2(%rip), %rax +_sub_lit_b_a: + movq _qux2(%rip), %rax + subq _baz2(%rip), %rax + .globl _main _main: @@ -82,5 +107,9 @@ callq _baz2_ref callq _qux1_ref callq _qux2_ref + callq _sub_str_a_b + callq _sub_str_b_a + callq _sub_lit_a_b + callq _sub_lit_b_a .subsections_via_symbols