Index: llvm/trunk/tools/llvm-exegesis/lib/BenchmarkRunner.h =================================================================== --- llvm/trunk/tools/llvm-exegesis/lib/BenchmarkRunner.h +++ llvm/trunk/tools/llvm-exegesis/lib/BenchmarkRunner.h @@ -35,6 +35,9 @@ // The sequence of instructions that are to be repeated. std::vector Snippet; + + // Informations about how this configuration was built. + std::string Info; }; // Common code for all benchmark modes. @@ -56,8 +59,9 @@ virtual ~BenchmarkRunner(); - InstructionBenchmark run(unsigned Opcode, const InstructionFilter &Filter, - unsigned NumRepetitions); + llvm::Expected> + run(unsigned Opcode, const InstructionFilter &Filter, + unsigned NumRepetitions); protected: const LLVMState &State; @@ -65,11 +69,14 @@ const llvm::MCRegisterInfo &MCRegisterInfo; private: + InstructionBenchmark runOne(const BenchmarkConfiguration &Configuration, + unsigned Opcode, unsigned NumRepetitions) const; + virtual InstructionBenchmark::ModeE getMode() const = 0; - virtual llvm::Expected - createConfiguration(RegisterAliasingTrackerCache &RATC, unsigned Opcode, - llvm::raw_ostream &Debug) const = 0; + virtual llvm::Expected> + createConfigurations(RegisterAliasingTrackerCache &RATC, + unsigned Opcode) const = 0; virtual std::vector runMeasurements(const ExecutableFunction &EF, Index: llvm/trunk/tools/llvm-exegesis/lib/BenchmarkRunner.cpp =================================================================== --- llvm/trunk/tools/llvm-exegesis/lib/BenchmarkRunner.cpp +++ llvm/trunk/tools/llvm-exegesis/lib/BenchmarkRunner.cpp @@ -24,54 +24,57 @@ namespace exegesis { BenchmarkRunner::InstructionFilter::~InstructionFilter() = default; + BenchmarkRunner::BenchmarkRunner(const LLVMState &State) : State(State), MCInstrInfo(State.getInstrInfo()), MCRegisterInfo(State.getRegInfo()), RATC(MCRegisterInfo, getFunctionReservedRegs(*State.createTargetMachine())) {} + BenchmarkRunner::~BenchmarkRunner() = default; -InstructionBenchmark BenchmarkRunner::run(unsigned Opcode, - const InstructionFilter &Filter, - unsigned NumRepetitions) { - InstructionBenchmark InstrBenchmark; +llvm::Expected> +BenchmarkRunner::run(unsigned Opcode, const InstructionFilter &Filter, + unsigned NumRepetitions) { + // Ignore instructions that we cannot run. + if (State.getInstrInfo().get(Opcode).isPseudo()) + return llvm::make_error("Unsupported opcode: isPseudo", + llvm::inconvertibleErrorCode()); + + if (llvm::Error E = Filter.shouldRun(State, Opcode)) + return std::move(E); + llvm::Expected> ConfigurationOrError = + createConfigurations(RATC, Opcode); + + if (llvm::Error E = ConfigurationOrError.takeError()) + return std::move(E); + + std::vector InstrBenchmarks; + for (const BenchmarkConfiguration &Conf : ConfigurationOrError.get()) + InstrBenchmarks.push_back(runOne(Conf, Opcode, NumRepetitions)); + return InstrBenchmarks; +} + +InstructionBenchmark +BenchmarkRunner::runOne(const BenchmarkConfiguration &Configuration, + unsigned Opcode, unsigned NumRepetitions) const { + InstructionBenchmark InstrBenchmark; InstrBenchmark.Key.OpcodeName = State.getInstrInfo().getName(Opcode); InstrBenchmark.Mode = getMode(); InstrBenchmark.CpuName = State.getCpuName(); InstrBenchmark.LLVMTriple = State.getTriple(); InstrBenchmark.NumRepetitions = NumRepetitions; + InstrBenchmark.Info = Configuration.Info; - // Ignore instructions that we cannot run. - if (State.getInstrInfo().get(Opcode).isPseudo()) { - InstrBenchmark.Error = "Unsupported opcode: isPseudo"; - return InstrBenchmark; - } - if (llvm::Error E = Filter.shouldRun(State, Opcode)) { - InstrBenchmark.Error = llvm::toString(std::move(E)); - return InstrBenchmark; - } - llvm::raw_string_ostream InfoStream(InstrBenchmark.Info); - llvm::Expected ConfigurationOrError = - createConfiguration(RATC, Opcode, InfoStream); - if (llvm::Error E = ConfigurationOrError.takeError()) { - InstrBenchmark.Error = llvm::toString(std::move(E)); - return InstrBenchmark; - } - BenchmarkConfiguration &Configuration = ConfigurationOrError.get(); const std::vector &Snippet = Configuration.Snippet; if (Snippet.empty()) { InstrBenchmark.Error = "Empty snippet"; return InstrBenchmark; } - for (const auto &MCInst : Snippet) { + + for (const auto &MCInst : Snippet) InstrBenchmark.Key.Instructions.push_back(MCInst); - } - InfoStream << "Snippet:\n"; - for (const auto &MCInst : Snippet) { - DumpMCInst(MCRegisterInfo, MCInstrInfo, MCInst, InfoStream); - InfoStream << "\n"; - } std::vector Code; for (int I = 0; I < InstrBenchmark.NumRepetitions; ++I) Index: llvm/trunk/tools/llvm-exegesis/lib/Latency.h =================================================================== --- llvm/trunk/tools/llvm-exegesis/lib/Latency.h +++ llvm/trunk/tools/llvm-exegesis/lib/Latency.h @@ -27,9 +27,9 @@ private: InstructionBenchmark::ModeE getMode() const override; - llvm::Expected - createConfiguration(RegisterAliasingTrackerCache &RATC, unsigned OpcodeIndex, - llvm::raw_ostream &Info) const override; + llvm::Expected> + createConfigurations(RegisterAliasingTrackerCache &RATC, + unsigned OpcodeIndex) const override; std::vector runMeasurements(const ExecutableFunction &EF, Index: llvm/trunk/tools/llvm-exegesis/lib/Latency.cpp =================================================================== --- llvm/trunk/tools/llvm-exegesis/lib/Latency.cpp +++ llvm/trunk/tools/llvm-exegesis/lib/Latency.cpp @@ -45,40 +45,35 @@ return false; } -static llvm::Error makeError(llvm::Twine Msg) { - return llvm::make_error(Msg, - llvm::inconvertibleErrorCode()); -} - LatencyBenchmarkRunner::~LatencyBenchmarkRunner() = default; InstructionBenchmark::ModeE LatencyBenchmarkRunner::getMode() const { return InstructionBenchmark::Latency; } -llvm::Expected -LatencyBenchmarkRunner::createConfiguration(RegisterAliasingTrackerCache &RATC, - unsigned Opcode, - llvm::raw_ostream &Info) const { - BenchmarkConfiguration Configuration; - std::vector &Snippet = Configuration.Snippet; +llvm::Expected> +LatencyBenchmarkRunner::createConfigurations(RegisterAliasingTrackerCache &RATC, + unsigned Opcode) const { const llvm::MCInstrDesc &MCInstrDesc = MCInstrInfo.get(Opcode); const Instruction ThisInstruction(MCInstrDesc, RATC); std::string Error; if (IsInfeasible(ThisInstruction, Error)) - return makeError(llvm::Twine("Infeasible : ").concat(Error)); + return llvm::make_error( + llvm::Twine("Infeasible : ").concat(Error), + llvm::inconvertibleErrorCode()); + BenchmarkConfiguration Conf; const AliasingConfigurations SelfAliasing(ThisInstruction, ThisInstruction); if (!SelfAliasing.empty()) { if (!SelfAliasing.hasImplicitAliasing()) { - Info << "explicit self cycles, selecting one aliasing configuration.\n"; + Conf.Info = "explicit self cycles, selecting one aliasing Conf."; setRandomAliasing(SelfAliasing); } else { - Info << "implicit Self cycles, picking random values.\n"; + Conf.Info = "implicit Self cycles, picking random values."; } - Snippet.push_back(randomizeUnsetVariablesAndBuild(ThisInstruction)); - return Configuration; + Conf.Snippet = {randomizeUnsetVariablesAndBuild(ThisInstruction)}; + return std::vector{Conf}; } // Let's try to create a dependency through another opcode. @@ -99,15 +94,18 @@ continue; setRandomAliasing(Forward); setRandomAliasing(Back); - Info << "creating cycle through " << MCInstrInfo.getName(OtherOpcode) - << ".\n"; - Snippet.push_back(randomizeUnsetVariablesAndBuild(ThisInstruction)); - Snippet.push_back(randomizeUnsetVariablesAndBuild(OtherInstruction)); - return Configuration; + Conf.Info = llvm::Twine("creating cycle through ") + .concat(MCInstrInfo.getName(OtherOpcode)) + .concat(".") + .str(); + Conf.Snippet.push_back(randomizeUnsetVariablesAndBuild(ThisInstruction)); + Conf.Snippet.push_back(randomizeUnsetVariablesAndBuild(OtherInstruction)); + return std::vector{Conf}; } - return makeError( - "Infeasible : Didn't find any scheme to make the instruction serial\n"); + return llvm::make_error( + "Infeasible : Didn't find any scheme to make the instruction serial", + llvm::inconvertibleErrorCode()); } std::vector Index: llvm/trunk/tools/llvm-exegesis/lib/Uops.h =================================================================== --- llvm/trunk/tools/llvm-exegesis/lib/Uops.h +++ llvm/trunk/tools/llvm-exegesis/lib/Uops.h @@ -27,9 +27,9 @@ private: InstructionBenchmark::ModeE getMode() const override; - llvm::Expected - createConfiguration(RegisterAliasingTrackerCache &RATC, unsigned Opcode, - llvm::raw_ostream &Info) const override; + llvm::Expected> + createConfigurations(RegisterAliasingTrackerCache &RATC, + unsigned Opcode) const override; std::vector runMeasurements(const ExecutableFunction &EF, Index: llvm/trunk/tools/llvm-exegesis/lib/Uops.cpp =================================================================== --- llvm/trunk/tools/llvm-exegesis/lib/Uops.cpp +++ llvm/trunk/tools/llvm-exegesis/lib/Uops.cpp @@ -134,51 +134,43 @@ a.reset(I); } -static llvm::Error makeError(llvm::Twine Msg) { - return llvm::make_error(Msg, - llvm::inconvertibleErrorCode()); -} - UopsBenchmarkRunner::~UopsBenchmarkRunner() = default; InstructionBenchmark::ModeE UopsBenchmarkRunner::getMode() const { return InstructionBenchmark::Uops; } -llvm::Expected -UopsBenchmarkRunner::createConfiguration(RegisterAliasingTrackerCache &RATC, - unsigned Opcode, - llvm::raw_ostream &Info) const { - BenchmarkConfiguration Configuration; - std::vector &Snippet = Configuration.Snippet; +llvm::Expected> +UopsBenchmarkRunner::createConfigurations(RegisterAliasingTrackerCache &RATC, + unsigned Opcode) const { const llvm::MCInstrDesc &MCInstrDesc = MCInstrInfo.get(Opcode); const Instruction Instruction(MCInstrDesc, RATC); std::string Error; - if (isInfeasible(Instruction, Error)) { - llvm::report_fatal_error(llvm::Twine("Infeasible : ").concat(Error)); - } + if (isInfeasible(Instruction, Error)) + return llvm::make_error( + llvm::Twine("Infeasible : ").concat(Error), + llvm::inconvertibleErrorCode()); + BenchmarkConfiguration Conf; const AliasingConfigurations SelfAliasing(Instruction, Instruction); if (SelfAliasing.empty()) { - Info << "instruction is parallel, repeating a random one.\n"; - Snippet.push_back(randomizeUnsetVariablesAndBuild(Instruction)); - return Configuration; + Conf.Info = "instruction is parallel, repeating a random one."; + Conf.Snippet = {randomizeUnsetVariablesAndBuild(Instruction)}; + return std::vector{Conf}; } if (SelfAliasing.hasImplicitAliasing()) { - Info << "instruction is serial, repeating a random one.\n"; - Snippet.push_back(randomizeUnsetVariablesAndBuild(Instruction)); - return Configuration; + Conf.Info = "instruction is serial, repeating a random one."; + Conf.Snippet = {randomizeUnsetVariablesAndBuild(Instruction)}; + return std::vector{Conf}; } const auto TiedVariables = getTiedVariables(Instruction); if (!TiedVariables.empty()) { - if (TiedVariables.size() > 1) { - Info << "Not yet implemented, don't know how to handle several tied " - "variables\n"; - return makeError("Infeasible : don't know how to handle several tied " - "variables"); - } - Info << "instruction has tied variables using static renaming.\n"; + if (TiedVariables.size() > 1) + return llvm::make_error( + "Infeasible : don't know how to handle several tied variables", + llvm::inconvertibleErrorCode()); + Conf.Info = "instruction has tied variables using static renaming."; Variable *Var = TiedVariables.front(); assert(Var); assert(!Var->TiedOperands.empty()); @@ -187,9 +179,9 @@ for (const llvm::MCPhysReg Reg : Operand.Tracker->sourceBits().set_bits()) { clearVariableAssignments(Instruction); Var->AssignedValue = llvm::MCOperand::createReg(Reg); - Snippet.push_back(randomizeUnsetVariablesAndBuild(Instruction)); + Conf.Snippet.push_back(randomizeUnsetVariablesAndBuild(Instruction)); } - return Configuration; + return std::vector{Conf}; } // No tied variables, we pick random values for defs. llvm::BitVector Defs(MCRegisterInfo.getNumRegs()); @@ -217,10 +209,10 @@ Op.Var->AssignedValue = llvm::MCOperand::createReg(RandomReg); } } - Info - << "instruction has no tied variables picking Uses different from defs\n"; - Snippet.push_back(randomizeUnsetVariablesAndBuild(Instruction)); - return Configuration; + Conf.Info = + "instruction has no tied variables picking Uses different from defs"; + Conf.Snippet = {randomizeUnsetVariablesAndBuild(Instruction)}; + return std::vector{Conf}; } std::vector Index: llvm/trunk/tools/llvm-exegesis/llvm-exegesis.cpp =================================================================== --- llvm/trunk/tools/llvm-exegesis/llvm-exegesis.cpp +++ llvm/trunk/tools/llvm-exegesis/llvm-exegesis.cpp @@ -144,9 +144,12 @@ if (BenchmarkFile.empty()) BenchmarkFile = "-"; - ExitOnErr( - Runner->run(GetOpcodeOrDie(State.getInstrInfo()), Filter, NumRepetitions) - .writeYaml(getBenchmarkResultContext(State), BenchmarkFile)); + const BenchmarkResultContext Context = getBenchmarkResultContext(State); + std::vector Results = ExitOnErr(Runner->run( + GetOpcodeOrDie(State.getInstrInfo()), Filter, NumRepetitions)); + for (InstructionBenchmark &Result : Results) + Result.writeYaml(Context, BenchmarkFile); + exegesis::pfm::pfmTerminate(); }