From 0ba5b5b01b0d5a2b42dc39c643c73dd718b59e4b Mon Sep 17 00:00:00 2001 From: Clement Courbet Date: Thu, 24 May 2018 10:47:05 +0000 Subject: [PATCH] [llvm-exegesis] Show sched class details in analysis. Summary: And update docs. Reviewers: gchatelet Subscribers: tschuett, craig.topper, RKSimon, llvm-commits Differential Revision: https://reviews.llvm.org/D47254 llvm-svn: 333169 --- docs/CommandGuide/llvm-exegesis-analysis.png | Bin 0 -> 34817 bytes docs/CommandGuide/llvm-exegesis.rst | 16 +- tools/llvm-exegesis/lib/Analysis.cpp | 152 +++++++++++++++++-- tools/llvm-exegesis/lib/Analysis.h | 6 +- 4 files changed, 145 insertions(+), 29 deletions(-) create mode 100644 docs/CommandGuide/llvm-exegesis-analysis.png diff --git a/docs/CommandGuide/llvm-exegesis-analysis.png b/docs/CommandGuide/llvm-exegesis-analysis.png new file mode 100644 index 0000000000000000000000000000000000000000..e232f5f123559a7f91b13ba214e9d60e14f4508e GIT binary patch literal 34817 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 literal 0 HcmV?d00001 diff --git a/docs/CommandGuide/llvm-exegesis.rst b/docs/CommandGuide/llvm-exegesis.rst index 9f81bef148d..bd7132700d0 100644 --- a/docs/CommandGuide/llvm-exegesis.rst +++ b/docs/CommandGuide/llvm-exegesis.rst @@ -113,20 +113,10 @@ following format: :program:`llvm-exegesis` will also analyze the clusters to point out inconsistencies in the scheduling information. The output is an html file. For -example, `/tmp/inconsistencies.html` will contain messages like: +example, `/tmp/inconsistencies.html` will contain messages like the following : -.. code-block:: none - - Sched Class EXTRACTPSrr_VEXTRACTPSrr contains instructions with distinct performance characteristics, falling into 2 clusters: - 4,EXTRACTPSrr,,3.00 - 3,VEXTRACTPSrr,,2.01 - - Sched Class WriteCRC32 contains instructions with distinct performance characteristics, falling into 2 clusters: - 4,CRC32r32r16,,3.01 - 4,CRC32r32r32,,3.00 - 11,CRC32r32r8,,4.01 - 4,CRC32r64r64,,3.01 - 4,CRC32r64r8,,3.00 +.. image:: llvm-exegesis-analysis.png + :align: center Note that the scheduling class names will be resolved only when :program:`llvm-exegesis` is compiled in debug mode, else only the class id will diff --git a/tools/llvm-exegesis/lib/Analysis.cpp b/tools/llvm-exegesis/lib/Analysis.cpp index cb3800e7db5..b709dc9378a 100644 --- a/tools/llvm-exegesis/lib/Analysis.cpp +++ b/tools/llvm-exegesis/lib/Analysis.cpp @@ -167,8 +167,8 @@ Analysis::makePointsPerSchedClass() const { return PointsPerSchedClass; } -void Analysis::printSchedClassHtml(std::vector PointIds, - llvm::raw_ostream &OS) const { +void Analysis::printSchedClassClustersHtml(std::vector PointIds, + llvm::raw_ostream &OS) const { assert(!PointIds.empty()); // Sort the points by cluster id so that we can display them grouped by // cluster. @@ -178,7 +178,7 @@ void Analysis::printSchedClassHtml(std::vector PointIds, Clustering_.getClusterIdForPoint(B); }); const auto &Points = Clustering_.getPoints(); - OS << ""; + OS << "
"; OS << ""; for (const auto &Measurement : Points[PointIds[0]].Measurements) { OS << "
ClusterIdOpcode/Config"; @@ -214,6 +214,120 @@ void Analysis::printSchedClassHtml(std::vector PointIds, OS << "
"; } +// Return the non-redundant list of WriteProcRes used by the given sched class. +// The scheduling model for LLVM is such that each instruction has a certain +// number of uops which consume resources which are described by WriteProcRes +// entries. Each entry describe how many cycles are spent on a specific ProcRes +// kind. +// For example, an instruction might have 3 uOps, one dispatching on P0 +// (ProcResIdx=1) and two on P06 (ProcResIdx = 7). +// Note that LLVM additionally denormalizes resource consumption to include +// usage of super resources by subresources. So in practice if there exists a +// P016 (ProcResIdx=10), then the cycles consumed by P0 are also consumed by +// P06 (ProcResIdx = 7) and P016 (ProcResIdx = 10), and the resources consumed +// by P06 are also consumed by P016. In the figure below, parenthesized cycles +// denote implied usage of superresources by subresources: +// P0 P06 P016 +// uOp1 1 (1) (1) +// uOp2 1 (1) +// uOp3 1 (1) +// ============================= +// 1 3 3 +// Eventually we end up with three entries for the WriteProcRes of the +// instruction: +// {ProcResIdx=1, Cycles=1} // P0 +// {ProcResIdx=7, Cycles=3} // P06 +// {ProcResIdx=10, Cycles=3} // P016 +// +// Note that in this case, P016 does not contribute any cycles, so it would +// be removed by this function. +// FIXME: Move this to MCSubtargetInfo and use it in llvm-mca. +static llvm::SmallVector +getNonRedundantWriteProcRes(const llvm::MCSchedClassDesc &SCDesc, + const llvm::MCSubtargetInfo &STI) { + llvm::SmallVector Result; + const auto &SM = STI.getSchedModel(); + const unsigned NumProcRes = SM.getNumProcResourceKinds(); + + // This assumes that the ProcResDescs are sorted in topological order, which + // is guaranteed by the tablegen backend. + llvm::SmallVector ProcResUnitUsage(NumProcRes); + for (const auto *WPR = STI.getWriteProcResBegin(&SCDesc), + *const WPREnd = STI.getWriteProcResEnd(&SCDesc); + WPR != WPREnd; ++WPR) { + const llvm::MCProcResourceDesc *const ProcResDesc = + SM.getProcResource(WPR->ProcResourceIdx); + if (ProcResDesc->SubUnitsIdxBegin == nullptr) { + // This is a ProcResUnit. + Result.push_back({WPR->ProcResourceIdx, WPR->Cycles}); + ProcResUnitUsage[WPR->ProcResourceIdx] += WPR->Cycles; + } else { + // This is a ProcResGroup. First see if it contributes any cycles or if + // it has cycles just from subunits. + float RemainingCycles = WPR->Cycles; + for (const auto *SubResIdx = ProcResDesc->SubUnitsIdxBegin; + SubResIdx != ProcResDesc->SubUnitsIdxBegin + ProcResDesc->NumUnits; + ++SubResIdx) { + RemainingCycles -= ProcResUnitUsage[*SubResIdx]; + } + if (RemainingCycles < 0.01f) { + // The ProcResGroup contributes no cycles of its own. + continue; + } + // The ProcResGroup contributes `RemainingCycles` cycles of its own. + Result.push_back({WPR->ProcResourceIdx, + static_cast(std::round(RemainingCycles))}); + // Spread the remaining cycles over all subunits. + for (const auto *SubResIdx = ProcResDesc->SubUnitsIdxBegin; + SubResIdx != ProcResDesc->SubUnitsIdxBegin + ProcResDesc->NumUnits; + ++SubResIdx) { + ProcResUnitUsage[*SubResIdx] += RemainingCycles / ProcResDesc->NumUnits; + } + } + } + return Result; +} + +void Analysis::printSchedClassDescHtml(const llvm::MCSchedClassDesc &SCDesc, + llvm::raw_ostream &OS) const { + OS << ""; + OS << ""; + if (SCDesc.isValid()) { + OS << ""; + OS << ""; + OS << ""; + // Latencies. + OS << ""; + // WriteProcRes. + OS << ""; + OS << ""; + } else { + OS << ""; + } + OS << "
ValidVariantuOpsLatencyWriteProcRes
" << (SCDesc.isVariant() ? "✔" : "✕") << "" << SCDesc.NumMicroOps << "
    "; + for (int I = 0, E = SCDesc.NumWriteLatencyEntries; I < E; ++I) { + const auto *const Entry = + SubtargetInfo_->getWriteLatencyEntry(&SCDesc, I); + OS << "
  • " << Entry->Cycles; + if (SCDesc.NumWriteLatencyEntries > 1) { + // Dismabiguate if more than 1 latency. + OS << " (WriteResourceID " << Entry->WriteResourceID << ")"; + } + OS << "
  • "; + } + OS << "
    "; + for (const auto &WPR : + getNonRedundantWriteProcRes(SCDesc, *SubtargetInfo_)) { + OS << "
  • "; + writeEscaped(OS, SubtargetInfo_->getSchedModel() + .getProcResource(WPR.ProcResourceIdx) + ->Name); + OS << ": " << WPR.Cycles << "
  • "; + } + OS << "
"; +} + static constexpr const char kHtmlHead[] = R"( llvm-exegesis Analysis Results @@ -234,23 +348,29 @@ span.config { div.inconsistency { margin-top: 50px; } -table.sched-class { +table { margin-left: 50px; border-collapse: collapse; } -table.sched-class, table.sched-class tr,td,th { +table, table tr,td,th { border: 1px solid #444; } -table.sched-class td { +table ul { + padding-left: 0px; + margin: 0px; + list-style-type: none; +} +table.sched-class-clusters td { padding-left: 10px; padding-right: 10px; padding-top: 10px; padding-bottom: 10px; } -table.sched-class ul { - padding-left: 0px; - margin: 0px; - list-style-type: none; +table.sched-class-desc td { + padding-left: 10px; + padding-right: 10px; + padding-top: 2px; + padding-bottom: 2px; } span.mono { font-family: monospace; @@ -284,12 +404,14 @@ llvm::Error Analysis::run( if (ClustersForSchedClass.size() <= 1) continue; // Nothing weird. - OS << "

Sched Class "; -#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) const auto &SchedModel = SubtargetInfo_->getSchedModel(); const llvm::MCSchedClassDesc *const SCDesc = SchedModel.getSchedClassDesc(SchedClassAndPoints.first); + if (!SCDesc) + continue; + OS << "

Sched Class "; +#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) writeEscaped(OS, SCDesc->Name); #else OS << SchedClassAndPoints.first; @@ -297,7 +419,9 @@ llvm::Error Analysis::run( OS << " contains instructions with distinct performance " "characteristics, falling into " << ClustersForSchedClass.size() << " clusters:

"; - printSchedClassHtml(SchedClassAndPoints.second, OS); + printSchedClassClustersHtml(SchedClassAndPoints.second, OS); + OS << "

llvm data:

"; + printSchedClassDescHtml(*SCDesc, OS); OS << "
"; } diff --git a/tools/llvm-exegesis/lib/Analysis.h b/tools/llvm-exegesis/lib/Analysis.h index ef9ded7ad3a..cb3ef30f0a5 100644 --- a/tools/llvm-exegesis/lib/Analysis.h +++ b/tools/llvm-exegesis/lib/Analysis.h @@ -42,8 +42,10 @@ public: private: void printInstructionRowCsv(size_t PointId, llvm::raw_ostream &OS) const; - void printSchedClassHtml(std::vector PointIds, - llvm::raw_ostream &OS) const; + void printSchedClassClustersHtml(std::vector PointIds, + llvm::raw_ostream &OS) const; + void printSchedClassDescHtml(const llvm::MCSchedClassDesc &SCDesc, + llvm::raw_ostream &OS) const; // Builds a map of Sched Class -> indices of points that belong to the sched // class.