From da11b85606f532a1b4aac96d5f9c92eded60e568 Mon Sep 17 00:00:00 2001 From: Guillaume Chatelet Date: Wed, 24 Oct 2018 11:55:06 +0000 Subject: [PATCH] [llvm-exegesis] Implements a cache of Instruction objects. llvm-svn: 345130 --- llvm/tools/llvm-exegesis/lib/Latency.cpp | 2 +- llvm/tools/llvm-exegesis/lib/LlvmState.cpp | 1 + llvm/tools/llvm-exegesis/lib/LlvmState.h | 3 +++ llvm/tools/llvm-exegesis/lib/MCInstrDescView.cpp | 19 +++++++++++++++---- llvm/tools/llvm-exegesis/lib/MCInstrDescView.h | 21 +++++++++++++++++++-- llvm/tools/llvm-exegesis/llvm-exegesis.cpp | 2 +- .../llvm-exegesis/X86/SnippetGeneratorTest.cpp | 6 +++--- 7 files changed, 43 insertions(+), 11 deletions(-) diff --git a/llvm/tools/llvm-exegesis/lib/Latency.cpp b/llvm/tools/llvm-exegesis/lib/Latency.cpp index ec92d93..602b379 100644 --- a/llvm/tools/llvm-exegesis/lib/Latency.cpp +++ b/llvm/tools/llvm-exegesis/lib/Latency.cpp @@ -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)) diff --git a/llvm/tools/llvm-exegesis/lib/LlvmState.cpp b/llvm/tools/llvm-exegesis/lib/LlvmState.cpp index ba786cc..58e9db3 100644 --- a/llvm/tools/llvm-exegesis/lib/LlvmState.cpp +++ b/llvm/tools/llvm-exegesis/lib/LlvmState.cpp @@ -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() diff --git a/llvm/tools/llvm-exegesis/lib/LlvmState.h b/llvm/tools/llvm-exegesis/lib/LlvmState.h index f8ef866..9187385 100644 --- a/llvm/tools/llvm-exegesis/lib/LlvmState.h +++ b/llvm/tools/llvm-exegesis/lib/LlvmState.h @@ -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 TargetMachine; std::unique_ptr RATC; + std::unique_ptr IC; }; } // namespace exegesis diff --git a/llvm/tools/llvm-exegesis/lib/MCInstrDescView.cpp b/llvm/tools/llvm-exegesis/lib/MCInstrDescView.cpp index 2b4624b..e0521af 100644 --- a/llvm/tools/llvm-exegesis/lib/MCInstrDescView.cpp +++ b/llvm/tools/llvm-exegesis/lib/MCInstrDescView.cpp @@ -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); diff --git a/llvm/tools/llvm-exegesis/lib/MCInstrDescView.h b/llvm/tools/llvm-exegesis/lib/MCInstrDescView.h index 4e8278b..58efd2a 100644 --- a/llvm/tools/llvm-exegesis/lib/MCInstrDescView.h +++ b/llvm/tools/llvm-exegesis/lib/MCInstrDescView.h @@ -20,8 +20,8 @@ #define LLVM_TOOLS_LLVM_EXEGESIS_MCINSTRDESCVIEW_H #include +#include -#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> + Instructions; +}; + // Represents the assignment of a Register to an Operand. struct RegisterOperandAssignment { RegisterOperandAssignment(const Operand *Operand, llvm::MCPhysReg Reg) diff --git a/llvm/tools/llvm-exegesis/llvm-exegesis.cpp b/llvm/tools/llvm-exegesis/llvm-exegesis.cpp index ea99142..689a1e0 100644 --- a/llvm/tools/llvm-exegesis/llvm-exegesis.cpp +++ b/llvm/tools/llvm-exegesis/llvm-exegesis.cpp @@ -147,7 +147,7 @@ getOpcodesOrDie(const llvm::MCInstrInfo &MCInstrInfo) { // Generates code snippets for opcode `Opcode`. static llvm::Expected> 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()) diff --git a/llvm/unittests/tools/llvm-exegesis/X86/SnippetGeneratorTest.cpp b/llvm/unittests/tools/llvm-exegesis/X86/SnippetGeneratorTest.cpp index 0451735..1689def 100644 --- a/llvm/unittests/tools/llvm-exegesis/X86/SnippetGeneratorTest.cpp +++ b/llvm/unittests/tools/llvm-exegesis/X86/SnippetGeneratorTest.cpp @@ -61,7 +61,7 @@ protected: std::vector 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: -- 2.7.4