Skip to content

[llvm-exegesis] [AArch64] Resolving "snippet crashed while running: Segmentation fault" for Load Instructions #142552

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 12 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
505 changes: 504 additions & 1 deletion llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp

Large diffs are not rendered by default.

36 changes: 35 additions & 1 deletion llvm/tools/llvm-exegesis/lib/Assembler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/raw_ostream.h"

#define DEBUG_TYPE "exegesis-assembler"
#ifdef HAVE_LIBPFM
#include "perfmon/perf_event.h"
#endif // HAVE_LIBPFM
Expand Down Expand Up @@ -66,6 +67,8 @@ static bool generateSnippetSetupCode(const ExegesisTarget &ET,
assert(MM.Address % getpagesize() == 0 &&
"Memory mappings need to be aligned to page boundaries.");
#endif
// FIXME: file descriptor for aux memory seems not initialized.
// TODO: Invoke openat syscall to get correct fd for aux memory
const MemoryValue &MemVal = Key.MemoryValues.at(MM.MemoryValueName);
BBF.addInstructions(ET.generateMmap(
MM.Address, MemVal.SizeBytes,
Expand All @@ -78,15 +81,45 @@ static bool generateSnippetSetupCode(const ExegesisTarget &ET,
Register StackPointerRegister = BBF.MF.getSubtarget()
.getTargetLowering()
->getStackPointerRegisterToSaveRestore();
bool isFirstRegister = true;
for (const RegisterValue &RV : Key.RegisterInitialValues) {
// Debug: register name and class name and value from BenchmarkKey
const MCRegisterInfo *RegInfo = BBF.MF.getTarget().getMCRegisterInfo();
const char *RegName = RegInfo->getName(RV.Register);
const char *regClassName = "Unknown";
for (unsigned i = 0, e = RegInfo->getNumRegClasses(); i < e; ++i) {
const MCRegisterClass &RC = RegInfo->getRegClass(i);
if (RC.contains(RV.Register)) {
regClassName = RegInfo->getRegClassName(&RC);
break;
}
}
LLVM_DEBUG(
dbgs() << "Setting register (Class: " << regClassName << ") " << RegName
<< std::string(
std::max(0, 3 - static_cast<int>(strlen(RegName))), ' '));

if (GenerateMemoryInstructions) {
// If we're generating memory instructions, don't load in the value for
// the register with the stack pointer as it will be used later to finish
// the setup.
if (Register(RV.Register) == StackPointerRegister)
continue;
#if defined(__aarch64__)
auto StackLoadInsts = ET._generateRegisterStackPop(RV.Register, 16);
if (!StackLoadInsts.empty() && isFirstRegister) {
for (const auto &Inst : StackLoadInsts)
BBF.addInstruction(Inst);
isFirstRegister = false;
LLVM_DEBUG(dbgs() << "from stack with post-increment offset of " << 16
<< " bytes\n");
continue;
}
#endif
}

// Load a constant in the register.
LLVM_DEBUG(dbgs() << " to " << RV.Value << "\n");
const auto SetRegisterCode = ET.setRegTo(*MSI, RV.Register, RV.Value);
if (SetRegisterCode.empty())
IsSnippetSetupComplete = false;
Expand Down Expand Up @@ -225,7 +258,8 @@ ArrayRef<MCRegister> FunctionFiller::getRegistersSetUp() const {
}

static std::unique_ptr<Module>
createModule(const std::unique_ptr<LLVMContext> &Context, const DataLayout &DL) {
createModule(const std::unique_ptr<LLVMContext> &Context,
const DataLayout &DL) {
auto Mod = std::make_unique<Module>(ModuleID, *Context);
Mod->setDataLayout(DL);
return Mod;
Expand Down
21 changes: 15 additions & 6 deletions llvm/tools/llvm-exegesis/lib/MCInstrDescView.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,17 @@ bool Operand::isVariable() const { return VariableIndex.has_value(); }

bool Operand::isEarlyClobber() const { return IsEarlyClobber; }

// FIXME: Verify if mayLoadOrStore check is necessary for AArch64 memory operand
// detection
bool Operand::isMemory() const {
return isExplicit() &&
getExplicitOperandInfo().OperandType == MCOI::OPERAND_MEMORY;
return (isExplicit() &&
getExplicitOperandInfo().OperandType == MCOI::OPERAND_MEMORY)
// || mayLoadOrStore
;
// AArch64 has no operands with MCOI::OPERAND_MEMORY thus also adding
// mayLoadOrStore to check for mayLoad and mayStore which potentially have
// memory operands Uncommenting this check will cause illegal instruction
// error for AArch64
}

bool Operand::isImmediate() const {
Expand Down Expand Up @@ -130,6 +138,7 @@ Instruction::create(const MCInstrInfo &InstrInfo,
if (TiedToIndex >= 0)
Operand.TiedToIndex = TiedToIndex;
Operand.Info = &OpInfo;
Operand.mayLoadOrStore = Description->mayLoad() || Description->mayStore();
Operands.push_back(Operand);
}
for (MCPhysReg MCPhysReg : Description->implicit_defs()) {
Expand Down Expand Up @@ -325,13 +334,13 @@ const Instruction &InstructionsCache::getInstr(unsigned Opcode) const {
return *Found;
}

bool RegisterOperandAssignment::
operator==(const RegisterOperandAssignment &Other) const {
bool RegisterOperandAssignment::operator==(
const RegisterOperandAssignment &Other) const {
return std::tie(Op, Reg) == std::tie(Other.Op, Other.Reg);
}

bool AliasingRegisterOperands::
operator==(const AliasingRegisterOperands &Other) const {
bool AliasingRegisterOperands::operator==(
const AliasingRegisterOperands &Other) const {
return std::tie(Defs, Uses) == std::tie(Other.Defs, Other.Uses);
}

Expand Down
1 change: 1 addition & 0 deletions llvm/tools/llvm-exegesis/lib/MCInstrDescView.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ struct Operand {
bool IsDef = false;
bool IsEarlyClobber = false;
const RegisterAliasingTracker *Tracker = nullptr; // Set for Register Op.
bool mayLoadOrStore = false; // checks mayLoad and store
const MCOperandInfo *Info = nullptr; // Set for Explicit Op.
std::optional<uint8_t> TiedToIndex; // Set for Reg&Explicit Op.
MCRegister ImplicitReg; // Non-0 for Implicit Op.
Expand Down
6 changes: 6 additions & 0 deletions llvm/tools/llvm-exegesis/lib/SerialSnippetGenerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,12 @@ static void appendCodeTemplates(const LLVMState &State,

// Register classes of def operand and memory operand must be the same
// to perform aliasing.

// TODO: Get a valid scratch memory register,

// Do we need to set scratch memory register based on reg class ?
// Or is this code flow even required i.e. would setting register
// requiring memory address from stack correct approach ?
if (!RegClass.contains(ScratchMemoryRegister))
return;

Expand Down
8 changes: 8 additions & 0 deletions llvm/tools/llvm-exegesis/lib/SnippetGenerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,18 @@ Error SnippetGenerator::generateConfigurations(
ForbiddenRegs |= ExtraForbiddenRegs;
// If the instruction has memory registers, prevent the generator from
// using the scratch register and its aliasing registers.

// hasMemoryOperands(): if any register is an explicit memory register,
// then the instruction has memory operands
if (Variant.getInstr().hasMemoryOperands()) {
const auto &ET = State.getExegesisTarget();
MCRegister ScratchSpacePointerInReg =
ET.getScratchMemoryRegister(State.getTargetMachine().getTargetTriple());

// TODO: Get a valid scratch memory register,
// if MCRegister() is used, code flow exits here with below error,
// else if hardcoded X14 is used as scratch memory register,
// then illegal instruction is generated: undefined physical register
if (!ScratchSpacePointerInReg.isValid())
return make_error<Failure>(
"Infeasible : target does not support memory instructions");
Expand Down
8 changes: 6 additions & 2 deletions llvm/tools/llvm-exegesis/lib/Target.h
Original file line number Diff line number Diff line change
Expand Up @@ -268,8 +268,7 @@ class ExegesisTarget {

// Creates a snippet generator for the given mode.
std::unique_ptr<SnippetGenerator>
createSnippetGenerator(Benchmark::ModeE Mode,
const LLVMState &State,
createSnippetGenerator(Benchmark::ModeE Mode, const LLVMState &State,
const SnippetGenerator::Options &Opts) const;
// Creates a benchmark runner for the given mode.
Expected<std::unique_ptr<BenchmarkRunner>> createBenchmarkRunner(
Expand Down Expand Up @@ -308,6 +307,11 @@ class ExegesisTarget {
return std::make_unique<SavedState>();
}

virtual std::vector<MCInst> _generateRegisterStackPop(MCRegister Reg,
int imm = 0) const {
return {};
}

private:
virtual bool matchesArch(Triple::ArchType Arch) const = 0;

Expand Down
Loading