blob: 36a3479b6df89febb2a8531833ba63b112cc4d12 [file] [log] [blame]
Clement Courbet37f0ca02018-05-15 12:08:00 +00001//===-- Analysis.h ----------------------------------------------*- C++ -*-===//
2//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
Clement Courbet37f0ca02018-05-15 12:08:00 +00006//
7//===----------------------------------------------------------------------===//
8///
9/// \file
10/// Analysis output for benchmark results.
11///
12//===----------------------------------------------------------------------===//
13
14#ifndef LLVM_TOOLS_LLVM_EXEGESIS_ANALYSIS_H
15#define LLVM_TOOLS_LLVM_EXEGESIS_ANALYSIS_H
16
17#include "Clustering.h"
Clement Courbet4273e1e2018-06-15 07:30:45 +000018#include "llvm/MC/MCContext.h"
19#include "llvm/MC/MCDisassembler/MCDisassembler.h"
20#include "llvm/MC/MCInstPrinter.h"
Clement Courbet6d6c1a92018-05-16 08:47:21 +000021#include "llvm/MC/MCInstrInfo.h"
Clement Courbet4273e1e2018-06-15 07:30:45 +000022#include "llvm/MC/MCObjectFileInfo.h"
Clement Courbet37f0ca02018-05-15 12:08:00 +000023#include "llvm/MC/MCSubtargetInfo.h"
24#include "llvm/Support/Error.h"
Clement Courbet448550d2018-05-17 12:25:18 +000025#include "llvm/Support/TargetRegistry.h"
Clement Courbet37f0ca02018-05-15 12:08:00 +000026#include "llvm/Support/raw_ostream.h"
Clement Courbet4273e1e2018-06-15 07:30:45 +000027#include <memory>
Clement Courbet72287212018-06-04 11:11:55 +000028#include <set>
Clement Courbet6d6c1a92018-05-16 08:47:21 +000029#include <string>
30#include <unordered_map>
Clement Courbet37f0ca02018-05-15 12:08:00 +000031
Fangrui Song32401af2018-10-22 17:10:47 +000032namespace llvm {
Clement Courbet37f0ca02018-05-15 12:08:00 +000033namespace exegesis {
34
Clement Courbet6d6c1a92018-05-16 08:47:21 +000035// A helper class to analyze benchmark results for a target.
36class Analysis {
37public:
Clement Courbet448550d2018-05-17 12:25:18 +000038 Analysis(const llvm::Target &Target,
Roman Lebedev69716392019-02-20 09:14:04 +000039 std::unique_ptr<llvm::MCInstrInfo> InstrInfo,
40 const InstructionBenchmarkClustering &Clustering,
Roman Lebedev542e5d72019-02-25 09:36:12 +000041 double AnalysisInconsistencyEpsilon,
Roman Lebedev69716392019-02-20 09:14:04 +000042 bool AnalysisDisplayUnstableOpcodes);
Clement Courbet6d6c1a92018-05-16 08:47:21 +000043
44 // Prints a csv of instructions for each cluster.
Clement Courbetcf210742018-05-17 13:41:28 +000045 struct PrintClusters {};
Clement Courbet448550d2018-05-17 12:25:18 +000046 // Find potential errors in the scheduling information given measurements.
Clement Courbetcf210742018-05-17 13:41:28 +000047 struct PrintSchedClassInconsistencies {};
48
49 template <typename Pass> llvm::Error run(llvm::raw_ostream &OS) const;
Clement Courbet6d6c1a92018-05-16 08:47:21 +000050
Clement Courbet448550d2018-05-17 12:25:18 +000051private:
Clement Courbet72287212018-06-04 11:11:55 +000052 using ClusterId = InstructionBenchmarkClustering::ClusterId;
53
54 // An llvm::MCSchedClassDesc augmented with some additional data.
Clement Courbetd5a39552018-10-03 11:50:25 +000055 struct ResolvedSchedClass {
56 ResolvedSchedClass(const llvm::MCSubtargetInfo &STI,
57 unsigned ResolvedSchedClassId, bool WasVariant);
Clement Courbet72287212018-06-04 11:11:55 +000058
Clement Courbet8a5a6be2018-10-03 12:35:35 +000059 const unsigned SchedClassId;
Clement Courbet4273e1e2018-06-15 07:30:45 +000060 const llvm::MCSchedClassDesc *const SCDesc;
Clement Courbetd5a39552018-10-03 11:50:25 +000061 const bool WasVariant; // Whether the original class was variant.
Clement Courbet72287212018-06-04 11:11:55 +000062 const llvm::SmallVector<llvm::MCWriteProcResEntry, 8>
63 NonRedundantWriteProcRes;
64 const std::vector<std::pair<uint16_t, float>> IdealizedProcResPressure;
65 };
66
67 // Represents the intersection of a sched class and a cluster.
68 class SchedClassCluster {
69 public:
70 const InstructionBenchmarkClustering::ClusterId &id() const {
71 return ClusterId;
72 }
73
74 const std::vector<size_t> &getPointIds() const { return PointIds; }
75
Roman Lebedevc2423fe2019-03-28 08:55:01 +000076 void addPoint(size_t PointId,
77 const InstructionBenchmarkClustering &Clustering);
78
Clement Courbet72287212018-06-04 11:11:55 +000079 // Return the cluster centroid.
Roman Lebedevc2423fe2019-03-28 08:55:01 +000080 const SchedClassClusterCentroid &getCentroid() const { return Centroid; }
Clement Courbet72287212018-06-04 11:11:55 +000081
Roman Lebedevb8fb15d2019-03-29 11:36:08 +000082 std::vector<BenchmarkMeasure>
83 getSchedClassPoint(InstructionBenchmark::ModeE Mode,
84 const llvm::MCSubtargetInfo &STI,
85 const ResolvedSchedClass &SC,
86 ArrayRef<PerInstructionStats> Representative) const;
87
Clement Courbet72287212018-06-04 11:11:55 +000088 // Returns true if the cluster representative measurements match that of SC.
89 bool
Clement Courbetd5a39552018-10-03 11:50:25 +000090 measurementsMatch(const llvm::MCSubtargetInfo &STI,
91 const ResolvedSchedClass &SC,
Roman Lebedev542e5d72019-02-25 09:36:12 +000092 const InstructionBenchmarkClustering &Clustering,
93 const double AnalysisInconsistencyEpsilonSquared_) const;
Clement Courbet72287212018-06-04 11:11:55 +000094
Clement Courbet72287212018-06-04 11:11:55 +000095 private:
96 InstructionBenchmarkClustering::ClusterId ClusterId;
97 std::vector<size_t> PointIds;
98 // Measurement stats for the points in the SchedClassCluster.
Roman Lebedevc2423fe2019-03-28 08:55:01 +000099 SchedClassClusterCentroid Centroid;
Clement Courbet72287212018-06-04 11:11:55 +0000100 };
101
Clement Courbet17d3c252018-05-22 13:31:29 +0000102 void printInstructionRowCsv(size_t PointId, llvm::raw_ostream &OS) const;
103
Clement Courbet72287212018-06-04 11:11:55 +0000104 void
105 printSchedClassClustersHtml(const std::vector<SchedClassCluster> &Clusters,
Clement Courbetd5a39552018-10-03 11:50:25 +0000106 const ResolvedSchedClass &SC,
Clement Courbet72287212018-06-04 11:11:55 +0000107 llvm::raw_ostream &OS) const;
Clement Courbetd5a39552018-10-03 11:50:25 +0000108 void printSchedClassDescHtml(const ResolvedSchedClass &SC,
Clement Courbet2637e5f2018-05-24 10:47:05 +0000109 llvm::raw_ostream &OS) const;
Clement Courbet448550d2018-05-17 12:25:18 +0000110
Clement Courbetd5a39552018-10-03 11:50:25 +0000111 // A pair of (Sched Class, indices of points that belong to the sched
112 // class).
113 struct ResolvedSchedClassAndPoints {
114 explicit ResolvedSchedClassAndPoints(ResolvedSchedClass &&RSC);
115
116 ResolvedSchedClass RSC;
117 std::vector<size_t> PointIds;
118 };
119
120 // Builds a list of ResolvedSchedClassAndPoints.
121 std::vector<ResolvedSchedClassAndPoints> makePointsPerSchedClass() const;
Clement Courbet448550d2018-05-17 12:25:18 +0000122
Clement Courbet4273e1e2018-06-15 07:30:45 +0000123 template <typename EscapeTag, EscapeTag Tag>
124 void writeSnippet(llvm::raw_ostream &OS, llvm::ArrayRef<uint8_t> Bytes,
125 const char *Separator) const;
126
Clement Courbet448550d2018-05-17 12:25:18 +0000127 const InstructionBenchmarkClustering &Clustering_;
Clement Courbet4273e1e2018-06-15 07:30:45 +0000128 llvm::MCObjectFileInfo ObjectFileInfo_;
129 std::unique_ptr<llvm::MCContext> Context_;
Clement Courbet448550d2018-05-17 12:25:18 +0000130 std::unique_ptr<llvm::MCSubtargetInfo> SubtargetInfo_;
131 std::unique_ptr<llvm::MCInstrInfo> InstrInfo_;
Clement Courbet4273e1e2018-06-15 07:30:45 +0000132 std::unique_ptr<llvm::MCRegisterInfo> RegInfo_;
133 std::unique_ptr<llvm::MCAsmInfo> AsmInfo_;
134 std::unique_ptr<llvm::MCInstPrinter> InstPrinter_;
135 std::unique_ptr<llvm::MCDisassembler> Disasm_;
Roman Lebedev542e5d72019-02-25 09:36:12 +0000136 const double AnalysisInconsistencyEpsilonSquared_;
Roman Lebedev69716392019-02-20 09:14:04 +0000137 const bool AnalysisDisplayUnstableOpcodes_;
Clement Courbet6d6c1a92018-05-16 08:47:21 +0000138};
Clement Courbet37f0ca02018-05-15 12:08:00 +0000139
Clement Courbetdf79e792018-06-01 14:18:02 +0000140// Computes the idealized ProcRes Unit pressure. This is the expected
141// distribution if the CPU scheduler can distribute the load as evenly as
142// possible.
143std::vector<std::pair<uint16_t, float>> computeIdealizedProcResPressure(
144 const llvm::MCSchedModel &SM,
145 llvm::SmallVector<llvm::MCWriteProcResEntry, 8> WPRS);
146
Clement Courbet37f0ca02018-05-15 12:08:00 +0000147} // namespace exegesis
Fangrui Song32401af2018-10-22 17:10:47 +0000148} // namespace llvm
Clement Courbet37f0ca02018-05-15 12:08:00 +0000149
150#endif // LLVM_TOOLS_LLVM_EXEGESIS_CLUSTERING_H