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; }
Instruction * Instruction::clone(ClonePolicy<Function>& pol, Instruction *i) const { if (!i) i = new_Instruction(pol.context(), op, dType); #ifndef NDEBUG // non-conformant assert, so this is required assert(typeid(*i) == typeid(*this)); #endif pol.set<Instruction>(this, i); i->sType = sType; i->rnd = rnd; i->cache = cache; i->subOp = subOp; i->saturate = saturate; i->join = join; i->exit = exit; i->mask = mask; i->ftz = ftz; i->dnz = dnz; i->ipa = ipa; i->lanes = lanes; i->perPatch = perPatch; i->postFactor = postFactor; for (int d = 0; defExists(d); ++d) i->setDef(d, pol.get(getDef(d))); for (int s = 0; srcExists(s); ++s) { i->setSrc(s, pol.get(getSrc(s))); i->src(s).mod = src(s).mod; } i->cc = cc; i->predSrc = predSrc; i->flagsDef = flagsDef; i->flagsSrc = flagsSrc; return i; }
// Efficiently Computing Static Single Assignment Form and // the Control Dependence Graph, // R. Cytron, J. Ferrante, B. K. Rosen, M. N. Wegman, F. K. Zadeck bool Function::convertToSSA() { // 0. calculate live in variables (for pruned SSA) buildLiveSets(); // 1. create the dominator tree domTree = new DominatorTree(&cfg); reinterpret_cast<DominatorTree *>(domTree)->findDominanceFrontiers(); // 2. insert PHI functions DLList workList; LValue *lval; BasicBlock *bb; int var; int iterCount = 0; int *hasAlready = new int[allBBlocks.getSize() * 2]; int *work = &hasAlready[allBBlocks.getSize()]; memset(hasAlready, 0, allBBlocks.getSize() * 2 * sizeof(int)); // for each variable for (var = 0; var < allLValues.getSize(); ++var) { if (!allLValues.get(var)) continue; lval = reinterpret_cast<Value *>(allLValues.get(var))->asLValue(); if (!lval || lval->defs.empty()) continue; ++iterCount; // TODO: don't add phi functions for values that aren't used outside // the BB they're defined in // gather blocks with assignments to lval in workList for (Value::DefIterator d = lval->defs.begin(); d != lval->defs.end(); ++d) { bb = ((*d)->getInsn() ? (*d)->getInsn()->bb : NULL); if (!bb) continue; // instruction likely been removed but not XXX deleted if (work[bb->getId()] == iterCount) continue; work[bb->getId()] = iterCount; workList.insert(bb); } // for each block in workList, insert a phi for lval in the block's // dominance frontier (if we haven't already done so) for (DLList::Iterator wI = workList.iterator(); !wI.end(); wI.erase()) { bb = BasicBlock::get(wI); DLList::Iterator dfIter = bb->getDF().iterator(); for (; !dfIter.end(); dfIter.next()) { Instruction *phi; BasicBlock *dfBB = BasicBlock::get(dfIter); if (hasAlready[dfBB->getId()] >= iterCount) continue; hasAlready[dfBB->getId()] = iterCount; // pruned SSA: don't need a phi if the value is not live-in if (!dfBB->liveSet.test(lval->id)) continue; phi = new_Instruction(this, OP_PHI, typeOfSize(lval->reg.size)); dfBB->insertTail(phi); phi->setDef(0, lval); for (int s = 0; s < dfBB->cfg.incidentCount(); ++s) phi->setSrc(s, lval); if (work[dfBB->getId()] < iterCount) { work[dfBB->getId()] = iterCount; wI.insert(dfBB); } } } } delete[] hasAlready; RenamePass rename(this); return rename.run(); }