<div dir="ltr">Thank you so much Lorenzo, your detailed explanation is very helpful! Really appreciate it.<div><br></div><div>Regards,</div><div><br></div><div>Yanjun</div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Tue, 24 Mar 2020 at 03:56, Lorenzo Casalino via llvm-dev <<a href="mailto:llvm-dev@lists.llvm.org">llvm-dev@lists.llvm.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Hi Yanjun,<br>
<br>
> *First*, I thought I could rely on the HazardRecoginer to help me decide<br>
> when I should insert the NOPs. But we<br>
> want to use the new MachineSchedModel instead of the legacy Itinerary based<br>
> model. That means we<br>
> won't define Itinerary model in our backend. Does that mean I cannot use<br>
> the HazardRecoginzer llvm<br>
> frame code to help me decide when to insert NOPs? i.e: I need people to<br>
> help me confirm: whether it<br>
> is possible to use the LLVM HazardRecoginzer to help deciding when to<br>
> insert NOPs without defining<br>
> Itinerary info?<br>
<br>
I'm assuming you're referring to the ScoreBoard-based implementation of the<br>
recognizer (which is the only recognizer implementation available in the<br>
official trunck of LLVM).<br>
<br>
The brief answer is (as far as I know): no, you cannot use the<br>
ScoreBoard-based<br>
HazardRecognizer without an Itinerary-based scheduling model.<br>
<br>
However, note that the HazardRecognizer<br>
(include/llvm/HazardRecognizer.h) provides<br>
only an API, which is agnostic on what sched model is employed; but it<br>
happens that the backend, up to know, is populated only with recognizers<br>
based<br>
on itineraries.<br>
<br>
> Hexagon does define *Itinerary *in their<br>
> MachineSchedModel. This confuses me,<br>
> does this mean the new MachineSchedModel can work together with the old<br>
> Itinerary model?<br>
<br>
Yes, the new MachineScheduler is able to manage scheduling driven both by<br>
Itinerary-basedmodel and Per-Operand model. Indeed, when itineraries are<br>
provided, the (Post)GenericScheduler strategy is initialized with a<br>
Scoreboard-based HazardRecognizer, skipping any internal scheduling<br>
tracking.<br>
<br>
> Is that the<br>
> best  way to do scheduling modeling? I was assuming the community now<br>
> recommend people to use the<br>
> new MIScheduler + new MachineScheModel for new target development.<br>
I think that the assumption is correct. Indeed, for instance, recently added<br>
in-order targets (e.g., ARM R52 and ARM M4) employ solely a Per-Operand<br>
model.<br>
> And<br>
> there is also a stand-alone<br>
> postRA hazard recognizer which runs the hazard recoginzer and emits noops<br>
> when necessary. It gives targets<br>
>  a way to run the hazard recognizer without running one of the schedulers.<br>
> Should I explore that one instead?<br>
Actually, this pass creates a HazardRecognizer via:<br>
<br>
(1) "CreateTargetPostRAHazardRecognizer(const MachineFunction &)"<br>
<br>
which istarget-dependent.<br>
<br>
For instance, ARM backend does not override (1), thus won't create a<br>
valid recognizer,<br>
early exiting the postRA hazard recognizer.<br>
<br>
As said before, the HazardRecognizer is merely an interface abstracting<br>
on the specific<br>
scheduling model provided: if you want to use an hazard recognizer not<br>
based on itineraries,<br>
you have to specialize such interface.<br>
<br>
> *Second*, about dual issue. How does MIScheduler handle dual issue vs<br>
> single issue? The only thing that I found<br>
> was *IssueWidth*,which should be set to 2 if dual issue, and 1 if single<br>
> issue.<br>
<br>
The (Post)GenericScheduler strategy tracks 5 main informations:<br>
<br>
1. CurrCycle: the current cycle where the scheduling decision is taken<br>
<br>
2. CurrMOps: number of micro-ops issued in CurrCycle (usually,<br>
instructions are modeled as<br>
1 mops, but is target-dependent).<br>
<br>
3. Reservation of Resource Units: for how many cycles each units is<br>
unavailable (i.e., already<br>
processing an instruction).<br>
<br>
4. PendingQueue: the nodes which cannot be issued due to some hazards.<br>
<br>
5. AvailableQueue: the nodes ready to be issued.<br>
<br>
The strategy checks if it is possible to issue an instruction, according<br>
to (2), (3), (4)<br>
and (5). Concerning the dual-issuing, this is possible only if there's<br>
an instruction (MI) in (5),<br>
such that (2) + MOps(MI) <= IssueLimit, and there's a Resource unit<br>
ready to consume MI.<br>
<br>
As long as such conditions are satisfied, dual-issuing is possible.<br>
<br>
> what should I do to insert NOPs? I also looked  ARM<br>
> backend, it doesn't override the<br>
> insertNoop() function, does that mean ARM hardware can automatically stall<br>
> when NOP is needed?<br>
I haven't work with the Scoreboard-based hazard recognizer; hence, I cannot<br>
tell you how noops are handled in such case. However, in the<br>
MachineScheduler,<br>
explicit noop insertion is not required, for the scheduler using (1):<br>
when no instruction is<br>
issuable, the pipeline is assumed to be stalled, and (1) bumped until<br>
(5) is filled with<br>
an instruction, and scheduling resumed.<br>
> Any comments and suggestions will be greatly appreciated, thanks!<br>
The scheduling model for the ARM Cortex-R52, an in-order dual issue<br>
target, provides a really clean<br>
and complete per-operand model. I'd really suggest you to look at it :).<br>
<br>
<br>
Cheers,<br>
<br>
-- Lorenzo<br>
<br>
<br>
_______________________________________________<br>
LLVM Developers mailing list<br>
<a href="mailto:llvm-dev@lists.llvm.org" target="_blank">llvm-dev@lists.llvm.org</a><br>
<a href="https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev" rel="noreferrer" target="_blank">https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev</a><br>
</blockquote></div>