LValue * RenamePass::mkUndefined(Value *val) { LValue *lval = val->asLValue(); assert(lval); LValue *ud = new_LValue(func, lval); Instruction *nop = new_Instruction(func, OP_NOP, typeOfSize(lval->reg.size)); nop->setDef(0, ud); BasicBlock::get(func->cfg.getRoot())->insertHead(nop); return ud; }
LValue * LValue::clone(ClonePolicy<Function>& pol) const { LValue *that = new_LValue(pol.context(), reg.file); pol.set<Value>(this, that); that->reg.size = this->reg.size; that->reg.type = this->reg.type; that->reg.data = this->reg.data; return that; }
// Go through BBs in dominance order, create new values for each definition, // and replace all sources with their current new values. // // NOTE: The values generated for function inputs/outputs have no connection // to their corresponding outputs/inputs in other functions. Only allocation // of physical registers will establish this connection. // void RenamePass::search(BasicBlock *bb) { LValue *lval, *ssa; int d, s; const Target *targ = prog->getTarget(); // Put current definitions for function inputs values on the stack. // They can be used before any redefinitions are pushed. if (bb == BasicBlock::get(func->cfg.getRoot())) { for (std::deque<ValueDef>::iterator it = func->ins.begin(); it != func->ins.end(); ++it) { lval = it->get()->asLValue(); assert(lval); ssa = new_LValue(func, targ->nativeFile(lval->reg.file)); ssa->reg.size = lval->reg.size; ssa->reg.data.id = lval->reg.data.id; it->setSSA(ssa); stack[lval->id].push(ssa); } } for (Instruction *stmt = bb->getFirst(); stmt; stmt = stmt->next) { // PHI sources get definitions from the passes through the incident BBs, // so skip them here. if (stmt->op != OP_PHI) { for (s = 0; stmt->srcExists(s); ++s) { lval = stmt->getSrc(s)->asLValue(); if (!lval) continue; // Values on the stack created in previously visited blocks, and // function inputs, will be valid because they dominate this one. lval = getStackTop(lval); if (!lval) lval = mkUndefined(stmt->getSrc(s)); stmt->setSrc(s, lval); } } for (d = 0; stmt->defExists(d); ++d) { lval = stmt->def(d).get()->asLValue(); assert(lval); stmt->def(d).setSSA( new_LValue(func, targ->nativeFile(lval->reg.file))); stmt->def(d).get()->reg.size = lval->reg.size; stmt->def(d).get()->reg.data.id = lval->reg.data.id; stack[lval->id].push(stmt->def(d).get()); } } // Update sources of PHI ops corresponding to this BB in outgoing BBs. for (Graph::EdgeIterator ei = bb->cfg.outgoing(); !ei.end(); ei.next()) { Instruction *phi; int p = 0; BasicBlock *sb = BasicBlock::get(ei.getNode()); // which predecessor of sb is bb ? for (Graph::EdgeIterator ei = sb->cfg.incident(); !ei.end(); ei.next()) { if (ei.getNode() == &bb->cfg) break; ++p; } assert(p < sb->cfg.incidentCount()); for (phi = sb->getPhi(); phi && phi->op == OP_PHI; phi = phi->next) { lval = getStackTop(phi->getSrc(p)); if (!lval) lval = mkUndefined(phi->getSrc(p)); phi->setSrc(p, lval); } } // Visit the BBs we dominate. for (Graph::EdgeIterator ei = bb->dom.outgoing(); !ei.end(); ei.next()) search(BasicBlock::get(ei.getNode())); // Update function outputs to the last definitions of their pre-SSA values. // I hope they're unique, i.e. that we get PHIs for all of them ... if (bb == BasicBlock::get(func->cfgExit)) { for (std::deque<ValueRef>::iterator it = func->outs.begin(); it != func->outs.end(); ++it) { lval = it->get()->asLValue(); if (!lval) continue; lval = getStackTop(lval); if (!lval) lval = mkUndefined(it->get()); it->set(lval); } } // Pop the values we created in this block from the stack because we will // return to blocks that we do not dominate. for (Instruction *stmt = bb->getFirst(); stmt; stmt = stmt->next) { if (stmt->op == OP_NOP) continue; for (d = 0; stmt->defExists(d); ++d) stack[stmt->def(d).preSSA()->id].pop(); } }