Skip to content
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

[BOLT] Support computed goto and allow map addrs inside functions #120267

Open
wants to merge 6 commits into
base: main
Choose a base branch
from

Conversation

Rin18
Copy link

@Rin18 Rin18 commented Dec 17, 2024

Create entry points for addresses referenced by dynamic relocations and allow getNewFunctionOrDataAddress to map addrs inside functions. By adding addresses referenced by dynamic relocations as entry points, this patch fixes an issue where bolt fails on code using computing goto's. This also fixes a mapping issue with the bugfix from this PR: #117766.

…ic relocations and allow getNewFunctionOrDataAddress to map addrs inside functions.

By adding addresses referenced by dynamic relocations as entry points,
this patch fixes an issue where bolt fails on code using computing
goto's. This also fixes a mapping issue with the bugfix from this
PR: llvm#117766.
@llvmbot
Copy link
Member

llvmbot commented Dec 17, 2024

@llvm/pr-subscribers-bolt

Author: Rin Dobrescu (Rin18)

Changes

By adding addresses referenced by dynamic relocations as entry points, this patch fixes an issue where bolt fails on code using computing goto's. This also fixes a mapping issue with the bugfix from this PR: #117766.


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

2 Files Affected:

  • (modified) bolt/lib/Rewrite/RewriteInstance.cpp (+9-1)
  • (added) bolt/test/AArch64/computed-goto.s (+39)
diff --git a/bolt/lib/Rewrite/RewriteInstance.cpp b/bolt/lib/Rewrite/RewriteInstance.cpp
index 4329235d470497..55fcd6b6e782c4 100644
--- a/bolt/lib/Rewrite/RewriteInstance.cpp
+++ b/bolt/lib/Rewrite/RewriteInstance.cpp
@@ -2439,6 +2439,14 @@ void RewriteInstance::readDynamicRelocations(const SectionRef &Section,
     if (Symbol)
       SymbolIndex[Symbol] = getRelocationSymbol(InputFile, Rel);
 
+    const uint64_t SymAddress = SymbolAddress + Addend;
+    BinaryFunction *Func = BC->getBinaryFunctionContainingAddress(SymAddress);
+    if(Func){
+      const uint64_t FunctionOffset = SymAddress - Func->getAddress();
+      if(FunctionOffset)
+        Func->addEntryPointAtOffset(FunctionOffset);
+    }
+
     BC->addDynamicRelocation(Rel.getOffset(), Symbol, RType, Addend);
   }
 }
@@ -5599,7 +5607,7 @@ uint64_t RewriteInstance::getNewFunctionOrDataAddress(uint64_t OldAddress) {
         for (const BinaryBasicBlock &BB : *BF)
           if (BB.isEntryPoint() &&
               (BF->getAddress() + BB.getOffset()) == OldAddress)
-            return BF->getOutputAddress() + BB.getOffset();
+            return BB.getOutputStartAddress();
       }
       BC->errs() << "BOLT-ERROR: unable to get new address corresponding to "
                     "input address 0x"
diff --git a/bolt/test/AArch64/computed-goto.s b/bolt/test/AArch64/computed-goto.s
new file mode 100644
index 00000000000000..043f9a8e37e6b0
--- /dev/null
+++ b/bolt/test/AArch64/computed-goto.s
@@ -0,0 +1,39 @@
+# RUN: llvm-mc -filetype=obj -triple aarch64-unknown-unknown %s -o %t.o
+# RUN: %clang %cflags %t.o -o %t.exe -Wl,-q
+# RUN: llvm-bolt %t.exe -o %t.bolt 2>&1 | FileCheck %s
+
+## Before bolt could handle mapping addresses within moved functions, it
+## would bail out with an error of the form:
+## BOLT-ERROR: unable to get new address corresponding to input address 0x10390 in function main. Consider adding this function to --skip-funcs=...
+## These addresses arise if computed GOTO is in use.
+## Check that bolt does not emit any error.
+
+# CHECK-NOT: BOLT-ERROR
+
+.globl  main
+.p2align        2
+.type   main,@function
+main:
+.cfi_startproc
+        adrp    x8, .L__const.main.ptrs+8
+        add     x8, x8, :lo12:.L__const.main.ptrs+8
+        ldr     x9, [x8], #8
+        br      x9
+
+.Label0: // Block address taken
+        ldr     x9, [x8], #8
+        br      x9
+
+.Label1: // Block address taken
+        mov     w0, #42
+        ret
+
+.Lfunc_end0:
+.size   main, .Lfunc_end0-main
+.cfi_endproc
+        .type   .L__const.main.ptrs,@object
+        .section        .data.rel.ro,"aw",@progbits
+        .p2align        3, 0x0
+.L__const.main.ptrs:
+        .xword  .Label0
+        .xword  .Label1

Copy link

github-actions bot commented Dec 17, 2024

✅ With the latest revision this PR passed the C/C++ code formatter.

Copy link
Contributor

@aaupov aaupov left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good overall. The PR isn't limited to AArch64, so please drop that from the title. Please make the title more concise, e.g. "Support computed goto", expanding what is changed in the summary.

bolt/lib/Rewrite/RewriteInstance.cpp Outdated Show resolved Hide resolved
bolt/lib/Rewrite/RewriteInstance.cpp Outdated Show resolved Hide resolved
bolt/test/AArch64/computed-goto.s Show resolved Hide resolved
@Rin18 Rin18 changed the title [BOLT][AArch64] Create entry points for addresses referenced by dynamic relocations and allow getNewFunctionOrDataAddress to map addrs inside functions. [BOLT] Support computed goto and allow map addrs inside functions. Dec 18, 2024
@Rin18
Copy link
Author

Rin18 commented Dec 18, 2024

Looks good overall. The PR isn't limited to AArch64, so please drop that from the title. Please make the title more concise, e.g. "Support computed goto", expanding what is changed in the summary.

Thanks for pointing this out, I'll change the title and summary.

@ms178
Copy link

ms178 commented Jan 1, 2025

@Rin18 FYI, this patch might help to improve the usage of BOLT in Python as discussed in a related Python issue, see the comment and discussion in: python/cpython#124948 (comment)

Maybe it is a good test case for this MR, too.

@Rin18
Copy link
Author

Rin18 commented Jan 2, 2025

@Rin18 FYI, this patch might help to improve the usage of BOLT in Python as discussed in a related Python issue, see the comment and discussion in: python/cpython#124948 (comment)

Maybe it is a good test case for this MR, too.

Thanks for bringing this to my attention, I'll need to look into the mentioned issue and see if this patch impacts it.

@ms178
Copy link

ms178 commented Jan 2, 2025

Thanks for bringing this to my attention, I'll need to look into the mentioned issue and see if this patch impacts it.

Great, please also notice some downstream work on the python side which works around the current BOLT issues and might provide some hints: astral-sh/python-build-standalone#463

Ideally, there should be no need to use --skip-funcs=sre_ucs1_match/1,_PyEval_EvalFrameDefault.localalias/1

@Rin18
Copy link
Author

Rin18 commented Jan 3, 2025

Thanks for bringing this to my attention, I'll need to look into the mentioned issue and see if this patch impacts it.

Great, please also notice some downstream work on the python side which works around the current BOLT issues and might provide some hints: astral-sh/python-build-standalone#463

Ideally, there should be no need to use --skip-funcs=sre_ucs1_match/1,_PyEval_EvalFrameDefault.localalias/1

I've taken a look at the link to the issue you've mentioned. This patch provides support for computed goto's. Once the PR is merged, it should get rid of the need to provide the --skip-funcs flag.

ms178 added a commit to ms178/archpkgbuilds that referenced this pull request Jan 10, 2025
- Updated BOLT flags; unfortunately three functions still need to get skipped even with a patched LLVM with llvm/llvm-project#120267
@Rin18
Copy link
Author

Rin18 commented Jan 20, 2025

I've added another test that is target independent. Is there anything else needed to approve this patch?

@Rin18
Copy link
Author

Rin18 commented Jan 23, 2025

I've tested this patch on an aarch64 python3.12 build and found that it allows BOLT to run without --skip-funcs flags.
Without this patch the following error occurs:

llvm-bolt -o test.out.bolt python3.12
BOLT-ERROR: unable to get new address corresponding to input address 0x1b3f14 in function sre_ucs1_match/1. Consider adding this function to --skip-funcs=...

These functions no longer need to be skipped when goto patch is applied:

sre_ucs1_match/1; sre_ucs2_match/1; sre_ucs4_match/1; _PyEval_EvalFrameDefault.localalias/1

@ilinpv
Copy link
Contributor

ilinpv commented Jan 23, 2025

@aaupov @rafaelauler Does it make sense to add aarch64 python3.12 to https://github.com/rafaelauler/bolt-tests/tree/main/test/AArch64 tests without --skip-funcs when the patch merged?

@zanieb
Copy link

zanieb commented Jan 23, 2025

@Rin18 that's great to hear! Looking forward to using this downstream.

@aaupov
Copy link
Contributor

aaupov commented Jan 23, 2025

@aaupov @rafaelauler Does it make sense to add aarch64 python3.12 to https://github.com/rafaelauler/bolt-tests/tree/main/test/AArch64 tests without --skip-funcs when the patch merged?

Yes, please make a PR there.

@ms178
Copy link

ms178 commented Jan 23, 2025

I've tested this patch on an aarch64 python3.12 build and found that it allows BOLT to run without --skip-funcs flags. Without this patch the following error occurs:

llvm-bolt -o test.out.bolt python3.12
BOLT-ERROR: unable to get new address corresponding to input address 0x1b3f14 in function sre_ucs1_match/1. Consider adding this function to --skip-funcs=...

These functions no longer need to be skipped when goto patch is applied:

sre_ucs1_match/1; sre_ucs2_match/1; sre_ucs4_match/1; _PyEval_EvalFrameDefault.localalias/1

I can confirm that it works on Intel Raptor Lake as well. With this patch applied to e4f03b1, compiling python 3.13.1 with --enable-bolt does work now which previously did not.

@Rin18
Copy link
Author

Rin18 commented Jan 28, 2025

I've also tested this patch on an aarch64 postgres build and found that it allows BOLT to run without --skip-funcs flags.
Without this patch the following error occurs:

llvm-bolt -o test.out.bolt postgres
BOLT-ERROR: unable to get new address corresponding to input address 0x2cb1b0 in function ExecInterpExpr/1(*2). Consider adding this function to --skip-funcs=...

The ExecInterpExpr/1 function no longer need to be skipped when goto patch is applied.

Copy link
Contributor

@maksfb maksfb left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for the PR!

@@ -5599,7 +5606,7 @@ uint64_t RewriteInstance::getNewFunctionOrDataAddress(uint64_t OldAddress) {
for (const BinaryBasicBlock &BB : *BF)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not directly related to your change, but we should use BinaryFunction::forEachEntryPoint() here.

Comment on lines +2444 to +2447
if (Func && !Func->isInConstantIsland(SymAddress)) {
if (const uint64_t SymOffset = SymAddress - Func->getAddress())
Func->addEntryPointAtOffset(SymOffset);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we add more checks? E.g., what happens if Symbol points to a function and SymAddress falls into another function? What if the reference is in the constant island? It's better to fail at build time.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll look into adding more checks.

bolt/test/AArch64/computed-goto.s Outdated Show resolved Hide resolved
bolt/test/dynamic-relocs.test Outdated Show resolved Hide resolved
bolt/test/dynamic-relocs.test Outdated Show resolved Hide resolved
Copy link
Contributor

@aaupov aaupov left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me, thank you for working on this.
Please address the feedback from Maksim.

small nit: please drop trailing dot in the title

bolt/test/dynamic-relocs.test Outdated Show resolved Hide resolved
@Rin18 Rin18 changed the title [BOLT] Support computed goto and allow map addrs inside functions. [BOLT] Support computed goto and allow map addrs inside functions Jan 31, 2025
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.

9 participants