Skip to content

Commit be083db

Browse files
[RISCV][NFC] Allow SchedVar to be a def inside our scheduler model files. (llvm#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`.
1 parent 52ada07 commit be083db

File tree

2 files changed

+15
-8
lines changed

2 files changed

+15
-8
lines changed

llvm/include/llvm/Target/TargetSchedule.td

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -399,6 +399,8 @@ def NoSchedPred : MCSchedPredicate<TruePred>;
399399
class SchedVar<SchedPredicateBase pred, list<SchedReadWrite> selected> {
400400
SchedPredicateBase Predicate = pred;
401401
list<SchedReadWrite> Selected = selected;
402+
// SchedModel silences warnings but is ignored.
403+
SchedMachineModel SchedModel = ?;
402404
}
403405

404406
// SchedModel silences warnings but is ignored.

llvm/lib/Target/RISCV/RISCVScheduleV.td

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -88,20 +88,25 @@ multiclass LMULWriteResMXVariant<string name, SchedPredicateBase Pred,
8888
let ReleaseAtCycles = noPredReleaseCycles;
8989
}
9090

91+
// Define SchedVars
92+
def nameMX # PredSchedVar
93+
: SchedVar<Pred, [!cast<SchedWriteRes>(NAME # nameMX # "_Pred")]>;
94+
def nameMX # NoPredSchedVar
95+
: SchedVar<NoSchedPred, [!cast<SchedWriteRes>(NAME # nameMX #"_NoPred")]>;
96+
// Allow multiclass to refer to SchedVars -- need to have NAME prefix.
97+
defvar PredSchedVar = !cast<SchedVar>(NAME # nameMX # PredSchedVar);
98+
defvar NoPredSchedVar = !cast<SchedVar>(NAME # nameMX # NoPredSchedVar);
99+
91100
// Tie behavior to predicate
92-
def NAME # nameMX # "_Variant" : SchedWriteVariant<[
93-
SchedVar<Pred, [!cast<SchedWriteRes>(NAME # nameMX # "_Pred")]>,
94-
SchedVar<NoSchedPred, [!cast<SchedWriteRes>(NAME # nameMX # "_NoPred")]>
95-
]>;
101+
def NAME # nameMX # "_Variant"
102+
: SchedWriteVariant<[PredSchedVar, NoPredSchedVar]>;
96103
def : SchedAlias<
97104
!cast<SchedReadWrite>(nameMX),
98105
!cast<SchedReadWrite>(NAME # nameMX # "_Variant")>;
99106

100107
if IsWorstCase then {
101-
def NAME # name # "_WorstCase_Variant" : SchedWriteVariant<[
102-
SchedVar<Pred, [!cast<SchedWriteRes>(NAME # nameMX # "_Pred")]>,
103-
SchedVar<NoSchedPred, [!cast<SchedWriteRes>(NAME # nameMX # "_NoPred")]>
104-
]>;
108+
def NAME # name # "_WorstCase_Variant"
109+
: SchedWriteVariant<[PredSchedVar, NoPredSchedVar]>;
105110
def : SchedAlias<
106111
!cast<SchedReadWrite>(name # "_WorstCase"),
107112
!cast<SchedReadWrite>(NAME # name # "_WorstCase_Variant")>;

0 commit comments

Comments
 (0)