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 "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
00056 if (_type != rhs._type)
00057 return false;
00058
00059
00060 switch (_type)
00061 {
00062 case sym_id:
00063 return (rhs._id == _id);
00064
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
00079 switch (_type)
00080 {
00081 case sym_id:
00082 assert (_id);
00083 return _id->type();
00084
00085 case sym_reg:
00086
00087
00088 if (_reg.type () == reg_gpr ||
00089 _reg.type () == reg_frame_ptr || _reg.type () == reg_stack_ptr)
00090 {
00091
00092 return CBZ::ArchInfo.get_reg_data_type_gpr ();
00093 }
00094 else if (_reg.type () == reg_fpr)
00095 {
00096
00097 return CBZ::ArchInfo.get_reg_data_type_fpr ();
00098 }
00099 else
00100 {
00101
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
00128
00129
00130
00131
00132
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
00163 adjNodes.insert (reg);
00164 num_ints++;
00165 }
00166
00167 void
00168 ListRecord::removeAdjacentNode (int reg)
00169 {
00170 bool found = false;
00171
00172
00173 int_set_p it = adjNodes.find (reg);
00174 assert (it != adjNodes.end ());
00175
00176
00177 adjNodes.erase (it);
00178 num_ints--;
00179
00180
00181 removeAdj.insert (reg);
00182 }
00183
00184 void
00185 ListRecord::removeAllAdjacencies ()
00186 {
00187
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
00219
00220 if (CBZ::ArchInfo.get_reg_fp ()->_id == reg ||
00221 CBZ::ArchInfo.get_reg_sp ()->_id == reg)
00222 return true;
00223
00224
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
00234 const Symbol & sym = wr->getSym ();
00235 typeNode * the_type = sym.getLirVt ();
00236
00237
00238
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
00247
00248
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
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
00268 pInst = *it;
00269 if (pInst->instruction != mn_Call)
00270 continue;
00271
00272
00273
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
00282
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
00296
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
00305 instruction_list & insts = proc->instructions ();
00306 for (++instr; instr != insts.end (); ++instr)
00307 {
00308
00309
00310 LirInst *inst = *instr;
00311
00312
00313 if (!inst->has_dest (true))
00314 continue;
00315
00316
00317 if (inst->dest.num () == reg_k || inst->dest.num () == reg_l)
00318 return false;
00319 }
00320
00321
00322 return true;
00323 }
00324
00325 void
00326 briggs_reg_alloc::deleteInstr (instruction_list_p it)
00327 {
00328
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
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
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
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
00366 reg_set current_regs;
00367 def_map defs_all;
00368 use_map uses_all;
00369
00370
00371
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
00378
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
00391 for (ilp = worklist.begin (); ilp != worklist.end (); ++ilp)
00392 {
00393 LirInst *inst = *ilp;
00394
00395
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
00406 if (inst->has_dest (true))
00407 defs_all[inst->get_dest ()].insert (inst);
00408 }
00409
00410
00411
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
00421 typedef map < unsigned int, hash_set_ex < DUChainDef > >reg_to_def_map;
00422
00423
00424 typedef map < LirInst *, reg_to_def_map > reach_map;
00425
00426
00427
00428 reach_map reach;
00429 while (worklist.size () != 0)
00430 {
00431 LirInst *inst = worklist.front ();
00432 worklist.pop_front ();
00433
00434
00435 reg_to_def_map thisReach;
00436 instruction_set_p pit = inst->preds.begin ();
00437 for (; pit != inst->preds.end (); ++pit)
00438 {
00439
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
00447 Register defReg;
00448 if (inst->has_dest (true))
00449 {
00450 hash_set_ex < DUChainDef > &defs =
00451 thisReach[inst->get_dest ().num ()];
00452
00453
00454 defs.clear ();
00455 defs.insert (inst);
00456 }
00457
00458
00459 if (thisReach != reach[inst])
00460 {
00461
00462 reach[inst] = thisReach;
00463
00464
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
00473 def_map::iterator dmit = defs_all.begin ();
00474 for (; dmit != defs_all.end (); ++dmit)
00475 {
00476 Register reg = dmit->first;
00477
00478
00479 def_set & defs = dmit->second;
00480 def_set::iterator def = defs.begin ();
00481 for (; def != defs.end (); ++def)
00482 {
00483
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
00495 use_set & possibles = uses_all[reg];
00496 use_set::iterator pit = possibles.begin ();
00497 for (; pit != possibles.end (); ++pit)
00498 {
00499
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
00509 sduList::iterator it = DuChains.begin ();
00510 for (; it != DuChains.end (); ++it)
00511 {
00512
00513
00514 sdu *du = *it;
00515 if (du->getDef ()->instruction == mn_DeclLocal
00516 && du->getUses ().size () == 0)
00517 DuChains.erase (it--);
00518 }
00519
00520
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
00544
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
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
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
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
00590 if ((web1->getSym () == web2->getSym ())
00591 && web1->intersectUses (web2->getUses ()))
00592 {
00593 assert (web1 != web2);
00594 assert (web1->getReg () == web2->getReg ());
00595
00596
00597 web1->unionDefs (web2->getDefs ());
00598 web1->unionUses (web2->getUses ());
00599
00600
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
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
00619 Register newReg ((*w)->getReg ());
00620 newReg = nextreg++;
00621
00622
00623 changeWebRegister (*w, newReg);
00624 }
00625
00626
00627 num_webs = nextreg;
00628
00629
00630 Symreg.clear ();
00631 Symreg.resize (num_webs);
00632
00633
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
00644 int num = (*p)->getReg ().num ();
00645 assert (num >= 0 && num < (int) Symreg.size ());
00646 Symreg[num] = *p;
00647 }
00648
00649
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
00688 lir_flow_walker::computeRegisterLiveness (proc->instructions (), liveRegs);
00689
00690
00691
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
00718 for (j = 0; j < num_regs; j++)
00719 {
00720 if (interfere (Symreg[i], j))
00721 adjMatrix[i][j] = true;
00722 }
00723
00724
00725 for (j = num_regs; j < num_webs; j++)
00726 {
00727 if (!Symreg[j] || i == j)
00728 continue;
00729
00730
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
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
00776 LirInst *inst = *it;
00777
00778
00779
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
00791 Symreg[l]->getDefs ().remove (*it);
00792 deleteInstr (it--);
00793
00794
00795 changeWebRegister (Symreg[l], Symreg[k]->getReg ());
00796
00797
00798 Symreg[k]->unionDefs (Symreg[l]->getDefs ());
00799 Symreg[k]->unionUses (Symreg[l]->getUses ());
00800
00801
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
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
00825
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
00834 for (i = num_regs; i < num_webs; i++)
00835 {
00836 adjLists.push_back (new ListRecord (i, 0.0));
00837 }
00838
00839
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);
00847
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
00869 adjLists[instr->opnd1.num ()]->incCost (copyWt *
00870 (float) pow (10.0,
00871 depth (it)));
00872 }
00873 else
00874 {
00875
00876
00877 if (instr->has_dest ())
00878 adjLists[instr->dest.num ()]->incCost (defWt *
00879 (float) pow (10.0,
00880 depth (it)));
00881
00882
00883 if (instr->has_opnd1 ())
00884 adjLists[instr->opnd1.num ()]->incCost (defWt *
00885 (float) pow (10.0,
00886 depth (it)));
00887
00888
00889 if (instr->has_opnd2 ())
00890 adjLists[instr->opnd2._reg.num ()]->incCost (defWt *
00891 (float) pow (10.0,
00892 depth
00893 (it)));
00894
00895
00896 if (instr->has_base ())
00897 adjLists[instr->memBase.num ()]->incCost (defWt *
00898 (float) pow (10.0,
00899 depth
00900 (it)));
00901
00902
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
00913
00914
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
00927 int_set okNodes;
00928
00929 do
00930 {
00931
00932 do
00933 {
00934 finished = true;
00935 for (i = 0; i < num_webs; i++)
00936 {
00937
00938
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
00947
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
00963
00964 int spillnode = -1;
00965 float spillcost = std::numeric_limits < float >::max ();
00966 for (i = 0; i < num_webs; i++)
00967 {
00968
00969
00970 if (adjLists[i]->numInts () == 0
00971 || adjLists[i]->getSpillCost () == numeric_limits <
00972 float >::infinity ())
00973 continue;
00974
00975
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
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
01004 adjLists[i]->removeAllAdjacencies ();
01005 }
01006
01007 bool
01008 briggs_reg_alloc::assignRegisters ()
01009 {
01010 int i;
01011
01012
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
01030 colorToRealReg.clear ();
01031 colorToRealReg.resize (num_regs);
01032
01033
01034 bool success = true;
01035 while (!nodeStack.empty ())
01036 {
01037
01038 int reg = nodeStack.front ();
01039 nodeStack.pop_front ();
01040 ListRecord *adj = adjLists[reg];
01041 WebRecord *web = Symreg[reg];
01042
01043
01044 if (reg < num_regs)
01045 {
01046 adj->getColor () = reg;
01047 colorToRealReg[reg] = reg;
01048 continue;
01049 }
01050
01051
01052 color_set okColors = colors;
01053 removeUnavailableColors (adj, okColors);
01054
01055
01056 if (okColors.empty ())
01057 {
01058
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
01068
01069
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
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
01103 for (int i = num_regs; i < num_webs; ++i)
01104 {
01105
01106 WebRecord *web = Symreg[i];
01107 if (!web)
01108 continue;
01109
01110
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
01122 Register oldReg (web->getReg ());
01123 web->getReg () = newReg;
01124
01125
01126 DUChainDefs & defs = web->getDefs ();
01127 DUChainDefs::iterator def = defs.begin ();
01128 for (; def != defs.end (); ++def)
01129 {
01130 LirInst *pdef = *def;
01131
01132
01133 assert (!pdef->has_dest (false) || pdef->dest == oldReg);
01134
01135
01136 if (pdef->has_dest (false))
01137 pdef->dest = newReg;
01138
01139
01140 else if (pdef->has_dest (true))
01141 ((declNode *) pdef->nodeExtra)->storage_location ()._register =
01142 newReg;
01143 }
01144
01145
01146 DUChainDefs & uses = web->getUses ();
01147 DUChainDefs::iterator use = uses.begin ();
01148 for (; use != uses.end (); ++use)
01149 {
01150 LirInst *pdef = *use;
01151
01152
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
01172 assert (contents > DATA_CONTENTS__SPECIAL);
01173
01174
01175
01176
01177 assert (contents->decl_location () == declNode::BLOCK);
01178 proc->alloc_stack_local (contents);
01179
01180
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
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
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
01204
01205
01206
01207
01208 Register alreadyLoaded;
01209
01210
01211 if (inst->has_opnd1 () && isSymReg (inst->opnd1) &&
01212 Symreg[inst->opnd1.num ()]->getSpill ())
01213 {
01214
01215
01216 loadSymReg (inst->opnd1, inst->opnd1_contents, it, insts);
01217
01218
01219
01220 alreadyLoaded = inst->opnd1;
01221 }
01222
01223
01224 if (inst->has_opnd2 () && isSymReg (inst->opnd2._reg) &&
01225 Symreg[inst->opnd2._reg.num ()]->getSpill ()
01226 && inst->opnd2._reg != alreadyLoaded)
01227 {
01228
01229
01230 loadSymReg (inst->opnd2._reg, inst->opnd2_contents, it, insts);
01231 }
01232
01233
01234 if (inst->has_base () && isSymReg (inst->memBase) &&
01235 Symreg[inst->memBase.num ()]->getSpill ())
01236 {
01237
01238
01239 loadSymReg (inst->memBase, inst->memBase_contents, it, insts);
01240 }
01241
01242
01243 if (inst->has_offset () && isSymReg (inst->memOffset._reg) &&
01244 Symreg[inst->memOffset._reg.num ()]->getSpill ())
01245 {
01246
01247
01248 loadSymReg (inst->memOffset._reg, inst->memOffset_contents, it,
01249 insts);
01250 }
01251
01252
01253 if (inst->has_dest (true) && isSymReg (inst->dest)
01254 && Symreg[inst->dest.num ()]->getSpill ())
01255 {
01256
01257
01258 assert (inst->dest_contents > DATA_CONTENTS__SPECIAL);
01259
01260
01261
01262
01263 assert (inst->dest_contents->decl_location () == declNode::BLOCK);
01264 proc->alloc_stack_local (inst->dest_contents);
01265
01266
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
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
01285
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
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
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
01313
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
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
01358 RegAllocWalker::RegAllocWalker(void) :
01359 Walker(Preorder, Subtree)
01360 {
01361 }
01362
01363
01364
01365
01366
01367
01368
01369
01370
01371
01372
01373
01374 void
01375 RegAllocWalker::at_proc (procNode * the_proc, Order ord)
01376 {
01377
01378 briggs_reg_alloc ra;
01379 ra.allocate (the_proc);
01380 }