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