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