memory_inliner.cc

Go to the documentation of this file.
00001 #include <lestes/backend_v2/intercode/ge.g.hh>
00002 #include <lestes/backend_v2/structs/func_data.g.hh>
00003 #include <lestes/backend_v2/workers/memory_inliner.g.hh>
00004 #include <lestes/md/literals/literal_info_base.g.hh>
00005 #include <lestes/md/instructions/tm_instr.g.hh>
00006 #include <lestes/std/list.hh>
00007 #include <lestes/std/map.hh>
00008 #include <lestes/std/vector.hh>
00009 
00010 package(lestes);
00011 package(backend_v2);
00012 package(workers);
00013 
00014 using namespace ::lestes::backend_v2::structs;
00015 using namespace ::lestes::backend_v2::intercode;
00016 using namespace ::lestes::md::instructions;
00017 using namespace ::lestes::md::literals;
00018 
00019 typedef list< srp<ge_pi> > ge_pi_list__type;
00020 typedef vector< srp<ge_operand> > ge_op_vector__type;
00021 typedef map< srp<ge_operand_reg>, srp<ge_operand_mem> > reg2mem__type;
00022 typedef set<ulint> id_set__type;
00023 
00024 /*!
00025         \brief Performs inlining of memory operands.
00026 */
00027 void memory_inliner::process() {
00028         
00029         ptr<reg2mem__type> reg2mem = reg2mem__type::create();
00030         
00031         ptr<ge_pi_list__type> body = data_get()->ge_body_get(); 
00032 
00033         for(ge_pi_list__type::iterator it = body->begin(); it!=body->end(); ++it) {
00034                 ptr<ge_pi> ge = *it;
00035                 ptr<tm_instr_base> tm = ge->instruction_get();
00036                 
00037                 if ( !tm ) {
00038                         continue;
00039                 }
00040                 
00041                 if ( tm->is_load() 
00042                         && ge->operands_input_get()->front()->kind_get()==ge_operand::MEMORY
00043                         && ge->operands_output_get()->front()->kind_get()==ge_operand::REGISTER ) {
00044                                 //The instruction is load instruction that loads memory operand to register.
00045                                 ptr<ge_operand_mem> mem = ge->operands_input_get()->front().dncast<ge_operand_mem>();
00046                                 
00047                                 //Note: Do not inline pi_mf_ptr_deref.
00048                                 if ( mem->factory_get() && mem->factory_get()->kind_get()!=pi_mem_factory::MF_PTR_DEREF ) {
00049                                         (*reg2mem)[ge->operands_output_get()->front().dncast<ge_operand_reg>()] = mem;
00050                                 }
00051                 } else if ( tm->versions_get() ) {
00052                         //The instruction has exchangeable tm_instr version available.
00053                         //Go through input operands and search for a register operand that can be echanged for its immediate source.
00054                         ptr<ge_op_vector__type> operands = ge->operands_input_get();
00055                         for(ge_op_vector__type::iterator it_op = operands->begin(); it_op!=operands->end();) {
00056                                 if ( (*it_op)->kind_get()!=ge_operand::REGISTER ) {
00057                                         ++it_op;
00058                                         continue;
00059                                 }
00060                                 
00061                                 ptr<ge_operand_reg> reg = (*it_op).dncast<ge_operand_reg>();
00062                                 
00063                                 reg2mem__type::iterator it_mem = reg2mem->find(reg);
00064                                 
00065                                 if ( it_mem==reg2mem->end() ) {
00066                                         ++it_op;
00067                                         continue;
00068                                 }
00069                                 
00070                                 //Ok, the immediate source has been found.
00071                                 ptr<ge_operand_mem> mem = it_mem->second;
00072                                 
00073                                 //Exchange immediate after register.
00074                                 *it_op = mem;
00075                                 
00076                                 //Try to find compatible tm_instr version that is compatible with this operand.
00077                                 if ( find_compatible_version(ge) ) {
00078                                         //Compatible version exists and it has been set to the ge_pi. 
00079                                         //Remove dependence on the origin of the register (load of immediate).
00080                                         ge->dependencies_get()->erase(reg->origin_get());
00081                                         
00082                                         //Restart search for exchangeable operans.
00083                                         it_op = operands->begin();
00084                                 } else {
00085                                         //Restore operands.
00086                                         *it_op = reg;
00087                                         ++it_op;
00088                                 }
00089                         }
00090                 }
00091         }
00092 }
00093 
00094 /*!
00095         \brief Finds a target machine instruction description that is compatible with given pseudoinstruction.
00096         
00097         \param ge The pseudoinstruction.
00098 */
00099 bool memory_inliner::find_compatible_version(ptr<ge_pi> ge) {
00100         ptr<tm_instr_base> backup = ge->instruction_get();
00101         ptr<id_set__type> versions = backup->versions_get();
00102         
00103         for(id_set__type::iterator it = versions->begin(); it!=versions->end();++it) {
00104                 ge->instruction_set(tm_instr::instance(*it));
00105                 
00106                 if ( ge->validate() ) {
00107                         //Compatible version found.
00108                         return true;
00109                 }
00110         }
00111         
00112         ge->instruction_set(backup);
00113         return false;
00114 }
00115 
00116 /*!
00117         \brief Returns data of the currently processed function with immediates inlined whereever possible.
00118 */
00119 ptr<func_data> memory_inliner::get_result() {
00120         return data_get();
00121 }
00122 
00123 
00124 
00125 end_package(workers);
00126 end_package(backend_v2);
00127 end_package(lestes);
00128 

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