[llvm] [BOLT][AArch64] Enable safe ICF (PR #170172)

via llvm-commits llvm-commits at lists.llvm.org
Mon Dec 1 09:19:47 PST 2025


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-bolt

Author: YongKang Zhu (yozhu)

<details>
<summary>Changes</summary>

All the pieces required seem to have already been in place so just need to enable the option. Also added one more prefix string for vtable recognition.

---
Full diff: https://github.com/llvm/llvm-project/pull/170172.diff


2 Files Affected:

- (modified) bolt/lib/Passes/IdenticalCodeFolding.cpp (+5-3) 
- (added) bolt/test/AArch64/safe-icf.s (+73) 


``````````diff
diff --git a/bolt/lib/Passes/IdenticalCodeFolding.cpp b/bolt/lib/Passes/IdenticalCodeFolding.cpp
index 8923562776cc4..9a8f79ea7de0e 100644
--- a/bolt/lib/Passes/IdenticalCodeFolding.cpp
+++ b/bolt/lib/Passes/IdenticalCodeFolding.cpp
@@ -377,7 +377,8 @@ namespace bolt {
 void IdenticalCodeFolding::initVTableReferences(const BinaryContext &BC) {
   for (const auto &[Address, Data] : BC.getBinaryData()) {
     // Filter out all symbols that are not vtables.
-    if (!Data->getName().starts_with("_ZTV"))
+    if (!Data->getName().starts_with("_ZTV") && // vtable
+        !Data->getName().starts_with("_ZTCN"))  // construction vtable
       continue;
     for (uint64_t I = Address, End = I + Data->getSize(); I < End; I += 8)
       setAddressUsedInVTable(I);
@@ -437,8 +438,9 @@ void IdenticalCodeFolding::markFunctionsUnsafeToFold(BinaryContext &BC) {
   NamedRegionTimer MarkFunctionsUnsafeToFoldTimer(
       "markFunctionsUnsafeToFold", "markFunctionsUnsafeToFold", "ICF breakdown",
       "ICF breakdown", opts::TimeICF);
-  if (!BC.isX86())
-    BC.outs() << "BOLT-WARNING: safe ICF is only supported for x86\n";
+  if (!BC.isX86() && !BC.isAArch64())
+    BC.outs()
+        << "BOLT-WARNING: safe ICF is only supported for x86 and AArch64\n";
   analyzeDataRelocations(BC);
   analyzeFunctions(BC);
 }
diff --git a/bolt/test/AArch64/safe-icf.s b/bolt/test/AArch64/safe-icf.s
new file mode 100644
index 0000000000000..bb8681c13c771
--- /dev/null
+++ b/bolt/test/AArch64/safe-icf.s
@@ -0,0 +1,73 @@
+# Test BOLT can do safe ICF for AArch64.
+
+# REQUIRES: system-linux,asserts
+
+# RUN: %clang %cflags -x assembler-with-cpp %s -o %t1.so -Wl,-q \
+# RUN:    -Wl,-z,notext -DREF_BY_NON_CONTROL_FLOW_INSTR
+# RUN: %clang %cflags -x assembler-with-cpp %s -o %t2.so -Wl,-q \
+# RUN:    -Wl,-z,notext -DREF_IN_RW_DATA_SEC
+# RUN: %clang %cflags -x assembler-with-cpp %s -o %t3.so -Wl,-q \
+# RUN:    -Wl,-z,notext -DNO_DUMMY_TEXT_RELOC
+
+# RUN: llvm-bolt %t1.so -o %t.bolt --no-threads --debug-only=bolt-icf \
+# RUN:   --icf=all 2>&1 | FileCheck %s --check-prefix=ICF-ALL
+# RUN: llvm-bolt %t2.so -o %t.bolt --no-threads --debug-only=bolt-icf \
+# RUN:   --icf=all 2>&1 | FileCheck %s --check-prefix=ICF-ALL
+# RUN: llvm-bolt %t3.so -o %t.bolt --no-threads --debug-only=bolt-icf \
+# RUN:   --icf=all 2>&1 | FileCheck %s --check-prefix=ICF-ALL
+
+# RUN: llvm-bolt %t1.so -o %t.bolt --no-threads --debug-only=bolt-icf \
+# RUN:   --icf=safe 2>&1 | FileCheck %s --check-prefix=ICF-SAFE
+# RUN: llvm-bolt %t2.so -o %t.bolt --no-threads --debug-only=bolt-icf \
+# RUN:   --icf=safe 2>&1 | FileCheck %s --check-prefix=ICF-SAFE
+
+# RUN: not llvm-bolt %t3.so -o %t.bolt --icf=safe 2>&1 | FileCheck %s \
+# RUN:   --check-prefix=ERROR
+
+# ICF-ALL:  folding bar into foo
+# ICF-SAFE: skipping function with reference taken foo
+# ERROR:    binary built without relocations. Safe ICF is not supported
+
+  .text
+
+  .global foo
+  .type foo, %function
+foo:
+  mov x0, #0x10
+  ret
+
+  .global bar
+  .type bar, %function
+bar:
+  mov x0, #0x10
+  ret
+
+#if defined(REF_IN_RW_DATA_SEC) && !defined(NO_DUMMY_TEXT_RELOC)
+  # Dummy relocation to force relocation mode
+  .reloc 0, R_AARCH64_NONE
+#endif
+
+#if defined(REF_BY_NON_CONTROL_FLOW_INSTR)
+  .global random
+  .type random, %function
+random:
+  adrp x8, foo
+  add  x8, x8, :lo12:goo
+  br   x8
+#endif
+
+#if defined(REF_IN_RW_DATA_SEC)
+  .data
+  .balign 8
+  .global funcptr
+funcptr:
+  .xword foo
+#endif
+
+  .section .rodata
+  .global _ZTVxx
+  .balign 8
+_ZTVxx:
+  .xword foo
+  .xword bar
+  .size _ZTVxx, .-_ZTVxx

``````````

</details>


https://github.com/llvm/llvm-project/pull/170172


More information about the llvm-commits mailing list