bool PrintPass::visit(Function *fn) { char str[16]; INFO("\n%s:%i (", fn->getName(), fn->getLabel()); if (!fn->outs.empty()) INFO("out"); for (std::deque<ValueRef>::iterator it = fn->outs.begin(); it != fn->outs.end(); ++it) { it->get()->print(str, sizeof(str), typeOfSize(it->get()->reg.size)); INFO(" %s", str); } if (!fn->ins.empty()) INFO("%s%sin", colour[TXT_DEFAULT], fn->outs.empty() ? "" : ", "); for (std::deque<ValueDef>::iterator it = fn->ins.begin(); it != fn->ins.end(); ++it) { it->get()->print(str, sizeof(str), typeOfSize(it->get()->reg.size)); INFO(" %s", str); } INFO("%s)\n", colour[TXT_DEFAULT]); return true; }
int Symbol::print(char *buf, size_t size, Value *rel, Value *dimRel, DataType ty) const { size_t pos = 0; char c; if (ty == TYPE_NONE) ty = typeOfSize(reg.size); if (reg.file == FILE_SYSTEM_VALUE) { PRINT("%ssv[%s%s:%i%s", colour[TXT_MEM], colour[TXT_REGISTER], SemanticStr[reg.data.sv.sv], reg.data.sv.index, colour[TXT_MEM]); if (rel) { PRINT("%s+", colour[TXT_DEFAULT]); pos += rel->print(&buf[pos], size - pos); } PRINT("%s]", colour[TXT_MEM]); return pos; } switch (reg.file) { case FILE_MEMORY_CONST: c = 'c'; break; case FILE_SHADER_INPUT: c = 'a'; break; case FILE_SHADER_OUTPUT: c = 'o'; break; case FILE_MEMORY_BUFFER: c = 'b'; break; // Only used before lowering case FILE_MEMORY_GLOBAL: c = 'g'; break; case FILE_MEMORY_SHARED: c = 's'; break; case FILE_MEMORY_LOCAL: c = 'l'; break; default: assert(!"invalid file"); c = '?'; break; } if (c == 'c') PRINT("%s%c%i[", colour[TXT_MEM], c, reg.fileIndex); else PRINT("%s%c[", colour[TXT_MEM], c); if (dimRel) { pos += dimRel->print(&buf[pos], size - pos, TYPE_S32); PRINT("%s][", colour[TXT_MEM]); } if (rel) { pos += rel->print(&buf[pos], size - pos); PRINT("%s%c", colour[TXT_DEFAULT], (reg.data.offset < 0) ? '-' : '+'); } else { assert(reg.data.offset >= 0); } PRINT("%s0x%x%s]", colour[TXT_IMMD], abs(reg.data.offset), colour[TXT_MEM]); return pos; }
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; }
// 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(); }