[llvm] [MachinePipeliner] Add validation for missed dependencies (PR #135148)

Ryotaro Kasuga via llvm-commits llvm-commits at lists.llvm.org
Mon Apr 21 05:25:10 PDT 2025


================
@@ -3922,41 +4187,202 @@ SwingSchedulerDDG::getEdges(const SUnit *SU) const {
 void SwingSchedulerDDG::addEdge(const SUnit *SU,
                                 const SwingSchedulerDDGEdge &Edge) {
   auto &Edges = getEdges(SU);
-  if (Edge.getSrc() == SU)
-    Edges.Succs.push_back(Edge);
-  else
-    Edges.Preds.push_back(Edge);
+  if (Edge.isValidationOnly()) {
+    assert(SU == Edge.getDst() && "Validation only edges must be added to the "
+                                  "destination node");
+    Edges.ValidationOnlyPreds.push_back(Edge);
+  } else {
+    if (Edge.getSrc() == SU)
+      Edges.Succs.append(Edge);
+    else
+      Edges.Preds.append(Edge);
+  }
 }
 
 void SwingSchedulerDDG::initEdges(SUnit *SU) {
   for (const auto &PI : SU->Preds) {
-    SwingSchedulerDDGEdge Edge(SU, PI, false);
+    SwingSchedulerDDGEdge Edge(SU, PI, false, false);
     addEdge(SU, Edge);
   }
 
   for (const auto &SI : SU->Succs) {
-    SwingSchedulerDDGEdge Edge(SU, SI, true);
+    SwingSchedulerDDGEdge Edge(SU, SI, true, false);
     addEdge(SU, Edge);
   }
 }
 
 SwingSchedulerDDG::SwingSchedulerDDG(std::vector<SUnit> &SUnits, SUnit *EntrySU,
-                                     SUnit *ExitSU)
+                                     SUnit *ExitSU, const LoopCarriedEdges &LCE)
     : EntrySU(EntrySU), ExitSU(ExitSU) {
   EdgesVec.resize(SUnits.size());
 
   initEdges(EntrySU);
   initEdges(ExitSU);
   for (auto &SU : SUnits)
     initEdges(&SU);
+
+  for (SUnit &SU : SUnits) {
+    SUnit *Src = &SU;
+
+    if (auto *OutputDep = LCE.getOutputDepOrNull(Src))
+      for (const auto &[Reg, Set] : *OutputDep) {
+        SDep Dep(Src, SDep::Output, Reg);
+        Dep.setLatency(1);
+        for (SUnit *Dst : Set) {
+          SwingSchedulerDDGEdge Edge(Dst, Dep, /*IsSucc=*/false,
+                                     /*IsValidationOnly=*/true);
+          Edge.setDistance(1);
+          addEdge(Dst, Edge);
+        }
+      }
+
+    if (auto *OrderDep = LCE.getOrderDepOrNull(Src)) {
+      SDep Dep(Src, SDep::Barrier);
+      Dep.setLatency(1);
+      for (SUnit *Dst : *OrderDep) {
+        SwingSchedulerDDGEdge Edge(
+            Dst, Dep, /*IsSucc=*/false,
+            /*IsValidationOnly=*/!LCE.shouldUseWhenScheduling(Src, Dst));
+        Edge.setDistance(1);
+
+        // If this edge is used when scheduling, this should be added both Preds
+        // and Succs.
+        if (!Edge.isValidationOnly())
+          addEdge(Src, Edge);
+        addEdge(Dst, Edge);
+      }
+    }
+  }
 }
 
-const SwingSchedulerDDG::EdgesType &
+ArrayRef<SwingSchedulerDDGEdge>
 SwingSchedulerDDG::getInEdges(const SUnit *SU) const {
-  return getEdges(SU).Preds;
+  return getEdges(SU).Preds.get(UseLoopCarriedEdges);
 }
 
-const SwingSchedulerDDG::EdgesType &
+ArrayRef<SwingSchedulerDDGEdge>
 SwingSchedulerDDG::getOutEdges(const SUnit *SU) const {
-  return getEdges(SU).Succs;
+  return getEdges(SU).Succs.get(UseLoopCarriedEdges);
+}
+
+bool SwingSchedulerDDG::isValidSchedule(std::vector<SUnit> &SUnits,
+                                        const SMSchedule &Schedule) const {
+  unsigned II = Schedule.getInitiationInterval();
+
+  auto ExpandedCycle = [&](SUnit *SU) {
+    int Stage = Schedule.stageScheduled(SU);
+    int Cycle = Schedule.cycleScheduled(SU);
+    return Cycle + (Stage * II);
+  };
+
+  for (SUnit &Dst : SUnits) {
+    if (!Dst.isInstr())
+      continue;
+    int CycleDst = ExpandedCycle(&Dst);
+    for (const SwingSchedulerDDGEdge &Edge :
+         getEdges(&Dst).ValidationOnlyPreds) {
+      SUnit *Src = Edge.getSrc();
+      if (!Src->isInstr())
+        continue;
+      int CycleSrc = ExpandedCycle(Src);
+      int MaxLateStart = CycleDst + Edge.getDistance() * II - Edge.getLatency();
+      if (CycleSrc > MaxLateStart) {
+        LLVM_DEBUG({
+          dbgs() << "Validation failed for edge from " << Src->NodeNum << " to "
+                 << Dst.NodeNum << "\n";
+        });
+        return false;
+      }
+    }
+  }
+  return true;
+}
+
+void SwingSchedulerDDG::EdgesType::append(const SwingSchedulerDDGEdge &Edge) {
+  bool LoopCarriedOrderDep = Edge.isOrderDep() && Edge.getDistance() != 0;
+  assert(!(LoopCarriedOrderDepsCount != 0 && !LoopCarriedOrderDep) &&
+         "Loop-carried edges should not be added to the underlying edges");
+  Underlying.push_back(Edge);
+  if (LoopCarriedOrderDep)
+    ++LoopCarriedOrderDepsCount;
+}
+
+bool LoopCarriedEdges::shouldUseWhenScheduling(const SUnit *From,
+                                               const SUnit *To) const {
+  if (From->NodeNum < To->NodeNum)
+    return false;
+  auto Ite = BackEdges.find(From);
+  if (Ite == BackEdges.end())
+    return false;
+  return Ite->second.contains(To);
+}
+
+void LoopCarriedEdges::modifySUnits(std::vector<SUnit> &SUnits,
+                                    const TargetInstrInfo *TII) {
+  for (SUnit &SU : SUnits) {
+    SUnit *Src = &SU;
+    if (auto *OrderDep = getOrderDepOrNull(Src)) {
+      SDep Dep(Src, SDep::Barrier);
+      Dep.setLatency(1);
+      for (SUnit *Dst : *OrderDep) {
+        SUnit *From = Src;
+        SUnit *To = Dst;
+        bool IsBackEdge = Src->NodeNum > Dst->NodeNum;
+        if (IsBackEdge) {
+          BackEdges[From].insert(To);
+          std::swap(From, To);
+        }
+
+        // To keep the previouse behavior, add a foward direction edge if the
+        // following conditions are met:
+        //
+        // - From is a load and To is a store.
+        // - The load apprears before the store in the original basic block.
+        // - There is no barrier/store between the two instructions.
+        // - We cannot reach to the store from the load through current edges in
+        //   the DAG.
----------------
kasuga-fj wrote:

These are what the previous implementation added in `addLoopCarriedDependencies`. Essentially, other types of dependencies (store-to-store, store-to-load) need to be added as well.

https://github.com/llvm/llvm-project/pull/135148


More information about the llvm-commits mailing list