[llvm] r334165 - [llvm-exegesis] Serializes instruction's operand in BenchmarkResult's key.

Guillaume Chatelet via llvm-commits llvm-commits at lists.llvm.org
Thu Jun 7 00:40:40 PDT 2018


Author: gchatelet
Date: Thu Jun  7 00:40:40 2018
New Revision: 334165

URL: http://llvm.org/viewvc/llvm-project?rev=334165&view=rev
Log:
[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

Modified:
    llvm/trunk/tools/llvm-exegesis/lib/BenchmarkResult.cpp
    llvm/trunk/tools/llvm-exegesis/lib/BenchmarkRunner.cpp
    llvm/trunk/unittests/tools/llvm-exegesis/BenchmarkResultTest.cpp

Modified: llvm/trunk/tools/llvm-exegesis/lib/BenchmarkResult.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-exegesis/lib/BenchmarkResult.cpp?rev=334165&r1=334164&r2=334165&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-exegesis/lib/BenchmarkResult.cpp (original)
+++ llvm/trunk/tools/llvm-exegesis/lib/BenchmarkResult.cpp Thu Jun  7 00:40:40 2018
@@ -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::MC
 
   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(
                                         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(con
 }
 
 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;
 }
 

Modified: llvm/trunk/tools/llvm-exegesis/lib/BenchmarkRunner.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-exegesis/lib/BenchmarkRunner.cpp?rev=334165&r1=334164&r2=334165&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-exegesis/lib/BenchmarkRunner.cpp (original)
+++ llvm/trunk/tools/llvm-exegesis/lib/BenchmarkRunner.cpp Thu Jun  7 00:40:40 2018
@@ -63,7 +63,9 @@ InstructionBenchmark BenchmarkRunner::ru
     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);

Modified: llvm/trunk/unittests/tools/llvm-exegesis/BenchmarkResultTest.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/tools/llvm-exegesis/BenchmarkResultTest.cpp?rev=334165&r1=334164&r2=334165&view=diff
==============================================================================
--- llvm/trunk/unittests/tools/llvm-exegesis/BenchmarkResultTest.cpp (original)
+++ llvm/trunk/unittests/tools/llvm-exegesis/BenchmarkResultTest.cpp Thu Jun  7 00:40:40 2018
@@ -28,23 +28,46 @@ bool operator==(const BenchmarkMeasure &
   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";




More information about the llvm-commits mailing list