//===-- llvm-exegesis.cpp ---------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// /// /// \file /// Measures execution properties (latencies/uops) of an instruction. /// //===----------------------------------------------------------------------===// #include "lib/BenchmarkResult.h" #include "lib/BenchmarkRunner.h" #include "lib/Latency.h" #include "lib/LlvmState.h" #include "lib/PerfHelper.h" #include "lib/Uops.h" #include "lib/X86.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/Twine.h" #include "llvm/MC/MCInstBuilder.h" #include "llvm/MC/MCRegisterInfo.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Path.h" #include "llvm/Support/TargetSelect.h" #include #include #include #include static llvm::cl::opt OpcodeIndex("opcode-index", llvm::cl::desc("opcode to measure, by index"), llvm::cl::init(0)); static llvm::cl::opt OpcodeName("opcode-name", llvm::cl::desc("opcode to measure, by name"), llvm::cl::init("")); enum class BenchmarkModeE { Latency, Uops }; static llvm::cl::opt BenchmarkMode("benchmark-mode", llvm::cl::desc("the benchmark mode to run"), llvm::cl::values(clEnumValN(BenchmarkModeE::Latency, "latency", "Instruction Latency"), clEnumValN(BenchmarkModeE::Uops, "uops", "Uop Decomposition"))); static llvm::cl::opt NumRepetitions("num-repetitions", llvm::cl::desc("number of time to repeat the asm snippet"), llvm::cl::init(10000)); namespace exegesis { void main() { if (OpcodeName.empty() == (OpcodeIndex == 0)) { llvm::report_fatal_error( "please provide one and only one of 'opcode-index' or 'opcode-name'"); } llvm::InitializeNativeTarget(); llvm::InitializeNativeTargetAsmPrinter(); // FIXME: Target-specific filter. X86Filter Filter; const LLVMState State; if (!State.getSubtargetInfo().getSchedModel().hasExtraProcessorInfo()) llvm::report_fatal_error("sched model is missing extra processor info!"); unsigned Opcode = OpcodeIndex; if (Opcode == 0) { // Resolve opcode name -> opcode. for (unsigned I = 0, E = State.getInstrInfo().getNumOpcodes(); I < E; ++I) { if (State.getInstrInfo().getName(I) == OpcodeName) { Opcode = I; break; } } if (Opcode == 0) { llvm::report_fatal_error( llvm::Twine("unknown opcode ").concat(OpcodeName)); } } std::unique_ptr Runner; switch (BenchmarkMode) { case BenchmarkModeE::Latency: Runner = llvm::make_unique(); break; case BenchmarkModeE::Uops: Runner = llvm::make_unique(); break; } Runner->run(State, Opcode, NumRepetitions > 0 ? NumRepetitions : 1, Filter) .writeYamlOrDie("-"); } } // namespace exegesis int main(int Argc, char **Argv) { llvm::cl::ParseCommandLineOptions(Argc, Argv, ""); if (exegesis::pfm::pfmInitialize()) { llvm::errs() << "cannot initialize libpfm\n"; return EXIT_FAILURE; } exegesis::main(); exegesis::pfm::pfmTerminate(); return EXIT_SUCCESS; }