Skip to content

Conversation

Jianghibo
Copy link
Contributor

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.

Copy link

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 @ followed by their GitHub username.

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.

@llvmbot llvmbot added the BOLT label Jul 28, 2025
@llvmbot
Copy link
Member

llvmbot commented Jul 28, 2025

@llvm/pr-subscribers-bolt

Author: Haibo Jiang (Jianghibo)

Changes

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.


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

4 Files Affected:

  • (modified) bolt/include/bolt/Core/MCPlusBuilder.h (+3)
  • (modified) bolt/lib/Core/BinaryFunction.cpp (+3-2)
  • (modified) bolt/lib/Target/X86/X86MCPlusBuilder.cpp (+4)
  • (modified) bolt/test/X86/static-exe.test (+3)
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

@maksfb
Copy link
Contributor

maksfb commented Jul 28, 2025

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 MCPlusBuilder::isTerminator() handles HLT instruction and add a dedicated test case.

@Jianghibo
Copy link
Contributor Author

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 MCPlusBuilder::isTerminator() handles HLT instruction and add a dedicated test case.

@maksfb Thanks for your review.
yeah, I am trying to optimize the Linux kernel 5.10 for openEuler using llvm-bolt, and I encountered an error caused by the hlt instruction.
image

I checked the definition of the hlt instruction under the x86 architecture, and it is defined as a terminator.
image

@maksfb
Copy link
Contributor

maksfb commented Jul 29, 2025

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 MCPlusBuilder::isTerminator().

@Jianghibo Jianghibo force-pushed the fix-bolt-handle-hlt branch from dce028b to 536fec3 Compare July 29, 2025 14:40
@Jianghibo Jianghibo requested a review from yozhu as a code owner July 29, 2025 14:40
@Jianghibo
Copy link
Contributor Author

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 MCPlusBuilder::isTerminator().

updated the implementation.

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.

Thanks for addressing the feedback and adding a new test case. Please see the comments inlined.

Copy link
Contributor

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.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done.

Comment on lines 4 to 8
Copy link
Contributor

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.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done.

Copy link
Contributor

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.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done, thanks

@Jianghibo Jianghibo force-pushed the fix-bolt-handle-hlt branch from 536fec3 to 76b0ce7 Compare July 30, 2025 12:44
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.

Thanks. Please address a couple of minor nits and it's good to go.

Comment on lines 17 to 18
Copy link
Contributor

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.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

updated

Copy link
Contributor Author

Choose a reason for hiding this comment

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

gentle ping.

Copy link
Contributor

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().

Copy link
Contributor Author

Choose a reason for hiding this comment

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

updated

@Jianghibo Jianghibo force-pushed the fix-bolt-handle-hlt branch from 76b0ce7 to 86a61ab Compare August 1, 2025 14:08
@Jianghibo
Copy link
Contributor Author

@maksfb Hi, is there any other comment?

@Jianghibo Jianghibo requested a review from maksfb August 13, 2025 02:59
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.

Thanks!

@maksfb maksfb changed the title [BOLT] Not use hlt as split point when build the CFG [BOLT] Do not use HLT as split point when build the CFG Aug 14, 2025
@Jianghibo
Copy link
Contributor Author

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.
image

Thanks.

Copy link

github-actions bot commented Aug 15, 2025

✅ 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.
@Jianghibo Jianghibo force-pushed the fix-bolt-handle-hlt branch from 7f54066 to 4d80efe Compare August 15, 2025 08:17
@Jianghibo
Copy link
Contributor Author

@maksfb could you help to merge this pr? thanks.

@maksfb maksfb merged commit 21a5729 into llvm:main Aug 15, 2025
9 checks passed
Copy link

@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!

@Jianghibo Jianghibo deleted the fix-bolt-handle-hlt branch August 16, 2025 01:25
maksfb added a commit to maksfb/llvm-project that referenced this pull request Aug 19, 2025
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.
maksfb added a commit that referenced this pull request Aug 19, 2025
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.
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