This is an archive of the discontinued LLVM Phabricator instance.

[llvm-mca] Refactor how execution is orchestrated by the Pipeline. NFCI
ClosedPublic

Authored by andreadb on Aug 16 2018, 10:04 AM.

Details

Summary

This patch changes how instruction execution is orchestrated by the Pipeline.

In particular, this patch makes it more explicit how instructions transition through the various pipeline stages during execution.

The main goal is to simplify the stage API and simpify the Pipeline execution. At the same time, this patch fixes some issues which are currently latent, but that are likely to cause problems in future if people define custom pipelines.

The new design assumes that each pipeline stage knows the "next-in-sequence".
The Stage API has gained two new methods:

  • isAvailable(IR)
  • checkNextStage(IR)
  • moveToTheNextStage(IR).

An instruction IR can be executed by a Stage if method Stage::isAvailable(IR) returns true.
Stage may accept a limited number of instructions per cycle. So, method isAvailable(IR) is responsible for checking if instruction IR can execute within the current cycle.

Instructions can move to next stages using method moveToTheNextStage(IR).
An instruction cannot be moved to the next stage if method checkNextStage(IR) (called on the current stage) returns false.

Instruction IR may be allowed to transition through multiple stages in a single cycle, provided that stages are available, and that checkNextStage(IR) always returns true.

Since now stages know about their "next-in-sequence", some methods in the Stage interface have become now redundant. For example, this patch gets rid of Stage::preExecute() and Stage::postExecute().

Method Pipeline::runCycle() is now much simpler, and it correctly visits stages in post-order at the beginning/end of a cycle. Before, this caused an issue with the sequence of stages in the default pipeline; that issue is now fixed.

Other changes:

  1. DispatchStage no longer requires a reference to the Scheduler.
  2. ExecuteStage no longer needs to directly interact with the RetireControlUnit. Instead, executed instructions are now directly moved to the next stage (i.e. the retire stage).
  3. RetireStage gained an execute method. This allowed us to remove the dependency with the RCU in ExecuteStage.
  4. FecthStage now updates the "program counter" during cycleBegin() (i.e. before we start executing new instructions).
  5. We no longer need Stage::Status to be returned by method execute(). It has been dropped in favor of a more lightweight llvm::Error.

With this change, the Pipeline logic is simplified. We no longer generate extra calls to pre/postExecute() every instruction. We also avoid redundant execute(IR) calls on stages that are not reached by IR (that was an oddity of the previous design).

Overally, when testing a debug build of llvm-mca, I measured a ~11% performance gain w.r.t. the previous design. I also think that the Stage interface is probably easier to read now. That being said, code comments have to be improved (I plan to do it in a follow-up patch).

Please let me know if okay to commit.

-Andrea

Diff Detail

Repository
rL LLVM

Event Timeline

andreadb created this revision.Aug 16 2018, 10:04 AM

I made a few comments, all just nits. This is a pretty substantial change in design, but better. LGTM. Thanks for this!

tools/llvm-mca/FetchStage.cpp
37 ↗(On Diff #161045)

nit: Not sure if we want whitespace here. Lines 41 and 43 below do not use white space to separate the if block.

tools/llvm-mca/Stage.h
58 ↗(On Diff #161045)

Would there ever be the case where a stage might want to overwrite its NextInSequence? If not, then perhaps we should add an assertion.

65 ↗(On Diff #161045)

This is the fundamental difference from this design and the previous incarnation of Stage. I think this comment should be a bit more explicit in saying that a Stage is responsible for transferring the instruction it completes processing on to its immediate successor stage.

Hi Matt,

Thanks for the review.

tools/llvm-mca/Context.cpp
43 ↗(On Diff #161045)

I plan to change that variable name to "StagePipeline".
Just to be consistent with the other naming convention.

tools/llvm-mca/FetchStage.cpp
37 ↗(On Diff #161045)

I will remove that whitespace.

tools/llvm-mca/Stage.h
58 ↗(On Diff #161045)

In future, we may want to allow stages to be inserted at specific positions (i.e. not just appended at the end of the pipeline).
That being said, for now it makes sense to have an assert. I will do it.

65 ↗(On Diff #161045)

I will elaborate this a bit more.

andreadb updated this revision to Diff 161070.Aug 16 2018, 11:12 AM
andreadb marked 3 inline comments as done.

Addressed review comments.

mattd accepted this revision.Aug 16 2018, 11:13 AM

Thanks!
LGTM (again)

This revision is now accepted and ready to land.Aug 16 2018, 11:13 AM
This revision was automatically updated to reflect the committed changes.