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 "lir_flow_walker.h"
00040 #include "LIR.h"
00041
00042
00043 lir_flow_walker::lir_flow_walker ():
00044 Walker (Both, Subtree)
00045 {
00046 }
00047
00048 lir_flow_walker::~lir_flow_walker ()
00049 {
00050 }
00051
00052 void
00053 lir_flow_walker::build_lir_blocks (procNode * the_proc)
00054 {
00055
00056 LirBlockList & blocks = the_proc->lir_blocks ();
00057 blocks.clear ();
00058
00059
00060 typedef map < string, LirBlock * >HeaderMap;
00061 HeaderMap headerMap;
00062
00063
00064 int next = 1;
00065 const instruction_list & insts = the_proc->instructions ();
00066 instruction_list::const_iterator instIt = insts.begin ();
00067 LirBlock *block = new LirBlock (next++);
00068 bool nextNew = false;
00069 for (; instIt != insts.end (); ++instIt)
00070 {
00071 LirInst *inst = *instIt;
00072
00073
00074
00075 mnemonic mn = inst->instruction;
00076 if (mn == mn_Label || nextNew)
00077 {
00078
00079 if (block->insts ().size () > 0)
00080 {
00081 blocks.push_back (block);
00082 LirBlock *tempblock = new LirBlock (next++);
00083 block->_next = tempblock;
00084 block = tempblock;
00085 }
00086
00087
00088 headerMap[inst->target] = block;
00089 }
00090
00091
00092 nextNew = false;
00093
00094
00095 switch (mn)
00096 {
00097 case mn_BranchEQ:
00098 case mn_BranchNE:
00099 case mn_BranchLT:
00100 case mn_BranchLE:
00101 case mn_BranchGT:
00102 case mn_BranchGE:
00103 case mn_Jmp:
00104
00105
00106 nextNew = true;
00107 break;
00108
00109 default:
00110
00111
00112 break;
00113 }
00114
00115
00116 block->add_inst (inst);
00117 }
00118
00119
00120 if (block->insts ().size () > 0)
00121 blocks.push_back (block);
00122
00123
00124 LirBlock *s1, *s2;
00125 HeaderMap::iterator findIt;
00126 LirBlockList_p b;
00127 for (b = blocks.begin (); b != blocks.end (); ++b)
00128 {
00129 LirBlock *block = *b;
00130
00131
00132 s1 = NULL;
00133 s2 = NULL;
00134
00135
00136 LirInst *last = block->insts ().back ();
00137 switch (last->instruction)
00138 {
00139 case mn_Jmp:
00140
00141
00142 s1 = headerMap[last->target];
00143 assert (s1);
00144 break;
00145
00146 case mn_BranchEQ:
00147 case mn_BranchNE:
00148 case mn_BranchLT:
00149 case mn_BranchLE:
00150 case mn_BranchGT:
00151 case mn_BranchGE:
00152
00153
00154 s1 = headerMap[last->target];
00155 assert (s1);
00156 s2 = block->_next;
00157 break;
00158
00159 case mn_Return:
00160
00161
00162 break;
00163
00164 default:
00165
00166
00167 s1 = block->_next;
00168 break;
00169 }
00170
00171
00172 if (s1)
00173 {
00174 block->_succs.insert (s1);
00175 s1->_preds.insert (block);
00176 }
00177 if (s2)
00178 {
00179 block->_succs.insert (s2);
00180 s2->_preds.insert (block);
00181 }
00182 }
00183
00184 }
00185
00186 void
00187 lir_flow_walker::get_block_dfo (LirBlock * block, LirBlockList & blocks)
00188 {
00189
00190 if (!block || block->_visited)
00191 return;
00192
00193
00194 block->_visited = true;
00195
00196
00197 LirBlockSet_p it;
00198 for (it = block->_succs.begin (); it != block->_succs.end (); ++it)
00199 get_block_dfo (*it, blocks);
00200
00201
00202 blocks.push_back (block);
00203 }
00204
00205 void
00206 lir_flow_walker::find_block_doms (procNode * the_proc)
00207 {
00208 LirBlockList & blocks = the_proc->lir_blocks ();
00209 LirBlockList_p it;
00210
00211
00212
00213
00214
00215
00216
00217 if (blocks.size () < 1)
00218 return;
00219
00220
00221 LirBlockList dfoBlocks;
00222 LirBlock *root = *(blocks.begin ());
00223 root->reset_visited ();
00224 get_block_dfo (root, dfoBlocks);
00225
00226
00227 LirBlockSet allBlocks;
00228 it = dfoBlocks.begin ();
00229 while (it != dfoBlocks.end ())
00230 allBlocks.insert (*(it++));
00231
00232
00233 it = blocks.begin ();
00234 while (it != blocks.end ())
00235 (*it++)->_doms = allBlocks;
00236
00237
00238 root->_doms.clear ();
00239 root->_doms.insert (root);
00240
00241
00242 LirBlockSet allNoRoot = allBlocks - root;
00243
00244
00245 bool changed;
00246 LirBlockSet t, d;
00247 do
00248 {
00249
00250 changed = false;
00251
00252
00253 LirBlockSet_p itn;
00254 for (itn = allNoRoot.begin (); itn != allNoRoot.end (); ++itn)
00255 {
00256 LirBlock *n = *itn;
00257
00258
00259 t = allBlocks;
00260
00261
00262 LirBlockSet_p pred;
00263 for (pred = n->_preds.begin (); pred != n->_preds.end (); ++pred)
00264 t &= (*pred)->_doms;
00265
00266
00267 d = t | n;
00268 if (d != n->_doms)
00269 {
00270 n->_doms = d;
00271 changed = true;
00272 }
00273 }
00274 }
00275 while (changed);
00276 }
00277
00278 void
00279 lir_flow_walker::find_loops (procNode * proc, bool need_recompute_flow,
00280 vector < LirBlockSet > &loops)
00281 {
00282
00283 if (need_recompute_flow)
00284 {
00285 build_lir_blocks (proc);
00286 find_block_doms (proc);
00287 debug_print_block_info (proc);
00288 }
00289
00290
00291 edge_list backedges;
00292 LirBlockList & blocks = proc->lir_blocks ();
00293 LirBlockList_p bl = blocks.begin ();
00294 for (; bl != blocks.end (); ++bl)
00295 {
00296 LirBlock *block = *bl;
00297
00298
00299 block->_depth = 0;
00300
00301
00302 LirBlockSet & succs = block->_succs;
00303 LirBlockSet::iterator suc = succs.begin ();
00304 for (; suc != succs.end (); ++suc)
00305 {
00306 LirBlock *succ = *suc;
00307
00308
00309 if (succ == block->_next)
00310 continue;
00311
00312
00313 if (block->_doms.find (succ) != block->_doms.end ())
00314 {
00315
00316 edge e = { block, succ };
00317 backedges.push_back (e);
00318 }
00319 }
00320 }
00321
00322
00323 loops.clear ();
00324 edge_list_p edg = backedges.begin ();
00325 LirBlock *p, *q;
00326 for (; edg != backedges.end (); ++edg)
00327 {
00328 LirBlockList stack;
00329
00330 edge & e = *edg;
00331 LirBlock *m = e.source, *n = e.target;
00332
00333
00334 int sz = loops.size () + 1;
00335 loops.resize (sz);
00336 LirBlockSet & loop = loops[sz - 1];
00337 loop.insert (m);
00338 loop.insert (n);
00339
00340
00341 if (m != n)
00342 stack.push_back (m);
00343 while (stack.size () > 0)
00344 {
00345
00346 p = stack.back ();
00347 stack.pop_back ();
00348
00349
00350 LirBlockSet_p pr = p->_preds.begin ();
00351 for (; pr != p->_preds.end (); ++pr)
00352 {
00353 q = *pr;
00354 if (loop.find (q) == loop.end ())
00355 {
00356 loop.insert (q);
00357 stack.push_back (q);
00358 }
00359 }
00360 }
00361 }
00362
00363
00364 vector < LirBlockSet >::iterator lp = loops.begin ();
00365 for (; lp != loops.end (); ++lp)
00366 {
00367
00368 LirBlockSet & loop = *lp;
00369 LirBlockSet_p bl = loop.begin ();
00370 for (; bl != loop.end (); ++bl)
00371 (*bl)->_depth++;
00372 }
00373
00374 }
00375
00376 void
00377 lir_flow_walker::at_proc (procNode * the_proc, Order ord)
00378 {
00379 if (ord != Preorder)
00380 return;
00381
00382
00383 build_lir_blocks (the_proc);
00384 find_block_doms (the_proc);
00385
00386
00387 debug_print_block_info (the_proc);
00388 }
00389
00390
00391
00392 void
00393 lir_flow_walker::computeRegisterLiveness (instruction_list & insts,
00394 inst_to_reg_id_map & liveRegs)
00395 {
00396
00397 getInstructionFlowInfo (insts);
00398
00399
00400 instruction_list_p it = insts.begin ();
00401 for (; it != insts.end (); ++it)
00402 {
00403 LirInst *inst = *it;
00404 inst->visited = false;
00405 liveRegs[inst].clear ();
00406 }
00407
00408
00409 instruction_list rpo;
00410 getInstructionsPostorder (insts, insts.begin (), rpo);
00411
00412
00413
00414 #if 0
00415 {
00416 cout << "DEBUG:" << endl;
00417 cout << "Postorder:" << endl;
00418 instruction_list_p it = rpo.begin ();
00419 for (; it != rpo.end (); ++it)
00420 cout << **it << endl;
00421 cout << "END DEBUG" << endl;
00422 }
00423 #endif
00424
00425
00426
00427 instruction_list worklist = rpo;
00428 unsigned int idFp = CBZ::ArchInfo.get_reg_fp ()->_id;
00429 unsigned int idSp = CBZ::ArchInfo.get_reg_sp ()->_id;
00430 unsigned int idRvFixed = (unsigned int) -1;
00431 if (CBZ::ArchInfo.get_reg_retval_fixed ())
00432 idRvFixed = CBZ::ArchInfo.get_reg_retval_fixed ()->_id;
00433 unsigned int idRvFloat = (unsigned int) -1;
00434 if (CBZ::ArchInfo.get_reg_retval_float ())
00435 idRvFloat = CBZ::ArchInfo.get_reg_retval_float ()->_id;
00436 while (worklist.size () != 0)
00437 {
00438
00439 LirInst *inst = worklist.front ();
00440 worklist.pop_front ();
00441
00442
00443 reg_id_set used;
00444 if (inst->has_opnd1 ())
00445 used.insert (inst->opnd1.num ());
00446 if (inst->has_opnd2 ())
00447 used.insert (inst->opnd2._reg.num ());
00448 if (inst->has_base ())
00449 used.insert (inst->memBase.num ());
00450 if (inst->has_offset ())
00451 used.insert (inst->memOffset._reg.num ());
00452
00453
00454 reg_id_set succLive;
00455 instruction_set_p sit = inst->succs.begin ();
00456 for (; sit != inst->succs.end (); ++sit)
00457 succLive |= liveRegs[*sit];
00458
00459
00460 reg_id_set killRegs;
00461 if (inst->has_dest ())
00462 {
00463
00464 killRegs |= inst->dest.num ();
00465 }
00466
00467
00468 reg_id_set live = used | (succLive - killRegs);
00469
00470
00471
00472
00473 live -= idFp;
00474 live -= idSp;
00475 live -= idRvFixed;
00476 live -= idRvFloat;
00477
00478
00479 if (liveRegs[inst] != live)
00480 {
00481
00482 liveRegs[inst] = live;
00483
00484
00485 instruction_set_p pit = inst->preds.begin ();
00486 for (; pit != inst->preds.end (); ++pit)
00487 if (!cbz_util::list_find (worklist, *pit))
00488 worklist.push_back (*pit);
00489 }
00490 }
00491 }
00492
00493 void
00494 lir_flow_walker::getInstructionsPostorder (instruction_list & insts,
00495 instruction_list_p it,
00496 instruction_list & ordering)
00497 {
00498 LirInst *inst = *it;
00499
00500
00501 if (inst->visited)
00502 return;
00503
00504
00505 inst->visited = true;
00506
00507
00508 switch (inst->instruction)
00509 {
00510 case mn_Return:
00511
00512
00513 break;
00514
00515 case mn_Jmp:
00516
00517
00518 assert (inst->targetInst);
00519 if (!inst->targetInst->visited)
00520 getInstructionsPostorder (insts,
00521 findInstruction (insts, inst->targetInst),
00522 ordering);
00523 break;
00524
00525 case mn_BranchEQ:
00526 case mn_BranchNE:
00527 case mn_BranchLT:
00528 case mn_BranchLE:
00529 case mn_BranchGT:
00530 case mn_BranchGE:
00531
00532
00533 assert (inst->targetInst);
00534 if (!inst->targetInst->visited)
00535 getInstructionsPostorder (insts,
00536 findInstruction (insts, inst->targetInst),
00537 ordering);
00538
00539
00540
00541 default:
00542
00543
00544 assert (it != insts.end ());
00545 instruction_list_p next = it;
00546 next++;
00547 getInstructionsPostorder (insts, next, ordering);
00548 break;
00549 }
00550
00551
00552 ordering.push_back (inst);
00553 }
00554
00555 void
00556 lir_flow_walker::getInstructionFlowInfo (instruction_list & insts)
00557 {
00558 instruction_list_p it;
00559
00560
00561 typedef map < string, LirInst * >target_map;
00562 target_map targets;
00563 for (it = insts.begin (); it != insts.end (); ++it)
00564 {
00565 LirInst *inst = *it;
00566
00567
00568 inst->succs.clear ();
00569 inst->preds.clear ();
00570
00571
00572 if (inst->instruction == mn_Label)
00573 targets[inst->target] = inst;
00574 }
00575
00576
00577 LirInst *s1, *s2;
00578 for (it = insts.begin (); it != insts.end (); ++it)
00579 {
00580 LirInst *inst = *it;
00581
00582
00583 s1 = NULL;
00584 s2 = NULL;
00585
00586 switch (inst->instruction)
00587 {
00588 case mn_Return:
00589 case mn_EndProc:
00590
00591
00592 break;
00593
00594 case mn_Jmp:
00595 {
00596
00597 inst->targetInst = targets[inst->target];
00598 assert (inst->targetInst);
00599 s1 = inst->targetInst;
00600 break;
00601 }
00602 case mn_BranchEQ:
00603 case mn_BranchNE:
00604 case mn_BranchLT:
00605 case mn_BranchLE:
00606 case mn_BranchGT:
00607 case mn_BranchGE:
00608 {
00609
00610 inst->targetInst = targets[inst->target];
00611 assert (inst->targetInst);
00612 s2 = inst->targetInst;
00613
00614
00615 }
00616 default:
00617
00618
00619 instruction_list_p next = it;
00620 ++next;
00621 assert (next != insts.end ());
00622 s1 = *next;
00623 break;
00624 }
00625
00626
00627 if (s1)
00628 {
00629 inst->succs.insert (s1);
00630 s1->preds.insert (inst);
00631 }
00632 if (s2)
00633 {
00634 inst->succs.insert (s2);
00635 s2->preds.insert (inst);
00636 }
00637 }
00638 }
00639
00640 instruction_list_p
00641 lir_flow_walker::findInstruction (instruction_list & insts,
00642 const LirInst * inst)
00643 {
00644 instruction_list_p it = insts.begin ();
00645 for (; it != insts.end (); ++it)
00646 if (*it == inst)
00647 return it;
00648 return it;
00649 }
00650
00651 void
00652 lir_flow_walker::debug_print_block_info (procNode * proc)
00653 {
00654 #if 0
00655
00656 LirBlockList & blocks = proc->lir_blocks ();
00657 LirBlockList_p it = blocks.begin ();
00658 int inst = 0;
00659 while (it != blocks.end ())
00660 {
00661 printf ("\n");
00662 printf ("\n");
00663 printf ("block %d (instructions %d through %d) ",
00664 (*it)->_number, inst, inst + (*it)->insts ().size () - 1);
00665 printf ("\n");
00666 printf ("dominated by: ");
00667 LirBlockSet_p doms = (*it)->_doms.begin ();
00668 while (doms != (*it)->_doms.end ())
00669 printf ("%d ", (*doms++)->_number);
00670 printf ("\n");
00671 printf ("predecessors: ");
00672 LirBlockSet_p preds = (*it)->_preds.begin ();
00673 while (preds != (*it)->_preds.end ())
00674 printf ("%d ", (*preds++)->_number);
00675 printf ("\n");
00676 printf ("successors: ");
00677 LirBlockSet_p succs = (*it)->_succs.begin ();
00678 while (succs != (*it)->_succs.end ())
00679 printf ("%d ", (*succs++)->_number);
00680 printf ("\n");
00681 inst += (*it)->insts ().size ();
00682 it++;
00683 }
00684 #endif
00685 }