[llvm-branch-commits] [llvm] [AMDGPU] Allow MachinePipeliner to consider loops with large MIIs (PR #212537)

via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Tue Aug 11 13:53:11 PDT 2026


https://github.com/hjagasiaAMD updated https://github.com/llvm/llvm-project/pull/212537

>From 1c3c31110817e90f69900ddd9bdf06aad0c30709 Mon Sep 17 00:00:00 2001
From: Harsha Jagasia <harsha.jagasia at amd.com>
Date: Tue, 11 Aug 2026 14:55:30 -0500
Subject: [PATCH] [MachinePipeliner] Let targets configure the maximum MII

The pipeliner rejects a loop whose minimum initiation interval exceeds
-pipeliner-max-mii. Its default of 27 suits targets with short instruction
latencies, but is too small for others: on AMDGPU a couple of MFMA
instructions already push the MII past it, so the loop never pipelines.

Move the limit into a MachinePipelinerPolicy that targets customize by
implementing TargetSubtargetInfo::overridePipelinerPolicy(). The generic
default is unchanged and an explicit -pipeliner-max-mii still wins over the
target's choice, so no target changes behavior here. Exercised by the AMDGPU
adoption in a following commit.
---
 llvm/include/llvm/CodeGen/MachinePipeliner.h    | 14 ++++++++++++++
 llvm/include/llvm/CodeGen/TargetSubtargetInfo.h |  4 ++++
 llvm/lib/CodeGen/MachinePipeliner.cpp           | 15 ++++++++++++---
 3 files changed, 30 insertions(+), 3 deletions(-)

diff --git a/llvm/include/llvm/CodeGen/MachinePipeliner.h b/llvm/include/llvm/CodeGen/MachinePipeliner.h
index 19699f069ae72..41ab7c6891bb1 100644
--- a/llvm/include/llvm/CodeGen/MachinePipeliner.h
+++ b/llvm/include/llvm/CodeGen/MachinePipeliner.h
@@ -63,6 +63,14 @@ class SMSchedule;
 extern LLVM_ABI cl::opt<bool> SwpEnableCopyToPhi;
 extern LLVM_ABI cl::opt<int> SwpForceIssueWidth;
 
+/// Software pipelining policy for a loop, which a target can customize by
+/// implementing TargetSubtargetInfo::overridePipelinerPolicy.
+struct MachinePipelinerPolicy {
+  /// Don't pipeline loops whose minimum initiation interval exceeds this.
+  /// Overridden by -pipeliner-max-mii when that is passed.
+  int MaxMII = 27;
+};
+
 /// The main class in the implementation of the target independent
 /// software pipeliner pass.
 class LLVM_ABI MachinePipeliner : public MachineFunctionPass {
@@ -296,6 +304,9 @@ class LLVM_ABI SwingSchedulerDAG : public ScheduleDAGInstrs {
   unsigned II_setByPragma = 0;
   TargetInstrInfo::PipelinerLoopInfo *LoopPipelinerInfo = nullptr;
 
+  /// Policy for this loop, after target and command line overrides.
+  MachinePipelinerPolicy Policy;
+
   /// A topological ordering of the SUnits, which is needed for changing
   /// dependences and iterating over the SUnits.
   ScheduleDAGTopologicalSort Topo;
@@ -387,6 +398,7 @@ class LLVM_ABI SwingSchedulerDAG : public ScheduleDAGInstrs {
       : ScheduleDAGInstrs(*P.MF, P.MLI, false), Pass(P), Loop(L), LIS(lis),
         RegClassInfo(rci), II_setByPragma(II), LoopPipelinerInfo(PLI),
         Topo(SUnits, &ExitSU), AA(AA), BAA(*AA) {
+    initPolicy();
     P.MF->getSubtarget().getSMSMutations(Mutations);
     if (SwpEnableCopyToPhi)
       Mutations.push_back(std::make_unique<CopyToPhiMutation>());
@@ -453,6 +465,8 @@ class LLVM_ABI SwingSchedulerDAG : public ScheduleDAGInstrs {
                              const MachineInstr *OtherMI) const;
 
 private:
+  /// Set the policy for this loop, allowing the target to override it.
+  void initPolicy();
   LoopCarriedEdges addLoopCarriedDependences();
   void updatePhiDependences();
   void changeDependences();
diff --git a/llvm/include/llvm/CodeGen/TargetSubtargetInfo.h b/llvm/include/llvm/CodeGen/TargetSubtargetInfo.h
index a50f7f804b03d..616ed755de2be 100644
--- a/llvm/include/llvm/CodeGen/TargetSubtargetInfo.h
+++ b/llvm/include/llvm/CodeGen/TargetSubtargetInfo.h
@@ -42,6 +42,7 @@ class InstructionSelector;
 class LegalizerInfo;
 class LibcallLoweringInfo;
 class MachineInstr;
+struct MachinePipelinerPolicy;
 struct MachineSchedPolicy;
 struct MCReadAdvanceEntry;
 struct MCSchedModel;
@@ -276,6 +277,9 @@ class LLVM_ABI TargetSubtargetInfo : public MCSubtargetInfo {
   virtual void overridePostRASchedPolicy(MachineSchedPolicy &Policy,
                                          const SchedRegion &Region) const {}
 
+  /// Override generic software pipelining policy.
+  virtual void overridePipelinerPolicy(MachinePipelinerPolicy &Policy) const {}
+
   // Perform target-specific adjustments to the latency of a schedule
   // dependency.
   // If a pair of operands is associated with the schedule dependency, DefOpIdx
diff --git a/llvm/lib/CodeGen/MachinePipeliner.cpp b/llvm/lib/CodeGen/MachinePipeliner.cpp
index a97e0702d1911..d24e2425c8e14 100644
--- a/llvm/lib/CodeGen/MachinePipeliner.cpp
+++ b/llvm/lib/CodeGen/MachinePipeliner.cpp
@@ -813,8 +813,8 @@ void SwingSchedulerDAG::schedule() {
   }
 
   // Don't pipeline large loops.
-  if (SwpMaxMii != -1 && (int)MII > SwpMaxMii) {
-    LLVM_DEBUG(dbgs() << "MII > " << SwpMaxMii
+  if (Policy.MaxMII != -1 && (int)MII > Policy.MaxMII) {
+    LLVM_DEBUG(dbgs() << "MII > " << Policy.MaxMII
                       << ", we don't pipeline large loops\n");
     NumFailLargeMaxMII++;
     Pass.ORE->emit([&]() {
@@ -822,7 +822,7 @@ void SwingSchedulerDAG::schedule() {
                  DEBUG_TYPE, "schedule", Loop.getStartLoc(), Loop.getHeader())
              << "Minimal Initiation Interval too large: "
              << ore::NV("MII", (int)MII) << " > "
-             << ore::NV("SwpMaxMii", SwpMaxMii) << "."
+             << ore::NV("SwpMaxMii", Policy.MaxMII) << "."
              << "Refer to -pipeliner-max-mii.";
     });
     return;
@@ -2782,6 +2782,15 @@ void SwingSchedulerDAG::computeNodeOrder(NodeSetType &NodeSets) {
   });
 }
 
+/// Set the policy for this loop, allowing the target to override it.
+void SwingSchedulerDAG::initPolicy() {
+  MF.getSubtarget().overridePipelinerPolicy(Policy);
+
+  // After subtarget overrides, apply command line options.
+  if (SwpMaxMii.getNumOccurrences())
+    Policy.MaxMII = SwpMaxMii;
+}
+
 /// Process the nodes in the computed order and create the pipelined schedule
 /// of the instructions, if possible. Return true if a schedule is found.
 bool SwingSchedulerDAG::schedulePipeline(SMSchedule &Schedule) {



More information about the llvm-branch-commits mailing list