00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038 #include "c_breeze.h"
00039 #include "dummy_reg_alloc.h"
00040
00041
00042 typedef dummy_reg_alloc::vreg_info vreg_info;
00043 typedef dummy_reg_alloc::rreg_info rreg_info;
00044
00045 dummy_reg_alloc::dummy_reg_alloc()
00046 {
00047 _rregsGprCount = 0;
00048 _rregsFprCount = 0;
00049 }
00050
00051 dummy_reg_alloc::~dummy_reg_alloc()
00052 {
00053 }
00054
00055 void
00056 dummy_reg_alloc::setup_rregs()
00057 {
00058 int i, sz;
00059
00060
00061 const arch_info::register_info_list & regsGpr = CBZ::ArchInfo.get_regs_gpr();
00062 _rregsGprCount = (int)regsGpr.size();
00063 _rregsGpr.resize( CBZ::ArchInfo.get_all_regs().size(), 0 );
00064 for ( i = 0; i < _rregsGprCount; ++i )
00065 {
00066 int num = regsGpr[i]->_id;
00067
00068
00069 if ( num >= (int)_rregsGpr.size() )
00070 _rregsGpr.resize( num + 1, 0 );
00071
00072
00073 rreg_info * rreg = new rreg_info;
00074 rreg->pInfo = regsGpr[i];
00075 rreg->reg = CBZ::ArchInfo.get_register( rreg->pInfo );
00076
00077
00078 _rregsGpr[ num ] = rreg;
00079 }
00080
00081
00082 const arch_info::register_info_list & regsFpr = CBZ::ArchInfo.get_regs_fpr();
00083 _rregsFprCount = (int)regsFpr.size();
00084 _rregsFpr.resize( CBZ::ArchInfo.get_all_regs().size(), 0 );
00085 for ( i = 0; i < _rregsFprCount; ++i )
00086 {
00087 int num = regsFpr[i]->_id;
00088
00089
00090 if ( num >= (int)_rregsFpr.size() )
00091 _rregsFpr.resize( num + 1, 0 );
00092
00093
00094 rreg_info * rreg = new rreg_info;
00095 rreg->pInfo = regsFpr[i];
00096 rreg->reg = CBZ::ArchInfo.get_register( rreg->pInfo );
00097
00098
00099 _rregsFpr[ num ] = rreg;
00100 }
00101
00102
00103 _lastRealRegFixed = -1;
00104 _lastRealRegFloat = -1;
00105 }
00106
00107 inline bool
00108 dummy_reg_alloc::is_real_reg( const Register & reg )
00109 {
00110 int num = reg.num();
00111 return ( num >= 0 && num < (int)CBZ::ArchInfo.get_all_regs().size() );
00112 }
00113
00114 vreg_info*
00115 dummy_reg_alloc::get_vreg( const Register & vreg )
00116 {
00117 int num = vreg.num();
00118
00119
00120 if ( is_real_reg( vreg ) )
00121 return NULL;
00122 assert( num >= (int)CBZ::ArchInfo.get_all_regs().size() );
00123
00124
00125 if ( num >= (int)_vregs.size() )
00126 _vregs.resize( num+1, 0 );
00127
00128
00129 vreg_info * info = _vregs[num];
00130 if ( ! info )
00131 {
00132
00133 info = new vreg_info;
00134 info->reg = vreg;
00135 _vregs[num] = info;
00136 }
00137
00138 return info;
00139 }
00140
00141 rreg_info*
00142 dummy_reg_alloc::get_rreg( const Register & rreg )
00143 {
00144 int num = rreg.num();
00145
00146
00147 if ( ! is_real_reg( rreg ) )
00148 return NULL;
00149 assert( num >= 0 && num < (int)CBZ::ArchInfo.get_all_regs().size() );
00150
00151
00152 switch ( rreg.type() )
00153 {
00154 case reg_gpr: return _rregsGpr[num];
00155 case reg_fpr: return _rregsFpr[num];
00156 default: assert( false ); return NULL;
00157 }
00158 }
00159
00160
00161 void
00162 dummy_reg_alloc::allocate(procNode *proc)
00163 {
00164
00165 setup_rregs();
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176 instruction_list & insts = proc->instructions();
00177 instruction_list_p it = insts.begin();
00178 for ( ; it != insts.end(); ++it )
00179 {
00180 LirInst & inst = **it;
00181
00182
00183 if ( inst.has_opnd1() && ! fix_allocated_virtual( inst.opnd1, inst ) )
00184 return;
00185 if ( inst.has_opnd2() && ! fix_allocated_virtual( inst.opnd2._reg, inst ) )
00186 return;
00187 if ( inst.has_base() && ! fix_allocated_virtual( inst.memBase, inst ) )
00188 return;
00189 if ( inst.has_offset() && ! fix_allocated_virtual( inst.memOffset._reg, inst ) )
00190 return;
00191
00192
00193 if ( inst.has_dest() && ! allocate_real_for_virtual( inst.dest, inst.dest_contents, inst ) )
00194 return;
00195 }
00196 }
00197
00198 bool
00199 dummy_reg_alloc::fix_allocated_virtual( Register & reg, const LirInst & inst )
00200 {
00201
00202 if ( is_real_reg( reg ) )
00203 return true;
00204
00205
00206 vreg_info * info = get_vreg( reg );
00207 if ( ! info->pRealReg || info->reclaimed )
00208 {
00209
00210 if ( info->reclaimed )
00211 {
00212
00213
00214 cerr << "Register allocation error:" << endl <<
00215 "Instruction: " << endl <<
00216 " " << inst << endl <<
00217 "uses virtual register whose real register " << endl <<
00218 " " << info->pRealReg->reg.to_string() <<
00219 "was reclaimed because of register pressure." << endl;
00220 }
00221 else
00222 {
00223
00224 cerr << "Register allocation error:" << endl <<
00225 "Instruction: " << endl <<
00226 " " << inst << endl <<
00227 "uses register that was never defined." << endl;
00228 }
00229 return false;
00230 }
00231
00232
00233 reg = info->pRealReg->reg;
00234 return true;
00235 }
00236
00237 bool
00238 dummy_reg_alloc::allocate_real_for_virtual( Register & reg, declNode * pDecl, const LirInst & inst )
00239 {
00240
00241 if ( is_real_reg( reg ) )
00242 return true;
00243
00244
00245 vreg_info * vinfo = get_vreg( reg );
00246 if ( vinfo->pRealReg )
00247 {
00248
00249 cerr << "Register allocation error:" << endl <<
00250 "Virtual register defined by instruction: " << endl <<
00251 " " << inst << endl <<
00252 "already has a real register...?" << endl;
00253 return false;
00254 }
00255
00256 assert( pDecl > DATA_CONTENTS__SPECIAL );
00257
00258
00259 typeNode * the_type = pDecl->type();
00260 bool isfloat = the_type->is_float();
00261 if ( (! isfloat && _rregsGprCount < 1) ||
00262 (isfloat && _rregsFprCount < 1) )
00263 CBZFAIL(("Can't allocate register for var because "
00264 "architecture has no registers for data of this type."));
00265
00266
00267 int & last = isfloat ? _lastRealRegFloat : _lastRealRegFixed;
00268 vector<rreg_info*> & regs = isfloat ? _rregsFpr : _rregsGpr;
00269 int next = last;
00270 do
00271 {
00272 next++;
00273 if ( next >= (int)regs.size() )
00274 next = 0;
00275 } while ( regs[next] == 0 && next != last );
00276 assert( next != last );
00277 last = next;
00278
00279
00280 rreg_info * rinfo = regs[next];
00281 if ( rinfo->pVirtualReg )
00282 rinfo->pVirtualReg->reclaimed = true;
00283 rinfo->pVirtualReg = vinfo;
00284 vinfo->pRealReg = rinfo;
00285 reg = rinfo->reg;
00286
00287 return true;
00288 }
00289
00290 dummy_reg_alloc_walker::dummy_reg_alloc_walker() : Walker( Preorder, NodeOnly )
00291 {
00292 }
00293
00294
00295
00296 void dummy_reg_alloc_walker::at_unit(unitNode *the_unit, Order ord)
00297 {
00298
00299 const def_list & defs = the_unit->defs();
00300 def_list::const_iterator it = defs.begin();
00301 while ( it != defs.end() )
00302 (*(it++))->walk( *this );
00303 }
00304
00305 void dummy_reg_alloc_walker::at_proc(procNode *the_proc, Order ord)
00306 {
00307
00308 dummy_reg_alloc dra;
00309 dra.allocate( the_proc );
00310 }