static void replaceOperand(ir::PTXOperand& operand,
	ir::Instruction::RegisterType registerId,
	const ir::PTXOperand& immediate)
{
	if(!operand.array.empty())
	{
		for(auto sub = operand.array.begin();
			sub != operand.array.end(); ++sub)
		{
			replaceOperand(*sub, registerId, immediate);
		}

		return;
	}

	if(!operand.isRegister()) return;

	if(operand.reg != registerId) return;;
	
	int offset = 0;
	
	if(operand.addressMode == ir::PTXOperand::Indirect)
	{
		offset = operand.offset;
	}

	operand = immediate;
	
	operand.imm_uint += offset;
}
static void replaceOperand(ir::PTXInstruction& ptx,
	ir::Instruction::RegisterType registerId,
	const ir::PTXOperand& immediate)
{
	ir::PTXOperand* operands[] = {&ptx.a, &ptx.b, &ptx.c, &ptx.pq,
		&ptx.d};

	unsigned int sources = 4;

	if(ptx.isStore()) ++sources;
	
	for(unsigned int i = 0; i < sources; ++i)
	{
		replaceOperand(*operands[i], registerId, immediate);
	}
}
Exemplo n.º 3
0
void OSR::replaceOperands(Type* type, Inst* inst, SsaOpnd* iv,
                          SsaOpnd* rc, Opcode opcode, Operation op) {

    if (Log::isEnabled()) {
        Log::out() << "Replacing operands" << std::endl;
        Log::out() << "RC" << std::endl;
        rc->print(Log::out());
        Log::out() << "IV" << std::endl;
        iv->print(Log::out());
        Log::out() << std::endl;
    }

    U_32 numOpnds = inst->getNumSrcOperands();
    SsaOpnd* iv_lead = getLeadingOperand(iv);
    Node* iv_lead_node = iv_lead->getInst()->getNode();
    for (U_32 num = 0; num < numOpnds; num++) {
        SsaOpnd* opnd = inst->getSrc(num)->asSsaOpnd();
        replaceOperand(num, inst, opnd, iv_lead, iv_lead_node, type,
                       opcode, rc, op);
    }

}
static void updateUses(iterator block, ir::Instruction::RegisterType registerId,
	const ir::PTXOperand& value, BlockSet& visited)
{
	typedef analysis::DataflowGraph::RegisterPointerVector
		RegisterPointerVector;

	if(!visited.insert(block).second) return;

	// phi uses
	bool replacedPhi = false;
	bool anyPhis     = false;
	ir::Instruction::RegisterType newRegisterId = 0;
	
	for(auto phi = block->phis().begin(); phi != block->phis().end(); ++phi)
	{
		if(phi->s.size() != 1)
		{
			for(auto source = phi->s.begin(); source != phi->s.end(); ++source)
			{
				if(source->id == registerId)
				{
					anyPhis = true;
					report("    could not remove " << phi->toString());
					break;
				}
			}
									
			continue;
		}
		
		for(auto source = phi->s.begin(); source != phi->s.end(); ++source)
		{
			if(source->id == registerId)
			{
				newRegisterId = phi->d.id;
				block->phis().erase(phi);
			    	
				auto livein = block->aliveIn().find(registerId);
			    
			    assert(livein != block->aliveIn().end());
				block->aliveIn().erase(livein);
				
				report("    removed " << phi->toString());
				replacedPhi = true;
				break;
			}
		}

		if(replacedPhi)
		{
			break;
		}
	}

	if(replacedPhi)
	{
		BlockSet visited;
		
		updateUses(block, newRegisterId, value, visited);
	}
	
	// local uses
	for(auto instruction = block->instructions().begin();
		instruction != block->instructions().end(); ++instruction)
	{
		auto ptx = static_cast<ir::PTXInstruction*>(instruction->i);
	
		RegisterPointerVector newSources;
	
		for(auto source = instruction->s.begin(); source !=
			instruction->s.end(); ++source)
		{
			if(*source->pointer == registerId)
			{
				report("    updated use by '" << ptx->toString()
					<< "', of r" << registerId); 
		
				replaceOperand(*ptx, registerId, value);
			}
			else
			{
				newSources.push_back(*source);
			}
		}

		instruction->s = std::move(newSources);
	}
		
	if(!anyPhis)
	{
		auto livein = block->aliveIn().find(registerId);
   
		if(livein != block->aliveIn().end())
		{
			block->aliveIn().erase(livein);
																
			report("    removed from live-in set of block " <<
				block->id());
		}
	}

	auto liveout = block->aliveOut().find(registerId);

	if(liveout == block->aliveOut().end()) return;
	
	// uses by successors
	bool anyUsesBySuccessors = false;
	
	for(auto successor = block->successors().begin();
		successor != block->successors().end(); ++successor)
	{
		auto livein = (*successor)->aliveIn().find(registerId);
		
		if(livein == (*successor)->aliveIn().end()) continue;

		updateUses(*successor, registerId, value, visited);
		
		livein = (*successor)->aliveIn().find(registerId);
		
		if(livein == (*successor)->aliveIn().end()) continue;

		anyUsesBySuccessors = true;
	}

	if(!anyUsesBySuccessors)
	{
		report("    removed from live-out set of BB_" << block->id());
		block->aliveOut().erase(liveout);
	}	
}