Index: tools/llvm-exegesis/lib/BenchmarkResult.h =================================================================== --- tools/llvm-exegesis/lib/BenchmarkResult.h +++ tools/llvm-exegesis/lib/BenchmarkResult.h @@ -58,11 +58,11 @@ std::string Info; // Read functions. - static InstructionBenchmark + static llvm::Expected readYamlOrDie(const BenchmarkResultContext &Context, llvm::StringRef Filename); - static std::vector + static llvm::Expected> readYamlsOrDie(const BenchmarkResultContext &Context, llvm::StringRef Filename); @@ -72,8 +72,8 @@ // Write functions, non-const because of YAML traits. void writeYamlTo(const BenchmarkResultContext &Context, llvm::raw_ostream &S); - void writeYamlOrDie(const BenchmarkResultContext &Context, - const llvm::StringRef Filename); + llvm::Error writeYamlOrDie(const BenchmarkResultContext &Context, + const llvm::StringRef Filename); }; //------------------------------------------------------------------------------ Index: tools/llvm-exegesis/lib/BenchmarkResult.cpp =================================================================== --- tools/llvm-exegesis/lib/BenchmarkResult.cpp +++ tools/llvm-exegesis/lib/BenchmarkResult.cpp @@ -149,26 +149,32 @@ } template -static ObjectOrList readYamlOrDieCommon(const BenchmarkResultContext &Context, - llvm::StringRef Filename) { - std::unique_ptr MemBuffer = llvm::cantFail( - llvm::errorOrToExpected(llvm::MemoryBuffer::getFile(Filename))); - // YAML IO requires a mutable pointer to Context but we guarantee to not - // modify it. - llvm::yaml::Input Yin(*MemBuffer, - const_cast(&Context)); - ObjectOrList Benchmark; - Yin >> Benchmark; - return Benchmark; +static llvm::Expected +readYamlOrDieCommon(const BenchmarkResultContext &Context, + llvm::StringRef Filename) { + if (auto ExpectedMemoryBuffer = + llvm::errorOrToExpected(llvm::MemoryBuffer::getFile(Filename))) { + std::unique_ptr MemoryBuffer = + std::move(ExpectedMemoryBuffer.get()); + // YAML IO requires a mutable pointer to Context but we guarantee to not + // modify it. + llvm::yaml::Input Yin(*MemoryBuffer, + const_cast(&Context)); + ObjectOrList Benchmark; + Yin >> Benchmark; + return Benchmark; + } else { + return ExpectedMemoryBuffer.takeError(); + } } -InstructionBenchmark +llvm::Expected InstructionBenchmark::readYamlOrDie(const BenchmarkResultContext &Context, llvm::StringRef Filename) { return readYamlOrDieCommon(Context, Filename); } -std::vector +llvm::Expected> InstructionBenchmark::readYamlsOrDie(const BenchmarkResultContext &Context, llvm::StringRef Filename) { return readYamlOrDieCommon>(Context, @@ -192,18 +198,21 @@ Yin >> *this; } -// FIXME: Change the API to let the caller handle errors. -void InstructionBenchmark::writeYamlOrDie(const BenchmarkResultContext &Context, - const llvm::StringRef Filename) { +llvm::Error +InstructionBenchmark::writeYamlOrDie(const BenchmarkResultContext &Context, + const llvm::StringRef Filename) { if (Filename == "-") { writeYamlTo(Context, llvm::outs()); } else { int ResultFD = 0; - llvm::cantFail(llvm::errorCodeToError( - openFileForWrite(Filename, ResultFD, llvm::sys::fs::F_Text))); + if (auto E = llvm::errorCodeToError( + openFileForWrite(Filename, ResultFD, llvm::sys::fs::F_Text))) { + return E; + } llvm::raw_fd_ostream Ostr(ResultFD, true /*shouldClose*/); writeYamlTo(Context, Ostr); } + return llvm::Error::success(); } void BenchmarkMeasureStats::push(const BenchmarkMeasure &BM) { Index: tools/llvm-exegesis/llvm-exegesis.cpp =================================================================== --- tools/llvm-exegesis/llvm-exegesis.cpp +++ tools/llvm-exegesis/llvm-exegesis.cpp @@ -45,7 +45,7 @@ llvm::cl::init("")); static llvm::cl::opt - BenchmarkFile("benchmarks-file", llvm::cl::desc(""), llvm::cl::init("-")); + BenchmarkFile("benchmarks-file", llvm::cl::desc(""), llvm::cl::init("")); enum class BenchmarkModeE { Latency, Uops, Analysis }; static llvm::cl::opt BenchmarkMode( @@ -79,6 +79,8 @@ namespace exegesis { +static llvm::ExitOnError ExitOnErr; + static unsigned GetOpcodeOrDie(const llvm::MCInstrInfo &MCInstrInfo) { if (OpcodeName.empty() && (OpcodeIndex == 0)) llvm::report_fatal_error( @@ -138,8 +140,13 @@ if (NumRepetitions == 0) llvm::report_fatal_error("--num-repetitions must be greater than zero"); - Runner->run(GetOpcodeOrDie(State.getInstrInfo()), Filter, NumRepetitions) - .writeYamlOrDie(getBenchmarkResultContext(State), BenchmarkFile); + // Write to standard output if file is not set. + if (BenchmarkFile.empty()) + BenchmarkFile = "-"; + + ExitOnErr( + Runner->run(GetOpcodeOrDie(State.getInstrInfo()), Filter, NumRepetitions) + .writeYamlOrDie(getBenchmarkResultContext(State), BenchmarkFile)); exegesis::pfm::pfmTerminate(); } @@ -157,21 +164,21 @@ std::error_code ErrorCode; llvm::raw_fd_ostream ClustersOS(OutputFilename, ErrorCode, llvm::sys::fs::F_RW); - if (ErrorCode) - llvm::report_fatal_error("cannot open out file: " + OutputFilename); - if (auto Err = Analyzer.run(ClustersOS)) - llvm::report_fatal_error(std::move(Err)); + ExitOnErr(llvm::errorCodeToError(ErrorCode)); + ExitOnErr(Analyzer.run(ClustersOS)); } static void analysisMain() { + if (BenchmarkFile.empty()) + llvm::report_fatal_error("--benchmarks-file must be set."); + llvm::InitializeNativeTarget(); llvm::InitializeNativeTargetAsmPrinter(); - // Read benchmarks. const LLVMState State; const std::vector Points = - InstructionBenchmark::readYamlsOrDie(getBenchmarkResultContext(State), - BenchmarkFile); + ExitOnErr(InstructionBenchmark::readYamlsOrDie( + getBenchmarkResultContext(State), BenchmarkFile)); llvm::outs() << "Parsed " << Points.size() << " benchmark points\n"; if (Points.empty()) { llvm::errs() << "no benchmarks to analyze\n"; Index: unittests/tools/llvm-exegesis/BenchmarkResultTest.cpp =================================================================== --- unittests/tools/llvm-exegesis/BenchmarkResultTest.cpp +++ unittests/tools/llvm-exegesis/BenchmarkResultTest.cpp @@ -38,6 +38,7 @@ static constexpr const char kInstrName[] = "Instruction5"; TEST(BenchmarkResultTest, WriteToAndReadFromDisk) { + llvm::ExitOnError ExitOnErr; BenchmarkResultContext Ctx; Ctx.addInstrEntry(kInstrId, kInstrName); @@ -60,11 +61,12 @@ EC = llvm::sys::fs::createUniqueDirectory("BenchmarkResultTestDir", Filename); ASSERT_FALSE(EC); llvm::sys::path::append(Filename, "data.yaml"); - ToDisk.writeYamlOrDie(Ctx, Filename); + ExitOnErr(ToDisk.writeYamlOrDie(Ctx, Filename)); { // One-element version. - const auto FromDisk = InstructionBenchmark::readYamlOrDie(Ctx, Filename); + const auto FromDisk = + ExitOnErr(InstructionBenchmark::readYamlOrDie(Ctx, Filename)); EXPECT_EQ(FromDisk.Key.OpcodeName, ToDisk.Key.OpcodeName); EXPECT_THAT(FromDisk.Key.Instructions, @@ -81,7 +83,7 @@ { // Vector version. const auto FromDiskVector = - InstructionBenchmark::readYamlsOrDie(Ctx, Filename); + ExitOnErr(InstructionBenchmark::readYamlsOrDie(Ctx, Filename)); ASSERT_EQ(FromDiskVector.size(), size_t{1}); const auto FromDisk = FromDiskVector[0]; EXPECT_EQ(FromDisk.Key.OpcodeName, ToDisk.Key.OpcodeName);