if (config->icfLevel != ICFLevel::none) {
if (config->icfLevel == ICFLevel::safe)
markAddrSigSymbols();
- foldIdenticalSections();
+ foldIdenticalSections(/*onlyCfStrings=*/false);
+ } else if (config->dedupLiterals) {
+ foldIdenticalSections(/*onlyCfStrings=*/true);
}
// Write to an output file.
}
}
-void macho::foldIdenticalSections() {
+void macho::foldIdenticalSections(bool onlyCfStrings) {
TimeTraceScope timeScope("Fold Identical Code Sections");
// The ICF equivalence-class segregation algorithm relies on pre-computed
// hashes of InputSection::data for the ConcatOutputSection::inputs and all
for (ConcatInputSection *isec : inputSections) {
// FIXME: consider non-code __text sections as hashable?
bool isHashable =
+ (!onlyCfStrings || isCfStringSection(isec)) &&
(isCodeSection(isec) || isCfStringSection(isec) ||
isClassRefsSection(isec) || isGccExceptTabSection(isec)) &&
!isec->keepUnique && !isec->shouldOmitFromOutput() &&
if (segname == segment_names::ld)
return target->wordSize == 8 ? 32 : 20;
}
- if (config->icfLevel == ICFLevel::none)
+ if (!config->dedupLiterals)
return {};
if (name == section_names::cfString && segname == segment_names::data)
return target->wordSize == 8 ? 32 : 16;
+
+ if (config->icfLevel == ICFLevel::none)
+ return {};
+
if (name == section_names::objcClassRefs && segname == segment_names::data)
return target->wordSize;
return {};
# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %t/foo1.s -o %t/foo1.o
# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %t/foo2.s -o %t/foo2.o
# RUN: %lld -dylib --icf=all -framework CoreFoundation %t/foo1.o %t/foo2.o -o %t/foo
-# RUN: llvm-objdump --macho --rebase --bind --syms -d %t/foo | FileCheck %s
+# RUN: llvm-objdump --macho --rebase --bind --syms -d %t/foo | FileCheck %s --check-prefixes=CHECK,LITERALS
+# RUN: %lld -dylib --deduplicate-literals -framework CoreFoundation %t/foo1.o %t/foo2.o -o %t/foo
+# RUN: llvm-objdump --macho --rebase --bind --syms -d %t/foo | FileCheck %s --check-prefix=LITERALS
# CHECK: (__TEXT,__text) section
# CHECK-NEXT: _foo1:
# CHECK-DAG: [[#FOO]] g F __TEXT,__text _foo2
## Make sure we don't emit redundant bind / rebase opcodes for folded sections.
-# CHECK: Rebase table:
-# CHECK-NEXT: segment section address type
-# CHECK-NEXT: __DATA_CONST __cfstring {{.*}} pointer
-# CHECK-NEXT: __DATA_CONST __cfstring {{.*}} pointer
-# CHECK-NEXT: __DATA_CONST __cfstring {{.*}} pointer
-# CHECK-EMPTY:
-# CHECK-NEXT: Bind table:
-# CHECK-NEXT: segment section address type addend dylib symbol
-# CHECK-NEXT: __DATA_CONST __cfstring {{.*}} pointer 0 CoreFoundation ___CFConstantStringClassReference
-# CHECK-NEXT: __DATA_CONST __cfstring {{.*}} pointer 0 CoreFoundation ___CFConstantStringClassReference
-# CHECK-NEXT: __DATA_CONST __cfstring {{.*}} pointer 0 CoreFoundation ___CFConstantStringClassReference
-# CHECK-EMPTY:
+# LITERALS: Rebase table:
+# LITERALS-NEXT: segment section address type
+# LITERALS-NEXT: __DATA_CONST __cfstring {{.*}} pointer
+# LITERALS-NEXT: __DATA_CONST __cfstring {{.*}} pointer
+# LITERALS-NEXT: __DATA_CONST __cfstring {{.*}} pointer
+# LITERALS-EMPTY:
+# LITERALS-NEXT: Bind table:
+# LITERALS-NEXT: segment section address type addend dylib symbol
+# LITERALS-NEXT: __DATA_CONST __cfstring {{.*}} pointer 0 CoreFoundation ___CFConstantStringClassReference
+# LITERALS-NEXT: __DATA_CONST __cfstring {{.*}} pointer 0 CoreFoundation ___CFConstantStringClassReference
+# LITERALS-NEXT: __DATA_CONST __cfstring {{.*}} pointer 0 CoreFoundation ___CFConstantStringClassReference
+# LITERALS-EMPTY:
#--- foo1.s
.cstring