Index: llvm/trunk/tools/llvm-exegesis/lib/BenchmarkResult.h =================================================================== --- llvm/trunk/tools/llvm-exegesis/lib/BenchmarkResult.h +++ llvm/trunk/tools/llvm-exegesis/lib/BenchmarkResult.h @@ -58,13 +58,11 @@ std::string Info; // Read functions. - static InstructionBenchmark - readYamlOrDie(const BenchmarkResultContext &Context, - llvm::StringRef Filename); - - static std::vector - readYamlsOrDie(const BenchmarkResultContext &Context, - llvm::StringRef Filename); + static llvm::Expected + readYaml(const BenchmarkResultContext &Context, llvm::StringRef Filename); + + static llvm::Expected> + readYamls(const BenchmarkResultContext &Context, llvm::StringRef Filename); void readYamlFrom(const BenchmarkResultContext &Context, llvm::StringRef InputContent); @@ -72,8 +70,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 writeYaml(const BenchmarkResultContext &Context, + const llvm::StringRef Filename); }; //------------------------------------------------------------------------------ Index: llvm/trunk/tools/llvm-exegesis/lib/BenchmarkResult.cpp =================================================================== --- llvm/trunk/tools/llvm-exegesis/lib/BenchmarkResult.cpp +++ llvm/trunk/tools/llvm-exegesis/lib/BenchmarkResult.cpp @@ -210,27 +210,32 @@ } template -static ObjectOrList readYamlOrDieCommon(const BenchmarkResultContext &Context, - llvm::StringRef Filename) { - std::unique_ptr MemBuffer = llvm::cantFail( - llvm::errorOrToExpected(llvm::MemoryBuffer::getFile(Filename))); - llvm::yaml::Input Yin(*MemBuffer, getUntypedContext(Context)); - ObjectOrList Benchmark; - Yin >> Benchmark; - return Benchmark; -} - -InstructionBenchmark -InstructionBenchmark::readYamlOrDie(const BenchmarkResultContext &Context, - llvm::StringRef Filename) { - return readYamlOrDieCommon(Context, Filename); -} - -std::vector -InstructionBenchmark::readYamlsOrDie(const BenchmarkResultContext &Context, - llvm::StringRef Filename) { - return readYamlOrDieCommon>(Context, - Filename); +static llvm::Expected +readYamlCommon(const BenchmarkResultContext &Context, + llvm::StringRef Filename) { + if (auto ExpectedMemoryBuffer = + llvm::errorOrToExpected(llvm::MemoryBuffer::getFile(Filename))) { + std::unique_ptr MemoryBuffer = + std::move(ExpectedMemoryBuffer.get()); + llvm::yaml::Input Yin(*MemoryBuffer, getUntypedContext(Context)); + ObjectOrList Benchmark; + Yin >> Benchmark; + return Benchmark; + } else { + return ExpectedMemoryBuffer.takeError(); + } +} + +llvm::Expected +InstructionBenchmark::readYaml(const BenchmarkResultContext &Context, + llvm::StringRef Filename) { + return readYamlCommon(Context, Filename); +} + +llvm::Expected> +InstructionBenchmark::readYamls(const BenchmarkResultContext &Context, + llvm::StringRef Filename) { + return readYamlCommon>(Context, Filename); } void InstructionBenchmark::writeYamlTo(const BenchmarkResultContext &Context, @@ -245,18 +250,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::writeYaml(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: llvm/trunk/tools/llvm-exegesis/llvm-exegesis.cpp =================================================================== --- llvm/trunk/tools/llvm-exegesis/llvm-exegesis.cpp +++ llvm/trunk/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) + .writeYaml(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::readYamls( + getBenchmarkResultContext(State), BenchmarkFile)); llvm::outs() << "Parsed " << Points.size() << " benchmark points\n"; if (Points.empty()) { llvm::errs() << "no benchmarks to analyze\n"; Index: llvm/trunk/unittests/tools/llvm-exegesis/BenchmarkResultTest.cpp =================================================================== --- llvm/trunk/unittests/tools/llvm-exegesis/BenchmarkResultTest.cpp +++ llvm/trunk/unittests/tools/llvm-exegesis/BenchmarkResultTest.cpp @@ -55,6 +55,7 @@ static constexpr const char kReg2Name[] = "Reg2"; TEST(BenchmarkResultTest, WriteToAndReadFromDisk) { + llvm::ExitOnError ExitOnErr; BenchmarkResultContext Ctx; Ctx.addInstrEntry(kInstrId, kInstrName); Ctx.addRegEntry(kReg1Id, kReg1Name); @@ -83,11 +84,12 @@ EC = llvm::sys::fs::createUniqueDirectory("BenchmarkResultTestDir", Filename); ASSERT_FALSE(EC); llvm::sys::path::append(Filename, "data.yaml"); - ToDisk.writeYamlOrDie(Ctx, Filename); + ExitOnErr(ToDisk.writeYaml(Ctx, Filename)); { // One-element version. - const auto FromDisk = InstructionBenchmark::readYamlOrDie(Ctx, Filename); + const auto FromDisk = + ExitOnErr(InstructionBenchmark::readYaml(Ctx, Filename)); EXPECT_EQ(FromDisk.Key.OpcodeName, ToDisk.Key.OpcodeName); EXPECT_THAT(FromDisk.Key.Instructions, @@ -104,7 +106,7 @@ { // Vector version. const auto FromDiskVector = - InstructionBenchmark::readYamlsOrDie(Ctx, Filename); + ExitOnErr(InstructionBenchmark::readYamls(Ctx, Filename)); ASSERT_EQ(FromDiskVector.size(), size_t{1}); const auto FromDisk = FromDiskVector[0]; EXPECT_EQ(FromDisk.Key.OpcodeName, ToDisk.Key.OpcodeName);