Andrea Di Biagio | 3a6b092 | 2018-03-08 13:05:02 +0000 | [diff] [blame] | 1 | //===--------------------- Backend.h ----------------------------*- C++ -*-===// |
| 2 | // |
| 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 | /// |
| 11 | /// This file implements an OoO backend for the llvm-mca tool. |
| 12 | /// |
| 13 | //===----------------------------------------------------------------------===// |
| 14 | |
| 15 | #ifndef LLVM_TOOLS_LLVM_MCA_BACKEND_H |
| 16 | #define LLVM_TOOLS_LLVM_MCA_BACKEND_H |
| 17 | |
| 18 | #include "Dispatch.h" |
| 19 | #include "InstrBuilder.h" |
| 20 | #include "Scheduler.h" |
| 21 | #include "SourceMgr.h" |
| 22 | |
| 23 | namespace mca { |
| 24 | |
Andrea Di Biagio | 3db1fd9 | 2018-03-08 16:34:19 +0000 | [diff] [blame] | 25 | class HWEventListener; |
Clement Courbet | 844f22d | 2018-03-13 13:11:01 +0000 | [diff] [blame^] | 26 | class HWInstructionEvent; |
Andrea Di Biagio | 3a6b092 | 2018-03-08 13:05:02 +0000 | [diff] [blame] | 27 | |
| 28 | /// \brief An out of order backend for a specific subtarget. |
| 29 | /// |
| 30 | /// It emulates an out-of-order execution of instructions. Instructions are |
| 31 | /// fetched from a MCInst sequence managed by an object of class SourceMgr. |
| 32 | /// Instructions are firstly dispatched to the schedulers and then executed. |
| 33 | /// This class tracks the lifetime of an instruction from the moment where |
| 34 | /// it gets dispatched to the schedulers, to the moment where it finishes |
| 35 | /// executing and register writes are architecturally committed. |
| 36 | /// In particular, it monitors changes in the state of every instruction |
| 37 | /// in flight. |
| 38 | /// Instructions are executed in a loop of iterations. The number of iterations |
| 39 | /// is defined by the SourceMgr object. |
| 40 | /// The Backend entrypoint is method 'Run()' which execute cycles in a loop |
| 41 | /// until there are new instructions to dispatch, and not every instruction |
| 42 | /// has been retired. |
| 43 | /// Internally, the Backend collects statistical information in the form of |
| 44 | /// histograms. For example, it tracks how the dispatch group size changes |
| 45 | /// over time. |
| 46 | class Backend { |
| 47 | const llvm::MCSubtargetInfo &STI; |
| 48 | |
| 49 | std::unique_ptr<InstrBuilder> IB; |
| 50 | std::unique_ptr<Scheduler> HWS; |
| 51 | std::unique_ptr<DispatchUnit> DU; |
Andrea Di Biagio | 8af3fe8 | 2018-03-08 16:08:43 +0000 | [diff] [blame] | 52 | SourceMgr &SM; |
Andrea Di Biagio | 3a6b092 | 2018-03-08 13:05:02 +0000 | [diff] [blame] | 53 | unsigned Cycles; |
| 54 | |
| 55 | llvm::DenseMap<unsigned, std::unique_ptr<Instruction>> Instructions; |
| 56 | std::set<HWEventListener *> Listeners; |
| 57 | |
| 58 | void runCycle(unsigned Cycle); |
| 59 | |
| 60 | public: |
| 61 | Backend(const llvm::MCSubtargetInfo &Subtarget, const llvm::MCInstrInfo &MCII, |
Andrea Di Biagio | 8af3fe8 | 2018-03-08 16:08:43 +0000 | [diff] [blame] | 62 | const llvm::MCRegisterInfo &MRI, SourceMgr &Source, |
Andrea Di Biagio | 3a6b092 | 2018-03-08 13:05:02 +0000 | [diff] [blame] | 63 | unsigned DispatchWidth = 0, unsigned RegisterFileSize = 0, |
| 64 | unsigned MaxRetirePerCycle = 0, unsigned LoadQueueSize = 0, |
| 65 | unsigned StoreQueueSize = 0, bool AssumeNoAlias = false) |
| 66 | : STI(Subtarget), |
| 67 | HWS(llvm::make_unique<Scheduler>(this, Subtarget.getSchedModel(), |
| 68 | LoadQueueSize, StoreQueueSize, |
| 69 | AssumeNoAlias)), |
| 70 | DU(llvm::make_unique<DispatchUnit>( |
| 71 | this, MRI, Subtarget.getSchedModel().MicroOpBufferSize, |
| 72 | RegisterFileSize, MaxRetirePerCycle, DispatchWidth, HWS.get())), |
Andrea Di Biagio | 8af3fe8 | 2018-03-08 16:08:43 +0000 | [diff] [blame] | 73 | SM(Source), Cycles(0) { |
Andrea Di Biagio | 0c54129 | 2018-03-10 16:55:07 +0000 | [diff] [blame] | 74 | IB = llvm::make_unique<InstrBuilder>(MCII, HWS->getProcResourceMasks()); |
Clement Courbet | 844f22d | 2018-03-13 13:11:01 +0000 | [diff] [blame^] | 75 | HWS->setDispatchUnit(DU.get()); |
Andrea Di Biagio | 3a6b092 | 2018-03-08 13:05:02 +0000 | [diff] [blame] | 76 | } |
| 77 | |
| 78 | void run() { |
Andrea Di Biagio | 8af3fe8 | 2018-03-08 16:08:43 +0000 | [diff] [blame] | 79 | while (SM.hasNext() || !DU->isRCUEmpty()) |
Andrea Di Biagio | 3a6b092 | 2018-03-08 13:05:02 +0000 | [diff] [blame] | 80 | runCycle(Cycles++); |
| 81 | } |
| 82 | |
Andrea Di Biagio | 8af3fe8 | 2018-03-08 16:08:43 +0000 | [diff] [blame] | 83 | unsigned getNumIterations() const { return SM.getNumIterations(); } |
| 84 | unsigned getNumInstructions() const { return SM.size(); } |
Clement Courbet | 844f22d | 2018-03-13 13:11:01 +0000 | [diff] [blame^] | 85 | const Instruction &getInstruction(unsigned Index) const { |
| 86 | const auto It = Instructions.find(Index); |
| 87 | assert(It != Instructions.end() && "no running instructions with index"); |
| 88 | assert(It->second); |
| 89 | return *Instructions.find(Index)->second; |
| 90 | } |
| 91 | void eraseInstruction(unsigned Index) { Instructions.erase(Index); } |
Andrea Di Biagio | 3a6b092 | 2018-03-08 13:05:02 +0000 | [diff] [blame] | 92 | unsigned getNumCycles() const { return Cycles; } |
| 93 | unsigned getTotalRegisterMappingsCreated() const { |
| 94 | return DU->getTotalRegisterMappingsCreated(); |
| 95 | } |
| 96 | unsigned getMaxUsedRegisterMappings() const { |
| 97 | return DU->getMaxUsedRegisterMappings(); |
| 98 | } |
| 99 | unsigned getDispatchWidth() const { return DU->getDispatchWidth(); } |
| 100 | |
| 101 | const llvm::MCSubtargetInfo &getSTI() const { return STI; } |
| 102 | const llvm::MCSchedModel &getSchedModel() const { |
| 103 | return STI.getSchedModel(); |
| 104 | } |
Andrea Di Biagio | 3a6b092 | 2018-03-08 13:05:02 +0000 | [diff] [blame] | 105 | |
| 106 | double getRThroughput(const InstrDesc &ID) const { |
| 107 | return HWS->getRThroughput(ID); |
| 108 | } |
| 109 | void getBuffersUsage(std::vector<BufferUsageEntry> &Usage) const { |
| 110 | return HWS->getBuffersUsage(Usage); |
| 111 | } |
| 112 | |
| 113 | unsigned getNumRATStalls() const { return DU->getNumRATStalls(); } |
| 114 | unsigned getNumRCUStalls() const { return DU->getNumRCUStalls(); } |
| 115 | unsigned getNumSQStalls() const { return DU->getNumSQStalls(); } |
| 116 | unsigned getNumLDQStalls() const { return DU->getNumLDQStalls(); } |
| 117 | unsigned getNumSTQStalls() const { return DU->getNumSTQStalls(); } |
| 118 | unsigned getNumDispatchGroupStalls() const { |
| 119 | return DU->getNumDispatchGroupStalls(); |
| 120 | } |
| 121 | |
| 122 | const llvm::MCInst &getMCInstFromIndex(unsigned Index) const { |
Andrea Di Biagio | 8af3fe8 | 2018-03-08 16:08:43 +0000 | [diff] [blame] | 123 | return SM.getMCInstFromIndex(Index); |
Andrea Di Biagio | 3a6b092 | 2018-03-08 13:05:02 +0000 | [diff] [blame] | 124 | } |
| 125 | |
| 126 | const InstrDesc &getInstrDesc(const llvm::MCInst &Inst) const { |
| 127 | return IB->getOrCreateInstrDesc(STI, Inst); |
| 128 | } |
| 129 | |
Andrea Di Biagio | 8af3fe8 | 2018-03-08 16:08:43 +0000 | [diff] [blame] | 130 | const SourceMgr &getSourceMgr() const { return SM; } |
Andrea Di Biagio | 3a6b092 | 2018-03-08 13:05:02 +0000 | [diff] [blame] | 131 | |
| 132 | void addEventListener(HWEventListener *Listener); |
| 133 | void notifyCycleBegin(unsigned Cycle); |
Clement Courbet | 844f22d | 2018-03-13 13:11:01 +0000 | [diff] [blame^] | 134 | void notifyInstructionEvent(const HWInstructionEvent &Event); |
Andrea Di Biagio | 3a6b092 | 2018-03-08 13:05:02 +0000 | [diff] [blame] | 135 | void notifyResourceAvailable(const ResourceRef &RR); |
Andrea Di Biagio | 3a6b092 | 2018-03-08 13:05:02 +0000 | [diff] [blame] | 136 | void notifyCycleEnd(unsigned Cycle); |
| 137 | }; |
| 138 | |
| 139 | } // namespace mca |
| 140 | |
| 141 | #endif |