[llvm] [RISCV][PoC] Schedule RVV instructions with same type first (PR #95924)

Michael Maitland via llvm-commits llvm-commits at lists.llvm.org
Thu Jun 20 06:39:03 PDT 2024


================
@@ -0,0 +1,118 @@
+//===- RISCVMachineScheduler.cpp - MI Scheduler for RISC-V ----------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "RISCVMachineScheduler.h"
+#include "MCTargetDesc/RISCVBaseInfo.h"
+#include "MCTargetDesc/RISCVMCTargetDesc.h"
+#include "RISCVInstrInfo.h"
+#include "RISCVSubtarget.h"
+#include "llvm/CodeGen/MachineOperand.h"
+#include "llvm/CodeGen/MachineScheduler.h"
+#include "llvm/CodeGen/ScheduleDAG.h"
+#include "llvm/MC/MCInstrDesc.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/TargetParser/RISCVTargetParser.h"
+
+using namespace llvm;
+
+#define DEBUG_TYPE "riscv-prera-sched-strategy"
+
+static cl::opt<bool> EnableScheduleSameVType(
+    "riscv-enable-schedule-same-vtype", cl::init(false), cl::Hidden,
+    cl::desc("Enable scheduling RVV instructions with same vtype first"));
+
+SUnit *RISCVPreRAMachineSchedStrategy::pickNode(bool &IsTopNode) {
+  auto FindPotentialRVVInstructionInQueue =
+      [&](SchedBoundary &Boundary, ReadyQueue Q, bool ShouldBeTop) -> SUnit * {
+    for (SUnit *SU : Q) {
+      if (SU->isScheduled)
+        continue;
+
+      MachineInstr *MI = SU->getInstr();
+      const MCInstrDesc &Desc = MI->getDesc();
+      if (RISCVII::hasSEWOp(Desc.TSFlags)) {
+        unsigned CurVSEW = MI->getOperand(RISCVII::getSEWOpNum(Desc)).getImm();
+        RISCVII::VLMUL CurVLMUL = RISCVII::getLMul(Desc.TSFlags);
+        // FIXME: We should consider vl and policy here.
+        if (CurVSEW == PrevVSEW && CurVLMUL == PrevVLMUL) {
+          IsTopNode = ShouldBeTop;
+          // Boundary.removeReady(SU);
+          if (SU->isTopReady())
+            Top.removeReady(SU);
+          if (SU->isBottomReady())
+            Bot.removeReady(SU);
+          LLVM_DEBUG(dbgs() << "Scheduling SU(" << SU->NodeNum << ") "
+                            << *SU->getInstr());
+          return SU;
+        }
+      }
+    }
+    return nullptr;
+  };
+
+  auto FindPotentialRVVInstruction = [&](SchedBoundary &Boundary,
+                                         bool ShouldBeTop) -> SUnit * {
+    if (SUnit *Available = FindPotentialRVVInstructionInQueue(
+            Boundary, Boundary.Available, ShouldBeTop))
+      return Available;
+    if (SUnit *Pending = FindPotentialRVVInstructionInQueue(
+            Boundary, Boundary.Pending, ShouldBeTop))
+      return Pending;
+    return nullptr;
+  };
+
+  if (EnableScheduleSameVType) {
+    if (RegionPolicy.OnlyBottomUp) {
+      if (SUnit *SU = FindPotentialRVVInstruction(Bot, false))
+        return SU;
+    } else if (RegionPolicy.OnlyTopDown) {
+      if (SUnit *SU = FindPotentialRVVInstruction(Top, true))
+        return SU;
+    } else {
+      if (SUnit *SU =
----------------
michaelmaitland wrote:

I gave some more thought on this. I think we can reuse from `GenericScheduler::pickNode` and we should instead be overriding `pickNodeFromQueue`. `pickNodeFromQueue` is where the real picking of the node happens. `GenericScheduler::pickNode` just gets the correct queue based on direction and passes it to `pickNodeFromQueue`. Something like this:

```
SUnit *RISCVPreRAMachineSchedStrategy::pickNodeFromQueue(SchedBoundary &Zone,
                                                         const CandPolicy &ZonePolicy,
                                                         const RegPressureTracker &RPTracker,
                                                         SchedCandidate &Cand) {
  SchedCandidate RVVCand = FindRVVCandidate(Zone);
  GenericScheduler::pickNodeFromQueue(Zone, ZonePolicy, RPTracker, Cand);

  // Pass SchedBoundary only when comparing nodes from the same boundary.
  SchedBoundary *ZoneArg = Cand.AtTop == RVVCand.AtTop ? &Zone : nullptr;

  // TODO: we need to add our own heuristics here or inside an overriden
  // tryCandidate to make sure that we balance clustering RVV with same vtype
  // with the existing heuristics such as register pressure, latency, resource usage, etc.
  if (tryCandidate(RVVCand, Cand, ZoneArg)
    return RVVCand;
  return Cand;
}
```

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


More information about the llvm-commits mailing list