Пример #1
0
  LLVMBasicBlockRef DeclareBB(LLVMBasicBlockRef Src) {
    // Check if this is something we already computed.
    {
      auto i = BBMap.find(Src);
      if (i != BBMap.end()) {
        return i->second;
      }
    }

    LLVMValueRef V = LLVMBasicBlockAsValue(Src);
    if (!LLVMValueIsBasicBlock(V) || LLVMValueAsBasicBlock(V) != Src)
      report_fatal_error("Basic block is not a basic block");

    const char *Name = LLVMGetBasicBlockName(Src);
    const char *VName = LLVMGetValueName(V);
    if (Name != VName)
      report_fatal_error("Basic block name mismatch");

    LLVMBasicBlockRef BB = LLVMAppendBasicBlock(Fun, Name);
    return BBMap[Src] = BB;
  }
Пример #2
0
static void insertAndConnectBlocks(BasicBlockMap& newBlocks,
	ir::ControlFlowGraph::iterator& functionEntry,
	ir::ControlFlowGraph::iterator& functionExit,
	ir::IRKernel& kernel, unsigned int& nextRegister,
	const ir::IRKernel& inlinedKernel)
{
	typedef std::unordered_map<ir::PTXOperand::RegisterType,
		ir::PTXOperand::RegisterType> RegisterMap;
	
	ir::IRKernel copy;
	const ir::IRKernel* inlinedKernelPointer = &inlinedKernel;
	
	// create a copy if the call is recursive
	if(inlinedKernelPointer == &kernel)
	{
		copy = inlinedKernel;
		inlinedKernelPointer = &copy;
	}
	
	//  Insert new blocks
	for(auto block = inlinedKernelPointer->cfg()->begin();
		block != inlinedKernelPointer->cfg()->end(); ++block)
	{
		auto newBlock = kernel.cfg()->clone_block(block);
		
		newBlocks.insert(std::make_pair(block, newBlock));
	}
	
	//  Connect new blocks, rename branch labels
	for(auto block = newBlocks.begin(); block != newBlocks.end(); ++block)
	{
		for(auto edge = block->first->out_edges.begin();
			edge != block->first->out_edges.end(); ++edge)
		{
			auto headBlock = block->second;
			auto tail      = (*edge)->tail;
			
			auto tailBlock = newBlocks.find(tail);
			assert(tailBlock != newBlocks.end());
			
			kernel.cfg()->insert_edge(ir::Edge(headBlock,
				tailBlock->second, (*edge)->type));
			
			if((*edge)->type == ir::Edge::Branch)
			{
				assert(!headBlock->instructions.empty());
				auto instruction = headBlock->instructions.back();
				
				auto branch = static_cast<ir::PTXInstruction*>(instruction);

				if(branch->opcode == ir::PTXInstruction::Ret) continue;

				assertM(branch->opcode == ir::PTXInstruction::Bra, "Expecting "
					<< branch->toString() << " to be a branch");
				
				branch->d.identifier = tailBlock->second->label();
			}
		}
	}
	
	//  Assign copied blocks new registers
	RegisterMap newRegisters;
	
	for(auto block = newBlocks.begin(); block != newBlocks.end(); ++block)
	{
		for(auto instruction = block->second->instructions.begin();
			instruction != block->second->instructions.end(); ++instruction)
		{
			ir::PTXInstruction& ptx = static_cast<ir::PTXInstruction&>(
				**instruction);
		
			ir::PTXOperand* operands[] = {&ptx.pg, &ptx.pq, &ptx.d, &ptx.a,
				&ptx.b, &ptx.c};
				
			for(unsigned int i = 0; i < 6; ++i)
			{
				ir::PTXOperand& operand = *operands[i];
				
				if( operand.addressMode != ir::PTXOperand::Register &&
					operand.addressMode != ir::PTXOperand::Indirect &&
					operand.addressMode != ir::PTXOperand::ArgumentList)
				{
					continue;
				}
				
				if(operand.type != ir::PTXOperand::pred)
				{
					if(operand.array.empty() &&
						operand.addressMode != ir::PTXOperand::ArgumentList)
					{
						auto mapping = newRegisters.find(operand.reg);
						
						if(mapping == newRegisters.end())
						{
							mapping = newRegisters.insert(std::make_pair(
								operand.reg, nextRegister++)).first;
						}
						
						operand.reg = mapping->second;
					}
					else
					{
						for(auto subOperand = operand.array.begin(); 
							subOperand != operand.array.end(); ++subOperand )
						{
							if(!subOperand->isRegister()) continue;
							
							auto mapping = newRegisters.find(subOperand->reg);
						
							if(mapping == newRegisters.end())
							{
								mapping = newRegisters.insert(std::make_pair(
									subOperand->reg, nextRegister++)).first;
							}
						
							subOperand->reg = mapping->second;
						}
					}
				}
				else if(operand.addressMode != ir::PTXOperand::ArgumentList)
				{
					if(operand.condition == ir::PTXOperand::Pred
						|| operand.condition == ir::PTXOperand::InvPred)
					{
						auto mapping = newRegisters.find(operand.reg);
						
						if(mapping == newRegisters.end())
						{
							mapping = newRegisters.insert(std::make_pair(
								operand.reg, nextRegister++)).first;
						}
						
						operand.reg = mapping->second;
					}
				}
			}
		}
	}
	
	//  Assign copied blocks new local variables
	typedef std::unordered_map<std::string, std::string> LocalMap;
	
	LocalMap locals;
	
	for(auto local = inlinedKernel.locals.begin();
		local != inlinedKernel.locals.end(); ++local)
	{
		std::string newName = "_Zinlined_" + local->first;
	
		locals.insert(std::make_pair(local->first, newName));
		
		auto newLocal = kernel.locals.insert(
			std::make_pair(newName, local->second)).first;
		
		newLocal->second.name = newName;
	}
	
	for(auto block = newBlocks.begin(); block != newBlocks.end(); ++block)
	{
		for(auto instruction = block->second->instructions.begin();
			instruction != block->second->instructions.end(); ++instruction)
		{
			ir::PTXInstruction& ptx = static_cast<ir::PTXInstruction&>(
				**instruction);
		
			if(!ptx.mayHaveAddressableOperand()) continue;
		
			ir::PTXOperand* operands[] = {&ptx.pg, &ptx.pq, &ptx.d, &ptx.a,
				&ptx.b, &ptx.c};
				
			for(unsigned int i = 0; i < 6; ++i)
			{
				ir::PTXOperand& operand = *operands[i];
				
				if(operand.addressMode != ir::PTXOperand::Address) continue;
				
				auto local = locals.find(operand.identifier);
				
				if(local == locals.end()) continue;
				
				operand.identifier = local->second;
			}
		}
	}
	
	//  Get the entry and exit points
	auto entryMapping = newBlocks.find(
		inlinedKernelPointer->cfg()->get_entry_block());
	assert(entryMapping != newBlocks.end());
	
	functionEntry = entryMapping->second;
	
	auto exitMapping = newBlocks.find(
		inlinedKernelPointer->cfg()->get_exit_block());
	assert(exitMapping != newBlocks.end());
	
	functionExit = exitMapping->second;
}