C-Breeze
C Compiler Infrastructure

[ Project home page]
Main Page   Modules   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages  

dummy_reg_alloc.cc

Go to the documentation of this file.
00001 // $Id: dummy_reg_alloc.cc,v 1.7 2003/08/11 17:38:51 abrown Exp $
00002 // ----------------------------------------------------------------------
00003 //
00004 //  C-Breeze
00005 //  C Compiler Framework
00006 // 
00007 //  Copyright (c) 2002 University of Texas at Austin
00008 // 
00009 //  Paul Arthur Navratil
00010 //  Charles Nevill
00011 //  Calvin Lin
00012 // 
00013 //  Permission is hereby granted, free of charge, to any person
00014 //  obtaining a copy of this software and associated documentation
00015 //  files (the "Software"), to deal in the Software without
00016 //  restriction, including without limitation the rights to use, copy,
00017 //  modify, merge, publish, distribute, sublicense, and/or sell copies
00018 //  of the Software, and to permit persons to whom the Software is
00019 //  furnished to do so, subject to the following conditions:
00020 //  
00021 //  The above copyright notice and this permission notice shall be
00022 //  included in all copies or substantial portions of the Software.
00023 //  
00024 //  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
00025 //  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00026 //  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
00027 //  NONINFRINGEMENT.  IN NO EVENT SHALL THE UNIVERSITY OF TEXAS AT
00028 //  AUSTIN BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
00029 //  IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
00030 //  OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
00031 //  THE SOFTWARE.
00032 //
00033 //  We acknowledge the C-to-C Translator from MIT Laboratory for
00034 //  Computer Science for inspiring parts of the C-Breeze design.
00035 //
00036 // ----------------------------------------------------------------------
00037 
00038 #include "c_breeze.h"
00039 #include "dummy_reg_alloc.h"
00040 
00041 // because I'm lazy
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         // setup info for gprs
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                 // make room for it
00069                 if ( num >= (int)_rregsGpr.size() )
00070                         _rregsGpr.resize( num + 1, 0 );
00071 
00072                 // setup info for this one
00073                 rreg_info * rreg = new rreg_info;
00074                 rreg->pInfo = regsGpr[i];
00075                 rreg->reg = CBZ::ArchInfo.get_register( rreg->pInfo );
00076 
00077                 // add this to the list in the right place
00078                 _rregsGpr[ num ] = rreg;
00079         }
00080 
00081         // setup info for fprs
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                 // make room for it
00090                 if ( num >= (int)_rregsFpr.size() )
00091                         _rregsFpr.resize( num + 1, 0 );
00092 
00093                 // setup info for this one
00094                 rreg_info * rreg = new rreg_info;
00095                 rreg->pInfo = regsFpr[i];
00096                 rreg->reg = CBZ::ArchInfo.get_register( rreg->pInfo );
00097 
00098                 // add this to the list in the right place
00099                 _rregsFpr[ num ] = rreg;
00100         }
00101 
00102         // next is zero
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         // sanity check
00120         if ( is_real_reg( vreg ) )
00121                 return NULL;
00122         assert( num >= (int)CBZ::ArchInfo.get_all_regs().size() );
00123 
00124         // make sure array is big enough
00125         if ( num >= (int)_vregs.size() )
00126                 _vregs.resize( num+1, 0 );
00127 
00128         // need to allocate an entry for it?
00129         vreg_info * info = _vregs[num];
00130         if ( ! info )
00131         {
00132                 // add this to the list in the right place
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         // sanity checks
00147         if ( ! is_real_reg( rreg ) )
00148                 return NULL;
00149         assert( num >= 0 && num < (int)CBZ::ArchInfo.get_all_regs().size() );
00150 
00151         // return its info
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         // setup real registers
00165         setup_rregs();
00166 
00167         //
00168         // traverse all of this guy's instructions and replace virtual registers
00169         //      with real registers.
00170         //
00171         // we are assuming that all virtual registers are defined once and used
00172         //      a small number of times, all very close to their definition point.  
00173         //      if these assumptions fail, we will fail to allocate.
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                 // all uses should already have registers
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                 // allocate register for def
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         // make sure we need to fixup
00202         if ( is_real_reg( reg ) )
00203                 return true;
00204 
00205         // get info for this guy - make sure we have a real register for it
00206         vreg_info * info = get_vreg( reg );
00207         if ( ! info->pRealReg || info->reclaimed )
00208         {
00209                 // why is it gone?
00210                 if ( info->reclaimed )
00211                 {
00212                         // it was defined but we alraady had to reuse the real register for something
00213                         //      else, so the value is gone
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                         // it was never defined so we don't know what register it's in
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         // change virtual to real
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         // if this already is real then we're good
00241         if ( is_real_reg( reg ) )
00242                 return true;
00243 
00244         // get info for it
00245         vreg_info * vinfo = get_vreg( reg );
00246         if ( vinfo->pRealReg )
00247         {
00248                 // this already has a real register?  what the heck?
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         // what kind of thing is this?
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         // find the next non-NULL one in the list
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         // allocate this one (reclaim old register if necessary)
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 // acb - 6 May 2003
00295 // is this necessary?
00296 void dummy_reg_alloc_walker::at_unit(unitNode *the_unit, Order ord)
00297 {
00298   // process all defs
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   // allocate regs for this guy
00308   dummy_reg_alloc dra;
00309   dra.allocate( the_proc );
00310 }

Generated on August 27, 2003
Back to the C-Breeze home page