bb_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.g.hh>
00004 #include <lestes/backend_v2/workers/bb_finder.g.hh>
00005 #include <lestes/md/instructions/tm_instr.g.hh>
00006 
00007 package(lestes);
00008 package(backend_v2);
00009 package(workers);
00010 
00011 using namespace ::lestes::backend_v2::structs;
00012 using namespace ::lestes::backend_v2::intercode;
00013 using namespace ::lestes::md::instructions;
00014 using namespace ::lestes::msg;
00015 
00016 typedef set< srp<ge_pi> > ge_pi_set__type;
00017 typedef map<srp<pi_mem_factory>,srp<set< srp<ge_pi> > > > m2ge_pi_set__type;
00018 typedef list< srp<ge_pi> > ge_pi_list__type;
00019 typedef vector< srp<ge_pi> > ge_pi_vector__type;
00020 typedef vector< srp<ge_operand> > ge_operand_vector__type;
00021 typedef vector< srp<basic_block> > bb_vector__type;
00022 
00023 declare_logger(bblog);
00024 initialize_logger( bblog, "bb_finder", backend_v2_logger );
00025 
00026 /*!
00027         \brief Groups pseudoinstructions of a function body to basic blocks.
00028 */
00029 void bb_finder::process() {
00030         
00031         ptr<ge_pi_list__type> body = data_get()->ge_body_get();
00032         ptr<bb_vector__type> bbs = data_get()->bbs_get();
00033         
00034         ptr<basic_block> prev_bb = NULL;
00035         ptr<basic_block> active_bb = NULL;
00036         
00037         bool b_active_is_safe = true;
00038         
00039         for(ge_pi_list__type::iterator it = body->begin(); it!=body->end(); ++it) {
00040                 ptr<ge_pi> ge = *it;
00041 
00042                 if (ge->kind_get()==ge_pi::SP ) {
00043                         ptr<ge_sp> sp = ge.dncast<ge_sp>();
00044 
00045                         if ( active_bb ) {
00046                                 active_bb->lsp_set(sp);
00047                                 
00048                                 if ( prev_bb ) {
00049                                         //Join blocks.
00050                                         active_bb = join_blocks(prev_bb,active_bb);
00051                                 } else {                                        
00052                                         bbs->push_back(active_bb);
00053                                 }
00054                                 
00055                                 if ( sp->is_jmp_target_get() || !b_active_is_safe ) {
00056                                         prev_bb = NULL;
00057                                 } else {
00058                                         prev_bb = active_bb;
00059                                 }
00060                                 
00061                                 active_bb = NULL;
00062                         }
00063                         
00064                         if ( !active_bb && ge!=body->back() ) {
00065                                 active_bb = basic_block::create();
00066                                 active_bb->fsp_set(sp);
00067                                 b_active_is_safe = true;
00068                         }
00069                         
00070                 } else {                
00071                         /*
00072                                 The following code line turns off block joining.
00073                                 
00074                                 Extended basic blocks bring a lots of problems especially 
00075                                 in context with memory operands and memory alliasing.
00076                                 
00077                                 Extended blocks don't produce better results of code scheduling
00078                                 so it is better to switch off block joining to extended blocks.
00079                         */
00080                         prev_bb = NULL; 
00081                         
00082                         ge->bb_set(active_bb);
00083                         active_bb->instructions_get()->push_back(ge);
00084                         
00085                         if ( !is_instruction_safe(ge) ) {
00086                                  //The block contains instruction that doesn't allow the block to be merged with a previous one.
00087                                  prev_bb = NULL;
00088                                  b_active_is_safe = false;
00089                         }
00090                 }
00091         }
00092 }
00093 
00094 /*!
00095         \brief Tells whether a pseudoinstruction has any side-effect that disallows joining of the pseudoinstruction's basic block with preceding one.
00096         
00097         \param ge A pseudoinstruction.
00098         \return True it the pseudoinstruction is safe. False otherwise.
00099 */
00100 bool bb_finder::is_instruction_safe(ptr<ge_pi> ge) {
00101         if ( (ge->instruction_get() && ( ge->instruction_get()->is_system() || ge->instruction_get()->is_jump()) ) ||
00102                  (ge->kind_get()==ge_pi::SP && ge.dncast<ge_sp>()->is_jmp_target_get()) ) {
00103                  return false;
00104         }
00105         
00106         ptr<ge_operand_vector__type> operands = ge->operands_input_get();
00107         
00108         for(ge_operand_vector__type::iterator it_op = operands->begin(); it_op!=operands->end(); ++it_op) {
00109                 if ( (*it_op)->kind_get()!=ge_operand::MEMORY ) {
00110                         continue;
00111                 }
00112 
00113                 ptr<pi_mem_factory> mf = (*it_op).dncast<ge_operand_mem>()->factory_get();
00114                 
00115                 if ( mf->kind_get()==pi_mem_factory::MF_PTR_DEREF ) {
00116                         return false;
00117                 }                       
00118         }
00119 
00120         operands = ge->operands_output_get();
00121         
00122         for(ge_operand_vector__type::iterator it_op = operands->begin(); it_op!=operands->end(); ++it_op) {
00123                 if ( (*it_op)->kind_get()!=ge_operand::MEMORY ) {
00124                         continue;
00125                 }
00126 
00127                 ptr<pi_mem_factory> mf = (*it_op).dncast<ge_operand_mem>()->factory_get();
00128                 
00129                 if ( mf->kind_get()==pi_mem_factory::MF_PTR_DEREF ) {
00130                         return false;
00131                 }                       
00132         }
00133 
00134         return true;            
00135 }
00136 
00137 /*!
00138         \brief Merges two basic blocks into one.
00139         
00140         \param bb1 A first basic block.
00141         \param bb2 A second basic block.
00142         \return A merged result.
00143 */
00144 ptr<basic_block> bb_finder::join_blocks(ptr<basic_block> bb1, ptr<basic_block> bb2) {
00145         ptr<ge_pi_vector__type> active_instrs = bb2->instructions_get();
00146         ptr<ge_pi_vector__type> prev_instrs = bb1->instructions_get();
00147                                         
00148         ptr<ge_sp> prev_fsp = bb1->fsp_get();
00149         ptr<ge_sp> active_lsp = bb2->lsp_get();//
00150         
00151         bb1->lsp_set(active_lsp);
00152         
00153         ptr<ge_sp> active_fsp = bb2->fsp_get();
00154                                         
00155         /*  
00156                 Split the bording sp into two sps. The first one will inherit input operands and dependencies
00157                 and the second one will inherits output ones.
00158         */
00159         
00160         ptr<ge_sp> new_sp = ge_sp::create(NULL,NULL);
00161         new_sp->operands_input_set(active_fsp->operands_input_get());
00162         new_sp->dependencies_set(active_fsp->dependencies_get());
00163         new_sp->bb_set(bb1);
00164         prev_instrs->push_back(new_sp);
00165                                         
00166         prev_instrs->push_back(active_fsp);
00167         active_fsp->dependencies_set(ge_pi_set__type::create());
00168         active_fsp->operands_input_set(ge_operand_vector__type::create());
00169         active_fsp->bb_set(bb1);
00170                                         
00171         /*
00172                 In the first block, find instructions that stores into memory.
00173         */
00174         ptr<m2ge_pi_set__type> mfdeps = m2ge_pi_set__type::create();
00175         
00176         for(ge_pi_vector__type::iterator it = prev_instrs->begin(); it!=prev_instrs->end(); ++it) {
00177                 ptr<ge_pi> ge = *it;
00178                 
00179                 active_lsp->dependencies_get()->insert(ge);
00180                 
00181                 ptr<ge_operand_vector__type> operands = ge->operands_input_get();
00182                 
00183                 for(ge_operand_vector__type::iterator it_op = operands->begin(); it_op!=operands->end(); ++it_op) {
00184                         if ( (*it_op)->kind_get()!=ge_operand::MEMORY ) {
00185                                 continue;
00186                         }
00187 
00188                         ptr<pi_mem_factory> mf = (*it_op).dncast<ge_operand_mem>()->factory_get();
00189                                 
00190                         m2ge_pi_set__type::iterator it_search = mfdeps->find(mf);
00191                                 
00192                         if ( it_search!=mfdeps->end() ) {
00193                                 it_search->second->insert(ge);
00194                         } else {
00195                                 ptr<ge_pi_set__type> deps = ge_pi_set__type::create();
00196                                 deps->insert(ge);
00197                                 (*mfdeps)[mf] = deps;
00198                         }       
00199                 }
00200                 
00201                 operands = ge->operands_output_get();
00202                 
00203                 for(ge_operand_vector__type::iterator it_op = operands->begin(); it_op!=operands->end(); ++it_op) {
00204                         if ( (*it_op)->kind_get()!=ge_operand::MEMORY ) {
00205                                 continue;
00206                         }
00207 
00208                         ptr<pi_mem_factory> mf = (*it_op).dncast<ge_operand_mem>()->factory_get();
00209                                 
00210                         m2ge_pi_set__type::iterator it_search = mfdeps->find(mf);
00211                                 
00212                         if ( it_search!=mfdeps->end() ) {
00213                                 it_search->second->insert(ge);
00214                         } else {
00215                                 ptr<ge_pi_set__type> deps = ge_pi_set__type::create();
00216                                 deps->insert(ge);
00217                                 (*mfdeps)[mf] = deps;
00218                         }       
00219                 }
00220                 
00221         }
00222         
00223         /*
00224                 In the second block, find instructions that uses memory operands and set dependecies on instructions from the
00225                 first block that produces these operands.
00226         */
00227         for(ge_pi_vector__type::iterator it = active_instrs->begin(); it!=active_instrs->end(); ++it) {
00228                 ptr<ge_pi> ge = *it;
00229                 
00230                 ptr<ge_operand_vector__type> operands = ge->operands_input_get();
00231                 
00232                 for(ge_operand_vector__type::iterator it_op = operands->begin(); it_op!=operands->end(); ++it_op) {
00233                         if ( (*it_op)->kind_get()!=ge_operand::MEMORY ) {
00234                                 continue;
00235                         }
00236 
00237                         ptr<pi_mem_factory> mf = (*it_op).dncast<ge_operand_mem>()->factory_get();
00238                                 
00239                         m2ge_pi_set__type::iterator it_search = mfdeps->find(mf);
00240                                 
00241                         if ( it_search!=mfdeps->end() ) {
00242                                 ge->dependencies_get()->insert(it_search->second->begin(),it_search->second->end());
00243                         }       
00244                 }
00245                 
00246                 operands = ge->operands_output_get();
00247                 
00248                 for(ge_operand_vector__type::iterator it_op = operands->begin(); it_op!=operands->end(); ++it_op) {
00249                         if ( (*it_op)->kind_get()!=ge_operand::MEMORY ) {
00250                                 continue;
00251                         }
00252 
00253                         ptr<pi_mem_factory> mf = (*it_op).dncast<ge_operand_mem>()->factory_get();
00254                                 
00255                         m2ge_pi_set__type::iterator it_search = mfdeps->find(mf);
00256                                 
00257                         if ( it_search!=mfdeps->end() ) {
00258                                 ge->dependencies_get()->insert(it_search->second->begin(),it_search->second->end());
00259                         }       
00260                 }
00261                 
00262                 //Finaly, insert instruction from the second block to the first one.
00263                 prev_instrs->push_back(ge);
00264                 ge->bb_set(bb1);
00265                 ge->dependencies_get()->insert(prev_fsp);
00266                 active_lsp->dependencies_get()->insert(ge);
00267                 
00268         }
00269         
00270         bblog << "Blocks joined (" << bb1->uid_get() << "<-" << bb2->uid_get() << ").\n" << eolog;
00271         
00272         return bb1;
00273 }
00274 
00275 ptr<func_data> bb_finder::get_result() {
00276         return data_get();
00277 }
00278 
00279 end_package(workers);
00280 end_package(backend_v2);
00281 end_package(lestes);
00282 

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