forked from OSchip/llvm-project
[llvm-exegesis] Serializes registers initial values.
Summary: Adds the registers initial values to the YAML output of llvm-exegesis. Reviewers: courbet Subscribers: tschuett, llvm-commits Differential Revision: https://reviews.llvm.org/D52460 llvm-svn: 342982
This commit is contained in:
parent
6078f82241
commit
345fae5d56
|
@ -1,8 +1,11 @@
|
||||||
# RUN: llvm-exegesis -mode=latency -opcode-name=ADD32rr | FileCheck %s
|
# RUN: llvm-exegesis -mode=latency -opcode-name=ADD32rr | FileCheck %s
|
||||||
|
|
||||||
CHECK: ---
|
CHECK: ---
|
||||||
CHECK-NEXT: mode: latency
|
CHECK-NEXT: mode: latency
|
||||||
CHECK-NEXT: key:
|
CHECK-NEXT: key:
|
||||||
CHECK-NEXT: instructions:
|
CHECK-NEXT: instructions:
|
||||||
CHECK-NEXT: ADD32rr
|
CHECK-NEXT: ADD32rr
|
||||||
|
CHECK-NEXT: config: ''
|
||||||
|
CHECK-NEXT: register_initial_values:
|
||||||
|
CHECK-DAG: - '[[REG1:[A-Z0-9]+]]=0x0'
|
||||||
CHECK-LAST: ...
|
CHECK-LAST: ...
|
||||||
|
|
|
@ -54,6 +54,24 @@ struct YamlContext {
|
||||||
|
|
||||||
std::string &getLastError() { return ErrorStream.str(); }
|
std::string &getLastError() { return ErrorStream.str(); }
|
||||||
|
|
||||||
|
llvm::raw_string_ostream &getErrorStream() { return ErrorStream; }
|
||||||
|
|
||||||
|
llvm::StringRef getRegName(unsigned RegNo) {
|
||||||
|
const llvm::StringRef RegName = State->getRegInfo().getName(RegNo);
|
||||||
|
if (RegName.empty())
|
||||||
|
ErrorStream << "No register with enum value" << RegNo;
|
||||||
|
return RegName;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned getRegNo(llvm::StringRef RegName) {
|
||||||
|
const llvm::MCRegisterInfo &RegInfo = State->getRegInfo();
|
||||||
|
for (unsigned E = RegInfo.getNumRegs(), I = 0; I < E; ++I)
|
||||||
|
if (RegInfo.getName(I) == RegName)
|
||||||
|
return I;
|
||||||
|
ErrorStream << "No register with name " << RegName;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void serializeMCOperand(const llvm::MCOperand &MCOperand,
|
void serializeMCOperand(const llvm::MCOperand &MCOperand,
|
||||||
llvm::raw_ostream &OS) {
|
llvm::raw_ostream &OS) {
|
||||||
|
@ -83,13 +101,6 @@ private:
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
llvm::StringRef getRegName(unsigned RegNo) {
|
|
||||||
const llvm::StringRef RegName = State->getRegInfo().getName(RegNo);
|
|
||||||
if (RegName.empty())
|
|
||||||
ErrorStream << "No register with enum value" << RegNo;
|
|
||||||
return RegName;
|
|
||||||
}
|
|
||||||
|
|
||||||
llvm::StringRef getInstrName(unsigned InstrNo) {
|
llvm::StringRef getInstrName(unsigned InstrNo) {
|
||||||
const llvm::StringRef InstrName = State->getInstrInfo().getName(InstrNo);
|
const llvm::StringRef InstrName = State->getInstrInfo().getName(InstrNo);
|
||||||
if (InstrName.empty())
|
if (InstrName.empty())
|
||||||
|
@ -97,15 +108,6 @@ private:
|
||||||
return InstrName;
|
return InstrName;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned getRegNo(llvm::StringRef RegName) {
|
|
||||||
const llvm::MCRegisterInfo &RegInfo = State->getRegInfo();
|
|
||||||
for (unsigned E = RegInfo.getNumRegs(), I = 0; I < E; ++I)
|
|
||||||
if (RegInfo.getName(I) == RegName)
|
|
||||||
return I;
|
|
||||||
ErrorStream << "No register with name " << RegName;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned getInstrOpcode(llvm::StringRef InstrName) {
|
unsigned getInstrOpcode(llvm::StringRef InstrName) {
|
||||||
const llvm::MCInstrInfo &InstrInfo = State->getInstrInfo();
|
const llvm::MCInstrInfo &InstrInfo = State->getInstrInfo();
|
||||||
for (unsigned E = InstrInfo.getNumOpcodes(), I = 0; I < E; ++I)
|
for (unsigned E = InstrInfo.getNumOpcodes(), I = 0; I < E; ++I)
|
||||||
|
@ -124,6 +126,10 @@ private:
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
namespace yaml {
|
namespace yaml {
|
||||||
|
|
||||||
|
static YamlContext &getTypedContext(void *Ctx) {
|
||||||
|
return *reinterpret_cast<YamlContext *>(Ctx);
|
||||||
|
}
|
||||||
|
|
||||||
// std::vector<llvm::MCInst> will be rendered as a list.
|
// std::vector<llvm::MCInst> will be rendered as a list.
|
||||||
template <> struct SequenceElementTraits<llvm::MCInst> {
|
template <> struct SequenceElementTraits<llvm::MCInst> {
|
||||||
static const bool flow = false;
|
static const bool flow = false;
|
||||||
|
@ -133,15 +139,17 @@ template <> struct ScalarTraits<llvm::MCInst> {
|
||||||
|
|
||||||
static void output(const llvm::MCInst &Value, void *Ctx,
|
static void output(const llvm::MCInst &Value, void *Ctx,
|
||||||
llvm::raw_ostream &Out) {
|
llvm::raw_ostream &Out) {
|
||||||
reinterpret_cast<YamlContext *>(Ctx)->serializeMCInst(Value, Out);
|
getTypedContext(Ctx).serializeMCInst(Value, Out);
|
||||||
}
|
}
|
||||||
|
|
||||||
static StringRef input(StringRef Scalar, void *Ctx, llvm::MCInst &Value) {
|
static StringRef input(StringRef Scalar, void *Ctx, llvm::MCInst &Value) {
|
||||||
YamlContext &Context = *reinterpret_cast<YamlContext *>(Ctx);
|
YamlContext &Context = getTypedContext(Ctx);
|
||||||
Context.deserializeMCInst(Scalar, Value);
|
Context.deserializeMCInst(Scalar, Value);
|
||||||
return Context.getLastError();
|
return Context.getLastError();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// By default strings are quoted only when necessary.
|
||||||
|
// We force the use of single quotes for uniformity.
|
||||||
static QuotingType mustQuote(StringRef) { return QuotingType::Single; }
|
static QuotingType mustQuote(StringRef) { return QuotingType::Single; }
|
||||||
|
|
||||||
static const bool flow = true;
|
static const bool flow = true;
|
||||||
|
@ -173,6 +181,44 @@ struct ScalarEnumerationTraits<exegesis::InstructionBenchmark::ModeE> {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// std::vector<exegesis::RegisterValue> will be rendered as a list.
|
||||||
|
template <> struct SequenceElementTraits<exegesis::RegisterValue> {
|
||||||
|
static const bool flow = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <> struct ScalarTraits<exegesis::RegisterValue> {
|
||||||
|
static constexpr const unsigned kRadix = 16;
|
||||||
|
static constexpr const bool kSigned = false;
|
||||||
|
|
||||||
|
static void output(const exegesis::RegisterValue &RV, void *Ctx,
|
||||||
|
llvm::raw_ostream &Out) {
|
||||||
|
YamlContext &Context = getTypedContext(Ctx);
|
||||||
|
Out << Context.getRegName(RV.Register) << "=0x"
|
||||||
|
<< RV.Value.toString(kRadix, kSigned);
|
||||||
|
}
|
||||||
|
|
||||||
|
static StringRef input(StringRef String, void *Ctx,
|
||||||
|
exegesis::RegisterValue &RV) {
|
||||||
|
llvm::SmallVector<llvm::StringRef, 2> Pieces;
|
||||||
|
String.split(Pieces, "=0x", /* MaxSplit */ -1,
|
||||||
|
/* KeepEmpty */ false);
|
||||||
|
YamlContext &Context = getTypedContext(Ctx);
|
||||||
|
if (Pieces.size() == 2) {
|
||||||
|
RV.Register = Context.getRegNo(Pieces[0]);
|
||||||
|
const unsigned BitsNeeded = llvm::APInt::getBitsNeeded(Pieces[1], kRadix);
|
||||||
|
RV.Value = llvm::APInt(BitsNeeded, Pieces[1], kRadix);
|
||||||
|
} else {
|
||||||
|
Context.getErrorStream()
|
||||||
|
<< "Unknown initial register value: '" << String << "'";
|
||||||
|
}
|
||||||
|
return Context.getLastError();
|
||||||
|
}
|
||||||
|
|
||||||
|
static QuotingType mustQuote(StringRef) { return QuotingType::Single; }
|
||||||
|
|
||||||
|
static const bool flow = true;
|
||||||
|
};
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
struct MappingContextTraits<exegesis::InstructionBenchmarkKey, YamlContext> {
|
struct MappingContextTraits<exegesis::InstructionBenchmarkKey, YamlContext> {
|
||||||
static void mapping(IO &Io, exegesis::InstructionBenchmarkKey &Obj,
|
static void mapping(IO &Io, exegesis::InstructionBenchmarkKey &Obj,
|
||||||
|
@ -180,13 +226,13 @@ struct MappingContextTraits<exegesis::InstructionBenchmarkKey, YamlContext> {
|
||||||
Io.setContext(&Context);
|
Io.setContext(&Context);
|
||||||
Io.mapRequired("instructions", Obj.Instructions);
|
Io.mapRequired("instructions", Obj.Instructions);
|
||||||
Io.mapOptional("config", Obj.Config);
|
Io.mapOptional("config", Obj.Config);
|
||||||
|
Io.mapRequired("register_initial_values", Obj.RegisterInitialValues);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
struct MappingContextTraits<exegesis::InstructionBenchmark, YamlContext> {
|
struct MappingContextTraits<exegesis::InstructionBenchmark, YamlContext> {
|
||||||
class NormalizedBinary {
|
struct NormalizedBinary {
|
||||||
public:
|
|
||||||
NormalizedBinary(IO &io) {}
|
NormalizedBinary(IO &io) {}
|
||||||
NormalizedBinary(IO &, std::vector<uint8_t> &Data) : Binary(Data) {}
|
NormalizedBinary(IO &, std::vector<uint8_t> &Data) : Binary(Data) {}
|
||||||
std::vector<uint8_t> denormalize(IO &) {
|
std::vector<uint8_t> denormalize(IO &) {
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
#ifndef LLVM_TOOLS_LLVM_EXEGESIS_BENCHMARKRESULT_H
|
#ifndef LLVM_TOOLS_LLVM_EXEGESIS_BENCHMARKRESULT_H
|
||||||
#define LLVM_TOOLS_LLVM_EXEGESIS_BENCHMARKRESULT_H
|
#define LLVM_TOOLS_LLVM_EXEGESIS_BENCHMARKRESULT_H
|
||||||
|
|
||||||
|
#include "BenchmarkCode.h"
|
||||||
#include "LlvmState.h"
|
#include "LlvmState.h"
|
||||||
#include "llvm/ADT/StringMap.h"
|
#include "llvm/ADT/StringMap.h"
|
||||||
#include "llvm/ADT/StringRef.h"
|
#include "llvm/ADT/StringRef.h"
|
||||||
|
@ -32,6 +33,8 @@ namespace exegesis {
|
||||||
struct InstructionBenchmarkKey {
|
struct InstructionBenchmarkKey {
|
||||||
// The LLVM opcode name.
|
// The LLVM opcode name.
|
||||||
std::vector<llvm::MCInst> Instructions;
|
std::vector<llvm::MCInst> Instructions;
|
||||||
|
// The initial values of the registers.
|
||||||
|
std::vector<RegisterValue> RegisterInitialValues;
|
||||||
// An opaque configuration, that can be used to separate several benchmarks of
|
// An opaque configuration, that can be used to separate several benchmarks of
|
||||||
// the same instruction under different configurations.
|
// the same instruction under different configurations.
|
||||||
std::string Config;
|
std::string Config;
|
||||||
|
|
|
@ -57,6 +57,7 @@ BenchmarkRunner::runConfiguration(const BenchmarkCode &BC,
|
||||||
const std::vector<llvm::MCInst> &Instructions = BC.Instructions;
|
const std::vector<llvm::MCInst> &Instructions = BC.Instructions;
|
||||||
|
|
||||||
InstrBenchmark.Key.Instructions = Instructions;
|
InstrBenchmark.Key.Instructions = Instructions;
|
||||||
|
InstrBenchmark.Key.RegisterInitialValues = BC.RegisterInitialValues;
|
||||||
|
|
||||||
// Assemble at least kMinInstructionsForSnippet instructions by repeating the
|
// Assemble at least kMinInstructionsForSnippet instructions by repeating the
|
||||||
// snippet for debug/analysis. This is so that the user clearly understands
|
// snippet for debug/analysis. This is so that the user clearly understands
|
||||||
|
|
|
@ -68,6 +68,9 @@ TEST(BenchmarkResultTest, WriteToAndReadFromDisk) {
|
||||||
.addImm(123)
|
.addImm(123)
|
||||||
.addFPImm(0.5));
|
.addFPImm(0.5));
|
||||||
ToDisk.Key.Config = "config";
|
ToDisk.Key.Config = "config";
|
||||||
|
ToDisk.Key.RegisterInitialValues = {
|
||||||
|
RegisterValue{llvm::X86::AL, llvm::APInt(8, "-1", 10)},
|
||||||
|
RegisterValue{llvm::X86::AH, llvm::APInt(8, "123", 10)}};
|
||||||
ToDisk.Mode = InstructionBenchmark::Latency;
|
ToDisk.Mode = InstructionBenchmark::Latency;
|
||||||
ToDisk.CpuName = "cpu_name";
|
ToDisk.CpuName = "cpu_name";
|
||||||
ToDisk.LLVMTriple = "llvm_triple";
|
ToDisk.LLVMTriple = "llvm_triple";
|
||||||
|
|
Loading…
Reference in New Issue