Johnson, Nicholas Paul via llvm-dev
2017-Apr-03 19:37 UTC
[llvm-dev] Scheduler: modelling long register reservations?
Hello,
My out-of-tree target features some high latency instructions (let's call
them FXLV). When an FXLV issues, it reserves its destination register and
execution continues; if a subsequent instruction attempts to read or write that
register, the pipline will stall until the FXLV completes. I have attempted to
encode this constraint in the machine scheduler (excerpt at bottom of email).
This solves half of the problem: the scheduler moves any instruction that reads
the FXLV result register to a much later position.
However, this doesn't solve all of the problem. In particular, the
scheduler seems indifferent to an instruction which overwrites the FXLV's
result register---including instructions which overwrite only one lane of the
vector result. Am I specifying the scheduling constraints incorrectly? Can
llvm support this kind of constraint?
Thank you,
Nick Johnson
D. E. Shaw Research
// Excerpted from lib/Target/MyTarget/MyTargetSchedule.td:
//
def DesGCv3GenericModel : SchedMachineModel
{
let IssueWidth = 1;
let MicroOpBufferSize = 0;
let CompleteModel = 1;
}
// ...
def FlexU : ProcResource<64> { let BufferSize = 1; }
def : WriteRes<IIFlexRead, [FlexU]> { let Latency = 25; let
ResourceCycles = [25]; }
class SchedFlexRead : Sched< [IIFlexRead] >; // I apply this to the
definition of FXLV instruction
// ...
Johnson, Nicholas Paul via llvm-dev
2017-Apr-10 16:50 UTC
[llvm-dev] Scheduler: modelling long register reservations?
(Thank you Alex Bradbury for publicizing this thread in the weekly)
I'll update the thread with my partial solution. I have introduced a
pseudo-instruction 'DontOverwriteFlexResult' as in Snippet1 (below).
That instruction has no effect. Then, I updated some instruction selection
patterns so that they wrap every occurrence of FXLV within a
DontOverwriteFlexResult pseudo-instruction (Snippet2, below). The scheduler
will attempt to schedule the pseudo-instruction to satisfy the long latency.
This extends the live-interval of the FXLV's result vector register, and
prevents the register allocator from prematurely overwriting subvectors of the
result register.
This solution works in some cases, but doesn't yet support the case in which
the FXLV result is completely unused, since the
'DontOverwriteFlexResult' pseudo will get dead-code-eliminated. I'm
planning on marking the pseudo as side-effecting to inhibit dead code
elimination, but still need a plan to prevent that from pessimizing the
scheduler.
Nick Johnson
D. E. Shaw Research
// Snippet 1
// Here is a fancy fake instruction which prevent the compiler
// from clobbering all or part of a flex api instruction's result.
let hasNoSchedulingInfo = 1, mayLoad=0, mayStore=0, hasSideEffects=0,
isAsCheapAsAMove=1 in
{
def DontOverwriteFlexResults :
DesGCv3PseudoInst<
(outs VecRegs:$rd),
(ins VecRegs:$rs),
"# DontOverwriteFlexResults_v4i32\t$rd",
[]>
{
let Constraints = "$rd = $rs";
}
}
// Snippet 2
def : Pat<
(v4i32 (Aligned16LoadFromFlex (i32 DesGCv3RegPlusInt26:$ptr) )),
(DontOverwriteFlexResults (v4i32 (FXLV_UNCOUNTED (i32
DesGCv3RegPlusInt26:$ptr) )))>;
>-----Original Message-----
>From: llvm-dev [mailto:llvm-dev-bounces at lists.llvm.org] On Behalf Of
>Johnson, Nicholas Paul via llvm-dev
>Sent: Monday, April 03, 2017 3:38 PM
>To: llvm-dev at lists.llvm.org
>Subject: [llvm-dev] Scheduler: modelling long register reservations?
>
>Hello,
>
>My out-of-tree target features some high latency instructions (let's
call them
>FXLV). When an FXLV issues, it reserves its destination register and
>execution continues; if a subsequent instruction attempts to read or write
>that register, the pipline will stall until the FXLV completes. I have
>attempted to encode this constraint in the machine scheduler (excerpt at
>bottom of email). This solves half of the problem: the scheduler moves any
>instruction that reads the FXLV result register to a much later position.
>
>However, this doesn't solve all of the problem. In particular, the
scheduler
>seems indifferent to an instruction which overwrites the FXLV's result
>register---including instructions which overwrite only one lane of the
vector
>result. Am I specifying the scheduling constraints incorrectly? Can llvm
>support this kind of constraint?
>
>Thank you,
>Nick Johnson
>D. E. Shaw Research
>
>
>// Excerpted from lib/Target/MyTarget/MyTargetSchedule.td:
>//
>def DesGCv3GenericModel : SchedMachineModel
>{
> let IssueWidth = 1;
> let MicroOpBufferSize = 0;
>
> let CompleteModel = 1;
>}
>// ...
>def FlexU : ProcResource<64> { let BufferSize = 1; }
>def : WriteRes<IIFlexRead, [FlexU]> { let Latency = 25; let
>ResourceCycles = [25]; }
>class SchedFlexRead : Sched< [IIFlexRead] >; // I apply this to the
definition
>of FXLV instruction
>// ...
>
>
>
>
>_______________________________________________
>LLVM Developers mailing list
>llvm-dev at lists.llvm.org
>http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev
Jonas Paulsson via llvm-dev
2017-Apr-12 07:25 UTC
[llvm-dev] Scheduler: modelling long register reservations?
Hi Nick, ScheduleDAGInstrs::addPhysRegDeps(SUnit *SU, unsigned OperIdx) is the method that adds the edges with their latencies for Output dependencies (def -> def). It seems unfortunately that there currently isn't a way to specify latency for output deps with computeOperandLatency() or similar. I am then thinking that one option might be to add a DAGMutator where you could manually set the latency of the anti-edge to 25, after the DAG has been built. If you have a problem with subregs, did you try to model the stalling subreg def as defining the whole vector reg, while in the output adjusting the register operand text, or similar? /Jonas On 2017-04-10 19:50, Johnson, Nicholas Paul via llvm-dev wrote:> (Thank you Alex Bradbury for publicizing this thread in the weekly) > > I'll update the thread with my partial solution. I have introduced a pseudo-instruction 'DontOverwriteFlexResult' as in Snippet1 (below). That instruction has no effect. Then, I updated some instruction selection patterns so that they wrap every occurrence of FXLV within a DontOverwriteFlexResult pseudo-instruction (Snippet2, below). The scheduler will attempt to schedule the pseudo-instruction to satisfy the long latency. This extends the live-interval of the FXLV's result vector register, and prevents the register allocator from prematurely overwriting subvectors of the result register. > > This solution works in some cases, but doesn't yet support the case in which the FXLV result is completely unused, since the 'DontOverwriteFlexResult' pseudo will get dead-code-eliminated. I'm planning on marking the pseudo as side-effecting to inhibit dead code elimination, but still need a plan to prevent that from pessimizing the scheduler. > > Nick Johnson > D. E. Shaw Research > > > // Snippet 1 > // Here is a fancy fake instruction which prevent the compiler > // from clobbering all or part of a flex api instruction's result. > let hasNoSchedulingInfo = 1, mayLoad=0, mayStore=0, hasSideEffects=0, isAsCheapAsAMove=1 in > { > def DontOverwriteFlexResults : > DesGCv3PseudoInst< > (outs VecRegs:$rd), > (ins VecRegs:$rs), > "# DontOverwriteFlexResults_v4i32\t$rd", > []> > { > let Constraints = "$rd = $rs"; > } > } > > // Snippet 2 > def : Pat< > (v4i32 (Aligned16LoadFromFlex (i32 DesGCv3RegPlusInt26:$ptr) )), > (DontOverwriteFlexResults (v4i32 (FXLV_UNCOUNTED (i32 DesGCv3RegPlusInt26:$ptr) )))>; > > >> -----Original Message----- >> From: llvm-dev [mailto:llvm-dev-bounces at lists.llvm.org] On Behalf Of >> Johnson, Nicholas Paul via llvm-dev >> Sent: Monday, April 03, 2017 3:38 PM >> To: llvm-dev at lists.llvm.org >> Subject: [llvm-dev] Scheduler: modelling long register reservations? >> >> Hello, >> >> My out-of-tree target features some high latency instructions (let's call them >> FXLV). When an FXLV issues, it reserves its destination register and >> execution continues; if a subsequent instruction attempts to read or write >> that register, the pipline will stall until the FXLV completes. I have >> attempted to encode this constraint in the machine scheduler (excerpt at >> bottom of email). This solves half of the problem: the scheduler moves any >> instruction that reads the FXLV result register to a much later position. >> >> However, this doesn't solve all of the problem. In particular, the scheduler >> seems indifferent to an instruction which overwrites the FXLV's result >> register---including instructions which overwrite only one lane of the vector >> result. Am I specifying the scheduling constraints incorrectly? Can llvm >> support this kind of constraint? >> >> Thank you, >> Nick Johnson >> D. E. Shaw Research >> >> >> // Excerpted from lib/Target/MyTarget/MyTargetSchedule.td: >> // >> def DesGCv3GenericModel : SchedMachineModel >> { >> let IssueWidth = 1; >> let MicroOpBufferSize = 0; >> >> let CompleteModel = 1; >> } >> // ... >> def FlexU : ProcResource<64> { let BufferSize = 1; } >> def : WriteRes<IIFlexRead, [FlexU]> { let Latency = 25; let >> ResourceCycles = [25]; } >> class SchedFlexRead : Sched< [IIFlexRead] >; // I apply this to the definition >> of FXLV instruction >> // ... >> >> >> >> >> _______________________________________________ >> LLVM Developers mailing list >> llvm-dev at lists.llvm.org >> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev > _______________________________________________ > LLVM Developers mailing list > llvm-dev at lists.llvm.org > http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev