[llvm] [MISched] Add statistics for heuristics (PR #137981)

Cullen Rhodes via llvm-commits llvm-commits at lists.llvm.org
Fri May 9 00:56:52 PDT 2025


https://github.com/c-rhodes updated https://github.com/llvm/llvm-project/pull/137981

>From 04411f4c518759692e8be75b4f037a2b0d33bab9 Mon Sep 17 00:00:00 2001
From: Cullen Rhodes <cullen.rhodes at arm.com>
Date: Fri, 31 Jan 2025 14:21:49 +0000
Subject: [PATCH] [MISched] Add statistics for heuristics

When diagnosing scheduling issues it can be useful to know which
heuristics are driving the scheduler. This adds pre-RA and post-RA
statistics for all heuristics.
---
 llvm/lib/CodeGen/MachineScheduler.cpp | 241 ++++++++++++++++++++++++--
 1 file changed, 228 insertions(+), 13 deletions(-)

diff --git a/llvm/lib/CodeGen/MachineScheduler.cpp b/llvm/lib/CodeGen/MachineScheduler.cpp
index b8a7eb6b4068b..236c55cb04142 100644
--- a/llvm/lib/CodeGen/MachineScheduler.cpp
+++ b/llvm/lib/CodeGen/MachineScheduler.cpp
@@ -84,6 +84,97 @@ STATISTIC(NumInstrsScheduledPostRA,
           "Number of instructions scheduled by post-RA scheduler");
 STATISTIC(NumClustered, "Number of load/store pairs clustered");
 
+STATISTIC(NumTopPreRA,
+          "Number of scheduling units chosen from top queue pre-RA");
+STATISTIC(NumBotPreRA,
+          "Number of scheduling units chosen from bottom queue pre-RA");
+STATISTIC(NumNoCandPreRA,
+          "Number of scheduling units chosen for NoCand heuristic pre-RA");
+STATISTIC(NumOnly1PreRA,
+          "Number of scheduling units chosen for Only1 heuristic pre-RA");
+STATISTIC(NumPhysRegPreRA,
+          "Number of scheduling units chosen for PhysReg heuristic pre-RA");
+STATISTIC(NumRegExcessPreRA,
+          "Number of scheduling units chosen for RegExcess heuristic pre-RA");
+STATISTIC(NumRegCriticalPreRA,
+          "Number of scheduling units chosen for RegCritical heuristic pre-RA");
+STATISTIC(NumStallPreRA,
+          "Number of scheduling units chosen for Stall heuristic pre-RA");
+STATISTIC(NumClusterPreRA,
+          "Number of scheduling units chosen for Cluster heuristic pre-RA");
+STATISTIC(NumWeakPreRA,
+          "Number of scheduling units chosen for Weak heuristic pre-RA");
+STATISTIC(NumRegMaxPreRA,
+          "Number of scheduling units chosen for RegMax heuristic pre-RA");
+STATISTIC(
+    NumResourceReducePreRA,
+    "Number of scheduling units chosen for ResourceReduce heuristic pre-RA");
+STATISTIC(
+    NumResourceDemandPreRA,
+    "Number of scheduling units chosen for ResourceDemand heuristic pre-RA");
+STATISTIC(
+    NumTopDepthReducePreRA,
+    "Number of scheduling units chosen for TopDepthReduce heuristic pre-RA");
+STATISTIC(
+    NumTopPathReducePreRA,
+    "Number of scheduling units chosen for TopPathReduce heuristic pre-RA");
+STATISTIC(
+    NumBotHeightReducePreRA,
+    "Number of scheduling units chosen for BotHeightReduce heuristic pre-RA");
+STATISTIC(
+    NumBotPathReducePreRA,
+    "Number of scheduling units chosen for BotPathReduce heuristic pre-RA");
+STATISTIC(NumNodeOrderPreRA,
+          "Number of scheduling units chosen for NodeOrder heuristic pre-RA");
+STATISTIC(NumFirstValidPreRA,
+          "Number of scheduling units chosen for FirstValid heuristic pre-RA");
+
+STATISTIC(NumTopPostRA,
+          "Number of scheduling units chosen from top queue post-RA");
+STATISTIC(NumBotPostRA,
+          "Number of scheduling units chosen from bottom queue post-RA");
+STATISTIC(NumNoCandPostRA,
+          "Number of scheduling units chosen for NoCand heuristic post-RA");
+STATISTIC(NumOnly1PostRA,
+          "Number of scheduling units chosen for Only1 heuristic post-RA");
+STATISTIC(NumPhysRegPostRA,
+          "Number of scheduling units chosen for PhysReg heuristic post-RA");
+STATISTIC(NumRegExcessPostRA,
+          "Number of scheduling units chosen for RegExcess heuristic post-RA");
+STATISTIC(
+    NumRegCriticalPostRA,
+    "Number of scheduling units chosen for RegCritical heuristic post-RA");
+STATISTIC(NumStallPostRA,
+          "Number of scheduling units chosen for Stall heuristic post-RA");
+STATISTIC(NumClusterPostRA,
+          "Number of scheduling units chosen for Cluster heuristic post-RA");
+STATISTIC(NumWeakPostRA,
+          "Number of scheduling units chosen for Weak heuristic post-RA");
+STATISTIC(NumRegMaxPostRA,
+          "Number of scheduling units chosen for RegMax heuristic post-RA");
+STATISTIC(
+    NumResourceReducePostRA,
+    "Number of scheduling units chosen for ResourceReduce heuristic post-RA");
+STATISTIC(
+    NumResourceDemandPostRA,
+    "Number of scheduling units chosen for ResourceDemand heuristic post-RA");
+STATISTIC(
+    NumTopDepthReducePostRA,
+    "Number of scheduling units chosen for TopDepthReduce heuristic post-RA");
+STATISTIC(
+    NumTopPathReducePostRA,
+    "Number of scheduling units chosen for TopPathReduce heuristic post-RA");
+STATISTIC(
+    NumBotHeightReducePostRA,
+    "Number of scheduling units chosen for BotHeightReduce heuristic post-RA");
+STATISTIC(
+    NumBotPathReducePostRA,
+    "Number of scheduling units chosen for BotPathReduce heuristic post-RA");
+STATISTIC(NumNodeOrderPostRA,
+          "Number of scheduling units chosen for NodeOrder heuristic post-RA");
+STATISTIC(NumFirstValidPostRA,
+          "Number of scheduling units chosen for FirstValid heuristic post-RA");
+
 namespace llvm {
 
 cl::opt<MISched::Direction> PreRADirection(
@@ -3430,13 +3521,137 @@ bool tryLatency(GenericSchedulerBase::SchedCandidate &TryCand,
 }
 } // end namespace llvm
 
-static void tracePick(GenericSchedulerBase::CandReason Reason, bool IsTop) {
+static void tracePick(GenericSchedulerBase::CandReason Reason, bool IsTop,
+                      bool IsPostRA = false) {
   LLVM_DEBUG(dbgs() << "Pick " << (IsTop ? "Top " : "Bot ")
-                    << GenericSchedulerBase::getReasonStr(Reason) << '\n');
+                    << GenericSchedulerBase::getReasonStr(Reason) << " ["
+                    << (IsPostRA ? "post-RA" : "pre-RA") << "]\n");
+
+  if (IsPostRA) {
+    if (IsTop)
+      NumTopPostRA++;
+    else
+      NumBotPostRA++;
+
+    switch (Reason) {
+    case GenericScheduler::NoCand:
+      NumNoCandPostRA++;
+      return;
+    case GenericScheduler::Only1:
+      NumOnly1PostRA++;
+      return;
+    case GenericScheduler::PhysReg:
+      NumPhysRegPostRA++;
+      return;
+    case GenericScheduler::RegExcess:
+      NumRegExcessPostRA++;
+      return;
+    case GenericScheduler::RegCritical:
+      NumRegCriticalPostRA++;
+      return;
+    case GenericScheduler::Stall:
+      NumStallPostRA++;
+      return;
+    case GenericScheduler::Cluster:
+      NumClusterPostRA++;
+      return;
+    case GenericScheduler::Weak:
+      NumWeakPostRA++;
+      return;
+    case GenericScheduler::RegMax:
+      NumRegMaxPostRA++;
+      return;
+    case GenericScheduler::ResourceReduce:
+      NumResourceReducePostRA++;
+      return;
+    case GenericScheduler::ResourceDemand:
+      NumResourceDemandPostRA++;
+      return;
+    case GenericScheduler::TopDepthReduce:
+      NumTopDepthReducePostRA++;
+      return;
+    case GenericScheduler::TopPathReduce:
+      NumTopPathReducePostRA++;
+      return;
+    case GenericScheduler::BotHeightReduce:
+      NumBotHeightReducePostRA++;
+      return;
+    case GenericScheduler::BotPathReduce:
+      NumBotPathReducePostRA++;
+      return;
+    case GenericScheduler::NodeOrder:
+      NumNodeOrderPostRA++;
+      return;
+    case GenericScheduler::FirstValid:
+      NumFirstValidPostRA++;
+      return;
+    };
+  } else {
+    if (IsTop)
+      NumTopPreRA++;
+    else
+      NumBotPreRA++;
+
+    switch (Reason) {
+    case GenericScheduler::NoCand:
+      NumNoCandPreRA++;
+      return;
+    case GenericScheduler::Only1:
+      NumOnly1PreRA++;
+      return;
+    case GenericScheduler::PhysReg:
+      NumPhysRegPreRA++;
+      return;
+    case GenericScheduler::RegExcess:
+      NumRegExcessPreRA++;
+      return;
+    case GenericScheduler::RegCritical:
+      NumRegCriticalPreRA++;
+      return;
+    case GenericScheduler::Stall:
+      NumStallPreRA++;
+      return;
+    case GenericScheduler::Cluster:
+      NumClusterPreRA++;
+      return;
+    case GenericScheduler::Weak:
+      NumWeakPreRA++;
+      return;
+    case GenericScheduler::RegMax:
+      NumRegMaxPreRA++;
+      return;
+    case GenericScheduler::ResourceReduce:
+      NumResourceReducePreRA++;
+      return;
+    case GenericScheduler::ResourceDemand:
+      NumResourceDemandPreRA++;
+      return;
+    case GenericScheduler::TopDepthReduce:
+      NumTopDepthReducePreRA++;
+      return;
+    case GenericScheduler::TopPathReduce:
+      NumTopPathReducePreRA++;
+      return;
+    case GenericScheduler::BotHeightReduce:
+      NumBotHeightReducePreRA++;
+      return;
+    case GenericScheduler::BotPathReduce:
+      NumBotPathReducePreRA++;
+      return;
+    case GenericScheduler::NodeOrder:
+      NumNodeOrderPreRA++;
+      return;
+    case GenericScheduler::FirstValid:
+      NumFirstValidPreRA++;
+      return;
+    };
+  }
+  llvm_unreachable("Unknown reason!");
 }
 
-static void tracePick(const GenericSchedulerBase::SchedCandidate &Cand) {
-  tracePick(Cand.Reason, Cand.AtTop);
+static void tracePick(const GenericSchedulerBase::SchedCandidate &Cand,
+                      bool IsPostRA = false) {
+  tracePick(Cand.Reason, Cand.AtTop, IsPostRA);
 }
 
 void GenericScheduler::initialize(ScheduleDAGMI *dag) {
@@ -3862,12 +4077,12 @@ SUnit *GenericScheduler::pickNodeBidirectional(bool &IsTopNode) {
   // efficient, but also provides the best heuristics for CriticalPSets.
   if (SUnit *SU = Bot.pickOnlyChoice()) {
     IsTopNode = false;
-    tracePick(Only1, false);
+    tracePick(Only1, /*IsTopNode=*/false);
     return SU;
   }
   if (SUnit *SU = Top.pickOnlyChoice()) {
     IsTopNode = true;
-    tracePick(Only1, true);
+    tracePick(Only1, /*IsTopNode=*/true);
     return SU;
   }
   // Set the bottom-up policy based on the state of the current bottom zone and
@@ -4224,12 +4439,12 @@ SUnit *PostGenericScheduler::pickNodeBidirectional(bool &IsTopNode) {
   // efficient, but also provides the best heuristics for CriticalPSets.
   if (SUnit *SU = Bot.pickOnlyChoice()) {
     IsTopNode = false;
-    tracePick(Only1, false);
+    tracePick(Only1, /*IsTopNode=*/false, /*IsPostRA=*/true);
     return SU;
   }
   if (SUnit *SU = Top.pickOnlyChoice()) {
     IsTopNode = true;
-    tracePick(Only1, true);
+    tracePick(Only1, /*IsTopNode=*/true, /*IsPostRA=*/true);
     return SU;
   }
   // Set the bottom-up policy based on the state of the current bottom zone and
@@ -4292,7 +4507,7 @@ SUnit *PostGenericScheduler::pickNodeBidirectional(bool &IsTopNode) {
   }
 
   IsTopNode = Cand.AtTop;
-  tracePick(Cand);
+  tracePick(Cand, /*IsPostRA=*/true);
   return Cand.SU;
 }
 
@@ -4308,7 +4523,7 @@ SUnit *PostGenericScheduler::pickNode(bool &IsTopNode) {
     if (RegionPolicy.OnlyBottomUp) {
       SU = Bot.pickOnlyChoice();
       if (SU) {
-        tracePick(Only1, true);
+        tracePick(Only1, /*IsTopNode=*/true, /*IsPostRA=*/true);
       } else {
         CandPolicy NoPolicy;
         BotCand.reset(NoPolicy);
@@ -4317,14 +4532,14 @@ SUnit *PostGenericScheduler::pickNode(bool &IsTopNode) {
         setPolicy(BotCand.Policy, /*IsPostRA=*/true, Bot, nullptr);
         pickNodeFromQueue(Bot, BotCand);
         assert(BotCand.Reason != NoCand && "failed to find a candidate");
-        tracePick(BotCand);
+        tracePick(BotCand, /*IsPostRA=*/true);
         SU = BotCand.SU;
       }
       IsTopNode = false;
     } else if (RegionPolicy.OnlyTopDown) {
       SU = Top.pickOnlyChoice();
       if (SU) {
-        tracePick(Only1, true);
+        tracePick(Only1, /*IsTopNode=*/true, /*IsPostRA=*/true);
       } else {
         CandPolicy NoPolicy;
         TopCand.reset(NoPolicy);
@@ -4333,7 +4548,7 @@ SUnit *PostGenericScheduler::pickNode(bool &IsTopNode) {
         setPolicy(TopCand.Policy, /*IsPostRA=*/true, Top, nullptr);
         pickNodeFromQueue(Top, TopCand);
         assert(TopCand.Reason != NoCand && "failed to find a candidate");
-        tracePick(TopCand);
+        tracePick(TopCand, /*IsPostRA=*/true);
         SU = TopCand.SU;
       }
       IsTopNode = true;



More information about the llvm-commits mailing list