/// indicate that the instruction requires multiple stages at the
/// same time.
///
+/// FU reservation can be of two different kinds:
+/// - FUs which instruction actually requires
+/// - FUs which instruction just reserves. Reserved unit is not available for
+/// execution of other instruction. However, several instructions can reserve
+/// the same unit several times.
+/// Such two types of units reservation is used to model instruction domain
+/// change stalls, FUs using the same resource (e.g. same register file), etc.
+
struct InstrStage {
+ enum ReservationKinds {
+ Required = 0,
+ Reserved = 1
+ };
+
unsigned Cycles_; ///< Length of stage in machine cycles
unsigned Units_; ///< Choice of functional units
- int NextCycles_; ///< Number of machine cycles to next stage
+ int NextCycles_; ///< Number of machine cycles to next stage
+ ReservationKinds Kind_; ///< Kind of the FU reservation
/// getCycles - returns the number of cycles the stage is occupied
unsigned getCycles() const {
return Units_;
}
+ ReservationKinds getReservationKind() const {
+ return Kind_;
+ }
+
/// getNextCycles - returns the number of cycles from the start of
/// this stage to the start of the next stage in the itinerary
unsigned getNextCycles() const {
/// Instruction itinerary Data - Itinerary data supplied by a subtarget to be
/// used by a target.
///
-struct InstrItineraryData {
+class InstrItineraryData {
+public:
const InstrStage *Stages; ///< Array of stages selected
const unsigned *OperandCycles; ///< Array of operand cycles selected
const InstrItinerary *Itineratries; ///< Array of itineraries selected
/// isEmpty - Returns true if there are no itineraries.
///
bool isEmpty() const { return Itineratries == 0; }
-
+
+ /// isEndMarker - Returns true if the index is for the end marker
+ /// itinerary.
+ ///
+ bool isEndMarker(unsigned ItinClassIndx) const {
+ return ((Itineratries[ItinClassIndx].FirstStage == ~0U) &&
+ (Itineratries[ItinClassIndx].LastStage == ~0U));
+ }
+
/// beginStage - Return the first stage of the itinerary.
///
const InstrStage *beginStage(unsigned ItinClassIndx) const {
return Stages + StageIdx;
}
- /// getLatency - Return the scheduling latency of the given class. A
- /// simple latency value for an instruction is an over-simplification
- /// for some architectures, but it's a reasonable first approximation.
+ /// getStageLatency - Return the total stage latency of the given
+ /// class. The latency is the maximum completion time for any stage
+ /// in the itinerary.
///
- unsigned getLatency(unsigned ItinClassIndx) const {
- // If the target doesn't provide latency information, use a simple
- // non-zero default value for all instructions.
+ unsigned getStageLatency(unsigned ItinClassIndx) const {
+ // If the target doesn't provide itinerary information, use a
+ // simple non-zero default value for all instructions.
if (isEmpty())
return 1;
- // Caclulate the maximum completion time for any stage. The
- // assumption is that all inputs are consumed at the start of the
- // first stage and that all outputs are produced at the end of the
- // latest completing last stage.
+ // Calculate the maximum completion time for any stage.
unsigned Latency = 0, StartCycle = 0;
for (const InstrStage *IS = beginStage(ItinClassIndx),
*E = endStage(ItinClassIndx); IS != E; ++IS) {
return Latency;
}
+
+ /// getOperandCycle - Return the cycle for the given class and
+ /// operand. Return -1 if no cycle is specified for the operand.
+ ///
+ int getOperandCycle(unsigned ItinClassIndx, unsigned OperandIdx) const {
+ if (isEmpty())
+ return -1;
+
+ unsigned FirstIdx = Itineratries[ItinClassIndx].FirstOperandCycle;
+ unsigned LastIdx = Itineratries[ItinClassIndx].LastOperandCycle;
+ if ((FirstIdx + OperandIdx) >= LastIdx)
+ return -1;
+
+ return (int)OperandCycles[FirstIdx + OperandIdx];
+ }
};