[llvm] 37ef640 - [llvm-exegesis] Prevent llvm-exegesis from using unsupported opcodes
Pavel Kosov via llvm-commits
llvm-commits at lists.llvm.org
Wed Aug 2 05:44:29 PDT 2023
Author: Pavel Kosov
Date: 2023-08-02T15:44:14+03:00
New Revision: 37ef64078553af3e8d305ac2a5d50faa82f8b8bb
URL: https://github.com/llvm/llvm-project/commit/37ef64078553af3e8d305ac2a5d50faa82f8b8bb
DIFF: https://github.com/llvm/llvm-project/commit/37ef64078553af3e8d305ac2a5d50faa82f8b8bb.diff
LOG: [llvm-exegesis] Prevent llvm-exegesis from using unsupported opcodes
When generating snippets for AArch64 with --opcode-index=-1, the code
generator asserts on opcodes that are not supported according to CPU
features.
The same assertion can be triggered even when generating a serial
snippet for a supported opcode if SERIAL_VIA_NON_MEMORY_INSTR execution
mode is used and an unsupported instruction is chosen as the "other
instruction". Unlike the first case, this one may result in flaky
failures because the other instruction is randomly chosen from the
instructions suitable for serializing execution.
This patch adjusts TableGen emitter for *GenInstrInfo.inc to make
possible to query for opcode availability instead of just asserting on
unsupported ones.
~~
Huawei RRI, OS Lab
Reviewed By: courbet
Differential Revision: https://reviews.llvm.org/D146303
Added:
Modified:
llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp
llvm/tools/llvm-exegesis/lib/Mips/Target.cpp
llvm/tools/llvm-exegesis/lib/PowerPC/Target.cpp
llvm/tools/llvm-exegesis/lib/SerialSnippetGenerator.cpp
llvm/tools/llvm-exegesis/lib/Target.cpp
llvm/tools/llvm-exegesis/lib/Target.h
llvm/tools/llvm-exegesis/lib/X86/Target.cpp
llvm/tools/llvm-exegesis/llvm-exegesis.cpp
llvm/utils/TableGen/InstrInfoEmitter.cpp
Removed:
################################################################################
diff --git a/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp b/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp
index c778b89032cd63..51846862f0a734 100644
--- a/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp
+++ b/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp
@@ -9,6 +9,9 @@
#include "AArch64.h"
#include "AArch64RegisterInfo.h"
+#define GET_AVAILABLE_OPCODE_CHECKER
+#include "AArch64GenInstrInfo.inc"
+
namespace llvm {
namespace exegesis {
@@ -38,7 +41,8 @@ namespace {
class ExegesisAArch64Target : public ExegesisTarget {
public:
- ExegesisAArch64Target() : ExegesisTarget(AArch64CpuPfmCounters) {}
+ ExegesisAArch64Target()
+ : ExegesisTarget(AArch64CpuPfmCounters, AArch64_MC::isOpcodeAvailable) {}
private:
std::vector<MCInst> setRegTo(const MCSubtargetInfo &STI, unsigned Reg,
diff --git a/llvm/tools/llvm-exegesis/lib/Mips/Target.cpp b/llvm/tools/llvm-exegesis/lib/Mips/Target.cpp
index ec698e678f9c38..cc8cd5dd4a109d 100644
--- a/llvm/tools/llvm-exegesis/lib/Mips/Target.cpp
+++ b/llvm/tools/llvm-exegesis/lib/Mips/Target.cpp
@@ -11,6 +11,9 @@
#include "Mips.h"
#include "MipsRegisterInfo.h"
+#define GET_AVAILABLE_OPCODE_CHECKER
+#include "MipsGenInstrInfo.inc"
+
namespace llvm {
namespace exegesis {
@@ -51,7 +54,8 @@ static void setMemOp(InstructionTemplate &IT, int OpIdx,
namespace {
class ExegesisMipsTarget : public ExegesisTarget {
public:
- ExegesisMipsTarget() : ExegesisTarget(MipsCpuPfmCounters) {}
+ ExegesisMipsTarget()
+ : ExegesisTarget(MipsCpuPfmCounters, Mips_MC::isOpcodeAvailable) {}
private:
unsigned getScratchMemoryRegister(const llvm::Triple &TT) const override;
diff --git a/llvm/tools/llvm-exegesis/lib/PowerPC/Target.cpp b/llvm/tools/llvm-exegesis/lib/PowerPC/Target.cpp
index 54d42dfd22e5f4..5c944c90384e3e 100644
--- a/llvm/tools/llvm-exegesis/lib/PowerPC/Target.cpp
+++ b/llvm/tools/llvm-exegesis/lib/PowerPC/Target.cpp
@@ -10,6 +10,9 @@
#include "PPC.h"
#include "PPCRegisterInfo.h"
+#define GET_AVAILABLE_OPCODE_CHECKER
+#include "PPCGenInstrInfo.inc"
+
namespace llvm {
namespace exegesis {
@@ -26,7 +29,8 @@ static void setMemOp(InstructionTemplate &IT, int OpIdx,
namespace {
class ExegesisPowerPCTarget : public ExegesisTarget {
public:
- ExegesisPowerPCTarget() : ExegesisTarget(PPCCpuPfmCounters) {}
+ ExegesisPowerPCTarget()
+ : ExegesisTarget(PPCCpuPfmCounters, PPC_MC::isOpcodeAvailable) {}
private:
std::vector<MCInst> setRegTo(const MCSubtargetInfo &STI, unsigned Reg,
diff --git a/llvm/tools/llvm-exegesis/lib/SerialSnippetGenerator.cpp b/llvm/tools/llvm-exegesis/lib/SerialSnippetGenerator.cpp
index 07a009c09a0478..7100b51bbb7298 100644
--- a/llvm/tools/llvm-exegesis/lib/SerialSnippetGenerator.cpp
+++ b/llvm/tools/llvm-exegesis/lib/SerialSnippetGenerator.cpp
@@ -38,6 +38,8 @@ static std::vector<const Instruction *>
computeAliasingInstructions(const LLVMState &State, const Instruction *Instr,
size_t MaxAliasingInstructions,
const BitVector &ForbiddenRegisters) {
+ const auto &ET = State.getExegesisTarget();
+ const auto AvailableFeatures = State.getSubtargetInfo().getFeatureBits();
// Randomly iterate the set of instructions.
std::vector<unsigned> Opcodes;
Opcodes.resize(State.getInstrInfo().getNumOpcodes());
@@ -46,6 +48,8 @@ computeAliasingInstructions(const LLVMState &State, const Instruction *Instr,
std::vector<const Instruction *> AliasingInstructions;
for (const unsigned OtherOpcode : Opcodes) {
+ if (!ET.isOpcodeAvailable(OtherOpcode, AvailableFeatures))
+ continue;
if (OtherOpcode == Instr->Description.getOpcode())
continue;
const Instruction &OtherInstr = State.getIC().getInstr(OtherOpcode);
@@ -58,7 +62,7 @@ computeAliasingInstructions(const LLVMState &State, const Instruction *Instr,
}
if (OtherInstr.hasMemoryOperands())
continue;
- if (!State.getExegesisTarget().allowAsBackToBack(OtherInstr))
+ if (!ET.allowAsBackToBack(OtherInstr))
continue;
if (Instr->hasAliasingRegistersThrough(OtherInstr, ForbiddenRegisters))
AliasingInstructions.push_back(&OtherInstr);
diff --git a/llvm/tools/llvm-exegesis/lib/Target.cpp b/llvm/tools/llvm-exegesis/lib/Target.cpp
index 1e5f688cf61bd7..aed093548f1580 100644
--- a/llvm/tools/llvm-exegesis/lib/Target.cpp
+++ b/llvm/tools/llvm-exegesis/lib/Target.cpp
@@ -14,6 +14,7 @@
#include "UopsBenchmarkRunner.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Support/Error.h"
+#include "llvm/TargetParser/SubtargetFeature.h"
namespace llvm {
namespace exegesis {
@@ -180,10 +181,12 @@ ExegesisTarget::SavedState::~SavedState() {} // anchor.
namespace {
+bool opcodeIsNotAvailable(unsigned, const FeatureBitset &) { return false; }
+
// Default implementation.
class ExegesisDefaultTarget : public ExegesisTarget {
public:
- ExegesisDefaultTarget() : ExegesisTarget({}) {}
+ ExegesisDefaultTarget() : ExegesisTarget({}, opcodeIsNotAvailable) {}
private:
std::vector<MCInst> setRegTo(const MCSubtargetInfo &STI, unsigned Reg,
diff --git a/llvm/tools/llvm-exegesis/lib/Target.h b/llvm/tools/llvm-exegesis/lib/Target.h
index 986ad98e2b9702..6de5b3c1065f1a 100644
--- a/llvm/tools/llvm-exegesis/lib/Target.h
+++ b/llvm/tools/llvm-exegesis/lib/Target.h
@@ -29,6 +29,7 @@
#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Error.h"
+#include "llvm/TargetParser/SubtargetFeature.h"
#include "llvm/TargetParser/Triple.h"
namespace llvm {
@@ -70,8 +71,10 @@ struct CpuAndPfmCounters {
class ExegesisTarget {
public:
- explicit ExegesisTarget(ArrayRef<CpuAndPfmCounters> CpuPfmCounters)
- : CpuPfmCounters(CpuPfmCounters) {}
+ typedef bool (*OpcodeAvailabilityChecker)(unsigned, const FeatureBitset &);
+ ExegesisTarget(ArrayRef<CpuAndPfmCounters> CpuPfmCounters,
+ OpcodeAvailabilityChecker IsOpcodeAvailable)
+ : CpuPfmCounters(CpuPfmCounters), IsOpcodeAvailable(IsOpcodeAvailable) {}
// Targets can use this to create target-specific perf counters.
virtual Expected<std::unique_ptr<pfm::Counter>>
@@ -139,6 +142,12 @@ class ExegesisTarget {
"current architecture\n");
}
+ // Returns true if all features are available that are required by Opcode.
+ virtual bool isOpcodeAvailable(unsigned Opcode,
+ const FeatureBitset &Features) const {
+ return IsOpcodeAvailable(Opcode, Features);
+ }
+
// Sets the stack register to the auxiliary memory so that operations
// requiring the stack can be formed (e.g., setting large registers). The code
// generated by this function may clobber registers.
@@ -304,6 +313,7 @@ class ExegesisTarget {
const ExegesisTarget *Next = nullptr;
const ArrayRef<CpuAndPfmCounters> CpuPfmCounters;
+ const OpcodeAvailabilityChecker IsOpcodeAvailable;
};
} // namespace exegesis
diff --git a/llvm/tools/llvm-exegesis/lib/X86/Target.cpp b/llvm/tools/llvm-exegesis/lib/X86/Target.cpp
index e690089fec5656..d41fa44f9258d5 100644
--- a/llvm/tools/llvm-exegesis/lib/X86/Target.cpp
+++ b/llvm/tools/llvm-exegesis/lib/X86/Target.cpp
@@ -43,6 +43,9 @@
#include <unistd.h>
#endif
+#define GET_AVAILABLE_OPCODE_CHECKER
+#include "X86GenInstrInfo.inc"
+
namespace llvm {
namespace exegesis {
@@ -669,7 +672,8 @@ class X86SavedState : public ExegesisTarget::SavedState {
class ExegesisX86Target : public ExegesisTarget {
public:
- ExegesisX86Target() : ExegesisTarget(X86CpuPfmCounters) {}
+ ExegesisX86Target()
+ : ExegesisTarget(X86CpuPfmCounters, X86_MC::isOpcodeAvailable) {}
Expected<std::unique_ptr<pfm::Counter>>
createCounter(StringRef CounterName, const LLVMState &State,
diff --git a/llvm/tools/llvm-exegesis/llvm-exegesis.cpp b/llvm/tools/llvm-exegesis/llvm-exegesis.cpp
index ff868e756338af..7d2ce010bd7494 100644
--- a/llvm/tools/llvm-exegesis/llvm-exegesis.cpp
+++ b/llvm/tools/llvm-exegesis/llvm-exegesis.cpp
@@ -291,6 +291,9 @@ static std::vector<unsigned> getOpcodesOrDie(const LLVMState &State) {
const size_t NumSetFlags = (OpcodeNames.empty() ? 0 : 1) +
(OpcodeIndex == 0 ? 0 : 1) +
(SnippetsFile.empty() ? 0 : 1);
+ const auto &ET = State.getExegesisTarget();
+ const auto AvailableFeatures = State.getSubtargetInfo().getFeatureBits();
+
if (NumSetFlags != 1) {
ExitOnErr.setBanner("llvm-exegesis: ");
ExitWithError("please provide one and only one of 'opcode-index', "
@@ -304,8 +307,11 @@ static std::vector<unsigned> getOpcodesOrDie(const LLVMState &State) {
std::vector<unsigned> Result;
unsigned NumOpcodes = State.getInstrInfo().getNumOpcodes();
Result.reserve(NumOpcodes);
- for (unsigned I = 0, E = NumOpcodes; I < E; ++I)
+ for (unsigned I = 0, E = NumOpcodes; I < E; ++I) {
+ if (!ET.isOpcodeAvailable(I, AvailableFeatures))
+ continue;
Result.push_back(I);
+ }
return Result;
}
// Resolve opcode name -> opcode.
diff --git a/llvm/utils/TableGen/InstrInfoEmitter.cpp b/llvm/utils/TableGen/InstrInfoEmitter.cpp
index cab9ecd4ea974e..a16d9470cb087f 100644
--- a/llvm/utils/TableGen/InstrInfoEmitter.cpp
+++ b/llvm/utils/TableGen/InstrInfoEmitter.cpp
@@ -733,7 +733,9 @@ void InstrInfoEmitter::emitFeatureVerifier(raw_ostream &OS,
std::map<Record *, SubtargetFeatureInfo, LessRecordByID> SubtargetFeatures;
SubtargetFeatures.insert(All.begin(), All.end());
- OS << "#if defined(ENABLE_INSTR_PREDICATE_VERIFIER) && !defined(NDEBUG)\n"
+ OS << "#if (defined(ENABLE_INSTR_PREDICATE_VERIFIER) && !defined(NDEBUG)) "
+ << "||\\\n"
+ << " defined(GET_AVAILABLE_OPCODE_CHECKER)\n"
<< "#define GET_COMPUTE_FEATURES\n"
<< "#endif\n";
OS << "#ifdef GET_COMPUTE_FEATURES\n"
@@ -826,6 +828,25 @@ void InstrInfoEmitter::emitFeatureVerifier(raw_ostream &OS,
<< "} // end namespace llvm\n"
<< "#endif // GET_COMPUTE_FEATURES\n\n";
+ OS << "#ifdef GET_AVAILABLE_OPCODE_CHECKER\n"
+ << "#undef GET_AVAILABLE_OPCODE_CHECKER\n"
+ << "namespace llvm {\n"
+ << "namespace " << Target.getName() << "_MC {\n";
+ OS << "bool isOpcodeAvailable("
+ << "unsigned Opcode, const FeatureBitset &Features) {\n"
+ << " FeatureBitset AvailableFeatures = "
+ << "computeAvailableFeatures(Features);\n"
+ << " FeatureBitset RequiredFeatures = "
+ << "computeRequiredFeatures(Opcode);\n"
+ << " FeatureBitset MissingFeatures =\n"
+ << " (AvailableFeatures & RequiredFeatures) ^\n"
+ << " RequiredFeatures;\n"
+ << " return !MissingFeatures.any();\n"
+ << "}\n";
+ OS << "} // end namespace " << Target.getName() << "_MC\n"
+ << "} // end namespace llvm\n"
+ << "#endif // GET_AVAILABLE_OPCODE_CHECKER\n\n";
+
OS << "#ifdef ENABLE_INSTR_PREDICATE_VERIFIER\n"
<< "#undef ENABLE_INSTR_PREDICATE_VERIFIER\n"
<< "#include <sstream>\n\n";
More information about the llvm-commits
mailing list