Home | History | Annotate | Download | only in llvm-mca
      1 //===--------------------- Pipeline.cpp -------------------------*- C++ -*-===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 /// \file
     10 ///
     11 /// This file implements an ordered container of stages that simulate the
     12 /// pipeline of a hardware backend.
     13 ///
     14 //===----------------------------------------------------------------------===//
     15 
     16 #include "Pipeline.h"
     17 #include "HWEventListener.h"
     18 #include "llvm/CodeGen/TargetSchedule.h"
     19 #include "llvm/Support/Debug.h"
     20 
     21 namespace mca {
     22 
     23 #define DEBUG_TYPE "llvm-mca"
     24 
     25 using namespace llvm;
     26 
     27 void Pipeline::addEventListener(HWEventListener *Listener) {
     28   if (Listener)
     29     Listeners.insert(Listener);
     30   for (auto &S : Stages)
     31     S->addListener(Listener);
     32 }
     33 
     34 bool Pipeline::hasWorkToProcess() {
     35   const auto It = llvm::find_if(Stages, [](const std::unique_ptr<Stage> &S) {
     36     return S->hasWorkToComplete();
     37   });
     38   return It != Stages.end();
     39 }
     40 
     41 // This routine returns early if any stage returns 'false' after execute() is
     42 // called on it.
     43 bool Pipeline::executeStages(InstRef &IR) {
     44   for (const std::unique_ptr<Stage> &S : Stages)
     45     if (!S->execute(IR))
     46       return false;
     47   return true;
     48 }
     49 
     50 void Pipeline::preExecuteStages() {
     51   for (const std::unique_ptr<Stage> &S : Stages)
     52     S->preExecute();
     53 }
     54 
     55 void Pipeline::postExecuteStages() {
     56   for (const std::unique_ptr<Stage> &S : Stages)
     57     S->postExecute();
     58 }
     59 
     60 void Pipeline::run() {
     61   while (hasWorkToProcess()) {
     62     notifyCycleBegin();
     63     runCycle();
     64     notifyCycleEnd();
     65     ++Cycles;
     66   }
     67 }
     68 
     69 void Pipeline::runCycle() {
     70   // Update the stages before we do any processing for this cycle.
     71   InstRef IR;
     72   for (auto &S : Stages)
     73     S->cycleStart();
     74 
     75   // Continue executing this cycle until any stage claims it cannot make
     76   // progress.
     77   while (true) {
     78     preExecuteStages();
     79     if (!executeStages(IR))
     80       break;
     81     postExecuteStages();
     82   }
     83 
     84   for (auto &S : Stages)
     85     S->cycleEnd();
     86 }
     87 
     88 void Pipeline::notifyCycleBegin() {
     89   LLVM_DEBUG(dbgs() << "[E] Cycle begin: " << Cycles << '\n');
     90   for (HWEventListener *Listener : Listeners)
     91     Listener->onCycleBegin();
     92 }
     93 
     94 void Pipeline::notifyCycleEnd() {
     95   LLVM_DEBUG(dbgs() << "[E] Cycle end: " << Cycles << "\n\n");
     96   for (HWEventListener *Listener : Listeners)
     97     Listener->onCycleEnd();
     98 }
     99 } // namespace mca.
    100