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 24 void Pipeline::addEventListener(HWEventListener *Listener) { 25 if (Listener) 26 Listeners.insert(Listener); 27 for (auto &S : Stages) 28 S->addListener(Listener); 29 } 30 31 bool Pipeline::hasWorkToProcess() { 32 return any_of(Stages, [](const std::unique_ptr<Stage> &S) { 33 return S->hasWorkToComplete(); 34 }); 35 } 36 37 Expected<unsigned> Pipeline::run() { 38 assert(!Stages.empty() && "Unexpected empty pipeline found!"); 39 40 do { 41 notifyCycleBegin(); 42 if (Error Err = runCycle()) 43 return std::move(Err); 44 notifyCycleEnd(); 45 ++Cycles; 46 } while (hasWorkToProcess()); 47 48 return Cycles; 49 } 50 51 Error Pipeline::runCycle() { 52 Error Err = ErrorSuccess(); 53 // Update stages before we start processing new instructions. 54 for (auto I = Stages.rbegin(), E = Stages.rend(); I != E && !Err; ++I) { 55 const std::unique_ptr<Stage> &S = *I; 56 Err = S->cycleStart(); 57 } 58 59 // Now fetch and execute new instructions. 60 InstRef IR; 61 Stage &FirstStage = *Stages[0]; 62 while (!Err && FirstStage.isAvailable(IR)) 63 Err = FirstStage.execute(IR); 64 65 // Update stages in preparation for a new cycle. 66 for (const std::unique_ptr<Stage> &S : Stages) { 67 Err = S->cycleEnd(); 68 if (Err) 69 break; 70 } 71 72 return Err; 73 } 74 75 void 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 85 void Pipeline::notifyCycleBegin() { 86 LLVM_DEBUG(dbgs() << "\n[E] Cycle begin: " << Cycles << '\n'); 87 for (HWEventListener *Listener : Listeners) 88 Listener->onCycleBegin(); 89 } 90 91 void 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