diff --git a/llvm/test/tools/llvm-exegesis/AArch64/skip_unsupported_instructions.s b/llvm/test/tools/llvm-exegesis/AArch64/skip_unsupported_instructions.s new file mode 100644 index 0000000000000..927ee190e803f --- /dev/null +++ b/llvm/test/tools/llvm-exegesis/AArch64/skip_unsupported_instructions.s @@ -0,0 +1,10 @@ +llvm/test/tools/llvm-exegesis/AArch64/skip_unsupported_instructions.s + +# 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 \ No newline at end of file diff --git a/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp b/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp index bf2b053003ce3..6d8e19e5820c7 100644 --- a/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp +++ b/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp @@ -9,12 +9,64 @@ #include "AArch64.h" #include "AArch64RegisterInfo.h" +#if defined(__aarch64__) && defined(__linux__) +#include // For PR_PAC_* constants +#include +#ifndef PR_PAC_SET_ENABLED_KEYS +#define PR_PAC_SET_ENABLED_KEYS 60 +#endif +#ifndef PR_PAC_GET_ENABLED_KEYS +#define PR_PAC_GET_ENABLED_KEYS 61 +#endif +#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 + // 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: @@ -134,6 +186,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)) { +#if defined(__aarch64__) && defined(__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