[llvm-exegesis] Add a Configuration object for Benchmark.

Summary: This is the first step to have the BenchmarkRunner create and measure many different configurations (different initial values for instance).

Reviewers: courbet

Subscribers: tschuett, llvm-commits

Differential Revision: https://reviews.llvm.org/D47826

llvm-svn: 334169
diff --git a/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp b/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp
index 1d8b34f..4926637 100644
--- a/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp
+++ b/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp
@@ -52,13 +52,14 @@
     return InstrBenchmark;
   }
   llvm::raw_string_ostream InfoStream(InstrBenchmark.Info);
-  llvm::Expected<std::vector<llvm::MCInst>> SnippetOrError =
-      createSnippet(RATC, Opcode, InfoStream);
-  if (llvm::Error E = SnippetOrError.takeError()) {
+  llvm::Expected<BenchmarkConfiguration> ConfigurationOrError =
+      createConfiguration(RATC, Opcode, InfoStream);
+  if (llvm::Error E = ConfigurationOrError.takeError()) {
     InstrBenchmark.Error = llvm::toString(std::move(E));
     return InstrBenchmark;
   }
-  std::vector<llvm::MCInst> &Snippet = SnippetOrError.get();
+  BenchmarkConfiguration &Configuration = ConfigurationOrError.get();
+  const std::vector<llvm::MCInst> &Snippet = Configuration.Snippet;
   if (Snippet.empty()) {
     InstrBenchmark.Error = "Empty snippet";
     return InstrBenchmark;
diff --git a/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.h b/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.h
index 5dfd05e..8907ccc 100644
--- a/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.h
+++ b/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.h
@@ -26,6 +26,17 @@
 
 namespace exegesis {
 
+// A collection of instructions that are to be assembled, executed and measured.
+struct BenchmarkConfiguration {
+  // This code is run before the Snippet is iterated. Since it is part of the
+  // measurement it should be as short as possible. It is usually used to setup
+  // the content of the Registers.
+  std::vector<llvm::MCInst> SnippetSetup;
+
+  // The sequence of instructions that are to be repeated.
+  std::vector<llvm::MCInst> Snippet;
+};
+
 // Common code for all benchmark modes.
 class BenchmarkRunner {
 public:
@@ -56,9 +67,9 @@
 private:
   virtual InstructionBenchmark::ModeE getMode() const = 0;
 
-  virtual llvm::Expected<std::vector<llvm::MCInst>>
-  createSnippet(RegisterAliasingTrackerCache &RATC, unsigned Opcode,
-                llvm::raw_ostream &Debug) const = 0;
+  virtual llvm::Expected<BenchmarkConfiguration>
+  createConfiguration(RegisterAliasingTrackerCache &RATC, unsigned Opcode,
+                      llvm::raw_ostream &Debug) const = 0;
 
   virtual std::vector<BenchmarkMeasure>
   runMeasurements(const ExecutableFunction &EF,
diff --git a/llvm/tools/llvm-exegesis/lib/Latency.cpp b/llvm/tools/llvm-exegesis/lib/Latency.cpp
index 9c4ed56..59097e1 100644
--- a/llvm/tools/llvm-exegesis/lib/Latency.cpp
+++ b/llvm/tools/llvm-exegesis/lib/Latency.cpp
@@ -56,11 +56,12 @@
   return InstructionBenchmark::Latency;
 }
 
-llvm::Expected<std::vector<llvm::MCInst>>
-LatencyBenchmarkRunner::createSnippet(RegisterAliasingTrackerCache &RATC,
-                                      unsigned Opcode,
-                                      llvm::raw_ostream &Info) const {
-  std::vector<llvm::MCInst> Snippet;
+llvm::Expected<BenchmarkConfiguration>
+LatencyBenchmarkRunner::createConfiguration(RegisterAliasingTrackerCache &RATC,
+                                            unsigned Opcode,
+                                            llvm::raw_ostream &Info) const {
+  BenchmarkConfiguration Configuration;
+  std::vector<llvm::MCInst> &Snippet = Configuration.Snippet;
   const llvm::MCInstrDesc &MCInstrDesc = MCInstrInfo.get(Opcode);
   const Instruction ThisInstruction(MCInstrDesc, RATC);
 
@@ -77,7 +78,7 @@
       Info << "implicit Self cycles, picking random values.\n";
     }
     Snippet.push_back(randomizeUnsetVariablesAndBuild(ThisInstruction));
-    return Snippet;
+    return Configuration;
   }
 
   // Let's try to create a dependency through another opcode.
@@ -102,7 +103,7 @@
          << ".\n";
     Snippet.push_back(randomizeUnsetVariablesAndBuild(ThisInstruction));
     Snippet.push_back(randomizeUnsetVariablesAndBuild(OtherInstruction));
-    return Snippet;
+    return Configuration;
   }
 
   return makeError(
diff --git a/llvm/tools/llvm-exegesis/lib/Latency.h b/llvm/tools/llvm-exegesis/lib/Latency.h
index 1e6150e..6726a10 100644
--- a/llvm/tools/llvm-exegesis/lib/Latency.h
+++ b/llvm/tools/llvm-exegesis/lib/Latency.h
@@ -27,9 +27,9 @@
 private:
   InstructionBenchmark::ModeE getMode() const override;
 
-  llvm::Expected<std::vector<llvm::MCInst>>
-  createSnippet(RegisterAliasingTrackerCache &RATC, unsigned OpcodeIndex,
-                llvm::raw_ostream &Info) const override;
+  llvm::Expected<BenchmarkConfiguration>
+  createConfiguration(RegisterAliasingTrackerCache &RATC, unsigned OpcodeIndex,
+                      llvm::raw_ostream &Info) const override;
 
   std::vector<BenchmarkMeasure>
   runMeasurements(const ExecutableFunction &EF,
diff --git a/llvm/tools/llvm-exegesis/lib/Uops.cpp b/llvm/tools/llvm-exegesis/lib/Uops.cpp
index b90ab1a..7f1079e 100644
--- a/llvm/tools/llvm-exegesis/lib/Uops.cpp
+++ b/llvm/tools/llvm-exegesis/lib/Uops.cpp
@@ -145,11 +145,12 @@
   return InstructionBenchmark::Uops;
 }
 
-llvm::Expected<std::vector<llvm::MCInst>>
-UopsBenchmarkRunner::createSnippet(RegisterAliasingTrackerCache &RATC,
-                                   unsigned Opcode,
-                                   llvm::raw_ostream &Info) const {
-  std::vector<llvm::MCInst> Snippet;
+llvm::Expected<BenchmarkConfiguration>
+UopsBenchmarkRunner::createConfiguration(RegisterAliasingTrackerCache &RATC,
+                                         unsigned Opcode,
+                                         llvm::raw_ostream &Info) const {
+  BenchmarkConfiguration Configuration;
+  std::vector<llvm::MCInst> &Snippet = Configuration.Snippet;
   const llvm::MCInstrDesc &MCInstrDesc = MCInstrInfo.get(Opcode);
   const Instruction Instruction(MCInstrDesc, RATC);
 
@@ -162,12 +163,12 @@
   if (SelfAliasing.empty()) {
     Info << "instruction is parallel, repeating a random one.\n";
     Snippet.push_back(randomizeUnsetVariablesAndBuild(Instruction));
-    return Snippet;
+    return Configuration;
   }
   if (SelfAliasing.hasImplicitAliasing()) {
     Info << "instruction is serial, repeating a random one.\n";
     Snippet.push_back(randomizeUnsetVariablesAndBuild(Instruction));
-    return Snippet;
+    return Configuration;
   }
   const auto TiedVariables = getTiedVariables(Instruction);
   if (!TiedVariables.empty()) {
@@ -188,7 +189,7 @@
       Var->AssignedValue = llvm::MCOperand::createReg(Reg);
       Snippet.push_back(randomizeUnsetVariablesAndBuild(Instruction));
     }
-    return Snippet;
+    return Configuration;
   }
   // No tied variables, we pick random values for defs.
   llvm::BitVector Defs(MCRegisterInfo.getNumRegs());
@@ -219,7 +220,7 @@
   Info
       << "instruction has no tied variables picking Uses different from defs\n";
   Snippet.push_back(randomizeUnsetVariablesAndBuild(Instruction));
-  return Snippet;
+  return Configuration;
 }
 
 std::vector<BenchmarkMeasure>
diff --git a/llvm/tools/llvm-exegesis/lib/Uops.h b/llvm/tools/llvm-exegesis/lib/Uops.h
index a58fa1c..54b9433 100644
--- a/llvm/tools/llvm-exegesis/lib/Uops.h
+++ b/llvm/tools/llvm-exegesis/lib/Uops.h
@@ -27,9 +27,9 @@
 private:
   InstructionBenchmark::ModeE getMode() const override;
 
-  llvm::Expected<std::vector<llvm::MCInst>>
-  createSnippet(RegisterAliasingTrackerCache &RATC, unsigned Opcode,
-                llvm::raw_ostream &Info) const override;
+  llvm::Expected<BenchmarkConfiguration>
+  createConfiguration(RegisterAliasingTrackerCache &RATC, unsigned Opcode,
+                      llvm::raw_ostream &Info) const override;
 
   std::vector<BenchmarkMeasure>
   runMeasurements(const ExecutableFunction &EF,