[llvm-mca] LLVM Machine Code Analyzer.

llvm-mca is an LLVM based performance analysis tool that can be used to
statically measure the performance of code, and to help triage potential
problems with target scheduling models.

llvm-mca uses information which is already available in LLVM (e.g. scheduling
models) to statically measure the performance of machine code in a specific cpu.
Performance is measured in terms of throughput as well as processor resource
consumption. The tool currently works for processors with an out-of-order
backend, for which there is a scheduling model available in LLVM.

The main goal of this tool is not just to predict the performance of the code
when run on the target, but also help with diagnosing potential performance
issues.

Given an assembly code sequence, llvm-mca estimates the IPC (instructions per
cycle), as well as hardware resources pressure. The analysis and reporting style
were mostly inspired by the IACA tool from Intel.

This patch is related to the RFC on llvm-dev visible at this link:
http://lists.llvm.org/pipermail/llvm-dev/2018-March/121490.html

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

llvm-svn: 326998
diff --git a/llvm/tools/llvm-mca/BackendPrinter.h b/llvm/tools/llvm-mca/BackendPrinter.h
new file mode 100644
index 0000000..b4793b6
--- /dev/null
+++ b/llvm/tools/llvm-mca/BackendPrinter.h
@@ -0,0 +1,102 @@
+//===--------------------- BackendPrinter.h ---------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+/// \file
+///
+/// This file implements class BackendPrinter.
+/// BackendPrinter is able to collect statistics related to the code executed
+/// by the Backend class. Information is then printed out with the help of
+/// a MCInstPrinter (to pretty print MCInst objects) and other helper classes.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TOOLS_LLVM_MCA_BACKENDPRINTER_H
+#define LLVM_TOOLS_LLVM_MCA_BACKENDPRINTER_H
+
+#include "Backend.h"
+#include "BackendStatistics.h"
+#include "ResourcePressureView.h"
+#include "TimelineView.h"
+#include "llvm/MC/MCInstPrinter.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/FileUtilities.h"
+#include "llvm/Support/ToolOutputFile.h"
+
+#define DEBUG_TYPE "llvm-mca"
+
+namespace mca {
+
+class ResourcePressureView;
+class TimelineView;
+
+/// \brief A printer class that knows how to collects statistics on the
+/// code analyzed by the llvm-mca tool.
+///
+/// This class knows how to print out the analysis information collected
+/// during the execution of the code. Internally, it delegates to other
+/// classes the task of printing out timeline information as well as
+/// resource pressure.
+class BackendPrinter {
+  Backend &B;
+  bool EnableVerboseOutput;
+
+  std::unique_ptr<llvm::MCInstPrinter> MCIP;
+  std::unique_ptr<llvm::ToolOutputFile> File;
+
+  std::unique_ptr<ResourcePressureView> RPV;
+  std::unique_ptr<TimelineView> TV;
+  std::unique_ptr<BackendStatistics> BS;
+
+  using Histogram = std::map<unsigned, unsigned>;
+  void printDUStatistics(const Histogram &Stats, unsigned Cycles) const;
+  void printDispatchStalls(unsigned RATStalls, unsigned RCUStalls,
+                           unsigned SQStalls, unsigned LDQStalls,
+                           unsigned STQStalls, unsigned DGStalls) const;
+  void printRATStatistics(unsigned Mappings, unsigned MaxUsedMappings) const;
+  void printRCUStatistics(const Histogram &Histogram, unsigned Cycles) const;
+  void printIssuePerCycle(const Histogram &IssuePerCycle,
+                          unsigned TotalCycles) const;
+  void printSchedulerUsage(const llvm::MCSchedModel &SM,
+                           const llvm::ArrayRef<BufferUsageEntry> &Usage) const;
+  void printGeneralStatistics(unsigned Iterations, unsigned Cycles,
+                              unsigned Instructions,
+                              unsigned DispatchWidth) const;
+  void printInstructionInfo() const;
+
+  std::unique_ptr<llvm::ToolOutputFile> getOutputStream(std::string OutputFile);
+  void initialize(std::string OputputFileName);
+
+public:
+  BackendPrinter(Backend &backend, std::string OutputFileName,
+                 std::unique_ptr<llvm::MCInstPrinter> IP, bool EnableVerbose)
+      : B(backend), EnableVerboseOutput(EnableVerbose), MCIP(std::move(IP)) {
+    initialize(OutputFileName);
+  }
+
+  ~BackendPrinter() {
+    if (File)
+      File->keep();
+  }
+
+  bool isFileValid() const { return File.get(); }
+  llvm::raw_ostream &getOStream() const {
+    assert(isFileValid());
+    return File->os();
+  }
+
+  llvm::MCInstPrinter &getMCInstPrinter() const { return *MCIP; }
+
+  void addResourcePressureView();
+  void addTimelineView(unsigned MaxIterations = 3, unsigned MaxCycles = 80);
+
+  void printReport() const;
+};
+
+} // namespace mca
+
+#endif