Split Target/Machine.h into three files:
[oota-llvm.git] / lib / Target / TargetMachine.cpp
1 //===-- TargetMachine.cpp - General Target Information ---------------------==//
2 //
3 // This file describes the general parts of a Target machine.
4 //
5 //===----------------------------------------------------------------------===//
6
7 #include "llvm/Target/SchedInfo.h"
8 #include "llvm/Target/Machine.h"
9 #include "llvm/DerivedTypes.h"
10
11 // External object describing the machine instructions
12 // Initialized only when the TargetMachine class is created
13 // and reset when that class is destroyed.
14 // 
15 const MachineInstrDescriptor* TargetInstrDescriptors = NULL;
16
17 resourceId_t MachineResource::nextId = 0;
18
19 static cycles_t ComputeMinGap           (const InstrRUsage& fromRU,
20                                          const InstrRUsage& toRU);
21
22 static bool     RUConflict              (const vector<resourceId_t>& fromRVec,
23                                          const vector<resourceId_t>& fromRVec);
24
25 //---------------------------------------------------------------------------
26 // class TargetMachine
27 // 
28 // Purpose:
29 //   Machine description.
30 // 
31 //---------------------------------------------------------------------------
32
33
34 // function TargetMachine::findOptimalStorageSize 
35 // 
36 // Purpose:
37 //   This default implementation assumes that all sub-word data items use
38 //   space equal to optSizeForSubWordData, and all other primitive data
39 //   items use space according to the type.
40 //   
41 unsigned int TargetMachine::findOptimalStorageSize(const Type* ty) const {
42   switch(ty->getPrimitiveID()) {
43   case Type::BoolTyID:
44   case Type::UByteTyID:
45   case Type::SByteTyID:     
46   case Type::UShortTyID:
47   case Type::ShortTyID:     
48     return optSizeForSubWordData;
49     
50   default:
51     return DataLayout.getTypeSize(ty);
52   }
53 }
54
55
56 //---------------------------------------------------------------------------
57 // class MachineInstructionInfo
58 //      Interface to description of machine instructions
59 //---------------------------------------------------------------------------
60
61
62 /*ctor*/
63 MachineInstrInfo::MachineInstrInfo(const MachineInstrDescriptor* _desc,
64                                    unsigned int _descSize,
65                                    unsigned int _numRealOpCodes)
66   : desc(_desc), descSize(_descSize), numRealOpCodes(_numRealOpCodes)
67 {
68   assert(TargetInstrDescriptors == NULL && desc != NULL);
69   TargetInstrDescriptors = desc;        // initialize global variable
70 }  
71
72
73 /*dtor*/
74 MachineInstrInfo::~MachineInstrInfo()
75 {
76   TargetInstrDescriptors = NULL;        // reset global variable
77 }
78
79
80 bool
81 MachineInstrInfo::constantFitsInImmedField(MachineOpCode opCode,
82                                            int64_t intValue) const
83 {
84   // First, check if opCode has an immed field.
85   bool isSignExtended;
86   uint64_t maxImmedValue = this->maxImmedConstant(opCode, isSignExtended);
87   if (maxImmedValue != 0)
88     {
89       // Now check if the constant fits
90       if (intValue <= (int64_t) maxImmedValue &&
91           intValue >= -((int64_t) maxImmedValue+1))
92         return true;
93     }
94   
95   return false;
96 }
97
98
99 //---------------------------------------------------------------------------
100 // class MachineSchedInfo
101 //      Interface to machine description for instruction scheduling
102 //---------------------------------------------------------------------------
103
104 /*ctor*/
105 MachineSchedInfo::MachineSchedInfo(int                     _numSchedClasses,
106                                    const MachineInstrInfo* _mii,
107                                    const InstrClassRUsage* _classRUsages,
108                                    const InstrRUsageDelta* _usageDeltas,
109                                    const InstrIssueDelta*  _issueDeltas,
110                                    unsigned int            _numUsageDeltas,
111                                    unsigned int            _numIssueDeltas)
112   : numSchedClasses(_numSchedClasses),
113     mii(_mii),
114     classRUsages(_classRUsages),
115     usageDeltas(_usageDeltas),
116     issueDeltas(_issueDeltas),
117     numUsageDeltas(_numUsageDeltas),
118     numIssueDeltas(_numIssueDeltas)
119 {
120 }
121
122 void
123 MachineSchedInfo::initializeResources()
124 {
125   assert(MAX_NUM_SLOTS >= (int) getMaxNumIssueTotal()
126          && "Insufficient slots for static data! Increase MAX_NUM_SLOTS");
127   
128   // First, compute common resource usage info for each class because
129   // most instructions will probably behave the same as their class.
130   // Cannot allocate a vector of InstrRUsage so new each one.
131   // 
132   vector<InstrRUsage> instrRUForClasses;
133   instrRUForClasses.resize(numSchedClasses);
134   for (InstrSchedClass sc=0; sc < numSchedClasses; sc++)
135     {
136       // instrRUForClasses.push_back(new InstrRUsage);
137       instrRUForClasses[sc].setMaxSlots(getMaxNumIssueTotal());
138       instrRUForClasses[sc] = classRUsages[sc];
139     }
140   
141   computeInstrResources(instrRUForClasses);
142   
143   computeIssueGaps(instrRUForClasses);
144 }
145
146
147 void
148 MachineSchedInfo::computeInstrResources(const vector<InstrRUsage>& instrRUForClasses)
149 {
150   int numOpCodes =  mii->getNumRealOpCodes();
151   instrRUsages.resize(numOpCodes);
152   
153   // First get the resource usage information from the class resource usages.
154   for (MachineOpCode op=0; op < numOpCodes; op++)
155     {
156       InstrSchedClass sc = getSchedClass(op);
157       assert(sc >= 0 && sc < numSchedClasses);
158       instrRUsages[op] = instrRUForClasses[sc];
159     }
160   
161   // Now, modify the resource usages as specified in the deltas.
162   for (unsigned i=0; i < numUsageDeltas; i++)
163     {
164       MachineOpCode op = usageDeltas[i].opCode;
165       assert(op < numOpCodes);
166       instrRUsages[op].addUsageDelta(usageDeltas[i]);
167     }
168   
169   // Then modify the issue restrictions as specified in the deltas.
170   for (unsigned i=0; i < numIssueDeltas; i++)
171     {
172       MachineOpCode op = issueDeltas[i].opCode;
173       assert(op < numOpCodes);
174       instrRUsages[issueDeltas[i].opCode].addIssueDelta(issueDeltas[i]);
175     }
176 }
177
178
179 void
180 MachineSchedInfo::computeIssueGaps(const vector<InstrRUsage>& instrRUForClasses)
181 {
182   int numOpCodes =  mii->getNumRealOpCodes();
183   instrRUsages.resize(numOpCodes);
184   
185   assert(numOpCodes < (1 << MAX_OPCODE_SIZE) - 1
186          && "numOpCodes invalid for implementation of class OpCodePair!");
187   
188   // First, compute issue gaps between pairs of classes based on common
189   // resources usages for each class, because most instruction pairs will
190   // usually behave the same as their class.
191   // 
192   int classPairGaps[numSchedClasses][numSchedClasses];
193   for (InstrSchedClass fromSC=0; fromSC < numSchedClasses; fromSC++)
194     for (InstrSchedClass toSC=0; toSC < numSchedClasses; toSC++)
195       {
196         int classPairGap = ComputeMinGap(instrRUForClasses[fromSC],
197                                       instrRUForClasses[toSC]);
198         classPairGaps[fromSC][toSC] = classPairGap; 
199       }
200   
201   // Now, for each pair of instructions, use the class pair gap if both
202   // instructions have identical resource usage as their respective classes.
203   // If not, recompute the gap for the pair from scratch.
204
205   longestIssueConflict = 0;
206   
207   for (MachineOpCode fromOp=0; fromOp < numOpCodes; fromOp++)
208     for (MachineOpCode toOp=0; toOp < numOpCodes; toOp++)
209     {
210       int instrPairGap = 
211         (instrRUsages[fromOp].sameAsClass && instrRUsages[toOp].sameAsClass)
212         ? classPairGaps[getSchedClass(fromOp)][getSchedClass(toOp)]
213         : ComputeMinGap(instrRUsages[fromOp], instrRUsages[toOp]);
214       
215       if (instrPairGap > 0)
216         {
217           issueGaps[OpCodePair(fromOp,toOp)] = instrPairGap;
218           conflictLists[fromOp].push_back(toOp);
219           longestIssueConflict = max(longestIssueConflict, instrPairGap);
220         }
221     }
222 }
223
224
225 // Check if fromRVec and toRVec have *any* common entries.
226 // Assume the vectors are sorted in increasing order.
227 // Algorithm copied from function set_intersection() for sorted ranges (stl_algo.h).
228 inline static bool 
229 RUConflict(const vector<resourceId_t>& fromRVec,
230            const vector<resourceId_t>& toRVec)
231 {
232   bool commonElementFound = false;
233   
234   unsigned fN = fromRVec.size(), tN = toRVec.size(); 
235   unsigned fi = 0, ti = 0;
236   while (fi < fN && ti < tN)
237     if (fromRVec[fi] < toRVec[ti])
238       ++fi;
239     else if (toRVec[ti] < fromRVec[fi])
240       ++ti;
241     else
242       {
243         commonElementFound = true;
244         break;
245       }
246   
247   return commonElementFound; 
248 }
249
250
251 static cycles_t
252 ComputeMinGap(const InstrRUsage& fromRU, const InstrRUsage& toRU)
253 {
254   cycles_t minGap = 0;
255   
256   if (fromRU.numBubbles > 0)
257     minGap = fromRU.numBubbles;
258   
259   if (minGap < fromRU.numCycles)
260     {
261       // only need to check from cycle `minGap' onwards
262       for (cycles_t gap=minGap; gap <= fromRU.numCycles-1; gap++)
263         {
264           // check if instr. #2 can start executing `gap' cycles after #1
265           // by checking for resource conflicts in each overlapping cycle
266           cycles_t numOverlap = min(fromRU.numCycles - gap, toRU.numCycles);
267           for (cycles_t c = 0; c <= numOverlap-1; c++)
268             if (RUConflict(fromRU.resourcesByCycle[gap + c],
269                            toRU.resourcesByCycle[c]))
270               {// conflict found so minGap must be more than `gap'
271                 minGap = gap+1;
272                 break;
273               }
274         }
275     }
276   
277   return minGap;
278 }
279
280 //---------------------------------------------------------------------------