[llvm] r334805 - [llvm-exegesis] Print the whole snippet in analysis.

Clement Courbet via llvm-commits llvm-commits at lists.llvm.org
Fri Jun 15 00:30:45 PDT 2018


Author: courbet
Date: Fri Jun 15 00:30:45 2018
New Revision: 334805

URL: http://llvm.org/viewvc/llvm-project?rev=334805&view=rev
Log:
[llvm-exegesis] Print the whole snippet in analysis.

Summary:
On hover, the whole asm snippet is displayed, including operands.

This requires the actual assembly output instead of just the MCInsts:
This is because some pseudo-instructions get lowered to actual target
instructions during codegen (e.g. ABS_Fp32 -> SSE or X87).

Reviewers: gchatelet

Subscribers: mgorny, tschuett, llvm-commits

Differential Revision: https://reviews.llvm.org/D48164

Modified:
    llvm/trunk/tools/llvm-exegesis/lib/Analysis.cpp
    llvm/trunk/tools/llvm-exegesis/lib/Analysis.h
    llvm/trunk/tools/llvm-exegesis/lib/BenchmarkResult.cpp
    llvm/trunk/tools/llvm-exegesis/lib/BenchmarkResult.h
    llvm/trunk/tools/llvm-exegesis/lib/BenchmarkRunner.cpp
    llvm/trunk/tools/llvm-exegesis/lib/BenchmarkRunner.h
    llvm/trunk/tools/llvm-exegesis/lib/CMakeLists.txt
    llvm/trunk/tools/llvm-exegesis/lib/LLVMBuild.txt
    llvm/trunk/tools/llvm-exegesis/llvm-exegesis.cpp

Modified: llvm/trunk/tools/llvm-exegesis/lib/Analysis.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-exegesis/lib/Analysis.cpp?rev=334805&r1=334804&r2=334805&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-exegesis/lib/Analysis.cpp (original)
+++ llvm/trunk/tools/llvm-exegesis/lib/Analysis.cpp Fri Jun 15 00:30:45 2018
@@ -10,6 +10,7 @@
 #include "Analysis.h"
 #include "BenchmarkResult.h"
 #include "llvm/ADT/STLExtras.h"
+#include "llvm/MC/MCAsmInfo.h"
 #include "llvm/Support/FormatVariadic.h"
 #include <unordered_set>
 #include <vector>
@@ -57,7 +58,8 @@ void writeEscaped<kEscapeHtml>(llvm::raw
 }
 
 template <>
-void writeEscaped<kEscapeHtmlString>(llvm::raw_ostream &OS, const llvm::StringRef S) {
+void writeEscaped<kEscapeHtmlString>(llvm::raw_ostream &OS,
+                                     const llvm::StringRef S) {
   for (const char C : S) {
     if (C == '"')
       OS << "\\\"";
@@ -85,17 +87,31 @@ static void writeMeasurementValue(llvm::
   writeEscaped<Tag>(OS, llvm::formatv("{0:F}", Value).str());
 }
 
-template <EscapeTag Tag>
-static void writeSnippet(llvm::raw_ostream &OS,
-                         const std::vector<llvm::MCInst> &Instructions,
-                         const llvm::MCInstrInfo &InstrInfo,
-                         const char* Separator) {
-  // FIXME: Print operands.
-  llvm::SmallVector<llvm::StringRef, 3> Opcodes;
-  for (const llvm::MCInst &Instr : Instructions) {
-    Opcodes.push_back(InstrInfo.getName(Instr.getOpcode()));
+template <typename EscapeTag, EscapeTag Tag>
+void Analysis::writeSnippet(llvm::raw_ostream &OS,
+                            llvm::ArrayRef<uint8_t> Bytes,
+                            const char *Separator) const {
+  llvm::SmallVector<std::string, 3> Lines;
+  // Parse the asm snippet and print it.
+  while (!Bytes.empty()) {
+    llvm::MCInst MI;
+    uint64_t MISize = 0;
+    if (!Disasm_->getInstruction(MI, MISize, Bytes, 0, llvm::nulls(),
+                                 llvm::nulls())) {
+      writeEscaped<Tag>(OS, llvm::join(Lines, Separator));
+      writeEscaped<Tag>(OS, Separator);
+      writeEscaped<Tag>(OS, "[error decoding asm snippet]");
+      return;
+    }
+    Lines.emplace_back();
+    std::string &Line = Lines.back();
+    llvm::raw_string_ostream OSS(Line);
+    InstPrinter_->printInst(&MI, OSS, "", *SubtargetInfo_);
+    Bytes = Bytes.drop_front(MISize);
+    OSS.flush();
+    Line = llvm::StringRef(Line).trim().str();
   }
-  writeEscaped<Tag>(OS, llvm::join(Opcodes, Separator));
+  writeEscaped<Tag>(OS, llvm::join(Lines, Separator));
 }
 
 // Prints a row representing an instruction, along with scheduling info and
@@ -105,7 +121,7 @@ void Analysis::printInstructionRowCsv(co
   const InstructionBenchmark &Point = Clustering_.getPoints()[PointId];
   writeClusterId<kEscapeCsv>(OS, Clustering_.getClusterIdForPoint(PointId));
   OS << kCsvSep;
-  writeSnippet<kEscapeCsv>(OS, Point.Key.Instructions, *InstrInfo_, "; ");
+  writeSnippet<EscapeTag, kEscapeCsv>(OS, Point.AssembledSnippet, "; ");
   OS << kCsvSep;
   writeEscaped<kEscapeCsv>(OS, Point.Key.Config);
   OS << kCsvSep;
@@ -134,10 +150,21 @@ Analysis::Analysis(const llvm::Target &T
   if (Clustering.getPoints().empty())
     return;
 
-  InstrInfo_.reset(Target.createMCInstrInfo());
   const InstructionBenchmark &FirstPoint = Clustering.getPoints().front();
+  InstrInfo_.reset(Target.createMCInstrInfo());
+  RegInfo_.reset(Target.createMCRegInfo(FirstPoint.LLVMTriple));
+  AsmInfo_.reset(Target.createMCAsmInfo(*RegInfo_, FirstPoint.LLVMTriple));
   SubtargetInfo_.reset(Target.createMCSubtargetInfo(FirstPoint.LLVMTriple,
                                                     FirstPoint.CpuName, ""));
+  InstPrinter_.reset(Target.createMCInstPrinter(
+      llvm::Triple(FirstPoint.LLVMTriple), 0 /*default variant*/, *AsmInfo_,
+      *InstrInfo_, *RegInfo_));
+
+  Context_ = llvm::make_unique<llvm::MCContext>(AsmInfo_.get(), RegInfo_.get(),
+                                                &ObjectFileInfo_);
+  Disasm_.reset(Target.createMCDisassembler(*SubtargetInfo_, *Context_));
+  assert(Disasm_ && "cannot create MCDisassembler. missing call to "
+                    "InitializeXXXTargetDisassembler ?");
 }
 
 template <>
@@ -197,9 +224,10 @@ static void writeUopsSnippetHtml(llvm::r
 
 // Latency tries to find a serial path. Just show the opcode path and show the
 // whole snippet only on hover.
-static void writeLatencySnippetHtml(llvm::raw_ostream &OS,
-                                 const std::vector<llvm::MCInst> &Instructions,
-                                 const llvm::MCInstrInfo &InstrInfo) {
+static void
+writeLatencySnippetHtml(llvm::raw_ostream &OS,
+                        const std::vector<llvm::MCInst> &Instructions,
+                        const llvm::MCInstrInfo &InstrInfo) {
   bool First = true;
   for (const llvm::MCInst &Instr : Instructions) {
     if (First)
@@ -238,17 +266,18 @@ void Analysis::printSchedClassClustersHt
     for (const size_t PointId : Cluster.getPointIds()) {
       const auto &Point = Points[PointId];
       OS << "<li><span class=\"mono\" title=\"";
-      writeSnippet<kEscapeHtmlString>(OS, Point.Key.Instructions, *InstrInfo_, "\n");
+      writeSnippet<EscapeTag, kEscapeHtmlString>(OS, Point.AssembledSnippet,
+                                                 "\n");
       OS << "\">";
       switch (Point.Mode) {
-        case InstructionBenchmark::Latency:
-          writeLatencySnippetHtml(OS, Point.Key.Instructions, *InstrInfo_);
-          break;
-        case InstructionBenchmark::Uops:
-          writeUopsSnippetHtml(OS, Point.Key.Instructions, *InstrInfo_);
-          break;
-        default:
-          llvm_unreachable("invalid mode");
+      case InstructionBenchmark::Latency:
+        writeLatencySnippetHtml(OS, Point.Key.Instructions, *InstrInfo_);
+        break;
+      case InstructionBenchmark::Uops:
+        writeUopsSnippetHtml(OS, Point.Key.Instructions, *InstrInfo_);
+        break;
+      default:
+        llvm_unreachable("invalid mode");
       }
       OS << "</span> <span class=\"mono\">";
       writeEscaped<kEscapeHtml>(OS, Point.Key.Config);
@@ -345,7 +374,7 @@ getNonRedundantWriteProcRes(const llvm::
 
 Analysis::SchedClass::SchedClass(const llvm::MCSchedClassDesc &SD,
                                  const llvm::MCSubtargetInfo &STI)
-    : SCDesc(SD),
+    : SCDesc(&SD),
       NonRedundantWriteProcRes(getNonRedundantWriteProcRes(SD, STI)),
       IdealizedProcResPressure(computeIdealizedProcResPressure(
           STI.getSchedModel(), NonRedundantWriteProcRes)) {}
@@ -382,9 +411,9 @@ bool Analysis::SchedClassCluster::measur
     }
     // Find the latency.
     SchedClassPoint[0].Value = 0.0;
-    for (unsigned I = 0; I < SC.SCDesc.NumWriteLatencyEntries; ++I) {
+    for (unsigned I = 0; I < SC.SCDesc->NumWriteLatencyEntries; ++I) {
       const llvm::MCWriteLatencyEntry *const WLE =
-          STI.getWriteLatencyEntry(&SC.SCDesc, I);
+          STI.getWriteLatencyEntry(SC.SCDesc, I);
       SchedClassPoint[0].Value =
           std::max<double>(SchedClassPoint[0].Value, WLE->Cycles);
     }
@@ -425,19 +454,19 @@ void Analysis::printSchedClassDescHtml(c
         "th><th>WriteProcRes</th><th title=\"This is the idealized unit "
         "resource (port) pressure assuming ideal distribution\">Idealized "
         "Resource Pressure</th></tr>";
-  if (SC.SCDesc.isValid()) {
+  if (SC.SCDesc->isValid()) {
     const auto &SM = SubtargetInfo_->getSchedModel();
     OS << "<tr><td>✔</td>";
-    OS << "<td>" << (SC.SCDesc.isVariant() ? "✔" : "✕")
+    OS << "<td>" << (SC.SCDesc->isVariant() ? "✔" : "✕")
        << "</td>";
-    OS << "<td>" << SC.SCDesc.NumMicroOps << "</td>";
+    OS << "<td>" << SC.SCDesc->NumMicroOps << "</td>";
     // Latencies.
     OS << "<td><ul>";
-    for (int I = 0, E = SC.SCDesc.NumWriteLatencyEntries; I < E; ++I) {
+    for (int I = 0, E = SC.SCDesc->NumWriteLatencyEntries; I < E; ++I) {
       const auto *const Entry =
-          SubtargetInfo_->getWriteLatencyEntry(&SC.SCDesc, I);
+          SubtargetInfo_->getWriteLatencyEntry(SC.SCDesc, I);
       OS << "<li>" << Entry->Cycles;
-      if (SC.SCDesc.NumWriteLatencyEntries > 1) {
+      if (SC.SCDesc->NumWriteLatencyEntries > 1) {
         // Dismabiguate if more than 1 latency.
         OS << " (WriteResourceID " << Entry->WriteResourceID << ")";
       }

Modified: llvm/trunk/tools/llvm-exegesis/lib/Analysis.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-exegesis/lib/Analysis.h?rev=334805&r1=334804&r2=334805&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-exegesis/lib/Analysis.h (original)
+++ llvm/trunk/tools/llvm-exegesis/lib/Analysis.h Fri Jun 15 00:30:45 2018
@@ -16,11 +16,16 @@
 #define LLVM_TOOLS_LLVM_EXEGESIS_ANALYSIS_H
 
 #include "Clustering.h"
+#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCDisassembler/MCDisassembler.h"
+#include "llvm/MC/MCInstPrinter.h"
 #include "llvm/MC/MCInstrInfo.h"
+#include "llvm/MC/MCObjectFileInfo.h"
 #include "llvm/MC/MCSubtargetInfo.h"
 #include "llvm/Support/Error.h"
 #include "llvm/Support/TargetRegistry.h"
 #include "llvm/Support/raw_ostream.h"
+#include <memory>
 #include <set>
 #include <string>
 #include <unordered_map>
@@ -48,7 +53,7 @@ private:
     SchedClass(const llvm::MCSchedClassDesc &SD,
                const llvm::MCSubtargetInfo &STI);
 
-    const llvm::MCSchedClassDesc &SCDesc;
+    const llvm::MCSchedClassDesc *const SCDesc;
     const llvm::SmallVector<llvm::MCWriteProcResEntry, 8>
         NonRedundantWriteProcRes;
     const std::vector<std::pair<uint16_t, float>> IdealizedProcResPressure;
@@ -97,9 +102,19 @@ private:
   std::unordered_map<unsigned, std::vector<size_t>>
   makePointsPerSchedClass() const;
 
+  template <typename EscapeTag, EscapeTag Tag>
+  void writeSnippet(llvm::raw_ostream &OS, llvm::ArrayRef<uint8_t> Bytes,
+                    const char *Separator) const;
+
   const InstructionBenchmarkClustering &Clustering_;
+  llvm::MCObjectFileInfo ObjectFileInfo_;
+  std::unique_ptr<llvm::MCContext> Context_;
   std::unique_ptr<llvm::MCSubtargetInfo> SubtargetInfo_;
   std::unique_ptr<llvm::MCInstrInfo> InstrInfo_;
+  std::unique_ptr<llvm::MCRegisterInfo> RegInfo_;
+  std::unique_ptr<llvm::MCAsmInfo> AsmInfo_;
+  std::unique_ptr<llvm::MCInstPrinter> InstPrinter_;
+  std::unique_ptr<llvm::MCDisassembler> Disasm_;
   std::unordered_map<std::string, unsigned> MnemonicToOpcode_;
 };
 

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=334805&r1=334804&r2=334805&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-exegesis/lib/BenchmarkResult.cpp (original)
+++ llvm/trunk/tools/llvm-exegesis/lib/BenchmarkResult.cpp Fri Jun 15 00:30:45 2018
@@ -10,6 +10,7 @@
 #include "BenchmarkResult.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/StringRef.h"
+#include "llvm/ObjectYAML/YAML.h"
 #include "llvm/Support/FileOutputBuffer.h"
 #include "llvm/Support/FileSystem.h"
 #include "llvm/Support/Format.h"
@@ -146,6 +147,23 @@ template <> struct MappingTraits<exegesi
 };
 
 template <> struct MappingTraits<exegesis::InstructionBenchmark> {
+  class NormalizedBinary {
+  public:
+    NormalizedBinary(IO &io) {}
+    NormalizedBinary(IO &, std::vector<uint8_t> &Data) : Binary(Data) {}
+    std::vector<uint8_t> denormalize(IO &) {
+      std::vector<uint8_t> Data;
+      std::string Str;
+      raw_string_ostream OSS(Str);
+      Binary.writeAsBinary(OSS);
+      OSS.flush();
+      Data.assign(Str.begin(), Str.end());
+      return Data;
+    }
+
+    BinaryRef Binary;
+  };
+
   static void mapping(IO &Io, exegesis::InstructionBenchmark &Obj) {
     Io.mapRequired("mode", Obj.Mode);
     Io.mapRequired("key", Obj.Key);
@@ -155,6 +173,10 @@ template <> struct MappingTraits<exegesi
     Io.mapRequired("measurements", Obj.Measurements);
     Io.mapRequired("error", Obj.Error);
     Io.mapOptional("info", Obj.Info);
+    // AssembledSnippet
+    MappingNormalization<NormalizedBinary, std::vector<uint8_t>> BinaryString(
+        Io, Obj.AssembledSnippet);
+    Io.mapOptional("assembled_snippet", BinaryString->Binary);
   }
 };
 

Modified: llvm/trunk/tools/llvm-exegesis/lib/BenchmarkResult.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-exegesis/lib/BenchmarkResult.h?rev=334805&r1=334804&r2=334805&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-exegesis/lib/BenchmarkResult.h (original)
+++ llvm/trunk/tools/llvm-exegesis/lib/BenchmarkResult.h Fri Jun 15 00:30:45 2018
@@ -55,6 +55,7 @@ struct InstructionBenchmark {
   std::vector<BenchmarkMeasure> Measurements;
   std::string Error;
   std::string Info;
+  std::vector<uint8_t> AssembledSnippet;
 
   // Read functions.
   static llvm::Expected<InstructionBenchmark>

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=334805&r1=334804&r2=334805&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-exegesis/lib/BenchmarkRunner.cpp (original)
+++ llvm/trunk/tools/llvm-exegesis/lib/BenchmarkRunner.cpp Fri Jun 15 00:30:45 2018
@@ -74,24 +74,41 @@ BenchmarkRunner::runOne(const BenchmarkC
     return InstrBenchmark;
   }
 
-  for (const auto &MCInst : Snippet)
-    InstrBenchmark.Key.Instructions.push_back(MCInst);
+  InstrBenchmark.Key.Instructions = Snippet;
 
-  std::vector<llvm::MCInst> Code;
-  for (int I = 0; I < InstrBenchmark.NumRepetitions; ++I)
-    Code.push_back(Snippet[I % Snippet.size()]);
+  // Repeat the snippet until there are at least NumInstructions in the
+  // resulting code. The snippet is always repeated at least once.
+  const auto GenerateInstructions = [&Snippet](const int MinInstructions) {
+    std::vector<llvm::MCInst> Code = Snippet;
+    for (int I = 0; I < MinInstructions; ++I)
+      Code.push_back(Snippet[I % Snippet.size()]);
+    return Code;
+  };
+
+  // Assemble at least kMinInstructionsForSnippet instructions by repeating the
+  // snippet for debug/analysis. This is so that the user clearly understands
+  // that the inside instructions are repeated.
+  constexpr const int kMinInstructionsForSnippet = 16;
+  {
+    auto EF = createExecutableFunction(
+        GenerateInstructions(kMinInstructionsForSnippet));
+    if (llvm::Error E = EF.takeError()) {
+      InstrBenchmark.Error = llvm::toString(std::move(E));
+      return InstrBenchmark;
+    }
+    const auto FnBytes = EF->getFunctionBytes();
+    InstrBenchmark.AssembledSnippet.assign(FnBytes.begin(), FnBytes.end());
+  }
 
-  auto ExpectedObjectPath = writeObjectFile(Code);
-  if (llvm::Error E = ExpectedObjectPath.takeError()) {
+  // Assemble NumRepetitions instructions repetitions of the snippet for
+  // measurements.
+  auto EF = createExecutableFunction(
+      GenerateInstructions(InstrBenchmark.NumRepetitions));
+  if (llvm::Error E = EF.takeError()) {
     InstrBenchmark.Error = llvm::toString(std::move(E));
     return InstrBenchmark;
   }
-
-  // FIXME: Check if TargetMachine or ExecutionEngine can be reused instead of
-  // creating one everytime.
-  const ExecutableFunction EF(State.createTargetMachine(),
-                              getObjectFromFile(*ExpectedObjectPath));
-  InstrBenchmark.Measurements = runMeasurements(EF, NumRepetitions);
+  InstrBenchmark.Measurements = runMeasurements(*EF, NumRepetitions);
 
   return InstrBenchmark;
 }
@@ -110,4 +127,17 @@ BenchmarkRunner::writeObjectFile(llvm::A
   return ResultPath.str();
 }
 
+llvm::Expected<ExecutableFunction> BenchmarkRunner::createExecutableFunction(
+    llvm::ArrayRef<llvm::MCInst> Code) const {
+  auto ExpectedObjectPath = writeObjectFile(Code);
+  if (llvm::Error E = ExpectedObjectPath.takeError()) {
+    return std::move(E);
+  }
+
+  // FIXME: Check if TargetMachine or ExecutionEngine can be reused instead of
+  // creating one everytime.
+  return ExecutableFunction(State.createTargetMachine(),
+                            getObjectFromFile(*ExpectedObjectPath));
+}
+
 } // namespace exegesis

Modified: llvm/trunk/tools/llvm-exegesis/lib/BenchmarkRunner.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-exegesis/lib/BenchmarkRunner.h?rev=334805&r1=334804&r2=334805&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-exegesis/lib/BenchmarkRunner.h (original)
+++ llvm/trunk/tools/llvm-exegesis/lib/BenchmarkRunner.h Fri Jun 15 00:30:45 2018
@@ -91,6 +91,8 @@ private:
 
   llvm::Expected<std::string>
   writeObjectFile(llvm::ArrayRef<llvm::MCInst> Code) const;
+  llvm::Expected<ExecutableFunction>
+  createExecutableFunction(llvm::ArrayRef<llvm::MCInst> Code) const;
 };
 
 } // namespace exegesis

Modified: llvm/trunk/tools/llvm-exegesis/lib/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-exegesis/lib/CMakeLists.txt?rev=334805&r1=334804&r2=334805&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-exegesis/lib/CMakeLists.txt (original)
+++ llvm/trunk/tools/llvm-exegesis/lib/CMakeLists.txt Fri Jun 15 00:30:45 2018
@@ -22,8 +22,10 @@ llvm_map_components_to_libnames(libs
   ExecutionEngine
   GlobalISel
   MC
+  MCDisassembler
   MCJIT
   Object
+  ObjectYAML
   Support
   )
 

Modified: llvm/trunk/tools/llvm-exegesis/lib/LLVMBuild.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-exegesis/lib/LLVMBuild.txt?rev=334805&r1=334804&r2=334805&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-exegesis/lib/LLVMBuild.txt (original)
+++ llvm/trunk/tools/llvm-exegesis/lib/LLVMBuild.txt Fri Jun 15 00:30:45 2018
@@ -19,4 +19,4 @@
 type = Library
 name = Exegesis
 parent = Libraries
-required_libraries = CodeGen ExecutionEngine MC MCJIT Object Support
+required_libraries = CodeGen ExecutionEngine MC MCDisassembler MCJIT Object ObjectYAML Support

Modified: llvm/trunk/tools/llvm-exegesis/llvm-exegesis.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-exegesis/llvm-exegesis.cpp?rev=334805&r1=334804&r2=334805&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-exegesis/llvm-exegesis.cpp (original)
+++ llvm/trunk/tools/llvm-exegesis/llvm-exegesis.cpp Fri Jun 15 00:30:45 2018
@@ -180,6 +180,7 @@ static void analysisMain() {
 
   llvm::InitializeNativeTarget();
   llvm::InitializeNativeTargetAsmPrinter();
+  llvm::InitializeNativeTargetDisassembler();
   // Read benchmarks.
   const LLVMState State;
   const std::vector<InstructionBenchmark> Points =




More information about the llvm-commits mailing list