From 4d80efe87d5c2f87c3fc73c88e54579bb70d7ff3 Mon Sep 17 00:00:00 2001 From: jianghaibo Date: Mon, 28 Jul 2025 22:43:43 +0800 Subject: [PATCH] [BOLT] Not use hlt as split point when build the CFG 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. --- bolt/include/bolt/Core/MCPlusBuilder.h | 4 ++++ bolt/lib/Core/MCPlusBuilder.cpp | 6 ++++-- bolt/lib/Target/X86/X86MCPlusBuilder.cpp | 4 ++++ bolt/test/X86/cfg_build_hlt.s | 17 +++++++++++++++++ 4 files changed, 29 insertions(+), 2 deletions(-) create mode 100644 bolt/test/X86/cfg_build_hlt.s diff --git a/bolt/include/bolt/Core/MCPlusBuilder.h b/bolt/include/bolt/Core/MCPlusBuilder.h index f902a8c43cd1d..e773250ce8734 100644 --- a/bolt/include/bolt/Core/MCPlusBuilder.h +++ b/bolt/include/bolt/Core/MCPlusBuilder.h @@ -740,6 +740,10 @@ class MCPlusBuilder { return false; } + /// Return true if the hlt instruction under the x86, otherwise, default to + /// false. + virtual bool isX86HLT(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/MCPlusBuilder.cpp b/bolt/lib/Core/MCPlusBuilder.cpp index fa8f4d1df308b..d8a2ac6f6837a 100644 --- a/bolt/lib/Core/MCPlusBuilder.cpp +++ b/bolt/lib/Core/MCPlusBuilder.cpp @@ -132,8 +132,10 @@ bool MCPlusBuilder::equals(const MCSpecifierExpr &A, const MCSpecifierExpr &B, } bool MCPlusBuilder::isTerminator(const MCInst &Inst) const { - return Analysis->isTerminator(Inst) || - (opts::TerminalTrap && Info->get(Inst.getOpcode()).isTrap()); + return (opts::TerminalTrap && Info->get(Inst.getOpcode()).isTrap()) || + Analysis->isTerminator(Inst) + ? !isX86HLT(Inst) + : false; } void MCPlusBuilder::setTailCall(MCInst &Inst) const { diff --git a/bolt/lib/Target/X86/X86MCPlusBuilder.cpp b/bolt/lib/Target/X86/X86MCPlusBuilder.cpp index a60c1a6bf156e..1842509dcc5e0 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 isX86HLT(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/cfg_build_hlt.s b/bolt/test/X86/cfg_build_hlt.s new file mode 100644 index 0000000000000..a78134df34014 --- /dev/null +++ b/bolt/test/X86/cfg_build_hlt.s @@ -0,0 +1,17 @@ +## Check CFG for halt instruction + +# RUN: %clang %cflags %s -static -o %t.exe -nostdlib +# RUN: llvm-bolt %t.exe --print-cfg --print-only=main -o %t 2>&1 | FileCheck %s --check-prefix=CHECK-CFG +# RUN: llvm-objdump -d %t --print-imm-hex | FileCheck %s --check-prefix=CHECK-BIN + +# CHECK-CFG: BB Count : 1 +# CHECK-BIN:
: +# CHECK-BIN-NEXT: f4 hlt +# CHECK-BIN-NEXT: c3 retq + +.global main + .type main, %function +main: + hlt + retq +.size main, .-main