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 <set>
00039 #include "c_breeze.h"
00040 #include "dominators.h"
00041 #include "loops.h"
00042
00043
00044
00045
00046
00047 loopTreeNode::loopTreeNode(LoopKind kind, basicblockNode * header)
00048 : _kind(kind),
00049 _header(header),
00050 _preheader(0),
00051 _parentLoop(0),
00052 _nestedLoops(),
00053 _blocks()
00054 {
00055 _blocks.insert(header);
00056 }
00057
00058 void loopTreeNode::output(output_context & ct, Node * parent)
00059 {
00060 output_stmt(ct, parent);
00061 }
00062
00063 void loopTreeNode::output_stmt(output_context & ct, Node * parent)
00064 {
00065
00066 cout << "LoopTreeNode header: " << endl;
00067 _header->output(ct, NULL);
00068
00069 }
00070
00071
00072 void loopTreeNode::report()
00073 {
00074 switch (kind()) {
00075 case SingleEntry:
00076 cout << "Single entry: ";
00077 break;
00078 case MultipleEntry:
00079 cout << "Multiple entry: ";
00080 break;
00081 case Top:
00082 cout << "(Top): ";
00083 break;
00084 default:
00085 cout << "(ERROR): ";
00086 break;
00087 }
00088
00089 cout << "Depth = " << depth() << ", ";
00090
00091 cout << "Header is #" << header()->dfn();
00092 cout << ", blocks: ";
00093
00094 for (basicblock_set_p p = blocks().begin();
00095 p != blocks().end();
00096 ++p)
00097 cout << "#" << (*p)->dfn() << " ";
00098
00099 cout << endl;
00100 }
00101
00102
00103
00104
00105
00106 loopTree::loopTree(procNode * procedure)
00107 : _procedure(procedure),
00108 _top(0),
00109 _loops(),
00110 _containedIn(),
00111 _backEdges(),
00112 _forwardEdges(),
00113 _crossEdges()
00114 {
00115
00116
00117
00118 basicblock_list post_order;
00119 classifyEdges(post_order);
00120
00121
00122
00123
00124 basicblock_set_map generators_map;
00125
00126 for (basicblock_list_p p = post_order.begin();
00127 p != post_order.end();
00128 ++p)
00129 {
00130 basicblockNode * cur = *p;
00131
00132
00133
00134
00135
00136
00137 if ( ! generators_map[cur].empty() )
00138 findBody(cur, generators_map[cur], loopTreeNode::MultipleEntry);
00139
00140
00141
00142 findLoop(cur, generators_map);
00143 }
00144
00145
00146
00147 basicblock_set just_exit;
00148 just_exit.insert(procedure->exit());
00149
00150 findBody(procedure->entry(), just_exit, loopTreeNode::Top);
00151
00152
00153
00154 setDepths(_top, 0);
00155 }
00156
00157 loopTree::~loopTree()
00158 {
00159
00160
00161 for (loop_list_p p = _loops.begin();
00162 p != _loops.end();
00163 ++p)
00164 delete *p;
00165 }
00166
00167 loopTreeNode * loopTree::whichLoop(basicblockNode * block)
00168 {
00169 blockloop_map_p p = _containedIn.find(block);
00170 if (p != _containedIn.end())
00171 return (*p).second;
00172 else
00173 return 0;
00174 }
00175
00176 void loopTree::findLoop(basicblockNode * candidate,
00177 basicblock_set_map & generators_map)
00178 {
00179
00180
00181 edge_map_p p = _backEdges.find(candidate);
00182
00183 if (p != _backEdges.end()) {
00184
00185
00186
00187
00188
00189
00190
00191
00192 basicblock_set & predecessors = (*p).second;
00193
00194
00195
00196 basicblockNode * header = candidate;
00197
00198
00199
00200 basicblock_set generators;
00201
00202
00203
00204 for (basicblock_set_p q = predecessors.begin();
00205 q != predecessors.end();
00206 ++q)
00207 {
00208 basicblockNode * pred = *q;
00209
00210
00211
00212 header = commonDominator(header, pred);
00213
00214
00215
00216 if (pred != candidate)
00217 generators.insert(pred);
00218 }
00219
00220
00221
00222
00223
00224
00225 if (header == candidate) {
00226
00227
00228
00229
00230 findBody(candidate, generators, loopTreeNode::SingleEntry);
00231 }
00232 else {
00233
00234
00235
00236
00237
00238 generators_map[header].insert(generators.begin(), generators.end());
00239 }
00240 }
00241 }
00242
00243 void loopTree::findBody(basicblockNode * head,
00244 basicblock_set & generators,
00245 loopTreeNode::LoopKind kind)
00246 {
00247
00248
00249 basicblock_set loop_nodes;
00250
00251
00252
00253 basicblock_list loop_queue;
00254
00255
00256
00257
00258
00259 for (basicblock_set_p p = generators.begin();
00260 p != generators.end();
00261 ++p)
00262 {
00263 basicblockNode * generator = *p;
00264
00265 loopTreeNode * loop = whichLoop(generator);
00266 if (! loop) {
00267 loop_nodes.insert(generator);
00268 loop_queue.push_back(generator);
00269 }
00270 }
00271
00272
00273
00274
00275 while ( ! loop_queue.empty()) {
00276
00277 basicblockNode * cur = loop_queue.front();
00278 loop_queue.pop_front();
00279
00280
00281
00282 for (basicblock_list_p q = cur->preds().begin();
00283 q != cur->preds().end();
00284 ++q)
00285 {
00286 basicblockNode * pred = *q;
00287
00288
00289
00290
00291 if ((pred != head) &&
00292 (loop_nodes.find(pred) == loop_nodes.end())) {
00293 loop_nodes.insert(pred);
00294 loop_queue.push_back(pred);
00295 }
00296 }
00297 }
00298
00299
00300
00301
00302 loopTreeNode * loop = new loopTreeNode(kind, head);
00303
00304 _containedIn[head] = loop;
00305
00306 _loops.push_front(loop);
00307
00308
00309
00310
00311 for (basicblock_set_p w = loop_nodes.begin();
00312 w != loop_nodes.end();
00313 ++w)
00314 {
00315 basicblockNode * block = *w;
00316
00317
00318
00319 loopTreeNode * nested_loop = whichLoop(block);
00320 if (nested_loop) {
00321
00322
00323
00324 loopTreeNode * ancestor = loopAncestor(nested_loop);
00325
00326 if (ancestor != loop) {
00327 loop->addNestedLoop(ancestor);
00328 ancestor->parentLoop(loop);
00329 }
00330 }
00331 else {
00332
00333
00334
00335 _containedIn[block] = loop;
00336
00337
00338
00339 loop->addBlock(block);
00340 }
00341 }
00342
00343
00344
00345 if (kind != loopTreeNode::Top) {
00346
00347 ostringstream comment;
00348
00349 comment << endl;
00350 switch (kind) {
00351 case loopTreeNode::SingleEntry:
00352 comment << " Single entry loop: ";
00353 break;
00354 case loopTreeNode::MultipleEntry:
00355 comment << " Multiple entry loop: ";
00356 break;
00357 default:
00358 comment << " (ERROR): ";
00359 break;
00360 }
00361
00362 for (basicblock_set_p p = loop->blocks().begin();
00363 p != loop->blocks().end();
00364 ++p)
00365 {
00366 basicblockNode * bb = *p;
00367 comment << " #" << _preOrder[bb] << " ";
00368 }
00369
00370 head->comment() += comment.str();
00371 }
00372
00373
00374
00375
00376 if (kind == loopTreeNode::Top)
00377 _top = loop;
00378 }
00379
00380 basicblockNode * loopTree::commonDominator(basicblockNode * first,
00381 basicblockNode * second)
00382 {
00383
00384
00385
00386 basicblockNode * cur = first;
00387
00388 while ( cur && ( ! Dominators::dominates(cur, second)))
00389 cur = cur->parent();
00390
00391
00392
00393 if ( ! cur )
00394 cerr << "ERROR: Entry node does not dominate the rest of the basic blocks" << endl;
00395
00396 return cur;
00397 }
00398
00399 loopTreeNode * loopTree::loopAncestor(loopTreeNode * loop)
00400 {
00401 loopTreeNode * cur = loop;
00402
00403 while (cur->parentLoop())
00404 cur = cur->parentLoop();
00405
00406 return cur;
00407 }
00408
00409 void loopTree::classifyEdges(basicblock_list & post_order)
00410 {
00411
00412
00413
00414 _backEdges.clear();
00415 _forwardEdges.clear();
00416 _crossEdges.clear();
00417 _preOrder.clear();
00418 _rpostOrder.clear();
00419
00420
00421
00422
00423 stmt_list & body = _procedure->body()->stmts();
00424
00425 int pre_order_number = 0;
00426 int rpost_order_number = body.size() - 1;
00427
00428 for (stmt_list_p x = body.begin();
00429 x != body.end();
00430 ++x)
00431 {
00432 basicblockNode * cur = (basicblockNode *) *x;
00433 _preOrder[cur] = -1;
00434 _rpostOrder[cur] = -1;
00435 }
00436
00437
00438
00439 depthFirstSearch(_procedure->entry(), post_order,
00440 pre_order_number, rpost_order_number);
00441 }
00442
00443 void loopTree::depthFirstSearch(basicblockNode * cur,
00444 basicblock_list & post_order,
00445 int & pre_order_number,
00446 int & rpost_order_number)
00447 {
00448
00449
00450 ostringstream comment;
00451
00452
00453
00454 _preOrder[cur] = pre_order_number;
00455 comment << " BB #" << pre_order_number;
00456 pre_order_number++;
00457
00458
00459
00460
00461 comment << " : Successors: ";
00462
00463 for (basicblock_list_p p = cur->succs().begin();
00464 p != cur->succs().end();
00465 ++p)
00466 {
00467 basicblockNode * successor = *p;
00468 EdgeKind kind;
00469
00470 if (_preOrder[successor] == -1) {
00471
00472
00473
00474 kind = TreeEdge;
00475
00476 _treeEdges[cur].insert(successor);
00477
00478 depthFirstSearch(successor, post_order,
00479 pre_order_number, rpost_order_number);
00480 }
00481 else if (_rpostOrder[successor] == -1) {
00482
00483
00484
00485 kind = BackEdge;
00486
00487 _backEdges[successor].insert(cur);
00488 }
00489 else if (_preOrder[cur] < _preOrder[successor]) {
00490
00491
00492
00493 kind = ForwardEdge;
00494
00495 _forwardEdges[cur].insert(successor);
00496 }
00497 else {
00498
00499
00500
00501 kind = CrossEdge;
00502
00503 _crossEdges[cur].insert(successor);
00504 }
00505
00506 comment << " #" << _preOrder[successor] << " ";
00507 switch (kind) {
00508 case TreeEdge: comment << "(Tree)";
00509 break;
00510 case BackEdge: comment << "(Back)";
00511 break;
00512 case ForwardEdge: comment << "(Forward)";
00513 break;
00514 case CrossEdge: default: comment << "(Cross)";
00515 break;
00516 }
00517 comment << " ";
00518 }
00519
00520
00521
00522 cur->comment() = comment.str();
00523
00524
00525
00526 post_order.push_back(cur);
00527
00528
00529
00530 _rpostOrder[cur] = rpost_order_number;
00531 rpost_order_number--;
00532 }
00533
00534 void loopTree::setDepths(loopTreeNode * cur, int depth)
00535 {
00536
00537
00538 cur->depth(depth);
00539
00540
00541
00542 for (loop_set_p q = cur->nestedLoops().begin();
00543 q != cur->nestedLoops().end();
00544 ++q)
00545 setDepths(*q, depth+1);
00546 }
00547
00548 loopTree::EdgeKind loopTree::classifyEdge(basicblockNode * source,
00549 basicblockNode * target)
00550 {
00551 edge_map_p p;
00552
00553
00554
00555
00556 p = _backEdges.find(target);
00557 if (p != _backEdges.end()) {
00558 basicblock_set & edges = (*p).second;
00559 if (edges.find(source) != edges.end())
00560 return BackEdge;
00561 }
00562
00563
00564
00565 p = _forwardEdges.find(source);
00566 if (p != _forwardEdges.end()) {
00567 basicblock_set & edges = (*p).second;
00568 if (edges.find(target) != edges.end())
00569 return ForwardEdge;
00570 }
00571
00572
00573
00574 p = _crossEdges.find(source);
00575 if (p != _crossEdges.end()) {
00576 basicblock_set & edges = (*p).second;
00577 if (edges.find(target) != edges.end())
00578 return CrossEdge;
00579 }
00580
00581
00582
00583 return TreeEdge;
00584 }
00585
00586 void loopTree::report()
00587 {
00588 cout << "Loop tree:" << endl;
00589
00590 report(_top, 0);
00591 }
00592
00593
00594 void loopTree::report(loopTreeNode * cur, int level)
00595 {
00596 for (int i = 0; i < level*2; i++)
00597 cout << " ";
00598
00599 cur->report();
00600
00601 for (loop_set_p q = cur->nestedLoops().begin();
00602 q != cur->nestedLoops().end();
00603 ++q)
00604 report(*q, level+1);
00605 }
00606