LLVM API Documentation
00001 //===- Target/TargetSchedInfo.h - Target Instruction Sched Info -*- C++ -*-===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file was developed by the LLVM research group and is distributed under 00006 // the University of Illinois Open Source License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // This file describes the target machine to the instruction scheduler. 00011 // 00012 // NOTE: This file is currently sparc V9 specific. 00013 // 00014 //===----------------------------------------------------------------------===// 00015 00016 #ifndef LLVM_TARGET_TARGETSCHEDINFO_H 00017 #define LLVM_TARGET_TARGETSCHEDINFO_H 00018 00019 #include "llvm/Target/TargetInstrInfo.h" 00020 #include "llvm/ADT/hash_map" 00021 #include <string> 00022 00023 namespace llvm { 00024 00025 typedef long long cycles_t; 00026 static const cycles_t HUGE_LATENCY = ~((long long) 1 << (sizeof(cycles_t)-2)); 00027 static const cycles_t INVALID_LATENCY = -HUGE_LATENCY; 00028 00029 //--------------------------------------------------------------------------- 00030 // class MachineResource 00031 // class CPUResource 00032 // 00033 // Purpose: 00034 // Representation of a single machine resource used in specifying 00035 // resource usages of machine instructions for scheduling. 00036 //--------------------------------------------------------------------------- 00037 00038 00039 typedef unsigned resourceId_t; 00040 00041 struct CPUResource { 00042 const std::string rname; 00043 resourceId_t rid; 00044 int maxNumUsers; // MAXINT if no restriction 00045 00046 CPUResource(const std::string& resourceName, int maxUsers); 00047 static CPUResource* getCPUResource(resourceId_t id); 00048 private: 00049 static resourceId_t nextId; 00050 }; 00051 00052 00053 //--------------------------------------------------------------------------- 00054 // struct InstrClassRUsage 00055 // struct InstrRUsageDelta 00056 // struct InstrIssueDelta 00057 // struct InstrRUsage 00058 // 00059 // Purpose: 00060 // The first three are structures used to specify machine resource 00061 // usages for each instruction in a machine description file: 00062 // InstrClassRUsage : resource usages common to all instrs. in a class 00063 // InstrRUsageDelta : add/delete resource usage for individual instrs. 00064 // InstrIssueDelta : add/delete instr. issue info for individual instrs 00065 // 00066 // The last one (InstrRUsage) is the internal representation of 00067 // instruction resource usage constructed from the above three. 00068 //--------------------------------------------------------------------------- 00069 00070 const int MAX_NUM_SLOTS = 32; 00071 const int MAX_NUM_CYCLES = 32; 00072 00073 struct InstrClassRUsage { 00074 InstrSchedClass schedClass; 00075 int totCycles; 00076 00077 // Issue restrictions common to instructions in this class 00078 unsigned maxNumIssue; 00079 bool isSingleIssue; 00080 bool breaksGroup; 00081 cycles_t numBubbles; 00082 00083 // Feasible slots to use for instructions in this class. 00084 // The size of vector S[] is `numSlots'. 00085 unsigned numSlots; 00086 unsigned feasibleSlots[MAX_NUM_SLOTS]; 00087 00088 // Resource usages common to instructions in this class. 00089 // The size of vector V[] is `numRUEntries'. 00090 unsigned numRUEntries; 00091 struct { 00092 resourceId_t resourceId; 00093 unsigned startCycle; 00094 int numCycles; 00095 } V[MAX_NUM_CYCLES]; 00096 }; 00097 00098 struct InstrRUsageDelta { 00099 MachineOpCode opCode; 00100 resourceId_t resourceId; 00101 unsigned startCycle; 00102 int numCycles; 00103 }; 00104 00105 // Specify instruction issue restrictions for individual instructions 00106 // that differ from the common rules for the class. 00107 // 00108 struct InstrIssueDelta { 00109 MachineOpCode opCode; 00110 bool isSingleIssue; 00111 bool breaksGroup; 00112 cycles_t numBubbles; 00113 }; 00114 00115 00116 struct InstrRUsage { 00117 bool sameAsClass; 00118 00119 // Issue restrictions for this instruction 00120 bool isSingleIssue; 00121 bool breaksGroup; 00122 cycles_t numBubbles; 00123 00124 // Feasible slots to use for this instruction. 00125 std::vector<bool> feasibleSlots; 00126 00127 // Resource usages for this instruction, with one resource vector per cycle. 00128 cycles_t numCycles; 00129 std::vector<std::vector<resourceId_t> > resourcesByCycle; 00130 00131 private: 00132 // Conveniences for initializing this structure 00133 void setTo(const InstrClassRUsage& classRU); 00134 00135 void addIssueDelta(const InstrIssueDelta& delta) { 00136 sameAsClass = false; 00137 isSingleIssue = delta.isSingleIssue; 00138 breaksGroup = delta.breaksGroup; 00139 numBubbles = delta.numBubbles; 00140 } 00141 00142 void addUsageDelta (const InstrRUsageDelta& delta); 00143 void setMaxSlots (int maxNumSlots) { 00144 feasibleSlots.resize(maxNumSlots); 00145 } 00146 00147 friend class TargetSchedInfo; // give access to these functions 00148 }; 00149 00150 00151 //--------------------------------------------------------------------------- 00152 /// TargetSchedInfo - Common interface to machine information for 00153 /// instruction scheduling 00154 /// 00155 class TargetSchedInfo { 00156 public: 00157 const TargetMachine& target; 00158 00159 unsigned maxNumIssueTotal; 00160 int longestIssueConflict; 00161 00162 protected: 00163 inline const InstrRUsage& getInstrRUsage(MachineOpCode opCode) const { 00164 assert(opCode >= 0 && opCode < (int) instrRUsages.size()); 00165 return instrRUsages[opCode]; 00166 } 00167 const InstrClassRUsage& getClassRUsage(const InstrSchedClass& sc) const { 00168 assert(sc < numSchedClasses); 00169 return classRUsages[sc]; 00170 } 00171 00172 private: 00173 TargetSchedInfo(const TargetSchedInfo &); // DO NOT IMPLEMENT 00174 void operator=(const TargetSchedInfo &); // DO NOT IMPLEMENT 00175 public: 00176 /*ctor*/ TargetSchedInfo (const TargetMachine& tgt, 00177 int _numSchedClasses, 00178 const InstrClassRUsage* _classRUsages, 00179 const InstrRUsageDelta* _usageDeltas, 00180 const InstrIssueDelta* _issueDeltas, 00181 unsigned _numUsageDeltas, 00182 unsigned _numIssueDeltas); 00183 /*dtor*/ virtual ~TargetSchedInfo() {} 00184 00185 inline const TargetInstrInfo& getInstrInfo() const { 00186 return *mii; 00187 } 00188 00189 inline int getNumSchedClasses() const { 00190 return numSchedClasses; 00191 } 00192 00193 inline unsigned getMaxNumIssueTotal() const { 00194 return maxNumIssueTotal; 00195 } 00196 00197 inline unsigned getMaxIssueForClass(const InstrSchedClass& sc) const { 00198 assert(sc < numSchedClasses); 00199 return classRUsages[sc].maxNumIssue; 00200 } 00201 00202 inline InstrSchedClass getSchedClass (MachineOpCode opCode) const { 00203 return getInstrInfo().getSchedClass(opCode); 00204 } 00205 00206 inline bool instrCanUseSlot (MachineOpCode opCode, 00207 unsigned s) const { 00208 assert(s < getInstrRUsage(opCode).feasibleSlots.size() && "Invalid slot!"); 00209 return getInstrRUsage(opCode).feasibleSlots[s]; 00210 } 00211 00212 inline int getLongestIssueConflict () const { 00213 return longestIssueConflict; 00214 } 00215 00216 inline int getMinIssueGap (MachineOpCode fromOp, 00217 MachineOpCode toOp) const { 00218 assert(fromOp < (int) issueGaps.size()); 00219 const std::vector<int>& toGaps = issueGaps[fromOp]; 00220 return (toOp < (int) toGaps.size())? toGaps[toOp] : 0; 00221 } 00222 00223 inline const std::vector<MachineOpCode>& 00224 getConflictList(MachineOpCode opCode) const { 00225 assert(opCode < (int) conflictLists.size()); 00226 return conflictLists[opCode]; 00227 } 00228 00229 inline bool isSingleIssue (MachineOpCode opCode) const { 00230 return getInstrRUsage(opCode).isSingleIssue; 00231 } 00232 00233 inline bool breaksIssueGroup (MachineOpCode opCode) const { 00234 return getInstrRUsage(opCode).breaksGroup; 00235 } 00236 00237 inline unsigned numBubblesAfter (MachineOpCode opCode) const { 00238 return getInstrRUsage(opCode).numBubbles; 00239 } 00240 00241 inline unsigned getCPUResourceNum(int rd)const{ 00242 for(unsigned i=0;i<resourceNumVector.size();i++){ 00243 if(resourceNumVector[i].first == rd) return resourceNumVector[i].second; 00244 } 00245 assert( 0&&"resource not found"); 00246 return 0; 00247 } 00248 00249 00250 protected: 00251 virtual void initializeResources (); 00252 00253 private: 00254 void computeInstrResources(const std::vector<InstrRUsage>& instrRUForClasses); 00255 void computeIssueGaps(const std::vector<InstrRUsage>& instrRUForClasses); 00256 00257 void setGap(int gap, MachineOpCode fromOp, MachineOpCode toOp) { 00258 std::vector<int>& toGaps = issueGaps[fromOp]; 00259 if (toOp >= (int) toGaps.size()) 00260 toGaps.resize(toOp+1); 00261 toGaps[toOp] = gap; 00262 } 00263 00264 public: 00265 std::vector<std::pair<int,int> > resourceNumVector; 00266 00267 protected: 00268 unsigned numSchedClasses; 00269 const TargetInstrInfo* mii; 00270 const InstrClassRUsage* classRUsages; // raw array by sclass 00271 const InstrRUsageDelta* usageDeltas; // raw array [1:numUsageDeltas] 00272 const InstrIssueDelta* issueDeltas; // raw array [1:numIssueDeltas] 00273 unsigned numUsageDeltas; 00274 unsigned numIssueDeltas; 00275 00276 std::vector<InstrRUsage> instrRUsages; // indexed by opcode 00277 std::vector<std::vector<int> > issueGaps; // indexed by [opcode1][opcode2] 00278 std::vector<std::vector<MachineOpCode> > 00279 conflictLists; // indexed by [opcode] 00280 00281 00282 friend class ModuloSchedulingPass; 00283 friend class MSSchedule; 00284 00285 }; 00286 00287 } // End llvm namespace 00288 00289 #endif