blob: acc30ab791210f4f18a06d12a1914fa02cc3bb66 [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
Clement Courbet37f0ca02018-05-15 12:08:00 +000010#include "Analysis.h"
Clement Courbeta66bfaa42018-05-15 13:07:05 +000011#include "BenchmarkResult.h"
Clement Courbet37f0ca02018-05-15 12:08:00 +000012#include "llvm/Support/FormatVariadic.h"
13#include <vector>
14
15namespace exegesis {
16
17static const char kCsvSep = ',';
18
Clement Courbeta66bfaa42018-05-15 13:07:05 +000019static void writeCsvEscaped(llvm::raw_ostream &OS, const std::string &S) {
Clement Courbet37f0ca02018-05-15 12:08:00 +000020 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,
Clement Courbeta66bfaa42018-05-15 13:07:05 +000038 const llvm::MCSubtargetInfo &STI,
39 const size_t ClusterId, llvm::raw_ostream &OS) {
Clement Courbet37f0ca02018-05-15 12:08:00 +000040 OS << ClusterId << kCsvSep;
Clement Courbeta66bfaa42018-05-15 13:07:05 +000041 writeCsvEscaped(OS, Point.Key.OpcodeName);
42 OS << kCsvSep;
43 writeCsvEscaped(OS, Point.Key.Config);
Clement Courbet37f0ca02018-05-15 12:08:00 +000044 // FIXME: Print the sched class once InstructionBenchmark separates key into
45 // (mnemonic, mode, opaque).
46 for (const auto &Measurement : Point.Measurements) {
47 OS << kCsvSep;
48 writeCsvEscaped(OS, llvm::formatv("{0:F}", Measurement.Value));
49 }
50 OS << "\n";
51}
52
53static void printCluster(const std::vector<InstructionBenchmark> &Points,
Clement Courbeta66bfaa42018-05-15 13:07:05 +000054 const llvm::MCSubtargetInfo &STI,
55 const size_t ClusterId,
56 const InstructionBenchmarkClustering::Cluster &Cluster,
57 llvm::raw_ostream &OS) {
Clement Courbet37f0ca02018-05-15 12:08:00 +000058 // Print all points.
59 for (const auto &PointId : Cluster.PointIndices) {
60 printInstructionRow(Points[PointId], STI, ClusterId, OS);
61 }
62}
63
64llvm::Error
65printAnalysisClusters(const InstructionBenchmarkClustering &Clustering,
66 const llvm::MCSubtargetInfo &STI, llvm::raw_ostream &OS) {
67 if (Clustering.getPoints().empty())
68 return llvm::Error::success();
69
70 // Write the header.
Clement Courbeta66bfaa42018-05-15 13:07:05 +000071 OS << "cluster_id" << kCsvSep << "opcode_name" << kCsvSep << "config"
72 << kCsvSep << "sched_class";
Clement Courbet37f0ca02018-05-15 12:08:00 +000073 for (const auto &Measurement : Clustering.getPoints().front().Measurements) {
74 OS << kCsvSep;
75 writeCsvEscaped(OS, Measurement.Key);
76 }
77 OS << "\n";
78
79 // Write the points.
80 for (size_t I = 0, E = Clustering.getValidClusters().size(); I < E; ++I) {
81 printCluster(Clustering.getPoints(), STI, I,
82 Clustering.getValidClusters()[I], OS);
83 OS << "\n\n";
84 }
85 return llvm::Error::success();
86}
87
88} // namespace exegesis