1 //===--------------------- Pipeline.cpp -------------------------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 /// \file 9 /// 10 /// This file implements an ordered container of stages that simulate the 11 /// pipeline of a hardware backend. 12 /// 13 //===----------------------------------------------------------------------===// 14 15 #include "llvm/MCA/Pipeline.h" 16 #include "llvm/MCA/HWEventListener.h" 17 #include "llvm/Support/Debug.h" 18 19 namespace llvm { 20 namespace mca { 21 22 #define DEBUG_TYPE "llvm-mca" 23 addEventListener(HWEventListener * Listener)24void Pipeline::addEventListener(HWEventListener *Listener) { 25 if (Listener) 26 Listeners.insert(Listener); 27 for (auto &S : Stages) 28 S->addListener(Listener); 29 } 30 hasWorkToProcess()31bool Pipeline::hasWorkToProcess() { 32 return any_of(Stages, [](const std::unique_ptr<Stage> &S) { 33 return S->hasWorkToComplete(); 34 }); 35 } 36 run()37Expected<unsigned> Pipeline::run() { 38 assert(!Stages.empty() && "Unexpected empty pipeline found!"); 39 40 do { 41 if (!isPaused()) 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 if (isPaused()) 58 Err = S->cycleResume(); 59 else 60 Err = S->cycleStart(); 61 } 62 63 CurrentState = State::Started; 64 65 // Now fetch and execute new instructions. 66 InstRef IR; 67 Stage &FirstStage = *Stages[0]; 68 while (!Err && FirstStage.isAvailable(IR)) 69 Err = FirstStage.execute(IR); 70 71 if (Err.isA<InstStreamPause>()) { 72 CurrentState = State::Paused; 73 return Err; 74 } 75 76 // Update stages in preparation for a new cycle. 77 for (const std::unique_ptr<Stage> &S : Stages) { 78 Err = S->cycleEnd(); 79 if (Err) 80 break; 81 } 82 83 return Err; 84 } 85 appendStage(std::unique_ptr<Stage> S)86void Pipeline::appendStage(std::unique_ptr<Stage> S) { 87 assert(S && "Invalid null stage in input!"); 88 if (!Stages.empty()) { 89 Stage *Last = Stages.back().get(); 90 Last->setNextInSequence(S.get()); 91 } 92 93 Stages.push_back(std::move(S)); 94 } 95 notifyCycleBegin()96void Pipeline::notifyCycleBegin() { 97 LLVM_DEBUG(dbgs() << "\n[E] Cycle begin: " << Cycles << '\n'); 98 for (HWEventListener *Listener : Listeners) 99 Listener->onCycleBegin(); 100 } 101 notifyCycleEnd()102void Pipeline::notifyCycleEnd() { 103 LLVM_DEBUG(dbgs() << "[E] Cycle end: " << Cycles << "\n"); 104 for (HWEventListener *Listener : Listeners) 105 Listener->onCycleEnd(); 106 } 107 } // namespace mca. 108 } // namespace llvm 109