blob: d6b3902744578e03535c1e840d175c587dcc80a4 [file] [log] [blame]
Clement Courbet37f0ca02018-05-15 12:08:00 +00001//===-- Analysis.cpp --------------------------------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "BenchmarkResult.h"
11#include "Analysis.h"
12#include "llvm/Support/FormatVariadic.h"
13#include <vector>
14
15namespace exegesis {
16
17static const char kCsvSep = ',';
18
19static void writeCsvEscaped(llvm::raw_ostream& OS, const std::string& S) {
20 if (std::find(S.begin(), S.end(), kCsvSep) == S.end()) {
21 OS << S;
22 } else {
23 // Needs escaping.
24 OS << '"';
25 for (const char C : S) {
26 if (C == '"')
27 OS << "\"\"";
28 else
29 OS << C;
30 }
31 OS << '"';
32 }
33}
34
35// Prints a row representing an instruction, along with scheduling info and
36// point coordinates (measurements).
37static void printInstructionRow(const InstructionBenchmark &Point,
38 const llvm::MCSubtargetInfo &STI,
39 const size_t ClusterId, llvm::raw_ostream &OS) {
40 OS << ClusterId << kCsvSep;
41 writeCsvEscaped(OS, Point.AsmTmpl.Name);
42 // FIXME: Print the sched class once InstructionBenchmark separates key into
43 // (mnemonic, mode, opaque).
44 for (const auto &Measurement : Point.Measurements) {
45 OS << kCsvSep;
46 writeCsvEscaped(OS, llvm::formatv("{0:F}", Measurement.Value));
47 }
48 OS << "\n";
49}
50
51static void printCluster(const std::vector<InstructionBenchmark> &Points,
52 const llvm::MCSubtargetInfo &STI, const size_t ClusterId,
53 const InstructionBenchmarkClustering::Cluster &Cluster,
54 llvm::raw_ostream &OS) {
55 // Print all points.
56 for (const auto &PointId : Cluster.PointIndices) {
57 printInstructionRow(Points[PointId], STI, ClusterId, OS);
58 }
59}
60
61llvm::Error
62printAnalysisClusters(const InstructionBenchmarkClustering &Clustering,
63 const llvm::MCSubtargetInfo &STI, llvm::raw_ostream &OS) {
64 if (Clustering.getPoints().empty())
65 return llvm::Error::success();
66
67 // Write the header.
68 OS << "cluster_id;key,sched_class";
69 for (const auto &Measurement : Clustering.getPoints().front().Measurements) {
70 OS << kCsvSep;
71 writeCsvEscaped(OS, Measurement.Key);
72 }
73 OS << "\n";
74
75 // Write the points.
76 for (size_t I = 0, E = Clustering.getValidClusters().size(); I < E; ++I) {
77 printCluster(Clustering.getPoints(), STI, I,
78 Clustering.getValidClusters()[I], OS);
79 OS << "\n\n";
80 }
81 return llvm::Error::success();
82}
83
84} // namespace exegesis