| Tanya Lattner | 642685a | 2004-05-26 06:27:36 +0000 | [diff] [blame] | 1 | //===-- 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 | // | 
|  | 10 | // | 
|  | 11 | // | 
|  | 12 | //===----------------------------------------------------------------------===// | 
|  | 13 | #define DEBUG_TYPE "ModuloSched" | 
|  | 14 |  | 
|  | 15 | #include "MSSchedule.h" | 
| Reid Spencer | 7c16caa | 2004-09-01 22:55:40 +0000 | [diff] [blame] | 16 | #include "llvm/Support/Debug.h" | 
| Tanya Lattner | 642685a | 2004-05-26 06:27:36 +0000 | [diff] [blame] | 17 | #include "llvm/Target/TargetSchedInfo.h" | 
| Misha Brukman | 9da1134b | 2004-10-10 23:34:50 +0000 | [diff] [blame] | 18 | #include "../SparcV9Internals.h" | 
| Tanya Lattner | 642685a | 2004-05-26 06:27:36 +0000 | [diff] [blame] | 19 |  | 
|  | 20 | using namespace llvm; | 
|  | 21 |  | 
|  | 22 | bool MSSchedule::insert(MSchedGraphNode *node, int cycle) { | 
|  | 23 |  | 
|  | 24 | //First, check if the cycle has a spot free to start | 
|  | 25 | if(schedule.find(cycle) != schedule.end()) { | 
| Tanya Lattner | 13c71ca | 2004-11-24 01:49:10 +0000 | [diff] [blame] | 26 | //Check if we have a free issue slot at this cycle | 
| Tanya Lattner | 642685a | 2004-05-26 06:27:36 +0000 | [diff] [blame] | 27 | if (schedule[cycle].size() < numIssue) { | 
| Tanya Lattner | 13c71ca | 2004-11-24 01:49:10 +0000 | [diff] [blame] | 28 | //Now check if all the resources in their respective cycles are available | 
| Tanya Lattner | 642685a | 2004-05-26 06:27:36 +0000 | [diff] [blame] | 29 | if(resourcesFree(node, cycle)) { | 
| Tanya Lattner | 341828e | 2004-11-28 23:36:15 +0000 | [diff] [blame] | 30 | //Insert to preserve dependencies | 
|  | 31 | addToSchedule(cycle,node); | 
| Tanya Lattner | 642685a | 2004-05-26 06:27:36 +0000 | [diff] [blame] | 32 | DEBUG(std::cerr << "Found spot in map, and there is an issue slot\n"); | 
|  | 33 | return false; | 
|  | 34 | } | 
|  | 35 | } | 
|  | 36 | } | 
|  | 37 | //Not in the map yet so put it in | 
|  | 38 | else { | 
|  | 39 | if(resourcesFree(node,cycle)) { | 
|  | 40 | std::vector<MSchedGraphNode*> nodes; | 
|  | 41 | nodes.push_back(node); | 
|  | 42 | schedule[cycle] = nodes; | 
|  | 43 | DEBUG(std::cerr << "Nothing in map yet so taking an issue slot\n"); | 
|  | 44 | return false; | 
|  | 45 | } | 
|  | 46 | } | 
|  | 47 |  | 
|  | 48 | DEBUG(std::cerr << "All issue slots taken\n"); | 
|  | 49 | return true; | 
| Tanya Lattner | 13c71ca | 2004-11-24 01:49:10 +0000 | [diff] [blame] | 50 |  | 
| Tanya Lattner | 642685a | 2004-05-26 06:27:36 +0000 | [diff] [blame] | 51 | } | 
|  | 52 |  | 
| Tanya Lattner | 341828e | 2004-11-28 23:36:15 +0000 | [diff] [blame] | 53 | void MSSchedule::addToSchedule(int cycle, MSchedGraphNode *node) { | 
|  | 54 | std::vector<MSchedGraphNode*> nodesAtCycle = schedule[cycle]; | 
|  | 55 |  | 
|  | 56 | std::map<unsigned, MSchedGraphNode*> indexMap; | 
|  | 57 | for(unsigned i=0; i < nodesAtCycle.size(); ++i) { | 
|  | 58 | indexMap[nodesAtCycle[i]->getIndex()] = nodesAtCycle[i]; | 
|  | 59 | } | 
|  | 60 |  | 
|  | 61 | indexMap[node->getIndex()] = node; | 
|  | 62 |  | 
|  | 63 | std::vector<MSchedGraphNode*> nodes; | 
|  | 64 | for(std::map<unsigned, MSchedGraphNode*>::iterator I = indexMap.begin(), E = indexMap.end(); I != E; ++I) | 
|  | 65 | nodes.push_back(I->second); | 
|  | 66 |  | 
|  | 67 | schedule[cycle] =  nodes; | 
|  | 68 | } | 
|  | 69 |  | 
|  | 70 |  | 
| Tanya Lattner | 642685a | 2004-05-26 06:27:36 +0000 | [diff] [blame] | 71 | bool MSSchedule::resourcesFree(MSchedGraphNode *node, int cycle) { | 
| Tanya Lattner | 13c71ca | 2004-11-24 01:49:10 +0000 | [diff] [blame] | 72 |  | 
| Tanya Lattner | 642685a | 2004-05-26 06:27:36 +0000 | [diff] [blame] | 73 | //Get Resource usage for this instruction | 
| Tanya Lattner | 081fbd1 | 2004-07-30 23:36:10 +0000 | [diff] [blame] | 74 | const TargetSchedInfo *msi = node->getParent()->getTarget()->getSchedInfo(); | 
| Tanya Lattner | 642685a | 2004-05-26 06:27:36 +0000 | [diff] [blame] | 75 | int currentCycle = cycle; | 
|  | 76 | bool success = true; | 
| Tanya Lattner | 13c71ca | 2004-11-24 01:49:10 +0000 | [diff] [blame] | 77 |  | 
|  | 78 | //Get resource usage for this instruction | 
|  | 79 | InstrRUsage rUsage = msi->getInstrRUsage(node->getInst()->getOpcode()); | 
|  | 80 | std::vector<std::vector<resourceId_t> > resources = rUsage.resourcesByCycle; | 
|  | 81 |  | 
|  | 82 | //Loop over resources in each cycle and increments their usage count | 
|  | 83 | for(unsigned i=0; i < resources.size(); ++i) { | 
|  | 84 | for(unsigned j=0; j < resources[i].size(); ++j) { | 
|  | 85 |  | 
|  | 86 | //Get Resource to check its availability | 
|  | 87 | int resourceNum = resources[i][j]; | 
|  | 88 |  | 
|  | 89 | DEBUG(std::cerr << "Attempting to schedule Resource Num: " << resourceNum << " in cycle: " << currentCycle << "\n"); | 
|  | 90 |  | 
| Tanya Lattner | 642685a | 2004-05-26 06:27:36 +0000 | [diff] [blame] | 91 | //Check if this resource is available for this cycle | 
|  | 92 | std::map<int, std::map<int,int> >::iterator resourcesForCycle = resourceNumPerCycle.find(currentCycle); | 
|  | 93 |  | 
| Tanya Lattner | 13c71ca | 2004-11-24 01:49:10 +0000 | [diff] [blame] | 94 | //First check if map exists for this cycle | 
| Tanya Lattner | 642685a | 2004-05-26 06:27:36 +0000 | [diff] [blame] | 95 | if(resourcesForCycle != resourceNumPerCycle.end()) { | 
|  | 96 | //A map exists for this cycle, so lets check for the resource | 
|  | 97 | std::map<int, int>::iterator resourceUse = resourcesForCycle->second.find(resourceNum); | 
|  | 98 | if(resourceUse != resourcesForCycle->second.end()) { | 
|  | 99 | //Check if there are enough of this resource and if so, increase count and move on | 
| Tanya Lattner | 13c71ca | 2004-11-24 01:49:10 +0000 | [diff] [blame] | 100 | if(resourceUse->second < CPUResource::getCPUResource(resourceNum)->maxNumUsers) | 
| Tanya Lattner | 642685a | 2004-05-26 06:27:36 +0000 | [diff] [blame] | 101 | ++resourceUse->second; | 
| Tanya Lattner | ab9cf27 | 2004-11-22 20:41:24 +0000 | [diff] [blame] | 102 |  | 
| Tanya Lattner | 642685a | 2004-05-26 06:27:36 +0000 | [diff] [blame] | 103 | else { | 
| Tanya Lattner | 13c71ca | 2004-11-24 01:49:10 +0000 | [diff] [blame] | 104 | DEBUG(std::cerr << "No resource num " << resourceNum << " available for cycle " << currentCycle << "\n"); | 
| Tanya Lattner | 642685a | 2004-05-26 06:27:36 +0000 | [diff] [blame] | 105 | success = false; | 
|  | 106 | } | 
|  | 107 | } | 
|  | 108 | //Not in the map yet, so put it | 
|  | 109 | else | 
|  | 110 | resourcesForCycle->second[resourceNum] = 1; | 
|  | 111 |  | 
|  | 112 | } | 
|  | 113 | else { | 
|  | 114 | //Create a new map and put in our resource | 
|  | 115 | std::map<int, int> resourceMap; | 
|  | 116 | resourceMap[resourceNum] = 1; | 
| Tanya Lattner | ab9cf27 | 2004-11-22 20:41:24 +0000 | [diff] [blame] | 117 | resourceNumPerCycle[currentCycle] = resourceMap; | 
| Tanya Lattner | 642685a | 2004-05-26 06:27:36 +0000 | [diff] [blame] | 118 | } | 
|  | 119 | if(!success) | 
|  | 120 | break; | 
|  | 121 | } | 
|  | 122 | if(!success) | 
|  | 123 | break; | 
| Tanya Lattner | 13c71ca | 2004-11-24 01:49:10 +0000 | [diff] [blame] | 124 |  | 
| Tanya Lattner | 642685a | 2004-05-26 06:27:36 +0000 | [diff] [blame] | 125 |  | 
| Tanya Lattner | 13c71ca | 2004-11-24 01:49:10 +0000 | [diff] [blame] | 126 | //Increase cycle | 
|  | 127 | currentCycle++; | 
|  | 128 | } | 
|  | 129 |  | 
|  | 130 | if(!success) { | 
|  | 131 | int oldCycle = cycle; | 
|  | 132 | DEBUG(std::cerr << "Backtrack\n"); | 
|  | 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 | if(oldCycle < currentCycle) { | 
|  | 140 |  | 
|  | 141 | //Check if this resource is available for this cycle | 
|  | 142 | std::map<int, std::map<int,int> >::iterator resourcesForCycle = resourceNumPerCycle.find(oldCycle); | 
|  | 143 | if(resourcesForCycle != resourceNumPerCycle.end()) { | 
|  | 144 | for(unsigned j=0; j < resources[i].size(); ++j) { | 
|  | 145 | int resourceNum = resources[i][j]; | 
|  | 146 | //remove from map | 
|  | 147 | std::map<int, int>::iterator resourceUse = resourcesForCycle->second.find(resourceNum); | 
|  | 148 | //assert if not in the map.. since it should be! | 
|  | 149 | //assert(resourceUse != resourcesForCycle.end() && "Resource should be in map!"); | 
|  | 150 | --resourceUse->second; | 
| Tanya Lattner | 642685a | 2004-05-26 06:27:36 +0000 | [diff] [blame] | 151 | } | 
|  | 152 | } | 
| Tanya Lattner | 642685a | 2004-05-26 06:27:36 +0000 | [diff] [blame] | 153 | } | 
| Tanya Lattner | 13c71ca | 2004-11-24 01:49:10 +0000 | [diff] [blame] | 154 | else | 
|  | 155 | break; | 
|  | 156 | oldCycle++; | 
| Tanya Lattner | 642685a | 2004-05-26 06:27:36 +0000 | [diff] [blame] | 157 | } | 
| Tanya Lattner | 13c71ca | 2004-11-24 01:49:10 +0000 | [diff] [blame] | 158 | return false; | 
|  | 159 |  | 
|  | 160 | } | 
| Tanya Lattner | 642685a | 2004-05-26 06:27:36 +0000 | [diff] [blame] | 161 |  | 
| Tanya Lattner | 13c71ca | 2004-11-24 01:49:10 +0000 | [diff] [blame] | 162 | return true; | 
| Tanya Lattner | 642685a | 2004-05-26 06:27:36 +0000 | [diff] [blame] | 163 |  | 
|  | 164 | } | 
|  | 165 |  | 
|  | 166 | bool MSSchedule::constructKernel(int II) { | 
| Reid Spencer | 2bce800 | 2004-08-07 15:19:31 +0000 | [diff] [blame] | 167 | MSchedGraphNode *branchNode = 0; | 
| Tanya Lattner | dbac0cb | 2004-10-10 22:44:35 +0000 | [diff] [blame] | 168 | MSchedGraphNode *branchANode = 0; | 
| Tanya Lattner | 642685a | 2004-05-26 06:27:36 +0000 | [diff] [blame] | 169 |  | 
|  | 170 | int stageNum = (schedule.rbegin()->first)/ II; | 
|  | 171 | DEBUG(std::cerr << "Number of Stages: " << stageNum << "\n"); | 
|  | 172 |  | 
|  | 173 | for(int index = 0; index < II; ++index) { | 
|  | 174 | int count = 0; | 
|  | 175 | for(int i = index; i <= (schedule.rbegin()->first); i+=II) { | 
|  | 176 | if(schedule.count(i)) { | 
|  | 177 | for(std::vector<MSchedGraphNode*>::iterator I = schedule[i].begin(), | 
|  | 178 | E = schedule[i].end(); I != E; ++I) { | 
|  | 179 | //Check if its a branch | 
|  | 180 | if((*I)->isBranch()) { | 
| Tanya Lattner | dbac0cb | 2004-10-10 22:44:35 +0000 | [diff] [blame] | 181 | if((*I)->getInst()->getOpcode() == V9::BA) | 
|  | 182 | branchANode = *I; | 
|  | 183 | else | 
|  | 184 | branchNode = *I; | 
| Tanya Lattner | 642685a | 2004-05-26 06:27:36 +0000 | [diff] [blame] | 185 | assert(count == 0 && "Branch can not be from a previous iteration"); | 
|  | 186 | } | 
|  | 187 | else | 
|  | 188 | //FIXME: Check if the instructions in the earlier stage conflict | 
|  | 189 | kernel.push_back(std::make_pair(*I, count)); | 
|  | 190 | } | 
|  | 191 | } | 
|  | 192 | ++count; | 
|  | 193 | } | 
|  | 194 | } | 
|  | 195 |  | 
|  | 196 | //Add Branch to the end | 
|  | 197 | kernel.push_back(std::make_pair(branchNode, 0)); | 
| Tanya Lattner | dbac0cb | 2004-10-10 22:44:35 +0000 | [diff] [blame] | 198 |  | 
|  | 199 | //Add Branch Always to the end | 
|  | 200 | kernel.push_back(std::make_pair(branchANode, 0)); | 
|  | 201 |  | 
|  | 202 |  | 
|  | 203 | if(stageNum > 0) | 
|  | 204 | maxStage = stageNum; | 
|  | 205 | else | 
|  | 206 | maxStage = 0; | 
|  | 207 |  | 
| Tanya Lattner | 642685a | 2004-05-26 06:27:36 +0000 | [diff] [blame] | 208 | return true; | 
|  | 209 | } | 
|  | 210 |  | 
|  | 211 |  | 
|  | 212 | void MSSchedule::print(std::ostream &os) const { | 
|  | 213 | os << "Schedule:\n"; | 
|  | 214 |  | 
|  | 215 | for(schedule_const_iterator I =  schedule.begin(), E = schedule.end(); I != E; ++I) { | 
|  | 216 | os << "Cycle: " << I->first << "\n"; | 
|  | 217 | for(std::vector<MSchedGraphNode*>::const_iterator node = I->second.begin(), nodeEnd = I->second.end(); node != nodeEnd; ++node) | 
|  | 218 | os << **node << "\n"; | 
|  | 219 | } | 
|  | 220 |  | 
|  | 221 | os << "Kernel:\n"; | 
|  | 222 | for(std::vector<std::pair<MSchedGraphNode*, int> >::const_iterator I = kernel.begin(), | 
|  | 223 | E = kernel.end(); I != E; ++I) | 
|  | 224 | os << "Node: " << *(I->first) << " Stage: " << I->second << "\n"; | 
|  | 225 | } | 
|  | 226 |  |