[llvm] [BOLT] Not use hlt as split point when build the CFG (PR #150963)

via llvm-commits llvm-commits at lists.llvm.org
Mon Jul 28 07:46:22 PDT 2025


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-bolt

Author: Haibo Jiang (Jianghibo)

<details>
<summary>Changes</summary>

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

``````````

</details>


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


More information about the llvm-commits mailing list