-
Notifications
You must be signed in to change notification settings - Fork 10.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[RISCV][NFC] Allow SchedVar to be a def inside our scheduler model files. #82634
Conversation
…les. 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<SiFive7BaseConfig<...>>; defm "" :SiFive7Version2<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`.
@llvm/pr-subscribers-backend-risc-v Author: Michael Maitland (michaelmaitland) Changes…les. All SchedModel files have a line that looks like:
TableGen requires that all records defined within the top level Classes such as The reason we have never seen an error for
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 I plan to have something like:
In this scheme, VLDSX0Pred is defined within the same multiclass transaction that the The simplest example of this is:
In summary, in order to use a class based approach to creating scheduler resources to promote resusability, Full diff: https://github.com/llvm/llvm-project/pull/82634.diff 2 Files Affected:
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")>;
|
Why does |
In these cases, the predicate needs to be defined under the |
But we're talking about an MCSchedPredicate here not a SchedPredicate. Does an MCSchedPredicate have access to the model? |
Why? That SchedModel is coming from C++ code not from tablegen. It does not involve the let statement at all. It's the scheduler model that is active at the time the predicate is called. If the active scheduler model doesn't make reference to the predicate it won't ever be called when that scheduler model is active. |
We can move the predicate out, that is unrelated to this patch. We still need to def the SchedVar, otherwise it wont be able to find the SchedReadWrite that was defined just a few lines above. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM.
For some reason, TableGen does not allow Values to reference records that were created in the same parent record construction.
Yeah, this is a problem. I may make TableGen able to refer to other definitions in a multiclass:
multiclass Test {
def a;
def b: B<a>; // For `a`, we will search `NAME # a` first and then `a`.
}
(Hopefully this can be easy to design and implement)
This would be very nice. It is quite ugly to have to use |
I have tried it, it may be hard to implement based on my rough investigation. In short, the TableGen parser resolves Record after resolving variables/arguements. I need more time to think about it. |
All SchedModel files have a line that looks like:
TableGen requires that all records defined within the top level
let
must have a fieldSchedModel
somewhere in their nested record hierarchy (i.e. the record has a fieldSchedModel : SchedMachineModel
or recursively, one of its members has a fieldSchedModel : SchedMachineModel
).Classes such as
SchedPredicate
have added a fieldSchedModel : 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 samelet
statement littered in every scheduler model file.The reason we have never seen an error for
SchedVar
before is becauseSchedVar
is never instantiated with adef
. Instead, it is only created as a value that is consumed bySchedWriteVariant
: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 aSchedPredicateBase Pred
. Today, the RISCVSchedSiFive7.td file definesVLDSX0Pred
outside the scope of any class. That means thatVLDSX0Pred
exists beforeLMULWriteResMXVariant
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:
In this scheme, VLDSX0Pred is defined within the same multiclass transaction that the
LMULWriteResMXVariant
is defined in. For some reason, TableGen does not allowValues
to reference records that were created in the same parent record construction. If theSchedVar
is not adef
, then it will not be able to find the recordNAME # VLDSX0Pred
. Making it a def, allows TableGen to findNAME # VLDSX0Pred
in scope.The simplest example of this is:
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 levellet
statement that all scheduler model files use, we add an unused fieldSchedModel : SchedMachineModel
toSchedVar
, similiar to what has been done inSchedPredicate
.