[llvm] be083db - [RISCV][NFC] Allow SchedVar to be a def inside our scheduler model files. (#82634)

via llvm-commits llvm-commits at lists.llvm.org
Fri Feb 23 06:15:52 PST 2024


Author: Michael Maitland
Date: 2024-02-23T09:15:48-05:00
New Revision: be083dba95dfbbb0286d798cc06fbe021715bc03

URL: https://github.com/llvm/llvm-project/commit/be083dba95dfbbb0286d798cc06fbe021715bc03
DIFF: https://github.com/llvm/llvm-project/commit/be083dba95dfbbb0286d798cc06fbe021715bc03.diff

LOG: [RISCV][NFC] Allow SchedVar to be a def inside our scheduler model files. (#82634)

All SchedModel files have a line that looks like:

```
def SomeModel : SchedMachineModel;
let SchedModel = SomeModel in {
  ...
}
```

TableGen requires that all records defined within the top level `let`
must have a field `SchedModel` somewhere in their nested record
hierarchy (i.e. the record has a field `SchedModel : SchedMachineModel`
or recursively, one of its members has a field `SchedModel :
SchedMachineModel`).

Classes such as `SchedPredicate` have added a field `SchedModel :
SchedMachineModel`, even though the field is never used, just to supress
**errors** (not warnings) caused from having the top level let in the
model files. This decision was made to avoid having hundreds of the same
`let` statement littered in every scheduler model file.

The reason we have never seen an error for `SchedVar` before is because
`SchedVar` is never instantiated with a `def`. Instead, it is only
created as a value that is consumed by `SchedWriteVariant`:

```
... : SchedWriteVariant<[SchedVar<...>, SchedVar<...>]>;
```

There is a problem with this style of instantiation. In particular, the
problem arises as we try to take a class based approach to building
scheduler models. I will describe the problem from the bottom up.

The `LMULWriteResMXVariant` multiclass takes in a `SchedPredicateBase
Pred`. Today, the RISCVSchedSiFive7.td file defines `VLDSX0Pred` outside
the scope of any class. That means that `VLDSX0Pred` exists before
`LMULWriteResMXVariant` multiclass is instantiated. With this approach,
there is no error since the predicate is instantated in entirety before
the variant multiclass is instantiated. However, I have the intention to
move the definition of both the predicate and the variant multiclass
records inside a multiclass to factor out common parts between multiple
scheduler models.

I plan to have something like:

```
multiclass SiFive7Base<SiFive7BaseConfig c> {
  def VLDSX0Pred : ...;
  // Need defvar since record is prefixed with NAME.
  defvar VLDSX0Pred = !cast<...>(NAME # VLDSX0Pred);
  defm SiFive7 : LMULWriteResMXVariant<VLDSX0Pred>;
}

defm "SiFive7Version1" : SiFive7Base<SiFive7BaseConfig<...>>;
defm "SiFive7Version2" : SiFive7Base<SiFive7BaseConfig<...>>;
```

In this scheme, VLDSX0Pred is defined within the same multiclass
transaction that the `LMULWriteResMXVariant` is defined in. For some
reason, TableGen does not allow `Values` to reference records that were
created in the same parent record construction. If the `SchedVar` is not
a `def`, then it will not be able to find the record `NAME #
VLDSX0Pred`. Making it a def, allows TableGen to find `NAME #
VLDSX0Pred` in scope.

The simplest example of this is:

```
class A {}
class B<A a> { A x = a;}
class C<B b> { B y = b;}
multiclass D {
  def MyA : A;
  defvar aa = !cast<A>(NAME # MyA);
  // This works
  def : B<aa>;
  // This does not work because constructing B by value cannot find `NAME # MyA`
  // error: Undefined reference to record: 'MyA'
  def : C<B<aa>>;
  // To fix it, define it like such:
  def MyB : B<aa>;
  defvar bb = !cast<B>(NAME # MyB);
  def : C<bb>;
}
defm "" : D;
```

In summary, in order to use a class based approach to creating scheduler
resources to promote resusability, `SchedVar`s must be created using
defs instead of being instantiated by value so that it can resolve
records that were part of the instantiation of the parent record being
created. In order to do this without refactoring the top level `let`
statement that all scheduler model files use, we add an unused field
`SchedModel : SchedMachineModel` to `SchedVar`, similiar to what has
been done in `SchedPredicate`.

Added: 
    

Modified: 
    llvm/include/llvm/Target/TargetSchedule.td
    llvm/lib/Target/RISCV/RISCVScheduleV.td

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/Target/TargetSchedule.td b/llvm/include/llvm/Target/TargetSchedule.td
index e2781a5d1ea54a..48c9387977c075 100644
--- a/llvm/include/llvm/Target/TargetSchedule.td
+++ b/llvm/include/llvm/Target/TargetSchedule.td
@@ -399,6 +399,8 @@ def NoSchedPred : MCSchedPredicate<TruePred>;
 class SchedVar<SchedPredicateBase pred, list<SchedReadWrite> selected> {
   SchedPredicateBase Predicate = pred;
   list<SchedReadWrite> Selected = selected;
+  // SchedModel silences warnings but is ignored.
+  SchedMachineModel SchedModel = ?;
 }
 
 // SchedModel silences warnings but is ignored.

diff  --git a/llvm/lib/Target/RISCV/RISCVScheduleV.td b/llvm/lib/Target/RISCV/RISCVScheduleV.td
index d15cb611ae665e..0be681de3daf69 100644
--- a/llvm/lib/Target/RISCV/RISCVScheduleV.td
+++ b/llvm/lib/Target/RISCV/RISCVScheduleV.td
@@ -88,20 +88,25 @@ multiclass LMULWriteResMXVariant<string name, SchedPredicateBase Pred,
     let ReleaseAtCycles = noPredReleaseCycles;
   }
 
+  // Define SchedVars
+  def nameMX # PredSchedVar
+      : SchedVar<Pred, [!cast<SchedWriteRes>(NAME # nameMX # "_Pred")]>;
+  def nameMX # NoPredSchedVar
+      : SchedVar<NoSchedPred, [!cast<SchedWriteRes>(NAME # nameMX #"_NoPred")]>;
+  // Allow multiclass to refer to SchedVars -- need to have NAME prefix.
+  defvar PredSchedVar = !cast<SchedVar>(NAME # nameMX # PredSchedVar);
+  defvar NoPredSchedVar = !cast<SchedVar>(NAME # nameMX # NoPredSchedVar);
+
   // Tie behavior to predicate
-  def NAME # nameMX # "_Variant" : SchedWriteVariant<[
-    SchedVar<Pred, [!cast<SchedWriteRes>(NAME # nameMX # "_Pred")]>,
-    SchedVar<NoSchedPred, [!cast<SchedWriteRes>(NAME # nameMX # "_NoPred")]>
-  ]>;
+  def NAME # nameMX # "_Variant"
+      : SchedWriteVariant<[PredSchedVar, NoPredSchedVar]>;
   def : SchedAlias<
     !cast<SchedReadWrite>(nameMX),
     !cast<SchedReadWrite>(NAME # nameMX # "_Variant")>;
 
   if IsWorstCase then {
-    def NAME # name # "_WorstCase_Variant" : SchedWriteVariant<[
-      SchedVar<Pred, [!cast<SchedWriteRes>(NAME # nameMX # "_Pred")]>,
-      SchedVar<NoSchedPred, [!cast<SchedWriteRes>(NAME # nameMX # "_NoPred")]>
-    ]>;
+    def NAME # name # "_WorstCase_Variant"
+      : SchedWriteVariant<[PredSchedVar, NoPredSchedVar]>;
     def : SchedAlias<
       !cast<SchedReadWrite>(name # "_WorstCase"),
       !cast<SchedReadWrite>(NAME # name # "_WorstCase_Variant")>;


        


More information about the llvm-commits mailing list