Skip to content

[BOLT] Skip FDE emission for patch functions #136224

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Apr 18, 2025
Merged

Conversation

maksfb
Copy link
Contributor

@maksfb maksfb commented Apr 17, 2025

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.

Note that we use named patches to fix function entry points and in that case they behave more like regular functions. Thus we issue FDEs for those.

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.
@llvmbot
Copy link
Member

llvmbot commented Apr 17, 2025

@llvm/pr-subscribers-bolt

Author: Maksim Panchenko (maksfb)

Changes

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.


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

2 Files Affected:

  • (modified) bolt/lib/Core/BinaryEmitter.cpp (+2-2)
  • (modified) bolt/test/AArch64/lite-mode.s (+7)
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.

@maksfb maksfb merged commit 0977a71 into llvm:main Apr 18, 2025
10 checks passed
IanWood1 pushed a commit to IanWood1/llvm-project that referenced this pull request May 6, 2025
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.

Note that we use named patches to fix function entry points and in that
case they behave more like regular functions. Thus we issue FDEs for
those.
IanWood1 pushed a commit to IanWood1/llvm-project that referenced this pull request May 6, 2025
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.

Note that we use named patches to fix function entry points and in that
case they behave more like regular functions. Thus we issue FDEs for
those.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants