1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-10-20 19:42:54 +02:00
llvm-mirror/tools/llvm-mca/Pipeline.h
Andrea Di Biagio 081e1ff89b [llvm-mca] Refactor how execution is orchestrated by the Pipeline.
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 both the stage API and the Pipeline execution.  At
the same time, this patch fixes some design issues which are currently latent,
but that are likely to cause problems in future if people start defining custom
pipelines.

The new design assumes that each pipeline stage knows the "next-in-sequence".
The Stage API has gained three new methods:
 -   isAvailable(IR)
 -   checkNextStage(IR)
 -   moveToTheNextStage(IR).

An instruction IR can be executed by a Stage if method `Stage::isAvailable(IR)`
returns true.
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.
Stages are now responsible for moving instructions to the next stage in sequence
if necessary.

Instructions are allowed to transition through multiple stages during a single
cycle (as long as stages are available, and as long as all the calls to
`checkNextStage(IR)` returns true).

Methods `Stage::preExecute()` and `Stage::postExecute()` have now become
redundant, and those are removed by this patch.

Method Pipeline::runCycle() is now simpler, and it correctly visits stages
on every begin/end of cycle.

Other changes:
 - DispatchStage no longer requires a reference to the Scheduler.
 - 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).
 - RetireStage gained an execute method. This allowed us to remove the
   dependency with the RCU in ExecuteStage.
 - FecthStage now updates the "program counter" during cycleBegin() (i.e.
   before we start executing new instructions).
 - We no longer need Stage::Status to be returned by method execute(). It has
   been dropped in favor of a more lightweight llvm::Error.

Overally, 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, and I plan to do it in a follow-up patch.

Differential revision: https://reviews.llvm.org/D50849

llvm-svn: 339923
2018-08-16 19:00:48 +00:00

77 lines
2.5 KiB
C++

//===--------------------- Pipeline.h ---------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
/// \file
///
/// This file implements an ordered container of stages that simulate the
/// pipeline of a hardware backend.
///
//===----------------------------------------------------------------------===//
#ifndef LLVM_TOOLS_LLVM_MCA_PIPELINE_H
#define LLVM_TOOLS_LLVM_MCA_PIPELINE_H
#include "Scheduler.h"
#include "Stage.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/Error.h"
namespace mca {
class HWEventListener;
class HWInstructionEvent;
class HWStallEvent;
/// A pipeline for a specific subtarget.
///
/// It emulates an out-of-order execution of instructions. Instructions are
/// fetched from a MCInst sequence managed by an initial 'Fetch' stage.
/// Instructions are firstly fetched, then dispatched to the schedulers, and
/// then executed.
///
/// This class tracks the lifetime of an instruction from the moment where
/// it gets dispatched to the schedulers, to the moment where it finishes
/// executing and register writes are architecturally committed.
/// In particular, it monitors changes in the state of every instruction
/// in flight.
///
/// Instructions are executed in a loop of iterations. The number of iterations
/// is defined by the SourceMgr object, which is managed by the initial stage
/// of the instruction pipeline.
///
/// The Pipeline entry point is method 'run()' which executes cycles in a loop
/// until there are new instructions to dispatch, and not every instruction
/// has been retired.
///
/// Internally, the Pipeline collects statistical information in the form of
/// histograms. For example, it tracks how the dispatch group size changes
/// over time.
class Pipeline {
Pipeline(const Pipeline &P) = delete;
Pipeline &operator=(const Pipeline &P) = delete;
/// An ordered list of stages that define this instruction pipeline.
llvm::SmallVector<std::unique_ptr<Stage>, 8> Stages;
std::set<HWEventListener *> Listeners;
unsigned Cycles;
llvm::Error runCycle();
bool hasWorkToProcess();
void notifyCycleBegin();
void notifyCycleEnd();
public:
Pipeline() : Cycles(0) {}
void appendStage(std::unique_ptr<Stage> S);
llvm::Error run();
void addEventListener(HWEventListener *Listener);
};
} // namespace mca
#endif // LLVM_TOOLS_LLVM_MCA_PIPELINE_H