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