xref: /llvm-project/llvm/tools/llvm-exegesis/lib/Analysis.cpp (revision 37f0ca0328aa2571a05d530f35f5e2ef7cbb9498)
1 //===-- 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 
15 namespace exegesis {
16 
17 static const char kCsvSep = ',';
18 
19 static 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).
37 static 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 
51 static 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 
61 llvm::Error
62 printAnalysisClusters(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
85