1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-10-21 03:53:04 +02:00
llvm-mirror/tools/llvm-mca/Pipeline.cpp
Matt Davis 3de6f07d48 [llvm-mca] Add cycleBegin/cycleEnd callbacks to mca::Stage.
Summary:
This patch  clears up some of the semantics within the Stage class.  Now, preExecute
can be called multiple times per simulated cycle.  Previously preExecute was
only called once per cycle, and postExecute could have been called multiple
times.

Now, cycleStart/cycleEnd are called only once per simulated cycle.
preExecute/postExecute can be called multiple times per cycle.  This
occurs because multiple execution events can occur during a single cycle.

When stages are executed (Pipeline::runCycle), the postExecute hook will
be called only if all Stages return a success from their 'execute' callback.

Reviewers: andreadb, courbet, RKSimon

Reviewed By: andreadb

Subscribers: tschuett, gbedwell, llvm-commits

Differential Revision: https://reviews.llvm.org/D49250

llvm-svn: 336959
2018-07-12 22:59:53 +00:00

100 lines
2.5 KiB
C++

//===--------------------- Pipeline.cpp -------------------------*- 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.
///
//===----------------------------------------------------------------------===//
#include "Pipeline.h"
#include "HWEventListener.h"
#include "llvm/CodeGen/TargetSchedule.h"
#include "llvm/Support/Debug.h"
namespace mca {
#define DEBUG_TYPE "llvm-mca"
using namespace llvm;
void Pipeline::addEventListener(HWEventListener *Listener) {
if (Listener)
Listeners.insert(Listener);
for (auto &S : Stages)
S->addListener(Listener);
}
bool Pipeline::hasWorkToProcess() {
const auto It = llvm::find_if(Stages, [](const std::unique_ptr<Stage> &S) {
return S->hasWorkToComplete();
});
return It != Stages.end();
}
// This routine returns early if any stage returns 'false' after execute() is
// called on it.
bool Pipeline::executeStages(InstRef &IR) {
for (const std::unique_ptr<Stage> &S : Stages)
if (!S->execute(IR))
return false;
return true;
}
void Pipeline::preExecuteStages(const InstRef &IR) {
for (const std::unique_ptr<Stage> &S : Stages)
S->preExecute(IR);
}
void Pipeline::postExecuteStages(const InstRef &IR) {
for (const std::unique_ptr<Stage> &S : Stages)
S->postExecute(IR);
}
void Pipeline::run() {
while (hasWorkToProcess())
runCycle(Cycles++);
}
void Pipeline::runCycle(unsigned Cycle) {
notifyCycleBegin(Cycle);
// Update the stages before we do any processing for this cycle.
InstRef IR;
for (auto &S : Stages)
S->cycleStart();
// Continue executing this cycle until any stage claims it cannot make
// progress.
while (true) {
preExecuteStages(IR);
if (!executeStages(IR))
break;
postExecuteStages(IR);
}
for (auto &S : Stages)
S->cycleEnd();
notifyCycleEnd(Cycle);
}
void Pipeline::notifyCycleBegin(unsigned Cycle) {
LLVM_DEBUG(dbgs() << "[E] Cycle begin: " << Cycle << '\n');
for (HWEventListener *Listener : Listeners)
Listener->onCycleBegin();
}
void Pipeline::notifyCycleEnd(unsigned Cycle) {
LLVM_DEBUG(dbgs() << "[E] Cycle end: " << Cycle << "\n\n");
for (HWEventListener *Listener : Listeners)
Listener->onCycleEnd();
}
} // namespace mca.