diff options
Diffstat (limited to 'llvm/tools/llvm-exegesis/lib/Analysis.cpp')
-rw-r--r-- | llvm/tools/llvm-exegesis/lib/Analysis.cpp | 105 |
1 files changed, 79 insertions, 26 deletions
diff --git a/llvm/tools/llvm-exegesis/lib/Analysis.cpp b/llvm/tools/llvm-exegesis/lib/Analysis.cpp index df353dcbf33..842790d74c7 100644 --- a/llvm/tools/llvm-exegesis/lib/Analysis.cpp +++ b/llvm/tools/llvm-exegesis/lib/Analysis.cpp @@ -20,7 +20,7 @@ static const char kCsvSep = ','; namespace { -enum EscapeTag { kEscapeCsv, kEscapeHtml }; +enum EscapeTag { kEscapeCsv, kEscapeHtml, kEscapeHtmlString }; template <EscapeTag Tag> void writeEscaped(llvm::raw_ostream &OS, const llvm::StringRef S); @@ -56,6 +56,16 @@ void writeEscaped<kEscapeHtml>(llvm::raw_ostream &OS, const llvm::StringRef S) { } } +template <> +void writeEscaped<kEscapeHtmlString>(llvm::raw_ostream &OS, const llvm::StringRef S) { + for (const char C : S) { + if (C == '"') + OS << "\\\""; + else + OS << C; + } +} + } // namespace template <EscapeTag Tag> @@ -75,6 +85,19 @@ static void writeMeasurementValue(llvm::raw_ostream &OS, const double Value) { writeEscaped<Tag>(OS, llvm::formatv("{0:F}", Value).str()); } +template <EscapeTag Tag> +static void writeSnippet(llvm::raw_ostream &OS, + const std::vector<llvm::MCInst> &Instructions, + const llvm::MCInstrInfo &InstrInfo, + const char* Separator) { + // FIXME: Print operands. + llvm::SmallVector<llvm::StringRef, 3> Opcodes; + for (const llvm::MCInst &Instr : Instructions) { + Opcodes.push_back(InstrInfo.getName(Instr.getOpcode())); + } + writeEscaped<Tag>(OS, llvm::join(Opcodes, Separator)); +} + // Prints a row representing an instruction, along with scheduling info and // point coordinates (measurements). void Analysis::printInstructionRowCsv(const size_t PointId, @@ -82,25 +105,22 @@ void Analysis::printInstructionRowCsv(const size_t PointId, const InstructionBenchmark &Point = Clustering_.getPoints()[PointId]; writeClusterId<kEscapeCsv>(OS, Clustering_.getClusterIdForPoint(PointId)); OS << kCsvSep; - writeEscaped<kEscapeCsv>(OS, Point.Key.OpcodeName); + writeSnippet<kEscapeCsv>(OS, Point.Key.Instructions, *InstrInfo_, "; "); OS << kCsvSep; writeEscaped<kEscapeCsv>(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(); + assert(!Point.Key.Instructions.empty()); + // FIXME: Resolve variant classes. + const unsigned SchedClassId = + InstrInfo_->get(Point.Key.Instructions[0].getOpcode()).getSchedClass(); #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) - const auto &SchedModel = SubtargetInfo_->getSchedModel(); - const llvm::MCSchedClassDesc *const SCDesc = - SchedModel.getSchedClassDesc(SchedClassId); - writeEscaped<kEscapeCsv>(OS, SCDesc->Name); + const auto &SchedModel = SubtargetInfo_->getSchedModel(); + const llvm::MCSchedClassDesc *const SCDesc = + SchedModel.getSchedClassDesc(SchedClassId); + writeEscaped<kEscapeCsv>(OS, SCDesc->Name); #else - OS << SchedClassId; + OS << SchedClassId; #endif - } - // FIXME: Print the sched class once InstructionBenchmark separates key into - // (mnemonic, mode, opaque). for (const auto &Measurement : Point.Measurements) { OS << kCsvSep; writeMeasurementValue<kEscapeCsv>(OS, Measurement.Value); @@ -118,10 +138,6 @@ Analysis::Analysis(const llvm::Target &Target, const InstructionBenchmark &FirstPoint = Clustering.getPoints().front(); SubtargetInfo_.reset(Target.createMCSubtargetInfo(FirstPoint.LLVMTriple, FirstPoint.CpuName, "")); - - // Build an index of mnemonic->opcode. - for (int I = 0, E = InstrInfo_->getNumOpcodes(); I < E; ++I) - MnemonicToOpcode_.emplace(InstrInfo_->getName(I), I); } template <> @@ -158,16 +174,42 @@ Analysis::makePointsPerSchedClass() const { 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); + assert(!Point.Key.Instructions.empty()); + const auto Opcode = Point.Key.Instructions[0].getOpcode(); + // FIXME: Resolve variant classes. + PointsPerSchedClass[InstrInfo_->get(Opcode).getSchedClass()].push_back( + PointId); } return PointsPerSchedClass; } +// Uops repeat the same opcode over again. Just show this opcode and show the +// whole snippet only on hover. +static void writeUopsSnippetHtml(llvm::raw_ostream &OS, + const std::vector<llvm::MCInst> &Instructions, + const llvm::MCInstrInfo &InstrInfo) { + if (Instructions.empty()) + return; + writeEscaped<kEscapeHtml>(OS, InstrInfo.getName(Instructions[0].getOpcode())); + if (Instructions.size() > 1) + OS << " (x" << Instructions.size() << ")"; +} + +// Latency tries to find a serial path. Just show the opcode path and show the +// whole snippet only on hover. +static void writeLatencySnippetHtml(llvm::raw_ostream &OS, + const std::vector<llvm::MCInst> &Instructions, + const llvm::MCInstrInfo &InstrInfo) { + bool First = true; + for (const llvm::MCInst &Instr : Instructions) { + if (First) + First = false; + else + OS << " → "; + writeEscaped<kEscapeHtml>(OS, InstrInfo.getName(Instr.getOpcode())); + } +} + void Analysis::printSchedClassClustersHtml( const std::vector<SchedClassCluster> &Clusters, const SchedClass &SC, llvm::raw_ostream &OS) const { @@ -195,8 +237,19 @@ void Analysis::printSchedClassClustersHtml( OS << "</td><td><ul>"; for (const size_t PointId : Cluster.getPointIds()) { const auto &Point = Points[PointId]; - OS << "<li><span class=\"mono\">"; - writeEscaped<kEscapeHtml>(OS, Point.Key.OpcodeName); + OS << "<li><span class=\"mono\" title=\""; + writeSnippet<kEscapeHtmlString>(OS, Point.Key.Instructions, *InstrInfo_, "\n"); + OS << "\">"; + switch (Point.Mode) { + case InstructionBenchmark::Latency: + writeLatencySnippetHtml(OS, Point.Key.Instructions, *InstrInfo_); + break; + case InstructionBenchmark::Uops: + writeUopsSnippetHtml(OS, Point.Key.Instructions, *InstrInfo_); + break; + default: + llvm_unreachable("invalid mode"); + } OS << "</span> <span class=\"mono\">"; writeEscaped<kEscapeHtml>(OS, Point.Key.Config); OS << "</span></li>"; |