misched: count micro-ops toward the issue limit.
[oota-llvm.git] / include / llvm / MC / MCInstrItineraries.h
1 //===-- llvm/MC/MCInstrItineraries.h - Scheduling ---------------*- 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 //
10 // This file describes the structures used for instruction
11 // itineraries, stages, and operand reads/writes.  This is used by
12 // schedulers to determine instruction stages and latencies.
13 //
14 //===----------------------------------------------------------------------===//
15
16 #ifndef LLVM_MC_MCINSTRITINERARIES_H
17 #define LLVM_MC_MCINSTRITINERARIES_H
18
19 #include <algorithm>
20
21 namespace llvm {
22
23 //===----------------------------------------------------------------------===//
24 /// Instruction stage - 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 ///      consecuative 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 {
59   enum ReservationKinds {
60     Required = 0,
61     Reserved = 1
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   /// getCycles - returns the number of cycles the stage is occupied
70   unsigned getCycles() const {
71     return Cycles_;
72   }
73
74   /// getUnits - returns the choice of FUs
75   unsigned getUnits() const {
76     return Units_;
77   }
78
79   ReservationKinds getReservationKind() const {
80     return Kind_;
81   }
82
83   /// getNextCycles - returns the number of cycles from the start of
84   /// this stage to the start of the next stage in the itinerary
85   unsigned getNextCycles() const {
86     return (NextCycles_ >= 0) ? (unsigned)NextCycles_ : Cycles_;
87   }
88 };
89
90
91 //===----------------------------------------------------------------------===//
92 /// Instruction itinerary - An itinerary represents the scheduling
93 /// information for an instruction. This includes a set of stages
94 /// occupies by the instruction, and the pipeline cycle in which
95 /// operands are read and written.
96 ///
97 struct InstrItinerary {
98   int      NumMicroOps;        ///< # of micro-ops, -1 means it's variable
99   unsigned FirstStage;         ///< Index of first stage in itinerary
100   unsigned LastStage;          ///< Index of last + 1 stage in itinerary
101   unsigned FirstOperandCycle;  ///< Index of first operand rd/wr
102   unsigned LastOperandCycle;   ///< Index of last + 1 operand rd/wr
103 };
104
105
106 //===----------------------------------------------------------------------===//
107 /// Instruction itinerary properties - These properties provide general
108 /// information about the microarchitecture to the scheduler.
109 ///
110 struct InstrItineraryProps {
111   // IssueWidth is the maximum number of instructions that may be scheduled in
112   // the same per-cycle group.
113   unsigned IssueWidth;
114   static const unsigned DefaultIssueWidth = 1;
115
116   // MinLatency is the minimum latency between a register write
117   // followed by a data dependent read. This determines which
118   // instructions may be scheduled in the same per-cycle group. This
119   // is distinct from *expected* latency, which determines the likely
120   // critical path but does not guarantee a pipeline
121   // hazard. MinLatency can always be overridden by the number of
122   // InstrStage cycles.
123   //
124   // (-1) Standard in-order processor.
125   //      Use InstrItinerary OperandCycles as MinLatency.
126   //      If no OperandCycles exist, then use the cycle of the last InstrStage.
127   //
128   //  (0) Out-of-order processor, or in-order with bundled dependencies.
129   //      RAW dependencies may be dispatched in the same cycle.
130   //      Optional InstrItinerary OperandCycles provides expected latency.
131   //
132   // (>0) In-order processor with variable latencies.
133   //      Use the greater of this value or the cycle of the last InstrStage.
134   //      Optional InstrItinerary OperandCycles provides expected latency.
135   //      TODO: can't yet specify both min and expected latency per operand.
136   int MinLatency;
137   static const unsigned DefaultMinLatency = -1;
138
139   // LoadLatency is the expected latency of load instructions.
140   //
141   // If MinLatency >= 0, this may be overriden for individual load opcodes by
142   // InstrItinerary OperandCycles.
143   unsigned LoadLatency;
144   static const unsigned DefaultLoadLatency = 4;
145
146   // HighLatency is the expected latency of "very high latency" operations.
147   // See TargetInstrInfo::isHighLatencyDef().
148   // By default, this is set to an arbitrarily high number of cycles
149   // likely to have some impact on scheduling heuristics.
150   // If MinLatency >= 0, this may be overriden by InstrItinData OperandCycles.
151   unsigned HighLatency;
152   static const unsigned DefaultHighLatency = 10;
153
154   // Default's must be specified as static const literals so that tablegenerated
155   // target code can use it in static initializers. The defaults need to be
156   // initialized in this default ctor because some clients directly instantiate
157   // InstrItineraryData instead of using a generated itinerary.
158   InstrItineraryProps(): IssueWidth(DefaultMinLatency),
159                          MinLatency(DefaultMinLatency),
160                          LoadLatency(DefaultLoadLatency),
161                          HighLatency(DefaultHighLatency) {}
162
163   InstrItineraryProps(unsigned iw, int ml, unsigned ll, unsigned hl):
164     IssueWidth(iw), MinLatency(ml), LoadLatency(ll), HighLatency(hl) {}
165 };
166
167 //===----------------------------------------------------------------------===//
168 /// Encapsulate all subtarget specific information for scheduling for use with
169 /// SubtargetInfoKV.
170 struct InstrItinerarySubtargetValue {
171   const InstrItineraryProps *Props;
172   const InstrItinerary *Itineraries;
173 };
174
175 //===----------------------------------------------------------------------===//
176 /// Instruction itinerary Data - Itinerary data supplied by a subtarget to be
177 /// used by a target.
178 ///
179 class InstrItineraryData {
180 public:
181   InstrItineraryProps Props;
182   const InstrStage     *Stages;         ///< Array of stages selected
183   const unsigned       *OperandCycles;  ///< Array of operand cycles selected
184   const unsigned       *Forwardings;    ///< Array of pipeline forwarding pathes
185   const InstrItinerary *Itineraries;    ///< Array of itineraries selected
186
187   /// Ctors.
188   ///
189   InstrItineraryData() : Stages(0), OperandCycles(0), Forwardings(0),
190                          Itineraries(0) {}
191
192   InstrItineraryData(const InstrItineraryProps *P, const InstrStage *S,
193                      const unsigned *OS, const unsigned *F,
194                      const InstrItinerary *I)
195     : Props(*P), Stages(S), OperandCycles(OS), Forwardings(F), Itineraries(I) {}
196
197   /// isEmpty - Returns true if there are no itineraries.
198   ///
199   bool isEmpty() const { return Itineraries == 0; }
200
201   /// isEndMarker - Returns true if the index is for the end marker
202   /// itinerary.
203   ///
204   bool isEndMarker(unsigned ItinClassIndx) const {
205     return ((Itineraries[ItinClassIndx].FirstStage == ~0U) &&
206             (Itineraries[ItinClassIndx].LastStage == ~0U));
207   }
208
209   /// beginStage - Return the first stage of the itinerary.
210   ///
211   const InstrStage *beginStage(unsigned ItinClassIndx) const {
212     unsigned StageIdx = Itineraries[ItinClassIndx].FirstStage;
213     return Stages + StageIdx;
214   }
215
216   /// endStage - Return the last+1 stage of the itinerary.
217   ///
218   const InstrStage *endStage(unsigned ItinClassIndx) const {
219     unsigned StageIdx = Itineraries[ItinClassIndx].LastStage;
220     return Stages + StageIdx;
221   }
222
223   /// getStageLatency - Return the total stage latency of the given
224   /// class.  The latency is the maximum completion time for any stage
225   /// in the itinerary.
226   ///
227   /// InstrStages override the itinerary's MinLatency property. In fact, if the
228   /// stage latencies, which may be zero, are less than MinLatency,
229   /// getStageLatency returns a value less than MinLatency.
230   ///
231   /// If no stages exist, MinLatency is used. If MinLatency is invalid (<0),
232   /// then it defaults to one cycle.
233   unsigned getStageLatency(unsigned ItinClassIndx) const {
234     // If the target doesn't provide itinerary information, use a simple
235     // non-zero default value for all instructions.  Some target's provide a
236     // dummy (Generic) itinerary which should be handled as if it's itinerary is
237     // empty. We identify this by looking for a reference to stage zero (invalid
238     // stage). This is different from beginStage == endStage != 0, which could
239     // be used for zero-latency pseudo ops.
240     if (isEmpty() || Itineraries[ItinClassIndx].FirstStage == 0)
241       return (Props.MinLatency < 0) ? 1 : Props.MinLatency;
242
243     // Calculate the maximum completion time for any stage.
244     unsigned Latency = 0, StartCycle = 0;
245     for (const InstrStage *IS = beginStage(ItinClassIndx),
246            *E = endStage(ItinClassIndx); IS != E; ++IS) {
247       Latency = std::max(Latency, StartCycle + IS->getCycles());
248       StartCycle += IS->getNextCycles();
249     }
250
251     return Latency;
252   }
253
254   /// getOperandCycle - Return the cycle for the given class and
255   /// operand. Return -1 if no cycle is specified for the operand.
256   ///
257   int getOperandCycle(unsigned ItinClassIndx, unsigned OperandIdx) const {
258     if (isEmpty())
259       return -1;
260
261     unsigned FirstIdx = Itineraries[ItinClassIndx].FirstOperandCycle;
262     unsigned LastIdx = Itineraries[ItinClassIndx].LastOperandCycle;
263     if ((FirstIdx + OperandIdx) >= LastIdx)
264       return -1;
265
266     return (int)OperandCycles[FirstIdx + OperandIdx];
267   }
268
269   /// hasPipelineForwarding - Return true if there is a pipeline forwarding
270   /// between instructions of itinerary classes DefClass and UseClasses so that
271   /// value produced by an instruction of itinerary class DefClass, operand
272   /// index DefIdx can be bypassed when it's read by an instruction of
273   /// itinerary class UseClass, operand index UseIdx.
274   bool hasPipelineForwarding(unsigned DefClass, unsigned DefIdx,
275                              unsigned UseClass, unsigned UseIdx) const {
276     unsigned FirstDefIdx = Itineraries[DefClass].FirstOperandCycle;
277     unsigned LastDefIdx = Itineraries[DefClass].LastOperandCycle;
278     if ((FirstDefIdx + DefIdx) >= LastDefIdx)
279       return false;
280     if (Forwardings[FirstDefIdx + DefIdx] == 0)
281       return false;
282
283     unsigned FirstUseIdx = Itineraries[UseClass].FirstOperandCycle;
284     unsigned LastUseIdx = Itineraries[UseClass].LastOperandCycle;
285     if ((FirstUseIdx + UseIdx) >= LastUseIdx)
286       return false;
287
288     return Forwardings[FirstDefIdx + DefIdx] ==
289       Forwardings[FirstUseIdx + UseIdx];
290   }
291
292   /// getOperandLatency - Compute and return the use operand latency of a given
293   /// itinerary class and operand index if the value is produced by an
294   /// instruction of the specified itinerary class and def operand index.
295   int getOperandLatency(unsigned DefClass, unsigned DefIdx,
296                         unsigned UseClass, unsigned UseIdx) const {
297     if (isEmpty())
298       return -1;
299
300     int DefCycle = getOperandCycle(DefClass, DefIdx);
301     if (DefCycle == -1)
302       return -1;
303
304     int UseCycle = getOperandCycle(UseClass, UseIdx);
305     if (UseCycle == -1)
306       return -1;
307
308     UseCycle = DefCycle - UseCycle + 1;
309     if (UseCycle > 0 &&
310         hasPipelineForwarding(DefClass, DefIdx, UseClass, UseIdx))
311       // FIXME: This assumes one cycle benefit for every pipeline forwarding.
312       --UseCycle;
313     return UseCycle;
314   }
315
316   /// getNumMicroOps - Return the number of micro-ops that the given class
317   /// decodes to. Return -1 for classes that require dynamic lookup via
318   /// TargetInstrInfo.
319   int getNumMicroOps(unsigned ItinClassIndx) const {
320     if (isEmpty())
321       return 1;
322     return Itineraries[ItinClassIndx].NumMicroOps;
323   }
324 };
325
326 } // End llvm namespace
327
328 #endif