mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-22 18:54:02 +01:00
[llvm-exegesis] Serializes instruction's operand in BenchmarkResult's key.
Summary: Follow up patch to https://reviews.llvm.org/D47764. Reviewers: courbet Subscribers: tschuett, llvm-commits Differential Revision: https://reviews.llvm.org/D47785 llvm-svn: 334165
This commit is contained in:
parent
9fb142b4db
commit
7ada5fd5d2
@ -15,6 +15,78 @@
|
||||
#include "llvm/Support/Format.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
|
||||
static constexpr const char kIntegerFormat[] = "i_0x%" PRId64 "x";
|
||||
static constexpr const char kDoubleFormat[] = "f_%la";
|
||||
|
||||
static void serialize(const exegesis::BenchmarkResultContext &Context,
|
||||
const llvm::MCOperand &MCOperand, llvm::raw_ostream &OS) {
|
||||
if (MCOperand.isReg()) {
|
||||
OS << Context.getRegName(MCOperand.getReg());
|
||||
} else if (MCOperand.isImm()) {
|
||||
OS << llvm::format(kIntegerFormat, MCOperand.getImm());
|
||||
} else if (MCOperand.isFPImm()) {
|
||||
OS << llvm::format(kDoubleFormat, MCOperand.getFPImm());
|
||||
} else {
|
||||
OS << "INVALID";
|
||||
}
|
||||
}
|
||||
|
||||
static void serialize(const exegesis::BenchmarkResultContext &Context,
|
||||
const llvm::MCInst &MCInst, llvm::raw_ostream &OS) {
|
||||
OS << Context.getInstrName(MCInst.getOpcode());
|
||||
for (const auto &Op : MCInst) {
|
||||
OS << ' ';
|
||||
serialize(Context, Op, OS);
|
||||
}
|
||||
}
|
||||
|
||||
static llvm::MCOperand
|
||||
deserialize(const exegesis::BenchmarkResultContext &Context,
|
||||
llvm::StringRef String) {
|
||||
assert(!String.empty());
|
||||
int64_t IntValue = 0;
|
||||
double DoubleValue = 0;
|
||||
if (sscanf(String.data(), kIntegerFormat, &IntValue) == 1)
|
||||
return llvm::MCOperand::createImm(IntValue);
|
||||
if (sscanf(String.data(), kDoubleFormat, &DoubleValue) == 1)
|
||||
return llvm::MCOperand::createFPImm(DoubleValue);
|
||||
if (unsigned RegNo = Context.getRegNo(String)) // Returns 0 if invalid.
|
||||
return llvm::MCOperand::createReg(RegNo);
|
||||
return {};
|
||||
}
|
||||
|
||||
static llvm::StringRef
|
||||
deserialize(const exegesis::BenchmarkResultContext &Context,
|
||||
llvm::StringRef String, llvm::MCInst &Value) {
|
||||
llvm::SmallVector<llvm::StringRef, 8> Pieces;
|
||||
String.split(Pieces, " ");
|
||||
if (Pieces.empty())
|
||||
return "Invalid Instruction";
|
||||
bool ProcessOpcode = true;
|
||||
for (llvm::StringRef Piece : Pieces) {
|
||||
if (ProcessOpcode) {
|
||||
ProcessOpcode = false;
|
||||
Value.setOpcode(Context.getInstrOpcode(Piece));
|
||||
if (Value.getOpcode() == 0)
|
||||
return "Unknown Opcode Name";
|
||||
} else {
|
||||
Value.addOperand(deserialize(Context, Piece));
|
||||
}
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
// YAML IO requires a mutable pointer to Context but we guarantee to not
|
||||
// modify it.
|
||||
static void *getUntypedContext(const exegesis::BenchmarkResultContext &Ctx) {
|
||||
return const_cast<exegesis::BenchmarkResultContext *>(&Ctx);
|
||||
}
|
||||
|
||||
static const exegesis::BenchmarkResultContext &getTypedContext(void *Ctx) {
|
||||
assert(Ctx);
|
||||
return *static_cast<const exegesis::BenchmarkResultContext *>(Ctx);
|
||||
}
|
||||
|
||||
// Defining YAML traits for IO.
|
||||
namespace llvm {
|
||||
namespace yaml {
|
||||
@ -28,22 +100,11 @@ template <> struct ScalarTraits<llvm::MCInst> {
|
||||
|
||||
static void output(const llvm::MCInst &Value, void *Ctx,
|
||||
llvm::raw_ostream &Out) {
|
||||
assert(Ctx);
|
||||
auto *Context = static_cast<const exegesis::BenchmarkResultContext *>(Ctx);
|
||||
const StringRef Name = Context->getInstrName(Value.getOpcode());
|
||||
assert(!Name.empty());
|
||||
Out << Name;
|
||||
serialize(getTypedContext(Ctx), Value, Out);
|
||||
}
|
||||
|
||||
static StringRef input(StringRef Scalar, void *Ctx, llvm::MCInst &Value) {
|
||||
assert(Ctx);
|
||||
auto *Context = static_cast<const exegesis::BenchmarkResultContext *>(Ctx);
|
||||
const unsigned Opcode = Context->getInstrOpcode(Scalar);
|
||||
if (Opcode == 0) {
|
||||
return "Unable to parse instruction";
|
||||
}
|
||||
Value.setOpcode(Opcode);
|
||||
return StringRef();
|
||||
return deserialize(getTypedContext(Ctx), Scalar, Value);
|
||||
}
|
||||
|
||||
static QuotingType mustQuote(StringRef) { return QuotingType::Single; }
|
||||
@ -153,10 +214,7 @@ static ObjectOrList readYamlOrDieCommon(const BenchmarkResultContext &Context,
|
||||
llvm::StringRef Filename) {
|
||||
std::unique_ptr<llvm::MemoryBuffer> 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<BenchmarkResultContext *>(&Context));
|
||||
llvm::yaml::Input Yin(*MemBuffer, getUntypedContext(Context));
|
||||
ObjectOrList Benchmark;
|
||||
Yin >> Benchmark;
|
||||
return Benchmark;
|
||||
@ -176,19 +234,14 @@ InstructionBenchmark::readYamlsOrDie(const BenchmarkResultContext &Context,
|
||||
}
|
||||
|
||||
void InstructionBenchmark::writeYamlTo(const BenchmarkResultContext &Context,
|
||||
llvm::raw_ostream &S) {
|
||||
// YAML IO requires a mutable pointer to Context but we guarantee to not
|
||||
// modify it.
|
||||
llvm::yaml::Output Yout(S, const_cast<BenchmarkResultContext *>(&Context));
|
||||
llvm::raw_ostream &OS) {
|
||||
llvm::yaml::Output Yout(OS, getUntypedContext(Context));
|
||||
Yout << *this;
|
||||
}
|
||||
|
||||
void InstructionBenchmark::readYamlFrom(const BenchmarkResultContext &Context,
|
||||
llvm::StringRef InputContent) {
|
||||
// YAML IO requires a mutable pointer to Context but we guarantee to not
|
||||
// modify it.
|
||||
llvm::yaml::Input Yin(InputContent,
|
||||
const_cast<BenchmarkResultContext *>(&Context));
|
||||
llvm::yaml::Input Yin(InputContent, getUntypedContext(Context));
|
||||
Yin >> *this;
|
||||
}
|
||||
|
||||
|
@ -63,7 +63,9 @@ InstructionBenchmark BenchmarkRunner::run(unsigned Opcode,
|
||||
InstrBenchmark.Error = "Empty snippet";
|
||||
return InstrBenchmark;
|
||||
}
|
||||
|
||||
for (const auto &MCInst : Snippet) {
|
||||
InstrBenchmark.Key.Instructions.push_back(MCInst);
|
||||
}
|
||||
InfoStream << "Snippet:\n";
|
||||
for (const auto &MCInst : Snippet) {
|
||||
DumpMCInst(MCRegisterInfo, MCInstrInfo, MCInst, InfoStream);
|
||||
|
@ -28,23 +28,46 @@ bool operator==(const BenchmarkMeasure &A, const BenchmarkMeasure &B) {
|
||||
return std::tie(A.Key, A.Value) == std::tie(B.Key, B.Value);
|
||||
}
|
||||
|
||||
static std::string Dump(const llvm::MCInst &McInst) {
|
||||
std::string Buffer;
|
||||
llvm::raw_string_ostream OS(Buffer);
|
||||
McInst.print(OS);
|
||||
return Buffer;
|
||||
}
|
||||
|
||||
MATCHER(EqMCInst, "") {
|
||||
return get<0>(arg).getOpcode() == get<1>(arg).getOpcode();
|
||||
const std::string Lhs = Dump(get<0>(arg));
|
||||
const std::string Rhs = Dump(get<1>(arg));
|
||||
if (Lhs != Rhs) {
|
||||
*result_listener << Lhs << " <=> " << Rhs;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
static constexpr const unsigned kInstrId = 5;
|
||||
static constexpr const char kInstrName[] = "Instruction5";
|
||||
static constexpr const unsigned kReg1Id = 1;
|
||||
static constexpr const char kReg1Name[] = "Reg1";
|
||||
static constexpr const unsigned kReg2Id = 2;
|
||||
static constexpr const char kReg2Name[] = "Reg2";
|
||||
|
||||
TEST(BenchmarkResultTest, WriteToAndReadFromDisk) {
|
||||
BenchmarkResultContext Ctx;
|
||||
Ctx.addInstrEntry(kInstrId, kInstrName);
|
||||
Ctx.addRegEntry(kReg1Id, kReg1Name);
|
||||
Ctx.addRegEntry(kReg2Id, kReg2Name);
|
||||
|
||||
InstructionBenchmark ToDisk;
|
||||
|
||||
ToDisk.Key.OpcodeName = "name";
|
||||
ToDisk.Key.Instructions.push_back(llvm::MCInstBuilder(kInstrId));
|
||||
ToDisk.Key.Instructions.push_back(llvm::MCInstBuilder(kInstrId)
|
||||
.addReg(kReg1Id)
|
||||
.addReg(kReg2Id)
|
||||
.addImm(123)
|
||||
.addFPImm(0.5));
|
||||
ToDisk.Key.Config = "config";
|
||||
ToDisk.Mode = InstructionBenchmark::Latency;
|
||||
ToDisk.CpuName = "cpu_name";
|
||||
|
Loading…
Reference in New Issue
Block a user