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 19namespace llvm { 20namespace mca { 21 22#define DEBUG_TYPE "llvm-mca" 23 24void Pipeline::addEventListener(HWEventListener *Listener) { 25 if (Listener) 26 Listeners.insert(Listener); 27 for (auto &S : Stages) 28 S->addListener(Listener); 29} 30 31bool Pipeline::hasWorkToProcess() { 32 return any_of(Stages, [](const std::unique_ptr<Stage> &S) { 33 return S->hasWorkToComplete(); 34 }); 35} 36 37Expected<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 51Error 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 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 85void Pipeline::notifyCycleBegin() { 86 LLVM_DEBUG(dbgs() << "\n[E] Cycle begin: " << Cycles << '\n'); 87 for (HWEventListener *Listener : Listeners) 88 Listener->onCycleBegin(); 89} 90 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