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  

briggs_reg_alloc.cc

Go to the documentation of this file.
00001 // $Id: briggs_reg_alloc.cc,v 1.16 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 "briggs_reg_alloc.h"
00040 #include <limits>
00041 #include "LIR.h"
00042 #include "math.h"
00043 #include "instruction.h"
00044 #include "LIR.h"
00045 #include "hash_set_ex.h"
00046 #include "lir_flow_walker.h"
00047 
00048 const int
00049   ListRecord::color_none =
00050   INT_MIN;
00051 
00052 bool
00053 Symbol::operator == (const Symbol & rhs) const
00054 {
00055   // must have same type
00056   if (_type != rhs._type)
00057     return false;
00058 
00059   // compare the right thing
00060   switch (_type)
00061     {
00062     case sym_id:
00063       return (rhs._id == _id);  // FIXME: can we use pointer equivalence
00064                                 // here?
00065     case sym_reg:
00066       return (rhs._reg == _reg);
00067     case sym_const:
00068       return _const.is_equal_to (rhs._const);
00069     default:
00070       assert (false);
00071       return false;
00072     }
00073 }
00074 
00075 typeNode *
00076 Symbol::getLirVt () const
00077 {
00078   // compare the right thing
00079   switch (_type)
00080     {
00081     case sym_id:
00082       assert (_id);
00083       return _id->type();
00084 
00085     case sym_reg:
00086 
00087       // what kind of register is it?
00088       if (_reg.type () == reg_gpr ||
00089           _reg.type () == reg_frame_ptr || _reg.type () == reg_stack_ptr)
00090         {
00091           // it's a gpr
00092           return CBZ::ArchInfo.get_reg_data_type_gpr ();
00093         }
00094       else if (_reg.type () == reg_fpr)
00095         {
00096           // it's an fpr
00097           return CBZ::ArchInfo.get_reg_data_type_fpr ();
00098         }
00099       else
00100         {
00101           // this is an invalid register.
00102           assert (false);
00103           return NULL;
00104         }
00105 
00106     case sym_const:
00107       return new primNode(typeNode::NONE, _const.basic ());
00108 
00109     default:
00110       assert (false);
00111       return NULL;
00112     }
00113 }
00114 
00115 bool
00116 WebRecord::intersectUses (DUChainUses & u)
00117 {
00118   for (DUChainUses_p p = u.begin (); p != u.end (); ++p)
00119     {
00120       for (DUChainUses_p q = uses.begin (); q != uses.end (); ++q)
00121         {
00122           if (*p == *q)
00123             return true;
00124         }
00125     }
00126 
00127   // pnav -- use below if pointer equivalence fails from hash_multiset.find()
00128   // I'm assuming that the def-use chain method doesn't clone nodes before
00129   // putting them in chains.
00130 //                      for (DUChainUses_p q = uses->begin(); q != uses->end(); ++q) {
00131 //                              if (**p == **q) { // pnav -- get to the actual node object to test equality
00132 //              return true;
00133 //                              }
00134 //                      }
00135 
00136   return false;
00137 }
00138 
00139 void
00140 WebRecord::unionDefs (DUChainDefs & d)
00141 {
00142   for (DUChainUses_p p = d.begin (); p != d.end (); ++p)
00143     {
00144       defs.insert (defs.end (), *p);
00145     }
00146 }
00147 
00148 void
00149 WebRecord::unionUses (DUChainUses & u)
00150 {
00151   for (DUChainUses_p p = u.begin (); p != u.end (); ++p)
00152     {
00153       uses.insert (uses.end (), *p);
00154     }
00155 }
00156 
00157 void
00158 ListRecord::addAdjacentNode (int reg)
00159 {
00160   assert (reg != webNum);
00161 
00162   // add to our list
00163   adjNodes.insert (reg);
00164   num_ints++;
00165 }
00166 
00167 void
00168 ListRecord::removeAdjacentNode (int reg)
00169 {
00170   bool found = false;
00171 
00172   // remove any instances of reg from our adjacent list
00173   int_set_p it = adjNodes.find (reg);
00174   assert (it != adjNodes.end ());
00175 
00176   // remove from our set
00177   adjNodes.erase (it);
00178   num_ints--;
00179 
00180   // remember that we were adjacent to this
00181   removeAdj.insert (reg);
00182 }
00183 
00184 void
00185 ListRecord::removeAllAdjacencies ()
00186 {
00187   // move all remaining into removed set
00188   removeAdj.insert (adjNodes.begin (), adjNodes.end ());
00189   adjNodes.clear ();
00190   num_ints = 0;
00191 }
00192 
00193 const float
00194   briggs_reg_alloc::useWt =
00195   1.0;
00196 const float
00197   briggs_reg_alloc::copyWt =
00198   1.0;
00199 const float
00200   briggs_reg_alloc::defWt =
00201   1.0;
00202 
00203 template < class T > set < T > *briggs_reg_alloc::copySet (set < T > *s)
00204 {
00205   set < T > *retval = new set < T > ();
00206   for (typename set < T >::iterator p = s->begin (); p != s->end (); ++p)
00207     {
00208       retval->insert (*p);
00209     }
00210 
00211   return retval;
00212 }
00213 
00214 
00215 bool
00216 briggs_reg_alloc::interfere (WebRecord * wr, int reg)
00217 {
00218   // everything conflicts with stack ptr and frame ptr - these can never be
00219   // allocated for any other use
00220   if (CBZ::ArchInfo.get_reg_fp ()->_id == reg ||
00221       CBZ::ArchInfo.get_reg_sp ()->_id == reg)
00222     return true;
00223 
00224   // this had better be a real register - if not, it interferes
00225   const arch_info::register_info_list & allregs =
00226     CBZ::ArchInfo.get_all_regs ();
00227   if (reg < 0 || reg >= (int) allregs.size ())
00228     return true;
00229   const arch_info::register_info * regInfo = allregs[reg];
00230   if (!regInfo)
00231     return true;
00232 
00233   // find out the type of this symbol
00234   const Symbol & sym = wr->getSym ();
00235   typeNode * the_type = sym.getLirVt ();
00236 
00237   // if the types don't match, we have interference 
00238   // i.e. if it's a float, it can't go in gpr, etc.
00239   if (regInfo->_type == reg_fpr && !the_type->is_float())
00240     return true;
00241   if ( regInfo->_type == reg_gpr && !( the_type->is_integer() 
00242                                        || the_type->is_pointer() ) )
00243     return true;
00244 
00245   // /////////////////////////////////////////////////////////////////////
00246   // here's the nasty part - it conflicts with a return value register
00247   // if it's live across a function call instruction that writes that 
00248   // register.  for this we will use liveness info computed in makeWebs
00249 
00250   unsigned int rvFixedId = (unsigned int) -1;
00251   if (CBZ::ArchInfo.get_reg_retval_fixed ())
00252     rvFixedId = CBZ::ArchInfo.get_reg_retval_fixed ()->_id;
00253   unsigned int rvFloatId = (unsigned int) -1;
00254   if (CBZ::ArchInfo.get_reg_retval_float ())
00255     rvFloatId = CBZ::ArchInfo.get_reg_retval_float ()->_id;
00256 
00257   if (rvFixedId == reg || rvFloatId == reg)
00258     {
00259       instruction_list & insts = proc->instructions ();
00260 
00261       // for all call instructions, find out if this web's symreg is live
00262       unsigned int symRegNum = wr->getReg ().num ();
00263       instruction_list_p it = insts.begin ();
00264       LirInst *pInst;
00265       for (; it != insts.end (); ++it)
00266         {
00267           // get instrution and see if it's a call
00268           pInst = *it;
00269           if (pInst->instruction != mn_Call)
00270             continue;
00271 
00272           // see what the actual return register will be - if return value 
00273           // will not be in this register, there is no confict here
00274           typeNode * the_type = pInst->nodeExtra->type();
00275           if ( ( the_type->is_integer() || the_type->is_pointer() )
00276                && rvFixedId != reg )
00277             continue;
00278           if ( the_type->is_float() && rvFloatId != reg )
00279             continue;
00280 
00281           // is symreg live at this call? if so it cannot go in return value
00282           // register
00283           reg_id_set live = liveRegs[pInst];
00284           if ((live & symRegNum).size () != 0)
00285             return true;
00286         }
00287     }
00288 
00289   return false;
00290 }
00291 
00292 bool
00293 briggs_reg_alloc::liveAt (WebRecord * wr, DUChainDef def)
00294 {
00295   // just see if the symbolic register for this web is live at
00296   // the definition point in question.
00297   const reg_id_set & live = liveRegs[def];
00298   return (live.find (wr->getReg ().num ()) != live.end ());
00299 }
00300 
00301 bool
00302 briggs_reg_alloc::nonStore (int reg_k, int reg_l, instruction_list_p instr)
00303 {
00304   // look at all instructions after the starting instruction to end of block
00305   instruction_list & insts = proc->instructions ();
00306   for (++instr; instr != insts.end (); ++instr)
00307     {
00308 
00309       // instruction of interest
00310       LirInst *inst = *instr;
00311 
00312       // does it have a destination?
00313       if (!inst->has_dest (true))
00314         continue;
00315 
00316       // does it write to k or l?
00317       if (inst->dest.num () == reg_k || inst->dest.num () == reg_l)
00318         return false;
00319     }
00320 
00321   // apparently neither was stored to...
00322   return true;
00323 }
00324 
00325 void
00326 briggs_reg_alloc::deleteInstr (instruction_list_p it)
00327 {
00328   // just nuke this from the instruction list (and from its block)
00329   assert (proc);
00330   LirInst *inst = *it;
00331   if (inst->block)
00332     inst->block->remove_inst (inst);
00333   proc->instructions ().erase (it);
00334 }
00335 
00336 int
00337 briggs_reg_alloc::depth (instruction_list_p it)
00338 {
00339   // see if we have a block for it
00340   LirInst *inst = *it;
00341   if (!inst->block)
00342     {
00343       cerr <<
00344         "WARNING: LIR block flow info is missing - loop depth defaulted to 0."
00345         << endl;
00346       return 0;
00347     }
00348 
00349   // return depth of block
00350   return inst->block->_depth;
00351 }
00352 
00353 void
00354 briggs_reg_alloc::makeDuChains (sduList & DuChains)
00355 {
00356   instruction_list & insts = proc->instructions ();
00357   instruction_list_p ilp;
00358 
00359   // handy typedefs
00360   typedef hash_set_ex < DUChainDef > def_set;
00361   typedef map < Register, def_set > def_map;
00362   typedef hash_set_ex < DuChainUse > use_set;
00363   typedef map < Register, use_set > use_map;
00364 
00365   // map to hold current def and uses for each register
00366   reg_set current_regs;
00367   def_map defs_all;
00368   use_map uses_all;
00369 
00370   // generate postorder ordering of instructions, reverse to get reverse
00371   // postorder
00372   instruction_list worklist = insts;
00373   lir_flow_walker::getInstructionFlowInfo (insts);
00374   lir_flow_walker::getInstructionsPostorder (insts, insts.begin (), worklist);
00375   worklist.reverse ();
00376 
00377   // for debugging - trace out instructions in reverse postorder
00378   // change 0 to 1 to add this code
00379 #if 0
00380   {
00381     cout << "DEBUG:" << endl;
00382     cout << "Reverse Postorder:" << endl;
00383     instruction_list_p it = rpo.begin ();
00384     for (; it != rpo.end (); ++it)
00385       cout << **it << endl;
00386     cout << "END DEBUG" << endl;
00387   }
00388 #endif
00389 
00390   // go through and find defs and uses
00391   for (ilp = worklist.begin (); ilp != worklist.end (); ++ilp)
00392     {
00393       LirInst *inst = *ilp;
00394 
00395       // add uses for this instruction
00396       if (inst->has_opnd1 ())
00397         uses_all[inst->opnd1].insert (inst);
00398       if (inst->has_opnd2 ())
00399         uses_all[inst->opnd2._reg].insert (inst);
00400       if (inst->has_base ())
00401         uses_all[inst->memBase].insert (inst);
00402       if (inst->has_offset ())
00403         uses_all[inst->memOffset._reg].insert (inst);
00404 
00405       // do we define anything?
00406       if (inst->has_dest (true))
00407         defs_all[inst->get_dest ()].insert (inst);
00408     }
00409 
00410   // we don't care about defs or uses of any real registers - they are not
00411   // candidates for allocation
00412   for (int i = 0; i < num_regs; ++i)
00413     {
00414       Register reg;
00415       CBZ::ArchInfo.get_reg_by_index (i, reg);
00416       defs_all.erase (reg);
00417       uses_all.erase (reg);
00418     }
00419 
00420   // map from register to instructions that def that register
00421   typedef map < unsigned int, hash_set_ex < DUChainDef > >reg_to_def_map;
00422 
00423   // map from instruction to defs that reach that instruction
00424   typedef map < LirInst *, reg_to_def_map > reach_map;
00425 
00426   // do reaching definitions analysis over all instructions, in reverse
00427   // postorder
00428   reach_map reach;
00429   while (worklist.size () != 0)
00430     {
00431       LirInst *inst = worklist.front ();
00432       worklist.pop_front ();
00433 
00434       // figure out what reaches from predecessors
00435       reg_to_def_map thisReach;
00436       instruction_set_p pit = inst->preds.begin ();
00437       for (; pit != inst->preds.end (); ++pit)
00438         {
00439           // what reaches this predecessor?
00440           reg_to_def_map & pdefs = reach[*pit];
00441           reg_to_def_map::iterator regit = pdefs.begin ();
00442           for (; regit != pdefs.end (); ++regit)
00443             thisReach[regit->first] |= regit->second;
00444         }
00445 
00446       // adjust for what we define
00447       Register defReg;
00448       if (inst->has_dest (true))
00449         {
00450           hash_set_ex < DUChainDef > &defs =
00451             thisReach[inst->get_dest ().num ()];
00452 
00453           // kill any previous and set ours as the only one
00454           defs.clear ();
00455           defs.insert (inst);
00456         }
00457 
00458       // has this changed?
00459       if (thisReach != reach[inst])
00460         {
00461           // update new reaching info for this instruction
00462           reach[inst] = thisReach;
00463 
00464           // add all successors back to worklist
00465           instruction_set_p succit = inst->succs.begin ();
00466           for (; succit != inst->succs.end (); ++succit)
00467             if (!cbz_util::list_find (worklist, *succit))
00468               worklist.push_back (*succit);
00469         }
00470     }
00471 
00472   // now build def-use chains by finding which defs reach which uses
00473   def_map::iterator dmit = defs_all.begin ();
00474   for (; dmit != defs_all.end (); ++dmit)
00475     {
00476       Register reg = dmit->first;
00477 
00478       // iterate over each def of this register
00479       def_set & defs = dmit->second;
00480       def_set::iterator def = defs.begin ();
00481       for (; def != defs.end (); ++def)
00482         {
00483           // a new sdu for this thing
00484           Symbol *sym = NULL;
00485           if ((*def)->dest_contents)
00486             sym = new Symbol ((*def)->dest_contents);
00487           else
00488             sym = new Symbol (reg);
00489           sdu *defuse = new sdu (*sym, *def);
00490           DuChains.push_back (defuse);
00491           delete sym;
00492           DUChainUses & uses = defuse->getUses ();
00493 
00494           // find all uses that this reaches
00495           use_set & possibles = uses_all[reg];
00496           use_set::iterator pit = possibles.begin ();
00497           for (; pit != possibles.end (); ++pit)
00498             {
00499               // is this def live at this use?
00500               hash_set_ex < DUChainDef > &reach_defs =
00501                 reach[*pit][reg.num ()];
00502               if (reach_defs.find (*def) != reach_defs.end ())
00503                 uses.push_back (*pit);
00504             }
00505         }
00506     }
00507 
00508   // kill defs from decl nodes that were unused
00509   sduList::iterator it = DuChains.begin ();
00510   for (; it != DuChains.end (); ++it)
00511     {
00512       // if this def is a decl node, and it does not have any uses, throw it
00513       // away
00514       sdu *du = *it;
00515       if (du->getDef ()->instruction == mn_DeclLocal
00516           && du->getUses ().size () == 0)
00517         DuChains.erase (it--);
00518     }
00519 
00520   // debug - print out def-use chains
00521 #if 0
00522   {
00523     sduList::iterator it = DuChains.begin ();
00524     for (; it != DuChains.end (); ++it)
00525       {
00526         sdu *du = *it;
00527         cout << "DefUse:" << endl;
00528         cout << "  Def: " << *(du->getDef ()) << endl;
00529         cout << "  Uses: " << endl;
00530         DUChainUses::iterator uses = du->getUses ().begin ();
00531         for (; uses != du->getUses ().end (); ++uses)
00532           cout << "    " << **uses << endl;
00533         cout << endl;
00534       }
00535   }
00536 #endif
00537 
00538 }
00539 
00540 void
00541 briggs_reg_alloc::makeWebs (sduList & DuChains)
00542 {
00543   // make a semi-web for each du chain
00544   // also keep track of largest register # currently in use
00545   num_webs = 0;
00546   WRSet *Webs = new WRSet ();
00547   num_webs = num_regs;
00548   for (sduList_p p = DuChains.begin (); p != DuChains.end (); ++p)
00549     {
00550 
00551       sdu *chain = *p;
00552 
00553       // figure out which virtual register is being used for this duchain
00554       Register webreg = chain->getDef ()->get_dest ();
00555       if (!webreg.isValid () && chain->getSymbol ()._type == Symbol::sym_reg)
00556         webreg = chain->getSymbol ()._reg;
00557       assert (webreg.isValid ());
00558       if (num_webs < (int) webreg.num ())
00559         num_webs = webreg.num ();
00560 
00561       // make a web for this du chain
00562       WebRecord *wr = new WebRecord (chain->getSymbol (), webreg);
00563       wr->getDefs ().push_back (chain->getDef ());
00564       wr->getUses () = chain->getUses ();
00565       Webs->insert (wr);
00566     }
00567 
00568   // merge semi-webs into webs
00569   WRSet *Tmp1, *Tmp2;
00570   WebRecord *web1, *web2;
00571   bool changed;
00572   do
00573     {
00574       changed = false;
00575       Tmp1 = copySet (Webs);
00576 
00577       while (!Tmp1->empty ())
00578         {
00579           web1 = *(Tmp1->begin ());
00580           Tmp1->erase (web1);
00581           Tmp2 = copySet (Webs);
00582           Tmp2->erase (web1);
00583 
00584           while (!Tmp2->empty ())
00585             {
00586               web2 = *(Tmp2->begin ());
00587               Tmp2->erase (web2);
00588 
00589               // do these two intersect?
00590               if ((web1->getSym () == web2->getSym ())
00591                   && web1->intersectUses (web2->getUses ()))
00592                 {
00593                   assert (web1 != web2);
00594                   assert (web1->getReg () == web2->getReg ());
00595 
00596                   // union web2 into web1
00597                   web1->unionDefs (web2->getDefs ());
00598                   web1->unionUses (web2->getUses ());
00599 
00600                   // kill this web
00601                   Webs->erase (web2);
00602                   Tmp1->erase (web2);
00603                   Tmp2->erase (web2);
00604                   changed = true;
00605                 }
00606             }
00607         }
00608 
00609     }
00610   while (changed);
00611 
00612   // give each web a unique symbolic register
00613   set < unsigned int >usedRegs;
00614   unsigned int nextreg = num_regs + 1;
00615   for (WRSet_p w = Webs->begin (); w != Webs->end (); ++w)
00616     {
00617 
00618       // this web's new register 
00619       Register newReg ((*w)->getReg ());
00620       newReg = nextreg++;
00621 
00622       // fix it to match
00623       changeWebRegister (*w, newReg);
00624     }
00625 
00626   // compute total number of webs
00627   num_webs = nextreg;
00628 
00629   // kill old symbolic register info
00630   Symreg.clear ();
00631   Symreg.resize (num_webs);
00632 
00633   // setup info for symbolic registers
00634   for (int i = 0; i < num_regs; i++)
00635     {
00636       Register reg;
00637       CBZ::ArchInfo.get_reg_by_index (i, reg);
00638       WebRecord *wr = new WebRecord (reg, reg);
00639       Symreg[i] = wr;
00640     }
00641   for (WRSet_p p = Webs->begin (); p != Webs->end (); ++p)
00642     {
00643       // add to symregs
00644       int num = (*p)->getReg ().num ();
00645       assert (num >= 0 && num < (int) Symreg.size ());
00646       Symreg[num] = *p;
00647     }
00648 
00649   // print out all of the instructions
00650 #if 0
00651   {
00652     cout << "Instruction listing after makeWebs:" << endl;
00653     instruction_list::const_iterator it = proc->instructions ().begin ();
00654     int num = 0;
00655     while (it != proc->instructions ().end ())
00656       cout << num++ << " " << **(it++) << endl;
00657     cout << endl << endl;
00658   }
00659 #endif
00660 
00661 #if 0
00662   {
00663     cout << "Color assignments:" << endl;
00664     for (WRSet_p p = Webs->begin (); p != Webs->end (); ++p)
00665       {
00666         cout << "  Color: " << (*p)->getReg ().to_string () << endl;
00667         DUChainDefs & defs = (*p)->getDefs ();
00668         DUChainDefs::iterator it = defs.begin ();
00669         for (; it != defs.end (); ++it)
00670           cout << "    Def At: " << **it << endl;
00671       }
00672     cout << endl << endl;
00673   }
00674 #endif
00675 
00676 
00677 }
00678 
00679 void
00680 briggs_reg_alloc::buildAdjMatrix ()
00681 {
00682   int size = num_webs;
00683   int i, j;
00684 
00685   adjMatrix.clear ();
00686 
00687   // recompute liveness info
00688   lir_flow_walker::computeRegisterLiveness (proc->instructions (), liveRegs);
00689 
00690   // pnav -- this matrix is oversized. Needs only be a triangluar matrix
00691   // alg will only use bottom half, but we're wasting half the bits.
00692   adjMatrix.resize (size);
00693   for (i = 0; i < size; i++)
00694     adjMatrix[i].resize (size);
00695 
00696   for (i = 0; i < size; i++)
00697     {
00698       for (j = 0; j < size; j++)
00699         {
00700           adjMatrix[i][j] = false;
00701         }
00702     }
00703 
00704   for (i = 1; i < num_regs; i++)
00705     {
00706       for (j = 0; j < i; j++)
00707         {
00708           adjMatrix[i][j] = true;
00709         }
00710     }
00711 
00712   for (i = num_regs; i < num_webs; i++)
00713     {
00714       if (!Symreg[i])
00715         continue;
00716 
00717       // determine if web in Symreg[i] interferes with real reg j
00718       for (j = 0; j < num_regs; j++)
00719         {
00720           if (interfere (Symreg[i], j))
00721             adjMatrix[i][j] = true;
00722         }
00723 
00724       // determine whether or not 2 symregs interfere
00725       for (j = num_regs; j < num_webs; j++)
00726         {
00727           if (!Symreg[j] || i == j)
00728             continue;
00729 
00730           // determine which webs interfere
00731           DUChainDefs & defs = Symreg[i]->getDefs ();
00732           for (DUChainDefs_p p = defs.begin (); p != defs.end (); ++p)
00733             {
00734               if (liveAt (Symreg[j], *p))
00735                 adjMatrix[max (i, j)][min (i, j)] = true;
00736             }
00737         }
00738     }
00739 
00740 #if 0
00741   {
00742     unsigned int rfp = CBZ::ArchInfo.get_reg_fp ()->_id;
00743     unsigned int rsp = CBZ::ArchInfo.get_reg_sp ()->_id;
00744 
00745     // print out adjacency lists
00746     cout << "Interference graph:" << endl;
00747     for (i = num_regs; i < num_webs; ++i)
00748       for (j = 0; j < i; ++j)
00749         {
00750           if (i == rfp || i == rsp || j == rfp || j == rsp)
00751             continue;
00752 
00753           Register r1 (i, reg_unknown);
00754           Register r2 (j, reg_unknown);
00755           cout << r1.to_string () << "<->" << r2.to_string () << " : ";
00756           cout << (adjMatrix[i][j] ? "bad" : "ok") << endl;
00757         }
00758   }
00759 #endif
00760 
00761 }
00762 
00763 
00764 bool
00765 briggs_reg_alloc::coalesceRegisters ()
00766 {
00767   int k, l, p;
00768 
00769   instruction_list & insts = proc->instructions ();
00770   instruction_list_p it = insts.begin ();
00771   bool changed = false;
00772   for (; it != insts.end (); ++it)
00773     {
00774 
00775       // instruction of interest
00776       LirInst *inst = *it;
00777 
00778       // if this instruction is a coalescable copy (K <- L)
00779       // adjust assignments to its source to assign to its target
00780       if (inst->instruction == mn_Move && isSymReg (inst->opnd1))
00781         {
00782           k = inst->dest.num ();
00783           l = inst->opnd1.num ();
00784 #ifdef _DEBUG
00785           cout << "Coalescing " << l << " into " << k << endl;
00786 #endif
00787           if (!adjMatrix[max (k, l)][min (k, l)] || nonStore (k, l, it))
00788             {
00789 
00790               // remove the copy instruction (also adjust loop var)
00791               Symreg[l]->getDefs ().remove (*it);
00792               deleteInstr (it--);
00793 
00794               // change the L web to match the K web
00795               changeWebRegister (Symreg[l], Symreg[k]->getReg ());
00796 
00797               // combine Symregs
00798               Symreg[k]->unionDefs (Symreg[l]->getDefs ());
00799               Symreg[k]->unionUses (Symreg[l]->getUses ());
00800 
00801               // adjust adjacency matrix to reflect removal of the copy
00802               Symreg[l] = NULL;
00803               for (p = 0; p < num_webs; p++)
00804                 if (adjMatrix[max (p, l)][min (p, l)])
00805                   adjMatrix[max (p, k)][min (p, k)] = true;
00806 
00807               // we changed things
00808               changed = true;
00809             }
00810         }
00811     }
00812 
00813   return changed;
00814 }
00815 
00816 
00817 void
00818 briggs_reg_alloc::buildAdjLists ()
00819 {
00820   int i, j;
00821 
00822   adjLists.clear ();
00823 
00824   // initialize adjacency lists
00825   // infinite spill cost for 'real' registers
00826   for (i = 0; i < num_regs; i++)
00827     {
00828       adjLists.
00829         push_back (new
00830                    ListRecord (i,
00831                                std::numeric_limits < float >::infinity ()));
00832     }
00833   // zero spill cost for 'symbolic' registers
00834   for (i = num_regs; i < num_webs; i++)
00835     {
00836       adjLists.push_back (new ListRecord (i, 0.0));
00837     }
00838 
00839   // build lists based on adjacency matrix
00840   for (i = 1; i < num_webs; i++)
00841     {
00842       for (j = 0; j < (num_webs - 1); j++)
00843         {
00844           if (adjMatrix[i][j])
00845             {
00846               adjLists[i]->addAdjacentNode (j); // num_ints incremented in
00847                                                 // func
00848               adjLists[j]->addAdjacentNode (i);
00849             }
00850         }
00851     }
00852 
00853 }
00854 
00855 
00856 void
00857 briggs_reg_alloc::computeSpillCosts ()
00858 {
00859   instruction_list & insts = proc->instructions ();
00860   instruction_list_p it = insts.begin ();
00861   for (; it != insts.end (); ++it)
00862     {
00863 
00864       LirInst *instr = *it;
00865       if (instr->instruction == mn_Move)
00866         {
00867 
00868           // decrease weight by one copy
00869           adjLists[instr->opnd1.num ()]->incCost (copyWt *
00870                                                   (float) pow (10.0,
00871                                                                depth (it)));
00872         }
00873       else
00874         {
00875 
00876           // has destination?
00877           if (instr->has_dest ())
00878             adjLists[instr->dest.num ()]->incCost (defWt *
00879                                                    (float) pow (10.0,
00880                                                                 depth (it)));
00881 
00882           // has opnd1?
00883           if (instr->has_opnd1 ())
00884             adjLists[instr->opnd1.num ()]->incCost (defWt *
00885                                                     (float) pow (10.0,
00886                                                                  depth (it)));
00887 
00888           // has opnd2? (not constant)
00889           if (instr->has_opnd2 ())
00890             adjLists[instr->opnd2._reg.num ()]->incCost (defWt *
00891                                                          (float) pow (10.0,
00892                                                                       depth
00893                                                                       (it)));
00894 
00895           // has base?
00896           if (instr->has_base ())
00897             adjLists[instr->memBase.num ()]->incCost (defWt *
00898                                                       (float) pow (10.0,
00899                                                                    depth
00900                                                                    (it)));
00901 
00902           // has offset? (not constant)
00903           if (instr->has_offset ())
00904             adjLists[instr->memOffset._reg.num ()]->incCost (defWt *
00905                                                              (float)
00906                                                              pow (10.0,
00907                                                                   depth
00908                                                                   (it)));
00909         }
00910     }
00911 
00912   // replace spill cost by rematerialization cost if it is less
00913   // pnav -- do this if we have time...
00914 //              for (i = num_regs; i < num_webs; i++) {
00915 
00916 //              }
00917 }
00918 
00919 void
00920 briggs_reg_alloc::pruneGraph ()
00921 {
00922   bool finished;
00923   int i, nodes = num_webs;
00924   nodeStack.clear ();
00925 
00926   // keeps track of which nodes have already been pulled from graph
00927   int_set okNodes;
00928 
00929   do
00930     {
00931       // apply (degree < R) rule and push nodes onto stack
00932       do
00933         {
00934           finished = true;
00935           for (i = 0; i < num_webs; i++)
00936             {
00937 
00938               // can it be trivially colored?
00939               if (adjLists[i]->numInts () > 0
00940                   && (i < num_regs || adjLists[i]->numInts () < usable_regs))
00941                 {
00942                   finished = false;
00943                   adjustNeighbors (i);
00944                 }
00945 
00946               // if there is a web for it and there are no interferences, put 
00947               // it on the stack
00948               if (adjLists[i]->numInts () == 0
00949                   && okNodes.find (i) == okNodes.end ())
00950                 {
00951                   okNodes.insert (i);
00952                   if (Symreg[i])
00953                     nodeStack.push_back (i);
00954                   nodes--;
00955                   assert (nodes >= 0);
00956                 }
00957             }
00958         }
00959       while (!finished);
00960       if (nodes > 0)
00961         {
00962           // find node with minimal spill cost divided by its degree
00963           // push that node onto the stack
00964           int spillnode = -1;
00965           float spillcost = std::numeric_limits < float >::max ();
00966           for (i = 0; i < num_webs; i++)
00967             {
00968 
00969               // ignore nodes with no interferences or infinte cost
00970               if (adjLists[i]->numInts () == 0
00971                   || adjLists[i]->getSpillCost () == numeric_limits <
00972                   float >::infinity ())
00973                 continue;
00974 
00975               // evaluate spill cost
00976               float tmpcost =
00977                 adjLists[i]->getSpillCost () / adjLists[i]->numInts ();
00978               if (adjLists[i]->numInts () > 0 && tmpcost < spillcost)
00979                 {
00980                   spillnode = i;
00981                   spillcost = tmpcost;
00982                 }
00983             }
00984           assert (spillnode != -1);
00985           adjustNeighbors (spillnode);
00986         }
00987     }
00988   while (nodes > 0);
00989 }
00990 
00991 void
00992 briggs_reg_alloc::adjustNeighbors (int i)
00993 {
00994   // fixup all of i's neighbors
00995   const int_set & adjNodes = adjLists[i]->getAdjNodes ();
00996   int_set::const_iterator it = adjNodes.begin ();
00997   for (; it != adjNodes.end (); ++it)
00998     {
00999       assert (*it != i);
01000       adjLists[*it]->removeAdjacentNode (i);
01001     }
01002 
01003   // remove all entries from i
01004   adjLists[i]->removeAllAdjacencies ();
01005 }
01006 
01007 bool
01008 briggs_reg_alloc::assignRegisters ()
01009 {
01010   int i;
01011 
01012   // make list of available colors
01013   color_set colors;
01014   const arch_info::register_info_list & regsGpr =
01015     CBZ::ArchInfo.get_regs_gpr ();
01016   for (i = 0; i < (int) regsGpr.size (); ++i)
01017     colors.insert (regsGpr[i]->_id);
01018   const arch_info::register_info_list & regsFpr =
01019     CBZ::ArchInfo.get_regs_fpr ();
01020   for (i = 0; i < (int) regsFpr.size (); ++i)
01021     colors.insert (regsFpr[i]->_id);
01022   int rvFixed = -1;
01023   if (CBZ::ArchInfo.get_reg_retval_fixed ())
01024     rvFixed = CBZ::ArchInfo.get_reg_retval_fixed ()->_id;
01025   int rvFloat = -1;
01026   if (CBZ::ArchInfo.get_reg_retval_float ())
01027     rvFloat = CBZ::ArchInfo.get_reg_retval_float ()->_id;
01028 
01029   // reset this thing - we will be changing its info
01030   colorToRealReg.clear ();
01031   colorToRealReg.resize (num_regs);
01032 
01033   // pop webs off the stack and assign colors if possible
01034   bool success = true;
01035   while (!nodeStack.empty ())
01036     {
01037       // pop one off
01038       int reg = nodeStack.front ();
01039       nodeStack.pop_front ();
01040       ListRecord *adj = adjLists[reg];
01041       WebRecord *web = Symreg[reg];
01042 
01043       // real registers get their own number as their color
01044       if (reg < num_regs)
01045         {
01046           adj->getColor () = reg;
01047           colorToRealReg[reg] = reg;
01048           continue;
01049         }
01050 
01051       // get this node's info and available colors
01052       color_set okColors = colors;
01053       removeUnavailableColors (adj, okColors);
01054 
01055       // any colors that we can use?
01056       if (okColors.empty ())
01057         {
01058           // this has to be spilled
01059 #ifdef _DEBUG
01060           cout << "Don't know how to color register " << reg << " : spilling."
01061             << endl;
01062 #endif
01063           web->getSpill () = true;
01064           success = false;
01065         }
01066 
01067       // pick a color to use (this should be improved to try to pick one that 
01068       // 
01069       // cannot be used by an adjacent node)
01070       int color = *(okColors.begin ());
01071       adj->getColor () = color;
01072     }
01073 
01074   return success;
01075 }
01076 
01077 void
01078 briggs_reg_alloc::removeUnavailableColors (ListRecord * adj,
01079                                            color_set & colors)
01080 {
01081   // take out unavailable colors (used by adjacent nodes)
01082   const int_set & adjNodes = adj->getAdjNodes (), &rmadjNodes =
01083     adj->getRmAdjNodes ();
01084   int_set::const_iterator it;
01085   for (it = adjNodes.begin (); it != adjNodes.end (); ++it)
01086     {
01087       int color = adjLists[*it]->getColor ();
01088       if (color != ListRecord::color_none)
01089         colors -= color;
01090     }
01091   for (it = rmadjNodes.begin (); it != rmadjNodes.end (); ++it)
01092     {
01093       int color = adjLists[*it]->getColor ();
01094       if (color != ListRecord::color_none)
01095         colors -= color;
01096     }
01097 }
01098 
01099 void
01100 briggs_reg_alloc::modifyCode ()
01101 {
01102   // fixup each web as necessary
01103   for (int i = num_regs; i < num_webs; ++i)
01104     {
01105       // get the web, skip empties
01106       WebRecord *web = Symreg[i];
01107       if (!web)
01108         continue;
01109 
01110       // fixup this web
01111       Register reg;
01112       CBZ::ArchInfo.
01113         get_reg_by_index (colorToRealReg[adjLists[i]->getColor ()], reg);
01114       changeWebRegister (web, reg);
01115     }
01116 }
01117 
01118 void
01119 briggs_reg_alloc::changeWebRegister (WebRecord * web, const Register & newReg)
01120 {
01121   // this web's new register 
01122   Register oldReg (web->getReg ());
01123   web->getReg () = newReg;
01124 
01125   // fixup all defs to match
01126   DUChainDefs & defs = web->getDefs ();
01127   DUChainDefs::iterator def = defs.begin ();
01128   for (; def != defs.end (); ++def)
01129     {
01130       LirInst *pdef = *def;
01131 
01132       // if it has a dest it should be the old register
01133       assert (!pdef->has_dest (false) || pdef->dest == oldReg);
01134 
01135       // does it have an obvious destination?
01136       if (pdef->has_dest (false))
01137         pdef->dest = newReg;
01138 
01139       // is it a register variable?
01140       else if (pdef->has_dest (true))
01141         ((declNode *) pdef->nodeExtra)->storage_location ()._register =
01142           newReg;
01143     }
01144 
01145   // fixup all uses to match
01146   DUChainDefs & uses = web->getUses ();
01147   DUChainDefs::iterator use = uses.begin ();
01148   for (; use != uses.end (); ++use)
01149     {
01150       LirInst *pdef = *use;
01151 
01152       // fixup used registers
01153       if (pdef->has_opnd1 () && pdef->opnd1 == oldReg)
01154         pdef->opnd1 = newReg;
01155       if (pdef->has_opnd2 () && pdef->opnd2._reg == oldReg)
01156         pdef->opnd2._reg = newReg;
01157       if (pdef->has_base () && pdef->memBase == oldReg)
01158         pdef->memBase = newReg;
01159       if (pdef->has_offset () && pdef->memOffset._reg == oldReg)
01160         pdef->memOffset._reg = newReg;
01161     }
01162 }
01163 
01164 void
01165 briggs_reg_alloc::loadSymReg (Register & reg, declNode * contents,
01166                               instruction_list_p currentInstruction,
01167                               instruction_list & insts)
01168 {
01169   LirInst *current = *currentInstruction;
01170 
01171   // make sure contents are valid
01172   assert (contents > DATA_CONTENTS__SPECIAL);
01173 
01174   // make sure it has stack storage 
01175   // NOTE: we currently assume that register input params do not have to get
01176   // spilled, thus the assert()
01177   assert (contents->decl_location () == declNode::BLOCK);
01178   proc->alloc_stack_local (contents);
01179 
01180   // reload it
01181   LirInst *load = LIR::Load (contents->type(),
01182                              reg, contents,
01183                              Register::getRegFp (), DATA_CONTENTS_FRAMEP,
01184                              contents->storage_location ()._stack_offset,
01185                              NULL);
01186 
01187   // put this instruction in the right place (before the current instruction)
01188   insts.insert (currentInstruction, load);
01189   if (current->block)
01190     current->block->add_inst_after (load, current);
01191 }
01192 
01193 void
01194 briggs_reg_alloc::genSpillCode ()
01195 {
01196   // everyone that's supposed to be spilled must be spilled....
01197   instruction_list & insts = proc->instructions ();
01198   instruction_list_p it = insts.begin ();
01199   for (; it != insts.end (); ++it)
01200     {
01201       LirInst *inst = *it;
01202 
01203       // if we already loaded something this time around, this is its
01204       // register
01205       // NOTE: we use this for the case where we have (R1 = R2 op R2), and R2 
01206       // 
01207       // was spilled, so we don't reload R2 twice
01208       Register alreadyLoaded;
01209 
01210       // reload opnd1?
01211       if (inst->has_opnd1 () && isSymReg (inst->opnd1) &&
01212           Symreg[inst->opnd1.num ()]->getSpill ())
01213         {
01214 
01215           // load it back into its register
01216           loadSymReg (inst->opnd1, inst->opnd1_contents, it, insts);
01217 
01218           // remember that we already loaded this in case opnd2 uses it as
01219           // well
01220           alreadyLoaded = inst->opnd1;
01221         }
01222 
01223       // reload opnd2 register?
01224       if (inst->has_opnd2 () && isSymReg (inst->opnd2._reg) &&
01225           Symreg[inst->opnd2._reg.num ()]->getSpill ()
01226           && inst->opnd2._reg != alreadyLoaded)
01227         {
01228 
01229           // load it back into its register
01230           loadSymReg (inst->opnd2._reg, inst->opnd2_contents, it, insts);
01231         }
01232 
01233       // reload base register?
01234       if (inst->has_base () && isSymReg (inst->memBase) &&
01235           Symreg[inst->memBase.num ()]->getSpill ())
01236         {
01237 
01238           // load it back into its register
01239           loadSymReg (inst->memBase, inst->memBase_contents, it, insts);
01240         }
01241 
01242       // reload offset register?
01243       if (inst->has_offset () && isSymReg (inst->memOffset._reg) &&
01244           Symreg[inst->memOffset._reg.num ()]->getSpill ())
01245         {
01246 
01247           // load it back into its register
01248           loadSymReg (inst->memOffset._reg, inst->memOffset_contents, it,
01249                       insts);
01250         }
01251 
01252       // spill destination?
01253       if (inst->has_dest (true) && isSymReg (inst->dest)
01254           && Symreg[inst->dest.num ()]->getSpill ())
01255         {
01256 
01257           // this needs to have valid contents
01258           assert (inst->dest_contents > DATA_CONTENTS__SPECIAL);
01259 
01260           // make sure it has stack storage 
01261           // NOTE: we currently assume that register input params do not have 
01262           // to get spilled, thus the assert()
01263           assert (inst->dest_contents->decl_location () == declNode::BLOCK);
01264           proc->alloc_stack_local (inst->dest_contents);
01265 
01266           // store it
01267           LirInst *store =
01268             LIR::Store (inst->dest_contents->type(),
01269                         inst->dest, inst->dest_contents,
01270                         Register::getRegFp (), DATA_CONTENTS_FRAMEP,
01271                         inst->dest_contents->storage_location ().
01272                         _stack_offset, NULL);
01273 
01274           // put this instruction in the right place (after us)
01275           instruction_list_p insert = it;
01276           insert++;
01277           insts.insert (insert, store);
01278           if (inst->block)
01279             inst->block->add_inst_after (store, inst);
01280           it++;
01281         }
01282     }
01283 
01284   // now flag everything as non-spilled, so we don't try to spill it again
01285   // next time around
01286   for (int i = 0; i < (int) Symreg.size (); ++i)
01287     if (Symreg[i])
01288       Symreg[i]->getSpill () = false;
01289 }
01290 
01291 inline bool
01292 briggs_reg_alloc::isSymReg (const Register & reg)
01293 {
01294   // check out its number 
01295   assert (reg.num () >= 0);
01296   return ((int) reg.num () >= num_regs
01297           && (int) reg.num () < num_webs) ? true : false;
01298 }
01299 
01300 void
01301 briggs_reg_alloc::allocate (procNode * _proc)
01302 {
01303   bool success, coalesce = false;
01304   proc = _proc;
01305 
01306   // find out how many registers we have
01307   num_regs = CBZ::ArchInfo.get_all_regs ().size ();
01308   usable_regs =
01309     CBZ::ArchInfo.get_regs_gpr ().size () +
01310     CBZ::ArchInfo.get_regs_fpr ().size ();
01311 
01312   // do flow analysis on LIR to get loop info - this sets up _depth member of
01313   // each block, which we'll use later.
01314   vector < LirBlockSet > loops;
01315   lir_flow_walker::find_loops (_proc, true, loops);
01316 
01317   sduList duChains;
01318   do
01319     {
01320       do
01321         {
01322           duChains.clear ();
01323           makeDuChains (duChains);
01324           makeWebs (duChains);
01325           buildAdjMatrix ();
01326           coalesce = coalesceRegisters ();
01327         }
01328       while (coalesce);
01329 
01330       buildAdjLists ();
01331       computeSpillCosts ();
01332       pruneGraph ();
01333       success = assignRegisters ();
01334       if (success)
01335         {
01336           modifyCode ();
01337         }
01338       else
01339         {
01340           genSpillCode ();
01341         }
01342     }
01343   while (!success);
01344 
01345   // print out all of the instructions
01346 #if 1
01347   cout << "Post-allocation instruction listing:" << endl;
01348   instruction_list::const_iterator it = _proc->instructions ().begin ();
01349   int num = 0;
01350   while (it != _proc->instructions ().end ())
01351     cout << num++ << " " << **(it++) << endl;
01352   cout << endl << endl;
01353 #endif
01354 
01355 }
01356 
01357 // RegAllocWalker::RegAllocWalker ():Walker (Preorder, NodeOnly)
01358 RegAllocWalker::RegAllocWalker(void) :
01359         Walker(Preorder, Subtree)
01360 {
01361 }
01362 
01363 // acb - 6 May 2003
01364 // is this necessary?
01365 // void RegAllocWalker::at_unit(unitNode *the_unit, Order ord)
01366 // {
01367 //      // process all defs
01368 //      const def_list & defs = the_unit->defs();
01369 //      def_list::const_iterator it = defs.begin();
01370 //      while ( it != defs.end() )
01371 //              (*(it++))->walk( *this );
01372 // }
01373 
01374 void
01375 RegAllocWalker::at_proc (procNode * the_proc, Order ord)
01376 {
01377   // allocate regs for this guy
01378   briggs_reg_alloc ra;
01379   ra.allocate (the_proc);
01380 }

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