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