alloc_int_finder.cc

Go to the documentation of this file.
00001 #include <lestes/backend_v2/structs/func_data.g.hh>
00002 #include <lestes/backend_v2/intercode/ge.g.hh>
00003 #include <lestes/backend_v2/intercode/pi_mem_factory.g.hh>
00004 #include <lestes/backend_v2/workers/liveness_analysis.g.hh>
00005 #include <lestes/md/registers/tm_register.g.hh>
00006 #include <lestes/md/registers/move_generator.g.hh>
00007 #include <lestes/backend_v2/workers/alloc_int_finder.g.hh>
00008 
00009 package(lestes);
00010 package(backend_v2);
00011 package(workers);
00012 
00013 using namespace ::lestes::backend_v2::intercode;
00014 using namespace ::lestes::backend_v2::structs;
00015 using namespace ::lestes::md::instructions;
00016 using namespace ::lestes::md::registers;
00017 using namespace ::lestes::md::mem;
00018 
00019 typedef set<ulint> id_set__type;
00020 typedef vector<srp<ge_pi> > ge_pi_vector__type;
00021 typedef vector<srp<liveness_range> > liveness_rng_vector__type;
00022 typedef vector<srp<alloc_interval> > alloc_int_vector__type;
00023 
00024 /*!
00025         \brief Splits live ranges to regalloc intervals.
00026         
00027         It traverses list of live ranges and splits every range to intervals that
00028         have nonempty intersection of allowed register sets.
00029 */
00030 void alloc_int_finder::process() {
00031 
00032         //Find liveness ranges.
00033         ptr<liveness_analysis> liveness = liveness_analysis::create(data_get());
00034         liveness->process();
00035         ptr<liveness_rng_vector__type> liveness_rngs = liveness->get_result();  
00036         
00037         
00038         ptr<alloc_int_vector__type> ints = data_get()->alloc_ints_get();
00039         
00040         /*
00041                 Go through liveness ranges and try split them to intervals with nonempty intersections
00042                 of allowed registers. 
00043         */
00044         for(liveness_rng_vector__type::iterator it1 = liveness_rngs->begin(); it1!=liveness_rngs->end(); ++it1) {
00045                 ptr<liveness_range> rng = *it1;
00046                 ptr<ge_operand_reg> operand = rng->operand_get();
00047                 
00048                 ptr<alloc_interval> prev_inter = NULL;
00049                 
00050                 ptr<alloc_interval> inter = NULL;
00051                 ptr<id_set__type> int_allowed_regs = NULL;
00052                 ptr<ge_pi_vector__type> int_instrs = NULL;
00053                 
00054                 ptr<ge_pi_vector__type> rng_instrs = rng->instructions_get();
00055                 
00056                 /*
00057                         Create intervals of the range's instructions with non-empty intersection
00058                         of allowed registers.
00059                 */
00060                 for(ge_pi_vector__type::iterator it2 = rng_instrs->begin(); it2!=rng_instrs->end();) {
00061                         ptr<ge_pi> ge = *it2;
00062 
00063                         if ( !inter ) {
00064                                 inter = alloc_interval::create(operand,rng);
00065                                 ints->push_back(inter);
00066                 
00067                                 int_allowed_regs = NULL;
00068                                 int_instrs = inter->instructions_get();
00069                                 
00070                                 
00071                                 if ( !prev_inter ) {
00072                                         /*
00073                                                 Insert operand's origin to the first interval.
00074                                         
00075                                                 NOTE: This is ok, because of the register allocator does old interval expiration
00076                                                 before searching for free registers. So if live range of an operand ends as input 
00077                                                 operand of a ge_pi, register that is allocated for the operand is emediatly free
00078                                                 for any output operand of the ge_pi.
00079                                         */
00080                                         if ( operand->origin_get() ) {
00081                                                 if ( operand->origin_get()->kind_get()!=ge_pi::SP ) { //origin can be a ge_sp instruction.
00082                                                         int_allowed_regs = ge_pi__get_allowed_regs_for_op(operand->origin_get(),operand);
00083                                                 }
00084                                 
00085                                                 int_instrs->push_back(operand->origin_get());
00086                                         }       
00087                                 } 
00088                         }
00089                         
00090                         if ( ge==operand->origin_get() ) {
00091                                 //The ge_pi is already in interval.
00092                                 ++it2;
00093                                 continue;
00094                         }
00095                         
00096                         if ( ge->kind_get()==ge_pi::SP ) {
00097                                 ++it2;
00098                                 int_instrs->push_back(ge);
00099                                 continue;
00100                         }
00101                         
00102                         ptr<id_set__type> int_allowed_regs_tmp = id_set__type::create();
00103                                 
00104                         ptr<id_set__type> op_allowed_regs = ge_pi__get_allowed_regs_for_op(ge,operand);
00105                         
00106                         if ( !int_allowed_regs ) {
00107                                 //The first instruction in the set
00108                                 int_allowed_regs_tmp->insert(op_allowed_regs->begin(),op_allowed_regs->end());
00109                                 int_allowed_regs = int_allowed_regs_tmp;
00110                         } else {
00111                                 /*
00112                                         N'th instruction in the set. Compute allowed intersection of allowed registers for interval and 
00113                                         instruction.
00114                                 */
00115                                 set_intersection(
00116                                         int_allowed_regs->begin(),
00117                                         int_allowed_regs->end(),
00118                                         op_allowed_regs->begin(),
00119                                         op_allowed_regs->end(),
00120                                         ::std::insert_iterator<id_set__type>(*int_allowed_regs_tmp,int_allowed_regs_tmp->begin()));
00121                         }
00122                         
00123                         if ( int_allowed_regs_tmp->size()==0 ) {
00124                                 //Intersection is empty. Split intervals.
00125                                 lassert(int_instrs->size()!=0);
00126                                 
00127                                 inter->allowed_registers_set(int_allowed_regs);
00128                                 
00129                                 if ( prev_inter ) {
00130                                         inter->start_set(prev_inter->instructions_get()->back()->schedule_pos_get());
00131                                         prev_inter->end_set(int_instrs->front()->schedule_pos_get());
00132                                 } else {
00133                                         inter->start_set(int_instrs->front()->schedule_pos_get());
00134                                 }
00135                                 
00136                                 inter->end_set(int_instrs->back()->schedule_pos_get());
00137                                 
00138                                 if ( prev_inter ) {
00139                                         inter->prev_set(prev_inter);
00140                                         prev_inter->next_set(inter);
00141                                 }
00142                                 
00143                                 prev_inter = inter;
00144                                 
00145                                 inter = NULL;
00146                         } else {
00147                                 //Intersection is non-empty.
00148                                 int_allowed_regs = int_allowed_regs_tmp;
00149                                 int_instrs->push_back(ge);
00150                                 ++it2;  
00151                         }
00152                         
00153                         
00154                 }
00155                 
00156                 if ( inter ) {
00157                         //Finish the last interval.
00158                         lassert(int_instrs->size()!=0);
00159                         
00160                         inter->allowed_registers_set(int_allowed_regs);
00161                                 
00162                         if ( prev_inter ) {
00163                                 inter->start_set(prev_inter->instructions_get()->back()->schedule_pos_get());
00164                                 prev_inter->end_set(int_instrs->front()->schedule_pos_get());
00165                         } else {
00166                                 inter->start_set(int_instrs->front()->schedule_pos_get());
00167                         }
00168         
00169                         inter->end_set(int_instrs->back()->schedule_pos_get());
00170                                 
00171                         if ( prev_inter ) {
00172                                 inter->prev_set(prev_inter);
00173                                 prev_inter->next_set(inter);
00174                         }
00175                 }
00176                 
00177         }
00178         
00179 }
00180 
00181 /*!
00182         \brief Returns set of allowed register for an operand within a pseudoinstruction.
00183         
00184         \param ge A pseudoinstruction.
00185         \param op An operand.
00186         \return Id set of allowed registers.
00187 */
00188 ptr<id_set__type> alloc_int_finder::ge_pi__get_allowed_regs_for_op(ptr<ge_pi> ge,ptr<ge_operand_reg> op) {
00189         
00190         //get target machine description of the operand
00191         ptr<tm_instr_op_reg_base> tm_op = ge_pi__find_tm_op_by_ge_op(ge,op);
00192         lassert(tm_op);
00193         
00194         //allowed registers
00195         ptr<id_set__type> regs = id_set__type::create(tm_op->allowed_registers_get());
00196         
00197         ulint type_id = op->type_get()->id_get();
00198         /*
00199                 There are registers in the allowed register set that are incompatible with the operands datatype.
00200                 Those registers need to be removed from the set. 
00201         */
00202         for(id_set__type::iterator it = regs->begin(); it!=regs->end();) {
00203                 ptr<tm_register_base> reg = tm_register::instance(*it);
00204                 if ( reg->compatible_types_get()->find(type_id)==reg->compatible_types_get()->end() ) {
00205                         id_set__type::iterator del_it = it++;
00206                         regs->erase(del_it);
00207                 } else {
00208                         ++it;
00209                 }
00210         }
00211         
00212         lassert(regs->size()!=0);
00213         
00214         return regs;
00215 }
00216 
00217 /*!
00218         \brief Returns a target operand description that corresponds to an operand within a pseudoinstruction.
00219         
00220         \param ge A pseudoinstruction.
00221         \param op An operand.
00222         \return A target machine operand description.
00223 */
00224 ptr<tm_instr_op_reg_base> alloc_int_finder::ge_pi__find_tm_op_by_ge_op(ptr<ge_pi> ge,ptr<ge_operand_reg> op) {
00225         ptr<tm_instr_base> tm = ge->instruction_get();
00226         
00227         lassert(tm);
00228                                 
00229         for(ulint i=0; i<ge->operands_input_get()->size(); ++i) {
00230                 if ( op==(*ge->operands_input_get())[i] ) {
00231                         return (*tm->operands_input_get())[i].dncast<tm_instr_op_reg_base>();
00232                 }
00233         }
00234         
00235         for(ulint i=0; i<ge->operands_output_get()->size(); ++i) {
00236                 if ( op==(*ge->operands_output_get())[i] ) {
00237                         return (*tm->operands_output_get())[i].dncast<tm_instr_op_reg_base>();
00238                 }
00239         }
00240         
00241         return NULL;
00242         
00243 }
00244 
00245 
00246 /*!
00247         \brief Returns data of a processed function with result of the worker included.
00248         
00249         \return Data of a processed function.
00250 */
00251 ptr<func_data> alloc_int_finder::get_result() {
00252         return data_get();
00253 }
00254 
00255 end_package(workers);
00256 end_package(backend_v2);
00257 end_package(lestes);
00258 

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