Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

ShCtrlGraph.cpp

00001 // Sh: A GPU metaprogramming language.
00002 //
00003 // Copyright (c) 2003 University of Waterloo Computer Graphics Laboratory
00004 // Project administrator: Michael D. McCool
00005 // Authors: Zheng Qin, Stefanus Du Toit, Kevin Moule, Tiberiu S. Popa,
00006 //          Michael D. McCool
00007 // 
00008 // This software is provided 'as-is', without any express or implied
00009 // warranty. In no event will the authors be held liable for any damages
00010 // arising from the use of this software.
00011 // 
00012 // Permission is granted to anyone to use this software for any purpose,
00013 // including commercial applications, and to alter it and redistribute it
00014 // freely, subject to the following restrictions:
00015 // 
00016 // 1. The origin of this software must not be misrepresented; you must
00017 // not claim that you wrote the original software. If you use this
00018 // software in a product, an acknowledgment in the product documentation
00019 // would be appreciated but is not required.
00020 // 
00021 // 2. Altered source versions must be plainly marked as such, and must
00022 // not be misrepresented as being the original software.
00023 // 
00024 // 3. This notice may not be removed or altered from any source
00025 // distribution.
00027 #include "ShCtrlGraph.hpp"
00028 #include <iostream>
00029 #include <cassert>
00030 #include <vector>
00031 #include "ShBasicBlock.hpp"
00032 #include "ShToken.hpp"
00033 #include "ShTokenizer.hpp"
00034 #include "ShUtility.hpp"
00035 #include "ShParser.hpp"
00036 #include "ShDebug.hpp"
00037 
00038 namespace SH {
00039 
00040 ShCtrlGraphNode::ShCtrlGraphNode()
00041   : follower(0), m_marked(false)
00042 {
00043 }
00044 
00045 ShCtrlGraphNode::~ShCtrlGraphNode() {
00046 }
00047 
00048 std::ostream& ShCtrlGraphNode::print(std::ostream& out, int indent) const
00049 {
00050   if (marked()) return out;
00051   mark();
00052   
00053   if (block) block->print(out, indent);
00054   if (follower) {
00055     shPrintIndent(out, indent);
00056     out << "->" << std::endl;
00057     follower->print(out, indent + 2);
00058   }
00059   for (SuccessorList::const_iterator I = successors.begin();
00060        I != successors.end(); ++I) {
00061     shPrintIndent(out, indent);
00062     if (!I->cond.null()) {
00063       out << "[" << I->cond.name() << "]" << std::endl;
00064     }
00065     out << "->" << std::endl;
00066     I->node->print(out, indent + 2);
00067   }
00068   return out;
00069 }
00070 
00071 std::ostream& ShCtrlGraphNode::graphvizDump(std::ostream& out) const
00072 {
00073   if (marked()) return out;
00074   mark();
00075   out << "\"" << this << "\" ";
00076   if (block) {
00077     out << " [label=\"";
00078     block->graphvizDump(out);
00079     out << "\", shape=box]";
00080   } else {
00081     out << " [label=\"\", shape=circle, height=0.25]";
00082   }
00083   out << ";" << std::endl;
00084 
00085   for (SuccessorList::const_iterator I = successors.begin();
00086        I != successors.end(); ++I) {
00087     I->node->graphvizDump(out);
00088     out << "\"" << this << "\" ";
00089     out << "-> ";
00090     out << "\"" << I->node.object() << "\" ";
00091 
00092     out << "[style=dashed, label=\"" << I->cond.name() << "\"]";
00093     out << ";" << std::endl;
00094   }
00095 
00096   if (follower) {
00097     follower->graphvizDump(out);
00098     out << "\"" << this << "\" ";
00099     out << "-> ";
00100     out << "\"" << follower.object() << "\";" << std::endl;
00101   }
00102   
00103   return out;
00104 }
00105 
00106 bool ShCtrlGraphNode::marked() const
00107 {
00108   return m_marked;
00109 }
00110 
00111 void ShCtrlGraphNode::mark() const
00112 {
00113   m_marked = true;
00114 }
00115 
00116 void ShCtrlGraphNode::clearMarked() const
00117 {
00118   if (!marked()) return ;
00119   m_marked = false;
00120 
00121   if (follower) follower->clearMarked();
00122   
00123   for (SuccessorList::const_iterator I = successors.begin();
00124        I != successors.end(); ++I) {
00125     I->node->clearMarked();
00126   }
00127 }
00128 
00129 void ShCtrlGraphNode::append(const ShPointer<ShCtrlGraphNode>& node)
00130 {
00131   if (!node) return;
00132   assert(!follower);
00133   follower = node;
00134 }
00135 
00136 void ShCtrlGraphNode::append(const ShPointer<ShCtrlGraphNode>& node,
00137                              ShVariable cond)
00138 {
00139   if (node) successors.push_back(ShCtrlGraphBranch(node, cond));
00140 }
00141 
00142 ShCtrlGraphNodePtr ShCtrlGraphNode::split(ShBasicBlock::ShStmtList::iterator stmt) 
00143 {
00144   // make a new node to hold the statements after stmt
00145   // and move over the successors/follower info
00146   ShCtrlGraphNode *after = new ShCtrlGraphNode();
00147   after->successors = successors;
00148   after->follower = follower;
00149   successors.clear();
00150   follower = 0;
00151 
00152   // link up the two nodes
00153   after->predecessors.push_back(this);
00154   this->follower = after;
00155 
00156   // make a block for after and split up the statements
00157   after->block = new ShBasicBlock();
00158   after->block->splice(after->block->begin(), block->m_statements, stmt);
00159 
00160   return after;
00161 }
00162 
00163 ShCtrlGraphBranch::ShCtrlGraphBranch(const ShPointer<ShCtrlGraphNode>& node,
00164                                      ShVariable cond)
00165   : node(node), cond(cond)
00166 {
00167 }
00168 
00169 ShCtrlGraph::ShCtrlGraph(ShCtrlGraphNodePtr head, ShCtrlGraphNodePtr tail)
00170   : m_entry(head),
00171     m_exit(tail)
00172 {
00173 }
00174 
00175 ShCtrlGraph::ShCtrlGraph(ShBlockListPtr blocks)
00176   : m_entry(new ShCtrlGraphNode()),
00177     m_exit(new ShCtrlGraphNode())
00178 {
00179   ShCtrlGraphNodePtr head, tail;
00180 
00181   ShParser::parse(head, tail, blocks);
00182 
00183   if(!head && !tail) {
00184     m_entry->append(m_exit);
00185   } else {
00186     SH_DEBUG_ASSERT(head && tail);
00187     m_entry->append(head);
00188     tail->append(m_exit);
00189   }
00190 }
00191 
00192 ShCtrlGraph::~ShCtrlGraph()
00193 {
00194 }
00195 
00196 ShCtrlGraphNodePtr ShCtrlGraph::entry() const
00197 {
00198   return m_entry;
00199 }
00200 
00201 ShCtrlGraphNodePtr ShCtrlGraph::exit() const
00202 {
00203   return m_exit;
00204 }
00205 
00206 ShCtrlGraphNodePtr ShCtrlGraph::prependEntry() {
00207   ShCtrlGraphNodePtr newEntry = new ShCtrlGraphNode();
00208   ShCtrlGraphNodePtr oldEntry = m_entry;
00209   newEntry->append(oldEntry);
00210   newEntry->mark();
00211   
00212   if( oldEntry->block ) {
00213     SH_DEBUG_WARN( "Old entry to control graph did not have an empty block!");
00214   } else {
00215     oldEntry->block = new ShBasicBlock();
00216   }
00217   m_entry = newEntry;
00218   return oldEntry;
00219 }
00220 
00221 ShCtrlGraphNodePtr ShCtrlGraph::appendExit() {
00222   ShCtrlGraphNodePtr newExit = new ShCtrlGraphNode();
00223   ShCtrlGraphNodePtr oldExit = m_exit;
00224   oldExit->append(newExit);
00225   
00226   if( oldExit->block ) {
00227     SH_DEBUG_WARN( "Old exit to control graph did not have an empty block!");
00228   } else {
00229     oldExit->block = new ShBasicBlock();
00230   }
00231   m_exit = newExit;
00232   return oldExit;
00233 }
00234 
00235 std::ostream& ShCtrlGraph::print(std::ostream& out, int indent) const
00236 {
00237   if (m_entry) {
00238     m_entry->clearMarked();
00239     m_entry->print(out, indent);
00240   }
00241   
00242   return out;
00243 }
00244 
00245 std::ostream& ShCtrlGraph::graphvizDump(std::ostream& out) const
00246 {
00247   out << "digraph control {" << std::endl;
00248   
00249   if (m_entry) {
00250     m_entry->clearMarked();
00251     m_entry->graphvizDump(out);
00252   }
00253   
00254   out << "}" << std::endl;
00255   return out;
00256 }
00257 
00258 struct ClearPreds {
00259   void operator()(ShCtrlGraphNodePtr node) {
00260     if (!node) return;
00261     node->predecessors.clear();
00262   }
00263 };
00264 
00265 struct ComputePreds {
00266   void operator()(ShCtrlGraphNode* node) {
00267     if (!node) return;
00268     
00269     for (ShCtrlGraphNode::SuccessorList::iterator I = node->successors.begin();
00270          I != node->successors.end(); ++I) {
00271       if (I->node) I->node->predecessors.push_back(node);
00272     }
00273     if (node->follower) node->follower->predecessors.push_back(node);
00274   }
00275 };
00276 
00277 
00278 void ShCtrlGraph::computePredecessors()
00279 {
00280   ClearPreds clear;
00281   dfs(clear);
00282 
00283   ComputePreds comp;
00284   dfs(comp);
00285 }
00286 
00287 typedef std::map<ShCtrlGraphNodePtr, ShCtrlGraphNodePtr> CtrlGraphCopyMap;
00288 
00289 struct CtrlGraphCopier {
00290   CtrlGraphCopier(CtrlGraphCopyMap& copyMap)
00291     : copyMap(copyMap)
00292   {
00293   }
00294   
00295   void operator()(ShCtrlGraphNodePtr node) {
00296     if (!node) return;
00297     ShCtrlGraphNodePtr newNode = new ShCtrlGraphNode(*node);
00298     copyMap[node] = newNode;
00299   }
00300 
00301   CtrlGraphCopyMap& copyMap;
00302 };
00303 
00304 void ShCtrlGraph::copy(ShCtrlGraphNodePtr& newHead, ShCtrlGraphNodePtr& newTail) const
00305 {
00306   CtrlGraphCopyMap copyMap;
00307   copyMap[0] = 0;
00308   
00309   CtrlGraphCopier copier(copyMap);
00310   SH_DEBUG_ASSERT(m_entry);
00311   SH_DEBUG_ASSERT(m_exit); // catch empty tails
00312   m_entry->clearMarked();
00313   m_entry->dfs(copier);
00314 
00315   // Replace the successors and followers in the new graph with their new equivalents
00316   for (CtrlGraphCopyMap::iterator I = copyMap.begin(); I != copyMap.end(); ++I) {
00317     ShCtrlGraphNodePtr node = I->second; // Get the new node
00318     if (!node) continue;
00319     for (ShCtrlGraphNode::SuccessorList::iterator J = node->successors.begin();
00320          J != node->successors.end(); ++J) {
00321       J->node = copyMap[J->node];
00322     }
00323     node->follower = copyMap[node->follower];
00324     if (node->block) {
00325       ShBasicBlockPtr new_block = new ShBasicBlock(*node->block);
00326       node->block = new_block;
00327     }
00328   }
00329   newHead = copyMap[m_entry];
00330   newTail = copyMap[m_exit];
00331   SH_DEBUG_ASSERT(newHead);
00332   SH_DEBUG_ASSERT(newTail);
00333 
00334   m_entry->clearMarked();
00335 }
00336 
00337 
00338 
00339 }
00340 

Generated on Mon Jan 24 18:36:31 2005 for Sh by  doxygen 1.4.1