diff --git a/bolt/lib/Core/MCPlusBuilder.cpp b/bolt/lib/Core/MCPlusBuilder.cpp index d8a2ac6f6837a..7f962e14ea115 100644 --- a/bolt/lib/Core/MCPlusBuilder.cpp +++ b/bolt/lib/Core/MCPlusBuilder.cpp @@ -30,6 +30,11 @@ using namespace bolt; using namespace MCPlus; namespace opts { +cl::opt + TerminalHLT("terminal-x86-hlt", + cl::desc("Assume that execution stops at x86 HLT instruction"), + cl::init(true), cl::Hidden, cl::cat(BoltCategory)); + cl::opt TerminalTrap("terminal-trap", cl::desc("Assume that execution stops at trap instruction"), @@ -132,10 +137,13 @@ bool MCPlusBuilder::equals(const MCSpecifierExpr &A, const MCSpecifierExpr &B, } bool MCPlusBuilder::isTerminator(const MCInst &Inst) const { - return (opts::TerminalTrap && Info->get(Inst.getOpcode()).isTrap()) || - Analysis->isTerminator(Inst) - ? !isX86HLT(Inst) - : false; + if (isX86HLT(Inst)) + return opts::TerminalHLT; + + if (Info->get(Inst.getOpcode()).isTrap()) + return opts::TerminalTrap; + + return Analysis->isTerminator(Inst); } void MCPlusBuilder::setTailCall(MCInst &Inst) const { diff --git a/bolt/lib/Rewrite/RewriteInstance.cpp b/bolt/lib/Rewrite/RewriteInstance.cpp index fe4a23cc01382..b2056ba2380fb 100644 --- a/bolt/lib/Rewrite/RewriteInstance.cpp +++ b/bolt/lib/Rewrite/RewriteInstance.cpp @@ -84,6 +84,7 @@ extern cl::opt KeepNops; extern cl::opt Lite; extern cl::list ReorderData; extern cl::opt ReorderFunctions; +extern cl::opt TerminalHLT; extern cl::opt TerminalTrap; extern cl::opt TimeBuild; extern cl::opt TimeRewrite; @@ -2177,7 +2178,9 @@ void RewriteInstance::adjustCommandLineOptions() { if (!opts::KeepNops.getNumOccurrences()) opts::KeepNops = true; - // Linux kernel may resume execution after a trap instruction in some cases. + // Linux kernel may resume execution after a trap or x86 HLT instruction. + if (!opts::TerminalHLT.getNumOccurrences()) + opts::TerminalHLT = false; if (!opts::TerminalTrap.getNumOccurrences()) opts::TerminalTrap = false; } diff --git a/bolt/test/X86/cfg_build_hlt.s b/bolt/test/X86/cfg_build_hlt.s deleted file mode 100644 index a78134df34014..0000000000000 --- a/bolt/test/X86/cfg_build_hlt.s +++ /dev/null @@ -1,17 +0,0 @@ -## 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 diff --git a/bolt/test/X86/hlt-terminator.s b/bolt/test/X86/hlt-terminator.s new file mode 100644 index 0000000000000..3f67182fdf432 --- /dev/null +++ b/bolt/test/X86/hlt-terminator.s @@ -0,0 +1,24 @@ +## Check that HLT instruction is handled differently depending on the flags. +## It's a terminator in the user-level code, but the execution can resume in +## ring 0. + +# RUN: %clang %cflags %s -static -o %t.exe -nostdlib +# RUN: llvm-bolt %t.exe --print-cfg --print-only=main --terminal-x86-hlt=0 \ +# RUN: -o %t.ring0 2>&1 | FileCheck %s --check-prefix=CHECK-RING0 +# RUN: llvm-bolt %t.exe --print-cfg --print-only=main \ +# RUN: -o %t.ring3 2>&1 | FileCheck %s --check-prefix=CHECK-RING3 +# RUN: llvm-objdump -d %t.ring0 --print-imm-hex | FileCheck %s --check-prefix=CHECK-BIN + +# CHECK-RING0: BB Count : 1 +# CHECK-RING3: BB Count : 2 + +# CHECK-BIN:
: +# CHECK-BIN-NEXT: f4 hlt +# CHECK-BIN-NEXT: c3 retq + +.global main + .type main, %function +main: + hlt + retq +.size main, .-main