nv50/ir: add function for splitting a BasicBlock
authorChristoph Bumiller <e0425955@student.tuwien.ac.at>
Wed, 28 Mar 2012 19:30:59 +0000 (21:30 +0200)
committerChristoph Bumiller <e0425955@student.tuwien.ac.at>
Sat, 14 Apr 2012 19:54:00 +0000 (21:54 +0200)
Fixes to initial implementation by Francisco Jerez.

src/gallium/drivers/nv50/codegen/nv50_ir.h
src/gallium/drivers/nv50/codegen/nv50_ir_bb.cpp
src/gallium/drivers/nv50/codegen/nv50_ir_graph.h

index cf7bd3c..04ea5e6 100644 (file)
@@ -882,6 +882,10 @@ public:
 
    BasicBlock *idom() const;
 
+   // NOTE: currently does not rebuild the dominator tree
+   BasicBlock *splitBefore(Instruction *, bool attach = true);
+   BasicBlock *splitAfter(Instruction *, bool attach = true);
+
    DLList& getDF() { return df; }
    DLList::Iterator iterDF() { return df.iterator(); }
 
@@ -914,6 +918,8 @@ private:
 private:
    Function *func;
    Program *program;
+
+   void splitCommon(Instruction *, BasicBlock *, bool attach);
 };
 
 class Function
index c1c8278..e766c62 100644 (file)
@@ -258,6 +258,60 @@ void BasicBlock::permuteAdjacent(Instruction *a, Instruction *b)
       a->next->prev = a;
 }
 
+void
+BasicBlock::splitCommon(Instruction *insn, BasicBlock *bb, bool attach)
+{
+   bb->entry = insn;
+
+   if (insn) {
+      exit = insn->prev;
+      insn->prev = NULL;
+   }
+
+   if (exit)
+      exit->next = NULL;
+   else
+      entry = NULL;
+
+   while (!cfg.outgoing(true).end()) {
+      Graph::Edge *e = cfg.outgoing(true).getEdge();
+      bb->cfg.attach(e->getTarget(), e->getType());
+      this->cfg.detach(e->getTarget());
+   }
+
+   for (; insn; insn = insn->next) {
+      this->numInsns--;
+      bb->numInsns++;
+      insn->bb = bb;
+      bb->exit = insn;
+   }
+   if (attach)
+      this->cfg.attach(&bb->cfg, Graph::Edge::TREE);
+}
+
+BasicBlock *
+BasicBlock::splitBefore(Instruction *insn, bool attach)
+{
+   BasicBlock *bb = new BasicBlock(func);
+   assert(!insn || insn->op != OP_PHI);
+
+   splitCommon(insn, bb, attach);
+   return bb;
+}
+
+BasicBlock *
+BasicBlock::splitAfter(Instruction *insn, bool attach)
+{
+   BasicBlock *bb = new BasicBlock(func);
+   assert(!insn || insn->op != OP_PHI);
+
+   bb->joinAt = joinAt;
+   joinAt = NULL;
+
+   splitCommon(insn ? insn->next : NULL, bb, attach);
+   return bb;
+}
+
 bool
 BasicBlock::dominatedBy(BasicBlock *that)
 {
index 640f518..7f5f039 100644 (file)
@@ -80,10 +80,18 @@ public:
    class EdgeIterator : public Iterator
    {
    public:
-      EdgeIterator() : e(0), t(0), d(0) { }
-      EdgeIterator(Graph::Edge *first, int dir) : e(first), t(first), d(dir) { }
+      EdgeIterator() : e(0), t(0), d(0), rev(false) { }
+      EdgeIterator(Graph::Edge *first, int dir, bool reverse)
+         : d(dir), rev(reverse)
+      {
+         t = e = ((rev && first) ? first->prev[d] : first);
+      }
 
-      virtual void next() { e = (e->next[d] == t) ? 0 : e->next[d]; }
+      virtual void next()
+      {
+         Graph::Edge *n = (rev ? e->prev[d] : e->next[d]);
+         e = (n == t ? NULL : n);
+      }
       virtual bool end() const { return !e; }
       virtual void *get() const { return e; }
 
@@ -96,6 +104,7 @@ public:
       Graph::Edge *e;
       Graph::Edge *t;
       int d;
+      bool rev;
    };
 
    class Node
@@ -108,8 +117,8 @@ public:
       bool detach(Node *);
       void cut();
 
-      inline EdgeIterator outgoing() const;
-      inline EdgeIterator incident() const;
+      inline EdgeIterator outgoing(bool reverse = false) const;
+      inline EdgeIterator incident(bool reverse = false) const;
 
       inline Node *parent() const; // returns NULL if count(incident edges) != 1
 
@@ -204,14 +213,14 @@ void Graph::putIterator(Iterator *iter)
    delete reinterpret_cast<GraphIterator *>(iter);
 }
 
-Graph::EdgeIterator Graph::Node::outgoing() const
+Graph::EdgeIterator Graph::Node::outgoing(bool reverse) const
 {
-   return EdgeIterator(out, 0);
+   return EdgeIterator(out, 0, reverse);
 }
 
-Graph::EdgeIterator Graph::Node::incident() const
+Graph::EdgeIterator Graph::Node::incident(bool reverse) const
 {
-   return EdgeIterator(in, 1);
+   return EdgeIterator(in, 1, reverse);
 }
 
 int Graph::Node::incidentCountFwd() const