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

Michael Maitland via llvm-commits llvm-commits at lists.llvm.org
Wed Jun 19 20:02:24 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:

In the `GenericScheduler`, we tend not to pick from the `Pending` queues. It is usually better to move the node to `Available` and keep `pick` functions to take from `Available`. Otherwise, there are two cases we run into: 
1.  HazardRecognizers try and keep nodes on the `Pending` queue and this code here will ignore that. It will be really hard to keep the intended functionality of HazardRecognizers if we pick from `Pending`.
2. A node is `Pending` because it will lead to stalls. Picking from it ignores the scheduler model.

Do we really need to pick from `Pending` here? 

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


More information about the llvm-commits mailing list