From ebac64534ca8f7dbaddc7569d01f190ff57ce0ea Mon Sep 17 00:00:00 2001 From: Tanya Lattner Date: Wed, 26 May 2004 06:27:36 +0000 Subject: [PATCH] Adding scheduling class. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@13783 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/ModuloScheduling/MSSchedule.cpp | 183 ++++++++++++++++++ lib/CodeGen/ModuloScheduling/MSSchedule.h | 63 ++++++ .../SparcV9/ModuloScheduling/MSSchedule.cpp | 183 ++++++++++++++++++ .../SparcV9/ModuloScheduling/MSSchedule.h | 63 ++++++ 4 files changed, 492 insertions(+) create mode 100644 lib/CodeGen/ModuloScheduling/MSSchedule.cpp create mode 100644 lib/CodeGen/ModuloScheduling/MSSchedule.h create mode 100644 lib/Target/SparcV9/ModuloScheduling/MSSchedule.cpp create mode 100644 lib/Target/SparcV9/ModuloScheduling/MSSchedule.h diff --git a/lib/CodeGen/ModuloScheduling/MSSchedule.cpp b/lib/CodeGen/ModuloScheduling/MSSchedule.cpp new file mode 100644 index 00000000000..48ddd386fa8 --- /dev/null +++ b/lib/CodeGen/ModuloScheduling/MSSchedule.cpp @@ -0,0 +1,183 @@ +//===-- MSSchedule.cpp Schedule ---------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// +// +//===----------------------------------------------------------------------===// +#define DEBUG_TYPE "ModuloSched" + +#include "MSSchedule.h" +#include "Support/Debug.h" +#include "llvm/Target/TargetSchedInfo.h" +#include + +using namespace llvm; + +bool MSSchedule::insert(MSchedGraphNode *node, int cycle) { + + //First, check if the cycle has a spot free to start + if(schedule.find(cycle) != schedule.end()) { + if (schedule[cycle].size() < numIssue) { + if(resourcesFree(node, cycle)) { + schedule[cycle].push_back(node); + DEBUG(std::cerr << "Found spot in map, and there is an issue slot\n"); + return false; + } + } + } + //Not in the map yet so put it in + else { + if(resourcesFree(node,cycle)) { + std::vector nodes; + nodes.push_back(node); + schedule[cycle] = nodes; + DEBUG(std::cerr << "Nothing in map yet so taking an issue slot\n"); + return false; + } + } + + DEBUG(std::cerr << "All issue slots taken\n"); + return true; + +} + +bool MSSchedule::resourcesFree(MSchedGraphNode *node, int cycle) { + + //Get Resource usage for this instruction + const TargetSchedInfo & msi = node->getParent()->getTarget()->getSchedInfo(); + int currentCycle = cycle; + bool success = true; + + //Get resource usage for this instruction + InstrRUsage rUsage = msi.getInstrRUsage(node->getInst()->getOpcode()); + std::vector > resources = rUsage.resourcesByCycle; + + //Loop over resources in each cycle and increments their usage count + for(unsigned i=0; i < resources.size(); ++i) { + for(unsigned j=0; j < resources[i].size(); ++j) { + int resourceNum = resources[i][j]; + + //Check if this resource is available for this cycle + std::map >::iterator resourcesForCycle = resourceNumPerCycle.find(currentCycle); + + //First check map of resources for this cycle + if(resourcesForCycle != resourceNumPerCycle.end()) { + //A map exists for this cycle, so lets check for the resource + std::map::iterator resourceUse = resourcesForCycle->second.find(resourceNum); + if(resourceUse != resourcesForCycle->second.end()) { + //Check if there are enough of this resource and if so, increase count and move on + if(resourceUse->second < CPUResource::getCPUResource(resourceNum)->maxNumUsers) + ++resourceUse->second; + else { + success = false; + } + } + //Not in the map yet, so put it + else + resourcesForCycle->second[resourceNum] = 1; + + } + else { + //Create a new map and put in our resource + std::map resourceMap; + resourceMap[resourceNum] = 1; + resourceNumPerCycle[cycle] = resourceMap; + } + if(!success) + break; + } + if(!success) + break; + //Increase cycle + currentCycle++; + } + + if(!success) { + int oldCycle = cycle; + DEBUG(std::cerr << "Backtrack\n"); + //Get resource usage for this instruction + InstrRUsage rUsage = msi.getInstrRUsage(node->getInst()->getOpcode()); + std::vector > resources = rUsage.resourcesByCycle; + + //Loop over resources in each cycle and increments their usage count + for(unsigned i=0; i < resources.size(); ++i) { + if(oldCycle < currentCycle) { + + //Check if this resource is available for this cycle + std::map >::iterator resourcesForCycle = resourceNumPerCycle.find(oldCycle); + + for(unsigned j=0; j < resources[i].size(); ++j) { + int resourceNum = resources[i][j]; + //remove from map + std::map::iterator resourceUse = resourcesForCycle->second.find(resourceNum); + //assert if not in the map.. since it should be! + //assert(resourceUse != resourcesForCycle.end() && "Resource should be in map!"); + --resourceUse->second; + } + } + else + break; + oldCycle++; + } + return false; + + } + + return true; + +} + +bool MSSchedule::constructKernel(int II) { + MSchedGraphNode *branchNode; + + int stageNum = (schedule.rbegin()->first)/ II; + DEBUG(std::cerr << "Number of Stages: " << stageNum << "\n"); + + for(int index = 0; index < II; ++index) { + int count = 0; + for(int i = index; i <= (schedule.rbegin()->first); i+=II) { + if(schedule.count(i)) { + for(std::vector::iterator I = schedule[i].begin(), + E = schedule[i].end(); I != E; ++I) { + //Check if its a branch + if((*I)->isBranch()) { + branchNode = *I; + assert(count == 0 && "Branch can not be from a previous iteration"); + } + else + //FIXME: Check if the instructions in the earlier stage conflict + kernel.push_back(std::make_pair(*I, count)); + } + } + ++count; + } + } + + //Add Branch to the end + kernel.push_back(std::make_pair(branchNode, 0)); + + return true; +} + + +void MSSchedule::print(std::ostream &os) const { + os << "Schedule:\n"; + + for(schedule_const_iterator I = schedule.begin(), E = schedule.end(); I != E; ++I) { + os << "Cycle: " << I->first << "\n"; + for(std::vector::const_iterator node = I->second.begin(), nodeEnd = I->second.end(); node != nodeEnd; ++node) + os << **node << "\n"; + } + + os << "Kernel:\n"; + for(std::vector >::const_iterator I = kernel.begin(), + E = kernel.end(); I != E; ++I) + os << "Node: " << *(I->first) << " Stage: " << I->second << "\n"; +} + diff --git a/lib/CodeGen/ModuloScheduling/MSSchedule.h b/lib/CodeGen/ModuloScheduling/MSSchedule.h new file mode 100644 index 00000000000..892ab7c6081 --- /dev/null +++ b/lib/CodeGen/ModuloScheduling/MSSchedule.h @@ -0,0 +1,63 @@ +//===-- MSSchedule.h - Schedule ------- -------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// The schedule generated by a scheduling algorithm +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MSSCHEDULE_H +#define LLVM_MSSCHEDULE_H + +#include "MSchedGraph.h" +#include + +namespace llvm { + + class MSSchedule { + std::map > schedule; + unsigned numIssue; + + //Internal map to keep track of explicit resources + std::map > resourceNumPerCycle; + + //Check if all resources are free + bool resourcesFree(MSchedGraphNode*, int); + + //Resulting kernel + std::vector > kernel; + + public: + MSSchedule(int num) : numIssue(num) {} + MSSchedule() : numIssue(4) {} + bool insert(MSchedGraphNode *node, int cycle); + int getStartCycle(MSchedGraphNode *node); + void clear() { schedule.clear(); resourceNumPerCycle.clear(); kernel.clear(); } + std::vector >* getKernel() { return &kernel; } + bool constructKernel(int II); + + + + //iterators + typedef std::map >::iterator schedule_iterator; + typedef std::map >::const_iterator schedule_const_iterator; + schedule_iterator begin() { return schedule.begin(); }; + schedule_iterator end() { return schedule.end(); }; + void print(std::ostream &os) const; + + typedef std::vector >::iterator kernel_iterator; + typedef std::vector >::const_iterator kernel_const_iterator; + kernel_iterator kernel_begin() { return kernel.begin(); } + kernel_iterator kernel_end() { return kernel.end(); } + + }; + +} + + +#endif diff --git a/lib/Target/SparcV9/ModuloScheduling/MSSchedule.cpp b/lib/Target/SparcV9/ModuloScheduling/MSSchedule.cpp new file mode 100644 index 00000000000..48ddd386fa8 --- /dev/null +++ b/lib/Target/SparcV9/ModuloScheduling/MSSchedule.cpp @@ -0,0 +1,183 @@ +//===-- MSSchedule.cpp Schedule ---------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// +// +//===----------------------------------------------------------------------===// +#define DEBUG_TYPE "ModuloSched" + +#include "MSSchedule.h" +#include "Support/Debug.h" +#include "llvm/Target/TargetSchedInfo.h" +#include + +using namespace llvm; + +bool MSSchedule::insert(MSchedGraphNode *node, int cycle) { + + //First, check if the cycle has a spot free to start + if(schedule.find(cycle) != schedule.end()) { + if (schedule[cycle].size() < numIssue) { + if(resourcesFree(node, cycle)) { + schedule[cycle].push_back(node); + DEBUG(std::cerr << "Found spot in map, and there is an issue slot\n"); + return false; + } + } + } + //Not in the map yet so put it in + else { + if(resourcesFree(node,cycle)) { + std::vector nodes; + nodes.push_back(node); + schedule[cycle] = nodes; + DEBUG(std::cerr << "Nothing in map yet so taking an issue slot\n"); + return false; + } + } + + DEBUG(std::cerr << "All issue slots taken\n"); + return true; + +} + +bool MSSchedule::resourcesFree(MSchedGraphNode *node, int cycle) { + + //Get Resource usage for this instruction + const TargetSchedInfo & msi = node->getParent()->getTarget()->getSchedInfo(); + int currentCycle = cycle; + bool success = true; + + //Get resource usage for this instruction + InstrRUsage rUsage = msi.getInstrRUsage(node->getInst()->getOpcode()); + std::vector > resources = rUsage.resourcesByCycle; + + //Loop over resources in each cycle and increments their usage count + for(unsigned i=0; i < resources.size(); ++i) { + for(unsigned j=0; j < resources[i].size(); ++j) { + int resourceNum = resources[i][j]; + + //Check if this resource is available for this cycle + std::map >::iterator resourcesForCycle = resourceNumPerCycle.find(currentCycle); + + //First check map of resources for this cycle + if(resourcesForCycle != resourceNumPerCycle.end()) { + //A map exists for this cycle, so lets check for the resource + std::map::iterator resourceUse = resourcesForCycle->second.find(resourceNum); + if(resourceUse != resourcesForCycle->second.end()) { + //Check if there are enough of this resource and if so, increase count and move on + if(resourceUse->second < CPUResource::getCPUResource(resourceNum)->maxNumUsers) + ++resourceUse->second; + else { + success = false; + } + } + //Not in the map yet, so put it + else + resourcesForCycle->second[resourceNum] = 1; + + } + else { + //Create a new map and put in our resource + std::map resourceMap; + resourceMap[resourceNum] = 1; + resourceNumPerCycle[cycle] = resourceMap; + } + if(!success) + break; + } + if(!success) + break; + //Increase cycle + currentCycle++; + } + + if(!success) { + int oldCycle = cycle; + DEBUG(std::cerr << "Backtrack\n"); + //Get resource usage for this instruction + InstrRUsage rUsage = msi.getInstrRUsage(node->getInst()->getOpcode()); + std::vector > resources = rUsage.resourcesByCycle; + + //Loop over resources in each cycle and increments their usage count + for(unsigned i=0; i < resources.size(); ++i) { + if(oldCycle < currentCycle) { + + //Check if this resource is available for this cycle + std::map >::iterator resourcesForCycle = resourceNumPerCycle.find(oldCycle); + + for(unsigned j=0; j < resources[i].size(); ++j) { + int resourceNum = resources[i][j]; + //remove from map + std::map::iterator resourceUse = resourcesForCycle->second.find(resourceNum); + //assert if not in the map.. since it should be! + //assert(resourceUse != resourcesForCycle.end() && "Resource should be in map!"); + --resourceUse->second; + } + } + else + break; + oldCycle++; + } + return false; + + } + + return true; + +} + +bool MSSchedule::constructKernel(int II) { + MSchedGraphNode *branchNode; + + int stageNum = (schedule.rbegin()->first)/ II; + DEBUG(std::cerr << "Number of Stages: " << stageNum << "\n"); + + for(int index = 0; index < II; ++index) { + int count = 0; + for(int i = index; i <= (schedule.rbegin()->first); i+=II) { + if(schedule.count(i)) { + for(std::vector::iterator I = schedule[i].begin(), + E = schedule[i].end(); I != E; ++I) { + //Check if its a branch + if((*I)->isBranch()) { + branchNode = *I; + assert(count == 0 && "Branch can not be from a previous iteration"); + } + else + //FIXME: Check if the instructions in the earlier stage conflict + kernel.push_back(std::make_pair(*I, count)); + } + } + ++count; + } + } + + //Add Branch to the end + kernel.push_back(std::make_pair(branchNode, 0)); + + return true; +} + + +void MSSchedule::print(std::ostream &os) const { + os << "Schedule:\n"; + + for(schedule_const_iterator I = schedule.begin(), E = schedule.end(); I != E; ++I) { + os << "Cycle: " << I->first << "\n"; + for(std::vector::const_iterator node = I->second.begin(), nodeEnd = I->second.end(); node != nodeEnd; ++node) + os << **node << "\n"; + } + + os << "Kernel:\n"; + for(std::vector >::const_iterator I = kernel.begin(), + E = kernel.end(); I != E; ++I) + os << "Node: " << *(I->first) << " Stage: " << I->second << "\n"; +} + diff --git a/lib/Target/SparcV9/ModuloScheduling/MSSchedule.h b/lib/Target/SparcV9/ModuloScheduling/MSSchedule.h new file mode 100644 index 00000000000..892ab7c6081 --- /dev/null +++ b/lib/Target/SparcV9/ModuloScheduling/MSSchedule.h @@ -0,0 +1,63 @@ +//===-- MSSchedule.h - Schedule ------- -------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// The schedule generated by a scheduling algorithm +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MSSCHEDULE_H +#define LLVM_MSSCHEDULE_H + +#include "MSchedGraph.h" +#include + +namespace llvm { + + class MSSchedule { + std::map > schedule; + unsigned numIssue; + + //Internal map to keep track of explicit resources + std::map > resourceNumPerCycle; + + //Check if all resources are free + bool resourcesFree(MSchedGraphNode*, int); + + //Resulting kernel + std::vector > kernel; + + public: + MSSchedule(int num) : numIssue(num) {} + MSSchedule() : numIssue(4) {} + bool insert(MSchedGraphNode *node, int cycle); + int getStartCycle(MSchedGraphNode *node); + void clear() { schedule.clear(); resourceNumPerCycle.clear(); kernel.clear(); } + std::vector >* getKernel() { return &kernel; } + bool constructKernel(int II); + + + + //iterators + typedef std::map >::iterator schedule_iterator; + typedef std::map >::const_iterator schedule_const_iterator; + schedule_iterator begin() { return schedule.begin(); }; + schedule_iterator end() { return schedule.end(); }; + void print(std::ostream &os) const; + + typedef std::vector >::iterator kernel_iterator; + typedef std::vector >::const_iterator kernel_const_iterator; + kernel_iterator kernel_begin() { return kernel.begin(); } + kernel_iterator kernel_end() { return kernel.end(); } + + }; + +} + + +#endif