[llvm] r332601 - [llvm-exegesis] Analysis: detect clustering inconsistencies.
Clement Courbet via llvm-commits
llvm-commits at lists.llvm.org
Thu May 17 05:25:18 PDT 2018
Author: courbet
Date: Thu May 17 05:25:18 2018
New Revision: 332601
URL: http://llvm.org/viewvc/llvm-project?rev=332601&view=rev
Log:
[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
Modified:
llvm/trunk/tools/llvm-exegesis/lib/Analysis.cpp
llvm/trunk/tools/llvm-exegesis/lib/Analysis.h
llvm/trunk/tools/llvm-exegesis/llvm-exegesis.cpp
Modified: llvm/trunk/tools/llvm-exegesis/lib/Analysis.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-exegesis/lib/Analysis.cpp?rev=332601&r1=332600&r2=332601&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-exegesis/lib/Analysis.cpp (original)
+++ llvm/trunk/tools/llvm-exegesis/lib/Analysis.cpp Thu May 17 05:25:18 2018
@@ -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_os
// 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 &T
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
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
Modified: llvm/trunk/tools/llvm-exegesis/lib/Analysis.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-exegesis/lib/Analysis.h?rev=332601&r1=332600&r2=332601&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-exegesis/lib/Analysis.h (original)
+++ llvm/trunk/tools/llvm-exegesis/lib/Analysis.h Thu May 17 05:25:18 2018
@@ -18,8 +18,8 @@
#include "Clustering.h"
#include "llvm/MC/MCInstrInfo.h"
#include "llvm/MC/MCSubtargetInfo.h"
-#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/Error.h"
+#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/raw_ostream.h"
#include <string>
#include <unordered_map>
@@ -29,19 +29,28 @@ namespace exegesis {
// A helper class to analyze benchmark results for a target.
class Analysis {
public:
- Analysis(const llvm::Target& Target, const InstructionBenchmarkClustering &Clustering);
+ Analysis(const llvm::Target &Target,
+ const InstructionBenchmarkClustering &Clustering);
// Prints a csv of instructions for each cluster.
llvm::Error printClusters(llvm::raw_ostream &OS) const;
- private:
- void printInstructionRow(size_t ClusterId, size_t PointId,
- llvm::raw_ostream &OS) const;
-
- const InstructionBenchmarkClustering & Clustering_;
- std::unique_ptr<llvm::MCSubtargetInfo> SubtargetInfo_;
- std::unique_ptr<llvm::MCInstrInfo> InstrInfo_;
- std::unordered_map<std::string, unsigned> MnemonicToOpcode_;
+ // Find potential errors in the scheduling information given measurements.
+ llvm::Error printSchedClassInconsistencies(llvm::raw_ostream &OS) const;
+
+private:
+ void printInstructionRow(bool PrintSchedClass, size_t PointId,
+ llvm::raw_ostream &OS) const;
+
+ // Builds a map of Sched Class -> indices of points that belong to the sched
+ // class.
+ std::unordered_map<unsigned, std::vector<size_t>>
+ makePointsPerSchedClass() const;
+
+ const InstructionBenchmarkClustering &Clustering_;
+ std::unique_ptr<llvm::MCSubtargetInfo> SubtargetInfo_;
+ std::unique_ptr<llvm::MCInstrInfo> InstrInfo_;
+ std::unordered_map<std::string, unsigned> MnemonicToOpcode_;
};
} // namespace exegesis
Modified: llvm/trunk/tools/llvm-exegesis/llvm-exegesis.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-exegesis/llvm-exegesis.cpp?rev=332601&r1=332600&r2=332601&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-exegesis/llvm-exegesis.cpp (original)
+++ llvm/trunk/tools/llvm-exegesis/llvm-exegesis.cpp Thu May 17 05:25:18 2018
@@ -160,6 +160,9 @@ void analysisMain() {
if (auto Err = Analyzer.printClusters(ClustersOS))
llvm::report_fatal_error(std::move(Err));
+
+ if (auto Err = Analyzer.printSchedClassInconsistencies(llvm::outs()))
+ llvm::report_fatal_error(std::move(Err));
}
} // namespace exegesis
More information about the llvm-commits
mailing list