diff options
| author | Clement Courbet <courbet@google.com> | 2018-05-17 12:25:18 +0000 |
|---|---|---|
| committer | Clement Courbet <courbet@google.com> | 2018-05-17 12:25:18 +0000 |
| commit | 448550d947e74912b8a3b49db517ab793e96d027 (patch) | |
| tree | 5affccd03a792fc3a8a867bd686a835411b59818 /llvm/tools/llvm-exegesis/lib/Analysis.cpp | |
| parent | 3d5e08de9616791522a9ebd8d018dad0235b6330 (diff) | |
| download | bcm5719-llvm-448550d947e74912b8a3b49db517ab793e96d027.tar.gz bcm5719-llvm-448550d947e74912b8a3b49db517ab793e96d027.zip | |
[llvm-exegesis] Analysis: detect clustering inconsistencies.
Summary:
Warn on instructions that should have the same performance
characteristics according to the sched model but actually
differ in their benchmarks.
Next step: Make the display nicer to browse, I was thinking maybe html.
Reviewers: gchatelet
Subscribers: tschuett, llvm-commits
Differential Revision: https://reviews.llvm.org/D46945
llvm-svn: 332601
Diffstat (limited to 'llvm/tools/llvm-exegesis/lib/Analysis.cpp')
| -rw-r--r-- | llvm/tools/llvm-exegesis/lib/Analysis.cpp | 95 |
1 files changed, 79 insertions, 16 deletions
diff --git a/llvm/tools/llvm-exegesis/lib/Analysis.cpp b/llvm/tools/llvm-exegesis/lib/Analysis.cpp index e026308ad19..5b609257f59 100644 --- a/llvm/tools/llvm-exegesis/lib/Analysis.cpp +++ b/llvm/tools/llvm-exegesis/lib/Analysis.cpp @@ -10,6 +10,7 @@ #include "Analysis.h" #include "BenchmarkResult.h" #include "llvm/Support/FormatVariadic.h" +#include <unordered_set> #include <vector> namespace exegesis { @@ -34,26 +35,36 @@ static void writeCsvEscaped(llvm::raw_ostream &OS, const std::string &S) { // Prints a row representing an instruction, along with scheduling info and // point coordinates (measurements). -void Analysis::printInstructionRow(const size_t ClusterId, const size_t PointId, +void Analysis::printInstructionRow(const bool PrintSchedClass, + const size_t PointId, llvm::raw_ostream &OS) const { const InstructionBenchmark &Point = Clustering_.getPoints()[PointId]; - - OS << ClusterId << kCsvSep; + const auto &ClusterId = Clustering_.getClusterIdForPoint(PointId); + if (ClusterId.isNoise()) + OS << "[noise]"; + else if (ClusterId.isError()) + OS << "[error]"; + else + OS << ClusterId.getId(); + OS << kCsvSep; writeCsvEscaped(OS, Point.Key.OpcodeName); OS << kCsvSep; writeCsvEscaped(OS, Point.Key.Config); - OS << kCsvSep; - const auto OpcodeIt = MnemonicToOpcode_.find(Point.Key.OpcodeName); - if (OpcodeIt != MnemonicToOpcode_.end()) { - const unsigned SchedClassId = InstrInfo_->get(OpcodeIt->second).getSchedClass(); + if (PrintSchedClass) { + OS << kCsvSep; + const auto OpcodeIt = MnemonicToOpcode_.find(Point.Key.OpcodeName); + if (OpcodeIt != MnemonicToOpcode_.end()) { + const unsigned SchedClassId = + InstrInfo_->get(OpcodeIt->second).getSchedClass(); #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) - const auto &SchedModel = SubtargetInfo_->getSchedModel(); - const llvm::MCSchedClassDesc *const SCDesc = - SchedModel.getSchedClassDesc(SchedClassId); - writeCsvEscaped(OS, SCDesc->Name); + const auto &SchedModel = SubtargetInfo_->getSchedModel(); + const llvm::MCSchedClassDesc *const SCDesc = + SchedModel.getSchedClassDesc(SchedClassId); + writeCsvEscaped(OS, SCDesc->Name); #else - OS << SchedClassId; + OS << SchedClassId; #endif + } } // FIXME: Print the sched class once InstructionBenchmark separates key into // (mnemonic, mode, opaque). @@ -72,8 +83,8 @@ Analysis::Analysis(const llvm::Target &Target, InstrInfo_.reset(Target.createMCInstrInfo()); const InstructionBenchmark &FirstPoint = Clustering.getPoints().front(); - SubtargetInfo_.reset(Target.createMCSubtargetInfo( - FirstPoint.LLVMTriple, FirstPoint.CpuName, "")); + SubtargetInfo_.reset(Target.createMCSubtargetInfo(FirstPoint.LLVMTriple, + FirstPoint.CpuName, "")); // Build an index of mnemonic->opcode. for (int I = 0, E = InstrInfo_->getNumOpcodes(); I < E; ++I) @@ -94,14 +105,66 @@ llvm::Error Analysis::printClusters(llvm::raw_ostream &OS) const { OS << "\n"; // Write the points. - const auto& Clusters = Clustering_.getValidClusters(); + const auto &Clusters = Clustering_.getValidClusters(); for (size_t I = 0, E = Clusters.size(); I < E; ++I) { for (const size_t PointId : Clusters[I].PointIndices) { - printInstructionRow(I, PointId, OS); + printInstructionRow(/*PrintSchedClass*/ true, PointId, OS); } OS << "\n\n"; } return llvm::Error::success(); } +std::unordered_map<unsigned, std::vector<size_t>> +Analysis::makePointsPerSchedClass() const { + std::unordered_map<unsigned, std::vector<size_t>> PointsPerSchedClass; + const auto &Points = Clustering_.getPoints(); + for (size_t PointId = 0, E = Points.size(); PointId < E; ++PointId) { + const InstructionBenchmark &Point = Points[PointId]; + if (!Point.Error.empty()) + continue; + const auto OpcodeIt = MnemonicToOpcode_.find(Point.Key.OpcodeName); + if (OpcodeIt == MnemonicToOpcode_.end()) + continue; + const unsigned SchedClassId = + InstrInfo_->get(OpcodeIt->second).getSchedClass(); + PointsPerSchedClass[SchedClassId].push_back(PointId); + } + return PointsPerSchedClass; +} + +llvm::Error +Analysis::printSchedClassInconsistencies(llvm::raw_ostream &OS) const { + // All the points in a scheduling class should be in the same cluster. + // Print any scheduling class for which this is not the case. + for (const auto &SchedClassAndPoints : makePointsPerSchedClass()) { + std::unordered_set<size_t> ClustersForSchedClass; + for (const size_t PointId : SchedClassAndPoints.second) { + const auto &ClusterId = Clustering_.getClusterIdForPoint(PointId); + if (!ClusterId.isValid()) + continue; // Ignore noise and errors. + ClustersForSchedClass.insert(ClusterId.getId()); + } + if (ClustersForSchedClass.size() <= 1) + continue; // Nothing weird. + + OS << "\nSched Class "; +#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) + const auto &SchedModel = SubtargetInfo_->getSchedModel(); + const llvm::MCSchedClassDesc *const SCDesc = + SchedModel.getSchedClassDesc(SchedClassAndPoints.first); + OS << SCDesc->Name; +#else + OS << SchedClassAndPoints.first; +#endif + OS << " contains instructions with distinct performance " + "characteristics, falling into " + << ClustersForSchedClass.size() << " clusters:\n"; + for (const size_t PointId : SchedClassAndPoints.second) { + printInstructionRow(/*PrintSchedClass*/ false, PointId, OS); + } + } + return llvm::Error::success(); +} + } // namespace exegesis |

