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
26namespace 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.
32class DominatorTree : public Graph
33{
34public:
35   DominatorTree(Graph *cfg);
36   ~DominatorTree() { }
37
38   bool dominates(BasicBlock *, BasicBlock *);
39
40   void findDominanceFrontiers();
41
42private:
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
65void 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
76DominatorTree::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
97void 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
109void 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
120int DominatorTree::eval(int v)
121{
122   if (ANCESTOR(v) < 0)
123      return v;
124   squash(v);
125   return LABEL(v);
126}
127
128void DominatorTree::link(int v, int w)
129{
130   ANCESTOR(w) = v;
131}
132
133void 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
189void 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))
219void
220Function::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
264void
265Function::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
285class RenamePass
286{
287public:
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
298private:
299   Stack *stack;
300   Function *func;
301   Program *prog;
302};
303
304bool
305Program::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
320bool
321Function::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
404RenamePass::RenamePass(Function *fn) : func(fn), prog(fn->getProgram())
405{
406   stack = new Stack[func->allLValues.getSize()];
407}
408
409RenamePass::~RenamePass()
410{
411   if (stack)
412      delete[] stack;
413}
414
415LValue *
416RenamePass::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
423LValue *
424RenamePass::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
435bool RenamePass::run()
436{
437   if (!stack)
438      return false;
439   search(BasicBlock::get(func->domTree->getRoot()));
440
441   return true;
442}
443
444void 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