Skip to content
Merged
Show file tree
Hide file tree
Changes from 10 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
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# REQUIRES: aarch64-registered-target

# Check for skipping of illegal instruction errors (AUT and LDGM)
# RUN: llvm-exegesis -mcpu=neoverse-v2 -mode=latency --opcode-name=AUTIA --benchmark-phase=assemble-measured-code 2>&1 | FileCheck %s --check-prefix=CHECK-AUTIA
# CHECK-AUTIA-NOT: snippet crashed while running: Illegal instruction

# RUN: llvm-exegesis -mcpu=neoverse-v2 -mode=latency --opcode-name=LDGM --benchmark-phase=assemble-measured-code 2>&1 | FileCheck %s --check-prefix=CHECK-LDGM
# CHECK-LDGM: LDGM: Unsupported opcode: load tag multiple
75 changes: 75 additions & 0 deletions llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,58 @@
#include "AArch64.h"
#include "AArch64RegisterInfo.h"

#ifdef __linux__
#include <linux/prctl.h> // For PR_PAC_* constants
#include <sys/prctl.h>
#endif

#define GET_AVAILABLE_OPCODE_CHECKER
#include "AArch64GenInstrInfo.inc"

namespace llvm {
namespace exegesis {

bool isPointerAuth(unsigned Opcode) {
switch (Opcode) {
default:
return false;

// FIXME: Pointer Authentication instructions.
// We would like to measure these instructions, but they can behave
// differently on different platforms, and maybe the snippets need to look
// different for these instructions,
// Platform-specific handling: On Linux, we disable authentication, may
// interfere with measurements. On non-Linux platforms, disable opcodes for
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a note: Exegesis doesn't really support benchmarking on non-Linux platforms.

// now.
case AArch64::AUTDA:
case AArch64::AUTDB:
case AArch64::AUTDZA:
case AArch64::AUTDZB:
case AArch64::AUTIA:
case AArch64::AUTIA1716:
case AArch64::AUTIASP:
case AArch64::AUTIAZ:
case AArch64::AUTIB:
case AArch64::AUTIB1716:
case AArch64::AUTIBSP:
case AArch64::AUTIBZ:
case AArch64::AUTIZA:
case AArch64::AUTIZB:
return true;
}
}

bool isLoadTagMultiple(unsigned Opcode) {
switch (Opcode) {
default:
return false;

// Load tag multiple instruction
case AArch64::LDGM:
return true;
}
}

static unsigned getLoadImmediateOpcode(unsigned RegBitWidth) {
switch (RegBitWidth) {
case 32:
Expand Down Expand Up @@ -134,6 +180,35 @@ class ExegesisAArch64Target : public ExegesisTarget {
// Function return is a pseudo-instruction that needs to be expanded
PM.add(createAArch64ExpandPseudoPass());
}

const char *getIgnoredOpcodeReasonOrNull(const LLVMState &State,
unsigned Opcode) const override {
if (const char *Reason =
ExegesisTarget::getIgnoredOpcodeReasonOrNull(State, Opcode))
return Reason;

if (isPointerAuth(Opcode)) {
#ifdef __linux__
// Disable all PAC keys. Note that while we expect the measurements to
// be the same with PAC keys disabled, they could potentially be lower
// since authentication checks are bypassed.
if (prctl(PR_PAC_SET_ENABLED_KEYS,
PR_PAC_APIAKEY | PR_PAC_APIBKEY | PR_PAC_APDAKEY |
PR_PAC_APDBKEY, // all keys
0, // disable all
0, 0) < 0) {
return "Failed to disable PAC keys";
}
#else
return "Unsupported opcode: isPointerAuth";
#endif
}

if (isLoadTagMultiple(Opcode))
return "Unsupported opcode: load tag multiple";

return nullptr;
}
};

} // namespace
Expand Down
26 changes: 16 additions & 10 deletions llvm/tools/llvm-exegesis/lib/Target.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,18 @@ const char *
ExegesisTarget::getIgnoredOpcodeReasonOrNull(const LLVMState &State,
unsigned Opcode) const {
const MCInstrDesc &InstrDesc = State.getIC().getInstr(Opcode).Description;
if (InstrDesc.isPseudo() || InstrDesc.usesCustomInsertionHook())
return "Unsupported opcode: isPseudo/usesCustomInserter";
if (InstrDesc.isBranch() || InstrDesc.isIndirectBranch())
return "Unsupported opcode: isBranch/isIndirectBranch";
if (InstrDesc.isCall() || InstrDesc.isReturn())
return "Unsupported opcode: isCall/isReturn";
if (InstrDesc.isPseudo())
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All the changes in this file seem to be formatting changes that are now irrelevant to the PR? They should probably be reverted.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

split up the first couple of if-statements as I don't like error messages that say "it can be this or that":

Sjoerd suggested 'unclubbing' the unsupported error message to specify the exact reason. Thus, keeping this and formatter's changes for this file only.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would prefer these changes go in a separate patch.

return "Unsupported opcode: isPseudo";
if (InstrDesc.usesCustomInsertionHook())
return "Unsupported opcode: usesCustomInserter";
if (InstrDesc.isBranch())
return "Unsupported opcode: isBranch";
if (InstrDesc.isIndirectBranch())
return "Unsupported opcode: isIndirectBranch";
if (InstrDesc.isCall())
return "Unsupported opcode: isCall";
if (InstrDesc.isReturn())
return "Unsupported opcode: isReturn";
return nullptr;
}

Expand Down Expand Up @@ -113,9 +119,8 @@ ExegesisTarget::createBenchmarkRunner(
case Benchmark::InverseThroughput:
if (BenchmarkPhaseSelector == BenchmarkPhaseSelectorE::Measure &&
!PfmCounters.CycleCounter) {
const char *ModeName = Mode == Benchmark::Latency
? "latency"
: "inverse_throughput";
const char *ModeName =
Mode == Benchmark::Latency ? "latency" : "inverse_throughput";
return make_error<Failure>(
Twine("can't run '")
.concat(ModeName)
Expand Down Expand Up @@ -148,7 +153,8 @@ std::unique_ptr<SnippetGenerator> ExegesisTarget::createSerialSnippetGenerator(
return std::make_unique<SerialSnippetGenerator>(State, Opts);
}

std::unique_ptr<SnippetGenerator> ExegesisTarget::createParallelSnippetGenerator(
std::unique_ptr<SnippetGenerator>
ExegesisTarget::createParallelSnippetGenerator(
const LLVMState &State, const SnippetGenerator::Options &Opts) const {
return std::make_unique<ParallelSnippetGenerator>(State, Opts);
}
Expand Down