Index: llvm/trunk/tools/llvm-exegesis/lib/Assembler.h =================================================================== --- llvm/trunk/tools/llvm-exegesis/lib/Assembler.h +++ llvm/trunk/tools/llvm-exegesis/lib/Assembler.h @@ -43,7 +43,7 @@ // Instructions. Runs a set of llvm Passes to provide correct prologue and // epilogue. Once the MachineFunction is ready, it is assembled for TM to // AsmStream, the temporary function is eventually discarded. -void assembleToStream(const ExegesisTarget *ET, +void assembleToStream(const ExegesisTarget &ET, std::unique_ptr TM, llvm::ArrayRef RegsToDef, llvm::ArrayRef Instructions, Index: llvm/trunk/tools/llvm-exegesis/lib/Assembler.cpp =================================================================== --- llvm/trunk/tools/llvm-exegesis/lib/Assembler.cpp +++ llvm/trunk/tools/llvm-exegesis/lib/Assembler.cpp @@ -138,7 +138,7 @@ return MF.getSubtarget().getRegisterInfo()->getReservedRegs(MF); } -void assembleToStream(const ExegesisTarget *ET, +void assembleToStream(const ExegesisTarget &ET, std::unique_ptr TM, llvm::ArrayRef RegsToDef, llvm::ArrayRef Instructions, @@ -157,11 +157,10 @@ auto &Properties = MF.getProperties(); Properties.set(llvm::MachineFunctionProperties::Property::NoVRegs); Properties.reset(llvm::MachineFunctionProperties::Property::IsSSA); - std::vector SnippetWithSetup; - bool IsSnippetSetupComplete = RegsToDef.empty(); - if (ET) { - SnippetWithSetup = - generateSnippetSetupCode(RegsToDef, *ET, IsSnippetSetupComplete); + bool IsSnippetSetupComplete = false; + std::vector SnippetWithSetup = + generateSnippetSetupCode(RegsToDef, ET, IsSnippetSetupComplete); + if (!SnippetWithSetup.empty()) { SnippetWithSetup.insert(SnippetWithSetup.end(), Instructions.begin(), Instructions.end()); Instructions = SnippetWithSetup; @@ -190,10 +189,8 @@ PM.add(MMI.release()); TPC->printAndVerify("MachineFunctionGenerator::assemble"); // Add target-specific passes. - if (ET) { - ET->addTargetSpecificPasses(PM); - TPC->printAndVerify("After ExegesisTarget::addTargetSpecificPasses"); - } + ET.addTargetSpecificPasses(PM); + TPC->printAndVerify("After ExegesisTarget::addTargetSpecificPasses"); // Adding the following passes: // - machineverifier: checks that the MachineFunction is well formed. // - prologepilog: saves and restore callee saved registers. Index: llvm/trunk/tools/llvm-exegesis/lib/BenchmarkRunner.h =================================================================== --- llvm/trunk/tools/llvm-exegesis/lib/BenchmarkRunner.h +++ llvm/trunk/tools/llvm-exegesis/lib/BenchmarkRunner.h @@ -54,25 +54,12 @@ // Common code for all benchmark modes. class BenchmarkRunner { public: - explicit BenchmarkRunner(const LLVMState &State); - - // Subtargets can disable running benchmarks for some instructions by - // returning an error here. - class InstructionFilter { - public: - virtual ~InstructionFilter(); - - virtual llvm::Error shouldRun(const LLVMState &State, - unsigned Opcode) const { - return llvm::ErrorSuccess(); - } - }; + explicit BenchmarkRunner(const LLVMState &State, InstructionBenchmark::ModeE Mode); virtual ~BenchmarkRunner(); llvm::Expected> - run(unsigned Opcode, const InstructionFilter &Filter, - unsigned NumRepetitions); + run(unsigned Opcode, unsigned NumRepetitions); // Given a snippet, computes which registers the setup code needs to define. std::vector @@ -83,6 +70,15 @@ const RegisterAliasingTrackerCache RATC; private: + // API to be implemented by subclasses. + virtual llvm::Expected + generatePrototype(unsigned Opcode) const = 0; + + virtual std::vector + runMeasurements(const ExecutableFunction &EF, + const unsigned NumRepetitions) const = 0; + + // Internal helpers. InstructionBenchmark runOne(const BenchmarkConfiguration &Configuration, unsigned Opcode, unsigned NumRepetitions) const; @@ -91,18 +87,12 @@ llvm::Expected> generateConfigurations(unsigned Opcode) const; - virtual InstructionBenchmark::ModeE getMode() const = 0; - - virtual llvm::Expected - generatePrototype(unsigned Opcode) const = 0; - - virtual std::vector - runMeasurements(const ExecutableFunction &EF, - const unsigned NumRepetitions) const = 0; llvm::Expected writeObjectFile(const BenchmarkConfiguration::Setup &Setup, llvm::ArrayRef Code) const; + + const InstructionBenchmark::ModeE Mode; }; } // namespace exegesis Index: llvm/trunk/tools/llvm-exegesis/lib/BenchmarkRunner.cpp =================================================================== --- llvm/trunk/tools/llvm-exegesis/lib/BenchmarkRunner.cpp +++ llvm/trunk/tools/llvm-exegesis/lib/BenchmarkRunner.cpp @@ -26,23 +26,26 @@ BenchmarkFailure::BenchmarkFailure(const llvm::Twine &S) : llvm::StringError(S, llvm::inconvertibleErrorCode()) {} -BenchmarkRunner::InstructionFilter::~InstructionFilter() = default; - -BenchmarkRunner::BenchmarkRunner(const LLVMState &State) - : State(State), - RATC(State.getRegInfo(), getFunctionReservedRegs(State.getTargetMachine())) {} +BenchmarkRunner::BenchmarkRunner(const LLVMState &State, + InstructionBenchmark::ModeE Mode) + : State(State), RATC(State.getRegInfo(), + getFunctionReservedRegs(State.getTargetMachine())), + Mode(Mode) {} BenchmarkRunner::~BenchmarkRunner() = default; llvm::Expected> -BenchmarkRunner::run(unsigned Opcode, const InstructionFilter &Filter, - unsigned NumRepetitions) { +BenchmarkRunner::run(unsigned Opcode, unsigned NumRepetitions) { + const llvm::MCInstrDesc &InstrDesc = State.getInstrInfo().get(Opcode); // Ignore instructions that we cannot run. - if (State.getInstrInfo().get(Opcode).isPseudo()) + if (InstrDesc.isPseudo()) return llvm::make_error("Unsupported opcode: isPseudo"); - - if (llvm::Error E = Filter.shouldRun(State, Opcode)) - return std::move(E); + if (InstrDesc.isBranch() || InstrDesc.isIndirectBranch()) + return llvm::make_error( + "Unsupported opcode: isBranch/isIndirectBranch"); + if (InstrDesc.isCall() || InstrDesc.isReturn()) + return llvm::make_error( + "Unsupported opcode: isCall/isReturn"); llvm::Expected> ConfigurationOrError = generateConfigurations(Opcode); @@ -60,7 +63,7 @@ BenchmarkRunner::runOne(const BenchmarkConfiguration &Configuration, unsigned Opcode, unsigned NumRepetitions) const { InstructionBenchmark InstrBenchmark; - InstrBenchmark.Mode = getMode(); + InstrBenchmark.Mode = Mode; InstrBenchmark.CpuName = State.getTargetMachine().getTargetCPU(); InstrBenchmark.LLVMTriple = State.getTargetMachine().getTargetTriple().normalize(); Index: llvm/trunk/tools/llvm-exegesis/lib/CMakeLists.txt =================================================================== --- llvm/trunk/tools/llvm-exegesis/lib/CMakeLists.txt +++ llvm/trunk/tools/llvm-exegesis/lib/CMakeLists.txt @@ -16,7 +16,6 @@ RegisterAliasing.cpp Target.cpp Uops.cpp - X86.cpp ) llvm_update_compile_flags(LLVMExegesis) Index: llvm/trunk/tools/llvm-exegesis/lib/Latency.h =================================================================== --- llvm/trunk/tools/llvm-exegesis/lib/Latency.h +++ llvm/trunk/tools/llvm-exegesis/lib/Latency.h @@ -22,7 +22,8 @@ class LatencyBenchmarkRunner : public BenchmarkRunner { public: - using BenchmarkRunner::BenchmarkRunner; + LatencyBenchmarkRunner(const LLVMState &State) + : BenchmarkRunner(State, InstructionBenchmark::Latency) {} ~LatencyBenchmarkRunner() override; llvm::Expected @@ -39,8 +40,6 @@ const Instruction &Instr, const AliasingConfigurations &SelfAliasing) const; - InstructionBenchmark::ModeE getMode() const override; - std::vector runMeasurements(const ExecutableFunction &EF, const unsigned NumRepetitions) const override; Index: llvm/trunk/tools/llvm-exegesis/lib/Latency.cpp =================================================================== --- llvm/trunk/tools/llvm-exegesis/lib/Latency.cpp +++ llvm/trunk/tools/llvm-exegesis/lib/Latency.cpp @@ -31,14 +31,8 @@ LatencyBenchmarkRunner::~LatencyBenchmarkRunner() = default; -InstructionBenchmark::ModeE LatencyBenchmarkRunner::getMode() const { - return InstructionBenchmark::Latency; -} - llvm::Error LatencyBenchmarkRunner::isInfeasible( const llvm::MCInstrDesc &MCInstrDesc) const { - if (MCInstrDesc.isPseudo()) - return llvm::make_error("Infeasible : is pseudo"); if (llvm::any_of(MCInstrDesc.operands(), hasUnknownOperand)) return llvm::make_error( "Infeasible : has unknown operands"); Index: llvm/trunk/tools/llvm-exegesis/lib/LlvmState.h =================================================================== --- llvm/trunk/tools/llvm-exegesis/lib/LlvmState.h +++ llvm/trunk/tools/llvm-exegesis/lib/LlvmState.h @@ -15,7 +15,6 @@ #ifndef LLVM_TOOLS_LLVM_EXEGESIS_LLVMSTATE_H #define LLVM_TOOLS_LLVM_EXEGESIS_LLVMSTATE_H -#include "Target.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCInst.h" #include "llvm/MC/MCInstrInfo.h" @@ -41,7 +40,7 @@ const llvm::TargetMachine &getTargetMachine() const { return *TargetMachine; } std::unique_ptr createTargetMachine() const; - const ExegesisTarget *getExegesisTarget() const { return TheExegesisTarget; } + const ExegesisTarget &getExegesisTarget() const { return *TheExegesisTarget; } bool canAssemble(const llvm::MCInst &mc_inst) const; @@ -57,7 +56,7 @@ } private: - const ExegesisTarget *TheExegesisTarget = nullptr; + const ExegesisTarget *TheExegesisTarget; std::unique_ptr TargetMachine; }; Index: llvm/trunk/tools/llvm-exegesis/lib/LlvmState.cpp =================================================================== --- llvm/trunk/tools/llvm-exegesis/lib/LlvmState.cpp +++ llvm/trunk/tools/llvm-exegesis/lib/LlvmState.cpp @@ -8,6 +8,7 @@ //===----------------------------------------------------------------------===// #include "LlvmState.h" +#include "Target.h" #include "llvm/ADT/SmallVector.h" #include "llvm/MC/MCCodeEmitter.h" #include "llvm/MC/MCContext.h" @@ -30,6 +31,10 @@ TheTarget->createTargetMachine(Triple, CpuName, /*Features*/ "", Options, llvm::Reloc::Model::Static))); TheExegesisTarget = ExegesisTarget::lookup(TargetMachine->getTargetTriple()); + if (!TheExegesisTarget) { + llvm::errs() << "no exegesis target for " << Triple << ", using default\n"; + TheExegesisTarget = &ExegesisTarget::getDefault(); + } } LLVMState::LLVMState() Index: llvm/trunk/tools/llvm-exegesis/lib/Target.h =================================================================== --- llvm/trunk/tools/llvm-exegesis/lib/Target.h +++ llvm/trunk/tools/llvm-exegesis/lib/Target.h @@ -17,6 +17,9 @@ #ifndef LLVM_TOOLS_LLVM_EXEGESIS_TARGET_H #define LLVM_TOOLS_LLVM_EXEGESIS_TARGET_H +#include "BenchmarkResult.h" +#include "BenchmarkRunner.h" +#include "LlvmState.h" #include "llvm/ADT/Triple.h" #include "llvm/CodeGen/TargetPassConfig.h" #include "llvm/IR/LegacyPassManager.h" @@ -35,9 +38,16 @@ return {}; } + // Creates a benchmark runner for the given mode. + std::unique_ptr + createBenchmarkRunner(InstructionBenchmark::ModeE Mode, + const LLVMState &State) const; + // Returns the ExegesisTarget for the given triple or nullptr if the target // does not exist. static const ExegesisTarget *lookup(llvm::Triple TT); + // Returns the default (unspecialized) ExegesisTarget. + static const ExegesisTarget &getDefault(); // Registers a target. Not thread safe. static void registerTarget(ExegesisTarget *T); @@ -45,6 +55,14 @@ private: virtual bool matchesArch(llvm::Triple::ArchType Arch) const = 0; + + // Targets can implement their own Latency/Uops benchmarks runners by + // implementing these. + std::unique_ptr virtual createLatencyBenchmarkRunner( + const LLVMState &State) const; + std::unique_ptr virtual createUopsBenchmarkRunner( + const LLVMState &State) const; + const ExegesisTarget *Next = nullptr; }; Index: llvm/trunk/tools/llvm-exegesis/lib/Target.cpp =================================================================== --- llvm/trunk/tools/llvm-exegesis/lib/Target.cpp +++ llvm/trunk/tools/llvm-exegesis/lib/Target.cpp @@ -8,6 +8,9 @@ //===----------------------------------------------------------------------===// #include "Target.h" +#include "Latency.h" +#include "Uops.h" + namespace exegesis { ExegesisTarget::~ExegesisTarget() {} // anchor. @@ -33,4 +36,47 @@ Target->Next = FirstTarget; FirstTarget = Target; } + +std::unique_ptr +ExegesisTarget::createBenchmarkRunner(InstructionBenchmark::ModeE Mode, + const LLVMState &State) const { + switch (Mode) { + case InstructionBenchmark::Unknown: + return nullptr; + case InstructionBenchmark::Latency: + return createLatencyBenchmarkRunner(State); + case InstructionBenchmark::Uops: + return createUopsBenchmarkRunner(State); + } + return nullptr; +} + +std::unique_ptr +ExegesisTarget::createLatencyBenchmarkRunner(const LLVMState &State) const { + return llvm::make_unique(State); +} + +std::unique_ptr +ExegesisTarget::createUopsBenchmarkRunner(const LLVMState &State) const { + return llvm::make_unique(State); +} + +namespace { + +// Default implementation. +class ExegesisDefaultTarget : public ExegesisTarget { +private: + bool matchesArch(llvm::Triple::ArchType Arch) const override { + llvm_unreachable("never called"); + return false; + } +}; + +} // namespace + +const ExegesisTarget &ExegesisTarget::getDefault() { + static ExegesisDefaultTarget Target; + return Target; +} + } // namespace exegesis Index: llvm/trunk/tools/llvm-exegesis/lib/Uops.h =================================================================== --- llvm/trunk/tools/llvm-exegesis/lib/Uops.h +++ llvm/trunk/tools/llvm-exegesis/lib/Uops.h @@ -21,7 +21,8 @@ class UopsBenchmarkRunner : public BenchmarkRunner { public: - using BenchmarkRunner::BenchmarkRunner; + UopsBenchmarkRunner(const LLVMState &State) + : BenchmarkRunner(State, InstructionBenchmark::Uops) {} ~UopsBenchmarkRunner() override; llvm::Expected @@ -30,8 +31,6 @@ private: llvm::Error isInfeasible(const llvm::MCInstrDesc &MCInstrDesc) const; - InstructionBenchmark::ModeE getMode() const override; - std::vector runMeasurements(const ExecutableFunction &EF, const unsigned NumRepetitions) const override; Index: llvm/trunk/tools/llvm-exegesis/lib/Uops.cpp =================================================================== --- llvm/trunk/tools/llvm-exegesis/lib/Uops.cpp +++ llvm/trunk/tools/llvm-exegesis/lib/Uops.cpp @@ -91,8 +91,6 @@ llvm::Error UopsBenchmarkRunner::isInfeasible(const llvm::MCInstrDesc &MCInstrDesc) const { - if (MCInstrDesc.isPseudo()) - return llvm::make_error("Infeasible : is pseudo"); if (llvm::any_of(MCInstrDesc.operands(), hasUnknownOperand)) return llvm::make_error( "Infeasible : has unknown operands"); @@ -133,10 +131,6 @@ UopsBenchmarkRunner::~UopsBenchmarkRunner() = default; -InstructionBenchmark::ModeE UopsBenchmarkRunner::getMode() const { - return InstructionBenchmark::Uops; -} - llvm::Expected UopsBenchmarkRunner::generatePrototype(unsigned Opcode) const { const auto &InstrDesc = State.getInstrInfo().get(Opcode); Index: llvm/trunk/tools/llvm-exegesis/lib/X86.h =================================================================== --- llvm/trunk/tools/llvm-exegesis/lib/X86.h +++ llvm/trunk/tools/llvm-exegesis/lib/X86.h @@ -1,32 +0,0 @@ -//===-- X86.h ---------------------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -/// -/// \file -/// X86 target-specific setup. -/// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_TOOLS_LLVM_EXEGESIS_X86_H -#define LLVM_TOOLS_LLVM_EXEGESIS_X86_H - -#include "BenchmarkRunner.h" -#include "LlvmState.h" - -namespace exegesis { - -class X86Filter : public BenchmarkRunner::InstructionFilter { -public: - ~X86Filter() override; - - llvm::Error shouldRun(const LLVMState &State, unsigned Opcode) const override; -}; - -} // namespace exegesis - -#endif // LLVM_TOOLS_LLVM_EXEGESIS_X86_H Index: llvm/trunk/tools/llvm-exegesis/lib/X86.cpp =================================================================== --- llvm/trunk/tools/llvm-exegesis/lib/X86.cpp +++ llvm/trunk/tools/llvm-exegesis/lib/X86.cpp @@ -1,38 +0,0 @@ -//===-- X86.cpp --------------------------------------------------*- C++-*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "X86.h" - -namespace exegesis { - -static llvm::Error makeError(llvm::Twine Msg) { - return llvm::make_error(Msg, - llvm::inconvertibleErrorCode()); -} - -X86Filter::~X86Filter() = default; - -// Test whether we can generate a snippet for this instruction. -llvm::Error X86Filter::shouldRun(const LLVMState &State, - const unsigned Opcode) const { - const auto &InstrInfo = State.getInstrInfo(); - const llvm::MCInstrDesc &InstrDesc = InstrInfo.get(Opcode); - if (InstrDesc.isBranch() || InstrDesc.isIndirectBranch()) - return makeError("Unsupported opcode: isBranch/isIndirectBranch"); - if (InstrDesc.isCall() || InstrDesc.isReturn()) - return makeError("Unsupported opcode: isCall/isReturn"); - const auto OpcodeName = InstrInfo.getName(Opcode); - if (OpcodeName.startswith("POPF") || OpcodeName.startswith("PUSHF") || - OpcodeName.startswith("ADJCALLSTACK")) { - return makeError("Unsupported opcode: Push/Pop/AdjCallStack"); - } - return llvm::ErrorSuccess(); -} - -} // namespace exegesis Index: llvm/trunk/tools/llvm-exegesis/lib/X86/Target.cpp =================================================================== --- llvm/trunk/tools/llvm-exegesis/lib/X86/Target.cpp +++ llvm/trunk/tools/llvm-exegesis/lib/X86/Target.cpp @@ -8,6 +8,8 @@ //===----------------------------------------------------------------------===// #include "../Target.h" +#include "../Latency.h" +#include "../Uops.h" #include "MCTargetDesc/X86MCTargetDesc.h" #include "X86.h" #include "X86RegisterInfo.h" @@ -15,8 +17,46 @@ namespace exegesis { +// Test whether we can generate a snippet for this instruction. +static llvm::Error shouldRun(const LLVMState &State, const unsigned Opcode) { + const auto &InstrInfo = State.getInstrInfo(); + const auto OpcodeName = InstrInfo.getName(Opcode); + if (OpcodeName.startswith("POPF") || OpcodeName.startswith("PUSHF") || + OpcodeName.startswith("ADJCALLSTACK")) { + return llvm::make_error( + "Unsupported opcode: Push/Pop/AdjCallStack"); + } + return llvm::ErrorSuccess(); +} + namespace { +class X86LatencyBenchmarkRunner : public LatencyBenchmarkRunner { +private: + using LatencyBenchmarkRunner::LatencyBenchmarkRunner; + + llvm::Expected + generatePrototype(unsigned Opcode) const override { + if (llvm::Error E = shouldRun(State, Opcode)) { + return std::move(E); + } + return LatencyBenchmarkRunner::generatePrototype(Opcode); + } +}; + +class X86UopsBenchmarkRunner : public UopsBenchmarkRunner { +private: + using UopsBenchmarkRunner::UopsBenchmarkRunner; + + llvm::Expected + generatePrototype(unsigned Opcode) const override { + if (llvm::Error E = shouldRun(State, Opcode)) { + return std::move(E); + } + return UopsBenchmarkRunner::generatePrototype(Opcode); + } +}; + class ExegesisX86Target : public ExegesisTarget { void addTargetSpecificPasses(llvm::PassManagerBase &PM) const override { // Lowers FP pseudo-instructions, e.g. ABS_Fp32 -> ABS_F. @@ -55,6 +95,16 @@ return {}; } + std::unique_ptr + createLatencyBenchmarkRunner(const LLVMState &State) const override { + return llvm::make_unique(State); + } + + std::unique_ptr + createUopsBenchmarkRunner(const LLVMState &State) const override { + return llvm::make_unique(State); + } + bool matchesArch(llvm::Triple::ArchType Arch) const override { return Arch == llvm::Triple::x86_64 || Arch == llvm::Triple::x86; } Index: llvm/trunk/tools/llvm-exegesis/llvm-exegesis.cpp =================================================================== --- llvm/trunk/tools/llvm-exegesis/llvm-exegesis.cpp +++ llvm/trunk/tools/llvm-exegesis/llvm-exegesis.cpp @@ -16,11 +16,9 @@ #include "lib/BenchmarkResult.h" #include "lib/BenchmarkRunner.h" #include "lib/Clustering.h" -#include "lib/Latency.h" #include "lib/LlvmState.h" #include "lib/PerfHelper.h" -#include "lib/Uops.h" -#include "lib/X86.h" +#include "lib/Target.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/Twine.h" #include "llvm/MC/MCInstBuilder.h" @@ -47,13 +45,16 @@ static llvm::cl::opt BenchmarkFile("benchmarks-file", llvm::cl::desc(""), llvm::cl::init("")); -enum class BenchmarkModeE { Latency, Uops, Analysis }; -static llvm::cl::opt BenchmarkMode( +static llvm::cl::opt BenchmarkMode( "mode", llvm::cl::desc("the mode to run"), - llvm::cl::values( - clEnumValN(BenchmarkModeE::Latency, "latency", "Instruction Latency"), - clEnumValN(BenchmarkModeE::Uops, "uops", "Uop Decomposition"), - clEnumValN(BenchmarkModeE::Analysis, "analysis", "Analysis"))); + llvm::cl::values(clEnumValN(exegesis::InstructionBenchmark::Latency, + "latency", "Instruction Latency"), + clEnumValN(exegesis::InstructionBenchmark::Uops, "uops", + "Uop Decomposition"), + // When not asking for a specific benchmark mode, we'll + // analyse the results. + clEnumValN(exegesis::InstructionBenchmark::Unknown, + "analysis", "Analysis"))); static llvm::cl::opt NumRepetitions("num-repetitions", @@ -128,9 +129,6 @@ LLVM_EXEGESIS_INITIALIZE_NATIVE_TARGET(); #endif - // FIXME: Target-specific filter. - X86Filter Filter; - const LLVMState State; const auto Opcode = GetOpcodeOrDie(State.getInstrInfo()); @@ -146,16 +144,10 @@ if (!State.getSubtargetInfo().getSchedModel().hasExtraProcessorInfo()) llvm::report_fatal_error("sched model is missing extra processor info!"); - std::unique_ptr Runner; - switch (BenchmarkMode) { - case BenchmarkModeE::Latency: - Runner = llvm::make_unique(State); - break; - case BenchmarkModeE::Uops: - Runner = llvm::make_unique(State); - break; - case BenchmarkModeE::Analysis: - llvm_unreachable("not a benchmark"); + const std::unique_ptr Runner = + State.getExegesisTarget().createBenchmarkRunner(BenchmarkMode, State); + if (!Runner) { + llvm::report_fatal_error("cannot create benchmark runner"); } if (NumRepetitions == 0) @@ -167,7 +159,7 @@ const BenchmarkResultContext Context = getBenchmarkResultContext(State); std::vector Results = - ExitOnErr(Runner->run(Opcode, Filter, NumRepetitions)); + ExitOnErr(Runner->run(Opcode, NumRepetitions)); for (InstructionBenchmark &Result : Results) ExitOnErr(Result.writeYaml(Context, BenchmarkFile)); @@ -245,7 +237,7 @@ return EXIT_FAILURE; }); - if (BenchmarkMode == BenchmarkModeE::Analysis) { + if (BenchmarkMode == exegesis::InstructionBenchmark::Unknown) { exegesis::analysisMain(); } else { exegesis::benchmarkMain(); Index: llvm/trunk/unittests/tools/llvm-exegesis/Common/AssemblerUtils.h =================================================================== --- llvm/trunk/unittests/tools/llvm-exegesis/Common/AssemblerUtils.h +++ llvm/trunk/unittests/tools/llvm-exegesis/Common/AssemblerUtils.h @@ -8,6 +8,7 @@ //===----------------------------------------------------------------------===// #include "Assembler.h" +#include "Target.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/TargetInstrInfo.h" @@ -36,11 +37,11 @@ } template inline void Check(llvm::MCInst MCInst, Bs... Bytes) { - CheckWithSetup(nullptr, {}, MCInst, Bytes...); + CheckWithSetup(ExegesisTarget::getDefault(), {}, MCInst, Bytes...); } template - inline void CheckWithSetup(const ExegesisTarget *ET, + inline void CheckWithSetup(const ExegesisTarget &ET, llvm::ArrayRef RegsToDef, llvm::MCInst MCInst, Bs... Bytes) { ExecutableFunction Function = @@ -67,7 +68,7 @@ } ExecutableFunction - assembleToFunction(const ExegesisTarget *ET, + assembleToFunction(const ExegesisTarget &ET, llvm::ArrayRef RegsToDef, llvm::ArrayRef Instructions) { llvm::SmallString<256> Buffer; Index: llvm/trunk/unittests/tools/llvm-exegesis/X86/SnippetGeneratorTest.cpp =================================================================== --- llvm/trunk/unittests/tools/llvm-exegesis/X86/SnippetGeneratorTest.cpp +++ llvm/trunk/unittests/tools/llvm-exegesis/X86/SnippetGeneratorTest.cpp @@ -217,17 +217,14 @@ class FakeBenchmarkRunner : public BenchmarkRunner { public: - using BenchmarkRunner::BenchmarkRunner; + FakeBenchmarkRunner(const LLVMState &State) + : BenchmarkRunner(State, InstructionBenchmark::Unknown) {} Instruction createInstruction(unsigned Opcode) { return Instruction(State.getInstrInfo().get(Opcode), RATC); } private: - InstructionBenchmark::ModeE getMode() const override { - return InstructionBenchmark::Unknown; - } - llvm::Expected generatePrototype(unsigned Opcode) const override { return llvm::make_error("not implemented",