blob: 52d53243f9e49a27230300b227011826a967b039 [file] [log] [blame]
Tanya Lattner642685a2004-05-26 06:27:36 +00001//===-- MSSchedule.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//
Misha Brukmanb4402432005-04-21 23:30:14 +000010//
Tanya Lattner642685a2004-05-26 06:27:36 +000011//
12//===----------------------------------------------------------------------===//
13#define DEBUG_TYPE "ModuloSched"
14
15#include "MSSchedule.h"
Reid Spencer7c16caa2004-09-01 22:55:40 +000016#include "llvm/Support/Debug.h"
Tanya Lattner642685a2004-05-26 06:27:36 +000017#include "llvm/Target/TargetSchedInfo.h"
Misha Brukman9da1134b2004-10-10 23:34:50 +000018#include "../SparcV9Internals.h"
Tanya Lattner8bf63742005-06-17 04:00:57 +000019#include "llvm/CodeGen/MachineInstr.h"
Chris Lattner469640e2006-01-22 22:53:01 +000020#include <iostream>
Tanya Lattner642685a2004-05-26 06:27:36 +000021using namespace llvm;
22
Tanya Lattner8bf63742005-06-17 04:00:57 +000023//Check if all resources are free
Jeff Cohen5f4ef3c2005-07-27 06:12:32 +000024bool resourcesFree(MSchedGraphNode*, int,
Tanya Lattner8bf63742005-06-17 04:00:57 +000025std::map<int, std::map<int, int> > &resourceNumPerCycle);
26
Tanya Lattnera31ad512005-02-23 02:01:42 +000027//Returns a boolean indicating if the start cycle needs to be increased/decreased
Tanya Lattner8bf63742005-06-17 04:00:57 +000028bool MSSchedule::insert(MSchedGraphNode *node, int cycle, int II) {
Misha Brukmanb4402432005-04-21 23:30:14 +000029
Tanya Lattner642685a2004-05-26 06:27:36 +000030 //First, check if the cycle has a spot free to start
31 if(schedule.find(cycle) != schedule.end()) {
Tanya Lattner13c71ca2004-11-24 01:49:10 +000032 //Check if we have a free issue slot at this cycle
Tanya Lattner642685a2004-05-26 06:27:36 +000033 if (schedule[cycle].size() < numIssue) {
Tanya Lattner13c71ca2004-11-24 01:49:10 +000034 //Now check if all the resources in their respective cycles are available
Tanya Lattner8bf63742005-06-17 04:00:57 +000035 if(resourcesFree(node, cycle, II)) {
Jeff Cohen33a030e2005-07-27 05:53:44 +000036 //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;
Tanya Lattner642685a2004-05-26 06:27:36 +000040 }
41 }
42 }
43 //Not in the map yet so put it in
44 else {
Tanya Lattner8bf63742005-06-17 04:00:57 +000045 if(resourcesFree(node,cycle,II)) {
Tanya Lattner642685a2004-05-26 06:27:36 +000046 std::vector<MSchedGraphNode*> 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;
Misha Brukmanb4402432005-04-21 23:30:14 +000056
Tanya Lattner642685a2004-05-26 06:27:36 +000057}
58
Tanya Lattner341828e2004-11-28 23:36:15 +000059void MSSchedule::addToSchedule(int cycle, MSchedGraphNode *node) {
60 std::vector<MSchedGraphNode*> nodesAtCycle = schedule[cycle];
61
62 std::map<unsigned, MSchedGraphNode*> 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<MSchedGraphNode*> nodes;
70 for(std::map<unsigned, MSchedGraphNode*>::iterator I = indexMap.begin(), E = indexMap.end(); I != E; ++I)
71 nodes.push_back(I->second);
Misha Brukmanb4402432005-04-21 23:30:14 +000072
Tanya Lattner341828e2004-11-28 23:36:15 +000073 schedule[cycle] = nodes;
74}
75
Tanya Lattner8bf63742005-06-17 04:00:57 +000076bool MSSchedule::resourceAvailable(int resourceNum, int cycle) {
77 bool isFree = true;
Tanya Lattner341828e2004-11-28 23:36:15 +000078
Tanya Lattner8bf63742005-06-17 04:00:57 +000079 //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)
Jeff Cohen33a030e2005-07-27 05:53:44 +000084 isFree = false;
Tanya Lattner8bf63742005-06-17 04:00:57 +000085 }
86 }
Jeff Cohen5f4ef3c2005-07-27 06:12:32 +000087
Tanya Lattner8bf63742005-06-17 04:00:57 +000088 return isFree;
89}
90
91void MSSchedule::useResource(int resourceNum, int cycle) {
Jeff Cohen5f4ef3c2005-07-27 06:12:32 +000092
Tanya Lattner8bf63742005-06-17 04:00:57 +000093 //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 }
Jeff Cohen5f4ef3c2005-07-27 06:12:32 +0000108
Tanya Lattner8bf63742005-06-17 04:00:57 +0000109}
110
111bool MSSchedule::resourcesFree(MSchedGraphNode *node, int cycle, int II) {
Misha Brukmanb4402432005-04-21 23:30:14 +0000112
Tanya Lattner642685a2004-05-26 06:27:36 +0000113 //Get Resource usage for this instruction
Tanya Lattner081fbd12004-07-30 23:36:10 +0000114 const TargetSchedInfo *msi = node->getParent()->getTarget()->getSchedInfo();
Tanya Lattner642685a2004-05-26 06:27:36 +0000115 int currentCycle = cycle;
116 bool success = true;
Misha Brukmanb4402432005-04-21 23:30:14 +0000117
Tanya Lattner8bf63742005-06-17 04:00:57 +0000118 //Create vector of starting cycles
119 std::vector<int> cyclesMayConflict;
120 cyclesMayConflict.push_back(cycle);
Misha Brukmanb4402432005-04-21 23:30:14 +0000121
Tanya Lattner8bf63742005-06-17 04:00:57 +0000122 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);
Tanya Lattner13c71ca2004-11-24 01:49:10 +0000127 }
Misha Brukmanb4402432005-04-21 23:30:14 +0000128
Tanya Lattner8bf63742005-06-17 04:00:57 +0000129 //Now check all cycles for conflicts
130 for(int index = 0; index < (int) cyclesMayConflict.size(); ++index) {
131 currentCycle = cyclesMayConflict[index];
Jeff Cohen5f4ef3c2005-07-27 06:12:32 +0000132
Tanya Lattner13c71ca2004-11-24 01:49:10 +0000133 //Get resource usage for this instruction
134 InstrRUsage rUsage = msi->getInstrRUsage(node->getInst()->getOpcode());
135 std::vector<std::vector<resourceId_t> > resources = rUsage.resourcesByCycle;
Jeff Cohen5f4ef3c2005-07-27 06:12:32 +0000136
Tanya Lattner13c71ca2004-11-24 01:49:10 +0000137 //Loop over resources in each cycle and increments their usage count
138 for(unsigned i=0; i < resources.size(); ++i) {
Tanya Lattner8bf63742005-06-17 04:00:57 +0000139 for(unsigned j=0; j < resources[i].size(); ++j) {
Jeff Cohen5f4ef3c2005-07-27 06:12:32 +0000140
Jeff Cohen33a030e2005-07-27 05:53:44 +0000141 //Get Resource to check its availability
142 int resourceNum = resources[i][j];
Jeff Cohen5f4ef3c2005-07-27 06:12:32 +0000143
Jeff Cohen33a030e2005-07-27 05:53:44 +0000144 DEBUG(std::cerr << "Attempting to schedule Resource Num: " << resourceNum << " in cycle: " << currentCycle << "\n");
Jeff Cohen5f4ef3c2005-07-27 06:12:32 +0000145
146 success = resourceAvailable(resourceNum, currentCycle);
147
Jeff Cohen33a030e2005-07-27 05:53:44 +0000148 if(!success)
149 break;
Jeff Cohen5f4ef3c2005-07-27 06:12:32 +0000150
Tanya Lattner642685a2004-05-26 06:27:36 +0000151 }
Jeff Cohen5f4ef3c2005-07-27 06:12:32 +0000152
Tanya Lattner8bf63742005-06-17 04:00:57 +0000153 if(!success)
Jeff Cohen33a030e2005-07-27 05:53:44 +0000154 break;
Jeff Cohen5f4ef3c2005-07-27 06:12:32 +0000155
Tanya Lattner8bf63742005-06-17 04:00:57 +0000156 //Increase cycle
157 currentCycle++;
Tanya Lattner642685a2004-05-26 06:27:36 +0000158 }
Jeff Cohen5f4ef3c2005-07-27 06:12:32 +0000159
Tanya Lattner8bf63742005-06-17 04:00:57 +0000160 if(!success)
161 return false;
Tanya Lattner13c71ca2004-11-24 01:49:10 +0000162 }
Tanya Lattner642685a2004-05-26 06:27:36 +0000163
Tanya Lattner8bf63742005-06-17 04:00:57 +0000164 //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;
Jeff Cohen5f4ef3c2005-07-27 06:12:32 +0000171
Tanya Lattner8bf63742005-06-17 04:00:57 +0000172 //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) {
Jeff Cohen33a030e2005-07-27 05:53:44 +0000175 int resourceNum = resources[i][j];
176 useResource(resourceNum, currentCycle);
Tanya Lattner8bf63742005-06-17 04:00:57 +0000177 }
178 currentCycle++;
179 }
180 }
181
182
Tanya Lattner13c71ca2004-11-24 01:49:10 +0000183 return true;
Tanya Lattner642685a2004-05-26 06:27:36 +0000184
185}
186
Tanya Lattner13417b52005-03-23 01:47:20 +0000187bool MSSchedule::constructKernel(int II, std::vector<MSchedGraphNode*> &branches, std::map<const MachineInstr*, unsigned> &indVar) {
Misha Brukmanb4402432005-04-21 23:30:14 +0000188
Tanya Lattner13417b52005-03-23 01:47:20 +0000189 //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
Tanya Lattner8bf63742005-06-17 04:00:57 +0000196 //Using the schedule, fold up into kernel and check resource conflicts as we go
Tanya Lattner13417b52005-03-23 01:47:20 +0000197 std::vector<std::pair<MSchedGraphNode*, int> > tempKernel;
Jeff Cohen5f4ef3c2005-07-27 06:12:32 +0000198
Tanya Lattner13417b52005-03-23 01:47:20 +0000199 int stageNum = ((schedule.rbegin()->first-offset)+1)/ II;
200 int maxSN = 0;
201
Tanya Lattner642685a2004-05-26 06:27:36 +0000202 DEBUG(std::cerr << "Number of Stages: " << stageNum << "\n");
Misha Brukmanb4402432005-04-21 23:30:14 +0000203
Tanya Lattner13417b52005-03-23 01:47:20 +0000204 for(int index = offset; index < (II+offset); ++index) {
Tanya Lattner642685a2004-05-26 06:27:36 +0000205 int count = 0;
Misha Brukmanb4402432005-04-21 23:30:14 +0000206 for(int i = index; i <= (schedule.rbegin()->first); i+=II) {
Tanya Lattner642685a2004-05-26 06:27:36 +0000207 if(schedule.count(i)) {
Jeff Cohen33a030e2005-07-27 05:53:44 +0000208 for(std::vector<MSchedGraphNode*>::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!");
Tanya Lattner8bf63742005-06-17 04:00:57 +0000212
Jeff Cohen33a030e2005-07-27 05:53:44 +0000213 tempKernel.push_back(std::make_pair(*I, count));
214 maxSN = std::max(maxSN, count);
Jeff Cohen5f4ef3c2005-07-27 06:12:32 +0000215
Jeff Cohen33a030e2005-07-27 05:53:44 +0000216 }
Tanya Lattner642685a2004-05-26 06:27:36 +0000217 }
218 ++count;
219 }
220 }
Tanya Lattner13417b52005-03-23 01:47:20 +0000221
Tanya Lattner8bf63742005-06-17 04:00:57 +0000222
Tanya Lattner13417b52005-03-23 01:47:20 +0000223 //Add in induction var code
224 for(std::vector<std::pair<MSchedGraphNode*, 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
Jeff Cohen33a030e2005-07-27 05:53:44 +0000234 if(N->second < I->first->getIndex())
235 tmpMap[N->second] = (MachineInstr*) N->first;
Tanya Lattner13417b52005-03-23 01:47:20 +0000236 }
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) {
Jeff Cohen33a030e2005-07-27 05:53:44 +0000240 kernel.push_back(std::make_pair(N->second, 0));
241 indVar.erase(N->second);
Tanya Lattner13417b52005-03-23 01:47:20 +0000242 }
243 }
Misha Brukmanb4402432005-04-21 23:30:14 +0000244
Tanya Lattner13417b52005-03-23 01:47:20 +0000245 kernel.push_back(std::make_pair((MachineInstr*) I->first->getInst(), I->second));
246
Tanya Lattnera31ad512005-02-23 02:01:42 +0000247 }
248
Tanya Lattner13417b52005-03-23 01:47:20 +0000249 std::map<unsigned, MachineInstr*> tmpMap;
250
251 //Add remaining invar instructions
252 for(std::map<const MachineInstr*, unsigned>::iterator N = indVar.begin(), NE = indVar.end(); N != NE; ++N) {
253 tmpMap[N->second] = (MachineInstr*) N->first;
254 }
255
256 //Add to kernel, and delete from indVar
257 for(std::map<unsigned, MachineInstr*>::iterator N = tmpMap.begin(), NE = tmpMap.end(); N != NE; ++N) {
258 kernel.push_back(std::make_pair(N->second, 0));
259 indVar.erase(N->second);
260 }
261
262
263 maxStage = maxSN;
264
Tanya Lattnerdbac0cb2004-10-10 22:44:35 +0000265
Tanya Lattner642685a2004-05-26 06:27:36 +0000266 return true;
267}
268
Tanya Lattner8bf63742005-06-17 04:00:57 +0000269bool MSSchedule::defPreviousStage(Value *def, int stage) {
270
271 //Loop over kernel and determine if value is being defined in previous stage
272 for(std::vector<std::pair<MachineInstr*, int> >::iterator P = kernel.begin(), PE = kernel.end(); P != PE; ++P) {
273 MachineInstr* inst = P->first;
274
275 //Loop over Machine Operands
276 for(unsigned i=0; i < inst->getNumOperands(); ++i) {
277 //get machine operand
278 const MachineOperand &mOp = inst->getOperand(i);
279 if(mOp.getType() == MachineOperand::MO_VirtualRegister && mOp.isDef()) {
280 if(def == mOp.getVRegValue()) {
Jeff Cohen33a030e2005-07-27 05:53:44 +0000281 if(P->second >= stage)
282 return false;
283 else
284 return true;
Tanya Lattner8bf63742005-06-17 04:00:57 +0000285 }
286 }
287 }
288 }
Jeff Cohen5f4ef3c2005-07-27 06:12:32 +0000289
Tanya Lattner8bf63742005-06-17 04:00:57 +0000290 assert(0 && "We should always have found the def in our kernel\n");
Chris Lattner751c6c32005-08-25 00:00:26 +0000291 abort();
Tanya Lattner8bf63742005-06-17 04:00:57 +0000292}
293
Tanya Lattner642685a2004-05-26 06:27:36 +0000294
295void MSSchedule::print(std::ostream &os) const {
296 os << "Schedule:\n";
Misha Brukmanb4402432005-04-21 23:30:14 +0000297
Tanya Lattner642685a2004-05-26 06:27:36 +0000298 for(schedule_const_iterator I = schedule.begin(), E = schedule.end(); I != E; ++I) {
299 os << "Cycle: " << I->first << "\n";
300 for(std::vector<MSchedGraphNode*>::const_iterator node = I->second.begin(), nodeEnd = I->second.end(); node != nodeEnd; ++node)
301 os << **node << "\n";
302 }
303
304 os << "Kernel:\n";
Tanya Lattner13417b52005-03-23 01:47:20 +0000305 for(std::vector<std::pair<MachineInstr*, int> >::const_iterator I = kernel.begin(),
Jeff Cohen33a030e2005-07-27 05:53:44 +0000306 E = kernel.end(); I != E; ++I)
Tanya Lattner642685a2004-05-26 06:27:36 +0000307 os << "Node: " << *(I->first) << " Stage: " << I->second << "\n";
308}
Misha Brukmanb4402432005-04-21 23:30:14 +0000309