The prior naming scheme is incredibly hard to make sense out of. I
suspect the usage was actually backwards from intent - though that
didn't matter for any in tree schedule model.
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`.
Shortening Iota to Iot seemed strange to me.
I also remove the M from VMIota and VMIdx. The instruction for viota
does have an m at the end of it, but vid.v does not. The M didn't seem
very important for viota.
The Arithmetic, Load, and Store sequencers can accept instructions in
parallel. The PipeV blocked that from happening since it became busy if
any of the sequencers were busy. This change allows the sequencers to
accept instructions in parallel.
The VCQ accepts instructions from the the A Pipe and holds them until
the vector unit is ready to dequeue them. The unit dequeues up to one
instruction per cycle, in order, as soon as the sequencer for that type
of instruction is avaliable. This resource is meant to be used for 1
cycle by all vector instructions, to model that only one vector
instruction may be dequed at a time. The actual dequeueing into the
sequencer is modeled by the VA, VL, and VS sequencer resources below.
Each of them will only accept a single instruction at a time and remain
busy for the number of cycles associated with that instruction.
When stride is x0, a strided load should behave like a unit stride load,
which uses the VLDE sched class.
---------
Co-authored-by: Wang Pengcheng <wangpengcheng.pp@bytedance.com>
For Pseudos that end in _MASK or should be forceMasked,
which means that in the case that the instruction should be
mask undisturbed the destination register must be read to
determine the undisturbed values. This patch adds a SchedRead
that gets passed to MASK pseudos to represent this extra read that
must occur.
A future patch should do something similiar for when a pseudo is TU,
since those instructions must also read their destination to preserve
undisturbed-ness.
Differential Revision: https://reviews.llvm.org/D155654
Our downstream needs to give different scheduling for min/max from
other reductions.
Reviewed By: michaelmaitland
Differential Revision: https://reviews.llvm.org/D155108
vfredmax/min may have different scheduling behavior on different
microarchitectures compared to other reductions. This different
behavior can be described by giving vfredmax/min separate
scheduling resources.
Differential Revision: https://reviews.llvm.org/D153450
Compares write a mask result. Min/max write a full result. This
makes them sufficiently different to have their own classes.
Reviewed By: pcwang-thead
Differential Revision: https://reviews.llvm.org/D152020
Create SchedWrites, WriteRes for reduction instructions that
are SEW specific. Future patches can use these resources
to customize the behavior of these resources depending on SEW.
Differential Revision: https://reviews.llvm.org/D151470
These instructions don't read or write register groups. We only pretend they do in intrinsics and pseudoinstructions.
Differential Revision: https://reviews.llvm.org/D150238
Add scheduling information for vector extension in SiFive7,
while using new LMUL & SEW scheduling constructs.
Differential Revision: https://reviews.llvm.org/D149495
For floating-point instructions, SEW won't be 8. So we don't need
to generate scheduling resources for it.
Reviewed By: michaelmaitland
Differential Revision: https://reviews.llvm.org/D148317
Prior to this patch, UpperBound refered to the largest LMUL
supported. Instructions used UpperBound to assign the worst
case behaviour to records, since Instructions are not LMUL
specific. This forced the largest LMUL to have the worst case
behavior, even if that wasn't true for a subtarget.
Now that SchedWrites, SchedReads, WriteRes, and ReadAdvances
are created for (name, LMUL) pairs and (name, LMUL, SEW)
tuples, it becomes even less clear which pair should correspond
to the worst case behavior. Additionally, it no longer makes sense
for the UpperBound to belong to LMUL list and not to the SEW list.
Instead of creating a special UpperBound LMUL and an UpperBound
SEW, this patch renames UpperBound to WorstCaseBehavior, removes
it from the SchedMxList, and defines a WorstCaseBehavior SchedWrite,
SchedRead, WriteRes, and ReadAdvance for each name.
This gives subtargets the ability to describe the worst case behavior
of a record without forcing it to be the largest LMUL or the smallest
SEW.
Differential Revision: https://reviews.llvm.org/D146855
Prior to this patch, UpperBound refered to the largest LMUL
supported. Instructions used UpperBound to assign the worst
case behaviour to records, since Instructions are not LMUL
specific. This forced the largest LMUL to have the worst case
behavior, even if that wasn't true for a subtarget.
Now that SchedWrites, SchedReads, WriteRes, and ReadAdvances
are created for (name, LMUL) pairs and (name, LMUL, SEW)
tuples, it becomes even less clear which pair should correspond
to the worst case behavior. Additionally, it no longer makes sense
for the UpperBound to belong to LMUL list and not to the SEW list.
Instead of creating a special UpperBound LMUL and an UpperBound
SEW, this patch renames UpperBound to WorstCaseBehavior, removes
it from the SchedMxList, and defines a WorstCaseBehavior SchedWrite,
SchedRead, WriteRes, and ReadAdvance for each name.
This gives subtargets the ability to describe the worst case behavior
of a record without forcing it to be the largest LMUL or the smallest
SEW.
Differential Revision: https://reviews.llvm.org/D146855
SchedWrites are relevant to LMUL for most instructions, so we have
to enumerate all defined SchedWrites when defining ReadAdcance.
This patch adds some classes to simplify these definitions.
Reviewed By: michaelmaitland
Differential Revision: https://reviews.llvm.org/D145041
The core part of this change is an extension to the tablegen language to allow conditional definition of records using if-statements based on !exists conditions.
The RISCV td file change is mostly to illustrate the potential use of conditional definitions. I am deliberately not maximally simplifying in this change to make merging with downstream code (or simply rebasing while this on review) easier.
Some background to make the change understandable.
TableGen does not have an if statement internally. It has if expressions - in the form of TernInitOp with IF opcode - and foreach statements. It implements an if-statement as a foreach which iterates either 0 or 1 times.
Foreach nodes are then evaluated via unrolling inside the parser. Specifically, they are evaluated, at latest, when the outermost multiclass or loop containing them reaches end of scope. The unrolled statements remain (potentially) unresolved after unrolling, but the number of iterations must be known at this point.
An !exists clause can only evaluate at final evaluation. (Specifically, forward references to definitions are allowed - up to the end of the containing scope at least.) The existing code did not set the final flag on the resolver, and thus would leave the !exists clause in an unresolved state. This would then cause an error since we don't know how many iterations on which to unroll the (synthetic) foreach loop.
I chose to only finally-evaluate the condition of the if-expression. This allows us to pick an arm at scope exit without inhibiting definitions in the arm from having self references.
Differential Revision: https://reviews.llvm.org/D145108
Factoring out a shared multiclass imply makes it easier to see that all of these do the same thing, just on different lists. It also makes it easier to see differences - such as we don't define read related pieces for FWRed.
Differential Revision: https://reviews.llvm.org/D144899
The Reduction instruction destination register LMUL is 1. But the source
register(vs2) has different LMUL(MF8 to M8). It's beneficial to know how
many registers are working on reduction instructions.
This patch creates separate SchedWrite for each relevant LMUL that from VS2.
Reviewed By: michaelmaitland
Differential Revision: https://reviews.llvm.org/D141565
It is likley that subtargets act differently for a vector load store instructions based on the LMUL.
This patch creates seperate SchedRead, SchedWrite, WriteRes, ReadAdvance for each relevant LMUL.
Differential Revision: https://reviews.llvm.org/D137429
It is likley that subtargets act differently for vector fixed-point arithmetic instructions
based on the LMUL. This patch creates seperate SchedRead, SchedWrite, WriteRes, ReadAdvance
for each relevant LMUL.
Differential Revision: https://reviews.llvm.org/D137428
It is likley that subtargets act differently for vector fixed-point arithmetic instructions based on the LMUL.
This patch creates seperate SchedRead, SchedWrite, WriteRes, ReadAdvance for each relevant LMUL.
Differential Revision: https://reviews.llvm.org/D137427
It is likley that subtargets act differently for vector floating-point instructions based on the LMUL.
This patch creates seperate SchedRead, SchedWrite, WriteRes, ReadAdvance for each relevant LMUL.
Differential Revision: https://reviews.llvm.org/D137426
The original intention is adding a list of SchedWrites (which is a
default argument of ReadAdvance) to LMULReadAdvance, but it may not
be practical that there are two default arguments in one class. So
we add variants that are intended for widening and narrowing
instructions with postfix "W" and remove lmuls argument.
Reviewed By: michaelmaitland
Differential Revision: https://reviews.llvm.org/D138640
It is likley that subtargets act differently for vector fixed-point arithmetic instructions based on the LMUL.
This patch creates seperate SchedRead, SchedWrite, WriteRes, ReadAdvance for each relevant LMUL.
Differential Revision: https://reviews.llvm.org/D137342
It is likley that subtargets act differently for a vector integer arithmetic instruction based on the LMUL.
This patch creates seperate SchedRead, SchedWrite, WriteRes, ReadAdvance for each relevant LMUL. It also
introduces the concept of an "UpperBound LMUL" which allows us to describe how an instruction should behave
when the LMUL is unknown. All base instructions use the UpperBound resources because they are not tied to
a specific LMUL. This gives subtargetes the flexibility to describe their own upper bounds on each vector
instruction.
I have a series of patches for the rest of the vector instruction set ready to go, but I would like to first
get feedback on the first one of the series (this one).
Differential Revision: https://reviews.llvm.org/D136730
This removes the EEW from unit stride load/store and whole register
load, store, move.
It seems reasonable that implementations of these instructions wouldn't
usually be affected by element width.
We likely need to add LMUL information to our scheduling classes so
I thought it might be good to remove a few before they got multiplied
by LMUL.
Reviewed By: reames, michaelmaitland
Differential Revision: https://reviews.llvm.org/D135992