[clang] [lld] [lld-macho][draft]Allow folding entries with identical FDE (PR #216895)

Vy Nguyen via llvm-commits llvm-commits at lists.llvm.org
Tue Aug 18 17:58:00 PDT 2026


https://github.com/oontvoo updated https://github.com/llvm/llvm-project/pull/216895

>From 48bc3a4580675833dc69afcb8d6a4328644b6ce2 Mon Sep 17 00:00:00 2001
From: Vy Nguyen <vyng at google.com>
Date: Thu, 14 May 2026 15:36:16 -0400
Subject: [PATCH 1/6] [codegen]Ensure __builtin_trap() has an unreachable

---
 clang/lib/CodeGen/CGBuiltin.cpp | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index 20f99f489c55f..678985ebb55e1 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -4022,6 +4022,12 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
   }
   case Builtin::BI__builtin_trap:
     EmitTrapCall(Intrinsic::trap);
+    if (Builder.GetInsertBlock()) {
+      Builder.CreateUnreachable();
+      // Dummy block for the ret void - it'll be clened up
+      llvm::BasicBlock *DeadBB = createBasicBlock("dead.trap");
+      EmitBlock(DeadBB);
+    }
     return RValue::get(nullptr);
   case Builtin::BI__builtin_verbose_trap: {
     llvm::DILocation *TrapLocation = Builder.getCurrentDebugLocation();

>From 8d9683bb815903f607fef8bb372f1033f1128ea8 Mon Sep 17 00:00:00 2001
From: Vy Nguyen <vyng at google.com>
Date: Mon, 17 Aug 2026 21:17:55 -0400
Subject: [PATCH 2/6] [lld-macho]Allow folding functions with the same Dwarf
 FDE

This is done by normalising the embedded reloc data during ICF comparison and hashing.

(modified version of pr/213778)
---
 lld/MachO/ICF.cpp                | 76 +++++++++++++++++++++-----------
 lld/test/MachO/fold-dwarf-lsda.s |  6 +--
 2 files changed, 52 insertions(+), 30 deletions(-)

diff --git a/lld/MachO/ICF.cpp b/lld/MachO/ICF.cpp
index 8e9eb1d4e7950..60df53327b834 100644
--- a/lld/MachO/ICF.cpp
+++ b/lld/MachO/ICF.cpp
@@ -91,6 +91,32 @@ ICF::ICF(std::vector<ConcatInputSection *> &inputs) {
 // FIXME(gkm): implement keep-unique attributes
 // FIXME(gkm): implement address-significance tables for MachO object files
 
+static bool isFoldableWithAddendsRemoved(const ConcatInputSection *isec) {
+  return isCfStringSection(isec) || isClassRefsSection(isec) ||
+         isSelRefsSection(isec) || isEhFrameSection(isec);
+}
+
+// Make a normalized copy of a section's bytes by zeroing out the embedded relocs.
+// Return it in the given &buf
+static void getNormalizedData(const ConcatInputSection *isec,
+                             SmallVectorImpl<uint8_t> &buf) {
+  buf.assign(isec->data.begin(), isec->data.end());
+  for (const Relocation &r : isec->relocs)
+    target->relocateOne(buf.data() + r.offset, r, /*va=*/0, /*relocVA=*/0);
+}
+
+static bool compareData(const ConcatInputSection *ia,
+                        const ConcatInputSection *ib) {
+  if (ia->data == ib->data)
+    return true;
+  if (!isFoldableWithAddendsRemoved(ia))
+    return false;
+  SmallVector<uint8_t, 64> bufA, bufB;
+  getNormalizedData(ia, bufA);
+  getNormalizedData(ib, bufB);
+  return bufA == bufB;
+}
+
 // Compare "non-moving" parts of two ConcatInputSections, namely everything
 // except references to other ConcatInputSections.
 bool ICF::equalsConstant(const ConcatInputSection *ia,
@@ -100,7 +126,7 @@ bool ICF::equalsConstant(const ConcatInputSection *ia,
   // We can only fold within the same OutputSection.
   if (ia->parent != ib->parent)
     return false;
-  if (ia->data != ib->data)
+  if (!compareData(ia, ib))
     return false;
   auto f = [](const Relocation &ra, const Relocation &rb) {
     if (ra.type != rb.type)
@@ -573,9 +599,9 @@ void macho::foldIdenticalSections(bool onlyCfStrings) {
   // Reset the thunk counter for each run of ICF.
   icfThunkCounter = 0;
   for (ConcatInputSection *isec : inputSections) {
-    bool isFoldableWithAddendsRemoved = isCfStringSection(isec) ||
-                                        isClassRefsSection(isec) ||
-                                        isSelRefsSection(isec);
+    bool isUnconditionallyCoalescedData = isCfStringSection(isec) ||
+                                          isClassRefsSection(isec) ||
+                                          isSelRefsSection(isec);
     // NOTE: __objc_selrefs is typically marked as no_dead_strip by MC, but we
     // can still fold it.
     bool hasFoldableFlags = (isSelRefsSection(isec) ||
@@ -596,7 +622,6 @@ void macho::foldIdenticalSections(bool onlyCfStrings) {
     // Happens to match isFoldableWithAddendsRemoved today, but expresses a
     // different intent (ld64's coalescing semantics, not addend stripping),
     // so the two may diverge as either list grows.
-    bool isUnconditionallyCoalescedData = isFoldableWithAddendsRemoved;
     bool isSafeThunksCode =
         config->icfLevel == ICFLevel::safe_thunks && isCodeSec;
     bool keepUniqueAllowsFolding =
@@ -604,7 +629,7 @@ void macho::foldIdenticalSections(bool onlyCfStrings) {
 
     // FIXME: consider non-code __text sections as foldable?
     bool isFoldable = (!onlyCfStrings || isCfStringSection(isec)) &&
-                      (isCodeSec || isFoldableWithAddendsRemoved ||
+                      (isCodeSec || isFoldableWithAddendsRemoved(isec) ||
                        isGccExceptTabSection(isec)) &&
                       keepUniqueAllowsFolding && !isec->hasAltEntry &&
                       !isec->shouldOmitFromOutput() && hasFoldableFlags;
@@ -613,32 +638,33 @@ void macho::foldIdenticalSections(bool onlyCfStrings) {
       for (Defined *d : isec->symbols)
         if (d->unwindEntry())
           foldable.push_back(d->unwindEntry());
-
-      // Some sections have embedded addends that foil ICF's hashing / equality
-      // checks. (We can ignore embedded addends when doing ICF because the same
-      // information gets recorded in our Reloc structs.) We therefore create a
-      // mutable copy of the section data and zero out the embedded addends
-      // before performing any hashing / equality checks.
-      if (isFoldableWithAddendsRemoved) {
-        // We have to do this copying serially as the BumpPtrAllocator is not
-        // thread-safe. FIXME: Make a thread-safe allocator.
-        MutableArrayRef<uint8_t> copy = isec->data.copy(bAlloc());
-        for (const Relocation &r : isec->relocs)
-          target->relocateOne(copy.data() + r.offset, r, /*va=*/0,
-                              /*relocVA=*/0);
-        isec->data = copy;
-      }
-    } else if (!isEhFrameSection(isec)) {
-      // EH frames are gathered as foldables from unwindEntry above; give a
-      // unique ID to everything else.
+    } else if (isEhFrameSection(isec)) {
+      // __eh_frame contains two types of records: FDEs and CIEs.
+      // Functions point to FDEs, which are already collected above via unwindEntry().
+      // CIEs are shared headers and are not attached to individual functions.
+      // Collect only CIEs here so they can also be hashed and deduplicated.
+      auto *obj = dyn_cast_or_null<ObjFile>(isec->getFile());
+      if (!onlyCfStrings && obj && !obj->fdes.contains(isec) &&
+          !isec->shouldOmitFromOutput())
+        foldable.push_back(isec);
+    } else {
+      // Give a unique ID to everything else.
       isec->icfEqClass[0] = ++icfUniqueID;
     }
   }
   parallelForEach(foldable, [](ConcatInputSection *isec) {
     assert(isec->icfEqClass[0] == 0); // don't overwrite a unique ID!
+    uint64_t hash;
+    if (isFoldableWithAddendsRemoved(isec)) {
+      SmallVector<uint8_t, 64> stackBuf;
+      getNormalizedData(isec, stackBuf);
+      hash = xxh3_64bits(stackBuf);
+    } else {
+      hash = xxh3_64bits(isec->data);
+    }
     // Turn-on the top bit to guarantee that valid hashes have no collisions
     // with the small-integer unique IDs for ICF-ineligible sections
-    isec->icfEqClass[0] = xxh3_64bits(isec->data) | (1ull << 31);
+    isec->icfEqClass[0] = hash | (1ull << 31);
   });
   // Now that every input section is either hashed or marked as unique, run the
   // segregation algorithm to detect foldable subsections.
diff --git a/lld/test/MachO/fold-dwarf-lsda.s b/lld/test/MachO/fold-dwarf-lsda.s
index e651fa81b8b7a..0451bc8aae266 100644
--- a/lld/test/MachO/fold-dwarf-lsda.s
+++ b/lld/test/MachO/fold-dwarf-lsda.s
@@ -22,7 +22,7 @@
 # POST: [[#%x,EXCEPT_ADDR:]] l   O __TEXT,__gcc_except_tab GCC_except_table0
 # POST: [[#%x,EXCEPT_ADDR]]  l   O __TEXT,__gcc_except_tab GCC_except_table1
 # POST: [[#%.16x,F0_ADDR:]]  g   F __TEXT,__text _f0
-# POST: [[#%.16x,F1_ADDR:]]  g   F __TEXT,__text _f1
+# POST: [[#%.16x,F0_ADDR]]   g   F __TEXT,__text _f1
 # POST: [[#%.16x,G_ADDR:]]   g   F __TEXT,__text _g
 
 # POST-LABEL: .eh_frame contents:
@@ -32,10 +32,6 @@
 # POST: Format:       DWARF32 
 # POST: LSDA Address: [[#%.16x,EXCEPT_ADDR]]
 
-# POST: {{.*}} FDE cie={{.+}} pc=[[#%x,F1_ADDR]]...{{.+}}
-# POST Format:       DWARF32 
-# POST LSDA Address: [[#%.16x,EXCEPT_ADDR]]
-
 	.section        __TEXT,__text,regular,pure_instructions
 	.globl	_f0
 _f0:

>From d8dcc9b5c3e50b2cee6dbc50187670367b7e99ff Mon Sep 17 00:00:00 2001
From: Vy Nguyen <vyng at google.com>
Date: Tue, 18 Aug 2026 11:35:45 -0400
Subject: [PATCH 3/6] Revert "[codegen]Ensure __builtin_trap() has an
 unreachable"

This reverts commit 48bc3a4580675833dc69afcb8d6a4328644b6ce2.
---
 clang/lib/CodeGen/CGBuiltin.cpp | 6 ------
 1 file changed, 6 deletions(-)

diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index efcc33ac1f564..3f7b090315f5e 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -4068,12 +4068,6 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
   }
   case Builtin::BI__builtin_trap:
     EmitTrapCall(Intrinsic::trap);
-    if (Builder.GetInsertBlock()) {
-      Builder.CreateUnreachable();
-      // Dummy block for the ret void - it'll be clened up
-      llvm::BasicBlock *DeadBB = createBasicBlock("dead.trap");
-      EmitBlock(DeadBB);
-    }
     return RValue::get(nullptr);
   case Builtin::BI__builtin_verbose_trap: {
     llvm::DILocation *TrapLocation = Builder.getCurrentDebugLocation();

>From e3e70cdb8a2fe7181351bcefea3b5e16fe2a9dcf Mon Sep 17 00:00:00 2001
From: Vy Nguyen <vyng at google.com>
Date: Tue, 18 Aug 2026 13:40:10 -0400
Subject: [PATCH 4/6] add tests

---
 lld/test/MachO/icf-fold-dwarf-frame.s | 173 ++++++++++++++++++++++++++
 lld/test/MachO/icf.s                  |  10 +-
 2 files changed, 176 insertions(+), 7 deletions(-)
 create mode 100644 lld/test/MachO/icf-fold-dwarf-frame.s

diff --git a/lld/test/MachO/icf-fold-dwarf-frame.s b/lld/test/MachO/icf-fold-dwarf-frame.s
new file mode 100644
index 0000000000000..34fdc3cc55f42
--- /dev/null
+++ b/lld/test/MachO/icf-fold-dwarf-frame.s
@@ -0,0 +1,173 @@
+# REQUIRES: aarch64
+
+# RUN: llvm-mc -filetype=obj -triple=arm64-apple-macos11 %s -o %t.o
+# RUN: %lld -arch arm64 %t.o -o %t.dylib -undefined dynamic_lookup --icf=all
+# RUN: llvm-objdump --macho --syms --dwarf=frames --unwind-info %t.dylib | FileCheck %s
+
+# CHECK-LABEL: SYMBOL TABLE:
+# CHECK-DAG:  [[#%.16x,FOLD0:]] {{.*}} __TEXT,__text _foldA
+# CHECK-DAG:  [[#FOLD0]]        {{.*}} __TEXT,__text _foldB
+# CHECK-DAG:  [[#FOLD0]]        {{.*}} __TEXT,__text _foldC
+# CHECK-NOT:  [[#FOLD0]]        {{.*}} __TEXT,__text _diffLSDA
+# CHECK-NOT:  [[#FOLD0]]        {{.*}} __TEXT,__text _diffPersonality
+# CHECK-NOT:  [[#FOLD0]]        {{.*}} __TEXT,__text _diffCFI
+# CHECK-DAG:  [[#%.16x,FOLD1:]] {{.*}} __TEXT,__gcc_except_tab GCC_except_table0
+# CHECK-DAG:  [[#FOLD1]]        {{.*}} __TEXT,__gcc_except_tab GCC_except_table1
+# CHECK-NOT:  [[#FOLD1]]        {{.*}} __TEXT,__gcc_except_tab GCC_except_table2
+
+# CHECK-LABEL: Contents of __unwind_info section:
+
+# CHECK-LABEL: .eh_frame contents:
+# CHECK: {{^}}[[#%.8x,CIE0:]] {{.*}} CIE
+# CHECK: FDE cie=[[#%.8x,CIE0]]
+# CHECK: FDE cie=[[#%.8x,CIE0]]
+# CHECK: FDE cie=[[#%.8x,CIE0]]
+# CHECK: FDE cie=[[#%.8x,CIE0]]
+# CHECK: {{^}}[[#%.8x,CIE1:]] {{.*}} CIE
+# CHECK: FDE cie=[[#%.8x,CIE1]]
+# CHECK: FDE cie=[[#%.8x,CIE1]]
+
+# Due to padding, we need to emit a throwaway FDE for each personality, so that
+# subsequent FDEs are the same size and can be folded
+# TODO: Could we detect padding differences and fold anyway?
+_padA:
+  .cfi_startproc
+  .cfi_personality 155, _p0
+  .cfi_lsda 16, Lexception0
+  str x30, [sp, #-16]!
+  .cfi_def_cfa_offset 16
+  .cfi_offset w30, -16
+  bl _may_throw
+  ldr x30, [sp], #16
+  ret
+  .cfi_endproc
+
+_padB:
+  .cfi_startproc
+  .cfi_personality 155, _p1
+  .cfi_lsda 16, Lexception0
+  str x30, [sp, #-16]!
+  .cfi_def_cfa_offset 16
+  .cfi_offset w30, -16
+  bl _may_throw
+  ldr x30, [sp], #16
+  ret
+  .cfi_endproc
+
+_foldA:
+  .cfi_startproc
+  .cfi_personality 155, _p0
+  .cfi_lsda 16, Lexception0
+  str x30, [sp, #-16]!
+  .cfi_def_cfa_offset 16
+  .cfi_offset w30, -16
+  bl _may_throw
+  ldr x30, [sp], #16
+  ret
+  .cfi_endproc
+
+_foldB:
+  .cfi_startproc
+  .cfi_personality 155, _p0
+  .cfi_lsda 16, Lexception0
+  str x30, [sp, #-16]!
+  .cfi_def_cfa_offset 16
+  .cfi_offset w30, -16
+  bl _may_throw
+  ldr x30, [sp], #16
+  ret
+  .cfi_endproc
+
+# LSDA points to a different symbol, but the contents are the same as Lexception1 so it can be folded
+_foldC:
+  .cfi_startproc
+  .cfi_personality 155, _p0
+  .cfi_lsda 16, Lexception1
+  str x30, [sp, #-16]!
+  .cfi_def_cfa_offset 16
+  .cfi_offset w30, -16
+  bl _may_throw
+  ldr x30, [sp], #16
+  ret
+  .cfi_endproc
+
+# Different LSDAs cannot be folded
+_diffLSDA:
+  .cfi_startproc
+  .cfi_personality 155, _p0
+  .cfi_lsda 16, Lexception2
+  str x30, [sp, #-16]!
+  .cfi_def_cfa_offset 16
+  .cfi_offset w30, -16
+  bl _may_throw
+  ldr x30, [sp], #16
+  ret
+  .cfi_endproc
+
+_diffPersonality:
+  .cfi_startproc
+  .cfi_personality 155, _p1
+  .cfi_lsda 16, Lexception0
+  str x30, [sp, #-16]!
+  .cfi_def_cfa_offset 16
+  .cfi_offset w30, -16
+  bl _may_throw
+  ldr x30, [sp], #16
+  ret
+  .cfi_endproc
+
+_diffCFI:
+  .cfi_startproc
+  .cfi_personality 155, _p0
+  .cfi_lsda 16, Lexception0
+  str x30, [sp, #-16]!
+  .cfi_def_cfa_offset 160
+  .cfi_offset w30, -160
+  bl _may_throw
+  ldr x30, [sp], #16
+  ret
+  .cfi_endproc
+
+.section __TEXT,__gcc_except_tab
+.p2align 2
+GCC_except_table0:
+Lexception0:
+  .byte 0xFF
+  .byte 0x9B
+  .uleb128 Lttbase0-Lttbaseref0
+Lttbaseref0:
+  .byte 1
+  .uleb128 0
+  .p2align 2
+  .long 0
+Lttbase0:
+
+# Contents are identical to above. It should be folded
+.p2align 2
+GCC_except_table1:
+Lexception1:
+  .byte 0xFF
+  .byte 0x9B
+  .uleb128 Lttbase1-Lttbaseref1
+Lttbaseref1:
+  .byte 1
+  .uleb128 0
+  .p2align 2
+  .long 0
+Lttbase1:
+
+.p2align 2
+GCC_except_table2:
+Lexception2:
+  .byte 0xFF
+  .byte 0x9B
+  .uleb128 Lttbase2-Lttbaseref2
+Lttbaseref2:
+  .byte 1
+  .uleb128 1
+  .byte 0xAA
+  .p2align 2
+  .long 0
+Lttbase2:
+
+.subsections_via_symbols
diff --git a/lld/test/MachO/icf.s b/lld/test/MachO/icf.s
index 68ed369188e91..9db2a864be836 100644
--- a/lld/test/MachO/icf.s
+++ b/lld/test/MachO/icf.s
@@ -40,8 +40,8 @@
 # CHECK: [[#%x,HAS_UNWIND_4:]]              l     F __TEXT,__text _has_unwind_4
 # CHECK: [[#%x,HAS_ABS_PERSONALITY_1:]]     l     F __TEXT,__text _has_abs_personality_1
 # CHECK: [[#%x,HAS_ABS_PERSONALITY_2:]]     l     F __TEXT,__text _has_abs_personality_2
-# CHECK: [[#%x,HAS_EH_FRAME_1:]]            l     F __TEXT,__text _has_eh_frame_1
-# CHECK: [[#%x,HAS_EH_FRAME_2:]]            l     F __TEXT,__text _has_eh_frame_2
+# CHECK: [[#%x,HAS_EH_FRAME_2:]]            l     F __TEXT,__text _has_eh_frame_1
+# CHECK: [[#%x,HAS_EH_FRAME_2]]             l     F __TEXT,__text _has_eh_frame_2
 # CHECK: [[#%x,HAS_EH_FRAME_3:]]            l     F __TEXT,__text _has_eh_frame_3
 # CHECK: [[#%x,MUTALLY_RECURSIVE_2:]]       l     F __TEXT,__text _mutually_recursive_1
 # CHECK: [[#%x,MUTALLY_RECURSIVE_2]]        l     F __TEXT,__text _mutually_recursive_2
@@ -55,8 +55,6 @@
 # CHECK: [[#%x,GCC_EXCEPT_0]]               l     O __TEXT,__gcc_except_tab GCC_except_table1
 # CHECK: [[#%x,GCC_EXCEPT_2:]]              l     O __TEXT,__gcc_except_tab GCC_except_table2
 
-## Check that we don't accidentally dedup distinct EH frames.
-# CHECK: FDE {{.*}} pc=[[#%x,HAS_EH_FRAME_1]]
 # CHECK: FDE {{.*}} pc=[[#%x,HAS_EH_FRAME_2]]
 # CHECK: FDE {{.*}} pc=[[#%x,HAS_EH_FRAME_3]]
 
@@ -89,7 +87,7 @@
 # CHECK: callq 0x[[#%x,HAS_UNWIND_4]]              <_has_unwind_4>
 # CHECK: callq 0x[[#%x,HAS_ABS_PERSONALITY_1]]     <_has_abs_personality_1>
 # CHECK: callq 0x[[#%x,HAS_ABS_PERSONALITY_2]]     <_has_abs_personality_2>
-# CHECK: callq 0x[[#%x,HAS_EH_FRAME_1]]            <_has_eh_frame_1>
+# CHECK: callq 0x[[#%x,HAS_EH_FRAME_2]]            <_has_eh_frame_2>
 # CHECK: callq 0x[[#%x,HAS_EH_FRAME_2]]            <_has_eh_frame_2>
 # CHECK: callq 0x[[#%x,HAS_EH_FRAME_3]]            <_has_eh_frame_3>
 # CHECK: callq 0x[[#%x,MUTALLY_RECURSIVE_2]]       <_mutually_recursive_2>
@@ -261,8 +259,6 @@ _has_abs_personality_2:
 _abs_personality_1 = 0x1
 _abs_personality_2 = 0x2
 
-## In theory _has_eh_frame_{1, 2} can be dedup'ed, but we don't support this
-## yet.
 _has_eh_frame_1:
   .cfi_startproc
   .cfi_def_cfa_offset 8

>From b6594941d8d0d1ea69cce0334891ecf0bb89a389 Mon Sep 17 00:00:00 2001
From: Vy Nguyen <1762963+oontvoo at users.noreply.github.com>
Date: Tue, 18 Aug 2026 20:21:19 -0400
Subject: [PATCH 5/6] Apply suggestion from @ellishg

Co-authored-by: Ellis Hoag <ellis.sparky.hoag at gmail.com>
---
 lld/MachO/ICF.cpp | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/lld/MachO/ICF.cpp b/lld/MachO/ICF.cpp
index 60df53327b834..ac540e31d761e 100644
--- a/lld/MachO/ICF.cpp
+++ b/lld/MachO/ICF.cpp
@@ -107,6 +107,8 @@ static void getNormalizedData(const ConcatInputSection *isec,
 
 static bool compareData(const ConcatInputSection *ia,
                         const ConcatInputSection *ib) {
+  if (ia->data.size() != ib->data.size())
+    return false;
   if (ia->data == ib->data)
     return true;
   if (!isFoldableWithAddendsRemoved(ia))

>From 95e3d3a1ef31360e34f129b04d06c9702c99e58d Mon Sep 17 00:00:00 2001
From: Vy Nguyen <vyng at google.com>
Date: Tue, 18 Aug 2026 20:57:42 -0400
Subject: [PATCH 6/6] fix crash on arm64 and add assert

---
 lld/MachO/ICF.cpp | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/lld/MachO/ICF.cpp b/lld/MachO/ICF.cpp
index ac540e31d761e..0b9d3e9faf723 100644
--- a/lld/MachO/ICF.cpp
+++ b/lld/MachO/ICF.cpp
@@ -101,8 +101,11 @@ static bool isFoldableWithAddendsRemoved(const ConcatInputSection *isec) {
 static void getNormalizedData(const ConcatInputSection *isec,
                              SmallVectorImpl<uint8_t> &buf) {
   buf.assign(isec->data.begin(), isec->data.end());
-  for (const Relocation &r : isec->relocs)
-    target->relocateOne(buf.data() + r.offset, r, /*va=*/0, /*relocVA=*/0);
+  for (const Relocation &r : isec->relocs) {
+    size_t size = 1ULL << r.length;
+    if (r.offset + size <= buf.size())
+      memset(buf.data() + r.offset, 0, size);
+  }
 }
 
 static bool compareData(const ConcatInputSection *ia,
@@ -113,6 +116,8 @@ static bool compareData(const ConcatInputSection *ia,
     return true;
   if (!isFoldableWithAddendsRemoved(ia))
     return false;
+  assert(isFoldableWithAddendsRemoved(ib));
+
   SmallVector<uint8_t, 64> bufA, bufB;
   getNormalizedData(ia, bufA);
   getNormalizedData(ib, bufB);



More information about the llvm-commits mailing list