liveness_analysis.cc

Go to the documentation of this file.
00001 #include <lestes/backend_v2/structs/func_data.g.hh>
00002 #include <lestes/backend_v2/intercode/visitor_pi_pi2id.g.hh>
00003 #include <lestes/backend_v2/intercode/ge.g.hh>
00004 #include <lestes/backend_v2/intercode/pi_mem_factory.g.hh>
00005 #include <lestes/backend_v2/workers/liveness_analysis.g.hh>
00006 #include <lestes/backend_v2/debug/debug.hh>
00007 
00008 package(lestes);
00009 package(backend_v2);
00010 package(workers);
00011 
00012 using namespace ::lestes::backend_v2::intercode;
00013 
00014 typedef map< srp< ::lestes::backend_v2::intercode::ge_pi >, srp< ::lestes::std::pair< srp<set< srp< ::lestes::backend_v2::intercode::ge_operand_reg > > >, srp<set< srp< ::lestes::backend_v2::intercode::ge_operand_reg > > > > > > ge_pi2inout__type;
00015 typedef list< srp<ge_pi> > ge_pi_list__type;
00016 typedef set< srp< ::lestes::backend_v2::intercode::ge_operand_reg > > ge_op_set__type;
00017 typedef ::lestes::std::pair< srp<ge_op_set__type>,srp<ge_op_set__type> > ge_op_set_pair__type;
00018 typedef vector< srp<ge_operand> > ge_op_vector__type;
00019 typedef vector< srp < ge_sp > > ge_sp_vector__type;
00020 typedef map<srp<ge_operand>,srp<liveness_range> > ge_op2liveness__type;
00021 
00022 /*
00023         \brief Computes live ranges of operands.
00024         
00025         foreach n in BODY: 
00026                 in[n]<-{}; out[n]<-{};
00027         end_foreach
00028         
00029         repeat
00030         
00031                 foreach n in BODY:
00032                         in'[n] <- in[n]
00033                         out'[n] <- out[n]
00034                         
00035                         in[n] <- use[n] UNION ( out[n] DIFFERENCE def[n] )
00036                         out[n] <- UNION[s from succ(n)](in[s])
00037                         
00038                 end_foreach
00039                 
00040         until in'==in || out'==out;
00041         
00042 */
00043 void liveness_analysis::process() {
00044 
00045         ptr<visitor_pi_pi2id> pi2id = visitor_pi_pi2id::create();
00046         
00047         ptr<ge_pi_list__type> body = data_get()->ge_body_get(); 
00048 
00049         //initialise In and Out sets for every ge_pi in the body        
00050         for(ge_pi_list__type::iterator it = body->begin(); it!=body->end(); ++it) {
00051                 ptr<ge_pi> ge =  *it;
00052                 (*inout)[ge] = ge_op_set_pair__type::create(ge_op_set__type::create(),ge_op_set__type::create());
00053         }
00054                 
00055         bool changed = true;
00056         
00057         while(changed) {
00058         
00059                 changed = false;
00060                 
00061                 ptr<ge_pi> succ;
00062                 
00063                 for(ge_pi_list__type::reverse_iterator it = body->rbegin(); it!=body->rend(); ++it) {
00064                         ptr<ge_pi> ge =  *it;
00065                         
00066                         if ( ge->kind_get()==ge_pi::SP ) {
00067                                 /*
00068                                         ge_sp usually has no operands.
00069                                         
00070                                         Exception is the case that some instruction A has to be done 
00071                                         and its output operands are not used elsewhere. So the pi_sp 
00072                                         is set to use these output operand in order     to not allow a 
00073                                         dead code elimination to delete the instruction A.
00074                                         These operands aren't real operands, so the ge_sp should
00075                                         not be included in their liveness rangess.
00076                                 */
00077                                 continue;
00078                         }
00079                         
00080                         ptr<ge_op_vector__type> in_ops = ge->operands_input_get();
00081                         ptr<ge_op_vector__type> out_ops = ge->operands_output_get();
00082                         
00083                         //old Inp and Out sets of the current ge_pi
00084                         ptr<ge_op_set_pair__type> ge_io = (*inout)[ge];
00085                         ptr<ge_op_set__type> old_in = ge_io->first;
00086                         ptr<ge_op_set__type> old_out = ge_io->second;
00087                         
00088                         //updated sets
00089                         ptr<ge_op_set__type> in = ge_op_set__type::create();
00090                         ptr<ge_op_set__type> out = ge_op_set__type::create();
00091                         
00092                         ge_io->first = in;
00093                         ge_io->second = out;
00094                         
00095                         /*
00096                                 in[n] <- use[n] UNION ( out[n] DIFFERENCE def[n] )
00097                         */
00098                         for(ulint i=0; i<out_ops->size(); ++i) {
00099                                 ptr<ge_operand> op = (*out_ops)[i];
00100                                 
00101                                 ptr<ge_operand_reg> reg = extract_reg_operand(op);
00102                                 
00103                                 if ( !reg ) {
00104                                         continue;
00105                                 }
00106                                 
00107                                 if ( old_out->find(reg)==old_out->end() ) {
00108                                         in->insert(reg);
00109                                 }
00110                         }
00111                         
00112                         for(ulint i=0; i<in_ops->size(); ++i) {
00113                                 ptr<ge_operand> op = (*in_ops)[i];
00114                                 
00115                                 ptr<ge_operand_reg> reg = extract_reg_operand(op);
00116                                 
00117                                 if ( !reg ) {
00118                                         continue;
00119                                 }
00120                                 
00121                                 in->insert(reg);
00122                         }
00123                         
00124                         
00125                         /*
00126                                 out[n] <- UNION[s from succ(n)](in[s])
00127                         */
00128                         
00129                         visitor_pi_pi2id::kind_type pi_id = visitor_pi_pi2id::PI_ADD;
00130                         
00131                         if ( ge->pi_source_get() ) {
00132                                         pi_id = (visitor_pi_pi2id::kind_type)ge->pi_source_get()->accept_visitor_pi_pi2ulint_gen_base(pi2id);
00133                         }
00134                         
00135                         switch ( pi_id ) {
00136                                 case visitor_pi_pi2id::PI_BA:
00137                                 case visitor_pi_pi2id::PI_LEAVE: {
00138                                         /*
00139                                                 pi_ba and pi_leave always jumps to its target. 
00140                                                 The following instruction in scheduled order is not successor.
00141                                         */              
00142                                         ptr<ge_sp_vector__type> targets = ge->jmp_targets_get();
00143                                         
00144                                         if (  targets && targets->size()!=0 ) {
00145                                         
00146                                                 for(ulint i=0; i<targets->size(); ++i) {
00147                                                         ptr<ge_op_set_pair__type> succ_io = (*inout)[(*targets)[i]];
00148                                                         ptr<ge_op_set__type> succ_in = succ_io->first;
00149                                                         
00150                                                         set_union(
00151                                                                 out->begin(),
00152                                                                 out->end(),
00153                                                                 succ_in->begin(),
00154                                                                 succ_in->end(),
00155                                                                 ::std::insert_iterator<ge_op_set__type>(*out,out->begin()));
00156                                                 }
00157                                         }
00158                                         
00159                                 } break;
00160                                 
00161                                 case visitor_pi_pi2id::PI_BN: {
00162                                         /*
00163                                                 pi_bn never jumps to its target. 
00164                                                 The following instruction in scheduled order is the only successor.
00165                                         */
00166                                         if ( succ ) {
00167                                                 ptr<ge_op_set_pair__type> succ_io = (*inout)[succ];
00168                                                 ptr<ge_op_set__type> succ_in = succ_io->first;
00169                                                 
00170                                                 set_union(
00171                                                         out->begin(),
00172                                                         out->end(),
00173                                                         succ_in->begin(),
00174                                                         succ_in->end(),
00175                                                         ::std::insert_iterator<ge_op_set__type>(*out,out->begin()));
00176                                         }
00177                                         
00178                                 } break;
00179                                 
00180                                 default: {
00181                                         
00182                                         /*
00183                                                 The following instruction in scheduled order is successor.
00184                                         */
00185                                         if ( succ ) {
00186                                                 ptr<ge_op_set_pair__type> succ_io = (*inout)[succ];
00187                                                 ptr<ge_op_set__type> succ_in = succ_io->first;
00188                                                 
00189                                                 set_union(
00190                                                         out->begin(),
00191                                                         out->end(),
00192                                                         succ_in->begin(),
00193                                                         succ_in->end(),
00194                                                         ::std::insert_iterator<ge_op_set__type>(*out,out->begin()));
00195                                         }
00196                                         
00197                                         /*
00198                                                 Successors of a branch instruction are its targets too.
00199                                         */
00200                                         ptr<ge_sp_vector__type> targets = ge->jmp_targets_get();
00201                                         if (  targets && targets->size()!=0 ) {
00202                                                 
00203                                                 for(ulint i=0; i<targets->size(); ++i) {
00204                                                         ptr<ge_op_set_pair__type> succ_io = (*inout)[(*targets)[i]];
00205                                                         ptr<ge_op_set__type> succ_in = succ_io->first;
00206                                                         
00207                                                         set_union(
00208                                                                 out->begin(),
00209                                                                 out->end(),
00210                                                                 succ_in->begin(),
00211                                                                 succ_in->end(),
00212                                                                 ::std::insert_iterator<ge_op_set__type>(*out,out->begin()));
00213                                                 }
00214                                         }
00215                                         
00216                                 } break;
00217                                 
00218                         }
00219                                 
00220                         //Test whether In or Out set has been changed.
00221                         if ( in->size()!=old_in->size() || out->size()!=old_out->size() ) {
00222                                 changed = true;
00223                         }
00224                         
00225                         succ = ge;
00226                         
00227                 }       
00228         }
00229         
00230 }
00231 
00232 /*!
00233         \brief If a instance of ge_operand is of type the ge_operand_reg, then returns the instace casted as ge_operand_reg.
00234         
00235         \param op The operand instance.
00236         \return The operand casted as ge_operand_reg.
00237 */
00238 ptr<ge_operand_reg> liveness_analysis::extract_reg_operand(ptr<ge_operand> op) {
00239         ptr<ge_operand_reg> reg = NULL;
00240         
00241         if ( op->kind_get()==ge_operand::REGISTER ) {
00242                 reg = op.dncast<ge_operand_reg>();
00243         }       
00244 
00245         return reg;
00246 }
00247 
00248 /*!
00249         \brief Returns a vector of the computed live ranges.
00250 */
00251 ptr<vector<srp<liveness_range> > > liveness_analysis::get_result() {
00252         ptr<vector<srp<liveness_range> > > output = vector<srp<liveness_range> >::create();
00253         
00254         //Live ranges of operands
00255         ptr<ge_op2liveness__type> op2live = ge_op2liveness__type::create();
00256 
00257         ptr<ge_pi_list__type> body = data_get()->ge_body_get(); 
00258         
00259         for(ge_pi_list__type::iterator it = body->begin(); it!=body->end(); ++it) {
00260                 ptr<ge_pi> ge =  *it;
00261                 
00262                 ptr<ge_op_set__type> ge_io = (*inout)[ge]->first;
00263                 
00264                 for(ge_op_set__type::iterator it_op = ge_io->begin(); it_op!=ge_io->end(); ++it_op) { 
00265                         ptr<ge_operand_reg> reg = *it_op;
00266                         
00267                         ptr<liveness_range> rng;
00268                         
00269                         ge_op2liveness__type::iterator live_it = op2live->find(reg);
00270                         
00271                         if ( live_it==op2live->end() ) {
00272                                 rng = liveness_range::create(reg,ge->schedule_pos_get(),ge->schedule_pos_get());
00273                                 output->push_back(rng);
00274                                 (*op2live)[reg] = rng;
00275                         } else {
00276                                 rng = live_it->second;
00277                                 rng->end_set(ge->schedule_pos_get());
00278                         }
00279                         
00280                         rng->instructions_get()->push_back(ge);
00281                 }
00282         }
00283                 
00284         return output;
00285 }
00286 
00287 
00288 end_package(workers);
00289 end_package(backend_v2);
00290 end_package(lestes);
00291 

Generated on Mon Feb 12 18:22:38 2007 for lestes by doxygen 1.5.1-20070107