diff options
Diffstat (limited to 'llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp')
-rw-r--r-- | llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp | 67 |
1 files changed, 58 insertions, 9 deletions
diff --git a/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp b/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp index 063d72e2911..94b24732f6f 100644 --- a/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp +++ b/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp @@ -78,10 +78,11 @@ BenchmarkRunner::runOne(const BenchmarkConfiguration &Configuration, // Repeat the snippet until there are at least NumInstructions in the // resulting code. The snippet is always repeated at least once. - const auto GenerateInstructions = [&Snippet](const int MinInstructions) { - std::vector<llvm::MCInst> Code = Snippet; + const auto GenerateInstructions = [&Configuration]( + const int MinInstructions) { + std::vector<llvm::MCInst> Code = Configuration.Snippet; for (int I = 0; I < MinInstructions; ++I) - Code.push_back(Snippet[I % Snippet.size()]); + Code.push_back(Configuration.Snippet[I % Configuration.Snippet.size()]); return Code; }; @@ -91,7 +92,8 @@ BenchmarkRunner::runOne(const BenchmarkConfiguration &Configuration, constexpr const int kMinInstructionsForSnippet = 16; { auto ObjectFilePath = - writeObjectFile(GenerateInstructions(kMinInstructionsForSnippet)); + writeObjectFile(Configuration.SnippetSetup, + GenerateInstructions(kMinInstructionsForSnippet)); if (llvm::Error E = ObjectFilePath.takeError()) { InstrBenchmark.Error = llvm::toString(std::move(E)); return InstrBenchmark; @@ -105,7 +107,8 @@ BenchmarkRunner::runOne(const BenchmarkConfiguration &Configuration, // Assemble NumRepetitions instructions repetitions of the snippet for // measurements. auto ObjectFilePath = - writeObjectFile(GenerateInstructions(InstrBenchmark.NumRepetitions)); + writeObjectFile(Configuration.SnippetSetup, + GenerateInstructions(InstrBenchmark.NumRepetitions)); if (llvm::Error E = ObjectFilePath.takeError()) { InstrBenchmark.Error = llvm::toString(std::move(E)); return InstrBenchmark; @@ -126,22 +129,68 @@ BenchmarkRunner::generateConfigurations(unsigned Opcode) const { // TODO: Generate as many configurations as needed here. BenchmarkConfiguration Configuration; Configuration.Info = Prototype.Explanation; - for (InstructionInstance &II : Prototype.Snippet) - Configuration.Snippet.push_back(II.randomizeUnsetVariablesAndBuild()); + for (InstructionInstance &II : Prototype.Snippet) { + II.randomizeUnsetVariables(); + Configuration.Snippet.push_back(II.build()); + } + Configuration.SnippetSetup.RegsToDef = computeRegsToDef(Prototype.Snippet); return std::vector<BenchmarkConfiguration>{Configuration}; } else return E.takeError(); } +std::vector<unsigned> BenchmarkRunner::computeRegsToDef( + const std::vector<InstructionInstance> &Snippet) const { + // Collect all register uses and create an assignment for each of them. + // 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 InstructionInstance &II : Snippet) { + // Returns the register that this Operand sets or uses, or 0 if this is not + // a register. + const auto GetOpReg = [&II](const Operand &Op) -> unsigned { + if (Op.ImplicitReg) { + return *Op.ImplicitReg; + } else if (Op.IsExplicit && II.getValueFor(Op).isReg()) { + return II.getValueFor(Op).getReg(); + } + return 0; + }; + // Collect used registers that have never been def'ed. + for (const Operand &Op : II.Instr.Operands) { + if (!Op.IsDef) { + const unsigned Reg = GetOpReg(Op); + if (Reg > 0 && !DefinedRegs.test(Reg)) { + RegsToDef.push_back(Reg); + DefinedRegs.set(Reg); + } + } + } + // Mark defs as having been def'ed. + for (const Operand &Op : II.Instr.Operands) { + if (Op.IsDef) { + const unsigned Reg = GetOpReg(Op); + if (Reg > 0) { + DefinedRegs.set(Reg); + } + } + } + } + return RegsToDef; +} + llvm::Expected<std::string> -BenchmarkRunner::writeObjectFile(llvm::ArrayRef<llvm::MCInst> Code) const { +BenchmarkRunner::writeObjectFile(const BenchmarkConfiguration::Setup &Setup, + llvm::ArrayRef<llvm::MCInst> Code) const { int ResultFD = 0; llvm::SmallString<256> ResultPath; if (llvm::Error E = llvm::errorCodeToError(llvm::sys::fs::createTemporaryFile( "snippet", "o", ResultFD, ResultPath))) return std::move(E); llvm::raw_fd_ostream OFS(ResultFD, true /*ShouldClose*/); - assembleToStream(State.createTargetMachine(), Code, OFS); + assembleToStream(State.getExegesisTarget(), State.createTargetMachine(), + Setup.RegsToDef, Code, OFS); return ResultPath.str(); } |