static StringVector getAllSymbolsUsedByThisKernel( const std::string& kernelName, ir::Module* module) { auto kernel = module->kernels().find(kernelName); if(kernel == module->kernels().end()) return StringVector(); StringSet encountered; for(auto block = kernel->second->cfg()->begin(); block != kernel->second->cfg()->end(); ++block) { for(auto instruction = block->instructions.begin(); instruction != block->instructions.end(); ++instruction) { typedef std::vector<ir::PTXOperand*> OperandVector; auto ptx = static_cast<ir::PTXInstruction*>(*instruction); OperandVector operands; operands.push_back(&ptx->a); operands.push_back(&ptx->b); operands.push_back(&ptx->pg); operands.push_back(&ptx->pq); operands.push_back(&ptx->d); if(ptx->opcode != ir::PTXInstruction::Call) { operands.push_back(&ptx->c); } for(auto operand = operands.begin(); operand != operands.end(); ++operand) { if((*operand)->addressMode != ir::PTXOperand::Address && (*operand)->addressMode != ir::PTXOperand::FunctionName) { continue; } encountered.insert((*operand)->identifier); } } } return StringVector(encountered.begin(), encountered.end()); }
static void replaceInstances(ir::Module& module, const std::string& oldName, const std::string& newName) { for(auto kernel = module.kernels().begin(); kernel != module.kernels().end(); ++kernel) { for(auto block = kernel->second->cfg()->begin(); block != kernel->second->cfg()->end(); ++block) { for(auto instruction = block->instructions.begin(); instruction != block->instructions.end(); ++instruction) { typedef std::vector<ir::PTXOperand*> OperandVector; auto ptx = static_cast<ir::PTXInstruction*>(*instruction); OperandVector operands; operands.push_back(&ptx->a); operands.push_back(&ptx->b); operands.push_back(&ptx->pg); operands.push_back(&ptx->pq); operands.push_back(&ptx->d); if(ptx->opcode != ir::PTXInstruction::Call) { operands.push_back(&ptx->c); } for(auto operand = operands.begin(); operand != operands.end(); ++operand) { if((*operand)->addressMode != ir::PTXOperand::Address) { continue; } if((*operand)->identifier == oldName) { (*operand)->identifier = newName; } } } } } }
void ATIExecutableKernel::initializeSharedMemory() { report("Allocating shared memory"); typedef std::unordered_map<std::string, size_t> AllocationMap; typedef std::unordered_set<std::string> StringSet; typedef std::deque<ir::PTXOperand*> OperandVector; typedef std::unordered_map<std::string, ir::Module::GlobalMap::const_iterator> GlobalMap; AllocationMap map; GlobalMap sharedGlobals; StringSet external; OperandVector externalOperands; unsigned int externalAlignment = 1; size_t sharedSize = 0; assert(module != 0); // global shared variables ir::Module::GlobalMap globals = module->globals(); ir::Module::GlobalMap::const_iterator global; for (global = globals.begin() ; global != globals.end() ; global++) { ir::PTXStatement statement = global->second.statement; if (statement.directive == ir::PTXStatement::Shared) { if (statement.attribute == ir::PTXStatement::Extern) { report("Found global external shared variable \"" << statement.name << "\""); assertM(external.count(statement.name) == 0, "External global \"" << statement.name << "\" declared more than once."); external.insert(statement.name); externalAlignment = std::max(externalAlignment, (unsigned int)statement.alignment); externalAlignment = std::max(externalAlignment, ir::PTXOperand::bytes(statement.type)); } else { report("Found global shared variable \"" << statement.name << "\""); sharedGlobals.insert( std::make_pair(statement.name, global)); } } } // local shared variables LocalMap::const_iterator local; for (local = locals.begin() ; local != locals.end() ; local++) { if (local->second.space == ir::PTXInstruction::Shared) { if (local->second.attribute == ir::PTXStatement::Extern) { report("Found local external shared variable \"" << local->second.name << "\""); assertM(external.count(local->second.name) == 0, "External local \"" << local->second.name << "\" declared more than once."); external.insert(local->second.name); externalAlignment = std::max(externalAlignment, (unsigned int)local->second.alignment); externalAlignment = std::max(externalAlignment, ir::PTXOperand::bytes(local->second.type)); } else { report("Allocating local shared variable \"" << local->second.name << "\" of size " << local->second.getSize()); _pad(sharedSize, local->second.alignment); map.insert(std::make_pair(local->second.name, sharedSize)); sharedSize += local->second.getSize(); } } } ir::ControlFlowGraph::iterator block; for (block = cfg()->begin() ; block != cfg()->end() ; block++) { ir::ControlFlowGraph::InstructionList insts = block->instructions; ir::ControlFlowGraph::InstructionList::iterator inst; for (inst = insts.begin() ; inst != insts.end() ; inst++) { ir::PTXInstruction& ptx = static_cast<ir::PTXInstruction&>(**inst); if (ptx.opcode == ir::PTXInstruction::Mov || ptx.opcode == ir::PTXInstruction::Ld || ptx.opcode == ir::PTXInstruction::St) { ir::PTXOperand* operands[] = {&ptx.d, &ptx.a, &ptx.b, &ptx.c}; for (unsigned int i = 0 ; i != 4 ; i++) { ir::PTXOperand* operand = operands[i]; if (operand->addressMode == ir::PTXOperand::Address) { StringSet::iterator si = external.find(operand->identifier); if (si != external.end()) { report("For instruction \"" << ptx.toString() << "\", mapping shared label \"" << *si << "\" to external shared memory."); externalOperands.push_back(operand); continue; } GlobalMap::iterator gi = sharedGlobals.find(operand->identifier); if (gi != sharedGlobals.end()) { ir::Module::GlobalMap::const_iterator it = gi->second; sharedGlobals.erase(gi); report("Allocating global shared variable \"" << it->second.statement.name << "\""); map.insert(std::make_pair( it->second.statement.name, sharedSize)); sharedSize += it->second.statement.bytes(); } AllocationMap::iterator mapping = map.find(operand->identifier); if (mapping != map.end()) { report("For instruction " << ptx.toString() << ", mapping shared label " << mapping->first << " to " << mapping->second); operand->addressMode = ir::PTXOperand::Immediate; operand->imm_uint = mapping->second; } } } } } } _pad(sharedSize, externalAlignment); report("Mapping external shared variables."); OperandVector::iterator operand; for (operand = externalOperands.begin() ; operand != externalOperands.end() ; operand++) { report("Mapping external shared label \"" << (*operand)->identifier << "\" to " << sharedSize); (*operand)->addressMode = ir::PTXOperand::Immediate; (*operand)->imm_uint = sharedSize; } // allocate shared memory object _sharedMemorySize = sharedSize; report("Total shared memory size is " << _sharedMemorySize); }