1bf215546Sopenharmony_ci/* 2bf215546Sopenharmony_ci * Copyright 2011 Christoph Bumiller 3bf215546Sopenharmony_ci * 4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 5bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 6bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation 7bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the 9bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions: 10bf215546Sopenharmony_ci * 11bf215546Sopenharmony_ci * The above copyright notice and this permission notice shall be included in 12bf215546Sopenharmony_ci * all copies or substantial portions of the Software. 13bf215546Sopenharmony_ci * 14bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 18bf215546Sopenharmony_ci * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19bf215546Sopenharmony_ci * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20bf215546Sopenharmony_ci * OTHER DEALINGS IN THE SOFTWARE. 21bf215546Sopenharmony_ci */ 22bf215546Sopenharmony_ci 23bf215546Sopenharmony_ci#include "nv50_ir.h" 24bf215546Sopenharmony_ci#include "nv50_ir_target.h" 25bf215546Sopenharmony_ci 26bf215546Sopenharmony_cinamespace nv50_ir { 27bf215546Sopenharmony_ci 28bf215546Sopenharmony_ci// Converts nv50 IR generated from TGSI to SSA form. 29bf215546Sopenharmony_ci 30bf215546Sopenharmony_ci// DominatorTree implements an algorithm for finding immediate dominators, 31bf215546Sopenharmony_ci// as described by T. Lengauer & R. Tarjan. 32bf215546Sopenharmony_ciclass DominatorTree : public Graph 33bf215546Sopenharmony_ci{ 34bf215546Sopenharmony_cipublic: 35bf215546Sopenharmony_ci DominatorTree(Graph *cfg); 36bf215546Sopenharmony_ci ~DominatorTree() { } 37bf215546Sopenharmony_ci 38bf215546Sopenharmony_ci bool dominates(BasicBlock *, BasicBlock *); 39bf215546Sopenharmony_ci 40bf215546Sopenharmony_ci void findDominanceFrontiers(); 41bf215546Sopenharmony_ci 42bf215546Sopenharmony_ciprivate: 43bf215546Sopenharmony_ci void build(); 44bf215546Sopenharmony_ci void buildDFS(Node *); 45bf215546Sopenharmony_ci 46bf215546Sopenharmony_ci void squash(int); 47bf215546Sopenharmony_ci inline void link(int, int); 48bf215546Sopenharmony_ci inline int eval(int); 49bf215546Sopenharmony_ci 50bf215546Sopenharmony_ci void debugPrint(); 51bf215546Sopenharmony_ci 52bf215546Sopenharmony_ci Graph *cfg; 53bf215546Sopenharmony_ci 54bf215546Sopenharmony_ci Node **vert; 55bf215546Sopenharmony_ci int *data; 56bf215546Sopenharmony_ci const int count; 57bf215546Sopenharmony_ci 58bf215546Sopenharmony_ci #define SEMI(i) (data[(i) + 0 * count]) 59bf215546Sopenharmony_ci #define ANCESTOR(i) (data[(i) + 1 * count]) 60bf215546Sopenharmony_ci #define PARENT(i) (data[(i) + 2 * count]) 61bf215546Sopenharmony_ci #define LABEL(i) (data[(i) + 3 * count]) 62bf215546Sopenharmony_ci #define DOM(i) (data[(i) + 4 * count]) 63bf215546Sopenharmony_ci}; 64bf215546Sopenharmony_ci 65bf215546Sopenharmony_civoid DominatorTree::debugPrint() 66bf215546Sopenharmony_ci{ 67bf215546Sopenharmony_ci for (int i = 0; i < count; ++i) { 68bf215546Sopenharmony_ci INFO("SEMI(%i) = %i\n", i, SEMI(i)); 69bf215546Sopenharmony_ci INFO("ANCESTOR(%i) = %i\n", i, ANCESTOR(i)); 70bf215546Sopenharmony_ci INFO("PARENT(%i) = %i\n", i, PARENT(i)); 71bf215546Sopenharmony_ci INFO("LABEL(%i) = %i\n", i, LABEL(i)); 72bf215546Sopenharmony_ci INFO("DOM(%i) = %i\n", i, DOM(i)); 73bf215546Sopenharmony_ci } 74bf215546Sopenharmony_ci} 75bf215546Sopenharmony_ci 76bf215546Sopenharmony_ciDominatorTree::DominatorTree(Graph *cfgraph) : cfg(cfgraph), 77bf215546Sopenharmony_ci count(cfg->getSize()) 78bf215546Sopenharmony_ci{ 79bf215546Sopenharmony_ci int i = 0; 80bf215546Sopenharmony_ci 81bf215546Sopenharmony_ci vert = new Node * [count]; 82bf215546Sopenharmony_ci data = new int[5 * count]; 83bf215546Sopenharmony_ci 84bf215546Sopenharmony_ci for (IteratorRef it = cfg->iteratorDFS(true); !it->end(); it->next(), ++i) { 85bf215546Sopenharmony_ci vert[i] = reinterpret_cast<Node *>(it->get()); 86bf215546Sopenharmony_ci vert[i]->tag = i; 87bf215546Sopenharmony_ci LABEL(i) = i; 88bf215546Sopenharmony_ci SEMI(i) = ANCESTOR(i) = -1; 89bf215546Sopenharmony_ci } 90bf215546Sopenharmony_ci assert(i == count); 91bf215546Sopenharmony_ci 92bf215546Sopenharmony_ci build(); 93bf215546Sopenharmony_ci 94bf215546Sopenharmony_ci delete[] vert; 95bf215546Sopenharmony_ci delete[] data; 96bf215546Sopenharmony_ci} 97bf215546Sopenharmony_ci 98bf215546Sopenharmony_civoid DominatorTree::buildDFS(Graph::Node *node) 99bf215546Sopenharmony_ci{ 100bf215546Sopenharmony_ci SEMI(node->tag) = node->tag; 101bf215546Sopenharmony_ci 102bf215546Sopenharmony_ci for (Graph::EdgeIterator ei = node->outgoing(); !ei.end(); ei.next()) { 103bf215546Sopenharmony_ci if (SEMI(ei.getNode()->tag) < 0) { 104bf215546Sopenharmony_ci buildDFS(ei.getNode()); 105bf215546Sopenharmony_ci PARENT(ei.getNode()->tag) = node->tag; 106bf215546Sopenharmony_ci } 107bf215546Sopenharmony_ci } 108bf215546Sopenharmony_ci} 109bf215546Sopenharmony_ci 110bf215546Sopenharmony_civoid DominatorTree::squash(int v) 111bf215546Sopenharmony_ci{ 112bf215546Sopenharmony_ci if (ANCESTOR(ANCESTOR(v)) >= 0) { 113bf215546Sopenharmony_ci squash(ANCESTOR(v)); 114bf215546Sopenharmony_ci 115bf215546Sopenharmony_ci if (SEMI(LABEL(ANCESTOR(v))) < SEMI(LABEL(v))) 116bf215546Sopenharmony_ci LABEL(v) = LABEL(ANCESTOR(v)); 117bf215546Sopenharmony_ci ANCESTOR(v) = ANCESTOR(ANCESTOR(v)); 118bf215546Sopenharmony_ci } 119bf215546Sopenharmony_ci} 120bf215546Sopenharmony_ci 121bf215546Sopenharmony_ciint DominatorTree::eval(int v) 122bf215546Sopenharmony_ci{ 123bf215546Sopenharmony_ci if (ANCESTOR(v) < 0) 124bf215546Sopenharmony_ci return v; 125bf215546Sopenharmony_ci squash(v); 126bf215546Sopenharmony_ci return LABEL(v); 127bf215546Sopenharmony_ci} 128bf215546Sopenharmony_ci 129bf215546Sopenharmony_civoid DominatorTree::link(int v, int w) 130bf215546Sopenharmony_ci{ 131bf215546Sopenharmony_ci ANCESTOR(w) = v; 132bf215546Sopenharmony_ci} 133bf215546Sopenharmony_ci 134bf215546Sopenharmony_civoid DominatorTree::build() 135bf215546Sopenharmony_ci{ 136bf215546Sopenharmony_ci DLList *bucket = new DLList[count]; 137bf215546Sopenharmony_ci Node *nv, *nw; 138bf215546Sopenharmony_ci int p, u, v, w; 139bf215546Sopenharmony_ci 140bf215546Sopenharmony_ci buildDFS(cfg->getRoot()); 141bf215546Sopenharmony_ci 142bf215546Sopenharmony_ci for (w = count - 1; w >= 1; --w) { 143bf215546Sopenharmony_ci nw = vert[w]; 144bf215546Sopenharmony_ci assert(nw->tag == w); 145bf215546Sopenharmony_ci for (Graph::EdgeIterator ei = nw->incident(); !ei.end(); ei.next()) { 146bf215546Sopenharmony_ci nv = ei.getNode(); 147bf215546Sopenharmony_ci v = nv->tag; 148bf215546Sopenharmony_ci u = eval(v); 149bf215546Sopenharmony_ci if (SEMI(u) < SEMI(w)) 150bf215546Sopenharmony_ci SEMI(w) = SEMI(u); 151bf215546Sopenharmony_ci } 152bf215546Sopenharmony_ci p = PARENT(w); 153bf215546Sopenharmony_ci bucket[SEMI(w)].insert(nw); 154bf215546Sopenharmony_ci link(p, w); 155bf215546Sopenharmony_ci 156bf215546Sopenharmony_ci for (DLList::Iterator it = bucket[p].iterator(); !it.end(); it.erase()) { 157bf215546Sopenharmony_ci v = reinterpret_cast<Node *>(it.get())->tag; 158bf215546Sopenharmony_ci u = eval(v); 159bf215546Sopenharmony_ci DOM(v) = (SEMI(u) < SEMI(v)) ? u : p; 160bf215546Sopenharmony_ci } 161bf215546Sopenharmony_ci } 162bf215546Sopenharmony_ci for (w = 1; w < count; ++w) { 163bf215546Sopenharmony_ci if (DOM(w) != SEMI(w)) 164bf215546Sopenharmony_ci DOM(w) = DOM(DOM(w)); 165bf215546Sopenharmony_ci } 166bf215546Sopenharmony_ci DOM(0) = 0; 167bf215546Sopenharmony_ci 168bf215546Sopenharmony_ci insert(&BasicBlock::get(cfg->getRoot())->dom); 169bf215546Sopenharmony_ci do { 170bf215546Sopenharmony_ci p = 0; 171bf215546Sopenharmony_ci for (v = 1; v < count; ++v) { 172bf215546Sopenharmony_ci nw = &BasicBlock::get(vert[DOM(v)])->dom; 173bf215546Sopenharmony_ci nv = &BasicBlock::get(vert[v])->dom; 174bf215546Sopenharmony_ci if (nw->getGraph() && !nv->getGraph()) { 175bf215546Sopenharmony_ci ++p; 176bf215546Sopenharmony_ci nw->attach(nv, Graph::Edge::TREE); 177bf215546Sopenharmony_ci } 178bf215546Sopenharmony_ci } 179bf215546Sopenharmony_ci } while (p); 180bf215546Sopenharmony_ci 181bf215546Sopenharmony_ci delete[] bucket; 182bf215546Sopenharmony_ci} 183bf215546Sopenharmony_ci 184bf215546Sopenharmony_ci#undef SEMI 185bf215546Sopenharmony_ci#undef ANCESTOR 186bf215546Sopenharmony_ci#undef PARENT 187bf215546Sopenharmony_ci#undef LABEL 188bf215546Sopenharmony_ci#undef DOM 189bf215546Sopenharmony_ci 190bf215546Sopenharmony_civoid DominatorTree::findDominanceFrontiers() 191bf215546Sopenharmony_ci{ 192bf215546Sopenharmony_ci BasicBlock *bb; 193bf215546Sopenharmony_ci 194bf215546Sopenharmony_ci for (IteratorRef dtIt = iteratorDFS(false); !dtIt->end(); dtIt->next()) { 195bf215546Sopenharmony_ci EdgeIterator succIt, chldIt; 196bf215546Sopenharmony_ci 197bf215546Sopenharmony_ci bb = BasicBlock::get(reinterpret_cast<Node *>(dtIt->get())); 198bf215546Sopenharmony_ci bb->getDF().clear(); 199bf215546Sopenharmony_ci 200bf215546Sopenharmony_ci for (succIt = bb->cfg.outgoing(); !succIt.end(); succIt.next()) { 201bf215546Sopenharmony_ci BasicBlock *dfLocal = BasicBlock::get(succIt.getNode()); 202bf215546Sopenharmony_ci if (dfLocal->idom() != bb) 203bf215546Sopenharmony_ci bb->getDF().insert(dfLocal); 204bf215546Sopenharmony_ci } 205bf215546Sopenharmony_ci 206bf215546Sopenharmony_ci for (chldIt = bb->dom.outgoing(); !chldIt.end(); chldIt.next()) { 207bf215546Sopenharmony_ci BasicBlock *cb = BasicBlock::get(chldIt.getNode()); 208bf215546Sopenharmony_ci 209bf215546Sopenharmony_ci DLList::Iterator dfIt = cb->getDF().iterator(); 210bf215546Sopenharmony_ci for (; !dfIt.end(); dfIt.next()) { 211bf215546Sopenharmony_ci BasicBlock *dfUp = BasicBlock::get(dfIt); 212bf215546Sopenharmony_ci if (dfUp->idom() != bb) 213bf215546Sopenharmony_ci bb->getDF().insert(dfUp); 214bf215546Sopenharmony_ci } 215bf215546Sopenharmony_ci } 216bf215546Sopenharmony_ci } 217bf215546Sopenharmony_ci} 218bf215546Sopenharmony_ci 219bf215546Sopenharmony_ci// liveIn(bb) = usedBeforeAssigned(bb) U (liveOut(bb) - assigned(bb)) 220bf215546Sopenharmony_civoid 221bf215546Sopenharmony_ciFunction::buildLiveSetsPreSSA(BasicBlock *bb, const int seq) 222bf215546Sopenharmony_ci{ 223bf215546Sopenharmony_ci Function *f = bb->getFunction(); 224bf215546Sopenharmony_ci BitSet usedBeforeAssigned(allLValues.getSize(), true); 225bf215546Sopenharmony_ci BitSet assigned(allLValues.getSize(), true); 226bf215546Sopenharmony_ci 227bf215546Sopenharmony_ci bb->liveSet.allocate(allLValues.getSize(), false); 228bf215546Sopenharmony_ci 229bf215546Sopenharmony_ci int n = 0; 230bf215546Sopenharmony_ci for (Graph::EdgeIterator ei = bb->cfg.outgoing(); !ei.end(); ei.next()) { 231bf215546Sopenharmony_ci BasicBlock *out = BasicBlock::get(ei.getNode()); 232bf215546Sopenharmony_ci if (out == bb) 233bf215546Sopenharmony_ci continue; 234bf215546Sopenharmony_ci if (out->cfg.visit(seq)) 235bf215546Sopenharmony_ci buildLiveSetsPreSSA(out, seq); 236bf215546Sopenharmony_ci if (!n++) 237bf215546Sopenharmony_ci bb->liveSet = out->liveSet; 238bf215546Sopenharmony_ci else 239bf215546Sopenharmony_ci bb->liveSet |= out->liveSet; 240bf215546Sopenharmony_ci } 241bf215546Sopenharmony_ci if (!n && !bb->liveSet.marker) 242bf215546Sopenharmony_ci bb->liveSet.fill(0); 243bf215546Sopenharmony_ci bb->liveSet.marker = true; 244bf215546Sopenharmony_ci 245bf215546Sopenharmony_ci for (Instruction *i = bb->getEntry(); i; i = i->next) { 246bf215546Sopenharmony_ci for (int s = 0; i->srcExists(s); ++s) 247bf215546Sopenharmony_ci if (i->getSrc(s)->asLValue() && !assigned.test(i->getSrc(s)->id)) 248bf215546Sopenharmony_ci usedBeforeAssigned.set(i->getSrc(s)->id); 249bf215546Sopenharmony_ci for (int d = 0; i->defExists(d); ++d) 250bf215546Sopenharmony_ci assigned.set(i->getDef(d)->id); 251bf215546Sopenharmony_ci } 252bf215546Sopenharmony_ci 253bf215546Sopenharmony_ci if (bb == BasicBlock::get(f->cfgExit)) { 254bf215546Sopenharmony_ci for (std::deque<ValueRef>::iterator it = f->outs.begin(); 255bf215546Sopenharmony_ci it != f->outs.end(); ++it) { 256bf215546Sopenharmony_ci if (!assigned.test(it->get()->id)) 257bf215546Sopenharmony_ci usedBeforeAssigned.set(it->get()->id); 258bf215546Sopenharmony_ci } 259bf215546Sopenharmony_ci } 260bf215546Sopenharmony_ci 261bf215546Sopenharmony_ci bb->liveSet.andNot(assigned); 262bf215546Sopenharmony_ci bb->liveSet |= usedBeforeAssigned; 263bf215546Sopenharmony_ci} 264bf215546Sopenharmony_ci 265bf215546Sopenharmony_civoid 266bf215546Sopenharmony_ciFunction::buildDefSetsPreSSA(BasicBlock *bb, const int seq) 267bf215546Sopenharmony_ci{ 268bf215546Sopenharmony_ci bb->defSet.allocate(allLValues.getSize(), !bb->liveSet.marker); 269bf215546Sopenharmony_ci bb->liveSet.marker = true; 270bf215546Sopenharmony_ci 271bf215546Sopenharmony_ci for (Graph::EdgeIterator ei = bb->cfg.incident(); !ei.end(); ei.next()) { 272bf215546Sopenharmony_ci BasicBlock *in = BasicBlock::get(ei.getNode()); 273bf215546Sopenharmony_ci 274bf215546Sopenharmony_ci if (in->cfg.visit(seq)) 275bf215546Sopenharmony_ci buildDefSetsPreSSA(in, seq); 276bf215546Sopenharmony_ci 277bf215546Sopenharmony_ci bb->defSet |= in->defSet; 278bf215546Sopenharmony_ci } 279bf215546Sopenharmony_ci 280bf215546Sopenharmony_ci for (Instruction *i = bb->getEntry(); i; i = i->next) { 281bf215546Sopenharmony_ci for (int d = 0; i->defExists(d); ++d) 282bf215546Sopenharmony_ci bb->defSet.set(i->getDef(d)->id); 283bf215546Sopenharmony_ci } 284bf215546Sopenharmony_ci} 285bf215546Sopenharmony_ci 286bf215546Sopenharmony_ciclass RenamePass 287bf215546Sopenharmony_ci{ 288bf215546Sopenharmony_cipublic: 289bf215546Sopenharmony_ci RenamePass(Function *); 290bf215546Sopenharmony_ci ~RenamePass(); 291bf215546Sopenharmony_ci 292bf215546Sopenharmony_ci bool run(); 293bf215546Sopenharmony_ci void search(BasicBlock *); 294bf215546Sopenharmony_ci 295bf215546Sopenharmony_ci inline LValue *getStackTop(Value *); 296bf215546Sopenharmony_ci 297bf215546Sopenharmony_ci LValue *mkUndefined(Value *); 298bf215546Sopenharmony_ci 299bf215546Sopenharmony_ciprivate: 300bf215546Sopenharmony_ci Stack *stack; 301bf215546Sopenharmony_ci Function *func; 302bf215546Sopenharmony_ci Program *prog; 303bf215546Sopenharmony_ci}; 304bf215546Sopenharmony_ci 305bf215546Sopenharmony_cibool 306bf215546Sopenharmony_ciProgram::convertToSSA() 307bf215546Sopenharmony_ci{ 308bf215546Sopenharmony_ci for (ArrayList::Iterator fi = allFuncs.iterator(); !fi.end(); fi.next()) { 309bf215546Sopenharmony_ci Function *fn = reinterpret_cast<Function *>(fi.get()); 310bf215546Sopenharmony_ci if (!fn->convertToSSA()) 311bf215546Sopenharmony_ci return false; 312bf215546Sopenharmony_ci } 313bf215546Sopenharmony_ci return true; 314bf215546Sopenharmony_ci} 315bf215546Sopenharmony_ci 316bf215546Sopenharmony_ci// XXX: add edge from entry to exit ? 317bf215546Sopenharmony_ci 318bf215546Sopenharmony_ci// Efficiently Computing Static Single Assignment Form and 319bf215546Sopenharmony_ci// the Control Dependence Graph, 320bf215546Sopenharmony_ci// R. Cytron, J. Ferrante, B. K. Rosen, M. N. Wegman, F. K. Zadeck 321bf215546Sopenharmony_cibool 322bf215546Sopenharmony_ciFunction::convertToSSA() 323bf215546Sopenharmony_ci{ 324bf215546Sopenharmony_ci // 0. calculate live in variables (for pruned SSA) 325bf215546Sopenharmony_ci buildLiveSets(); 326bf215546Sopenharmony_ci 327bf215546Sopenharmony_ci // 1. create the dominator tree 328bf215546Sopenharmony_ci domTree = new DominatorTree(&cfg); 329bf215546Sopenharmony_ci reinterpret_cast<DominatorTree *>(domTree)->findDominanceFrontiers(); 330bf215546Sopenharmony_ci 331bf215546Sopenharmony_ci // 2. insert PHI functions 332bf215546Sopenharmony_ci DLList workList; 333bf215546Sopenharmony_ci LValue *lval; 334bf215546Sopenharmony_ci BasicBlock *bb; 335bf215546Sopenharmony_ci int var; 336bf215546Sopenharmony_ci int iterCount = 0; 337bf215546Sopenharmony_ci int *hasAlready = new int[allBBlocks.getSize() * 2]; 338bf215546Sopenharmony_ci int *work = &hasAlready[allBBlocks.getSize()]; 339bf215546Sopenharmony_ci 340bf215546Sopenharmony_ci memset(hasAlready, 0, allBBlocks.getSize() * 2 * sizeof(int)); 341bf215546Sopenharmony_ci 342bf215546Sopenharmony_ci // for each variable 343bf215546Sopenharmony_ci for (var = 0; var < allLValues.getSize(); ++var) { 344bf215546Sopenharmony_ci if (!allLValues.get(var)) 345bf215546Sopenharmony_ci continue; 346bf215546Sopenharmony_ci lval = reinterpret_cast<Value *>(allLValues.get(var))->asLValue(); 347bf215546Sopenharmony_ci if (!lval || lval->defs.empty()) 348bf215546Sopenharmony_ci continue; 349bf215546Sopenharmony_ci ++iterCount; 350bf215546Sopenharmony_ci 351bf215546Sopenharmony_ci // TODO: don't add phi functions for values that aren't used outside 352bf215546Sopenharmony_ci // the BB they're defined in 353bf215546Sopenharmony_ci 354bf215546Sopenharmony_ci // gather blocks with assignments to lval in workList 355bf215546Sopenharmony_ci for (Value::DefIterator d = lval->defs.begin(); 356bf215546Sopenharmony_ci d != lval->defs.end(); ++d) { 357bf215546Sopenharmony_ci bb = ((*d)->getInsn() ? (*d)->getInsn()->bb : NULL); 358bf215546Sopenharmony_ci if (!bb) 359bf215546Sopenharmony_ci continue; // instruction likely been removed but not XXX deleted 360bf215546Sopenharmony_ci 361bf215546Sopenharmony_ci if (work[bb->getId()] == iterCount) 362bf215546Sopenharmony_ci continue; 363bf215546Sopenharmony_ci work[bb->getId()] = iterCount; 364bf215546Sopenharmony_ci workList.insert(bb); 365bf215546Sopenharmony_ci } 366bf215546Sopenharmony_ci 367bf215546Sopenharmony_ci // for each block in workList, insert a phi for lval in the block's 368bf215546Sopenharmony_ci // dominance frontier (if we haven't already done so) 369bf215546Sopenharmony_ci for (DLList::Iterator wI = workList.iterator(); !wI.end(); wI.erase()) { 370bf215546Sopenharmony_ci bb = BasicBlock::get(wI); 371bf215546Sopenharmony_ci 372bf215546Sopenharmony_ci DLList::Iterator dfIter = bb->getDF().iterator(); 373bf215546Sopenharmony_ci for (; !dfIter.end(); dfIter.next()) { 374bf215546Sopenharmony_ci Instruction *phi; 375bf215546Sopenharmony_ci BasicBlock *dfBB = BasicBlock::get(dfIter); 376bf215546Sopenharmony_ci 377bf215546Sopenharmony_ci if (hasAlready[dfBB->getId()] >= iterCount) 378bf215546Sopenharmony_ci continue; 379bf215546Sopenharmony_ci hasAlready[dfBB->getId()] = iterCount; 380bf215546Sopenharmony_ci 381bf215546Sopenharmony_ci // pruned SSA: don't need a phi if the value is not live-in 382bf215546Sopenharmony_ci if (!dfBB->liveSet.test(lval->id)) 383bf215546Sopenharmony_ci continue; 384bf215546Sopenharmony_ci 385bf215546Sopenharmony_ci phi = new_Instruction(this, OP_PHI, typeOfSize(lval->reg.size)); 386bf215546Sopenharmony_ci dfBB->insertTail(phi); 387bf215546Sopenharmony_ci 388bf215546Sopenharmony_ci phi->setDef(0, lval); 389bf215546Sopenharmony_ci for (int s = 0; s < dfBB->cfg.incidentCount(); ++s) 390bf215546Sopenharmony_ci phi->setSrc(s, lval); 391bf215546Sopenharmony_ci 392bf215546Sopenharmony_ci if (work[dfBB->getId()] < iterCount) { 393bf215546Sopenharmony_ci work[dfBB->getId()] = iterCount; 394bf215546Sopenharmony_ci wI.insert(dfBB); 395bf215546Sopenharmony_ci } 396bf215546Sopenharmony_ci } 397bf215546Sopenharmony_ci } 398bf215546Sopenharmony_ci } 399bf215546Sopenharmony_ci delete[] hasAlready; 400bf215546Sopenharmony_ci 401bf215546Sopenharmony_ci RenamePass rename(this); 402bf215546Sopenharmony_ci return rename.run(); 403bf215546Sopenharmony_ci} 404bf215546Sopenharmony_ci 405bf215546Sopenharmony_ciRenamePass::RenamePass(Function *fn) : func(fn), prog(fn->getProgram()) 406bf215546Sopenharmony_ci{ 407bf215546Sopenharmony_ci stack = new Stack[func->allLValues.getSize()]; 408bf215546Sopenharmony_ci} 409bf215546Sopenharmony_ci 410bf215546Sopenharmony_ciRenamePass::~RenamePass() 411bf215546Sopenharmony_ci{ 412bf215546Sopenharmony_ci if (stack) 413bf215546Sopenharmony_ci delete[] stack; 414bf215546Sopenharmony_ci} 415bf215546Sopenharmony_ci 416bf215546Sopenharmony_ciLValue * 417bf215546Sopenharmony_ciRenamePass::getStackTop(Value *val) 418bf215546Sopenharmony_ci{ 419bf215546Sopenharmony_ci if (!stack[val->id].getSize()) 420bf215546Sopenharmony_ci return 0; 421bf215546Sopenharmony_ci return reinterpret_cast<LValue *>(stack[val->id].peek().u.p); 422bf215546Sopenharmony_ci} 423bf215546Sopenharmony_ci 424bf215546Sopenharmony_ciLValue * 425bf215546Sopenharmony_ciRenamePass::mkUndefined(Value *val) 426bf215546Sopenharmony_ci{ 427bf215546Sopenharmony_ci LValue *lval = val->asLValue(); 428bf215546Sopenharmony_ci assert(lval); 429bf215546Sopenharmony_ci LValue *ud = new_LValue(func, lval); 430bf215546Sopenharmony_ci Instruction *nop = new_Instruction(func, OP_NOP, typeOfSize(lval->reg.size)); 431bf215546Sopenharmony_ci nop->setDef(0, ud); 432bf215546Sopenharmony_ci BasicBlock::get(func->cfg.getRoot())->insertHead(nop); 433bf215546Sopenharmony_ci return ud; 434bf215546Sopenharmony_ci} 435bf215546Sopenharmony_ci 436bf215546Sopenharmony_cibool RenamePass::run() 437bf215546Sopenharmony_ci{ 438bf215546Sopenharmony_ci if (!stack) 439bf215546Sopenharmony_ci return false; 440bf215546Sopenharmony_ci search(BasicBlock::get(func->domTree->getRoot())); 441bf215546Sopenharmony_ci 442bf215546Sopenharmony_ci return true; 443bf215546Sopenharmony_ci} 444bf215546Sopenharmony_ci 445bf215546Sopenharmony_ci// Go through BBs in dominance order, create new values for each definition, 446bf215546Sopenharmony_ci// and replace all sources with their current new values. 447bf215546Sopenharmony_ci// 448bf215546Sopenharmony_ci// NOTE: The values generated for function inputs/outputs have no connection 449bf215546Sopenharmony_ci// to their corresponding outputs/inputs in other functions. Only allocation 450bf215546Sopenharmony_ci// of physical registers will establish this connection. 451bf215546Sopenharmony_ci// 452bf215546Sopenharmony_civoid RenamePass::search(BasicBlock *bb) 453bf215546Sopenharmony_ci{ 454bf215546Sopenharmony_ci LValue *lval, *ssa; 455bf215546Sopenharmony_ci int d, s; 456bf215546Sopenharmony_ci const Target *targ = prog->getTarget(); 457bf215546Sopenharmony_ci 458bf215546Sopenharmony_ci // Put current definitions for function inputs values on the stack. 459bf215546Sopenharmony_ci // They can be used before any redefinitions are pushed. 460bf215546Sopenharmony_ci if (bb == BasicBlock::get(func->cfg.getRoot())) { 461bf215546Sopenharmony_ci for (std::deque<ValueDef>::iterator it = func->ins.begin(); 462bf215546Sopenharmony_ci it != func->ins.end(); ++it) { 463bf215546Sopenharmony_ci lval = it->get()->asLValue(); 464bf215546Sopenharmony_ci assert(lval); 465bf215546Sopenharmony_ci 466bf215546Sopenharmony_ci ssa = new_LValue(func, targ->nativeFile(lval->reg.file)); 467bf215546Sopenharmony_ci ssa->reg.size = lval->reg.size; 468bf215546Sopenharmony_ci ssa->reg.data.id = lval->reg.data.id; 469bf215546Sopenharmony_ci 470bf215546Sopenharmony_ci it->setSSA(ssa); 471bf215546Sopenharmony_ci stack[lval->id].push(ssa); 472bf215546Sopenharmony_ci } 473bf215546Sopenharmony_ci } 474bf215546Sopenharmony_ci 475bf215546Sopenharmony_ci for (Instruction *stmt = bb->getFirst(); stmt; stmt = stmt->next) { 476bf215546Sopenharmony_ci // PHI sources get definitions from the passes through the incident BBs, 477bf215546Sopenharmony_ci // so skip them here. 478bf215546Sopenharmony_ci if (stmt->op != OP_PHI) { 479bf215546Sopenharmony_ci for (s = 0; stmt->srcExists(s); ++s) { 480bf215546Sopenharmony_ci lval = stmt->getSrc(s)->asLValue(); 481bf215546Sopenharmony_ci if (!lval) 482bf215546Sopenharmony_ci continue; 483bf215546Sopenharmony_ci // Values on the stack created in previously visited blocks, and 484bf215546Sopenharmony_ci // function inputs, will be valid because they dominate this one. 485bf215546Sopenharmony_ci lval = getStackTop(lval); 486bf215546Sopenharmony_ci if (!lval) 487bf215546Sopenharmony_ci lval = mkUndefined(stmt->getSrc(s)); 488bf215546Sopenharmony_ci stmt->setSrc(s, lval); 489bf215546Sopenharmony_ci } 490bf215546Sopenharmony_ci } 491bf215546Sopenharmony_ci for (d = 0; stmt->defExists(d); ++d) { 492bf215546Sopenharmony_ci lval = stmt->def(d).get()->asLValue(); 493bf215546Sopenharmony_ci assert(lval); 494bf215546Sopenharmony_ci stmt->def(d).setSSA( 495bf215546Sopenharmony_ci new_LValue(func, targ->nativeFile(lval->reg.file))); 496bf215546Sopenharmony_ci stmt->def(d).get()->reg.size = lval->reg.size; 497bf215546Sopenharmony_ci stmt->def(d).get()->reg.data.id = lval->reg.data.id; 498bf215546Sopenharmony_ci stack[lval->id].push(stmt->def(d).get()); 499bf215546Sopenharmony_ci } 500bf215546Sopenharmony_ci } 501bf215546Sopenharmony_ci 502bf215546Sopenharmony_ci // Update sources of PHI ops corresponding to this BB in outgoing BBs. 503bf215546Sopenharmony_ci for (Graph::EdgeIterator ei = bb->cfg.outgoing(); !ei.end(); ei.next()) { 504bf215546Sopenharmony_ci Instruction *phi; 505bf215546Sopenharmony_ci int p = 0; 506bf215546Sopenharmony_ci BasicBlock *sb = BasicBlock::get(ei.getNode()); 507bf215546Sopenharmony_ci 508bf215546Sopenharmony_ci // which predecessor of sb is bb ? 509bf215546Sopenharmony_ci for (Graph::EdgeIterator ei = sb->cfg.incident(); !ei.end(); ei.next()) { 510bf215546Sopenharmony_ci if (ei.getNode() == &bb->cfg) 511bf215546Sopenharmony_ci break; 512bf215546Sopenharmony_ci ++p; 513bf215546Sopenharmony_ci } 514bf215546Sopenharmony_ci assert(p < sb->cfg.incidentCount()); 515bf215546Sopenharmony_ci 516bf215546Sopenharmony_ci for (phi = sb->getPhi(); phi && phi->op == OP_PHI; phi = phi->next) { 517bf215546Sopenharmony_ci lval = getStackTop(phi->getSrc(p)); 518bf215546Sopenharmony_ci if (!lval) 519bf215546Sopenharmony_ci lval = mkUndefined(phi->getSrc(p)); 520bf215546Sopenharmony_ci phi->setSrc(p, lval); 521bf215546Sopenharmony_ci } 522bf215546Sopenharmony_ci } 523bf215546Sopenharmony_ci 524bf215546Sopenharmony_ci // Visit the BBs we dominate. 525bf215546Sopenharmony_ci for (Graph::EdgeIterator ei = bb->dom.outgoing(); !ei.end(); ei.next()) 526bf215546Sopenharmony_ci search(BasicBlock::get(ei.getNode())); 527bf215546Sopenharmony_ci 528bf215546Sopenharmony_ci // Update function outputs to the last definitions of their pre-SSA values. 529bf215546Sopenharmony_ci // I hope they're unique, i.e. that we get PHIs for all of them ... 530bf215546Sopenharmony_ci if (bb == BasicBlock::get(func->cfgExit)) { 531bf215546Sopenharmony_ci for (std::deque<ValueRef>::iterator it = func->outs.begin(); 532bf215546Sopenharmony_ci it != func->outs.end(); ++it) { 533bf215546Sopenharmony_ci lval = it->get()->asLValue(); 534bf215546Sopenharmony_ci if (!lval) 535bf215546Sopenharmony_ci continue; 536bf215546Sopenharmony_ci lval = getStackTop(lval); 537bf215546Sopenharmony_ci if (!lval) 538bf215546Sopenharmony_ci lval = mkUndefined(it->get()); 539bf215546Sopenharmony_ci it->set(lval); 540bf215546Sopenharmony_ci } 541bf215546Sopenharmony_ci } 542bf215546Sopenharmony_ci 543bf215546Sopenharmony_ci // Pop the values we created in this block from the stack because we will 544bf215546Sopenharmony_ci // return to blocks that we do not dominate. 545bf215546Sopenharmony_ci for (Instruction *stmt = bb->getFirst(); stmt; stmt = stmt->next) { 546bf215546Sopenharmony_ci if (stmt->op == OP_NOP) 547bf215546Sopenharmony_ci continue; 548bf215546Sopenharmony_ci for (d = 0; stmt->defExists(d); ++d) 549bf215546Sopenharmony_ci stack[stmt->def(d).preSSA()->id].pop(); 550bf215546Sopenharmony_ci } 551bf215546Sopenharmony_ci} 552bf215546Sopenharmony_ci 553bf215546Sopenharmony_ci} // namespace nv50_ir 554