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); } }
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); } }