C-Breeze
C Compiler Infrastructure

[ Project home page]
Main Page   Modules   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages  

liveness.cc

Go to the documentation of this file.
00001 // $Id: liveness.cc,v 1.13 2003/08/08 15:16:29 toktb Exp $
00002 // ----------------------------------------------------------------------
00003 //
00004 //  C-Breeze
00005 //  C Compiler Framework
00006 // 
00007 //  Copyright (c) 2003 University of Texas at Austin
00008 // 
00009 //  Samuel Z. Guyer
00010 //  Adam Brown
00011 //  Teck Bok Tok
00012 //  Paul Arthur Navratil
00013 //  Calvin Lin
00014 // 
00015 //  Permission is hereby granted, free of charge, to any person
00016 //  obtaining a copy of this software and associated documentation
00017 //  files (the "Software"), to deal in the Software without
00018 //  restriction, including without limitation the rights to use, copy,
00019 //  modify, merge, publish, distribute, sublicense, and/or sell copies
00020 //  of the Software, and to permit persons to whom the Software is
00021 //  furnished to do so, subject to the following conditions:
00022 //  
00023 //  The above copyright notice and this permission notice shall be
00024 //  included in all copies or substantial portions of the Software.
00025 //  
00026 //  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
00027 //  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00028 //  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
00029 //  NONINFRINGEMENT.  IN NO EVENT SHALL THE UNIVERSITY OF TEXAS AT
00030 //  AUSTIN BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
00031 //  IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
00032 //  OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
00033 //  THE SOFTWARE.
00034 //
00035 //  We acknowledge the C-to-C Translator from MIT Laboratory for
00036 //  Computer Science for inspiring parts of the C-Breeze design.
00037 //
00038 // ----------------------------------------------------------------------
00039 
00040 #include "c_breeze.h"
00041 #include "liveness.h"
00042 
00043 livenessAnalyzer::livenessAnalyzer()
00044   : analysisProblem(Backward),
00045     _live_stmts(),
00046     _live_stmtlocations(),
00047     _live_mergepoints(),
00048     _defs(),
00049     _change(false),
00050     _change_stack(),
00051     _visited_procedures()
00052 {}
00053 
00054 void livenessAnalyzer::clear()
00055 {
00056   _live_stmts.clear();
00057   _live_stmtlocations.clear();
00058   _live_mergepoints.clear();
00059   _defs.clear();
00060   _change = false;
00061   _change_stack.clear();
00062 }
00063 
00064 bool livenessAnalyzer::isLive(stmtNode * stmt)
00065 {
00066   stmt_liveness_set_p p = _live_stmts.find(stmt);
00067   return (p != _live_stmts.end());
00068 }
00069 
00070 void livenessAnalyzer::collectDefs(pointerValue & pointer)
00071 {
00072   for (memoryblock_set_p p = pointer.blocks.begin();
00073        p != pointer.blocks.end();
00074        ++p)
00075     {
00076       memoryBlock * block = *p;
00077       if ( ! block->write_protected()) {
00078         memoryDef * def = block->current_def();
00079         _defs.insert(def);
00080       }
00081     }
00082 }
00083 
00084 void livenessAnalyzer::addDef(memoryDef * def)
00085 {
00086   _defs.insert(def);
00087 }
00088 
00089 bool livenessAnalyzer::determineLiveness()
00090 {
00091   if (pointerOptions::Verbose_liveness)
00092     cout << "  + Determine liveness..." << endl;
00093 
00094   // -- For all defs at this statement...
00095 
00096   for (memorydef_set_p p = _defs.begin();
00097        p != _defs.end();
00098        ++p)
00099     {
00100       memoryDef * def = *p;
00101       memoryBlock * owner = def->owner();
00102 
00103       if (pointerOptions::Verbose_liveness)
00104         cout << "   - Def of " << owner->name() << " at " << * (def->where()) << endl;
00105 
00106       // -- For all uses of this def...
00107 
00108       memoryuse_list uses;
00109       owner->def_uses(def, uses);
00110 
00111       for (memoryuse_list_p q = uses.begin();
00112            q != uses.end();
00113            ++q)
00114         {
00115           memoryUse * use = *q;
00116 
00117           // -- If any one of them comes from a live statement...
00118 
00119           if (isLive(use, owner)) {
00120 
00121             if (pointerOptions::Verbose_liveness) {
00122               cout << "      + Use at " << * (use->where()) << " is live." << endl;
00123               cout << "  => Live" << endl;
00124             }
00125 
00126             // -- Then this statement is live.
00127 
00128             return true;
00129           }
00130 
00131           if (pointerOptions::Verbose_liveness)
00132             cout << "      + Use at " << * (use->where()) << " is dead." << endl;
00133         }
00134     }
00135 
00136   // -- Fall through, the statement is dead
00137 
00138   if (pointerOptions::Verbose_liveness)
00139     cout << "  => Dead" << endl;
00140 
00141   return false;
00142 }
00143 
00144 bool livenessAnalyzer::isLive(memoryUse * use, memoryBlock * owner)
00145 {
00146   Location * where = use->where();
00147   bool is_live = true;
00148 
00149   switch (where->kind()) {
00150 
00151   case Location::Procedure:
00152     {
00153       // -- Procedure locations are always live
00154 
00155       is_live = true;
00156     }
00157     break;
00158 
00159   case Location::BasicBlock:
00160     {
00161       // -- Basic block locations represent merge points
00162 
00163       basicblockLocation * bb_loc = (basicblockLocation *) where;
00164       mergepoint_pair merge_point(bb_loc, owner);
00165 
00166       mergepoint_liveness_set_p p = _live_mergepoints.find(merge_point);
00167       is_live = (p != _live_mergepoints.end());
00168     }
00169     break;
00170 
00171   case Location::Statement:
00172     {
00173       // -- Statement locations are regular computations
00174 
00175       stmtLocation * stmt_loc = (stmtLocation *) where;
00176 
00177       stmtlocation_liveness_set_p p = _live_stmtlocations.find(stmt_loc);
00178       is_live = (p != _live_stmtlocations.end());
00179     }
00180     break;
00181   }
00182 
00183   /*
00184   cout << "isLive(" << owner->name() << ", " << * (use->where()) << ") = ";
00185   if (is_live)
00186     cout << "true" << endl;
00187   else
00188     cout << "false" << endl;
00189   */
00190 
00191   return is_live;
00192 }
00193 
00194 void livenessAnalyzer::setLive(Location * where, memoryBlock * block)
00195 {
00196   pair< mergepoint_liveness_set_p, bool > result = _live_mergepoints.insert(mergepoint_pair(where, block));
00197 
00198   // -- Note any changes in liveness status
00199 
00200   if (result.second)
00201     _change = true;
00202 }
00203 
00204 
00205 void livenessAnalyzer::setLive(stmtLocation * stmt_loc)
00206 {
00207   pair< stmtlocation_liveness_set_p, bool > result = _live_stmtlocations.insert(stmt_loc);
00208 
00209   // -- Note any changes in liveness status
00210 
00211   if (result.second) {
00212     _change = true;
00213 
00214     if (pointerOptions::Verbose_liveness)
00215       cout << "  + Live statement at " << * stmt_loc << endl;
00216   }
00217 
00218   // -- Also, record context insensitive
00219 
00220   _live_stmts.insert(stmt_loc->stmt());
00221 }
00222 
00223 void livenessAnalyzer::at_index(stmtLocation * current,
00224                                 operandNode * operand,
00225                                 pointerValue & left,
00226                                 pointerValue & right,
00227                                 pointerValue & result)
00228 {
00229   setLive(current);
00230 }
00231 
00232 // -- Procedure calls
00233 
00234 void livenessAnalyzer::at_call(stmtLocation * current, operandNode * call,
00235                                pointerValue & call_target,
00236                                procNode * callee,
00237                                pointervalue_list & arguments,
00238                                pointerValue & return_val)
00239 {
00240   // -- Special case: procedure calls are always live
00241 
00242   setLive(current);
00243 }
00244 
00245 // -- Assignments
00246 
00247 void livenessAnalyzer::at_assignment(stmtLocation * current,
00248                                      pointerValue & left,
00249                                      pointerValue & right,
00250                                      pointerValue & result,
00251                                      memoryblock_set & changes)
00252 {
00253   collectDefs(left);
00254 }
00255 
00256 // -- Statement types
00257 
00258 void livenessAnalyzer::at_return(stmtLocation * stmt,
00259                                  returnNode * ret,
00260                                  pointerValue & result,
00261                                  pointerValue & return_val)
00262 {
00263   // -- Return statements are always live
00264 
00265   setLive(stmt);
00266 }
00267 
00268 void livenessAnalyzer::at_threeAddr(stmtLocation * stmt,
00269                                     threeAddrNode *threeaddr,
00270                                     pointerValue & result)
00271 {
00272   // -- Regular expression statement: test the defs to see if the uses that
00273   // they reach are live.
00274 
00275   if (determineLiveness())
00276     setLive(stmt);
00277 }
00278 
00279 void livenessAnalyzer::at_conditiongoto(stmtLocation * stmt,
00280                                         conditiongotoNode * c,
00281                                         pointerValue & result)
00282 {
00283   // -- If statements are always live
00284 
00285   setLive(stmt);
00286 }
00287 
00288 // -- Memory allocation and deallocation
00289 
00290 void livenessAnalyzer::at_allocation(stmtLocation * stmt,
00291                                      pointervalue_list & arguments,
00292                                      memoryBlock * block,
00293                                      memoryblock_set & changes)
00294 {
00295   setLive(stmt);
00296 }
00297 
00298 void livenessAnalyzer::at_deallocation(stmtLocation * stmt,
00299                                        pointerValue & to_deallocate,
00300                                        memoryblock_set & changes)
00301 {
00302   setLive(stmt);
00303 }
00304 
00305 // -- Process a merge point
00306 
00307 void livenessAnalyzer::at_merge(Location * where,
00308                                 memoryBlock * block,
00309                                 memoryuse_list & phi_uses,
00310                                 pointerValue & result,
00311                                 memoryblock_set & changes)
00312 {
00313   // -- Test the one def at the merge-point for liveness
00314 
00315   _defs.clear();
00316   _defs.insert(block->current_def());
00317 
00318   if (determineLiveness())
00319     setLive(where, block);
00320 }
00321 
00322 // -- Control-flow options
00323 
00324 void livenessAnalyzer::at_stmt_exit(stmtLocation * stmt,
00325                                     pointerValue & result)
00326 {
00327   // -- Make sure the _defs set is clear
00328 
00329   _defs.clear();
00330 }
00331 
00332 void livenessAnalyzer::at_basicblock_entry(basicblockLocation * blockloc,
00333                                            procedureInfo * info,
00334                                            pointerValue & initial)
00335 {
00336   // -- If any changes occured, add all the blocks in the backward
00337   // direction.
00338 
00339   if (_change) {
00340     info->add_reachable_blocks(blockloc->block(), Backward);
00341     _change = false;
00342   }
00343 }
00344 
00345   // -- Procedure boundaries
00346 
00347 void livenessAnalyzer::at_procedure_entry(procLocation * proc,
00348                                           procedureInfo * info,
00349                                           pointerValue & return_val)
00350 {
00351   // -- Pop the state of the change boolean
00352 
00353   _change = _change_stack.front();
00354   _change_stack.pop_front();
00355 
00356   // -- Record that this procedure is called
00357 
00358   _visited_procedures.insert(info->proc());
00359 }
00360 
00361 void livenessAnalyzer::at_procedure_exit(procLocation * proc,
00362                                          procedureInfo * info,
00363                                          pointerValue & return_val)
00364 {
00365   // -- Push the state of the change boolean
00366 
00367   _change_stack.push_front(_change);
00368   _change = false;
00369 }
00370 
00371 // ----------------------------------------------------------------------
00372 
00373 void deadcodeChanger::optimize(unitNode * u,
00374                                livenessAnalyzer * liveness)
00375 {
00376   deadcodeChanger ipcc(liveness);
00377 
00378   // -- Remove dead code only in the procedures that the liveness analyzer
00379   // actually visited
00380 
00381   const procedure_set & procs = liveness->visited_procedures();
00382 
00383   for (procedure_set_cp p = procs.begin();
00384        p != procs.end();
00385        ++p)
00386     {
00387       procNode * proc = *p;
00388 
00389       proc->change(ipcc);
00390     }
00391 }
00392 
00393 deadcodeChanger::deadcodeChanger(livenessAnalyzer * liveness)
00394   : Changer( Preorder, Subtree, true),
00395     _liveness(liveness)
00396 {}
00397 
00398 Node * deadcodeChanger::at_threeAddr(threeAddrNode * stmt, Order ord)
00399 {
00400     // -- If the statement is live, then leave it alone
00401 
00402   if (_liveness->isLive(stmt))
00403     return stmt;
00404   else {
00405 
00406     // -- Otherwise, get rid of it.
00407 
00408     ostringstream ostr;
00409     output_context oc(ostr);
00410     stmt->output(oc, 0);
00411 
00412     exprstmtNode * repl = new exprstmtNode((exprNode *)0);
00413     repl->comment() = string("--- DEAD :") + ostr.str();
00414 
00415 
00416     if (pointerOptions::Verbose_liveness) {
00417       cout << "--- DEAD CODE -------------------------------------" << endl;
00418 
00419       output_context oc2(cout);
00420       stmt->output(oc2, 0);
00421       cout << endl;
00422     }
00423 
00424     return repl;
00425   }
00426 
00427   return stmt;
00428 }
00429 

Generated on August 27, 2003
Back to the C-Breeze home page