Skip to content

Commit 9eb80ab

Browse files
[llvm-exegesis] Set stack pointer register after starting perf counter (#72489)
Before this patch, in subprocess mode, llvm-exegesis setup the stack pointer register with the rest of the registers when it was requested by the user. This would cause a segfault when the instructions to start the perf counter ran as they use the stack to preserve the three registers needed to make the syscall. This patch moves the setup of the stack register to after the configuration of the perf counter to fix this issue so that we have a valid stack pointer for all the preceeding operations. Regression test added. This fixes #72193.
1 parent e2a37e5 commit 9eb80ab

File tree

2 files changed

+41
-0
lines changed

2 files changed

+41
-0
lines changed
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# REQUIRES: exegesis-can-execute-x86_64
2+
3+
# RUN: llvm-exegesis -mtriple=x86_64-unknown-unknown -mode=latency -snippets-file=%s -execution-mode=subprocess | FileCheck %s
4+
5+
# Check that we can set the value of RSP in subprocess mode without
6+
# segfaulting as we need to restore it after the rest of the setup is
7+
# complete to prevent loading from the stack where we set it instead
8+
# of where the stack actuall is.
9+
10+
# LLVM-EXEGESIS-MEM-DEF test1 4096 2147483647
11+
# LLVM-EXEGESIS-MEM-MAP test1 1048576
12+
# LLVM-EXEGESIS-DEFREG RAX 100000
13+
# LLVM-EXEGESIS-DEFREG R14 100000
14+
# LLVM-EXEGESIS-DEFREG RSP 100000
15+
16+
movq %r14, (%rax)
17+
18+
# CHECK-NOT: error: 'The benchmarking subprocess sent unexpected signal: Segmentation fault'

llvm/tools/llvm-exegesis/lib/Assembler.cpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include "llvm/CodeGen/MachineModuleInfo.h"
2020
#include "llvm/CodeGen/MachineRegisterInfo.h"
2121
#include "llvm/CodeGen/TargetInstrInfo.h"
22+
#include "llvm/CodeGen/TargetLowering.h"
2223
#include "llvm/CodeGen/TargetPassConfig.h"
2324
#include "llvm/CodeGen/TargetSubtargetInfo.h"
2425
#include "llvm/ExecutionEngine/Orc/LLJIT.h"
@@ -60,7 +61,17 @@ static bool generateSnippetSetupCode(
6061
}
6162
BBF.addInstructions(ET.setStackRegisterToAuxMem());
6263
}
64+
Register StackPointerRegister = BBF.MF.getSubtarget()
65+
.getTargetLowering()
66+
->getStackPointerRegisterToSaveRestore();
6367
for (const RegisterValue &RV : RegisterInitialValues) {
68+
if (GenerateMemoryInstructions) {
69+
// If we're generating memory instructions, don't load in the value for
70+
// the register with the stack pointer as it will be used later to finish
71+
// the setup.
72+
if (RV.Register == StackPointerRegister)
73+
continue;
74+
}
6475
// Load a constant in the register.
6576
const auto SetRegisterCode = ET.setRegTo(*MSI, RV.Register, RV.Value);
6677
if (SetRegisterCode.empty())
@@ -71,6 +82,18 @@ static bool generateSnippetSetupCode(
7182
#ifdef HAVE_LIBPFM
7283
BBF.addInstructions(ET.configurePerfCounter(PERF_EVENT_IOC_RESET, true));
7384
#endif // HAVE_LIBPFM
85+
for (const RegisterValue &RV : RegisterInitialValues) {
86+
// Load in the stack register now as we're done using it elsewhere
87+
// and need to set the value in preparation for executing the
88+
// snippet.
89+
if (RV.Register == StackPointerRegister)
90+
continue;
91+
const auto SetRegisterCode = ET.setRegTo(*MSI, RV.Register, RV.Value);
92+
if (SetRegisterCode.empty())
93+
IsSnippetSetupComplete = false;
94+
BBF.addInstructions(SetRegisterCode);
95+
break;
96+
}
7497
}
7598
return IsSnippetSetupComplete;
7699
}

0 commit comments

Comments
 (0)