forked from OSchip/llvm-project
[llvm-exegesis] Improve error reporting.
Summary: BenchmarkResult IO functions now return an Error or Expected so caller can deal take proper action. Reviewers: courbet Subscribers: tschuett, llvm-commits Differential Revision: https://reviews.llvm.org/D47868 llvm-svn: 334167
This commit is contained in:
parent
30c5e4ad35
commit
8c91d4cb04
|
@ -210,27 +210,32 @@ unsigned BenchmarkResultContext::getInstrOpcode(llvm::StringRef Name) const {
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename ObjectOrList>
|
template <typename ObjectOrList>
|
||||||
static ObjectOrList readYamlOrDieCommon(const BenchmarkResultContext &Context,
|
static llvm::Expected<ObjectOrList>
|
||||||
llvm::StringRef Filename) {
|
readYamlCommon(const BenchmarkResultContext &Context,
|
||||||
std::unique_ptr<llvm::MemoryBuffer> MemBuffer = llvm::cantFail(
|
llvm::StringRef Filename) {
|
||||||
llvm::errorOrToExpected(llvm::MemoryBuffer::getFile(Filename)));
|
if (auto ExpectedMemoryBuffer =
|
||||||
llvm::yaml::Input Yin(*MemBuffer, getUntypedContext(Context));
|
llvm::errorOrToExpected(llvm::MemoryBuffer::getFile(Filename))) {
|
||||||
ObjectOrList Benchmark;
|
std::unique_ptr<llvm::MemoryBuffer> MemoryBuffer =
|
||||||
Yin >> Benchmark;
|
std::move(ExpectedMemoryBuffer.get());
|
||||||
return Benchmark;
|
llvm::yaml::Input Yin(*MemoryBuffer, getUntypedContext(Context));
|
||||||
|
ObjectOrList Benchmark;
|
||||||
|
Yin >> Benchmark;
|
||||||
|
return Benchmark;
|
||||||
|
} else {
|
||||||
|
return ExpectedMemoryBuffer.takeError();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
InstructionBenchmark
|
llvm::Expected<InstructionBenchmark>
|
||||||
InstructionBenchmark::readYamlOrDie(const BenchmarkResultContext &Context,
|
InstructionBenchmark::readYaml(const BenchmarkResultContext &Context,
|
||||||
llvm::StringRef Filename) {
|
llvm::StringRef Filename) {
|
||||||
return readYamlOrDieCommon<InstructionBenchmark>(Context, Filename);
|
return readYamlCommon<InstructionBenchmark>(Context, Filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<InstructionBenchmark>
|
llvm::Expected<std::vector<InstructionBenchmark>>
|
||||||
InstructionBenchmark::readYamlsOrDie(const BenchmarkResultContext &Context,
|
InstructionBenchmark::readYamls(const BenchmarkResultContext &Context,
|
||||||
llvm::StringRef Filename) {
|
llvm::StringRef Filename) {
|
||||||
return readYamlOrDieCommon<std::vector<InstructionBenchmark>>(Context,
|
return readYamlCommon<std::vector<InstructionBenchmark>>(Context, Filename);
|
||||||
Filename);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void InstructionBenchmark::writeYamlTo(const BenchmarkResultContext &Context,
|
void InstructionBenchmark::writeYamlTo(const BenchmarkResultContext &Context,
|
||||||
|
@ -245,18 +250,21 @@ void InstructionBenchmark::readYamlFrom(const BenchmarkResultContext &Context,
|
||||||
Yin >> *this;
|
Yin >> *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: Change the API to let the caller handle errors.
|
llvm::Error
|
||||||
void InstructionBenchmark::writeYamlOrDie(const BenchmarkResultContext &Context,
|
InstructionBenchmark::writeYaml(const BenchmarkResultContext &Context,
|
||||||
const llvm::StringRef Filename) {
|
const llvm::StringRef Filename) {
|
||||||
if (Filename == "-") {
|
if (Filename == "-") {
|
||||||
writeYamlTo(Context, llvm::outs());
|
writeYamlTo(Context, llvm::outs());
|
||||||
} else {
|
} else {
|
||||||
int ResultFD = 0;
|
int ResultFD = 0;
|
||||||
llvm::cantFail(llvm::errorCodeToError(
|
if (auto E = llvm::errorCodeToError(
|
||||||
openFileForWrite(Filename, ResultFD, llvm::sys::fs::F_Text)));
|
openFileForWrite(Filename, ResultFD, llvm::sys::fs::F_Text))) {
|
||||||
|
return E;
|
||||||
|
}
|
||||||
llvm::raw_fd_ostream Ostr(ResultFD, true /*shouldClose*/);
|
llvm::raw_fd_ostream Ostr(ResultFD, true /*shouldClose*/);
|
||||||
writeYamlTo(Context, Ostr);
|
writeYamlTo(Context, Ostr);
|
||||||
}
|
}
|
||||||
|
return llvm::Error::success();
|
||||||
}
|
}
|
||||||
|
|
||||||
void BenchmarkMeasureStats::push(const BenchmarkMeasure &BM) {
|
void BenchmarkMeasureStats::push(const BenchmarkMeasure &BM) {
|
||||||
|
|
|
@ -58,13 +58,11 @@ struct InstructionBenchmark {
|
||||||
std::string Info;
|
std::string Info;
|
||||||
|
|
||||||
// Read functions.
|
// Read functions.
|
||||||
static InstructionBenchmark
|
static llvm::Expected<InstructionBenchmark>
|
||||||
readYamlOrDie(const BenchmarkResultContext &Context,
|
readYaml(const BenchmarkResultContext &Context, llvm::StringRef Filename);
|
||||||
llvm::StringRef Filename);
|
|
||||||
|
|
||||||
static std::vector<InstructionBenchmark>
|
static llvm::Expected<std::vector<InstructionBenchmark>>
|
||||||
readYamlsOrDie(const BenchmarkResultContext &Context,
|
readYamls(const BenchmarkResultContext &Context, llvm::StringRef Filename);
|
||||||
llvm::StringRef Filename);
|
|
||||||
|
|
||||||
void readYamlFrom(const BenchmarkResultContext &Context,
|
void readYamlFrom(const BenchmarkResultContext &Context,
|
||||||
llvm::StringRef InputContent);
|
llvm::StringRef InputContent);
|
||||||
|
@ -72,8 +70,8 @@ struct InstructionBenchmark {
|
||||||
// Write functions, non-const because of YAML traits.
|
// Write functions, non-const because of YAML traits.
|
||||||
void writeYamlTo(const BenchmarkResultContext &Context, llvm::raw_ostream &S);
|
void writeYamlTo(const BenchmarkResultContext &Context, llvm::raw_ostream &S);
|
||||||
|
|
||||||
void writeYamlOrDie(const BenchmarkResultContext &Context,
|
llvm::Error writeYaml(const BenchmarkResultContext &Context,
|
||||||
const llvm::StringRef Filename);
|
const llvm::StringRef Filename);
|
||||||
};
|
};
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
|
@ -45,7 +45,7 @@ static llvm::cl::opt<std::string>
|
||||||
llvm::cl::init(""));
|
llvm::cl::init(""));
|
||||||
|
|
||||||
static llvm::cl::opt<std::string>
|
static llvm::cl::opt<std::string>
|
||||||
BenchmarkFile("benchmarks-file", llvm::cl::desc(""), llvm::cl::init("-"));
|
BenchmarkFile("benchmarks-file", llvm::cl::desc(""), llvm::cl::init(""));
|
||||||
|
|
||||||
enum class BenchmarkModeE { Latency, Uops, Analysis };
|
enum class BenchmarkModeE { Latency, Uops, Analysis };
|
||||||
static llvm::cl::opt<BenchmarkModeE> BenchmarkMode(
|
static llvm::cl::opt<BenchmarkModeE> BenchmarkMode(
|
||||||
|
@ -79,6 +79,8 @@ static llvm::cl::opt<std::string>
|
||||||
|
|
||||||
namespace exegesis {
|
namespace exegesis {
|
||||||
|
|
||||||
|
static llvm::ExitOnError ExitOnErr;
|
||||||
|
|
||||||
static unsigned GetOpcodeOrDie(const llvm::MCInstrInfo &MCInstrInfo) {
|
static unsigned GetOpcodeOrDie(const llvm::MCInstrInfo &MCInstrInfo) {
|
||||||
if (OpcodeName.empty() && (OpcodeIndex == 0))
|
if (OpcodeName.empty() && (OpcodeIndex == 0))
|
||||||
llvm::report_fatal_error(
|
llvm::report_fatal_error(
|
||||||
|
@ -138,8 +140,13 @@ void benchmarkMain() {
|
||||||
if (NumRepetitions == 0)
|
if (NumRepetitions == 0)
|
||||||
llvm::report_fatal_error("--num-repetitions must be greater than zero");
|
llvm::report_fatal_error("--num-repetitions must be greater than zero");
|
||||||
|
|
||||||
Runner->run(GetOpcodeOrDie(State.getInstrInfo()), Filter, NumRepetitions)
|
// Write to standard output if file is not set.
|
||||||
.writeYamlOrDie(getBenchmarkResultContext(State), BenchmarkFile);
|
if (BenchmarkFile.empty())
|
||||||
|
BenchmarkFile = "-";
|
||||||
|
|
||||||
|
ExitOnErr(
|
||||||
|
Runner->run(GetOpcodeOrDie(State.getInstrInfo()), Filter, NumRepetitions)
|
||||||
|
.writeYaml(getBenchmarkResultContext(State), BenchmarkFile));
|
||||||
exegesis::pfm::pfmTerminate();
|
exegesis::pfm::pfmTerminate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -157,21 +164,21 @@ static void maybeRunAnalysis(const Analysis &Analyzer, const std::string &Name,
|
||||||
std::error_code ErrorCode;
|
std::error_code ErrorCode;
|
||||||
llvm::raw_fd_ostream ClustersOS(OutputFilename, ErrorCode,
|
llvm::raw_fd_ostream ClustersOS(OutputFilename, ErrorCode,
|
||||||
llvm::sys::fs::F_RW);
|
llvm::sys::fs::F_RW);
|
||||||
if (ErrorCode)
|
ExitOnErr(llvm::errorCodeToError(ErrorCode));
|
||||||
llvm::report_fatal_error("cannot open out file: " + OutputFilename);
|
ExitOnErr(Analyzer.run<Pass>(ClustersOS));
|
||||||
if (auto Err = Analyzer.run<Pass>(ClustersOS))
|
|
||||||
llvm::report_fatal_error(std::move(Err));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void analysisMain() {
|
static void analysisMain() {
|
||||||
|
if (BenchmarkFile.empty())
|
||||||
|
llvm::report_fatal_error("--benchmarks-file must be set.");
|
||||||
|
|
||||||
llvm::InitializeNativeTarget();
|
llvm::InitializeNativeTarget();
|
||||||
llvm::InitializeNativeTargetAsmPrinter();
|
llvm::InitializeNativeTargetAsmPrinter();
|
||||||
|
|
||||||
// Read benchmarks.
|
// Read benchmarks.
|
||||||
const LLVMState State;
|
const LLVMState State;
|
||||||
const std::vector<InstructionBenchmark> Points =
|
const std::vector<InstructionBenchmark> Points =
|
||||||
InstructionBenchmark::readYamlsOrDie(getBenchmarkResultContext(State),
|
ExitOnErr(InstructionBenchmark::readYamls(
|
||||||
BenchmarkFile);
|
getBenchmarkResultContext(State), BenchmarkFile));
|
||||||
llvm::outs() << "Parsed " << Points.size() << " benchmark points\n";
|
llvm::outs() << "Parsed " << Points.size() << " benchmark points\n";
|
||||||
if (Points.empty()) {
|
if (Points.empty()) {
|
||||||
llvm::errs() << "no benchmarks to analyze\n";
|
llvm::errs() << "no benchmarks to analyze\n";
|
||||||
|
|
|
@ -55,6 +55,7 @@ static constexpr const unsigned kReg2Id = 2;
|
||||||
static constexpr const char kReg2Name[] = "Reg2";
|
static constexpr const char kReg2Name[] = "Reg2";
|
||||||
|
|
||||||
TEST(BenchmarkResultTest, WriteToAndReadFromDisk) {
|
TEST(BenchmarkResultTest, WriteToAndReadFromDisk) {
|
||||||
|
llvm::ExitOnError ExitOnErr;
|
||||||
BenchmarkResultContext Ctx;
|
BenchmarkResultContext Ctx;
|
||||||
Ctx.addInstrEntry(kInstrId, kInstrName);
|
Ctx.addInstrEntry(kInstrId, kInstrName);
|
||||||
Ctx.addRegEntry(kReg1Id, kReg1Name);
|
Ctx.addRegEntry(kReg1Id, kReg1Name);
|
||||||
|
@ -83,11 +84,12 @@ TEST(BenchmarkResultTest, WriteToAndReadFromDisk) {
|
||||||
EC = llvm::sys::fs::createUniqueDirectory("BenchmarkResultTestDir", Filename);
|
EC = llvm::sys::fs::createUniqueDirectory("BenchmarkResultTestDir", Filename);
|
||||||
ASSERT_FALSE(EC);
|
ASSERT_FALSE(EC);
|
||||||
llvm::sys::path::append(Filename, "data.yaml");
|
llvm::sys::path::append(Filename, "data.yaml");
|
||||||
ToDisk.writeYamlOrDie(Ctx, Filename);
|
ExitOnErr(ToDisk.writeYaml(Ctx, Filename));
|
||||||
|
|
||||||
{
|
{
|
||||||
// One-element version.
|
// 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_EQ(FromDisk.Key.OpcodeName, ToDisk.Key.OpcodeName);
|
||||||
EXPECT_THAT(FromDisk.Key.Instructions,
|
EXPECT_THAT(FromDisk.Key.Instructions,
|
||||||
|
@ -104,7 +106,7 @@ TEST(BenchmarkResultTest, WriteToAndReadFromDisk) {
|
||||||
{
|
{
|
||||||
// Vector version.
|
// Vector version.
|
||||||
const auto FromDiskVector =
|
const auto FromDiskVector =
|
||||||
InstructionBenchmark::readYamlsOrDie(Ctx, Filename);
|
ExitOnErr(InstructionBenchmark::readYamls(Ctx, Filename));
|
||||||
ASSERT_EQ(FromDiskVector.size(), size_t{1});
|
ASSERT_EQ(FromDiskVector.size(), size_t{1});
|
||||||
const auto FromDisk = FromDiskVector[0];
|
const auto FromDisk = FromDiskVector[0];
|
||||||
EXPECT_EQ(FromDisk.Key.OpcodeName, ToDisk.Key.OpcodeName);
|
EXPECT_EQ(FromDisk.Key.OpcodeName, ToDisk.Key.OpcodeName);
|
||||||
|
|
Loading…
Reference in New Issue