LLVM  9.0.0svn
MCInstrItineraries.h
Go to the documentation of this file.
1 //===- llvm/MC/MCInstrItineraries.h - Scheduling ----------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file describes the structures used for instruction
10 // itineraries, stages, and operand reads/writes. This is used by
11 // schedulers to determine instruction stages and latencies.
12 //
13 //===----------------------------------------------------------------------===//
14 
15 #ifndef LLVM_MC_MCINSTRITINERARIES_H
16 #define LLVM_MC_MCINSTRITINERARIES_H
17 
18 #include "llvm/MC/MCSchedule.h"
19 #include <algorithm>
20 
21 namespace llvm {
22 
23 //===----------------------------------------------------------------------===//
24 /// These values represent a non-pipelined step in
25 /// the execution of an instruction. Cycles represents the number of
26 /// discrete time slots needed to complete the stage. Units represent
27 /// the choice of functional units that can be used to complete the
28 /// stage. Eg. IntUnit1, IntUnit2. NextCycles indicates how many
29 /// cycles should elapse from the start of this stage to the start of
30 /// the next stage in the itinerary. A value of -1 indicates that the
31 /// next stage should start immediately after the current one.
32 /// For example:
33 ///
34 /// { 1, x, -1 }
35 /// indicates that the stage occupies FU x for 1 cycle and that
36 /// the next stage starts immediately after this one.
37 ///
38 /// { 2, x|y, 1 }
39 /// indicates that the stage occupies either FU x or FU y for 2
40 /// consecutive cycles and that the next stage starts one cycle
41 /// after this stage starts. That is, the stage requirements
42 /// overlap in time.
43 ///
44 /// { 1, x, 0 }
45 /// indicates that the stage occupies FU x for 1 cycle and that
46 /// the next stage starts in this same cycle. This can be used to
47 /// indicate that the instruction requires multiple stages at the
48 /// same time.
49 ///
50 /// FU reservation can be of two different kinds:
51 /// - FUs which instruction actually requires
52 /// - FUs which instruction just reserves. Reserved unit is not available for
53 /// execution of other instruction. However, several instructions can reserve
54 /// the same unit several times.
55 /// Such two types of units reservation is used to model instruction domain
56 /// change stalls, FUs using the same resource (e.g. same register file), etc.
57 
58 struct InstrStage {
60  Required = 0,
62  };
63 
64  unsigned Cycles_; ///< Length of stage in machine cycles
65  unsigned Units_; ///< Choice of functional units
66  int NextCycles_; ///< Number of machine cycles to next stage
67  ReservationKinds Kind_; ///< Kind of the FU reservation
68 
69  /// Returns the number of cycles the stage is occupied.
70  unsigned getCycles() const {
71  return Cycles_;
72  }
73 
74  /// Returns the choice of FUs.
75  unsigned getUnits() const {
76  return Units_;
77  }
78 
80  return Kind_;
81  }
82 
83  /// Returns the number of cycles from the start of this stage to the
84  /// start of the next stage in the itinerary
85  unsigned getNextCycles() const {
86  return (NextCycles_ >= 0) ? (unsigned)NextCycles_ : Cycles_;
87  }
88 };
89 
90 //===----------------------------------------------------------------------===//
91 /// An itinerary represents the scheduling information for an instruction.
92 /// This includes a set of stages occupied by the instruction and the pipeline
93 /// cycle in which operands are read and written.
94 ///
96  int16_t NumMicroOps; ///< # of micro-ops, -1 means it's variable
97  uint16_t FirstStage; ///< Index of first stage in itinerary
98  uint16_t LastStage; ///< Index of last + 1 stage in itinerary
99  uint16_t FirstOperandCycle; ///< Index of first operand rd/wr
100  uint16_t LastOperandCycle; ///< Index of last + 1 operand rd/wr
101 };
102 
103 //===----------------------------------------------------------------------===//
104 /// Itinerary data supplied by a subtarget to be used by a target.
105 ///
107 public:
108  MCSchedModel SchedModel =
109  MCSchedModel::GetDefaultSchedModel(); ///< Basic machine properties.
110  const InstrStage *Stages = nullptr; ///< Array of stages selected
111  const unsigned *OperandCycles = nullptr; ///< Array of operand cycles selected
112  const unsigned *Forwardings = nullptr; ///< Array of pipeline forwarding paths
113  const InstrItinerary *Itineraries =
114  nullptr; ///< Array of itineraries selected
115 
116  InstrItineraryData() = default;
118  const unsigned *OS, const unsigned *F)
119  : SchedModel(SM), Stages(S), OperandCycles(OS), Forwardings(F),
120  Itineraries(SchedModel.InstrItineraries) {}
121 
122  /// Returns true if there are no itineraries.
123  bool isEmpty() const { return Itineraries == nullptr; }
124 
125  /// Returns true if the index is for the end marker itinerary.
126  bool isEndMarker(unsigned ItinClassIndx) const {
127  return ((Itineraries[ItinClassIndx].FirstStage == UINT16_MAX) &&
128  (Itineraries[ItinClassIndx].LastStage == UINT16_MAX));
129  }
130 
131  /// Return the first stage of the itinerary.
132  const InstrStage *beginStage(unsigned ItinClassIndx) const {
133  unsigned StageIdx = Itineraries[ItinClassIndx].FirstStage;
134  return Stages + StageIdx;
135  }
136 
137  /// Return the last+1 stage of the itinerary.
138  const InstrStage *endStage(unsigned ItinClassIndx) const {
139  unsigned StageIdx = Itineraries[ItinClassIndx].LastStage;
140  return Stages + StageIdx;
141  }
142 
143  /// Return the total stage latency of the given class. The latency is
144  /// the maximum completion time for any stage in the itinerary. If no stages
145  /// exist, it defaults to one cycle.
146  unsigned getStageLatency(unsigned ItinClassIndx) const {
147  // If the target doesn't provide itinerary information, use a simple
148  // non-zero default value for all instructions.
149  if (isEmpty())
150  return 1;
151 
152  // Calculate the maximum completion time for any stage.
153  unsigned Latency = 0, StartCycle = 0;
154  for (const InstrStage *IS = beginStage(ItinClassIndx),
155  *E = endStage(ItinClassIndx); IS != E; ++IS) {
156  Latency = std::max(Latency, StartCycle + IS->getCycles());
157  StartCycle += IS->getNextCycles();
158  }
159  return Latency;
160  }
161 
162  /// Return the cycle for the given class and operand. Return -1 if no
163  /// cycle is specified for the operand.
164  int getOperandCycle(unsigned ItinClassIndx, unsigned OperandIdx) const {
165  if (isEmpty())
166  return -1;
167 
168  unsigned FirstIdx = Itineraries[ItinClassIndx].FirstOperandCycle;
169  unsigned LastIdx = Itineraries[ItinClassIndx].LastOperandCycle;
170  if ((FirstIdx + OperandIdx) >= LastIdx)
171  return -1;
172 
173  return (int)OperandCycles[FirstIdx + OperandIdx];
174  }
175 
176  /// Return true if there is a pipeline forwarding between instructions
177  /// of itinerary classes DefClass and UseClasses so that value produced by an
178  /// instruction of itinerary class DefClass, operand index DefIdx can be
179  /// bypassed when it's read by an instruction of itinerary class UseClass,
180  /// operand index UseIdx.
181  bool hasPipelineForwarding(unsigned DefClass, unsigned DefIdx,
182  unsigned UseClass, unsigned UseIdx) const {
183  unsigned FirstDefIdx = Itineraries[DefClass].FirstOperandCycle;
184  unsigned LastDefIdx = Itineraries[DefClass].LastOperandCycle;
185  if ((FirstDefIdx + DefIdx) >= LastDefIdx)
186  return false;
187  if (Forwardings[FirstDefIdx + DefIdx] == 0)
188  return false;
189 
190  unsigned FirstUseIdx = Itineraries[UseClass].FirstOperandCycle;
191  unsigned LastUseIdx = Itineraries[UseClass].LastOperandCycle;
192  if ((FirstUseIdx + UseIdx) >= LastUseIdx)
193  return false;
194 
195  return Forwardings[FirstDefIdx + DefIdx] ==
196  Forwardings[FirstUseIdx + UseIdx];
197  }
198 
199  /// Compute and return the use operand latency of a given itinerary
200  /// class and operand index if the value is produced by an instruction of the
201  /// specified itinerary class and def operand index.
202  int getOperandLatency(unsigned DefClass, unsigned DefIdx,
203  unsigned UseClass, unsigned UseIdx) const {
204  if (isEmpty())
205  return -1;
206 
207  int DefCycle = getOperandCycle(DefClass, DefIdx);
208  if (DefCycle == -1)
209  return -1;
210 
211  int UseCycle = getOperandCycle(UseClass, UseIdx);
212  if (UseCycle == -1)
213  return -1;
214 
215  UseCycle = DefCycle - UseCycle + 1;
216  if (UseCycle > 0 &&
217  hasPipelineForwarding(DefClass, DefIdx, UseClass, UseIdx))
218  // FIXME: This assumes one cycle benefit for every pipeline forwarding.
219  --UseCycle;
220  return UseCycle;
221  }
222 
223  /// Return the number of micro-ops that the given class decodes to.
224  /// Return -1 for classes that require dynamic lookup via TargetInstrInfo.
225  int getNumMicroOps(unsigned ItinClassIndx) const {
226  if (isEmpty())
227  return 1;
228  return Itineraries[ItinClassIndx].NumMicroOps;
229  }
230 };
231 
232 } // end namespace llvm
233 
234 #endif // LLVM_MC_MCINSTRITINERARIES_H
GCNRegPressure max(const GCNRegPressure &P1, const GCNRegPressure &P2)
This class represents lattice values for constants.
Definition: AllocatorList.h:23
const InstrStage * beginStage(unsigned ItinClassIndx) const
Return the first stage of the itinerary.
unsigned Units_
Choice of functional units.
unsigned getUnits() const
Returns the choice of FUs.
int NextCycles_
Number of machine cycles to next stage.
F(f)
InstrItineraryData(const MCSchedModel &SM, const InstrStage *S, const unsigned *OS, const unsigned *F)
Itinerary data supplied by a subtarget to be used by a target.
int getNumMicroOps(unsigned ItinClassIndx) const
Return the number of micro-ops that the given class decodes to.
unsigned getStageLatency(unsigned ItinClassIndx) const
Return the total stage latency of the given class.
static const MCSchedModel & GetDefaultSchedModel()
Returns the default initialized model.
Definition: MCSchedule.h:379
unsigned getNextCycles() const
Returns the number of cycles from the start of this stage to the start of the next stage in the itine...
ReservationKinds getReservationKind() const
int getOperandLatency(unsigned DefClass, unsigned DefIdx, unsigned UseClass, unsigned UseIdx) const
Compute and return the use operand latency of a given itinerary class and operand index if the value ...
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
int16_t NumMicroOps
of micro-ops, -1 means it&#39;s variable
ReservationKinds Kind_
Kind of the FU reservation.
unsigned Cycles_
Length of stage in machine cycles.
bool isEndMarker(unsigned ItinClassIndx) const
Returns true if the index is for the end marker itinerary.
unsigned getCycles() const
Returns the number of cycles the stage is occupied.
uint16_t LastOperandCycle
Index of last + 1 operand rd/wr.
uint16_t FirstStage
Index of first stage in itinerary.
bool isEmpty() const
Returns true if there are no itineraries.
These values represent a non-pipelined step in the execution of an instruction.
const InstrStage * endStage(unsigned ItinClassIndx) const
Return the last+1 stage of the itinerary.
bool hasPipelineForwarding(unsigned DefClass, unsigned DefIdx, unsigned UseClass, unsigned UseIdx) const
Return true if there is a pipeline forwarding between instructions of itinerary classes DefClass and ...
uint16_t LastStage
Index of last + 1 stage in itinerary.
uint16_t FirstOperandCycle
Index of first operand rd/wr.
An itinerary represents the scheduling information for an instruction.
int getOperandCycle(unsigned ItinClassIndx, unsigned OperandIdx) const
Return the cycle for the given class and operand.
Machine model for scheduling, bundling, and heuristics.
Definition: MCSchedule.h:244