blob: baf66f58ad13fe54016afdc26187af66db2960b2 [file] [log] [blame]
Tanya Lattner64a1a122005-06-17 04:15:43 +00001//===-- MSScheduleSB.cpp Schedule ---------------------------------*- 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//
11//
12//===----------------------------------------------------------------------===//
13#define DEBUG_TYPE "ModuloSchedSB"
14
15#include "MSScheduleSB.h"
16#include "llvm/Support/Debug.h"
17#include "llvm/Target/TargetSchedInfo.h"
18#include "../SparcV9Internals.h"
19#include "llvm/CodeGen/MachineInstr.h"
20
21using namespace llvm;
22
23//Check if all resources are free
24bool resourcesFree(MSchedGraphSBNode*, int,
25std::map<int, std::map<int, int> > &resourceNumPerCycle);
26
27//Returns a boolean indicating if the start cycle needs to be increased/decreased
28bool MSScheduleSB::insert(MSchedGraphSBNode *node, int cycle, int II) {
29
30 //First, check if the cycle has a spot free to start
31 if(schedule.find(cycle) != schedule.end()) {
32 //Check if we have a free issue slot at this cycle
33 if (schedule[cycle].size() < numIssue) {
34 //Now check if all the resources in their respective cycles are available
35 if(resourcesFree(node, cycle, II)) {
36 //Insert to preserve dependencies
37 addToSchedule(cycle,node);
38 DEBUG(std::cerr << "Found spot in map, and there is an issue slot\n");
39 return false;
40 }
41 }
42 }
43 //Not in the map yet so put it in
44 else {
45 if(resourcesFree(node,cycle,II)) {
46 std::vector<MSchedGraphSBNode*> nodes;
47 nodes.push_back(node);
48 schedule[cycle] = nodes;
49 DEBUG(std::cerr << "Nothing in map yet so taking an issue slot\n");
50 return false;
51 }
52 }
53
54 DEBUG(std::cerr << "All issue slots taken\n");
55 return true;
56
57}
58
59void MSScheduleSB::addToSchedule(int cycle, MSchedGraphSBNode *node) {
60 std::vector<MSchedGraphSBNode*> nodesAtCycle = schedule[cycle];
61
62 std::map<unsigned, MSchedGraphSBNode*> indexMap;
63 for(unsigned i=0; i < nodesAtCycle.size(); ++i) {
64 indexMap[nodesAtCycle[i]->getIndex()] = nodesAtCycle[i];
65 }
66
67 indexMap[node->getIndex()] = node;
68
69 std::vector<MSchedGraphSBNode*> nodes;
70 for(std::map<unsigned, MSchedGraphSBNode*>::iterator I = indexMap.begin(), E = indexMap.end(); I != E; ++I)
71 nodes.push_back(I->second);
72
73 schedule[cycle] = nodes;
74}
75
76bool MSScheduleSB::resourceAvailable(int resourceNum, int cycle) {
77 bool isFree = true;
78
79 //Get Map for this cycle
80 if(resourceNumPerCycle.count(cycle)) {
81 if(resourceNumPerCycle[cycle].count(resourceNum)) {
82 int maxRes = CPUResource::getCPUResource(resourceNum)->maxNumUsers;
83 if(resourceNumPerCycle[cycle][resourceNum] >= maxRes)
84 isFree = false;
85 }
86 }
87
88 return isFree;
89}
90
91void MSScheduleSB::useResource(int resourceNum, int cycle) {
92
93 //Get Map for this cycle
94 if(resourceNumPerCycle.count(cycle)) {
95 if(resourceNumPerCycle[cycle].count(resourceNum)) {
96 resourceNumPerCycle[cycle][resourceNum]++;
97 }
98 else {
99 resourceNumPerCycle[cycle][resourceNum] = 1;
100 }
101 }
102 //If no map, create one!
103 else {
104 std::map<int, int> resourceUse;
105 resourceUse[resourceNum] = 1;
106 resourceNumPerCycle[cycle] = resourceUse;
107 }
108
109}
110
111bool MSScheduleSB::resourcesFree(MSchedGraphSBNode *node, int cycle, int II) {
112
113 //Get Resource usage for this instruction
114 const TargetSchedInfo *msi = node->getParent()->getTarget()->getSchedInfo();
115 int currentCycle = cycle;
116 bool success = true;
117
118 //Create vector of starting cycles
119 std::vector<int> cyclesMayConflict;
120 cyclesMayConflict.push_back(cycle);
121
122 if(resourceNumPerCycle.size() > 0) {
123 for(int i = cycle-II; i >= (resourceNumPerCycle.begin()->first); i-=II)
124 cyclesMayConflict.push_back(i);
125 for(int i = cycle+II; i <= resourceNumPerCycle.end()->first; i+=II)
126 cyclesMayConflict.push_back(i);
127 }
128
129 //Now check all cycles for conflicts
130 for(int index = 0; index < (int) cyclesMayConflict.size(); ++index) {
131 currentCycle = cyclesMayConflict[index];
132
133 //Get resource usage for this instruction
134 InstrRUsage rUsage = msi->getInstrRUsage(node->getInst()->getOpcode());
135 std::vector<std::vector<resourceId_t> > resources = rUsage.resourcesByCycle;
136
137 //Loop over resources in each cycle and increments their usage count
138 for(unsigned i=0; i < resources.size(); ++i) {
139 for(unsigned j=0; j < resources[i].size(); ++j) {
140
141 //Get Resource to check its availability
142 int resourceNum = resources[i][j];
143
144 DEBUG(std::cerr << "Attempting to schedule Resource Num: " << resourceNum << " in cycle: " << currentCycle << "\n");
145
146 success = resourceAvailable(resourceNum, currentCycle);
147
148 if(!success)
149 break;
150
151 }
152
153 if(!success)
154 break;
155
156 //Increase cycle
157 currentCycle++;
158 }
159
160 if(!success)
161 return false;
162 }
163
164 //Actually put resources into the map
165 if(success) {
166
167 int currentCycle = cycle;
168 //Get resource usage for this instruction
169 InstrRUsage rUsage = msi->getInstrRUsage(node->getInst()->getOpcode());
170 std::vector<std::vector<resourceId_t> > resources = rUsage.resourcesByCycle;
171
172 //Loop over resources in each cycle and increments their usage count
173 for(unsigned i=0; i < resources.size(); ++i) {
174 for(unsigned j=0; j < resources[i].size(); ++j) {
175 int resourceNum = resources[i][j];
176 useResource(resourceNum, currentCycle);
177 }
178 currentCycle++;
179 }
180 }
181
182
183 return true;
184
185}
186
187bool MSScheduleSB::constructKernel(int II, std::vector<MSchedGraphSBNode*> &branches, std::map<const MachineInstr*, unsigned> &indVar) {
188
189 //Our schedule is allowed to have negative numbers, so lets calculate this offset
190 int offset = schedule.begin()->first;
191 if(offset > 0)
192 offset = 0;
193
194 DEBUG(std::cerr << "Offset: " << offset << "\n");
195
196 //Using the schedule, fold up into kernel and check resource conflicts as we go
197 std::vector<std::pair<MSchedGraphSBNode*, int> > tempKernel;
198
199 int stageNum = ((schedule.rbegin()->first-offset)+1)/ II;
200 int maxSN = 0;
201
202 DEBUG(std::cerr << "Number of Stages: " << stageNum << "\n");
203
204 for(int index = offset; index < (II+offset); ++index) {
205 int count = 0;
206 for(int i = index; i <= (schedule.rbegin()->first); i+=II) {
207 if(schedule.count(i)) {
208 for(std::vector<MSchedGraphSBNode*>::iterator I = schedule[i].begin(),
209 E = schedule[i].end(); I != E; ++I) {
210 //Check if its a branch
211 assert(!(*I)->isBranch() && "Branch should not be schedule!");
212
213 tempKernel.push_back(std::make_pair(*I, count));
214 maxSN = std::max(maxSN, count);
215
216 }
217 }
218 ++count;
219 }
220 }
221
222
223 //Add in induction var code
224 for(std::vector<std::pair<MSchedGraphSBNode*, int> >::iterator I = tempKernel.begin(), IE = tempKernel.end();
225 I != IE; ++I) {
226 //Add indVar instructions before this one for the current iteration
227 if(I->second == 0) {
228 std::map<unsigned, MachineInstr*> tmpMap;
229
230 //Loop over induction variable instructions in the map that come before this instr
231 for(std::map<const MachineInstr*, unsigned>::iterator N = indVar.begin(), NE = indVar.end(); N != NE; ++N) {
232
233
234 if(N->second < I->first->getIndex())
235 tmpMap[N->second] = (MachineInstr*) N->first;
236 }
237
238 //Add to kernel, and delete from indVar
239 for(std::map<unsigned, MachineInstr*>::iterator N = tmpMap.begin(), NE = tmpMap.end(); N != NE; ++N) {
240 kernel.push_back(std::make_pair(N->second, 0));
241 indVar.erase(N->second);
242 }
243 }
244
245 kernel.push_back(std::make_pair((MachineInstr*) I->first->getInst(), I->second));
246 if(I->first->isPredicate()) {
247 //assert(I->second == 0 && "Predicate node must be from current iteration\n");
248 std::vector<const MachineInstr*> otherInstrs = I->first->getOtherInstrs();
249 for(std::vector<const MachineInstr*>::iterator O = otherInstrs.begin(), OE = otherInstrs.end(); O != OE; ++O) {
250 kernel.push_back(std::make_pair((MachineInstr*) *O, I->second));
251 }
252 }
253
254 }
255
256 std::map<unsigned, MachineInstr*> tmpMap;
257
258 //Add remaining invar instructions
259 for(std::map<const MachineInstr*, unsigned>::iterator N = indVar.begin(), NE = indVar.end(); N != NE; ++N) {
260 tmpMap[N->second] = (MachineInstr*) N->first;
261 }
262
263 //Add to kernel, and delete from indVar
264 for(std::map<unsigned, MachineInstr*>::iterator N = tmpMap.begin(), NE = tmpMap.end(); N != NE; ++N) {
265 kernel.push_back(std::make_pair(N->second, 0));
266 indVar.erase(N->second);
267 }
268
269
270 maxStage = maxSN;
271
272
273 return true;
274}
275
276bool MSScheduleSB::defPreviousStage(Value *def, int stage) {
277
278 //Loop over kernel and determine if value is being defined in previous stage
279 for(std::vector<std::pair<MachineInstr*, int> >::iterator P = kernel.begin(), PE = kernel.end(); P != PE; ++P) {
280 MachineInstr* inst = P->first;
281
282 //Loop over Machine Operands
283 for(unsigned i=0; i < inst->getNumOperands(); ++i) {
284 //get machine operand
285 const MachineOperand &mOp = inst->getOperand(i);
286 if(mOp.getType() == MachineOperand::MO_VirtualRegister && mOp.isDef()) {
287 if(def == mOp.getVRegValue()) {
288 if(P->second >= stage)
289 return false;
290 else
291 return true;
292 }
293 }
294 }
295 }
296
297 assert(0 && "We should always have found the def in our kernel\n");
298}
299
300
301void MSScheduleSB::print(std::ostream &os) const {
302 os << "Schedule:\n";
303
304 for(schedule_const_iterator I = schedule.begin(), E = schedule.end(); I != E; ++I) {
305 os << "Cycle: " << I->first << "\n";
306 for(std::vector<MSchedGraphSBNode*>::const_iterator node = I->second.begin(), nodeEnd = I->second.end(); node != nodeEnd; ++node)
307 os << **node << "\n";
308 }
309
310 os << "Kernel:\n";
311 for(std::vector<std::pair<MachineInstr*, int> >::const_iterator I = kernel.begin(),
312 E = kernel.end(); I != E; ++I)
313 os << "Node: " << *(I->first) << " Stage: " << I->second << "\n";
314}
315
316void MSScheduleSB::printSchedule(std::ostream &os) const {
317 os << "Schedule:\n";
318
319 for(schedule_const_iterator I = schedule.begin(), E = schedule.end(); I != E; ++I) {
320 os << "Cycle: " << I->first << "\n";
321 for(std::vector<MSchedGraphSBNode*>::const_iterator node = I->second.begin(), nodeEnd = I->second.end(); node != nodeEnd; ++node)
322 os << **node << "\n";
323 }
324}