Re-land r329156 "Add llvm-exegesis tool."
Fixed to depend on and initialize the native target instead of X86.
llvm-svn: 329169
diff --git a/llvm/tools/llvm-exegesis/llvm-exegesis.cpp b/llvm/tools/llvm-exegesis/llvm-exegesis.cpp
new file mode 100644
index 0000000..c9dfe84
--- /dev/null
+++ b/llvm/tools/llvm-exegesis/llvm-exegesis.cpp
@@ -0,0 +1,114 @@
+//===-- 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 <algorithm>
+#include <random>
+#include <string>
+#include <unordered_map>
+
+static llvm::cl::opt<unsigned>
+ OpcodeIndex("opcode-index", llvm::cl::desc("opcode to measure, by index"),
+ llvm::cl::init(0));
+
+static llvm::cl::opt<std::string>
+ OpcodeName("opcode-name", llvm::cl::desc("opcode to measure, by name"),
+ llvm::cl::init(""));
+
+enum class BenchmarkModeE { Latency, Uops };
+static llvm::cl::opt<BenchmarkModeE>
+ 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<unsigned>
+ 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;
+
+ 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<BenchmarkRunner> Runner;
+ switch (BenchmarkMode) {
+ case BenchmarkModeE::Latency:
+ Runner = llvm::make_unique<LatencyBenchmarkRunner>();
+ break;
+ case BenchmarkModeE::Uops:
+ Runner = llvm::make_unique<UopsBenchmarkRunner>();
+ 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;
+}