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  

live.cc

Go to the documentation of this file.
00001 // $Id: live.cc,v 1.7 2003/08/07 23:14:16 pnav Exp $
00002 // ----------------------------------------------------------------------
00003 //
00004 //  C-Breeze
00005 //  C Compiler Framework
00006 // 
00007 //  Copyright (c) 2000 University of Texas at Austin
00008 // 
00009 //  Adam Brown
00010 //  Samuel Z. Guyer
00011 //  Daniel A. Jimenez
00012 //  Calvin Lin
00013 // 
00014 //  Permission is hereby granted, free of charge, to any person
00015 //  obtaining a copy of this software and associated documentation
00016 //  files (the "Software"), to deal in the Software without
00017 //  restriction, including without limitation the rights to use, copy,
00018 //  modify, merge, publish, distribute, sublicense, and/or sell copies
00019 //  of the Software, and to permit persons to whom the Software is
00020 //  furnished to do so, subject to the following conditions:
00021 //  
00022 //  The above copyright notice and this permission notice shall be
00023 //  included in all copies or substantial portions of the Software.
00024 //  
00025 //  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
00026 //  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00027 //  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
00028 //  NONINFRINGEMENT.  IN NO EVENT SHALL THE UNIVERSITY OF TEXAS AT
00029 //  AUSTIN BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
00030 //  IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
00031 //  OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
00032 //  THE SOFTWARE.
00033 //
00034 //  We acknowledge the C-to-C Translator from MIT Laboratory for
00035 //  Computer Science for inspiring parts of the C-Breeze design.
00036 //
00037 // ----------------------------------------------------------------------
00038 
00039 #include "live.h"
00040 #include "cfg.h"
00041 
00042 LivenessWalker::LivenessWalker(): 
00043   Walker (Both, Subtree),
00044   _num_decls(0),
00045   _num2decl()
00046 {}
00047 
00048 LivenessWalker * LivenessWalker::walk(procNode * the_proc) {
00049   LivenessWalker * lw = new LivenessWalker();
00050   the_proc->walk(*lw);
00051   return lw;
00052 }
00053 
00054 void LivenessWalker::at_proc(procNode * the_proc, Order ord) {
00055   if ( ord == Preorder ) {
00056     assert(the_proc->decl()->type()->typ() == Func);
00057     funcNode * the_func = (funcNode *) the_proc->decl()->type();
00058     blockNode * the_body = the_proc->body();
00059 
00060     // Set the _decl2num & _num2decl for the arguments & local vars
00061     // We start from 1 b/c all globals map to 0 (the default)
00062     int num_decls =  the_func->args().size() + the_body->decls().size();
00063     _num2decl.push_back(NULL);
00064     int i = 1;
00065     for ( decl_list_p p = the_func->args().begin();
00066           p != the_func->args().end();
00067           p++, i++ ) {
00068       _decl2num[*p] = i;
00069       _num2decl.push_back(*p);
00070     }
00071     for ( decl_list_p p = the_body->decls().begin();
00072           p != the_body->decls().end();
00073           p++, i++ ) {
00074       _decl2num[*p] = i;
00075       _num2decl.push_back(*p);
00076     }
00077 
00078     assert(i == num_decls + 1);
00079     _num_decls = i;
00080   } else { // ord == Postorder 
00081     // Perform global Liveness analysis based on the local analysis from
00082     // each basic block.  Use IDFA.
00083 
00084     // TODO: change this to use a worklist
00085     bool changed = false;
00086     do { 
00087       changed = false;
00088       for ( stmt_list_p p = the_proc->body()->stmts().begin();
00089             p != the_proc->body()->stmts().end();
00090             p++ ) {
00091         basicblockNode * the_bb = dynamic_cast<basicblockNode *> (*p);
00092         assert(the_bb);
00093         
00094         // live_out = U live_in (over all successors)
00095         for ( basicblock_list_p q = the_bb->succs().begin();
00096               q != the_bb->succs().end();
00097               q++ ) {
00098           _live_out[the_bb]->Or(_live_in[*q]);
00099         }
00100         
00101         // live_in = use U (live_out - def)
00102         Bits old_in(_num_decls);
00103         old_in.copy(_live_in[the_bb]);  
00104         _live_in[the_bb]->copy(_live_out[the_bb]);
00105         _live_in[the_bb]->Difference(_def[the_bb]);
00106         _live_in[the_bb]->Or(_use[the_bb]);
00107         
00108         if ( *_live_in[the_bb] != old_in )
00109           changed = true;
00110       }
00111 //       cout << "changed? " << changed << endl;
00112     } while ( changed );
00113 
00114     // Propagate the global liveness information back into the statements 
00115     // inside each basic block.  Note that this simply adds to the information
00116     // that each stmtNode already had;  it does not completely replace/generate
00117     // the liveness information for each statment.
00118     for ( stmt_list_p p = the_proc->body()->stmts().begin();
00119           p != the_proc->body()->stmts().end();
00120           p++ ) {
00121       stmt_list::reverse_iterator q;
00122       basicblockNode * the_bb = (basicblockNode *) *p;
00123       Bits current(_num_decls);
00124       current.copy(_live_out[the_bb]);
00125       for ( q = the_bb->stmts().rbegin(); q != the_bb->stmts().rend(); q++ ) {
00126         if ( _live_out.find(*q) != _live_out.end() ) {
00127           _live_out[*q]->Or(&current);
00128           current.Difference(_def[*q]);
00129           _live_in[*q]->Or(&current);
00130         }
00131       }
00132     }
00133   }
00134 }
00135 
00136 void LivenessWalker::at_basicblock(basicblockNode * the_bb, Order ord) {
00137   if ( ord == Postorder ) {
00138     // Do local Liveness analysis inside the basic block.
00139     Bits current(_num_decls);
00140     Bits block_def(_num_decls);
00141     Bits block_use(_num_decls);
00142     stmt_list::reverse_iterator p;
00143     for ( p = the_bb->stmts().rbegin(); p != the_bb->stmts().rend(); p++ ) {
00144       if ( _def.find(*p) != _def.end() ) {
00145         _live_out[*p]->copy(&current);
00146 
00147         // in[n] = use[n] U (out[n] - def[n])
00148         current.Difference(_def[*p]);
00149         current.Or(_use[*p]);
00150         _live_in[*p]->copy(&current);
00151 
00152         block_def.Or(_def[*p]);
00153         block_use.Difference(_def[*p]);
00154         block_use.Or(_use[*p]);
00155       }
00156     } // end for ( ... the_bb->stmts() ... )
00157     _def[the_bb] = block_def.clone();
00158     _use[the_bb] = block_use.clone();
00159     _live_in[the_bb] = new Bits(_num_decls);
00160     _live_out[the_bb] = new Bits(_num_decls);
00161   }
00162 }
00163 
00164 void LivenessWalker::at_return(returnNode * the_return, Order ord) {
00165   if ( ord == Preorder ) {
00166     _use[the_return] = new Bits(_num_decls);
00167     _def[the_return] = new Bits(_num_decls);
00168     _live_in[the_return] = new Bits(_num_decls);
00169     _live_out[the_return] = new Bits(_num_decls);
00170     if ( the_return->expr() ) {
00171       idNode * return_expr = dynamic_cast<idNode *> (the_return->expr());
00172       assert(return_expr); // otherwise, this isn't really dismantled code
00173       _use[the_return]->set(_decl2num[return_expr->decl()]);
00174     }
00175   }
00176 }
00177 
00178 void LivenessWalker::at_conditiongoto(conditiongotoNode * the_condgoto,
00179                                       Order ord) {
00180   if ( ord == Preorder ) {
00181     _use[the_condgoto] = new Bits(_num_decls);
00182     _def[the_condgoto] = new Bits(_num_decls);
00183     _live_in[the_condgoto] = new Bits(_num_decls);
00184     _live_out[the_condgoto] = new Bits(_num_decls);
00185     idNode * left = dynamic_cast<idNode *> (the_condgoto->left());
00186     if ( left )
00187       _use[the_condgoto]->set(_decl2num[left->decl()]);
00188     idNode * right = dynamic_cast<idNode *> (the_condgoto->right());
00189     if ( right )
00190       _use[the_condgoto]->set(_decl2num[right->decl()]);
00191   }
00192 }
00193 
00194 void LivenessWalker::at_threeAddr(threeAddrNode * the_3addr, Order ord) {
00195   if ( ord == Preorder ) {
00196     // Generate the _def's and _use's sets for each stmt
00197     _use[the_3addr] = new Bits(_num_decls);
00198     _def[the_3addr] = new Bits(_num_decls);
00199     _live_in[the_3addr] = new Bits(_num_decls);
00200     _live_out[the_3addr] = new Bits(_num_decls);
00201 
00202     if ( the_3addr->lhs() )
00203       defUseOperand(the_3addr, the_3addr->lhs(), true, false);
00204     if ( the_3addr->rhs1() )
00205       defUseOperand(the_3addr, the_3addr->rhs1(), false, false);
00206     if ( the_3addr->rhs2() )
00207       defUseOperand(the_3addr, the_3addr->rhs2(), false, false);
00208     if ( !the_3addr->arg_list().empty() )
00209       for ( operand_list_p p = the_3addr->arg_list().begin();
00210             p != the_3addr->arg_list().end();
00211             p++ )
00212         defUseOperand(the_3addr, *p, false, true);
00213   }
00214 }
00215 
00216 // This analysis does not differentiate between different fields in a
00217 // struct nor the different elements in an array.
00218 // TODO: update defUseOperand to perform some simple pointer analyses.
00219 //       Instead of the set_all() calls, we can track which variables have
00220 //       had their address taken (&) and only set the bits corresponding to
00221 //       those variables instead.  We will also have to track arrays and
00222 //       pointer assignments (?).
00223 void LivenessWalker::defUseOperand(threeAddrNode * the_3addr, 
00224                                    operandNode * the_oper,
00225                                    bool on_left,
00226                                    bool func_arg) {
00227   if ( on_left ) {
00228     if ( the_oper->star() ) {
00229       _def[the_3addr]->set_all();
00230       _use[the_3addr]->set(_decl2num[((idNode *) the_oper->var())->decl()]);
00231     } else
00232       _def[the_3addr]->set(_decl2num[((idNode *) the_oper->var())->decl()]);
00233   } else if ( func_arg ) {
00234     idNode * var = dynamic_cast<idNode *> (the_oper->var());
00235     if ( var ) {
00236       if ( the_oper->star() )
00237         _use[the_3addr]->set_all();
00238       else if ( the_oper->addr() )
00239         _def[the_3addr]->set(_decl2num[var->decl()]);
00240       else // simply a use of the variable
00241         _use[the_3addr]->set(_decl2num[var->decl()]);
00242     }
00243   } else {
00244     idNode * var = dynamic_cast<idNode *> (the_oper->var());
00245     if ( var ) {
00246       if ( the_oper->star() )
00247         _use[the_3addr]->set_all();
00248       else if ( the_oper->addr() )
00249         ;  // possibly add to set of vars whose address is taken
00250       else // simply a use of the variable
00251         _use[the_3addr]->set(_decl2num[var->decl()]);
00252     }
00253   }
00254   
00255   if ( the_oper->index()
00256        && the_oper->index()->typ() == Id )
00257     _use[the_3addr]->set(_decl2num[((idNode *) the_oper->index())->decl()]);
00258 }
00259 
00260 void LivenessWalker::at_stmt(stmtNode * the_stmt, Order ord) {
00261   // catch all for statements that don't have defs or uses, and thus
00262   // don't affect the liveness within a block.  for example,
00263   // labelNodes, and gotoNodes
00264   if ( ord == Preorder ) {
00265     _use[the_stmt] = new Bits(_num_decls);
00266     _def[the_stmt] = new Bits(_num_decls);
00267     _live_in[the_stmt] = new Bits(_num_decls);
00268     _live_out[the_stmt] = new Bits(_num_decls);
00269   }
00270 }
00271 
00272 // returns NULL if bits is NULL
00273 decl_set * LivenessWalker::bits2decls(Bits * bits) {
00274   if ( !bits )
00275     return NULL;
00276   decl_set * the_set = new decl_set;
00277   for ( int i = 1; i < bits->size(); i++ )
00278     if ( bits->value(i) )
00279       the_set->insert(_num2decl[i]);
00280   return the_set;
00281 }
00282 
00283 // returns NULL if the_stmt is not in the procedure that this LivenessWalker
00284 // have liveness information about
00285 decl_set * LivenessWalker::defs(stmtNode * the_stmt) {
00286   return bits2decls(_def[the_stmt]);
00287 }
00288 
00289 // returns NULL if the_stmt is not in the procedure that this LivenessWalker
00290 // have liveness information about
00291 decl_set * LivenessWalker::uses(stmtNode * the_stmt) {
00292   return bits2decls(_use[the_stmt]);
00293 }
00294 
00295 // returns NULL if the_stmt is not in the procedure that this LivenessWalker
00296 // have liveness information about
00297 decl_set * LivenessWalker::live_in(stmtNode * the_stmt) {
00298   return bits2decls(_live_in[the_stmt]);
00299 }
00300 
00301 // returns NULL if the_stmt is not in the procedure that this LivenessWalker
00302 // have liveness information about
00303 decl_set * LivenessWalker::live_out(stmtNode * the_stmt) {
00304   return bits2decls(_live_out[the_stmt]);
00305 }
00306 
00307 LivenessComments::LivenessComments(void):
00308   Walker(Both, Subtree),
00309   _lw(NULL)
00310 {}
00311 
00312 void LivenessComments::at_proc(procNode * the_proc, Order ord) {
00313   if ( ord == Preorder )
00314     _lw = LivenessWalker::walk(the_proc);
00315   else
00316     if ( _lw )
00317       delete _lw;
00318 }
00319 
00320 void LivenessComments::comment_stmt(stmtNode * the_stmt) {
00321   ostringstream ost;
00322   ost << endl << "defs: ";
00323   decl_set * defs = _lw->defs(the_stmt);
00324   for ( decl_set_p p = defs->begin(); p != defs->end(); p++ )
00325     ost << (*p)->name() << " ";
00326   delete defs;
00327   decl_set * uses = _lw->uses(the_stmt);
00328   ost << "; uses: ";
00329   for ( decl_set_p p = uses->begin(); p != uses->end(); p++ )
00330     ost << (*p)->name() << " ";
00331   delete uses;
00332   decl_set * live_in = _lw->live_in(the_stmt);
00333   ost << "; live_in: ";
00334   for ( decl_set_p p = live_in->begin(); p != live_in->end(); p++ )
00335     ost << (*p)->name() << " ";
00336   delete live_in;
00337   decl_set * live_out = _lw->live_out(the_stmt);
00338   ost << "; live_out: ";
00339   for ( decl_set_p p = live_out->begin(); p != live_out->end(); p++ )
00340     ost << (*p)->name() << " ";
00341   delete live_out;
00342   the_stmt->comment() += ost.str();
00343 }
00344 void LivenessComments::at_threeAddr(threeAddrNode * the_3addr, Order ord) {
00345   if ( ord == Preorder )
00346     comment_stmt(the_3addr);
00347 }
00348 
00349 void LivenessComments::at_basicblock(basicblockNode * the_bb, Order ord) {
00350   if ( ord == Preorder )
00351     comment_stmt(the_bb);
00352 }
00353 
00354 void LivenessComments::at_return(returnNode * the_return, Order ord) {
00355   if ( ord == Preorder )
00356    comment_stmt(the_return);
00357 }
00358 
00359 void LivenessComments::at_conditiongoto(conditiongotoNode * the_condgoto,
00360                                         Order ord) {
00361   if ( ord == Preorder )
00362     comment_stmt(the_condgoto);
00363 }
00364 
00368 class LiveTest : public Phase {
00369 public:
00370   void run(void) {
00371     for ( unit_list_p u = CBZ::Program.begin(); u != CBZ::Program.end(); 
00372           u++ ) {
00373       cfg_changer::generate_cfg(*u);
00374 
00375       LivenessComments lc;
00376       (*u)->walk(lc);
00377     }
00378   }
00379 };  
00380 
00381 Phases LiveTestPhase("livetest", new LiveTest());

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