|  | //===--------------------- 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() { | 
|  | for (const std::unique_ptr<Stage> &S : Stages) | 
|  | S->preExecute(); | 
|  | } | 
|  |  | 
|  | void Pipeline::postExecuteStages() { | 
|  | for (const std::unique_ptr<Stage> &S : Stages) | 
|  | S->postExecute(); | 
|  | } | 
|  |  | 
|  | void Pipeline::run() { | 
|  | while (hasWorkToProcess()) { | 
|  | notifyCycleBegin(); | 
|  | runCycle(); | 
|  | notifyCycleEnd(); | 
|  | ++Cycles; | 
|  | } | 
|  | } | 
|  |  | 
|  | void Pipeline::runCycle() { | 
|  | // 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(); | 
|  | if (!executeStages(IR)) | 
|  | break; | 
|  | postExecuteStages(); | 
|  | } | 
|  |  | 
|  | for (auto &S : Stages) | 
|  | S->cycleEnd(); | 
|  | } | 
|  |  | 
|  | void Pipeline::notifyCycleBegin() { | 
|  | LLVM_DEBUG(dbgs() << "[E] Cycle begin: " << Cycles << '\n'); | 
|  | for (HWEventListener *Listener : Listeners) | 
|  | Listener->onCycleBegin(); | 
|  | } | 
|  |  | 
|  | void Pipeline::notifyCycleEnd() { | 
|  | LLVM_DEBUG(dbgs() << "[E] Cycle end: " << Cycles << "\n\n"); | 
|  | for (HWEventListener *Listener : Listeners) | 
|  | Listener->onCycleEnd(); | 
|  | } | 
|  | } // namespace mca. |