[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:17:48 PDT 2026
================
@@ -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;
----------------
oontvoo wrote:
> But if the section size is larger than 64 bytes, then we will have a heap allocation, right
Yes. But they're typically not larger than 64.
Specifically,
- __objc_selrefs and __objc_classrefs are exactly 8 bytes
- __cfstring : 32 bytes max
```
struct __CFString {
void *isa; // 8 bytes
uintptr_t flags; // 8 bytes
const char *str; // 8 bytes
uintptr_t length; // 8 bytes
};
```
- CIE:
```
struct CIE {
uint8_t fdePtrEnc = 0;
uint8_t lsdaPtrEnc = 0;
uint8_t personalityEnc = 0;
uint8_t funcPtrSize = 0;
uint8_t lsdaPtrSize = 0;
Symbol *personalitySymbol = nullptr;
}; // 16 bytes max (with alignment)
```
- FDE: ~56
```
Length: 4
CIE Pointer: 4
func offset: 4
function size: 4
augmentation len: 1
lsda ptr: 4
DW_CFA_advance_loc: 1
DW_CFA_def_cfa_offset: 2
DW_CFA_offset (FP): 2
[DW_CFA_offset (LR): 2
[DW_CFA_offset (x19): 2
< .... more here...>
[Padding: 3B]
---------------------------
Total: ~40 to 56 bytes in binary
```
- (other "regular sections" are handled in the "else" below)
https://github.com/llvm/llvm-project/pull/216895
More information about the llvm-commits
mailing list