[Beignet] [PATCH 2/3] Add data structures and functions for CFG structure identification
Yongjia Zhang
zhang_yong_jia at 126.com
Fri May 23 02:19:08 PDT 2014
This patch adds primary control flow analysis data structures and
functions. These can identify structured regions such as If-Then,
If-Else, Self-Loop and While-Loop.
Signed-off-by: Yongjia Zhang <yongjia.zhang at intel.com>
---
backend/src/CMakeLists.txt | 2 +
backend/src/ir/function.cpp | 4 +-
backend/src/ir/function.hpp | 4 +-
backend/src/ir/structural_analysis.cpp | 501 +++++++++++++++++++++++++++++++++
backend/src/ir/structural_analysis.hpp | 279 ++++++++++++++++++
backend/src/llvm/llvm_to_gen.cpp | 14 +
6 files changed, 800 insertions(+), 4 deletions(-)
create mode 100644 backend/src/ir/structural_analysis.cpp
create mode 100644 backend/src/ir/structural_analysis.hpp
diff --git a/backend/src/CMakeLists.txt b/backend/src/CMakeLists.txt
index 2d59644..4a58ff7 100644
--- a/backend/src/CMakeLists.txt
+++ b/backend/src/CMakeLists.txt
@@ -135,6 +135,8 @@ else (GBE_USE_BLOB)
ir/value.hpp
ir/lowering.cpp
ir/lowering.hpp
+ ir/structural_analysis.cpp
+ ir/structural_analysis.hpp
backend/context.cpp
backend/context.hpp
backend/program.cpp
diff --git a/backend/src/ir/function.cpp b/backend/src/ir/function.cpp
index b0df412..83936ad 100644
--- a/backend/src/ir/function.cpp
+++ b/backend/src/ir/function.cpp
@@ -184,12 +184,12 @@ namespace ir {
return &bb == this->blocks[0];
}
- const BasicBlock &Function::getTopBlock(void) const {
+ BasicBlock &Function::getTopBlock(void) const {
GBE_ASSERT(blockNum() > 0 && blocks[0] != NULL);
return *blocks[0];
}
- const BasicBlock &Function::getBottomBlock(void) const {
+ BasicBlock &Function::getBottomBlock(void) const {
const uint32_t n = blockNum();
GBE_ASSERT(n > 0 && blocks[n-1] != NULL);
return *blocks[n-1];
diff --git a/backend/src/ir/function.hpp b/backend/src/ir/function.hpp
index 8831d47..2c60f4d 100644
--- a/backend/src/ir/function.hpp
+++ b/backend/src/ir/function.hpp
@@ -260,9 +260,9 @@ namespace ir {
/*! Says if this is the top basic block (entry point) */
bool isEntryBlock(const BasicBlock &bb) const;
/*! Get function the entry point block */
- const BasicBlock &getTopBlock(void) const;
+ BasicBlock &getTopBlock(void) const;
/*! Get the last block */
- const BasicBlock &getBottomBlock(void) const;
+ BasicBlock &getBottomBlock(void) const;
/*! Get the last block */
BasicBlock &getBottomBlock(void);
/*! Get block from its label */
diff --git a/backend/src/ir/structural_analysis.cpp b/backend/src/ir/structural_analysis.cpp
new file mode 100644
index 0000000..fad77b3
--- /dev/null
+++ b/backend/src/ir/structural_analysis.cpp
@@ -0,0 +1,501 @@
+#include "structural_analysis.hpp"
+
+namespace analysis
+{
+
+ ControlTree::~ControlTree()
+ {
+ NodeVector::iterator iter = nodes.begin();
+ NodeVector::iterator iter_end = nodes.end();
+ while(iter != iter_end)
+ {
+ delete *iter;
+ iter++;
+ }
+ }
+
+
+ Node* ControlTree::insertNode(Node *p_node)
+ {
+ nodes.push_back(p_node);
+ return p_node;
+ }
+
+
+ bool ControlTree::checkForBarrier(const ir::BasicBlock* bb)
+ {
+ ir::BasicBlock::const_iterator iter = bb->begin();
+ ir::BasicBlock::const_iterator iter_end = bb->end();
+ while(iter != iter_end)
+ {
+ if((*iter).getOpcode() == ir::OP_SYNC)
+ return true;
+ iter++;
+ }
+
+ return false;
+ }
+
+
+ void ControlTree::initializeNodes()
+ {
+ ir::BasicBlock& tmp_bb = fn->getTopBlock();
+ ir::BasicBlock* p_tmp_bb = &tmp_bb;
+ Node* p = NULL;
+
+ if(NULL != p_tmp_bb)
+ {
+ Node *p_tmp_node = new BasicBlockNode(p_tmp_bb);
+ if(checkForBarrier(p_tmp_bb))
+ p_tmp_node->hasBarrier() = true;
+ nodes.push_back(p_tmp_node);
+ bbmap[p_tmp_bb] = p_tmp_node;
+ p_tmp_bb = p_tmp_bb->getNextBlock();
+ p = p_tmp_node;
+ }
+
+ while(p_tmp_bb != NULL)
+ {
+ Node *p_tmp_node = new BasicBlockNode(p_tmp_bb);
+ if(checkForBarrier(p_tmp_bb))
+ p_tmp_node->hasBarrier() = true;
+ p->fallthrough() = p_tmp_node;
+ p = p_tmp_node;
+ nodes.push_back(p_tmp_node);
+ bbmap[p_tmp_bb] = p_tmp_node;
+ p_tmp_bb = p_tmp_bb->getNextBlock();
+ }
+
+ if(NULL != p)
+ p->fallthrough() = NULL;
+
+ p_tmp_bb = &tmp_bb;
+
+ this->nodes_entry = bbmap[p_tmp_bb];
+
+ while(p_tmp_bb != NULL)
+ {
+ ir::BlockSet::const_iterator iter_begin = p_tmp_bb->getPredecessorSet().begin();
+ ir::BlockSet::const_iterator iter_end = p_tmp_bb->getPredecessorSet().end();
+ while(iter_begin != iter_end)
+ {
+ bbmap[p_tmp_bb]->preds().insert(bbmap[*iter_begin]);
+ iter_begin++;
+ }
+
+ iter_begin = p_tmp_bb->getSuccessorSet().begin();
+ iter_end = p_tmp_bb->getSuccessorSet().end();
+ while(iter_begin != iter_end)
+ {
+ bbmap[p_tmp_bb]->succs().insert(bbmap[*iter_begin]);
+ iter_begin++;
+ }
+
+ p_tmp_bb = p_tmp_bb->getNextBlock();
+ }
+ }
+
+
+ void ControlTree::DFSPostOrder(Node *start)
+ {
+ visited.insert(start);
+ NodeSet::iterator y;
+ NodeSet::iterator iter_begin = start->succs().begin();
+ NodeSet::iterator iter_end = start->succs().end();
+ for(y = iter_begin; y != iter_end; ++y )
+ {
+ if(visited.find(*y) != visited.end())
+ continue;
+ DFSPostOrder(*y);
+ }
+ post_order.push_back(start);
+ }
+
+
+ bool ControlTree::isCyclic(Node* node)
+ {
+ if(node->type() == NaturalLoop ||
+ node->type() == WhileLoop ||
+ node->type() == SelfLoop)
+ return true;
+
+ return false;
+ }
+
+
+ bool ControlTree::isBackedge(const Node* head, const Node* tail)
+ {
+ const Node* match[] = {head, tail};
+ NodeList::iterator n = find_first_of(post_order.begin(), post_order.end(), match, match + 2);
+
+ if(*n == head)
+ return true;
+ if(*n == tail)
+ return false;
+
+ return false;
+ }
+
+
+ bool ControlTree::pathBack(Node* m, Node* n)
+ {
+ for(NodeSet::const_iterator iter = n->preds().begin(); iter!= n->preds().end(); iter++)
+ {
+ if(isBackedge(*iter, n))
+ {
+ visited.clear();
+ if(path(m, *iter, n))
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /* totally textbook */
+ Node* ControlTree::acyclicRegionType(Node* node, NodeSet& nset)
+ {
+ nset.clear();
+ Node *n;
+ bool p, s;
+ NodeList nodes;
+
+ n = node;
+ p = true;
+ s = (n->succs().size()==1);
+
+ while(p && s)
+ {
+ if(nset.insert(n).second)
+ nodes.push_back(n);
+ n = *(n->succs().begin());
+ p = (n->preds().size() == 1);
+ s = (n->succs().size() == 1);
+ }
+
+ if(p)
+ {
+ if(nset.insert(n).second)
+ nodes.push_back(n);
+ }
+
+ n = node;
+ p = (n->preds().size() == 1);
+ s = true;
+
+ while(p && s)
+ {
+ if(nset.insert(n).second)
+ nodes.push_front(n);
+ n = *(n->preds().begin());
+ p = (n->preds().size() == 1);
+ s = (n->succs().size() == 1);
+ }
+
+ if(s)
+ {
+ if(nset.insert(n).second)
+ nodes.push_front(n);
+ }
+
+ node = n;
+
+ if(nodes.size() >=2 )
+ {
+ Node* p = new BlockNode(nodes);
+ return insertNode(p);
+ }
+
+ else if(node->succs().size() == 2)
+ {
+ Node *m;
+ m = *(node->succs().begin());
+ n = *(++(node->succs().begin()));
+
+ /* check for if node then n */
+ if(n->succs().size() == 1 &&
+ n->preds().size() == 1 &&
+ *(n->succs().begin()) == m &&
+ !n->hasBarrier())
+ {
+ nset.clear();
+ nset.insert(node);
+ nset.insert(n);
+
+ Node* p = new IfThenNode(node, n);
+ return insertNode(p);
+ }
+
+ /* check for if node then m */
+ if(m->succs().size() == 1 &&
+ m->preds().size() == 1 &&
+ *(m->succs().begin()) == n &&
+ !m->hasBarrier())
+ {
+ nset.clear();
+ nset.insert(node);
+ nset.insert(m);
+
+ Node* p = new IfThenNode(node, m);
+ return insertNode(p);
+ }
+
+ /* check for if node then n else m */
+ if(m->succs().size() == 1 && n->succs().size() == 1 &&
+ m->preds().size() == 1 && n->preds().size() == 1 &&
+ *(m->succs().begin()) == *(n->succs().begin()) &&
+ node->fallthrough() == n && !m->hasBarrier() && !n->hasBarrier())
+ {
+ nset.clear();
+ nset.insert(node);
+ nset.insert(n);
+ nset.insert(m);
+
+ Node* p = new IfElseNode(node, n, m);
+ return insertNode(p);
+ }
+
+ /* check for if node then m else n */
+ if(m->succs().size() == 1 && n->succs().size() == 1 &&
+ m->preds().size() == 1 && n->preds().size() == 1 &&
+ *(m->succs().begin()) == *(n->succs().begin()) &&
+ node->fallthrough() == m && !m->hasBarrier() && !n->hasBarrier())
+ {
+ nset.clear();
+ nset.insert(node);
+ nset.insert(m);
+ nset.insert(n);
+
+ Node* p = new IfElseNode(node, m, n);
+ return insertNode(p);
+ }
+ }
+
+ return NULL;
+ }
+
+
+ bool ControlTree::path(Node *from, Node *to, Node *notthrough)
+ {
+
+ if(from == notthrough || visited.find(from) != visited.end())
+ return false;
+
+ if(from == to)
+ return true;
+
+ visited.insert(from);
+
+ for(NodeSet::const_iterator s = from->succs().begin(); s != from->succs().end(); s++)
+ {
+ if(path(*s, to, notthrough))
+ return true;
+ }
+
+ return false;
+ }
+
+
+ Node * ControlTree::cyclicRegionType(Node *node, NodeList &nset)
+ {
+ /* check for self-loop */
+ if(nset.size() == 1)
+ {
+ if(node->succs().find(node) != node->succs().end())
+ {
+ Node* p = new SelfLoopNode(node);
+ return insertNode(p);
+ }
+ else
+ return NULL;
+ }
+
+ /* check for improper region */
+ for(NodeList::const_iterator m = nset.begin(); m != nset.end(); m++)
+ {
+ visited.clear();
+ if(!path(node, *m))
+ return NULL;
+ }
+
+ /* check for while loop */
+ NodeList::iterator m;
+ for(m = nset.begin(); m != nset.end(); ++m)
+ {
+ if(*m == node)
+ continue;
+ if(node->succs().size() == 2 && (*m)->succs().size() == 1 &&
+ node->preds().size() == 2 && (*m)->preds().size() == 1)
+ {
+ Node* p = new WhileLoopNode(node, *m);
+ return insertNode(p);
+ }
+ }
+
+ /* TODO add code here to identify natural loop */
+ return NULL;
+ }
+
+
+ void ControlTree::reduce(Node* node, NodeSet nodeSet)
+ {
+ NodeSet::iterator n;
+ for(n = nodeSet.begin(); n != nodeSet.end(); n++)
+ {
+ NodeSet::iterator p;
+ for(p = (*n)->preds().begin(); p != (*n)->preds().end(); p++)
+ {
+ if(nodeSet.find(*p) != nodeSet.end())
+ continue;
+
+ (*p)->succs().erase(*n);
+
+ (*p)->succs().insert(node);
+ node->preds().insert(*p);
+
+ if((*p)->fallthrough() == *n)
+ (*p)->fallthrough() = node;
+ }
+
+
+ NodeSet::iterator s;
+ for(s = (*n)->succs().begin(); s != (*n)->succs().end(); s++)
+ {
+ if(nodeSet.find(*s) != nodeSet.end())
+ continue;
+
+ (*s)->preds().erase(*n);
+
+ (*s)->preds().insert(node);
+ node->succs().insert(*s);
+
+ if((*n)->fallthrough() == *s)
+ node->fallthrough() = *s;
+ }
+ }
+
+ if(!isCyclic(node))
+ {
+ for(n = nodeSet.begin(); n != nodeSet.end(); n++)
+ {
+ bool shouldbreak = false;
+ NodeSet::iterator p;
+ for(p = (*n)->preds().begin(); p != (*n)->preds().end(); p++)
+ {
+ if(nodeSet.find(*p) == nodeSet.end())
+ continue;
+
+ if(isBackedge(*p, *n))
+ {
+ node->preds().insert(node);
+ node->succs().insert(node);
+
+ shouldbreak = true;
+ break;
+ }
+ }
+
+ if(shouldbreak)
+ break;
+ }
+ }
+
+ compact(node, nodeSet);
+ }
+
+
+ void ControlTree::compact(Node* node, NodeSet nodeSet)
+ {
+ NodeList::iterator n, pos;
+ for(n = post_order.begin(); n!= post_order.end() && !nodeSet.empty();)
+ {
+ if(!nodeSet.erase(*n))
+ {
+ n++;
+ continue;
+ }
+
+ n = post_order.erase(n);
+ pos = n;
+ }
+
+ post_ctr = post_order.insert(pos, node);
+ }
+
+
+ void ControlTree::structuralAnalysis(Node *entry)
+ {
+ Node* n;
+ NodeSet nset;
+ NodeList reachUnder;
+ bool changed;
+ do
+ {
+ changed = false;
+ post_order.clear();
+ visited.clear();
+
+ DFSPostOrder(entry);
+ post_ctr = post_order.begin();
+
+ while(post_order.size() > 1 && post_ctr != post_order.end())
+ {
+ n = *post_ctr;
+ Node* region = acyclicRegionType(n, nset);
+
+ if( NULL != region)
+ {
+ changed = true;
+
+ reduce(region, nset);
+
+ if(nset.find(entry) != nset.end())
+ entry = region;
+ }
+ else
+ {
+ reachUnder.clear();
+ nset.clear();
+ for(NodeList::const_iterator m = post_order.begin(); m != post_order.end(); m++)
+ {
+ if(*m != n && pathBack(*m, n))
+ {
+ reachUnder.push_front(*m);
+ nset.insert(*m);
+ }
+ }
+
+ reachUnder.push_front(n);
+ nset.insert(n);
+ region = cyclicRegionType(n, reachUnder);
+
+ if(NULL != region)
+ {
+ reduce(region, nset);
+ changed = true;
+
+ if(nset.find(entry) != nset.end())
+ entry = region;
+ }
+ else
+ {
+ post_ctr++;
+ }
+ }
+ }
+
+ if(!changed)
+ {
+ break;
+ }
+
+ } while(post_order.size()>1);
+
+ }
+
+ void ControlTree::analyze()
+ {
+ initializeNodes();
+ structuralAnalysis(nodes_entry);
+ }
+}
diff --git a/backend/src/ir/structural_analysis.hpp b/backend/src/ir/structural_analysis.hpp
new file mode 100644
index 0000000..c23d0d5
--- /dev/null
+++ b/backend/src/ir/structural_analysis.hpp
@@ -0,0 +1,279 @@
+#ifndef __STRUCTURAL_ANALYSIS_HPP__
+#define __STRUCTURAL_ANALYSIS_HPP__
+
+#include "ir/unit.hpp"
+#include "ir/function.hpp"
+#include "ir/instruction.hpp"
+
+#include <iostream>
+#include <unordered_set>
+#include <unordered_map>
+#include <vector>
+#include <map>
+#include <list>
+#include <algorithm>
+
+namespace analysis
+{
+ using namespace std;
+ using namespace gbe;
+
+ enum RegionType
+ {
+ BasicBlock = 0,
+ Block,
+ IfThen,
+ IfElse,
+ SelfLoop,
+ WhileLoop,
+ NaturalLoop
+ } ;
+
+ /* control tree virtual node */
+ class Node;
+
+ typedef unordered_set<Node *> NodeSet;
+ typedef list<Node *> NodeList;
+ typedef std::vector<Node *> NodeVector;
+
+ /* control tree virtual node */
+ class Node
+ {
+ public:
+ Node(RegionType rtype, const NodeList& children): has_barrier(false)
+ {
+ this->rtype = rtype;
+ this->children = children;
+ }
+ virtual ~Node() {}
+ NodeSet& preds() { return pred; }
+ NodeSet& succs() { return succ; }
+ Node*& fallthrough() { return fall_through; }
+ bool& hasBarrier() { return has_barrier; }
+ RegionType type() { return rtype; }
+ virtual ir::BasicBlock* getEntry() { return NULL; };
+ virtual ir::BasicBlock* getExit() { return NULL; };
+
+ public:
+ RegionType rtype;
+ NodeSet pred;
+ NodeSet succ;
+ NodeList children;
+ Node* fall_through;
+ bool has_barrier;
+ };
+
+ /* represents basic block */
+ class BasicBlockNode : public Node
+ {
+ public:
+ BasicBlockNode(ir::BasicBlock *p_bb) : Node(BasicBlock, NodeList()) { this->p_bb = p_bb; }
+ virtual ~BasicBlockNode() {}
+ ir::BasicBlock* getBasicBlock() { return p_bb; }
+ virtual ir::BasicBlock* getEntry() { return p_bb; }
+ virtual ir::BasicBlock* getExit() { return p_bb; }
+
+ private:
+ ir::BasicBlock *p_bb;
+ };
+
+ /* a sequence of nodes */
+ class BlockNode : public Node
+ {
+ public:
+ BlockNode(NodeList& children) : Node(Block, children) {}
+ virtual ~BlockNode(){}
+ virtual ir::BasicBlock *getEntry()
+ {
+ NodeList::const_iterator it = children.begin();
+ while((*it)->type() != BasicBlock)
+ it = (*it)->children.begin();
+ return (*it)->getEntry();
+ }
+ virtual ir::BasicBlock *getExit()
+ {
+ NodeList::const_iterator it = children.end();
+ it--;
+ while((*it)->type() != BasicBlock)
+ {
+ it = (*it)->children.end();
+ it--;
+ }
+ return (*it)->getExit();
+ }
+ };
+
+ /* If-Then structure node */
+ class IfThenNode : public Node
+ {
+ public:
+ IfThenNode(Node* cond, Node* ifTrue) : Node(IfThen, BuildChildren(cond, ifTrue)) {}
+ virtual ~IfThenNode() {}
+ virtual ir::BasicBlock* getEntry()
+ {
+ NodeList::const_iterator it = children.begin();
+ while((*it)->type() != BasicBlock)
+ it = (*it)->children.begin();
+ return (*it)->getEntry();
+ }
+ virtual ir::BasicBlock* getExit()
+ {
+ NodeList::const_iterator it = children.end();
+ it--;
+ while((*it)->type() != BasicBlock)
+ {
+ it = (*it)->children.end();
+ it--;
+ }
+ return (*it)->getExit();
+ }
+
+ private:
+ const NodeList BuildChildren(Node* cond, Node* ifTrue)
+ {
+ NodeList children;
+ children.push_back(cond);
+ children.push_back(ifTrue);
+ return children;
+ }
+ };
+
+ /* If-Else structure node */
+ class IfElseNode : public Node
+ {
+ public:
+ IfElseNode(Node* cond, Node* ifTrue, Node* ifFalse) : Node(IfElse, BuildChildren(cond, ifTrue, ifFalse)) {}
+ virtual ~IfElseNode() {}
+ virtual ir::BasicBlock* getEntry()
+ {
+ NodeList::const_iterator it = children.begin();
+ while((*it)->type() != BasicBlock)
+ it = (*it)->children.begin();
+ return (*it)->getEntry();
+ }
+ virtual ir::BasicBlock* getExit()
+ {
+ NodeList::const_iterator it = children.begin();
+ while((*it)->type() != BasicBlock)
+ {
+ it = (*it)->children.end();
+ it--;
+ }
+ return (*it)->getExit();
+ }
+
+ private:
+ const NodeList BuildChildren(Node* cond, Node* ifTrue, Node* ifFalse)
+ {
+ NodeList children;
+ children.push_back(cond);
+ children.push_back(ifTrue);
+ children.push_back(ifFalse);
+ return children;
+ }
+ };
+
+ /* Self loop structure node */
+ class SelfLoopNode : public Node
+ {
+ public:
+ SelfLoopNode(Node* node) : Node(SelfLoop, BuildChildren(node)) {}
+ virtual ~SelfLoopNode() {}
+ virtual ir::BasicBlock* getEntry()
+ {
+ return (*(children.begin()))->getEntry();
+ }
+ virtual ir::BasicBlock* getExit()
+ {
+ return (*(children.begin()))->getExit();
+ }
+
+ private:
+ const NodeList BuildChildren(Node *node)
+ {
+ NodeList children;
+ children.push_back(node);
+ return children;
+ }
+ };
+
+ /* While loop structure node */
+ class WhileLoopNode : public Node
+ {
+ public:
+ WhileLoopNode(Node* cond, Node* execute) : Node(WhileLoop, BuildChildren(cond, execute)) {}
+ virtual ~WhileLoopNode() {}
+ virtual ir::BasicBlock* getEntry()
+ {
+ return (*(children.begin()))->getEntry();
+ }
+ virtual ir::BasicBlock* getExit()
+ {
+ return (*(children.begin()))->getExit();
+ }
+
+ private:
+ const NodeList BuildChildren(Node* cond, Node* execute)
+ {
+ NodeList children;
+ children.push_back(cond);
+ children.push_back(execute);
+ return children;
+ }
+
+ };
+
+ /* Natural loop structure node */
+ class NaturalLoopNode : public Node
+ {
+ public:
+ NaturalLoopNode(const NodeList& children): Node(NaturalLoop, children){}
+ virtual ~NaturalLoopNode() {}
+ virtual ir::BasicBlock* getEntry()
+ {
+ //TODO implement it
+ return NULL;
+ }
+ virtual ir::BasicBlock* getExit()
+ {
+ //TODO implement it
+ return NULL;
+ }
+ };
+
+ /* computes the control tree, and do the structure transform during the computation */
+ class ControlTree
+ {
+ public:
+ void analyze();
+
+ ControlTree(ir::Function* fn) { this->fn = fn; }
+ ~ControlTree();
+
+ private:
+ void initializeNodes();
+ Node* insertNode(Node *);
+ void structuralAnalysis(Node * entry);
+ void DFSPostOrder(Node *start);
+ bool path(Node *, Node *, Node *notthrough = NULL);
+ void reduce(Node* node, NodeSet nodeSet);
+ void compact(Node* node, NodeSet nodeSet);
+ Node* getNodesEntry() const { return nodes_entry;}
+ Node* acyclicRegionType(Node*, NodeSet&);
+ Node* cyclicRegionType(Node*, NodeList&);
+ bool isCyclic(Node*);
+ bool isBackedge(const Node*, const Node*);
+ bool pathBack(Node*, Node*);
+ bool checkForBarrier(const ir::BasicBlock*);
+
+ private:
+ NodeVector nodes;
+ Node* nodes_entry;
+ unordered_map<ir::BasicBlock *, Node *> bbmap;
+ NodeList post_order;
+ NodeSet visited;
+ NodeList::iterator post_ctr;
+ ir::Function *fn;
+ };
+}
+#endif
diff --git a/backend/src/llvm/llvm_to_gen.cpp b/backend/src/llvm/llvm_to_gen.cpp
index 37a5b2b..4e27935 100644
--- a/backend/src/llvm/llvm_to_gen.cpp
+++ b/backend/src/llvm/llvm_to_gen.cpp
@@ -60,6 +60,8 @@
#include "llvm/llvm_to_gen.hpp"
#include "sys/cvar.hpp"
#include "sys/platform.hpp"
+#include "ir/unit.hpp"
+#include "ir/structural_analysis.hpp"
#include <sys/types.h>
#include <sys/stat.h>
@@ -223,6 +225,18 @@ namespace gbe
#endif
passes.run(mod);
+#ifdef TRANSFORM_UNSTRUCTURE
+ const ir::Unit::FunctionSet& fs = unit.getFunctionSet();
+ ir::Unit::FunctionSet::const_iterator iter = fs.begin();
+ while(iter != fs.end())
+ {
+ analysis::ControlTree *ct = new analysis::ControlTree(iter->second);
+ ct->analyze();
+ delete ct;
+ iter++;
+ }
+#endif
+
return true;
}
} /* namespace gbe */
--
1.8.3.2
More information about the Beignet
mailing list