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

ShOptimizations.cpp

00001 #include "ShOptimizations.hpp" 00002 #include <map> 00003 #include <set> 00004 #include <utility> 00005 #include "ShBitSet.hpp" 00006 #include "ShCtrlGraph.hpp" 00007 #include "ShDebug.hpp" 00008 #include "ShEvaluate.hpp" 00009 #include "ShContext.hpp" 00010 #include "ShSyntax.hpp" 00011 #include <sstream> 00012 #include <fstream> 00013 00014 namespace { 00015 00016 using namespace SH; 00017 00018 // Branch instruction insertion/removal 00019 00020 struct BraInstInserter { 00021 void operator()(ShCtrlGraphNodePtr node) 00022 { 00023 if (!node) return; 00024 00025 for (std::vector<ShCtrlGraphBranch>::const_iterator I = node->successors.begin(); 00026 I != node->successors.end(); ++I) { 00027 if (!node->block) node->block = new ShBasicBlock(); 00028 node->block->addStatement(ShStatement(I->cond, SH_OP_OPTBRA, I->cond)); 00029 } 00030 } 00031 }; 00032 00033 struct BraInstRemover { 00034 void operator()(ShCtrlGraphNodePtr node) 00035 { 00036 if (!node) return; 00037 ShBasicBlockPtr block = node->block; 00038 if (!block) return; 00039 00040 for (ShBasicBlock::ShStmtList::iterator I = block->begin(); I != block->end();) { 00041 if (I->op == SH_OP_OPTBRA) { 00042 I = block->erase(I); 00043 continue; 00044 } 00045 ++I; 00046 } 00047 } 00048 }; 00049 00050 // Straightening 00051 struct Straightener { 00052 Straightener(const ShCtrlGraphPtr& graph, bool& changed) 00053 : graph(graph), changed(changed) 00054 { 00055 } 00056 00057 void operator()(const ShCtrlGraphNodePtr& node) 00058 { 00059 if (!node) return; 00060 if (!node->follower) return; 00061 if (node == graph->entry()) return; 00062 if (node->follower == graph->exit()) return; 00063 if (!node->successors.empty()) return; 00064 if (node->follower->predecessors.size() > 1) return; 00065 00066 if (!node->block) node->block = new ShBasicBlock(); 00067 if (!node->follower->block) node->follower->block = new ShBasicBlock(); 00068 00069 for (ShBasicBlock::ShStmtList::iterator I = node->follower->block->begin(); I != node->follower->block->end(); ++I) { 00070 node->block->addStatement(*I); 00071 } 00072 node->successors = node->follower->successors; 00073 00074 // Update predecessors 00075 00076 for (std::vector<ShCtrlGraphBranch>::iterator I = node->follower->successors.begin(); 00077 I != node->follower->successors.end(); ++I) { 00078 replacePredecessors(I->node, node->follower.object(), node.object()); 00079 } 00080 if (node->follower->follower) replacePredecessors(node->follower->follower, node->follower.object(), node.object()); 00081 00082 node->follower = node->follower->follower; 00083 00084 changed = true; 00085 } 00086 00087 void replacePredecessors(ShCtrlGraphNodePtr node, 00088 ShCtrlGraphNode* old, 00089 ShCtrlGraphNode* replacement) 00090 { 00091 for (ShCtrlGraphNode::ShPredList::iterator I = node->predecessors.begin(); I != node->predecessors.end(); ++I) { 00092 if (*I == old) { 00093 *I = replacement; 00094 break; 00095 } 00096 } 00097 } 00098 00099 ShCtrlGraphPtr graph; 00100 bool& changed; 00101 }; 00102 00103 typedef std::queue<ShStatement*> DeadCodeWorkList; 00104 00105 struct InitLiveCode { 00106 InitLiveCode(DeadCodeWorkList& w) 00107 : w(w) 00108 { 00109 } 00110 00111 void operator()(ShCtrlGraphNodePtr node) { 00112 if (!node) return; 00113 ShBasicBlockPtr block = node->block; 00114 if (!block) return; 00115 00116 for (ShBasicBlock::ShStmtList::iterator I = block->begin(); I != block->end(); ++I) { 00117 if (I->dest.node()->kind() != SH_TEMP 00118 || I->dest.node()->uniform() 00119 || I->op == SH_OP_KIL 00120 /* 00121 || I->op == SH_OP_FETCH // Keep stream fetches, since these 00122 // are like inputs. 00123 */ 00124 || I->op == SH_OP_OPTBRA) { 00125 I->marked = true; 00126 w.push(&(*I)); 00127 continue; 00128 } 00129 I->marked = false; 00130 } 00131 } 00132 00133 DeadCodeWorkList& w; 00134 }; 00135 00136 struct DeadCodeRemover { 00137 DeadCodeRemover(bool& changed) 00138 : changed(changed) 00139 { 00140 } 00141 00142 void operator()(ShCtrlGraphNodePtr node) { 00143 if (!node) return; 00144 ShBasicBlockPtr block = node->block; 00145 if (!block) return; 00146 00147 for (ShBasicBlock::ShStmtList::iterator I = block->begin(); I != block->end();) { 00148 if (!I->marked) { 00149 changed = true; 00150 I = block->erase(I); 00151 continue; 00152 } 00153 ++I; 00154 } 00155 } 00156 00157 bool& changed; 00158 }; 00159 00160 00161 // Copy propagation 00162 00163 struct CopyPropagator { 00164 CopyPropagator(bool& changed) 00165 : changed(changed) 00166 { 00167 } 00168 00169 void operator()(const ShCtrlGraphNodePtr& node) { 00170 if (!node) return; 00171 ShBasicBlockPtr block = node->block; 00172 00173 if (!block) return; 00174 for (ShBasicBlock::ShStmtList::iterator I = block->begin(); I != block->end(); ++I) { 00175 for (int i = 0; i < opInfo[I->op].arity; i++) copyValue(I->src[i]); 00176 removeACP(I->dest); 00177 00178 if (I->op == SH_OP_ASN 00179 && I->dest.node() != I->src[0].node() 00180 && I->dest.node()->kind() == SH_TEMP 00181 && I->dest.swizzle().identity() 00182 && I->src[0].swizzle().identity()) { 00183 m_acp.push_back(std::make_pair(I->dest, I->src[0])); 00184 } 00185 } 00186 m_acp.clear(); 00187 } 00188 00189 void removeACP(const ShVariable& var) 00190 { 00191 for (ACP::iterator I = m_acp.begin(); I != m_acp.end();) { 00192 if (I->first.node() == var.node() || I->second.node() == var.node()) { 00193 I = m_acp.erase(I); 00194 continue; 00195 } 00196 ++I; 00197 } 00198 } 00199 00200 00201 void copyValue(ShVariable& var) 00202 { 00203 for (ACP::const_iterator I = m_acp.begin(); I != m_acp.end(); ++I) { 00204 if (I->first.node() == var.node()) { 00205 changed = true; 00206 var = ShVariable(I->second.node(), var.swizzle(), 00207 var.neg() ^ (I->first.neg() ^ I->second.neg())); 00208 break; 00209 } 00210 } 00211 } 00212 00213 typedef std::list< std::pair<ShVariable, ShVariable> > ACP; 00214 ACP m_acp; 00215 00216 bool& changed; 00217 }; 00218 00219 00221 bool inRHS(const ShVariableNodePtr& node, 00222 const ShStatement& stmt) 00223 { 00224 for (int i = 0; i < opInfo[stmt.op].arity; i++) { 00225 if (stmt.src[i].node() == node) return true; 00226 } 00227 00228 return false; 00229 } 00230 00231 struct ForwardSubst { 00232 ForwardSubst(bool& changed) 00233 : changed(changed) 00234 { 00235 } 00236 00237 void operator()(const ShCtrlGraphNodePtr& node) { 00238 if (!node) return; 00239 ShBasicBlockPtr block = node->block; 00240 if (!block) return; 00241 for (ShBasicBlock::ShStmtList::iterator I = block->begin(); 00242 I != block->end(); ++I) { 00243 substitute(*I); 00244 00245 removeAME(I->dest.node()); 00246 00247 if (!inRHS(I->dest.node(), *I) 00248 && I->dest.node()->kind() == SH_TEMP 00249 && I->dest.swizzle().identity()) { 00250 m_ame.push_back(*I); 00251 } 00252 } 00253 m_ame.clear(); 00254 } 00255 00256 void substitute(ShStatement& stmt) 00257 { 00258 if (stmt.op != SH_OP_ASN) return; 00259 if (stmt.src[0].neg()) return; 00260 if (stmt.src[0].node()->kind() != SH_TEMP) return; 00261 if (!stmt.src[0].swizzle().identity()) return; 00262 00263 for (AME::const_iterator I = m_ame.begin(); I != m_ame.end(); ++I) { 00264 if (I->dest.node() == stmt.src[0].node()) { 00265 ShVariable v = stmt.dest; 00266 stmt = *I; 00267 stmt.dest = v; 00268 changed = true; 00269 break; 00270 } 00271 } 00272 } 00273 00274 void removeAME(const ShVariableNodePtr& node) 00275 { 00276 for (AME::iterator I = m_ame.begin(); I != m_ame.end();) { 00277 if (I->dest.node() == node || inRHS(node, *I)) { 00278 I = m_ame.erase(I); 00279 continue; 00280 } 00281 ++I; 00282 } 00283 } 00284 00285 bool& changed; 00286 typedef std::list<ShStatement> AME; 00287 AME m_ame; 00288 }; 00289 00290 } 00291 00292 namespace SH { 00293 00294 void insert_branch_instructions(ShProgram& p) 00295 { 00296 BraInstInserter r; 00297 p.node()->ctrlGraph->dfs(r); 00298 } 00299 00300 void remove_branch_instructions(ShProgram& p) 00301 { 00302 BraInstRemover r; 00303 p.node()->ctrlGraph->dfs(r); 00304 } 00305 00306 void straighten(ShProgram& p, bool& changed) 00307 { 00308 Straightener s(p.node()->ctrlGraph, changed); 00309 p.node()->ctrlGraph->dfs(s); 00310 } 00311 00312 void remove_dead_code(ShProgram& p, bool& changed) 00313 { 00314 DeadCodeWorkList w; 00315 00316 ShCtrlGraphPtr graph = p.node()->ctrlGraph; 00317 00318 InitLiveCode init(w); 00319 graph->dfs(init); 00320 00321 while (!w.empty()) { 00322 ShStatement* stmt = w.front(); w.pop(); 00323 ValueTracking* vt = stmt->template get_info<ValueTracking>(); 00324 if (!vt) continue; // Should never happen! 00325 00326 for (int i = 0; i < opInfo[stmt->op].arity; i++) { 00327 00328 for (ValueTracking::TupleUseDefChain::iterator C = vt->defs[i].begin(); 00329 C != vt->defs[i].end(); ++C) { 00330 for (ValueTracking::UseDefChain::iterator I = C->begin(); I != C->end(); ++I) { 00331 if (I->stmt->marked) continue; 00332 I->stmt->marked = true; 00333 w.push(I->stmt); 00334 } 00335 } 00336 } 00337 } 00338 00339 DeadCodeRemover r(changed); 00340 graph->dfs(r); 00341 } 00342 00343 void copy_propagate(ShProgram& p, bool& changed) 00344 { 00345 CopyPropagator c(changed); 00346 p.node()->ctrlGraph->dfs(c); 00347 } 00348 00349 void forward_substitute(ShProgram& p, bool& changed) 00350 { 00351 ForwardSubst f(changed); 00352 p.node()->ctrlGraph->dfs(f); 00353 } 00354 00355 void optimize(ShProgram& p, int level) 00356 { 00357 if (level <= 0) return; 00358 00359 #ifdef SH_DEBUG_OPTIMIZER 00360 int pass = 0; 00361 SH_DEBUG_PRINT("Begin optimization for program with target " << p.node()->target()); 00362 #endif 00363 00364 bool changed; 00365 do { 00366 00367 #ifdef SH_DEBUG_OPTIMIZER 00368 SH_DEBUG_PRINT("---Optimizer pass " << pass << " BEGIN---"); 00369 std::ostringstream s; 00370 s << "opt_" << pass; 00371 std::string filename = s.str() + ".dot"; 00372 std::ofstream out(filename.c_str()); 00373 p.node()->ctrlGraph->graphvizDump(out); 00374 out.close(); 00375 std::string cmdline = std::string("dot -Tps -o ") + s.str() + ".ps " + s.str() + ".dot"; 00376 system(cmdline.c_str()); 00377 #endif 00378 00379 changed = false; 00380 00381 if (!ShContext::current()->optimization_disabled("copy propagation")) { 00382 copy_propagate(p, changed); 00383 } 00384 if (!ShContext::current()->optimization_disabled("forward substitution")) { 00385 forward_substitute(p, changed); 00386 } 00387 00388 p.node()->ctrlGraph->computePredecessors(); 00389 00390 if (!ShContext::current()->optimization_disabled("straightening")) { 00391 straighten(p, changed); 00392 } 00393 00394 insert_branch_instructions(p); 00395 00396 if (level >= 2 && 00397 !ShContext::current()->optimization_disabled("propagation")) { 00398 add_value_tracking(p); 00399 propagate_constants(p); 00400 } 00401 00402 if (!ShContext::current()->optimization_disabled("deadcode")) { 00403 add_value_tracking(p); // TODO: Really necessary? 00404 remove_dead_code(p, changed); 00405 } 00406 00407 remove_branch_instructions(p); 00408 00409 #ifdef SH_DEBUG_OPTIMIZER 00410 SH_DEBUG_PRINT("---Optimizer pass " << pass << " END---"); 00411 pass++; 00412 #endif 00413 } while (changed); 00414 } 00415 00416 void optimize(const ShProgramNodePtr& n, int level) 00417 { 00418 ShProgram p(n); 00419 optimize(p, level); 00420 } 00421 00422 void optimize(ShProgram& p) 00423 { 00424 optimize(p, ShContext::current()->optimization()); 00425 } 00426 00427 void optimize(const ShProgramNodePtr& n) 00428 { 00429 ShProgram p(n); 00430 optimize(p); 00431 } 00432 00433 }

Generated on Mon Oct 18 14:17:39 2004 for Sh by doxygen 1.3.7