blob: 4c0e37c9ba7eb5d75657e7439ad6efab25d994c8 [file] [log] [blame]
Matt Davisd8c387b2018-06-25 16:53:00 +00001//===--------------------- Pipeline.cpp -------------------------*- C++ -*-===//
Andrea Di Biagio29b29cc2018-03-08 13:05:02 +00002//
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///
Matt Davisd8c387b2018-06-25 16:53:00 +000011/// This file implements an ordered container of stages that simulate the
12/// pipeline of a hardware backend.
Andrea Di Biagio29b29cc2018-03-08 13:05:02 +000013///
14//===----------------------------------------------------------------------===//
15
Clement Courbet8178ac82018-12-17 08:08:31 +000016#include "llvm/MCA/Pipeline.h"
17#include "llvm/MCA/HWEventListener.h"
Andrea Di Biagio29b29cc2018-03-08 13:05:02 +000018#include "llvm/Support/Debug.h"
19
Fangrui Song467c3072018-10-30 15:56:08 +000020namespace llvm {
Andrea Di Biagio29b29cc2018-03-08 13:05:02 +000021namespace mca {
22
23#define DEBUG_TYPE "llvm-mca"
24
Matt Davisd8c387b2018-06-25 16:53:00 +000025void Pipeline::addEventListener(HWEventListener *Listener) {
Andrea Di Biagio29b29cc2018-03-08 13:05:02 +000026 if (Listener)
27 Listeners.insert(Listener);
Matt Davis90b999f2018-06-27 16:09:33 +000028 for (auto &S : Stages)
29 S->addListener(Listener);
Andrea Di Biagio29b29cc2018-03-08 13:05:02 +000030}
31
Matt Davisd8c387b2018-06-25 16:53:00 +000032bool Pipeline::hasWorkToProcess() {
Andrea Di Biagio965ed082018-09-28 10:47:24 +000033 return any_of(Stages, [](const std::unique_ptr<Stage> &S) {
Matt Davis6299c232018-06-22 16:17:26 +000034 return S->hasWorkToComplete();
35 });
Matt Davis6299c232018-06-22 16:17:26 +000036}
37
Andrea Di Biagio3d1a12c2018-11-28 19:31:19 +000038Expected<unsigned> Pipeline::run() {
Andrea Di Biagiocfeb0f32018-08-16 15:43:09 +000039 assert(!Stages.empty() && "Unexpected empty pipeline found!");
40
Andrea Di Biagioe65789f2018-10-24 19:37:45 +000041 do {
Andrea Di Biagio27babdf2018-07-13 09:27:34 +000042 notifyCycleBegin();
Andrea Di Biagio965ed082018-09-28 10:47:24 +000043 if (Error Err = runCycle())
Andrea Di Biagio3d1a12c2018-11-28 19:31:19 +000044 return std::move(Err);
Andrea Di Biagio27babdf2018-07-13 09:27:34 +000045 notifyCycleEnd();
46 ++Cycles;
Andrea Di Biagioe65789f2018-10-24 19:37:45 +000047 } while (hasWorkToProcess());
48
Andrea Di Biagio3d1a12c2018-11-28 19:31:19 +000049 return Cycles;
Matt Davis1b9c9432018-05-15 20:21:04 +000050}
51
Andrea Di Biagio965ed082018-09-28 10:47:24 +000052Error Pipeline::runCycle() {
53 Error Err = ErrorSuccess();
Andrea Di Biagio8744f362018-08-16 19:00:48 +000054 // Update stages before we start processing new instructions.
55 for (auto I = Stages.rbegin(), E = Stages.rend(); I != E && !Err; ++I) {
Andrea Di Biagiocfeb0f32018-08-16 15:43:09 +000056 const std::unique_ptr<Stage> &S = *I;
57 Err = S->cycleStart();
58 }
Matt Davis5fd7b632018-05-22 20:51:58 +000059
Andrea Di Biagiocfeb0f32018-08-16 15:43:09 +000060 // Now fetch and execute new instructions.
61 InstRef IR;
Andrea Di Biagio8744f362018-08-16 19:00:48 +000062 Stage &FirstStage = *Stages[0];
63 while (!Err && FirstStage.isAvailable(IR))
64 Err = FirstStage.execute(IR);
Matt Davis5c43c4c2018-07-12 22:59:53 +000065
Andrea Di Biagiocfeb0f32018-08-16 15:43:09 +000066 // Update stages in preparation for a new cycle.
Andrea Di Biagio8744f362018-08-16 19:00:48 +000067 for (auto I = Stages.rbegin(), E = Stages.rend(); I != E && !Err; ++I) {
Andrea Di Biagiocfeb0f32018-08-16 15:43:09 +000068 const std::unique_ptr<Stage> &S = *I;
69 Err = S->cycleEnd();
70 }
Andrea Di Biagio8744f362018-08-16 19:00:48 +000071
Andrea Di Biagiocfeb0f32018-08-16 15:43:09 +000072 return Err;
Andrea Di Biagio29b29cc2018-03-08 13:05:02 +000073}
74
Andrea Di Biagio8744f362018-08-16 19:00:48 +000075void 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
Andrea Di Biagio27babdf2018-07-13 09:27:34 +000085void Pipeline::notifyCycleBegin() {
Andrea Di Biagio437f3bd2019-01-10 13:59:13 +000086 LLVM_DEBUG(dbgs() << "\n[E] Cycle begin: " << Cycles << '\n');
Andrea Di Biagio29b29cc2018-03-08 13:05:02 +000087 for (HWEventListener *Listener : Listeners)
Andrea Di Biagioca9b26e2018-04-12 10:49:40 +000088 Listener->onCycleBegin();
Andrea Di Biagio29b29cc2018-03-08 13:05:02 +000089}
90
Andrea Di Biagio27babdf2018-07-13 09:27:34 +000091void Pipeline::notifyCycleEnd() {
Andrea Di Biagio437f3bd2019-01-10 13:59:13 +000092 LLVM_DEBUG(dbgs() << "[E] Cycle end: " << Cycles << "\n");
Andrea Di Biagio29b29cc2018-03-08 13:05:02 +000093 for (HWEventListener *Listener : Listeners)
Andrea Di Biagioca9b26e2018-04-12 10:49:40 +000094 Listener->onCycleEnd();
Andrea Di Biagio29b29cc2018-03-08 13:05:02 +000095}
Andrea Di Biagio29b29cc2018-03-08 13:05:02 +000096} // namespace mca.
Fangrui Song467c3072018-10-30 15:56:08 +000097} // namespace llvm