-
Notifications
You must be signed in to change notification settings - Fork 12.6k
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
base: main
Are you sure you want to change the base?
Conversation
…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.
@llvm/pr-subscribers-bolt Author: Rin Dobrescu (Rin18) ChangesBy 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:
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
|
✅ With the latest revision this PR passed the C/C++ code formatter. |
There was a problem hiding this 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.
Thanks for pointing this out, I'll change the title and summary. |
@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. |
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 |
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 |
- Updated BOLT flags; unfortunately three functions still need to get skipped even with a patched LLVM with llvm/llvm-project#120267
I've added another test that is target independent. Is there anything else needed to approve this patch? |
I've tested this patch on an aarch64 python3.12 build and found that it allows BOLT to run without
These functions no longer need to be skipped when goto patch is applied:
|
@aaupov @rafaelauler Does it make sense to add aarch64 python3.12 to https://github.com/rafaelauler/bolt-tests/tree/main/test/AArch64 tests without |
@Rin18 that's great to hear! Looking forward to using this downstream. |
Yes, please make a PR there. |
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. |
I've also tested this patch on an aarch64
The |
There was a problem hiding this 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) |
There was a problem hiding this comment.
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.
if (Func && !Func->isInConstantIsland(SymAddress)) { | ||
if (const uint64_t SymOffset = SymAddress - Func->getAddress()) | ||
Func->addEntryPointAtOffset(SymOffset); | ||
} |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this 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
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.