[llvm-exegesis] Implements a cache of Instruction objects.
authorGuillaume Chatelet <gchatelet@google.com>
Wed, 24 Oct 2018 11:55:06 +0000 (11:55 +0000)
committerGuillaume Chatelet <gchatelet@google.com>
Wed, 24 Oct 2018 11:55:06 +0000 (11:55 +0000)
llvm-svn: 345130

llvm/tools/llvm-exegesis/lib/Latency.cpp
llvm/tools/llvm-exegesis/lib/LlvmState.cpp
llvm/tools/llvm-exegesis/lib/LlvmState.h
llvm/tools/llvm-exegesis/lib/MCInstrDescView.cpp
llvm/tools/llvm-exegesis/lib/MCInstrDescView.h
llvm/tools/llvm-exegesis/llvm-exegesis.cpp
llvm/unittests/tools/llvm-exegesis/X86/SnippetGeneratorTest.cpp

index ec92d93..602b379 100644 (file)
@@ -49,7 +49,7 @@ computeAliasingInstructions(const LLVMState &State, const Instruction &Instr,
   for (const unsigned OtherOpcode : Opcodes) {
     if (OtherOpcode == Instr.Description->getOpcode())
       continue;
-    const Instruction OtherInstr(State, OtherOpcode);
+    const Instruction &OtherInstr = State.getIC().getInstr(OtherOpcode);
     if (OtherInstr.hasMemoryOperands())
       continue;
     if (Instr.hasAliasingRegistersThrough(OtherInstr))
index ba786cc..58e9db3 100644 (file)
@@ -38,6 +38,7 @@ LLVMState::LLVMState(const std::string &Triple, const std::string &CpuName) {
   }
   RATC.reset(new RegisterAliasingTrackerCache(
       getRegInfo(), getFunctionReservedRegs(getTargetMachine())));
+  IC.reset(new InstructionsCache(getInstrInfo(), getRATC()));
 }
 
 LLVMState::LLVMState()
index f8ef866..9187385 100644 (file)
@@ -15,6 +15,7 @@
 #ifndef LLVM_TOOLS_LLVM_EXEGESIS_LLVMSTATE_H
 #define LLVM_TOOLS_LLVM_EXEGESIS_LLVMSTATE_H
 
+#include "MCInstrDescView.h"
 #include "RegisterAliasing.h"
 #include "llvm/MC/MCAsmInfo.h"
 #include "llvm/MC/MCInst.h"
@@ -57,11 +58,13 @@ public:
     return *TargetMachine->getMCSubtargetInfo();
   }
   const RegisterAliasingTrackerCache &getRATC() const { return *RATC; }
+  const InstructionsCache &getIC() const { return *IC; }
 
 private:
   const ExegesisTarget *TheExegesisTarget;
   std::unique_ptr<const llvm::TargetMachine> TargetMachine;
   std::unique_ptr<const RegisterAliasingTrackerCache> RATC;
+  std::unique_ptr<const InstructionsCache> IC;
 };
 
 } // namespace exegesis
index 2b4624b..e0521af 100644 (file)
@@ -95,10 +95,10 @@ const llvm::MCOperandInfo &Operand::getExplicitOperandInfo() const {
   return *Info;
 }
 
-Instruction::Instruction(const LLVMState &State, unsigned Opcode)
-    : Description(&State.getInstrInfo().get(Opcode)),
-      Name(State.getInstrInfo().getName(Opcode)) {
-  const auto &RATC = State.getRATC();
+Instruction::Instruction(const llvm::MCInstrInfo &InstrInfo,
+                         const RegisterAliasingTrackerCache &RATC,
+                         unsigned Opcode)
+    : Description(&InstrInfo.get(Opcode)), Name(InstrInfo.getName(Opcode)) {
   unsigned OpIndex = 0;
   for (; OpIndex < Description->getNumOperands(); ++OpIndex) {
     const auto &OpInfo = Description->opInfo_begin()[OpIndex];
@@ -262,6 +262,17 @@ void Instruction::dump(const llvm::MCRegisterInfo &RegInfo,
     Stream << "- hasAliasingRegisters\n";
 }
 
+InstructionsCache::InstructionsCache(const llvm::MCInstrInfo &InstrInfo,
+                                     const RegisterAliasingTrackerCache &RATC)
+    : InstrInfo(InstrInfo), RATC(RATC) {}
+
+const Instruction &InstructionsCache::getInstr(unsigned Opcode) const {
+  auto &Found = Instructions[Opcode];
+  if (!Found)
+    Found.reset(new Instruction(InstrInfo, RATC, Opcode));
+  return *Found;
+}
+
 bool RegisterOperandAssignment::
 operator==(const RegisterOperandAssignment &Other) const {
   return std::tie(Op, Reg) == std::tie(Other.Op, Other.Reg);
index 4e8278b..58efd2a 100644 (file)
@@ -20,8 +20,8 @@
 #define LLVM_TOOLS_LLVM_EXEGESIS_MCINSTRDESCVIEW_H
 
 #include <random>
+#include <unordered_map>
 
-#include "LlvmState.h"
 #include "RegisterAliasing.h"
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/Optional.h"
@@ -94,7 +94,8 @@ struct Operand {
 // A view over an MCInstrDesc offering a convenient interface to compute
 // Register aliasing.
 struct Instruction {
-  Instruction(const LLVMState &State, unsigned Opcode);
+  Instruction(const llvm::MCInstrInfo &InstrInfo,
+              const RegisterAliasingTrackerCache &RATC, unsigned Opcode);
 
   // Returns the Operand linked to this Variable.
   // In case the Variable is tied, the primary (i.e. Def) Operand is returned.
@@ -145,6 +146,22 @@ struct Instruction {
   llvm::BitVector AllUseRegs;  // The set of all aliased use registers.
 };
 
+// Instructions are expensive to instantiate. This class provides a cache of
+// Instructions with lazy construction.
+struct InstructionsCache {
+  InstructionsCache(const llvm::MCInstrInfo &InstrInfo,
+                    const RegisterAliasingTrackerCache &RATC);
+
+  // Returns the Instruction object corresponding to this Opcode.
+  const Instruction &getInstr(unsigned Opcode) const;
+
+private:
+  const llvm::MCInstrInfo &InstrInfo;
+  const RegisterAliasingTrackerCache &RATC;
+  mutable std::unordered_map<unsigned, std::unique_ptr<Instruction>>
+      Instructions;
+};
+
 // Represents the assignment of a Register to an Operand.
 struct RegisterOperandAssignment {
   RegisterOperandAssignment(const Operand *Operand, llvm::MCPhysReg Reg)
index ea99142..689a1e0 100644 (file)
@@ -147,7 +147,7 @@ getOpcodesOrDie(const llvm::MCInstrInfo &MCInstrInfo) {
 // Generates code snippets for opcode `Opcode`.
 static llvm::Expected<std::vector<BenchmarkCode>>
 generateSnippets(const LLVMState &State, unsigned Opcode) {
-  const Instruction Instr(State, Opcode);
+  const Instruction &Instr = State.getIC().getInstr(Opcode);
   const llvm::MCInstrDesc &InstrDesc = *Instr.Description;
   // Ignore instructions that we cannot run.
   if (InstrDesc.isPseudo())
index 0451735..1689def 100644 (file)
@@ -61,7 +61,7 @@ protected:
 
   std::vector<CodeTemplate> checkAndGetCodeTemplates(unsigned Opcode) {
     randomGenerator().seed(0); // Initialize seed.
-    const Instruction Instr(State, Opcode);
+    const Instruction &Instr = State.getIC().getInstr(Opcode);
     auto CodeTemplateOrError = Generator.generateCodeTemplates(Instr);
     EXPECT_FALSE(CodeTemplateOrError.takeError()); // Valid configuration.
     return std::move(CodeTemplateOrError.get());
@@ -341,7 +341,7 @@ TEST_F(UopsSnippetGeneratorTest, MemoryUse_Movsb) {
   // - hasAliasingImplicitRegisters (execution is always serial)
   // - hasAliasingRegisters
   const unsigned Opcode = llvm::X86::MOVSB;
-  const Instruction Instr(State, Opcode);
+  const Instruction &Instr = State.getIC().getInstr(Opcode);
   auto Error = Generator.generateCodeTemplates(Instr).takeError();
   EXPECT_TRUE((bool)Error);
   llvm::consumeError(std::move(Error));
@@ -352,7 +352,7 @@ public:
   FakeSnippetGenerator(const LLVMState &State) : SnippetGenerator(State) {}
 
   Instruction createInstruction(unsigned Opcode) {
-    return Instruction(State, Opcode);
+    return State.getIC().getInstr(Opcode);
   }
 
 private: