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 "llvm/MCA/Pipeline.h" 17 #include "llvm/MCA/HWEventListener.h" 18 #include "llvm/Support/Debug.h" 19 20 namespace llvm { 21 namespace mca { 22 23 #define DEBUG_TYPE "llvm-mca" 24 addEventListener(HWEventListener * Listener)25void Pipeline::addEventListener(HWEventListener *Listener) { 26 if (Listener) 27 Listeners.insert(Listener); 28 for (auto &S : Stages) 29 S->addListener(Listener); 30 } 31 hasWorkToProcess()32bool Pipeline::hasWorkToProcess() { 33 return any_of(Stages, [](const std::unique_ptr<Stage> &S) { 34 return S->hasWorkToComplete(); 35 }); 36 } 37 run()38Expected<unsigned> Pipeline::run() { 39 assert(!Stages.empty() && "Unexpected empty pipeline found!"); 40 41 do { 42 notifyCycleBegin(); 43 if (Error Err = runCycle()) 44 return std::move(Err); 45 notifyCycleEnd(); 46 ++Cycles; 47 } while (hasWorkToProcess()); 48 49 return Cycles; 50 } 51 runCycle()52Error Pipeline::runCycle() { 53 Error Err = ErrorSuccess(); 54 // Update stages before we start processing new instructions. 55 for (auto I = Stages.rbegin(), E = Stages.rend(); I != E && !Err; ++I) { 56 const std::unique_ptr<Stage> &S = *I; 57 Err = S->cycleStart(); 58 } 59 60 // Now fetch and execute new instructions. 61 InstRef IR; 62 Stage &FirstStage = *Stages[0]; 63 while (!Err && FirstStage.isAvailable(IR)) 64 Err = FirstStage.execute(IR); 65 66 // Update stages in preparation for a new cycle. 67 for (auto I = Stages.rbegin(), E = Stages.rend(); I != E && !Err; ++I) { 68 const std::unique_ptr<Stage> &S = *I; 69 Err = S->cycleEnd(); 70 } 71 72 return Err; 73 } 74 appendStage(std::unique_ptr<Stage> S)75void Pipeline::appendStage(std::unique_ptr<Stage> S) { 76 assert(S && "Invalid null stage in input!"); 77 if (!Stages.empty()) { 78 Stage *Last = Stages.back().get(); 79 Last->setNextInSequence(S.get()); 80 } 81 82 Stages.push_back(std::move(S)); 83 } 84 notifyCycleBegin()85void Pipeline::notifyCycleBegin() { 86 LLVM_DEBUG(dbgs() << "\n[E] Cycle begin: " << Cycles << '\n'); 87 for (HWEventListener *Listener : Listeners) 88 Listener->onCycleBegin(); 89 } 90 notifyCycleEnd()91void Pipeline::notifyCycleEnd() { 92 LLVM_DEBUG(dbgs() << "[E] Cycle end: " << Cycles << "\n"); 93 for (HWEventListener *Listener : Listeners) 94 Listener->onCycleEnd(); 95 } 96 } // namespace mca. 97 } // namespace llvm 98