From 42386dc46d8217b2dfed8dfc41afeec366ec2015 Mon Sep 17 00:00:00 2001 From: Phil Camp Date: Mon, 19 Aug 2024 17:16:19 +0100 Subject: [PATCH] [llvm-mca] Add bottle-neck analysis to JSON output. (#90056) This patch implements the bottle-neck analysis data in the JSON dump mode. --- .../llvm-mca/JSON/X86/views-bottleneck.s | 73 +++++++++++++++++++ .../JSON/X86/views-custom-parameters.s | 3 + .../X86/views-multiple-anonymous-regions.s | 69 ++++++++++++++++++ .../llvm-mca/JSON/X86/views-multiple-region.s | 26 +++++++ llvm/test/tools/llvm-mca/JSON/X86/views.s | 3 + .../llvm-mca/Views/BottleneckAnalysis.cpp | 46 ++++++++++++ .../tools/llvm-mca/Views/BottleneckAnalysis.h | 3 +- 7 files changed, 222 insertions(+), 1 deletion(-) create mode 100644 llvm/test/tools/llvm-mca/JSON/X86/views-bottleneck.s diff --git a/llvm/test/tools/llvm-mca/JSON/X86/views-bottleneck.s b/llvm/test/tools/llvm-mca/JSON/X86/views-bottleneck.s new file mode 100644 index 000000000000..c8ad60ee5420 --- /dev/null +++ b/llvm/test/tools/llvm-mca/JSON/X86/views-bottleneck.s @@ -0,0 +1,73 @@ +# NOTE: Assertions have been autogenerated by utils/update_mca_test_checks.py +# RUN: llvm-mca -mtriple=x86_64-unknown-unknown -mcpu=haswell --json --timeline-max-iterations=1 --bottleneck-analysis --resource-pressure=false --instruction-info=false < %s | FileCheck %s +vaddps %xmm0, %xmm0, %xmm1 +vblendvps %xmm1, (%rdi), %xmm2, %xmm3 + +# CHECK: { +# CHECK-NEXT: "CodeRegions": [ +# CHECK-NEXT: { +# CHECK-NEXT: "BottleneckAnalysis": { +# CHECK-NEXT: "DataDependencyCycles": 0, +# CHECK-NEXT: "DependencyEdge": [ +# CHECK-NEXT: { +# CHECK-NEXT: "FromID": 1, +# CHECK-NEXT: "ResourceOrRegID": 128, +# CHECK-NEXT: "ToID": 3, +# CHECK-NEXT: "Type": 3 +# CHECK-NEXT: }, +# CHECK-NEXT: { +# CHECK-NEXT: "FromID": 3, +# CHECK-NEXT: "ResourceOrRegID": 128, +# CHECK-NEXT: "ToID": 5, +# CHECK-NEXT: "Type": 3 +# CHECK-NEXT: } +# CHECK-NEXT: ], +# CHECK-NEXT: "MemoryDependencyCycles": 0, +# CHECK-NEXT: "PressureIncreaseCycles": 56, +# CHECK-NEXT: "RegisterDependencyCycles": 0, +# CHECK-NEXT: "ResourcePressure": [ +# CHECK-NEXT: { +# CHECK-NEXT: "HWPort5": 56 +# CHECK-NEXT: } +# CHECK-NEXT: ], +# CHECK-NEXT: "ResourcePressureCycles": 56, +# CHECK-NEXT: "TotalCycles": 209 +# CHECK-NEXT: }, +# CHECK-NEXT: "Instructions": [ +# CHECK-NEXT: "vaddps\t%xmm0, %xmm0, %xmm1", +# CHECK-NEXT: "vblendvps\t%xmm1, (%rdi), %xmm2, %xmm3" +# CHECK-NEXT: ], +# CHECK-NEXT: "Name": "", +# CHECK-NEXT: "SummaryView": { +# CHECK-NEXT: "BlockRThroughput": 2, +# CHECK-NEXT: "DispatchWidth": 4, +# CHECK-NEXT: "IPC": 0.9569377990430622, +# CHECK-NEXT: "Instructions": 200, +# CHECK-NEXT: "Iterations": 100, +# CHECK-NEXT: "TotalCycles": 209, +# CHECK-NEXT: "TotaluOps": 400, +# CHECK-NEXT: "uOpsPerCycle": 1.9138755980861244 +# CHECK-NEXT: } +# CHECK-NEXT: } +# CHECK-NEXT: ], +# CHECK-NEXT: "SimulationParameters": { +# CHECK-NEXT: "-march": "x86_64", +# CHECK-NEXT: "-mcpu": "haswell", +# CHECK-NEXT: "-mtriple": "x86_64-unknown-unknown" +# CHECK-NEXT: }, +# CHECK-NEXT: "TargetInfo": { +# CHECK-NEXT: "CPUName": "haswell", +# CHECK-NEXT: "Resources": [ +# CHECK-NEXT: "HWDivider", +# CHECK-NEXT: "HWFPDivider", +# CHECK-NEXT: "HWPort0", +# CHECK-NEXT: "HWPort1", +# CHECK-NEXT: "HWPort2", +# CHECK-NEXT: "HWPort3", +# CHECK-NEXT: "HWPort4", +# CHECK-NEXT: "HWPort5", +# CHECK-NEXT: "HWPort6", +# CHECK-NEXT: "HWPort7" +# CHECK-NEXT: ] +# CHECK-NEXT: } +# CHECK-NEXT: } diff --git a/llvm/test/tools/llvm-mca/JSON/X86/views-custom-parameters.s b/llvm/test/tools/llvm-mca/JSON/X86/views-custom-parameters.s index 1301c4acda83..538175f6ac61 100644 --- a/llvm/test/tools/llvm-mca/JSON/X86/views-custom-parameters.s +++ b/llvm/test/tools/llvm-mca/JSON/X86/views-custom-parameters.s @@ -16,6 +16,9 @@ add %edx, %edx # CHECK: { # CHECK-NEXT: "CodeRegions": [ # CHECK-NEXT: { +# CHECK-NEXT: "BottleneckAnalysis": { +# CHECK-NEXT: "PressureIncreaseCycles": 0 +# CHECK-NEXT: }, # CHECK-NEXT: "DispatchStatistics": { # CHECK-NEXT: "GROUP": 0, # CHECK-NEXT: "LQ": 0, diff --git a/llvm/test/tools/llvm-mca/JSON/X86/views-multiple-anonymous-regions.s b/llvm/test/tools/llvm-mca/JSON/X86/views-multiple-anonymous-regions.s index 8cd8d41a6ff6..ea9dbb632d7c 100644 --- a/llvm/test/tools/llvm-mca/JSON/X86/views-multiple-anonymous-regions.s +++ b/llvm/test/tools/llvm-mca/JSON/X86/views-multiple-anonymous-regions.s @@ -19,6 +19,29 @@ add %edx, %edx # CHECK: { # CHECK-NEXT: "CodeRegions": [ # CHECK-NEXT: { +# CHECK-NEXT: "BottleneckAnalysis": { +# CHECK-NEXT: "DataDependencyCycles": 39, +# CHECK-NEXT: "DependencyEdge": [ +# CHECK-NEXT: { +# CHECK-NEXT: "FromID": 0, +# CHECK-NEXT: "ResourceOrRegID": 22, +# CHECK-NEXT: "ToID": 1, +# CHECK-NEXT: "Type": 1 +# CHECK-NEXT: }, +# CHECK-NEXT: { +# CHECK-NEXT: "FromID": 1, +# CHECK-NEXT: "ResourceOrRegID": 22, +# CHECK-NEXT: "ToID": 2, +# CHECK-NEXT: "Type": 1 +# CHECK-NEXT: } +# CHECK-NEXT: ], +# CHECK-NEXT: "MemoryDependencyCycles": 0, +# CHECK-NEXT: "PressureIncreaseCycles": 39, +# CHECK-NEXT: "RegisterDependencyCycles": 39, +# CHECK-NEXT: "ResourcePressure": [], +# CHECK-NEXT: "ResourcePressureCycles": 0, +# CHECK-NEXT: "TotalCycles": 103 +# CHECK-NEXT: }, # CHECK-NEXT: "DispatchStatistics": { # CHECK-NEXT: "GROUP": 0, # CHECK-NEXT: "LQ": 0, @@ -175,6 +198,29 @@ add %edx, %edx # CHECK-NEXT: } # CHECK-NEXT: }, # CHECK-NEXT: { +# CHECK-NEXT: "BottleneckAnalysis": { +# CHECK-NEXT: "DataDependencyCycles": 69, +# CHECK-NEXT: "DependencyEdge": [ +# CHECK-NEXT: { +# CHECK-NEXT: "FromID": 0, +# CHECK-NEXT: "ResourceOrRegID": 24, +# CHECK-NEXT: "ToID": 2, +# CHECK-NEXT: "Type": 1 +# CHECK-NEXT: }, +# CHECK-NEXT: { +# CHECK-NEXT: "FromID": 2, +# CHECK-NEXT: "ResourceOrRegID": 24, +# CHECK-NEXT: "ToID": 4, +# CHECK-NEXT: "Type": 1 +# CHECK-NEXT: } +# CHECK-NEXT: ], +# CHECK-NEXT: "MemoryDependencyCycles": 0, +# CHECK-NEXT: "PressureIncreaseCycles": 69, +# CHECK-NEXT: "RegisterDependencyCycles": 69, +# CHECK-NEXT: "ResourcePressure": [], +# CHECK-NEXT: "ResourcePressureCycles": 0, +# CHECK-NEXT: "TotalCycles": 103 +# CHECK-NEXT: }, # CHECK-NEXT: "DispatchStatistics": { # CHECK-NEXT: "GROUP": 0, # CHECK-NEXT: "LQ": 0, @@ -411,6 +457,29 @@ add %edx, %edx # CHECK-NEXT: } # CHECK-NEXT: }, # CHECK-NEXT: { +# CHECK-NEXT: "BottleneckAnalysis": { +# CHECK-NEXT: "DataDependencyCycles": 39, +# CHECK-NEXT: "DependencyEdge": [ +# CHECK-NEXT: { +# CHECK-NEXT: "FromID": 0, +# CHECK-NEXT: "ResourceOrRegID": 27, +# CHECK-NEXT: "ToID": 1, +# CHECK-NEXT: "Type": 1 +# CHECK-NEXT: }, +# CHECK-NEXT: { +# CHECK-NEXT: "FromID": 1, +# CHECK-NEXT: "ResourceOrRegID": 27, +# CHECK-NEXT: "ToID": 2, +# CHECK-NEXT: "Type": 1 +# CHECK-NEXT: } +# CHECK-NEXT: ], +# CHECK-NEXT: "MemoryDependencyCycles": 0, +# CHECK-NEXT: "PressureIncreaseCycles": 39, +# CHECK-NEXT: "RegisterDependencyCycles": 39, +# CHECK-NEXT: "ResourcePressure": [], +# CHECK-NEXT: "ResourcePressureCycles": 0, +# CHECK-NEXT: "TotalCycles": 103 +# CHECK-NEXT: }, # CHECK-NEXT: "DispatchStatistics": { # CHECK-NEXT: "GROUP": 0, # CHECK-NEXT: "LQ": 0, diff --git a/llvm/test/tools/llvm-mca/JSON/X86/views-multiple-region.s b/llvm/test/tools/llvm-mca/JSON/X86/views-multiple-region.s index 0b7bb16beeb9..a000e9b7d217 100644 --- a/llvm/test/tools/llvm-mca/JSON/X86/views-multiple-region.s +++ b/llvm/test/tools/llvm-mca/JSON/X86/views-multiple-region.s @@ -20,6 +20,9 @@ add %edx, %edx # CHECK: { # CHECK-NEXT: "CodeRegions": [ # CHECK-NEXT: { +# CHECK-NEXT: "BottleneckAnalysis": { +# CHECK-NEXT: "PressureIncreaseCycles": 0 +# CHECK-NEXT: }, # CHECK-NEXT: "DispatchStatistics": { # CHECK-NEXT: "GROUP": 0, # CHECK-NEXT: "LQ": 0, @@ -164,6 +167,29 @@ add %edx, %edx # CHECK-NEXT: } # CHECK-NEXT: }, # CHECK-NEXT: { +# CHECK-NEXT: "BottleneckAnalysis": { +# CHECK-NEXT: "DataDependencyCycles": 69, +# CHECK-NEXT: "DependencyEdge": [ +# CHECK-NEXT: { +# CHECK-NEXT: "FromID": 0, +# CHECK-NEXT: "ResourceOrRegID": 24, +# CHECK-NEXT: "ToID": 2, +# CHECK-NEXT: "Type": 1 +# CHECK-NEXT: }, +# CHECK-NEXT: { +# CHECK-NEXT: "FromID": 2, +# CHECK-NEXT: "ResourceOrRegID": 24, +# CHECK-NEXT: "ToID": 4, +# CHECK-NEXT: "Type": 1 +# CHECK-NEXT: } +# CHECK-NEXT: ], +# CHECK-NEXT: "MemoryDependencyCycles": 0, +# CHECK-NEXT: "PressureIncreaseCycles": 69, +# CHECK-NEXT: "RegisterDependencyCycles": 69, +# CHECK-NEXT: "ResourcePressure": [], +# CHECK-NEXT: "ResourcePressureCycles": 0, +# CHECK-NEXT: "TotalCycles": 103 +# CHECK-NEXT: }, # CHECK-NEXT: "DispatchStatistics": { # CHECK-NEXT: "GROUP": 0, # CHECK-NEXT: "LQ": 0, diff --git a/llvm/test/tools/llvm-mca/JSON/X86/views.s b/llvm/test/tools/llvm-mca/JSON/X86/views.s index df85f2203f31..324d7b8efa07 100644 --- a/llvm/test/tools/llvm-mca/JSON/X86/views.s +++ b/llvm/test/tools/llvm-mca/JSON/X86/views.s @@ -16,6 +16,9 @@ add %edx, %edx # CHECK: { # CHECK-NEXT: "CodeRegions": [ # CHECK-NEXT: { +# CHECK-NEXT: "BottleneckAnalysis": { +# CHECK-NEXT: "PressureIncreaseCycles": 0 +# CHECK-NEXT: }, # CHECK-NEXT: "DispatchStatistics": { # CHECK-NEXT: "GROUP": 0, # CHECK-NEXT: "LQ": 0, diff --git a/llvm/tools/llvm-mca/Views/BottleneckAnalysis.cpp b/llvm/tools/llvm-mca/Views/BottleneckAnalysis.cpp index 409a7010b80c..ece5b6709a2e 100644 --- a/llvm/tools/llvm-mca/Views/BottleneckAnalysis.cpp +++ b/llvm/tools/llvm-mca/Views/BottleneckAnalysis.cpp @@ -641,5 +641,51 @@ void BottleneckAnalysis::printView(raw_ostream &OS) const { printCriticalSequence(OS); } +json::Value BottleneckAnalysis::toJSON() const { + if (!SeenStallCycles || !BPI.PressureIncreaseCycles) { + json::Object JO({{"PressureIncreaseCycles", 0}}); + return JO; + } + + json::Array CriticalSequence; + // get critical sequence + SmallVector Seq; + DG.getCriticalSequence(Seq); + if (!Seq.empty()) { + for (const DependencyEdge *&DE : Seq) { + json::Object DEJO({{"FromID", DE->FromIID}, + {"ToID", DE->ToIID}, + {"Type", static_cast(DE->Dep.Type)}, + {"ResourceOrRegID", DE->Dep.ResourceOrRegID}}); + CriticalSequence.push_back(std::move(DEJO)); + } + } + + json::Array ResourcePressure; + if (BPI.PressureIncreaseCycles) { + ArrayRef Distribution = Tracker.getResourcePressureDistribution(); + const MCSchedModel &SM = getSubTargetInfo().getSchedModel(); + for (unsigned I = 0, E = Distribution.size(); I < E; ++I) { + unsigned ReleaseAtCycles = Distribution[I]; + if (ReleaseAtCycles) { + const MCProcResourceDesc &PRDesc = *SM.getProcResource(I); + json::Object RPJO({{PRDesc.Name, ReleaseAtCycles}}); + ResourcePressure.push_back(std::move(RPJO)); + } + } + } + + json::Object JO({{"PressureIncreaseCycles", BPI.PressureIncreaseCycles}, + {"ResourcePressureCycles", BPI.ResourcePressureCycles}, + {"DataDependencyCycles", BPI.DataDependencyCycles}, + {"RegisterDependencyCycles", BPI.RegisterDependencyCycles}, + {"MemoryDependencyCycles", BPI.MemoryDependencyCycles}, + {"TotalCycles", TotalCycles}, + {"DependencyEdge", std::move(CriticalSequence)}, + {"ResourcePressure", std::move(ResourcePressure)}}); + + return JO; +} + } // namespace mca. } // namespace llvm diff --git a/llvm/tools/llvm-mca/Views/BottleneckAnalysis.h b/llvm/tools/llvm-mca/Views/BottleneckAnalysis.h index e709b25c3f76..529090cf543f 100644 --- a/llvm/tools/llvm-mca/Views/BottleneckAnalysis.h +++ b/llvm/tools/llvm-mca/Views/BottleneckAnalysis.h @@ -335,7 +335,8 @@ public: void printView(raw_ostream &OS) const override; StringRef getNameAsString() const override { return "BottleneckAnalysis"; } - bool isSerializable() const override { return false; } + bool isSerializable() const override { return true; } + json::Value toJSON() const override; #ifndef NDEBUG void dump(raw_ostream &OS, MCInstPrinter &MCIP) const { DG.dump(OS, MCIP); }