-
Notifications
You must be signed in to change notification settings - Fork 14.9k
[BOLT] Do not use HLT as split point when build the CFG #150963
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
Conversation
Thank you for submitting a Pull Request (PR) to the LLVM Project! This PR will be automatically labeled and the relevant teams will be notified. If you wish to, you can add reviewers by using the "Reviewers" section on this page. If this is not working for you, it is probably because you do not have write permissions for the repository. In which case you can instead tag reviewers by name in a comment by using If you have received no comments on your PR for a week, you can request a review by "ping"ing the PR by adding a comment “Ping”. The common courtesy "ping" rate is once a week. Please remember that you are asking for valuable time from other developers. If you have further questions, they may be answered by the LLVM GitHub User Guide. You can also ask questions in a comment on this PR, on the LLVM Discord or on the forums. |
@llvm/pr-subscribers-bolt Author: Haibo Jiang (Jianghibo) ChangesFor x86, the halt instruction is defined as a terminator instruction. When building the CFG, the instruction sequence following the hlt instruction is treated as an independent MBB. Since there is no jump information, the predecessor of this MBB cannot be identified, and it is considered an unreachable MBB that will be removed. Using this fix, the instruction sequences before and after hlt are refused to be placed in different blocks. Full diff: https://github.com/llvm/llvm-project/pull/150963.diff 4 Files Affected:
diff --git a/bolt/include/bolt/Core/MCPlusBuilder.h b/bolt/include/bolt/Core/MCPlusBuilder.h
index f902a8c43cd1d..b698ce54d6899 100644
--- a/bolt/include/bolt/Core/MCPlusBuilder.h
+++ b/bolt/include/bolt/Core/MCPlusBuilder.h
@@ -740,6 +740,9 @@ class MCPlusBuilder {
return false;
}
+ /// Return true if the hlt instruction is defind as terminator
+ virtual bool isTerminatorHLT(const MCInst &Inst) const { return false; }
+
/// Return the width, in bytes, of the memory access performed by \p Inst, if
/// this is a pop instruction. Return zero otherwise.
virtual int getPopSize(const MCInst &Inst) const {
diff --git a/bolt/lib/Core/BinaryFunction.cpp b/bolt/lib/Core/BinaryFunction.cpp
index eec68ff5a5fce..0f904b679365f 100644
--- a/bolt/lib/Core/BinaryFunction.cpp
+++ b/bolt/lib/Core/BinaryFunction.cpp
@@ -2329,11 +2329,12 @@ Error BinaryFunction::buildCFG(MCPlusBuilder::AllocatorIdTy AllocatorId) {
assert(PrevBB && "no previous basic block for a fall through");
MCInst *PrevInstr = PrevBB->getLastNonPseudoInstr();
assert(PrevInstr && "no previous instruction for a fall through");
- if (MIB->isUnconditionalBranch(Instr) &&
+ if ((MIB->isUnconditionalBranch(Instr) &&
!MIB->isIndirectBranch(*PrevInstr) &&
!MIB->isUnconditionalBranch(*PrevInstr) &&
!MIB->getConditionalTailCall(*PrevInstr) &&
- !MIB->isReturn(*PrevInstr)) {
+ !MIB->isReturn(*PrevInstr)) ||
+ MIB->isTerminatorHLT(*PrevInstr)) {
// Temporarily restore inserter basic block.
InsertBB = PrevBB;
} else {
diff --git a/bolt/lib/Target/X86/X86MCPlusBuilder.cpp b/bolt/lib/Target/X86/X86MCPlusBuilder.cpp
index a60c1a6bf156e..090d933a1e66a 100644
--- a/bolt/lib/Target/X86/X86MCPlusBuilder.cpp
+++ b/bolt/lib/Target/X86/X86MCPlusBuilder.cpp
@@ -223,6 +223,10 @@ class X86MCPlusBuilder : public MCPlusBuilder {
return Inst.getOpcode() == X86::ENDBR32 || Inst.getOpcode() == X86::ENDBR64;
}
+ bool isTerminatorHLT(const MCInst &Inst) const override {
+ return Inst.getOpcode() == X86::HLT;
+ }
+
int getPopSize(const MCInst &Inst) const override {
switch (Inst.getOpcode()) {
case X86::POP16r:
diff --git a/bolt/test/X86/static-exe.test b/bolt/test/X86/static-exe.test
index e288160da1521..5d9b389d6ccca 100644
--- a/bolt/test/X86/static-exe.test
+++ b/bolt/test/X86/static-exe.test
@@ -1,6 +1,9 @@
## Check that llvm-bolt can rewrite static executable
+## And check CFG for halt instruction
RUN: %clang %cflags %S/Inputs/static_exe.s -static -o %t.exe -nostdlib
RUN: llvm-bolt %t.exe -o %t 2>&1 | FileCheck %s
+RUN: llvm-bolt %t.exe --print-cfg -o %t 2>&1 | FileCheck --check-prefix=CHECK-CFG
CHECK: 1 out of 1 functions were overwritten
+CHECK-CFG: BB Count : 1
|
Thanks for the PR. Could you please provide more context? I'm guessing the fix is for the kernel code. For the implementation, let's change how |
@maksfb Thanks for your review. I checked the definition of the hlt instruction under the x86 architecture, and it is defined as a terminator. |
Right. We don't want to change LLVM's definition, but for BOLT's CFG-building purposes we should treat it as non-terminator, that's why I propose to change |
dce028b
to
536fec3
Compare
updated the implementation. |
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.
Thanks for addressing the feedback and adding a new test case. Please see the comments inlined.
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.
Lets rename to isX86HLT()
or alternatively override isTerminator()
for X86MCPlusBuilder
.
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.
done.
bolt/test/X86/Inputs/cfg_build_hlt.s
Outdated
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.
Since we are not interested in other instructions, just leave hlt
followed by retq
.
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.
done.
bolt/test/X86/cfg_build_hlt.test
Outdated
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.
It's more convenient to combine *.s
sources with the test in the same file. Check double-rel.s
for example.
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.
Done, thanks
536fec3
to
76b0ce7
Compare
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.
Thanks. Please address a couple of minor nits and it's good to go.
bolt/test/X86/cfg_build_hlt.s
Outdated
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.
Let's remove these lines too.
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.
updated
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.
gentle ping.
bolt/test/X86/cfg_build_hlt.s
Outdated
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.
Add --print-only=main
to make sure we are looking at main()
.
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.
updated
76b0ce7
to
86a61ab
Compare
@maksfb Hi, is there any other comment? |
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.
Thanks!
@maksfb Hi, could you help to approve me to run these two workflows? It seems that since this is my first time submitting code, I don't have sufficient permissions to run these two workflows and merge PR. Thanks. |
✅ With the latest revision this PR passed the C/C++ code formatter. |
For x86, the halt instruction is defined as a terminator instruction. When building the CFG, the instruction sequence following the hlt instruction is treated as an independent MBB. Since there is no jump information, the predecessor of this MBB cannot be identified, and it is considered an unreachable MBB that will be removed. Using this fix, the instruction sequences before and after hlt are refused to be placed in different blocks.
7f54066
to
4d80efe
Compare
@maksfb could you help to merge this pr? thanks. |
@Jianghibo Congratulations on having your first Pull Request (PR) merged into the LLVM Project! Your changes will be combined with recent changes from other authors, then tested by our build bots. If there is a problem with a build, you may receive a report in an email or a comment on this PR. Please check whether problems have been caused by your change specifically, as the builds can include changes from many authors. It is not uncommon for your change to be included in a build that fails due to someone else's changes, or infrastructure issues. How to do this, and the rest of the post-merge process, is covered in detail here. If your change does cause a problem, it may be reverted, or you can revert it yourself. This is a normal part of LLVM development. You can fix your changes and open a new PR to merge them again. If you don't get any reports, no action is required from you. Your changes are working as expected, well done! |
This is a follow-up to llvm#150963. X86 HLT instruction may appear in the user-level code, in which case we should treat it as a terminator. Handle it as a non-terminator in the Linux kernel mode.
This is a follow-up to #150963. X86 HLT instruction may appear in the user-level code, in which case we should treat it as a terminator. Handle it as a non-terminator in the Linux kernel mode.
For x86, the halt instruction is defined as a terminator instruction. When building the CFG, the instruction sequence following the hlt instruction is treated as an independent MBB. Since there is no jump information, the predecessor of this MBB cannot be identified, and it is considered an unreachable MBB that will be removed.
Using this fix, the instruction sequences before and after hlt are refused to be placed in different blocks.