blob: 9f61034d61ef86503742fdf517d3be52a73554a9 [file] [log] [blame]
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +00001//===--------------------- Dispatch.cpp -------------------------*- 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///
Matt Davisb7972f82018-05-16 17:07:08 +000011/// This file implements methods declared by the DispatchUnit class.
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +000012///
13//===----------------------------------------------------------------------===//
14
15#include "Dispatch.h"
16#include "Backend.h"
Clement Courbet844f22d2018-03-13 13:11:01 +000017#include "HWEventListener.h"
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +000018#include "Scheduler.h"
19#include "llvm/Support/Debug.h"
20
21using namespace llvm;
22
23#define DEBUG_TYPE "llvm-mca"
24
25namespace mca {
26
Matt Davis21a8d322018-05-07 18:29:15 +000027void DispatchUnit::notifyInstructionDispatched(const InstRef &IR,
Andrea Di Biagio94fafdf2018-03-24 16:05:36 +000028 ArrayRef<unsigned> UsedRegs) {
Nicola Zaghend34e60c2018-05-14 12:53:11 +000029 LLVM_DEBUG(dbgs() << "[E] Instruction Dispatched: " << IR << '\n');
Matt Davis21a8d322018-05-07 18:29:15 +000030 Owner->notifyInstructionEvent(HWInstructionDispatchedEvent(IR, UsedRegs));
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +000031}
32
Matt Davis21a8d322018-05-07 18:29:15 +000033void DispatchUnit::notifyInstructionRetired(const InstRef &IR) {
Nicola Zaghend34e60c2018-05-14 12:53:11 +000034 LLVM_DEBUG(dbgs() << "[E] Instruction Retired: " << IR << '\n');
Andrea Di Biagio12ef5262018-03-21 18:11:05 +000035 SmallVector<unsigned, 4> FreedRegs(RAT->getNumRegisterFiles());
Andrea Di Biagio8ea3a342018-05-14 15:08:22 +000036 const InstrDesc &Desc = IR.getInstruction()->getDesc();
37
Matt Davis21a8d322018-05-07 18:29:15 +000038 for (const std::unique_ptr<WriteState> &WS : IR.getInstruction()->getDefs())
Andrea Di Biagio8ea3a342018-05-14 15:08:22 +000039 RAT->removeRegisterWrite(*WS.get(), FreedRegs, !Desc.isZeroLatency());
Matt Davis21a8d322018-05-07 18:29:15 +000040 Owner->notifyInstructionEvent(HWInstructionRetiredEvent(IR, FreedRegs));
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +000041}
42
Matt Davis21a8d322018-05-07 18:29:15 +000043bool DispatchUnit::checkRAT(const InstRef &IR) {
Andrea Di Biagio9ecb4012018-03-27 15:23:41 +000044 SmallVector<unsigned, 4> RegDefs;
Matt Davis21a8d322018-05-07 18:29:15 +000045 for (const std::unique_ptr<WriteState> &RegDef :
46 IR.getInstruction()->getDefs())
Andrea Di Biagio9ecb4012018-03-27 15:23:41 +000047 RegDefs.emplace_back(RegDef->getRegisterID());
48
49 unsigned RegisterMask = RAT->isAvailable(RegDefs);
Andrea Di Biagioe64f3b12018-03-18 15:33:27 +000050 // A mask with all zeroes means: register files are available.
51 if (RegisterMask) {
Matt Davis21a8d322018-05-07 18:29:15 +000052 Owner->notifyStallEvent(HWStallEvent(HWStallEvent::RegisterFileStall, IR));
Andrea Di Biagioe64f3b12018-03-18 15:33:27 +000053 return false;
54 }
55
56 return true;
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +000057}
58
Matt Davis21a8d322018-05-07 18:29:15 +000059bool DispatchUnit::checkRCU(const InstRef &IR) {
60 const unsigned NumMicroOps = IR.getInstruction()->getDesc().NumMicroOps;
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +000061 if (RCU->isAvailable(NumMicroOps))
62 return true;
Andrea Di Biagio91ab2ee2018-03-19 13:23:07 +000063 Owner->notifyStallEvent(
Matt Davis21a8d322018-05-07 18:29:15 +000064 HWStallEvent(HWStallEvent::RetireControlUnitStall, IR));
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +000065 return false;
66}
67
Matt Davis21a8d322018-05-07 18:29:15 +000068bool DispatchUnit::checkScheduler(const InstRef &IR) {
69 return SC->canBeDispatched(IR);
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +000070}
71
Andrea Di Biagio4732d43ca2018-03-14 14:57:23 +000072void DispatchUnit::updateRAWDependencies(ReadState &RS,
73 const MCSubtargetInfo &STI) {
74 SmallVector<WriteState *, 4> DependentWrites;
75
76 collectWrites(DependentWrites, RS.getRegisterID());
77 RS.setDependentWrites(DependentWrites.size());
Nicola Zaghend34e60c2018-05-14 12:53:11 +000078 LLVM_DEBUG(dbgs() << "Found " << DependentWrites.size()
79 << " dependent writes\n");
Andrea Di Biagio4732d43ca2018-03-14 14:57:23 +000080 // We know that this read depends on all the writes in DependentWrites.
81 // For each write, check if we have ReadAdvance information, and use it
82 // to figure out in how many cycles this read becomes available.
83 const ReadDescriptor &RD = RS.getDescriptor();
84 if (!RD.HasReadAdvanceEntries) {
85 for (WriteState *WS : DependentWrites)
86 WS->addUser(&RS, /* ReadAdvance */ 0);
87 return;
88 }
89
90 const MCSchedModel &SM = STI.getSchedModel();
91 const MCSchedClassDesc *SC = SM.getSchedClassDesc(RD.SchedClassID);
92 for (WriteState *WS : DependentWrites) {
93 unsigned WriteResID = WS->getWriteResourceID();
Andrea Di Biagio0a837ef2018-03-29 14:26:56 +000094 int ReadAdvance = STI.getReadAdvanceCycles(SC, RD.UseIndex, WriteResID);
Andrea Di Biagio4732d43ca2018-03-14 14:57:23 +000095 WS->addUser(&RS, ReadAdvance);
96 }
97 // Prepare the set for another round.
98 DependentWrites.clear();
99}
100
Matt Davis21a8d322018-05-07 18:29:15 +0000101void DispatchUnit::dispatch(InstRef IR, const MCSubtargetInfo &STI) {
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000102 assert(!CarryOver && "Cannot dispatch another instruction!");
Matt Davis21a8d322018-05-07 18:29:15 +0000103 Instruction &IS = *IR.getInstruction();
104 const InstrDesc &Desc = IS.getDesc();
105 const unsigned NumMicroOps = Desc.NumMicroOps;
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000106 if (NumMicroOps > DispatchWidth) {
107 assert(AvailableEntries == DispatchWidth);
108 AvailableEntries = 0;
109 CarryOver = NumMicroOps - DispatchWidth;
110 } else {
111 assert(AvailableEntries >= NumMicroOps);
112 AvailableEntries -= NumMicroOps;
113 }
114
Andrea Di Biagio8ea3a342018-05-14 15:08:22 +0000115 // A dependency-breaking instruction doesn't have to wait on the register
116 // input operands, and it is often optimized at register renaming stage.
117 // Update RAW dependencies if this instruction is not a dependency-breaking
118 // instruction. A dependency-breaking instruction is a zero-latency
119 // instruction that doesn't consume hardware resources.
120 // An example of dependency-breaking instruction on X86 is a zero-idiom XOR.
121 if (!Desc.isZeroLatency())
Matt Davis21a8d322018-05-07 18:29:15 +0000122 for (std::unique_ptr<ReadState> &RS : IS.getUses())
Andrea Di Biagiodb66efc2018-04-25 09:38:58 +0000123 updateRAWDependencies(*RS, STI);
Andrea Di Biagio4732d43ca2018-03-14 14:57:23 +0000124
Andrea Di Biagio8ea3a342018-05-14 15:08:22 +0000125 // By default, a dependency-breaking zero-latency instruction is expected to
126 // be optimized at register renaming stage. That means, no physical register
127 // is allocated to the instruction.
Andrea Di Biagio12ef5262018-03-21 18:11:05 +0000128 SmallVector<unsigned, 4> RegisterFiles(RAT->getNumRegisterFiles());
Matt Davis21a8d322018-05-07 18:29:15 +0000129 for (std::unique_ptr<WriteState> &WS : IS.getDefs())
Andrea Di Biagio8ea3a342018-05-14 15:08:22 +0000130 RAT->addRegisterWrite(*WS, RegisterFiles, !Desc.isZeroLatency());
Andrea Di Biagio4732d43ca2018-03-14 14:57:23 +0000131
Andrea Di Biagio09ea09e2018-03-22 11:39:34 +0000132 // Reserve slots in the RCU, and notify the instruction that it has been
133 // dispatched to the schedulers for execution.
Matt Davis21a8d322018-05-07 18:29:15 +0000134 IS.dispatch(RCU->reserveSlot(IR, NumMicroOps));
Andrea Di Biagio4732d43ca2018-03-14 14:57:23 +0000135
Andrea Di Biagio09ea09e2018-03-22 11:39:34 +0000136 // Notify listeners of the "instruction dispatched" event.
Matt Davis21a8d322018-05-07 18:29:15 +0000137 notifyInstructionDispatched(IR, RegisterFiles);
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000138
Andrea Di Biagio09ea09e2018-03-22 11:39:34 +0000139 // Now move the instruction into the scheduler's queue.
140 // The scheduler is responsible for checking if this is a zero-latency
141 // instruction that doesn't consume pipeline/scheduler resources.
Matt Davis21a8d322018-05-07 18:29:15 +0000142 SC->scheduleInstruction(IR);
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000143}
144
145#ifndef NDEBUG
146void DispatchUnit::dump() const {
147 RAT->dump();
148 RCU->dump();
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000149}
150#endif
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000151} // namespace mca