[llvm-dev] [RFC][Scheduling] Insert NOPs &&dual issue MIs based on the new MIScheduler

66 views
Skip to first unread message

Tony Jiang via llvm-dev

unread,
Mar 23, 2020, 6:00:56 PM3/23/20
to llvm...@lists.llvm.org
Hi All,

I am currently investigating how to insert NOPs and dual issue MIs based on the new llvm MIScheduler. 
And encountered several issues requires help from the community.

First, I thought I could rely on the HazardRecoginer to help me decide when I should insert the NOPs. But we
want to use the new MachineSchedModel instead of the legacy Itinerary based model. That means we
won't define Itinerary model in our backend. Does that mean I cannot use the HazardRecoginzer llvm
frame code to help me decide when to insert NOPs? i.e: I need people to help me confirm: whether it 
is possible to use the LLVM HazardRecoginzer to help deciding when to insert NOPs without defining 
Itinerary info? Since it seems the following code says without Itineraries,HazardRecognizer will be disabled.
 If that's the case, what should I do to insert NOPs? I also looked  ARM backend, it doesn't override the 
insertNoop() function, does that mean ARM hardware can automatically stall when NOP is needed? 
Therefore, no need for the compiler to insert NOPs?  I also looked at Hexagon code, it does override the
the insertNoop() function. But it seems that was invoked through the old list scheduler rather than the new
MIScheduler. And also Hexagon does define Itinerary in their MachineSchedModel. This confuses me,
does this mean the new MachineSchedModel can work together with the old Itinerary model? Is that the 
best  way to do scheduling modeling? I was assuming the community now recommend people to use the
new MIScheduler + new MachineScheModel for new target development. And  there is also a stand-alone 
postRA hazard recognizer which runs the hazard recoginzer and emits noops when necessary. It gives targets
 a way to run the hazard recognizer without running one of the schedulers. Should I explore that one instead?

// Initialize the HazardRecognizers. If itineraries don't exist, are empty, or
2728  // are disabled, then these HazardRecs will be disabled.
2729  const InstrItineraryData *Itin = SchedModel->getInstrItineraries();
2730  if (!Top.HazardRec) {
2731  Top.HazardRec =
2732  DAG->MF.getSubtarget().getInstrInfo()->CreateTargetMIHazardRecognizer(
2733  Itin, DAG);
2734  }
2735  if (!Bot.HazardRec) {
2736  Bot.HazardRec =
2737  DAG->MF.getSubtarget().getInstrInfo()->CreateTargetMIHazardRecognizer(
2738  Itin, DAG);
2739  }



Second, about dual issue. How does MIScheduler handle dual issue vs single issue? The only thing that I found
was IssueWidth,which should be set to 2 if dual issue, and 1 if single issue.

Any comments and suggestions will be greatly appreciated, thanks!


Regards,

Yanjun

Lorenzo Casalino via llvm-dev

unread,
Mar 24, 2020, 3:56:54 AM3/24/20
to llvm...@lists.llvm.org
Hi Yanjun,

> *First*, I thought I could rely on the HazardRecoginer to help me decide


> when I should insert the NOPs. But we
> want to use the new MachineSchedModel instead of the legacy Itinerary based
> model. That means we
> won't define Itinerary model in our backend. Does that mean I cannot use
> the HazardRecoginzer llvm
> frame code to help me decide when to insert NOPs? i.e: I need people to
> help me confirm: whether it
> is possible to use the LLVM HazardRecoginzer to help deciding when to
> insert NOPs without defining
> Itinerary info?

I'm assuming you're referring to the ScoreBoard-based implementation of the
recognizer (which is the only recognizer implementation available in the
official trunck of LLVM).

The brief answer is (as far as I know): no, you cannot use the
ScoreBoard-based
HazardRecognizer without an Itinerary-based scheduling model.

However, note that the HazardRecognizer
(include/llvm/HazardRecognizer.h) provides
only an API, which is agnostic on what sched model is employed; but it
happens that the backend, up to know, is populated only with recognizers
based
on itineraries.

> Hexagon does define *Itinerary *in their


> MachineSchedModel. This confuses me,
> does this mean the new MachineSchedModel can work together with the old
> Itinerary model?

Yes, the new MachineScheduler is able to manage scheduling driven both by
Itinerary-basedmodel and Per-Operand model. Indeed, when itineraries are
provided, the (Post)GenericScheduler strategy is initialized with a
Scoreboard-based HazardRecognizer, skipping any internal scheduling
tracking.

> Is that the
> best way to do scheduling modeling? I was assuming the community now
> recommend people to use the
> new MIScheduler + new MachineScheModel for new target development.

I think that the assumption is correct. Indeed, for instance, recently added
in-order targets (e.g., ARM R52 and ARM M4) employ solely a Per-Operand
model.


> And
> there is also a stand-alone
> postRA hazard recognizer which runs the hazard recoginzer and emits noops
> when necessary. It gives targets
> a way to run the hazard recognizer without running one of the schedulers.
> Should I explore that one instead?

Actually, this pass creates a HazardRecognizer via:

(1) "CreateTargetPostRAHazardRecognizer(const MachineFunction &)"

which istarget-dependent.

For instance, ARM backend does not override (1), thus won't create a
valid recognizer,
early exiting the postRA hazard recognizer.

As said before, the HazardRecognizer is merely an interface abstracting
on the specific
scheduling model provided: if you want to use an hazard recognizer not
based on itineraries,
you have to specialize such interface.

> *Second*, about dual issue. How does MIScheduler handle dual issue vs


> single issue? The only thing that I found

> was *IssueWidth*,which should be set to 2 if dual issue, and 1 if single
> issue.

The (Post)GenericScheduler strategy tracks 5 main informations:

1. CurrCycle: the current cycle where the scheduling decision is taken

2. CurrMOps: number of micro-ops issued in CurrCycle (usually,
instructions are modeled as
1 mops, but is target-dependent).

3. Reservation of Resource Units: for how many cycles each units is
unavailable (i.e., already
processing an instruction).

4. PendingQueue: the nodes which cannot be issued due to some hazards.

5. AvailableQueue: the nodes ready to be issued.

The strategy checks if it is possible to issue an instruction, according
to (2), (3), (4)
and (5). Concerning the dual-issuing, this is possible only if there's
an instruction (MI) in (5),
such that (2) + MOps(MI) <= IssueLimit, and there's a Resource unit
ready to consume MI.

As long as such conditions are satisfied, dual-issuing is possible.

> what should I do to insert NOPs? I also looked ARM
> backend, it doesn't override the
> insertNoop() function, does that mean ARM hardware can automatically stall
> when NOP is needed?

I haven't work with the Scoreboard-based hazard recognizer; hence, I cannot
tell you how noops are handled in such case. However, in the
MachineScheduler,
explicit noop insertion is not required, for the scheduler using (1):
when no instruction is
issuable, the pipeline is assumed to be stalled, and (1) bumped until
(5) is filled with
an instruction, and scheduling resumed.


> Any comments and suggestions will be greatly appreciated, thanks!

The scheduling model for the ARM Cortex-R52, an in-order dual issue
target, provides a really clean
and complete per-operand model. I'd really suggest you to look at it :).


Cheers,

-- Lorenzo


_______________________________________________
LLVM Developers mailing list
llvm...@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev

Tony Jiang via llvm-dev

unread,
Mar 24, 2020, 9:13:52 AM3/24/20
to Lorenzo Casalino, llvm...@lists.llvm.org
Thank you so much Lorenzo, your detailed explanation is very helpful! Really appreciate it.

Regards,

Yanjun
Reply all
Reply to author
Forward
0 new messages