//===--------------------- 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 &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 &S : Stages) if (!S->execute(IR)) return false; return true; } void Pipeline::preExecuteStages() { for (const std::unique_ptr &S : Stages) S->preExecute(); } void Pipeline::postExecuteStages() { for (const std::unique_ptr &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.