[llvm] [BOLT] Skip FDE emission for patch functions (PR #136224)

Maksim Panchenko via llvm-commits llvm-commits at lists.llvm.org
Thu Apr 17 18:20:02 PDT 2025


https://github.com/maksfb updated https://github.com/llvm/llvm-project/pull/136224

>From 2316b4f9e4f363ba9cb1b533664b3c3429b03c0d Mon Sep 17 00:00:00 2001
From: Maksim Panchenko <maks at fb.com>
Date: Thu, 17 Apr 2025 16:24:20 -0700
Subject: [PATCH 1/2] [BOLT] Skip FDE emission for patch functions

Patch functions are used to fix instructions in the original code, i.e.,
they are not functions in a traditional sense, but rather pieces of
emitted code that are embedded into real functions.

We used to emit FDEs for all functions, including patch functions.
However, FDEs for patches are not only unnecessary, but they can lead to
problems with libraries and runtimes that consume FDEs, e.g. C++
exception handling runtime.
---
 bolt/lib/Core/BinaryEmitter.cpp | 4 ++--
 bolt/test/AArch64/lite-mode.s   | 7 +++++++
 2 files changed, 9 insertions(+), 2 deletions(-)

diff --git a/bolt/lib/Core/BinaryEmitter.cpp b/bolt/lib/Core/BinaryEmitter.cpp
index d3ed9e8088bfa..3414fc938719b 100644
--- a/bolt/lib/Core/BinaryEmitter.cpp
+++ b/bolt/lib/Core/BinaryEmitter.cpp
@@ -374,7 +374,7 @@ bool BinaryEmitter::emitFunction(BinaryFunction &Function,
   }
 
   // Emit CFI start
-  if (Function.hasCFI()) {
+  if (Function.hasCFI() && !Function.isPatch()) {
     Streamer.emitCFIStartProc(/*IsSimple=*/false);
     if (Function.getPersonalityFunction() != nullptr)
       Streamer.emitCFIPersonality(Function.getPersonalityFunction(),
@@ -421,7 +421,7 @@ bool BinaryEmitter::emitFunction(BinaryFunction &Function,
     Streamer.emitBytes(BC.MIB->getTrapFillValue());
 
   // Emit CFI end
-  if (Function.hasCFI())
+  if (Function.hasCFI() && !Function.isPatch())
     Streamer.emitCFIEndProc();
 
   MCSymbol *EndSymbol = Function.getFunctionEndLabel(FF.getFragmentNum());
diff --git a/bolt/test/AArch64/lite-mode.s b/bolt/test/AArch64/lite-mode.s
index d81206089aaef..a71edbe034669 100644
--- a/bolt/test/AArch64/lite-mode.s
+++ b/bolt/test/AArch64/lite-mode.s
@@ -11,6 +11,13 @@
 # RUN: llvm-objdump -d --disassemble-symbols=cold_function %t.bolt \
 # RUN:   | FileCheck %s
 
+
+## Verify that the number of FDEs matches the number of functions in the output
+## binary. There are three original functions and two optimized.
+# RUN: llvm-readelf -u %t.bolt | grep -wc FDE \
+# RUN:   | FileCheck --check-prefix=CHECK-FDE %s
+# CHECK-FDE: 5
+
 ## In lite mode, optimized code will be separated from the original .text by
 ## over 128MB, making it impossible for call/bl instructions in cold functions
 ## to reach optimized functions directly.

>From 48fb62778363bd0576f4c6d7b9eaa56625e9b98c Mon Sep 17 00:00:00 2001
From: Maksim Panchenko <maks at fb.com>
Date: Thu, 17 Apr 2025 18:19:51 -0700
Subject: [PATCH 2/2] fixup! [BOLT] Skip FDE emission for patch functions

---
 bolt/lib/Core/BinaryEmitter.cpp | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/bolt/lib/Core/BinaryEmitter.cpp b/bolt/lib/Core/BinaryEmitter.cpp
index 3414fc938719b..7b5cd276fee89 100644
--- a/bolt/lib/Core/BinaryEmitter.cpp
+++ b/bolt/lib/Core/BinaryEmitter.cpp
@@ -373,8 +373,10 @@ bool BinaryEmitter::emitFunction(BinaryFunction &Function,
     Streamer.emitLabel(StartSymbol);
   }
 
+  const bool NeedsFDE =
+      Function.hasCFI() && !(Function.isPatch() && Function.isAnonymous());
   // Emit CFI start
-  if (Function.hasCFI() && !Function.isPatch()) {
+  if (NeedsFDE) {
     Streamer.emitCFIStartProc(/*IsSimple=*/false);
     if (Function.getPersonalityFunction() != nullptr)
       Streamer.emitCFIPersonality(Function.getPersonalityFunction(),
@@ -421,7 +423,7 @@ bool BinaryEmitter::emitFunction(BinaryFunction &Function,
     Streamer.emitBytes(BC.MIB->getTrapFillValue());
 
   // Emit CFI end
-  if (Function.hasCFI() && !Function.isPatch())
+  if (NeedsFDE)
     Streamer.emitCFIEndProc();
 
   MCSymbol *EndSymbol = Function.getFunctionEndLabel(FF.getFragmentNum());



More information about the llvm-commits mailing list