diff options
author | Guillaume Chatelet <gchatelet@google.com> | 2018-08-03 09:29:38 +0000 |
---|---|---|
committer | Guillaume Chatelet <gchatelet@google.com> | 2018-08-03 09:29:38 +0000 |
commit | 80d3cc7363b473caef0700747787970daf2003f7 (patch) | |
tree | 23636df19497db6ab0ee6ae910e468e9f9700583 /tools/llvm-exegesis | |
parent | 33493244220b8f1bc9b52bfa4bf02d54ccebdd72 (diff) |
[llvm-exegesis] Renaming classes and functions.
Summary: Functional No Op.
Reviewers: gchatelet
Subscribers: tschuett, courbet, llvm-commits
Differential Revision: https://reviews.llvm.org/D50231
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@338836 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'tools/llvm-exegesis')
-rw-r--r-- | tools/llvm-exegesis/lib/BenchmarkRunner.cpp | 122 | ||||
-rw-r--r-- | tools/llvm-exegesis/lib/BenchmarkRunner.h | 51 | ||||
-rw-r--r-- | tools/llvm-exegesis/lib/Latency.cpp | 25 | ||||
-rw-r--r-- | tools/llvm-exegesis/lib/Latency.h | 8 | ||||
-rw-r--r-- | tools/llvm-exegesis/lib/MCInstrDescView.cpp | 4 | ||||
-rw-r--r-- | tools/llvm-exegesis/lib/MCInstrDescView.h | 50 | ||||
-rw-r--r-- | tools/llvm-exegesis/lib/Uops.cpp | 67 | ||||
-rw-r--r-- | tools/llvm-exegesis/lib/Uops.h | 4 | ||||
-rw-r--r-- | tools/llvm-exegesis/lib/X86/Target.cpp | 24 |
9 files changed, 174 insertions, 181 deletions
diff --git a/tools/llvm-exegesis/lib/BenchmarkRunner.cpp b/tools/llvm-exegesis/lib/BenchmarkRunner.cpp index f740489dd76..42fad2ff48f 100644 --- a/tools/llvm-exegesis/lib/BenchmarkRunner.cpp +++ b/tools/llvm-exegesis/lib/BenchmarkRunner.cpp @@ -47,55 +47,54 @@ BenchmarkRunner::run(unsigned Opcode, unsigned NumRepetitions) { return llvm::make_error<BenchmarkFailure>( "Unsupported opcode: isCall/isReturn"); - llvm::Expected<std::vector<BenchmarkConfiguration>> ConfigurationOrError = + llvm::Expected<std::vector<BenchmarkCode>> ConfigurationOrError = generateConfigurations(Opcode); if (llvm::Error E = ConfigurationOrError.takeError()) return std::move(E); std::vector<InstructionBenchmark> InstrBenchmarks; - for (const BenchmarkConfiguration &Conf : ConfigurationOrError.get()) - InstrBenchmarks.push_back(runOne(Conf, Opcode, NumRepetitions)); + for (const BenchmarkCode &Conf : ConfigurationOrError.get()) + InstrBenchmarks.push_back(runConfiguration(Conf, Opcode, NumRepetitions)); return InstrBenchmarks; } +// Repeat the snippet until there are at least NumInstructions in the resulting +// code. +static std::vector<llvm::MCInst> +GenerateInstructions(const BenchmarkCode &BC, const int MinInstructions) { + std::vector<llvm::MCInst> Code = BC.Instructions; + for (int I = 0; I < MinInstructions; ++I) + Code.push_back(BC.Instructions[I % BC.Instructions.size()]); + return Code; +} + InstructionBenchmark -BenchmarkRunner::runOne(const BenchmarkConfiguration &Configuration, - unsigned Opcode, unsigned NumRepetitions) const { +BenchmarkRunner::runConfiguration(const BenchmarkCode &BC, unsigned Opcode, + unsigned NumRepetitions) const { InstructionBenchmark InstrBenchmark; InstrBenchmark.Mode = Mode; InstrBenchmark.CpuName = State.getTargetMachine().getTargetCPU(); InstrBenchmark.LLVMTriple = State.getTargetMachine().getTargetTriple().normalize(); InstrBenchmark.NumRepetitions = NumRepetitions; - InstrBenchmark.Info = Configuration.Info; + InstrBenchmark.Info = BC.Info; - const std::vector<llvm::MCInst> &Snippet = Configuration.Snippet; - if (Snippet.empty()) { + const std::vector<llvm::MCInst> &Instructions = BC.Instructions; + if (Instructions.empty()) { InstrBenchmark.Error = "Empty snippet"; return InstrBenchmark; } - InstrBenchmark.Key.Instructions = Snippet; - - // Repeat the snippet until there are at least NumInstructions in the - // resulting code. The snippet is always repeated at least once. - const auto GenerateInstructions = [&Configuration]( - const int MinInstructions) { - std::vector<llvm::MCInst> Code = Configuration.Snippet; - for (int I = 0; I < MinInstructions; ++I) - Code.push_back(Configuration.Snippet[I % Configuration.Snippet.size()]); - return Code; - }; + InstrBenchmark.Key.Instructions = Instructions; // Assemble at least kMinInstructionsForSnippet instructions by repeating the // snippet for debug/analysis. This is so that the user clearly understands // that the inside instructions are repeated. constexpr const int kMinInstructionsForSnippet = 16; { - auto ObjectFilePath = - writeObjectFile(Configuration.SnippetSetup, - GenerateInstructions(kMinInstructionsForSnippet)); + auto ObjectFilePath = writeObjectFile( + BC, GenerateInstructions(BC, kMinInstructionsForSnippet)); if (llvm::Error E = ObjectFilePath.takeError()) { InstrBenchmark.Error = llvm::toString(std::move(E)); return InstrBenchmark; @@ -108,9 +107,8 @@ BenchmarkRunner::runOne(const BenchmarkConfiguration &Configuration, // Assemble NumRepetitions instructions repetitions of the snippet for // measurements. - auto ObjectFilePath = - writeObjectFile(Configuration.SnippetSetup, - GenerateInstructions(InstrBenchmark.NumRepetitions)); + auto ObjectFilePath = writeObjectFile( + BC, GenerateInstructions(BC, InstrBenchmark.NumRepetitions)); if (llvm::Error E = ObjectFilePath.takeError()) { InstrBenchmark.Error = llvm::toString(std::move(E)); return InstrBenchmark; @@ -124,37 +122,41 @@ BenchmarkRunner::runOne(const BenchmarkConfiguration &Configuration, return InstrBenchmark; } -llvm::Expected<std::vector<BenchmarkConfiguration>> +llvm::Expected<std::vector<BenchmarkCode>> BenchmarkRunner::generateConfigurations(unsigned Opcode) const { - if (auto E = generatePrototype(Opcode)) { - SnippetPrototype &Prototype = E.get(); - // TODO: Generate as many configurations as needed here. - BenchmarkConfiguration Configuration; - Configuration.Info = Prototype.Explanation; - for (InstructionBuilder &IB : Prototype.Snippet) { - IB.randomizeUnsetVariables( - Prototype.ScratchSpaceReg - ? RATC.getRegister(Prototype.ScratchSpaceReg).aliasedBits() - : RATC.emptyRegisters()); - Configuration.Snippet.push_back(IB.build()); + if (auto E = generateCodeTemplate(Opcode)) { + CodeTemplate &CT = E.get(); + std::vector<BenchmarkCode> Output; + // TODO: Generate as many BenchmarkCode as needed. + { + BenchmarkCode BC; + BC.Info = CT.Info; + for (InstructionBuilder &IB : CT.Instructions) { + IB.randomizeUnsetVariables( + CT.ScratchSpacePointerInReg + ? RATC.getRegister(CT.ScratchSpacePointerInReg).aliasedBits() + : RATC.emptyRegisters()); + BC.Instructions.push_back(IB.build()); + } + if (CT.ScratchSpacePointerInReg) + BC.LiveIns.push_back(CT.ScratchSpacePointerInReg); + BC.RegsToDef = computeRegsToDef(CT.Instructions); + Output.push_back(std::move(BC)); } - if (Prototype.ScratchSpaceReg) - Configuration.SnippetSetup.LiveIns.push_back(Prototype.ScratchSpaceReg); - Configuration.SnippetSetup.RegsToDef = computeRegsToDef(Prototype.Snippet); - return std::vector<BenchmarkConfiguration>{Configuration}; + return Output; } else return E.takeError(); } std::vector<unsigned> BenchmarkRunner::computeRegsToDef( - const std::vector<InstructionBuilder> &Snippet) const { + const std::vector<InstructionBuilder> &Instructions) const { // Collect all register uses and create an assignment for each of them. // Ignore memory operands which are handled separately. // Loop invariant: DefinedRegs[i] is true iif it has been set at least once // before the current instruction. llvm::BitVector DefinedRegs = RATC.emptyRegisters(); std::vector<unsigned> RegsToDef; - for (const InstructionBuilder &IB : Snippet) { + for (const InstructionBuilder &IB : Instructions) { // Returns the register that this Operand sets or uses, or 0 if this is not // a register. const auto GetOpReg = [&IB](const Operand &Op) -> unsigned { @@ -189,7 +191,7 @@ std::vector<unsigned> BenchmarkRunner::computeRegsToDef( } llvm::Expected<std::string> -BenchmarkRunner::writeObjectFile(const BenchmarkConfiguration::Setup &Setup, +BenchmarkRunner::writeObjectFile(const BenchmarkCode &BC, llvm::ArrayRef<llvm::MCInst> Code) const { int ResultFD = 0; llvm::SmallString<256> ResultPath; @@ -198,38 +200,36 @@ BenchmarkRunner::writeObjectFile(const BenchmarkConfiguration::Setup &Setup, return std::move(E); llvm::raw_fd_ostream OFS(ResultFD, true /*ShouldClose*/); assembleToStream(State.getExegesisTarget(), State.createTargetMachine(), - Setup.LiveIns, Setup.RegsToDef, Code, OFS); + BC.LiveIns, BC.RegsToDef, Code, OFS); return ResultPath.str(); } -llvm::Expected<SnippetPrototype> -BenchmarkRunner::generateSelfAliasingPrototype(const Instruction &Instr) const { +llvm::Expected<CodeTemplate> BenchmarkRunner::generateSelfAliasingCodeTemplate( + const Instruction &Instr) const { const AliasingConfigurations SelfAliasing(Instr, Instr); if (SelfAliasing.empty()) { return llvm::make_error<BenchmarkFailure>("empty self aliasing"); } - SnippetPrototype Prototype; + CodeTemplate CT; InstructionBuilder IB(Instr); if (SelfAliasing.hasImplicitAliasing()) { - Prototype.Explanation = "implicit Self cycles, picking random values."; + CT.Info = "implicit Self cycles, picking random values."; } else { - Prototype.Explanation = - "explicit self cycles, selecting one aliasing Conf."; + CT.Info = "explicit self cycles, selecting one aliasing Conf."; // This is a self aliasing instruction so defs and uses are from the same // instance, hence twice IB in the following call. setRandomAliasing(SelfAliasing, IB, IB); } - Prototype.Snippet.push_back(std::move(IB)); - return std::move(Prototype); + CT.Instructions.push_back(std::move(IB)); + return std::move(CT); } -llvm::Expected<SnippetPrototype> -BenchmarkRunner::generateUnconstrainedPrototype(const Instruction &Instr, - llvm::StringRef Msg) const { - SnippetPrototype Prototype; - Prototype.Explanation = - llvm::formatv("{0}, repeating an unconstrained assignment", Msg); - Prototype.Snippet.emplace_back(Instr); - return std::move(Prototype); +llvm::Expected<CodeTemplate> +BenchmarkRunner::generateUnconstrainedCodeTemplate(const Instruction &Instr, + llvm::StringRef Msg) const { + CodeTemplate CT; + CT.Info = llvm::formatv("{0}, repeating an unconstrained assignment", Msg); + CT.Instructions.emplace_back(Instr); + return std::move(CT); } } // namespace exegesis diff --git a/tools/llvm-exegesis/lib/BenchmarkRunner.h b/tools/llvm-exegesis/lib/BenchmarkRunner.h index af3968f8944..fcf89f838b4 100644 --- a/tools/llvm-exegesis/lib/BenchmarkRunner.h +++ b/tools/llvm-exegesis/lib/BenchmarkRunner.h @@ -37,18 +37,17 @@ public: }; // 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. - struct Setup { - std::vector<unsigned> LiveIns; // The registers that are live on entry. - std::vector<unsigned> RegsToDef; - }; - Setup SnippetSetup; - +struct BenchmarkCode { // The sequence of instructions that are to be repeated. - std::vector<llvm::MCInst> Snippet; + std::vector<llvm::MCInst> Instructions; + + // Before the code is executed some instructions are added to setup the + // registers initial values. + std::vector<unsigned> RegsToDef; + + // We also need to provide the registers that are live on entry for the + // assembler to generate proper prologue/epilogue. + std::vector<unsigned> LiveIns; // Informations about how this configuration was built. std::string Info; @@ -90,34 +89,34 @@ protected: const LLVMState &State; const RegisterAliasingTrackerCache RATC; - // Generates a single instruction prototype that has a self-dependency. - llvm::Expected<SnippetPrototype> - generateSelfAliasingPrototype(const Instruction &Instr) const; - // Generates a single instruction prototype without assignment constraints. - llvm::Expected<SnippetPrototype> - generateUnconstrainedPrototype(const Instruction &Instr, - llvm::StringRef Msg) const; + // Generates a single code template that has a self-dependency. + llvm::Expected<CodeTemplate> + generateSelfAliasingCodeTemplate(const Instruction &Instr) const; + // Generates a single code template without assignment constraints. + llvm::Expected<CodeTemplate> + generateUnconstrainedCodeTemplate(const Instruction &Instr, + llvm::StringRef Msg) const; private: // API to be implemented by subclasses. - virtual llvm::Expected<SnippetPrototype> - generatePrototype(unsigned Opcode) const = 0; + virtual llvm::Expected<CodeTemplate> + generateCodeTemplate(unsigned Opcode) const = 0; virtual std::vector<BenchmarkMeasure> runMeasurements(const ExecutableFunction &EF, ScratchSpace &Scratch, const unsigned NumRepetitions) const = 0; // Internal helpers. - InstructionBenchmark runOne(const BenchmarkConfiguration &Configuration, - unsigned Opcode, unsigned NumRepetitions) const; + InstructionBenchmark runConfiguration(const BenchmarkCode &Configuration, + unsigned Opcode, + unsigned NumRepetitions) const; - // Calls generatePrototype and expands the SnippetPrototype into one or more - // BenchmarkConfiguration. - llvm::Expected<std::vector<BenchmarkConfiguration>> + // Calls generateCodeTemplate and expands it into one or more BenchmarkCode. + llvm::Expected<std::vector<BenchmarkCode>> generateConfigurations(unsigned Opcode) const; llvm::Expected<std::string> - writeObjectFile(const BenchmarkConfiguration::Setup &Setup, + writeObjectFile(const BenchmarkCode &Configuration, llvm::ArrayRef<llvm::MCInst> Code) const; const InstructionBenchmark::ModeE Mode; diff --git a/tools/llvm-exegesis/lib/Latency.cpp b/tools/llvm-exegesis/lib/Latency.cpp index 12bc8cd32b0..b8452ac35a8 100644 --- a/tools/llvm-exegesis/lib/Latency.cpp +++ b/tools/llvm-exegesis/lib/Latency.cpp @@ -42,7 +42,7 @@ llvm::Error LatencyBenchmarkRunner::isInfeasible( return llvm::Error::success(); } -llvm::Expected<SnippetPrototype> +llvm::Expected<CodeTemplate> LatencyBenchmarkRunner::generateTwoInstructionPrototype( const Instruction &Instr) const { std::vector<unsigned> Opcodes; @@ -68,28 +68,27 @@ LatencyBenchmarkRunner::generateTwoInstructionPrototype( setRandomAliasing(Forward, ThisIB, OtherIB); if (!Back.hasImplicitAliasing()) setRandomAliasing(Back, OtherIB, ThisIB); - SnippetPrototype Prototype; - Prototype.Explanation = - llvm::formatv("creating cycle through {0}.", - State.getInstrInfo().getName(OtherOpcode)); - Prototype.Snippet.push_back(std::move(ThisIB)); - Prototype.Snippet.push_back(std::move(OtherIB)); - return std::move(Prototype); + CodeTemplate CT; + CT.Info = llvm::formatv("creating cycle through {0}.", + State.getInstrInfo().getName(OtherOpcode)); + CT.Instructions.push_back(std::move(ThisIB)); + CT.Instructions.push_back(std::move(OtherIB)); + return std::move(CT); } return llvm::make_error<BenchmarkFailure>( "Infeasible : Didn't find any scheme to make the instruction serial"); } -llvm::Expected<SnippetPrototype> -LatencyBenchmarkRunner::generatePrototype(unsigned Opcode) const { +llvm::Expected<CodeTemplate> +LatencyBenchmarkRunner::generateCodeTemplate(unsigned Opcode) const { const auto &InstrDesc = State.getInstrInfo().get(Opcode); if (auto E = isInfeasible(InstrDesc)) return std::move(E); const Instruction Instr(InstrDesc, RATC); - if (auto SelfAliasingPrototype = generateSelfAliasingPrototype(Instr)) - return SelfAliasingPrototype; + if (auto CT = generateSelfAliasingCodeTemplate(Instr)) + return CT; else - llvm::consumeError(SelfAliasingPrototype.takeError()); + llvm::consumeError(CT.takeError()); // No self aliasing, trying to create a dependency through another opcode. return generateTwoInstructionPrototype(Instr); } diff --git a/tools/llvm-exegesis/lib/Latency.h b/tools/llvm-exegesis/lib/Latency.h index fdaeb786fa5..f8c524afce4 100644 --- a/tools/llvm-exegesis/lib/Latency.h +++ b/tools/llvm-exegesis/lib/Latency.h @@ -26,14 +26,14 @@ public: : BenchmarkRunner(State, InstructionBenchmark::Latency) {} ~LatencyBenchmarkRunner() override; - llvm::Expected<SnippetPrototype> - generatePrototype(unsigned Opcode) const override; + llvm::Expected<CodeTemplate> + generateCodeTemplate(unsigned Opcode) const override; private: llvm::Error isInfeasible(const llvm::MCInstrDesc &MCInstrDesc) const; - llvm::Expected<SnippetPrototype> generateTwoInstructionPrototype( - const Instruction &Instr) const; + llvm::Expected<CodeTemplate> + generateTwoInstructionPrototype(const Instruction &Instr) const; std::vector<BenchmarkMeasure> runMeasurements(const ExecutableFunction &EF, ScratchSpace &Scratch, diff --git a/tools/llvm-exegesis/lib/MCInstrDescView.cpp b/tools/llvm-exegesis/lib/MCInstrDescView.cpp index 39cb921d360..fc78bb121ae 100644 --- a/tools/llvm-exegesis/lib/MCInstrDescView.cpp +++ b/tools/llvm-exegesis/lib/MCInstrDescView.cpp @@ -159,9 +159,9 @@ llvm::MCInst InstructionBuilder::build() const { return Result; } -SnippetPrototype::SnippetPrototype(SnippetPrototype &&) = default; +CodeTemplate::CodeTemplate(CodeTemplate &&) = default; -SnippetPrototype &SnippetPrototype::operator=(SnippetPrototype &&) = default; +CodeTemplate &CodeTemplate::operator=(CodeTemplate &&) = default; bool RegisterOperandAssignment:: operator==(const RegisterOperandAssignment &Other) const { diff --git a/tools/llvm-exegesis/lib/MCInstrDescView.h b/tools/llvm-exegesis/lib/MCInstrDescView.h index 823c9e6b0fe..51f44cae45f 100644 --- a/tools/llvm-exegesis/lib/MCInstrDescView.h +++ b/tools/llvm-exegesis/lib/MCInstrDescView.h @@ -86,10 +86,10 @@ struct Instruction { struct InstructionBuilder { InstructionBuilder(const Instruction &Instr); - InstructionBuilder(const InstructionBuilder &); - InstructionBuilder &operator=(const InstructionBuilder &); - InstructionBuilder(InstructionBuilder &&); - InstructionBuilder &operator=(InstructionBuilder &&); + InstructionBuilder(const InstructionBuilder &); // default + InstructionBuilder &operator=(const InstructionBuilder &); // default + InstructionBuilder(InstructionBuilder &&); // default + InstructionBuilder &operator=(InstructionBuilder &&); // default unsigned getOpcode() const; llvm::MCOperand &getValueFor(const Variable &Var); @@ -102,34 +102,34 @@ struct InstructionBuilder { // Do not use any of the registers in `ForbiddenRegs`. void randomizeUnsetVariables(const llvm::BitVector &ForbiddenRegs); - // Returns the instance as an llvm::MCInst. The InstructionBuilder must be - // fully allocated (no invalid variables). + // Builds an llvm::MCInst from this InstructionBuilder setting its operands to + // the corresponding variable values. + // Precondition: All VariableValues must be set. llvm::MCInst build() const; Instruction Instr; llvm::SmallVector<llvm::MCOperand, 4> VariableValues; }; -// A prototype is a set of InstructionInstances with an explanation of how -// it's been built. The prototype can then be randomized to exercice several -// immediate values. It is also used to gather the used registers and define -// their initial values. -struct SnippetPrototype { - SnippetPrototype() = default; - - // No copy. - SnippetPrototype(const SnippetPrototype &) = delete; - SnippetPrototype &operator=(const SnippetPrototype &) = delete; - - // Moving is OK. - SnippetPrototype(SnippetPrototype &&); - SnippetPrototype &operator=(SnippetPrototype &&); - - std::string Explanation; - // If the prototype uses the provided scratch memory, the register in which +// A CodeTemplate is a set of InstructionBuilders that may not be fully +// specified (i.e. some variables are not yet set). +// This allows the BenchmarkRunner to instantiate it many times with specific +// values to study their impact on instruction's performance. +struct CodeTemplate { + CodeTemplate() = default; + + CodeTemplate(CodeTemplate &&); // default + CodeTemplate &operator=(CodeTemplate &&); // default + CodeTemplate(const CodeTemplate &) = delete; + CodeTemplate &operator=(const CodeTemplate &) = delete; + + // Some information about how this template has been created. + std::string Info; + // The list of the instructions for this template. + std::vector<InstructionBuilder> Instructions; + // If the template uses the provided scratch memory, the register in which // the pointer to this memory is passed in to the function. - unsigned ScratchSpaceReg = 0; - std::vector<InstructionBuilder> Snippet; + unsigned ScratchSpacePointerInReg = 0; }; // Represents the assignment of a Register to an Operand. diff --git a/tools/llvm-exegesis/lib/Uops.cpp b/tools/llvm-exegesis/lib/Uops.cpp index 3089a98ac48..d7346de85a0 100644 --- a/tools/llvm-exegesis/lib/Uops.cpp +++ b/tools/llvm-exegesis/lib/Uops.cpp @@ -125,47 +125,47 @@ static void remove(llvm::BitVector &a, const llvm::BitVector &b) { UopsBenchmarkRunner::~UopsBenchmarkRunner() = default; void UopsBenchmarkRunner::instantiateMemoryOperands( - const unsigned ScratchSpaceReg, - std::vector<InstructionBuilder> &Snippet) const { - if (ScratchSpaceReg == 0) + const unsigned ScratchSpacePointerInReg, + std::vector<InstructionBuilder> &Instructions) const { + if (ScratchSpacePointerInReg == 0) return; // no memory operands. const auto &ET = State.getExegesisTarget(); const unsigned MemStep = ET.getMaxMemoryAccessSize(); - const size_t OriginalSnippetSize = Snippet.size(); + const size_t OriginalInstructionsSize = Instructions.size(); size_t I = 0; - for (InstructionBuilder &IB : Snippet) { - ET.fillMemoryOperands(IB, ScratchSpaceReg, I * MemStep); + for (InstructionBuilder &IB : Instructions) { + ET.fillMemoryOperands(IB, ScratchSpacePointerInReg, I * MemStep); ++I; } - while (Snippet.size() < kMinNumDifferentAddresses) { - InstructionBuilder IB = Snippet[I % OriginalSnippetSize]; - ET.fillMemoryOperands(IB, ScratchSpaceReg, I * MemStep); + while (Instructions.size() < kMinNumDifferentAddresses) { + InstructionBuilder IB = Instructions[I % OriginalInstructionsSize]; + ET.fillMemoryOperands(IB, ScratchSpacePointerInReg, I * MemStep); ++I; - Snippet.push_back(std::move(IB)); + Instructions.push_back(std::move(IB)); } assert(I * MemStep < ScratchSpace::kSize && "not enough scratch space"); } -llvm::Expected<SnippetPrototype> -UopsBenchmarkRunner::generatePrototype(unsigned Opcode) const { +llvm::Expected<CodeTemplate> +UopsBenchmarkRunner::generateCodeTemplate(unsigned Opcode) const { const auto &InstrDesc = State.getInstrInfo().get(Opcode); if (auto E = isInfeasible(InstrDesc)) return std::move(E); const Instruction Instr(InstrDesc, RATC); const auto &ET = State.getExegesisTarget(); - SnippetPrototype Prototype; + CodeTemplate CT; const llvm::BitVector *ScratchSpaceAliasedRegs = nullptr; if (Instr.hasMemoryOperands()) { - Prototype.ScratchSpaceReg = + CT.ScratchSpacePointerInReg = ET.getScratchMemoryRegister(State.getTargetMachine().getTargetTriple()); - if (Prototype.ScratchSpaceReg == 0) + if (CT.ScratchSpacePointerInReg == 0) return llvm::make_error<BenchmarkFailure>( "Infeasible : target does not support memory instructions"); ScratchSpaceAliasedRegs = - &RATC.getRegister(Prototype.ScratchSpaceReg).aliasedBits(); - // If the instruction implicitly writes to ScratchSpaceReg , abort. + &RATC.getRegister(CT.ScratchSpacePointerInReg).aliasedBits(); + // If the instruction implicitly writes to ScratchSpacePointerInReg , abort. // FIXME: We could make a copy of the scratch register. for (const auto &Op : Instr.Operands) { if (Op.IsDef && Op.ImplicitReg && @@ -178,16 +178,16 @@ UopsBenchmarkRunner::generatePrototype(unsigned Opcode) const { const AliasingConfigurations SelfAliasing(Instr, Instr); InstructionBuilder IB(Instr); if (SelfAliasing.empty()) { - Prototype.Explanation = "instruction is parallel, repeating a random one."; - Prototype.Snippet.push_back(std::move(IB)); - instantiateMemoryOperands(Prototype.ScratchSpaceReg, Prototype.Snippet); - return std::move(Prototype); + CT.Info = "instruction is parallel, repeating a random one."; + CT.Instructions.push_back(std::move(IB)); + instantiateMemoryOperands(CT.ScratchSpacePointerInReg, CT.Instructions); + return std::move(CT); } if (SelfAliasing.hasImplicitAliasing()) { - Prototype.Explanation = "instruction is serial, repeating a random one."; - Prototype.Snippet.push_back(std::move(IB)); - instantiateMemoryOperands(Prototype.ScratchSpaceReg, Prototype.Snippet); - return std::move(Prototype); + CT.Info = "instruction is serial, repeating a random one."; + CT.Instructions.push_back(std::move(IB)); + instantiateMemoryOperands(CT.ScratchSpacePointerInReg, CT.Instructions); + return std::move(CT); } const auto TiedVariables = getTiedVariables(Instr); if (!TiedVariables.empty()) { @@ -200,17 +200,16 @@ UopsBenchmarkRunner::generatePrototype(unsigned Opcode) const { assert(!Var->TiedOperands.empty()); const Operand &Op = Instr.Operands[Var->TiedOperands.front()]; assert(Op.Tracker); - Prototype.Explanation = - "instruction has tied variables using static renaming."; + CT.Info = "instruction has tied variables using static renaming."; for (const llvm::MCPhysReg Reg : Op.Tracker->sourceBits().set_bits()) { if (ScratchSpaceAliasedRegs && ScratchSpaceAliasedRegs->test(Reg)) continue; // Do not use the scratch memory address register. InstructionBuilder TmpIB = IB; TmpIB.getValueFor(*Var) = llvm::MCOperand::createReg(Reg); - Prototype.Snippet.push_back(std::move(TmpIB)); + CT.Instructions.push_back(std::move(TmpIB)); } - instantiateMemoryOperands(Prototype.ScratchSpaceReg, Prototype.Snippet); - return std::move(Prototype); + instantiateMemoryOperands(CT.ScratchSpacePointerInReg, CT.Instructions); + return std::move(CT); } // No tied variables, we pick random values for defs. llvm::BitVector Defs(State.getRegInfo().getNumRegs()); @@ -242,11 +241,11 @@ UopsBenchmarkRunner::generatePrototype(unsigned Opcode) const { IB.getValueFor(Op) = llvm::MCOperand::createReg(RandomReg); } } - Prototype.Explanation = + CT.Info = "instruction has no tied variables picking Uses different from defs"; - Prototype.Snippet.push_back(std::move(IB)); - instantiateMemoryOperands(Prototype.ScratchSpaceReg, Prototype.Snippet); - return std::move(Prototype); + CT.Instructions.push_back(std::move(IB)); + instantiateMemoryOperands(CT.ScratchSpacePointerInReg, CT.Instructions); + return std::move(CT); } std::vector<BenchmarkMeasure> diff --git a/tools/llvm-exegesis/lib/Uops.h b/tools/llvm-exegesis/lib/Uops.h index 58c1d347d81..0236cd99182 100644 --- a/tools/llvm-exegesis/lib/Uops.h +++ b/tools/llvm-exegesis/lib/Uops.h @@ -25,8 +25,8 @@ public: : BenchmarkRunner(State, InstructionBenchmark::Uops) {} ~UopsBenchmarkRunner() override; - llvm::Expected<SnippetPrototype> - generatePrototype(unsigned Opcode) const override; + llvm::Expected<CodeTemplate> + generateCodeTemplate(unsigned Opcode) const override; static constexpr const size_t kMinNumDifferentAddresses = 6; diff --git a/tools/llvm-exegesis/lib/X86/Target.cpp b/tools/llvm-exegesis/lib/X86/Target.cpp index f958c8d99e7..511aa55919f 100644 --- a/tools/llvm-exegesis/lib/X86/Target.cpp +++ b/tools/llvm-exegesis/lib/X86/Target.cpp @@ -25,8 +25,8 @@ namespace { template <typename Impl> class X86BenchmarkRunner : public Impl { using Impl::Impl; - llvm::Expected<SnippetPrototype> - generatePrototype(unsigned Opcode) const override { + llvm::Expected<CodeTemplate> + generateCodeTemplate(unsigned Opcode) const override { // Test whether we can generate a snippet for this instruction. const auto &InstrInfo = this->State.getInstrInfo(); const auto OpcodeName = InstrInfo.getName(Opcode); @@ -54,7 +54,7 @@ template <typename Impl> class X86BenchmarkRunner : public Impl { // - `ST(0) = ST(0) + ST(i)` (TwoArgFP) // They are intrinsically serial and do not modify the state of the stack. // We generate the same code for latency and uops. - return this->generateSelfAliasingPrototype(Instr); + return this->generateSelfAliasingCodeTemplate(Instr); } case llvm::X86II::CompareFP: return Impl::handleCompareFP(Instr); @@ -67,7 +67,7 @@ template <typename Impl> class X86BenchmarkRunner : public Impl { } // Fallback to generic implementation. - return Impl::Base::generatePrototype(Opcode); + return Impl::Base::generateCodeTemplate(Opcode); } }; @@ -75,12 +75,10 @@ class X86LatencyImpl : public LatencyBenchmarkRunner { protected: using Base = LatencyBenchmarkRunner; using Base::Base; - llvm::Expected<SnippetPrototype> - handleCompareFP(const Instruction &Instr) const { + llvm::Expected<CodeTemplate> handleCompareFP(const Instruction &Instr) const { return llvm::make_error<BenchmarkFailure>("Unsupported x87 CompareFP"); } - llvm::Expected<SnippetPrototype> - handleCondMovFP(const Instruction &Instr) const { + llvm::Expected<CodeTemplate> handleCondMovFP(const Instruction &Instr) const { return llvm::make_error<BenchmarkFailure>("Unsupported x87 CondMovFP"); } }; @@ -91,14 +89,12 @@ protected: using Base::Base; // We can compute uops for any FP instruction that does not grow or shrink the // stack (either do not touch the stack or push as much as they pop). - llvm::Expected<SnippetPrototype> - handleCompareFP(const Instruction &Instr) const { - return generateUnconstrainedPrototype( + llvm::Expected<CodeTemplate> handleCompareFP(const Instruction &Instr) const { + return generateUnconstrainedCodeTemplate( Instr, "instruction does not grow/shrink the FP stack"); } - llvm::Expected<SnippetPrototype> - handleCondMovFP(const Instruction &Instr) const { - return generateUnconstrainedPrototype( + llvm::Expected<CodeTemplate> handleCondMovFP(const Instruction &Instr) const { + return generateUnconstrainedCodeTemplate( Instr, "instruction does not grow/shrink the FP stack"); } }; |