blob: f099ec629b9dbb5f493eaee8b30dab854d3e8cb6 [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() {
Matt Davis43de6db2018-06-22 16:17:26 +000035 const auto It = llvm::find_if(Stages, [](const std::unique_ptr<Stage> &S) {
36 return S->hasWorkToComplete();
37 });
38 return It != Stages.end();
39}
40
41// This routine returns early if any stage returns 'false' after execute() is
42// called on it.
Matt Davis4bcf3692018-08-13 18:11:48 +000043Stage::Status Pipeline::executeStages(InstRef &IR) {
44 for (const std::unique_ptr<Stage> &S : Stages) {
45 Stage::Status StatusOrErr = S->execute(IR);
46 if (!StatusOrErr)
47 return StatusOrErr.takeError();
48 else if (StatusOrErr.get() == Stage::Stop)
49 return Stage::Stop;
50 }
51 return Stage::Continue;
Matt Davis43de6db2018-06-22 16:17:26 +000052}
53
Matt Davisf6bcbf32018-07-14 00:10:42 +000054void Pipeline::preExecuteStages() {
Matt Davis32508992018-07-12 22:59:53 +000055 for (const std::unique_ptr<Stage> &S : Stages)
Matt Davisf6bcbf32018-07-14 00:10:42 +000056 S->preExecute();
Matt Davis32508992018-07-12 22:59:53 +000057}
58
Matt Davisf6bcbf32018-07-14 00:10:42 +000059void Pipeline::postExecuteStages() {
Matt Davis43de6db2018-06-22 16:17:26 +000060 for (const std::unique_ptr<Stage> &S : Stages)
Matt Davisf6bcbf32018-07-14 00:10:42 +000061 S->postExecute();
Matt Davis43de6db2018-06-22 16:17:26 +000062}
63
Matt Davis4bcf3692018-08-13 18:11:48 +000064llvm::Error Pipeline::run() {
Andrea Di Biagioef6b8a32018-07-13 09:27:34 +000065 while (hasWorkToProcess()) {
66 notifyCycleBegin();
Matt Davis4bcf3692018-08-13 18:11:48 +000067 if (llvm::Error Err = runCycle())
68 return Err;
Andrea Di Biagioef6b8a32018-07-13 09:27:34 +000069 notifyCycleEnd();
70 ++Cycles;
71 }
Matt Davis4bcf3692018-08-13 18:11:48 +000072 return llvm::ErrorSuccess();
Matt Davis5d1cda12018-05-15 20:21:04 +000073}
74
Matt Davis4bcf3692018-08-13 18:11:48 +000075llvm::Error Pipeline::runCycle() {
Matt Davis5b79ffc5b2018-05-25 18:00:25 +000076 // Update the stages before we do any processing for this cycle.
Matt Davis5d1cda12018-05-15 20:21:04 +000077 InstRef IR;
Matt Davis43de6db2018-06-22 16:17:26 +000078 for (auto &S : Stages)
Matt Davis32508992018-07-12 22:59:53 +000079 S->cycleStart();
Matt Davisbd125322018-05-22 20:51:58 +000080
Matt Davis43de6db2018-06-22 16:17:26 +000081 // Continue executing this cycle until any stage claims it cannot make
82 // progress.
Matt Davis32508992018-07-12 22:59:53 +000083 while (true) {
Matt Davisf6bcbf32018-07-14 00:10:42 +000084 preExecuteStages();
Matt Davis4bcf3692018-08-13 18:11:48 +000085 Stage::Status Val = executeStages(IR);
86 if (!Val)
87 return Val.takeError();
88 if (Val.get() == Stage::Stop)
Matt Davis32508992018-07-12 22:59:53 +000089 break;
Matt Davisf6bcbf32018-07-14 00:10:42 +000090 postExecuteStages();
Matt Davis32508992018-07-12 22:59:53 +000091 }
92
93 for (auto &S : Stages)
94 S->cycleEnd();
Matt Davis4bcf3692018-08-13 18:11:48 +000095 return llvm::ErrorSuccess();
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +000096}
97
Andrea Di Biagioef6b8a32018-07-13 09:27:34 +000098void Pipeline::notifyCycleBegin() {
99 LLVM_DEBUG(dbgs() << "[E] Cycle begin: " << Cycles << '\n');
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000100 for (HWEventListener *Listener : Listeners)
Andrea Di Biagio3e646442018-04-12 10:49:40 +0000101 Listener->onCycleBegin();
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000102}
103
Andrea Di Biagioef6b8a32018-07-13 09:27:34 +0000104void Pipeline::notifyCycleEnd() {
105 LLVM_DEBUG(dbgs() << "[E] Cycle end: " << Cycles << "\n\n");
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000106 for (HWEventListener *Listener : Listeners)
Andrea Di Biagio3e646442018-04-12 10:49:40 +0000107 Listener->onCycleEnd();
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000108}
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000109} // namespace mca.