LLVM API Documentation

MCSchedule.h
Go to the documentation of this file.
00001 //===-- llvm/MC/MCSchedule.h - Scheduling -----------------------*- C++ -*-===//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 //
00010 // This file defines the classes used to describe a subtarget's machine model
00011 // for scheduling and other instruction cost heuristics.
00012 //
00013 //===----------------------------------------------------------------------===//
00014 
00015 #ifndef LLVM_MC_MCSCHEDULE_H
00016 #define LLVM_MC_MCSCHEDULE_H
00017 
00018 #include "llvm/Support/DataTypes.h"
00019 #include <cassert>
00020 
00021 namespace llvm {
00022 
00023 struct InstrItinerary;
00024 
00025 /// Define a kind of processor resource that will be modeled by the scheduler.
00026 struct MCProcResourceDesc {
00027 #ifndef NDEBUG
00028   const char *Name;
00029 #endif
00030   unsigned NumUnits; // Number of resource of this kind
00031   unsigned SuperIdx; // Index of the resources kind that contains this kind.
00032 
00033   // Number of resources that may be buffered.
00034   //
00035   // Buffered resources (BufferSize != 0) may be consumed at some indeterminate
00036   // cycle after dispatch. This should be used for out-of-order cpus when
00037   // instructions that use this resource can be buffered in a reservaton
00038   // station.
00039   //
00040   // Unbuffered resources (BufferSize == 0) always consume their resource some
00041   // fixed number of cycles after dispatch. If a resource is unbuffered, then
00042   // the scheduler will avoid scheduling instructions with conflicting resources
00043   // in the same cycle. This is for in-order cpus, or the in-order portion of
00044   // an out-of-order cpus.
00045   int BufferSize;
00046 
00047   bool operator==(const MCProcResourceDesc &Other) const {
00048     return NumUnits == Other.NumUnits && SuperIdx == Other.SuperIdx
00049       && BufferSize == Other.BufferSize;
00050   }
00051 };
00052 
00053 /// Identify one of the processor resource kinds consumed by a particular
00054 /// scheduling class for the specified number of cycles.
00055 struct MCWriteProcResEntry {
00056   unsigned ProcResourceIdx;
00057   unsigned Cycles;
00058 
00059   bool operator==(const MCWriteProcResEntry &Other) const {
00060     return ProcResourceIdx == Other.ProcResourceIdx && Cycles == Other.Cycles;
00061   }
00062 };
00063 
00064 /// Specify the latency in cpu cycles for a particular scheduling class and def
00065 /// index. -1 indicates an invalid latency. Heuristics would typically consider
00066 /// an instruction with invalid latency to have infinite latency.  Also identify
00067 /// the WriteResources of this def. When the operand expands to a sequence of
00068 /// writes, this ID is the last write in the sequence.
00069 struct MCWriteLatencyEntry {
00070   int Cycles;
00071   unsigned WriteResourceID;
00072 
00073   bool operator==(const MCWriteLatencyEntry &Other) const {
00074     return Cycles == Other.Cycles && WriteResourceID == Other.WriteResourceID;
00075   }
00076 };
00077 
00078 /// Specify the number of cycles allowed after instruction issue before a
00079 /// particular use operand reads its registers. This effectively reduces the
00080 /// write's latency. Here we allow negative cycles for corner cases where
00081 /// latency increases. This rule only applies when the entry's WriteResource
00082 /// matches the write's WriteResource.
00083 ///
00084 /// MCReadAdvanceEntries are sorted first by operand index (UseIdx), then by
00085 /// WriteResourceIdx.
00086 struct MCReadAdvanceEntry {
00087   unsigned UseIdx;
00088   unsigned WriteResourceID;
00089   int Cycles;
00090 
00091   bool operator==(const MCReadAdvanceEntry &Other) const {
00092     return UseIdx == Other.UseIdx && WriteResourceID == Other.WriteResourceID
00093       && Cycles == Other.Cycles;
00094   }
00095 };
00096 
00097 /// Summarize the scheduling resources required for an instruction of a
00098 /// particular scheduling class.
00099 ///
00100 /// Defined as an aggregate struct for creating tables with initializer lists.
00101 struct MCSchedClassDesc {
00102   static const unsigned short InvalidNumMicroOps = UINT16_MAX;
00103   static const unsigned short VariantNumMicroOps = UINT16_MAX - 1;
00104 
00105 #ifndef NDEBUG
00106   const char* Name;
00107 #endif
00108   unsigned short NumMicroOps;
00109   bool     BeginGroup;
00110   bool     EndGroup;
00111   unsigned WriteProcResIdx; // First index into WriteProcResTable.
00112   unsigned NumWriteProcResEntries;
00113   unsigned WriteLatencyIdx; // First index into WriteLatencyTable.
00114   unsigned NumWriteLatencyEntries;
00115   unsigned ReadAdvanceIdx; // First index into ReadAdvanceTable.
00116   unsigned NumReadAdvanceEntries;
00117 
00118   bool isValid() const {
00119     return NumMicroOps != InvalidNumMicroOps;
00120   }
00121   bool isVariant() const {
00122     return NumMicroOps == VariantNumMicroOps;
00123   }
00124 };
00125 
00126 /// Machine model for scheduling, bundling, and heuristics.
00127 ///
00128 /// The machine model directly provides basic information about the
00129 /// microarchitecture to the scheduler in the form of properties. It also
00130 /// optionally refers to scheduler resource tables and itinerary
00131 /// tables. Scheduler resource tables model the latency and cost for each
00132 /// instruction type. Itinerary tables are an independent mechanism that
00133 /// provides a detailed reservation table describing each cycle of instruction
00134 /// execution. Subtargets may define any or all of the above categories of data
00135 /// depending on the type of CPU and selected scheduler.
00136 struct MCSchedModel {
00137   // IssueWidth is the maximum number of instructions that may be scheduled in
00138   // the same per-cycle group.
00139   unsigned IssueWidth;
00140   static const unsigned DefaultIssueWidth = 1;
00141 
00142   // MicroOpBufferSize is the number of micro-ops that the processor may buffer
00143   // for out-of-order execution.
00144   //
00145   // "0" means operations that are not ready in this cycle are not considered
00146   // for scheduling (they go in the pending queue). Latency is paramount. This
00147   // may be more efficient if many instructions are pending in a schedule.
00148   //
00149   // "1" means all instructions are considered for scheduling regardless of
00150   // whether they are ready in this cycle. Latency still causes issue stalls,
00151   // but we balance those stalls against other heuristics.
00152   //
00153   // "> 1" means the processor is out-of-order. This is a machine independent
00154   // estimate of highly machine specific characteristics such as the register
00155   // renaming pool and reorder buffer.
00156   unsigned MicroOpBufferSize;
00157   static const unsigned DefaultMicroOpBufferSize = 0;
00158 
00159   // LoopMicroOpBufferSize is the number of micro-ops that the processor may
00160   // buffer for optimized loop execution. More generally, this represents the
00161   // optimal number of micro-ops in a loop body. A loop may be partially
00162   // unrolled to bring the count of micro-ops in the loop body closer to this
00163   // number.
00164   unsigned LoopMicroOpBufferSize;
00165   static const unsigned DefaultLoopMicroOpBufferSize = 0;
00166 
00167   // LoadLatency is the expected latency of load instructions.
00168   //
00169   // If MinLatency >= 0, this may be overriden for individual load opcodes by
00170   // InstrItinerary OperandCycles.
00171   unsigned LoadLatency;
00172   static const unsigned DefaultLoadLatency = 4;
00173 
00174   // HighLatency is the expected latency of "very high latency" operations.
00175   // See TargetInstrInfo::isHighLatencyDef().
00176   // By default, this is set to an arbitrarily high number of cycles
00177   // likely to have some impact on scheduling heuristics.
00178   // If MinLatency >= 0, this may be overriden by InstrItinData OperandCycles.
00179   unsigned HighLatency;
00180   static const unsigned DefaultHighLatency = 10;
00181 
00182   // MispredictPenalty is the typical number of extra cycles the processor
00183   // takes to recover from a branch misprediction.
00184   unsigned MispredictPenalty;
00185   static const unsigned DefaultMispredictPenalty = 10;
00186   
00187   bool PostRAScheduler; // default value is false
00188 
00189   bool CompleteModel;
00190 
00191   unsigned ProcID;
00192   const MCProcResourceDesc *ProcResourceTable;
00193   const MCSchedClassDesc *SchedClassTable;
00194   unsigned NumProcResourceKinds;
00195   unsigned NumSchedClasses;
00196   // Instruction itinerary tables used by InstrItineraryData.
00197   friend class InstrItineraryData;
00198   const InstrItinerary *InstrItineraries;
00199 
00200   unsigned getProcessorID() const { return ProcID; }
00201 
00202   /// Does this machine model include instruction-level scheduling.
00203   bool hasInstrSchedModel() const { return SchedClassTable; }
00204 
00205   /// Return true if this machine model data for all instructions with a
00206   /// scheduling class (itinerary class or SchedRW list).
00207   bool isComplete() const { return CompleteModel; }
00208 
00209   unsigned getNumProcResourceKinds() const {
00210     return NumProcResourceKinds;
00211   }
00212 
00213   const MCProcResourceDesc *getProcResource(unsigned ProcResourceIdx) const {
00214     assert(hasInstrSchedModel() && "No scheduling machine model");
00215 
00216     assert(ProcResourceIdx < NumProcResourceKinds && "bad proc resource idx");
00217     return &ProcResourceTable[ProcResourceIdx];
00218   }
00219 
00220   const MCSchedClassDesc *getSchedClassDesc(unsigned SchedClassIdx) const {
00221     assert(hasInstrSchedModel() && "No scheduling machine model");
00222 
00223     assert(SchedClassIdx < NumSchedClasses && "bad scheduling class idx");
00224     return &SchedClassTable[SchedClassIdx];
00225   }
00226 
00227   // /\brief Returns a default initialiszed mdoel.  Used for unknown processors.
00228   static MCSchedModel GetDefaultSchedModel() {
00229     MCSchedModel Ret = { DefaultIssueWidth,
00230                          DefaultMicroOpBufferSize,
00231                          DefaultLoopMicroOpBufferSize,
00232                          DefaultLoadLatency,
00233                          DefaultHighLatency,
00234                          DefaultMispredictPenalty,
00235                          false,
00236                          true,
00237                          0,
00238                          nullptr,
00239                          nullptr,
00240                          0,
00241                          0,
00242                          nullptr
00243                        };
00244     return Ret;
00245   }
00246 };
00247 
00248 } // End llvm namespace
00249 
00250 #endif