blob: 91c7a5d25ea7c2b4649343a597b25fcbb54a2ebf [file] [log] [blame]
Matt Davisdea343d2018-06-25 16:53:00 +00001//===--------------------- Pipeline.cpp -------------------------*- C++ -*-===//
Andrea Di Biagio3a6b0922018-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 Davisdea343d2018-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 Biagio3a6b0922018-03-08 13:05:02 +000013///
14//===----------------------------------------------------------------------===//
15
Matt Davisdea343d2018-06-25 16:53:00 +000016#include "Pipeline.h"
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +000017#include "HWEventListener.h"
18#include "llvm/CodeGen/TargetSchedule.h"
19#include "llvm/Support/Debug.h"
20
21namespace mca {
22
23#define DEBUG_TYPE "llvm-mca"
24
25using namespace llvm;
26
Matt Davisdea343d2018-06-25 16:53:00 +000027void Pipeline::addEventListener(HWEventListener *Listener) {
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +000028 if (Listener)
29 Listeners.insert(Listener);
Matt Davis7b5a36e2018-06-27 16:09:33 +000030 for (auto &S : Stages)
31 S->addListener(Listener);
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +000032}
33
Matt Davisdea343d2018-06-25 16:53:00 +000034bool Pipeline::hasWorkToProcess() {
Andrea Di Biagio492816d2018-08-16 15:43:09 +000035 return llvm::any_of(Stages, [](const std::unique_ptr<Stage> &S) {
Matt Davis43de6db2018-06-22 16:17:26 +000036 return S->hasWorkToComplete();
37 });
Matt Davis43de6db2018-06-22 16:17:26 +000038}
39
40// This routine returns early if any stage returns 'false' after execute() is
41// called on it.
Matt Davis4bcf3692018-08-13 18:11:48 +000042Stage::Status Pipeline::executeStages(InstRef &IR) {
43 for (const std::unique_ptr<Stage> &S : Stages) {
44 Stage::Status StatusOrErr = S->execute(IR);
45 if (!StatusOrErr)
46 return StatusOrErr.takeError();
47 else if (StatusOrErr.get() == Stage::Stop)
48 return Stage::Stop;
49 }
50 return Stage::Continue;
Matt Davis43de6db2018-06-22 16:17:26 +000051}
52
Matt Davisf6bcbf32018-07-14 00:10:42 +000053void Pipeline::preExecuteStages() {
Matt Davis32508992018-07-12 22:59:53 +000054 for (const std::unique_ptr<Stage> &S : Stages)
Matt Davisf6bcbf32018-07-14 00:10:42 +000055 S->preExecute();
Matt Davis32508992018-07-12 22:59:53 +000056}
57
Matt Davisf6bcbf32018-07-14 00:10:42 +000058void Pipeline::postExecuteStages() {
Matt Davis43de6db2018-06-22 16:17:26 +000059 for (const std::unique_ptr<Stage> &S : Stages)
Matt Davisf6bcbf32018-07-14 00:10:42 +000060 S->postExecute();
Matt Davis43de6db2018-06-22 16:17:26 +000061}
62
Matt Davis4bcf3692018-08-13 18:11:48 +000063llvm::Error Pipeline::run() {
Andrea Di Biagio492816d2018-08-16 15:43:09 +000064 assert(!Stages.empty() && "Unexpected empty pipeline found!");
65
Andrea Di Biagioef6b8a32018-07-13 09:27:34 +000066 while (hasWorkToProcess()) {
67 notifyCycleBegin();
Matt Davis4bcf3692018-08-13 18:11:48 +000068 if (llvm::Error Err = runCycle())
69 return Err;
Andrea Di Biagioef6b8a32018-07-13 09:27:34 +000070 notifyCycleEnd();
71 ++Cycles;
72 }
Matt Davis4bcf3692018-08-13 18:11:48 +000073 return llvm::ErrorSuccess();
Matt Davis5d1cda12018-05-15 20:21:04 +000074}
75
Matt Davis4bcf3692018-08-13 18:11:48 +000076llvm::Error Pipeline::runCycle() {
Andrea Di Biagio492816d2018-08-16 15:43:09 +000077 // Update stages before we start processing new instructions.
78 llvm::Error Err = llvm::ErrorSuccess();
79 for (auto I = Stages.begin(), E = Stages.end(); I != E && !Err; ++I) {
80 const std::unique_ptr<Stage> &S = *I;
81 Err = S->cycleStart();
82 }
Matt Davisbd125322018-05-22 20:51:58 +000083
Andrea Di Biagio492816d2018-08-16 15:43:09 +000084 if (Err)
85 return Err;
86
87 // Now fetch and execute new instructions.
88 InstRef IR;
Matt Davis32508992018-07-12 22:59:53 +000089 while (true) {
Matt Davisf6bcbf32018-07-14 00:10:42 +000090 preExecuteStages();
Matt Davis4bcf3692018-08-13 18:11:48 +000091 Stage::Status Val = executeStages(IR);
92 if (!Val)
93 return Val.takeError();
94 if (Val.get() == Stage::Stop)
Matt Davis32508992018-07-12 22:59:53 +000095 break;
Matt Davisf6bcbf32018-07-14 00:10:42 +000096 postExecuteStages();
Matt Davis32508992018-07-12 22:59:53 +000097 }
98
Andrea Di Biagio492816d2018-08-16 15:43:09 +000099 // Update stages in preparation for a new cycle.
100 for (auto I = Stages.begin(), E = Stages.end(); I != E && !Err; ++I) {
101 const std::unique_ptr<Stage> &S = *I;
102 Err = S->cycleEnd();
103 }
104 return Err;
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000105}
106
Andrea Di Biagioef6b8a32018-07-13 09:27:34 +0000107void Pipeline::notifyCycleBegin() {
108 LLVM_DEBUG(dbgs() << "[E] Cycle begin: " << Cycles << '\n');
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000109 for (HWEventListener *Listener : Listeners)
Andrea Di Biagio3e646442018-04-12 10:49:40 +0000110 Listener->onCycleBegin();
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000111}
112
Andrea Di Biagioef6b8a32018-07-13 09:27:34 +0000113void Pipeline::notifyCycleEnd() {
114 LLVM_DEBUG(dbgs() << "[E] Cycle end: " << Cycles << "\n\n");
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000115 for (HWEventListener *Listener : Listeners)
Andrea Di Biagio3e646442018-04-12 10:49:40 +0000116 Listener->onCycleEnd();
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000117}
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000118} // namespace mca.