First cut at the Code Generator using the TableGen methodology.
[oota-llvm.git] / include / llvm / Target / TargetSchedInfo.h
1 //===- Target/TargetSchedInfo.h - Target Instruction Sched Info --*- C++ -*-==//
2 //
3 // This file describes the target machine to the instruction scheduler.
4 //
5 //===----------------------------------------------------------------------===//
6
7 #ifndef LLVM_TARGET_TARGETSCHEDINFO_H
8 #define LLVM_TARGET_TARGETSCHEDINFO_H
9
10 #include "llvm/Target/TargetInstrInfo.h"
11 #include "Support/hash_map"
12 #include <string>
13
14 typedef long long cycles_t; 
15 static const cycles_t HUGE_LATENCY = ~((long long) 1 << (sizeof(cycles_t)-2));
16 static const cycles_t INVALID_LATENCY = -HUGE_LATENCY; 
17 static const unsigned MAX_OPCODE_SIZE = 16;
18
19 class OpCodePair {
20 public:
21   long val;                     // make long by concatenating two opcodes
22   OpCodePair(MachineOpCode op1, MachineOpCode op2)
23     : val((op1 < 0 || op2 < 0)?
24         -1 : (long)((((unsigned) op1) << MAX_OPCODE_SIZE) | (unsigned) op2)) {}
25   bool operator==(const OpCodePair& op) const {
26     return val == op.val;
27   }
28 private:
29   OpCodePair();                 // disable for now
30 };
31
32 namespace HASH_NAMESPACE {
33   template <> struct hash<OpCodePair> {
34     size_t operator()(const OpCodePair& pair) const {
35       return hash<long>()(pair.val);
36     }
37   };
38 }
39
40 //---------------------------------------------------------------------------
41 // class MachineResource 
42 // class CPUResource
43 // 
44 // Purpose:
45 //   Representation of a single machine resource used in specifying
46 //   resource usages of machine instructions for scheduling.
47 //---------------------------------------------------------------------------
48
49
50 typedef unsigned resourceId_t;
51
52 struct MachineResource {
53   const std::string rname;
54   resourceId_t rid;
55   
56   MachineResource(const std::string &resourceName)
57     : rname(resourceName), rid(nextId++) {}
58   
59 private:
60   static resourceId_t nextId;
61   MachineResource();                    // disable
62 };
63
64
65 struct CPUResource : public MachineResource {
66   int maxNumUsers;   // MAXINT if no restriction
67   
68   CPUResource(const std::string& rname, int maxUsers)
69     : MachineResource(rname), maxNumUsers(maxUsers) {}
70 };
71
72
73 //---------------------------------------------------------------------------
74 // struct InstrClassRUsage
75 // struct InstrRUsageDelta 
76 // struct InstrIssueDelta 
77 // struct InstrRUsage 
78 // 
79 // Purpose:
80 //   The first three are structures used to specify machine resource 
81 //   usages for each instruction in a machine description file:
82 //    InstrClassRUsage : resource usages common to all instrs. in a class
83 //    InstrRUsageDelta : add/delete resource usage for individual instrs. 
84 //    InstrIssueDelta  : add/delete instr. issue info for individual instrs 
85 //   
86 //   The last one (InstrRUsage) is the internal representation of
87 //   instruction resource usage constructed from the above three.
88 //---------------------------------------------------------------------------
89
90 const int MAX_NUM_SLOTS  = 32;
91 const int MAX_NUM_CYCLES = 32;
92
93 struct InstrClassRUsage {
94   InstrSchedClass schedClass;
95   int           totCycles;
96   
97   // Issue restrictions common to instructions in this class
98   unsigned      maxNumIssue;
99   bool          isSingleIssue;
100   bool          breaksGroup;
101   cycles_t      numBubbles;
102   
103   // Feasible slots to use for instructions in this class.
104   // The size of vector S[] is `numSlots'.
105   unsigned      numSlots;
106   unsigned      feasibleSlots[MAX_NUM_SLOTS];
107   
108   // Resource usages common to instructions in this class.
109   // The size of vector V[] is `numRUEntries'.
110   unsigned      numRUEntries;
111   struct {
112     resourceId_t resourceId;
113     unsigned    startCycle;
114     int         numCycles;
115   } V[MAX_NUM_CYCLES];
116 };
117
118 struct InstrRUsageDelta {
119   MachineOpCode opCode;
120   resourceId_t  resourceId;
121   unsigned      startCycle;
122   int           numCycles;
123 };
124
125 // Specify instruction issue restrictions for individual instructions
126 // that differ from the common rules for the class.
127 // 
128 struct InstrIssueDelta {
129   MachineOpCode opCode;
130   bool          isSingleIssue;
131   bool          breaksGroup;
132   cycles_t      numBubbles;
133 };
134
135
136 struct InstrRUsage {
137   bool          sameAsClass;
138   
139   // Issue restrictions for this instruction
140   bool          isSingleIssue;
141   bool          breaksGroup;
142   cycles_t      numBubbles;
143   
144   // Feasible slots to use for this instruction.
145   std::vector<bool> feasibleSlots;
146   
147   // Resource usages for this instruction, with one resource vector per cycle.
148   cycles_t      numCycles;
149   std::vector<std::vector<resourceId_t> > resourcesByCycle;
150   
151 private:
152   // Conveniences for initializing this structure
153   void setTo(const InstrClassRUsage& classRU);
154
155   void addIssueDelta(const InstrIssueDelta& delta) {
156     sameAsClass = false;
157     isSingleIssue = delta.isSingleIssue;
158     breaksGroup = delta.breaksGroup;
159     numBubbles = delta.numBubbles;
160   }
161
162   void addUsageDelta    (const InstrRUsageDelta& delta);
163   void setMaxSlots      (int maxNumSlots) {
164     feasibleSlots.resize(maxNumSlots);
165   }
166   
167   friend class TargetSchedInfo; // give access to these functions
168 };
169
170
171 //---------------------------------------------------------------------------
172 /// TargetSchedInfo - Common interface to machine information for 
173 /// instruction scheduling
174 ///
175 struct TargetSchedInfo {
176   const TargetMachine& target;
177   
178   unsigned maxNumIssueTotal;
179   int   longestIssueConflict;
180   
181   int   branchMispredictPenalty;        // 4 for SPARC IIi
182   int   branchTargetUnknownPenalty;     // 2 for SPARC IIi
183   int   l1DCacheMissPenalty;            // 7 or 9 for SPARC IIi
184   int   l1ICacheMissPenalty;            // ? for SPARC IIi
185   
186   bool  inOrderLoads;                   // true for SPARC IIi
187   bool  inOrderIssue;                   // true for SPARC IIi
188   bool  inOrderExec;                    // false for most architectures
189   bool  inOrderRetire;                  // true for most architectures
190   
191 protected:
192   inline const InstrRUsage& getInstrRUsage(MachineOpCode opCode) const {
193     assert(opCode >= 0 && opCode < (int) instrRUsages.size());
194     return instrRUsages[opCode];
195   }
196   const InstrClassRUsage& getClassRUsage(const InstrSchedClass& sc) const {
197     assert(sc < numSchedClasses);
198     return classRUsages[sc];
199   }
200
201 private:
202   TargetSchedInfo(const TargetSchedInfo &);  // DO NOT IMPLEMENT
203   void operator=(const TargetSchedInfo &);  // DO NOT IMPLEMENT
204 public:
205   /*ctor*/         TargetSchedInfo      (const TargetMachine& tgt,
206                                          int                  _numSchedClasses,
207                                          const InstrClassRUsage* _classRUsages,
208                                          const InstrRUsageDelta* _usageDeltas,
209                                          const InstrIssueDelta*  _issueDeltas,
210                                          unsigned _numUsageDeltas,
211                                          unsigned _numIssueDeltas);
212   /*dtor*/ virtual ~TargetSchedInfo() {}
213   
214   inline const TargetInstrInfo& getInstrInfo() const {
215     return *mii;
216   }
217   
218   inline int            getNumSchedClasses()  const {
219     return numSchedClasses;
220   }  
221   
222   inline  unsigned getMaxNumIssueTotal() const {
223     return maxNumIssueTotal;
224   }
225   
226   inline  unsigned getMaxIssueForClass(const InstrSchedClass& sc) const {
227     assert(sc < numSchedClasses);
228     return classRUsages[sc].maxNumIssue;
229   }
230
231   inline InstrSchedClass getSchedClass  (MachineOpCode opCode) const {
232     return getInstrInfo().getSchedClass(opCode);
233   } 
234   
235   inline  bool  instrCanUseSlot         (MachineOpCode opCode,
236                                          unsigned s) const {
237     assert(s < getInstrRUsage(opCode).feasibleSlots.size() && "Invalid slot!");
238     return getInstrRUsage(opCode).feasibleSlots[s];
239   }
240   
241   inline int    getLongestIssueConflict () const {
242     return longestIssueConflict;
243   }
244
245   inline  int   getMinIssueGap          (MachineOpCode fromOp,
246                                          MachineOpCode toOp)   const {
247     assert(fromOp < (int) issueGaps.size());
248     const std::vector<int>& toGaps = issueGaps[fromOp];
249     return (toOp < (int) toGaps.size())? toGaps[toOp] : 0;
250   }
251
252   inline const std::vector<MachineOpCode>&
253                 getConflictList(MachineOpCode opCode) const {
254     assert(opCode < (int) conflictLists.size());
255     return conflictLists[opCode];
256   }
257
258   inline  bool  isSingleIssue           (MachineOpCode opCode) const {
259     return getInstrRUsage(opCode).isSingleIssue;
260   }
261   
262   inline  bool  breaksIssueGroup        (MachineOpCode opCode) const {
263     return getInstrRUsage(opCode).breaksGroup;
264   }
265   
266   inline  unsigned numBubblesAfter      (MachineOpCode opCode) const {
267     return getInstrRUsage(opCode).numBubbles;
268   }
269   
270   inline unsigned getCPUResourceNum(int rd)const{
271     for(unsigned i=0;i<resourceNumVector.size();i++){
272       if(resourceNumVector[i].first == rd) return resourceNumVector[i].second;
273     }
274     assert( 0&&"resource not found");
275     return 0;
276   }
277   
278
279 protected:
280   virtual void  initializeResources     ();
281   
282 private:
283   void computeInstrResources(const std::vector<InstrRUsage>& instrRUForClasses);
284   void computeIssueGaps(const std::vector<InstrRUsage>& instrRUForClasses);
285   
286   void setGap(int gap, MachineOpCode fromOp, MachineOpCode toOp) {
287     std::vector<int>& toGaps = issueGaps[fromOp];
288     if (toOp >= (int) toGaps.size())
289       toGaps.resize(toOp+1);
290     toGaps[toOp] = gap;
291   }
292   
293 public:
294   std::vector<std::pair<int,int> > resourceNumVector;
295   
296 protected:
297   unsigned                 numSchedClasses;
298   const TargetInstrInfo*   mii;
299   const InstrClassRUsage*  classRUsages;        // raw array by sclass
300   const InstrRUsageDelta*  usageDeltas;         // raw array [1:numUsageDeltas]
301   const InstrIssueDelta*   issueDeltas;         // raw array [1:numIssueDeltas]
302   unsigned                 numUsageDeltas;
303   unsigned                 numIssueDeltas;
304   
305   std::vector<InstrRUsage> instrRUsages;    // indexed by opcode
306   std::vector<std::vector<int> > issueGaps; // indexed by [opcode1][opcode2]
307   std::vector<std::vector<MachineOpCode> >
308                            conflictLists;   // indexed by [opcode]
309
310
311
312   friend class ModuloSchedGraph;
313   friend class ModuloScheduling;
314   
315 };
316
317 #endif