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
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097 #define USE_STANDARD_TYPE
00098 #include "opt_defs.h"
00099 #include "opt_bb.h"
00100 #include "bb_node_set.h"
00101 #include "opt_cfg.h"
00102 #include "opt_htable.h"
00103 #include "opt_fb.h"
00104 #include "opt_cfg_trans.h"
00105 #include "config_wopt.h"
00106
00107 #include "opt_main.h"
00108
00109 using std::insert_iterator;
00110 using std::map;
00111 using std::set;
00112
00113
00114 #ifdef Is_True_On
00115 extern void show_graph(successor_graph& g);
00116 extern void show_zone(zone& z);
00117 extern void show_all_zones(successor_graph&, zone_iterator, zone_iterator);
00118 extern void mark_attr_begin();
00119 extern void mark_attr_end();
00120 extern void mark_translated_vertex(vertex_id, vertex_id);
00121 #endif
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132 template <class Insert_iterator>
00133 static bool
00134 build_successor_graph(CFG *cfg, successor_graph& g, Insert_iterator entry)
00135 {
00136 for (BB_NODE *bb = cfg->First_bb();
00137 bb != NULL;
00138 bb = bb->Next()) {
00139
00140 if (bb->Kind() == BB_REGIONSTART)
00141 return false;
00142
00143 if (bb->Branch_stmtrep() && bb->Branch_stmtrep()->Op() == OPC_REGION)
00144 return false;
00145
00146 if (bb->Kind() == BB_ENTRY)
00147 *entry++ = bb->Id();
00148
00149 BB_LIST_ITER bb_succ_iter;
00150 BB_NODE *succ;
00151 BB_NODE *fall_thru = NULL;
00152 int count = 0;
00153 FOR_ALL_ELEM(succ, bb_succ_iter, Init(bb->Succ())) {
00154 ++count;
00155 if (succ == bb->Next())
00156 fall_thru = succ;
00157 else
00158 add_edge(g, edge(bb->Id(), succ->Id()));
00159 }
00160 if (fall_thru)
00161 add_edge(g, edge(bb->Id(), fall_thru->Id()));
00162
00163 if (fall_thru)
00164 if (count == 2 ||
00165 bb->Kind() == BB_REGIONSTART ||
00166 bb->Kind() == BB_ENTRY ||
00167 (bb->Next() != NULL &&
00168 bb->Next()->Kind() == BB_REGIONSTART) ||
00169 (count == 1 &&
00170 bb->Branch_stmtrep() != NULL &&
00171 bb->Branch_stmtrep()->Op() != OPC_GOTO)) {
00172 edge *e = find_edge(g, bb->Id(), fall_thru->Id());
00173 e->must_fall_thru = true;
00174 }
00175 }
00176
00177
00178 if (cfg->Fake_exit_bb()) {
00179 BB_NODE *bb = cfg->Fake_exit_bb();
00180 BB_LIST_ITER bb_pred_iter;
00181 BB_NODE *pred;
00182 edge *fall_thru = NULL;
00183 FOR_ALL_ELEM(pred, bb_pred_iter, Init(bb->Pred())) {
00184 if (pred->Kind() == BB_EXIT)
00185 add_edge(g, edge(pred->Id(), bb->Id()));
00186 }
00187 }
00188
00189 #ifdef __STRESS_TESTING
00190
00191 for (int i = 0; i < g.size(); ++i) {
00192 if (g[i].size() > 0) {
00193 random_shuffle(g[i].begin(), g[i].end());
00194 }
00195 }
00196 #endif
00197
00198 return true;
00199 }
00200
00201
00202
00203
00204
00205
00206 void
00207 reconstruct_CFG(successor_graph& g, CFG *cfg, bool trace)
00208 {
00209 if (trace) {
00210 fprintf(TFile, "edges: \n");
00211 for (successor_graph::iterator e = g.begin(); e != g.end(); ++e)
00212 fprintf(TFile, "(%d,%d)%c ",
00213 first(*e), second(*e), (*e).must_fall_thru?'y':'n');
00214 fprintf(TFile,"\n");
00215 }
00216
00217
00218 {
00219 vector<bool> was_fall_thru_target(g.size(), false);
00220 vector<pair<edge,edge> > out_buffer;
00221 successor_graph::cluster_id next_cluster_id = g.size();
00222 for (successor_graph::iterator ep = g.begin();
00223 ep != g.end();
00224 ++ep) {
00225 if ((*ep).must_fall_thru) {
00226 if (was_fall_thru_target[second(*ep)]) {
00227 successor_graph::cluster_id v = next_cluster_id++;
00228 out_buffer.push_back(pair<edge,edge>(*ep,edge(v, second(*ep))));
00229 (*ep).second = v;
00230 if (trace)
00231 fprintf(TFile, "CFG trans: added fall-thru basic block %d\n", v);
00232 BB_NODE *bb = cfg->Create_and_allocate_bb(BB_GOTO);
00233 Is_True(bb->Id() == v, ("vertex id not match"));
00234 bb->Clear();
00235 bb->Set_id(v);
00236 bb->Set_labnam(0);
00237 bb->Set_kind(BB_GOTO);
00238 bb->Set_phi_list(NULL);
00239 } else
00240 was_fall_thru_target[second(*ep)] = true;
00241 }
00242 }
00243
00244 for (vector<pair<edge,edge> >::iterator p = out_buffer.begin();
00245 p != out_buffer.end();
00246 ++p) {
00247 add_edge(g, (*p).second);
00248
00249 if (cfg->Feedback()) {
00250 IDTYPE nx_src = (*p).first.first;
00251 IDTYPE nx_mid = (*p).second.first;
00252 IDTYPE nx_dst = (*p).second.second;
00253 cfg->Feedback()->Split_edge(nx_src, nx_mid, nx_dst);
00254 }
00255 }
00256 }
00257
00258
00259 vector<int> layout_order;
00260 {
00261 vector<int> rpo;
00262 generate_reverse_post_order(g, cfg->First_bb()->Id(), rpo);
00263
00264 if (trace) {
00265 fprintf(TFile, "rpo order: ");
00266 for (int i = 0; i < rpo.size(); ++i)
00267 fprintf(TFile, "%d ", rpo[i]);
00268 fprintf(TFile, "\n");
00269
00270 fprintf(TFile, "edges: \n");
00271 for (successor_graph::iterator e = g.begin(); e != g.end(); ++e)
00272 fprintf(TFile, "(%d,%d)%c ",
00273 first(*e), second(*e), (*e).must_fall_thru ? 'y' : 'n');
00274 fprintf(TFile,"\n");
00275 }
00276
00277 vector<bool> visited(g.size(), false);
00278
00279
00280 int i;
00281 for (i = 0; i < rpo.size(); ++i) {
00282 int cur_bb_id = rpo[i];
00283 for (successor_graph::fast_iterator e = g[cur_bb_id].begin();
00284 e != g[cur_bb_id].end();
00285 ++e) {
00286 if ((*e).must_fall_thru) {
00287 visited[second(*e)] = true;
00288 break;
00289 }
00290 }
00291 }
00292
00293 insert_iterator<vector<int> > ii(layout_order,layout_order.begin());
00294
00295 for (i = 0; i < rpo.size(); ++i) {
00296 int cur_bb_id = rpo[i];
00297 if (visited[cur_bb_id])
00298 continue;
00299
00300 bool cont;
00301 do {
00302 Is_True(! visited[cur_bb_id],
00303 ("restructure_CFG: conflicting layout requirement BB%d"
00304 " cannot be the fall-thru of BB%d.",
00305 cur_bb_id, *(rpo.end() - 1)));
00306
00307 *ii++ = cur_bb_id;
00308 visited[cur_bb_id] = true;
00309 cont = false;
00310 for (successor_graph::fast_iterator e = g[cur_bb_id].begin();
00311 e != g[cur_bb_id].end();
00312 ++e) {
00313 if ((*e).must_fall_thru) {
00314 cont = true;
00315 cur_bb_id = second(*e);
00316 visited[cur_bb_id] = false;
00317 break;
00318 }
00319 }
00320 } while (cont);
00321 }
00322
00323 if (trace) {
00324 fprintf(TFile, "layout order: ");
00325 for (int i = 0; i < layout_order.size(); ++i)
00326 fprintf(TFile, "%d ", layout_order[i]);
00327 fprintf(TFile, "\nold bb order: ");
00328 for (BB_NODE *bb = cfg->First_bb(); bb != NULL; bb = bb->Next())
00329 fprintf(TFile, "%d ", bb->Id());
00330 fprintf(TFile, "\n");
00331 }
00332
00333 Is_True(rpo.size() == layout_order.size(),
00334 ("some BB are lost during layout."));
00335
00336
00337
00338 {
00339
00340 vector<bool> reachable( g.size(), false );
00341 for (int i = layout_order.size() - 1; i >= 0; --i) {
00342 int bb_id = layout_order[i];
00343 reachable[bb_id] = true;
00344 }
00345
00346
00347 BB_NODE *bb_next = NULL;
00348 for (BB_NODE *bb = cfg->First_bb(); bb != NULL; bb = bb_next) {
00349 bb_next = bb->Next();
00350 if ( ! reachable[bb->Id()] && cfg->Removable_bb( bb ) ) {
00351 cfg->Remove_bb(bb);
00352 }
00353 }
00354 }
00355
00356
00357 for (i = layout_order.size() - 1; i >= 0; --i) {
00358 int bb_id = layout_order[i];
00359 BB_NODE *bb = cfg->Get_bb(bb_id);
00360 bb->Set_succ(NULL);
00361 bb->Set_pred(NULL);
00362 }
00363
00364 for (i = 0; i < layout_order.size() - 1; ++i) {
00365 int bb_id = layout_order[i];
00366 int bb_id2 = layout_order[i+1];
00367 BB_NODE *bb = cfg->Get_bb(bb_id);
00368 BB_NODE *bb2 = cfg->Get_bb(bb_id2);
00369 bb->Set_next(bb2);
00370 bb2->Set_prev(bb);
00371 }
00372 {
00373 BB_NODE *bb = cfg->Get_bb(layout_order[0]);
00374 bb->Set_prev(NULL);
00375 bb = cfg->Get_bb(layout_order[layout_order.size() - 1]);
00376 bb->Set_next(NULL);
00377 }
00378
00379
00380 cfg->Set_last_bb( cfg->Get_bb(*(layout_order.end()-1)) );
00381 }
00382
00383
00384
00385 for (successor_graph::iterator e = g.begin();
00386 e != g.end();
00387 ++e) {
00388 BB_NODE *bb1 = cfg->Get_bb(first(*e));
00389 BB_NODE *bb2 = cfg->Get_bb(second(*e));
00390
00391 if (bb2 != cfg->Fake_exit_bb())
00392 bb1->Append_succ(bb2, cfg->Mem_pool());
00393
00394 if (bb1 != cfg->Fake_entry_bb())
00395 bb2->Append_pred(bb1, cfg->Mem_pool());
00396 }
00397
00398
00399 {
00400 vector<bool> need_label(g.size(), false);
00401
00402
00403 int i;
00404 for (i = 0; i < layout_order.size(); ++i) {
00405 vertex_id bb_id = layout_order[i];
00406 vertex_id fall_thru_bb_id =
00407 (i + 1 < layout_order.size()) ? layout_order[i + 1] : -1;
00408 BB_NODE *bb = cfg->Get_bb(bb_id);
00409
00410
00411 if (bb == cfg->Fake_entry_bb()) continue;
00412
00413 if (1 == g[bb_id].size()) {
00414 vertex_id goto_bb_id = second(*g[bb_id].begin());
00415 BB_NODE *goto_bb = cfg->Get_bb(goto_bb_id);
00416 if (goto_bb_id == fall_thru_bb_id) {
00417
00418 STMTREP *bb_branch = bb->Branch_stmtrep();
00419 if (bb_branch != NULL &&
00420 OPC_GOTO == bb_branch->Op())
00421 bb->Remove_stmtrep(bb_branch);
00422 } else {
00423 if (goto_bb != cfg->Fake_exit_bb()) {
00424
00425 need_label[goto_bb_id] = true;
00426 if (goto_bb->Labnam() == 0) goto_bb->Add_label(cfg);
00427
00428 STMTREP *branch_sr = bb->Branch_stmtrep();
00429 if (branch_sr == NULL) {
00430 branch_sr = CXX_NEW( STMTREP(OPC_GOTO), cfg->Mem_pool() );
00431 branch_sr->Init_Goto( NULL, goto_bb->Labnam(), 0);
00432 bb->Append_stmtrep( branch_sr);
00433 } else {
00434 #ifdef KEY // bug 12839
00435 if (branch_sr->Op() == OPC_AGOTO) {
00436 branch_sr->Set_op(OPC_GOTO);
00437 branch_sr->Rhs()->DecUsecnt();
00438 branch_sr->Set_rhs(NULL);
00439 bb->Set_kind(BB_GOTO);
00440 }
00441 #endif
00442 Is_True(branch_sr->Op() == OPC_GOTO, ("expected OPC_GOTO"));
00443 branch_sr->Set_label_number(goto_bb->Labnam());
00444 }
00445 }
00446 }
00447 } else if (1 < g[bb_id].size()) {
00448 for (successor_graph::fast_iterator e = g[bb_id].begin();
00449 e != g[bb_id].end();
00450 ++e) {
00451 vertex_id goto_bb_id = second(*e);
00452 if (goto_bb_id != fall_thru_bb_id) {
00453 BB_NODE *goto_bb = cfg->Get_bb(goto_bb_id);
00454
00455 if (goto_bb != cfg->Fake_exit_bb()) {
00456
00457 need_label[goto_bb_id] = true;
00458 if (goto_bb->Labnam() == 0) goto_bb->Add_label(cfg);
00459
00460 STMTREP *branch_sr = bb->Branch_stmtrep();
00461 Is_True(branch_sr != NULL,
00462 ("missing branch stmt in BB%d", bb->Id()));
00463
00464
00465 if ((branch_sr->Op() == OPC_TRUEBR ||
00466 branch_sr->Op() == OPC_FALSEBR)) {
00467 if (branch_sr->Label_number() != goto_bb->Labnam()) {
00468 branch_sr->Set_st(NULL);
00469 branch_sr->Set_label_number(goto_bb->Labnam());
00470 }
00471 } else {
00472 Is_True(branch_sr->Op() == OPC_COMPGOTO ||
00473 branch_sr->Op() == OPC_XGOTO ||
00474 branch_sr->Op() == OPC_AGOTO ||
00475 branch_sr->Op() == OPC_IO ||
00476 branch_sr->Op() == OPC_REGION,
00477 ("branch not expected in BB%d.", bb_id));
00478 }
00479 }
00480 }
00481 }
00482 }
00483 }
00484
00485
00486 for (i = 0; i < layout_order.size(); ++i) {
00487 vertex_id bb_id = layout_order[i];
00488 BB_NODE *bb = cfg->Get_bb(bb_id);
00489 if (need_label[bb_id]) {
00490 if (bb->Label_stmtrep() == NULL) {
00491 Is_True(bb->Labnam() != 0, ("missing label name."));
00492 bb->Add_label_stmtrep(cfg->Mem_pool());
00493 }
00494 } else
00495
00496 if ( bb->Labnam() > 0 && ! LABEL_addr_saved( bb->Labnam() ) )
00497 bb->Remove_label_stmtrep();
00498
00499
00500
00501 if (bb->Phi_list() == NULL) {
00502 bb->Set_phi_list(CXX_NEW(PHI_LIST(bb), cfg->Mem_pool()));
00503 }
00504 }
00505 }
00506
00507 #ifdef Is_True_On
00508
00509 {
00510 for (int i = 0; i < layout_order.size(); ++i) {
00511 vertex_id bb_id = layout_order[i];
00512 BB_NODE *bb = cfg->Get_bb(bb_id);
00513 if (bb->Branch_stmtrep() != NULL) {
00514 OPERATOR br_op = OPCODE_operator(bb->Branch_stmtrep()->Op());
00515 if (br_op == OPR_TRUEBR || br_op == OPR_FALSEBR)
00516 FmtAssert(bb->Succ()->Len() == 2,
00517 ("TRUEBR/FALSEBR must have 2 succs (BB%d).", bb_id));
00518 if (br_op == OPR_GOTO)
00519 FmtAssert(bb->Succ()->Len() == 1,
00520 ("GOTO must have 1 succ (BB%d).", bb_id));
00521 }
00522 }
00523 }
00524 #endif
00525
00526 if (trace) {
00527 fprintf(TFile, "====\n After CFG transformation\n====\n");
00528 cfg->Print(TFile, false, (unsigned) -1);
00529 if (cfg->Feedback())
00530 cfg->Feedback()->Print(TFile);
00531 }
00532
00533
00534 cfg->Invalidate_and_update_aux_info();
00535 }
00536
00537
00538 void
00539 zone::print(FILE *fp)
00540 {
00541 fprintf(fp, "zone-id %d priority %f", id, priority());
00542 if (skip) fprintf(fp, " skipped:\n");
00543 else if (id != merged_into)
00544 fprintf(fp, " merged into %d:\n", merged_into);
00545 else
00546 fprintf(fp, ":\n");
00547
00548 if (id == merged_into && !skip) {
00549 fprintf(fp, "entry "); print_edges(entry, fp);
00550 fprintf(fp, "clone "); print_edges(clone, fp);
00551 fprintf(fp, "exit "); print_edges(exit, fp);
00552 fprintf(fp, "side_entry "); print_edges(side_entry, fp);
00553 }
00554 }
00555
00556
00557 void print_zone(FILE *fp, zone& zone)
00558 {
00559 zone.print(fp);
00560 }
00561
00562
00563 struct comp_zones {
00564 zone_container *zones;
00565 bool operator()(int x, int y) {
00566 #ifdef KEY
00567
00568
00569
00570
00571
00572
00573
00574
00575 if( x == y ){
00576 return false;
00577 }
00578 #endif
00579
00580 #if 0
00581 bool t = (*zones)[x].priority() > (*zones)[y].priority();
00582
00583 if (t) {
00584 Is_True( !((*zones)[y].priority() > (*zones)[x].priority()),
00585 ("vx > vy && vy > vx."));
00586 }
00587 #else
00588
00589
00590
00591
00592 double vx = (*zones)[x].priority();
00593 double vy = (*zones)[y].priority();
00594
00595 bool t = vx > vy;
00596
00597 if (t) {
00598 Is_True( !(vy > vx),
00599 ("vx > vy && vy > vx."));
00600 }
00601 #endif
00602 return t;
00603 }
00604 comp_zones(zone_container& z):zones(&z) {}
00605 };
00606
00607
00608 void print_zone(FILE *fp, zone_container& zones)
00609 {
00610 vector<int> sorted;
00611 int i;
00612 for (i = 0; i < zones.size(); ++i)
00613 sorted.push_back(i);
00614 sort(sorted.begin(), sorted.end(), comp_zones(zones));
00615
00616 for (i = 0; i < sorted.size(); ++i)
00617 zones[ sorted[i] ].print(fp);
00618 }
00619
00620
00621
00622
00623
00624 static bool no_bad_interference(zone& z1, zone& z2)
00625 {
00626 if (z1.loop_butterfly || z2.loop_butterfly) return false;
00627
00628 vector<edge> t;
00629 insert_iterator<vector<edge> > ins_t(t, t.begin());
00630
00631 set_intersection(z1.entry.begin(), z1.entry.end(),
00632 z2.clone.begin(), z2.clone.end(), ins_t);
00633 if (t.begin() != t.end()) return false;
00634
00635 set_intersection(z1.entry.begin(), z1.entry.end(),
00636 z2.exit.begin(), z2.exit.end(), ins_t);
00637 if (t.begin() != t.end()) return false;
00638
00639 set_intersection(z1.entry.begin(), z1.entry.end(),
00640 z2.entry.begin(), z2.entry.end(), ins_t);
00641 if (t.begin() != t.end()) return false;
00642
00643 set_intersection(z2.entry.begin(), z2.entry.end(),
00644 z1.clone.begin(), z1.clone.end(), ins_t);
00645 if (t.begin() != t.end()) return false;
00646
00647 set_intersection(z2.entry.begin(), z2.entry.end(),
00648 z1.exit.begin(), z1.exit.end(), ins_t);
00649 if (t.begin() != t.end()) return false;
00650
00651 return true;
00652 }
00653
00654
00655
00656
00657 static bool can_be_merged(zone& z1, zone& z2)
00658 {
00659 if (z1.loop_butterfly || z2.loop_butterfly) return false;
00660
00661 vector<edge> t;
00662 insert_iterator<vector<edge> > ins_t(t, t.begin());
00663
00664 set_intersection(z1.side_entry.begin(), z1.side_entry.end(),
00665 z2.clone.begin(), z2.clone.end(), ins_t);
00666 if (t.begin() != t.end()) return false;
00667
00668 set_intersection(z1.side_entry.begin(), z1.side_entry.end(),
00669 z2.entry.begin(), z2.entry.end(), ins_t);
00670 if (t.begin() != t.end()) return false;
00671
00672 set_intersection(z2.side_entry.begin(), z2.side_entry.end(),
00673 z1.clone.begin(), z1.clone.end(), ins_t);
00674 if (t.begin() != t.end()) return false;
00675
00676 set_intersection(z2.side_entry.begin(), z2.side_entry.end(),
00677 z1.entry.begin(), z1.entry.end(), ins_t);
00678 if (t.begin() != t.end()) return false;
00679
00680 return true;
00681 }
00682
00683
00684
00685 static void merge_zone(zone& z1, zone& z2)
00686 {
00687 vector<edge> entry, clone, exit, side_entry;
00688 insert_iterator<vector<edge> > ins_entry(entry, entry.begin());
00689 insert_iterator<vector<edge> > ins_clone(clone, clone.begin());
00690 insert_iterator<vector<edge> > ins_exit(exit, exit.begin());
00691 insert_iterator<vector<edge> > ins_side_entry(side_entry,
00692 side_entry.begin());
00693
00694 set_union(z1.entry.begin(), z1.entry.end(),
00695 z2.entry.begin(), z2.entry.end(), ins_entry);
00696 set_union(z1.clone.begin(), z1.clone.end(),
00697 z2.clone.begin(), z2.clone.end(), ins_clone);
00698 set_union(z1.exit.begin(), z1.exit.end(),
00699 z2.exit.begin(), z2.exit.end(), ins_exit);
00700 set_union(z1.side_entry.begin(), z1.side_entry.end(),
00701 z2.side_entry.begin(), z2.side_entry.end(), ins_side_entry);
00702
00703 z1.entry.erase(z1.entry.begin(), z1.entry.end());
00704 z1.clone.erase(z1.clone.begin(), z1.clone.end());
00705 z1.exit.erase(z1.exit.begin(), z1.exit.end());
00706 z1.side_entry.erase(z1.side_entry.begin(), z1.side_entry.end());
00707
00708 z1.clone.insert(z1.clone.begin(), clone.begin(), clone.end());
00709
00710 insert_iterator<zone::edge_container> ins_z1_entry(z1.entry,
00711 z1.entry.begin());
00712 insert_iterator<zone::edge_container> ins_z1_exit(z1.exit, z1.exit.begin());
00713
00714 set_difference(entry.begin(), entry.end(),
00715 clone.begin(), clone.end(), ins_z1_entry);
00716 set_difference( exit.begin(), exit.end(),
00717 clone.begin(), clone.end(), ins_z1_exit);
00718
00719 z1.profit += z2.profit;
00720 z1.code_expansion_saved = unique_bb_count(z1.clone,z1.exit);
00721 z2.merged_into = z1.id;
00722 }
00723
00724
00725
00726
00727
00728 class interference_cache {
00729 vector<int> zones;
00730 map<vertex_id, set<int> > belongs_to;
00731
00732 void find_interference_from_edge(edge e, set<int>& interfered_zones) {
00733 map<vertex_id, set<int> >::iterator t1 = belongs_to.find(first(e));
00734 map<vertex_id, set<int> >::iterator t2 = belongs_to.find(second(e));
00735 if (t1 != belongs_to.end())
00736 interfered_zones.insert((*t1).second.begin(), (*t1).second.end());
00737 if (t2 != belongs_to.end())
00738 interfered_zones.insert((*t2).second.begin(), (*t2).second.end());
00739 }
00740
00741 void add_edge(edge e, int cur_zone_id) {
00742 if (belongs_to.find(first(e)) == belongs_to.end())
00743 belongs_to[first(e)] = set<int>();
00744 if (belongs_to.find(second(e)) == belongs_to.end())
00745 belongs_to[second(e)] = set<int>();
00746 belongs_to[first(e)].insert(cur_zone_id);
00747 belongs_to[second(e)].insert(cur_zone_id);
00748 }
00749
00750 public:
00751 void find_interference_zones(zone& cur_zone, set<int>& interfered_zones) {
00752 int j;
00753 for (j = 0; j < cur_zone.clone.size(); ++j)
00754 find_interference_from_edge(cur_zone.clone[j], interfered_zones);
00755 for (j = 0; j < cur_zone.exit.size(); ++j)
00756 find_interference_from_edge(cur_zone.exit[j], interfered_zones);
00757 }
00758
00759 void add_zone(zone& cur_zone) {
00760 int cur_zone_id = cur_zone.id;
00761 int j;
00762 for (j = 0; j < cur_zone.clone.size(); ++j)
00763 add_edge(cur_zone.clone[j], cur_zone_id);
00764 for (j = 0; j < cur_zone.exit.size(); ++j)
00765 add_edge(cur_zone.exit[j], cur_zone_id);
00766 }
00767 };
00768
00769
00770
00771 static bool zone_is_clonable(zone& z, CFG *cfg, const BVECTOR &vol)
00772 {
00773
00774 if (z.code_expansion() > WOPT_Enable_CFG_Opt_Limit)
00775 return false;
00776
00777 bool clone_loop = (z.loop_butterfly != 0);
00778 zone::iterator e;
00779 for (e = z.clone.begin(); e != z.clone.end(); ++e) {
00780 vertex_id from = (*e).first;
00781 vertex_id to = (*e).second;
00782 if (!cfg->Get_bb(from)->Clonable(clone_loop, &vol)) return false;
00783 if (!cfg->Get_bb(to)->Clonable(clone_loop, &vol)) return false;
00784 }
00785 for (e = z.entry.begin(); e != z.entry.end(); ++e) {
00786 vertex_id to = (*e).second;
00787 if (!cfg->Get_bb(to)->Clonable(clone_loop, &vol)) return false;
00788 }
00789 for (e = z.exit.begin(); e != z.exit.end(); ++e) {
00790 vertex_id from = (*e).first;
00791 if (!cfg->Get_bb(from)->Clonable(clone_loop, &vol)) return false;
00792 }
00793 return true;
00794 }
00795
00796
00797
00798
00799
00800
00801 void sort_merge_and_delete_zones(zone_container& zones, CFG *cfg, bool trace)
00802 {
00803 OPT_POOL_Push(cfg->Loc_pool(), -1);
00804 {
00805
00806
00807
00808 BVECTOR vol(cfg->Htable()->Coderep_id_cnt()+1,
00809 bool(FALSE),
00810 BVECTOR_ALLOCATOR(cfg->Loc_pool()));
00811
00812 Set_volatile_map(cfg, vol);
00813
00814 vector<int> sorted;
00815 int i;
00816 for (i = 0; i < zones.size(); ++i) {
00817 sorted.push_back(i);
00818 zones[i].canonicalize();
00819 }
00820 sort(sorted.begin(), sorted.end(), comp_zones(zones));
00821
00822 interference_cache zones_will_be_cloned;
00823
00824 for (i = 0; i < sorted.size(); ++i) {
00825
00826 int cur_zone_id = sorted[i];
00827 zone *cur_zone = &zones[cur_zone_id];
00828 if (trace)
00829 fprintf(TFile, "priority %f\n", zones[cur_zone_id].priority());
00830
00831 if (!zone_is_clonable(*cur_zone, cfg, vol)) {
00832 if (trace)
00833 fprintf(TFile, "zone %d is not clonable.\n", cur_zone_id);
00834 (*cur_zone).skip = true;
00835 continue;
00836 }
00837
00838 set<int> interfered_zones;
00839 zones_will_be_cloned.find_interference_zones(*cur_zone,
00840 interfered_zones);
00841
00842 bool skip = false;
00843 vector<int> need_merge;
00844 for (set<int>::iterator k = interfered_zones.begin();
00845 k != interfered_zones.end();
00846 ++k) {
00847 int zone_id = *k;
00848 if (zones[zone_id].merged_into == zone_id) {
00849 if (!can_be_merged(*cur_zone, zones[zone_id])) {
00850 if (no_bad_interference(*cur_zone, zones[zone_id])) {
00851
00852 } else {
00853 if (trace)
00854 fprintf(TFile,
00855 "zone %d skipped due to overlapping with zone %d\n",
00856 (*cur_zone).id, zone_id);
00857 skip = true;
00858 break;
00859 }
00860 } else {
00861 need_merge.push_back(zone_id);
00862 }
00863 }
00864 }
00865 if (need_merge.size() > 1)
00866 if (!WOPT_Enable_CFG_Merge_Multi_Zone ||
00867 (Cur_PU_Feedback && !WOPT_Enable_CFG_Merge_Multi_Zone_Set)) {
00868 if (trace)
00869 fprintf(TFile,
00870 "zone %d skipped due to overlapping with multiples zones\n",
00871 (*cur_zone).id);
00872 skip = true;
00873 }
00874 if (!skip) {
00875 for (vector<int>::iterator k = need_merge.begin();
00876 k != need_merge.end();
00877 ++k) {
00878 int zone_id = *k;
00879 if (trace)
00880 fprintf(TFile, "merging zone %d and zone %d\n",
00881 (*cur_zone).id, zone_id);
00882 merge_zone(*cur_zone, zones[zone_id]);
00883 }
00884 zones_will_be_cloned.add_zone(*cur_zone);
00885 }
00886 (*cur_zone).skip = skip;
00887 }
00888 }
00889 OPT_POOL_Pop(cfg->Loc_pool(), -1);
00890 }
00891
00892 static void remove_SCF(BB_NODE *header)
00893 {
00894
00895 BB_LOOP *loop = header->Loop();
00896 BB_NODE *bb;
00897 BB_NODE_SET_ITER bb_iter;
00898 FOR_ALL_ELEM(bb, bb_iter, Init(loop->True_body_set())) {
00899 switch (bb->Kind()) {
00900 case BB_DOSTART:
00901 case BB_DOEND:
00902 case BB_DOHEAD:
00903 case BB_DOSTEP:
00904 case BB_DOTAIL:
00905 case BB_REPEATBODY:
00906 case BB_REPEATEND:
00907 case BB_WHILEEND:
00908 bb->Set_kind(BB_GOTO);
00909 }
00910 }
00911 }
00912
00913
00914
00915
00916 void
00917 generate_zones(COMP_UNIT *cu, successor_graph &g, zone_container& zones,
00918 bool do_butterfly, bool trace, bool display)
00919 {
00920 if (WOPT_Enable_CFG_Opt1)
00921 generate_conditional_const_zones(cu, g, zones, trace);
00922
00923 if (do_butterfly)
00924 generate_loop_butterfly_zones(cu, g, zones,
00925 WOPT_Enable_CFG_Opt2_Limit, trace);
00926
00927 if (trace) {
00928 fprintf(TFile, ("set of clone zones before merging:\n"));
00929 print_zone(TFile, zones);
00930 }
00931 sort_merge_and_delete_zones(zones, cu->Cfg(), trace);
00932 if (trace) {
00933 fprintf(TFile, ("set of clone zones after merging:\n"));
00934 print_zone(TFile, zones);
00935 }
00936
00937 for (zone_iterator ri = zones.begin(); ri != zones.end(); ++ri) {
00938 if ((*ri).loop_butterfly) {
00939 edge e = *((*ri).entry.begin());
00940 remove_SCF(cu->Cfg()->Get_bb(e.second));
00941 }
00942 }
00943
00944 #ifdef Is_True_On
00945 if (display) show_all_zones(g, zones.begin(), zones.end());
00946 #endif
00947 }
00948
00949
00950
00951
00952
00953
00954
00955
00956
00957
00958
00959
00960
00961
00962
00963 static void connect_butterfly_zone(successor_graph& g, zone& z,
00964 vertex_id old_header, vertex_id new_header,
00965 vertex_id new_preheader,
00966 OPT_FEEDBACK *feedback)
00967 {
00968 vector<edge> edge_incident_to_header;
00969 insert_iterator<vector<edge> > ins(edge_incident_to_header,
00970 edge_incident_to_header.begin());
00971 zone::iterator e;
00972 for (e = z.entry.begin(); e != z.entry.end(); ++e) {
00973 if ((*e).second == old_header)
00974 *ins++ = (*e);
00975 }
00976 for (e = z.clone.begin(); e != z.clone.end(); ++e) {
00977 if ((*e).second == old_header)
00978 *ins++ = (*e);
00979 }
00980 for (e = z.exit.begin(); e != z.exit.end(); ++e) {
00981 if ((*e).second == old_header)
00982 *ins++ = (*e);
00983 }
00984 for (e = z.side_entry.begin(); e != z.side_entry.end(); ++e) {
00985 if ((*e).second == old_header)
00986 *ins++ = (*e);
00987 }
00988
00989 {
00990 for (vector<edge>::iterator e = edge_incident_to_header.begin();
00991 e != edge_incident_to_header.end();
00992 ++e) {
00993 vertex_id from = (*e).first;
00994 vertex_id to = (*e).second;
00995 edge *fix = find_edge(g, from, to);
00996 (*fix).second = new_preheader;
00997 }
00998 }
00999 add_edge(g, edge(new_preheader, new_header, true));
01000
01001 if (feedback) {
01002 feedback->Split_node(old_header, new_preheader);
01003 feedback->Move_edge_dest(new_preheader, old_header, new_header);
01004 }
01005 }
01006
01007
01008
01009
01010 static void connect_acyclic_zone(successor_graph& g, zone& z,
01011 map<vertex_id,vertex_id>& old_to_new,
01012 OPT_FEEDBACK *feedback)
01013 {
01014 for (zone::iterator e = z.entry.begin();
01015 e != z.entry.end();
01016 ++e) {
01017 vertex_id from = (*e).first;
01018 vertex_id to = (*e).second;
01019 edge *fix = find_edge(g, from, to);
01020 Is_True(fix, ("cannot update entry edge (%d,%d).", from, to));
01021 (*fix).second = old_to_new[to];
01022
01023 if (feedback) {
01024 feedback->Move_edge_dest(from, to, old_to_new[to]);
01025
01026
01027 }
01028 }
01029 }
01030
01031
01032
01033
01034
01035
01036
01037
01038 static void
01039 clone_zones(successor_graph& g, vector<vertex_id>& entry,
01040 zone_iterator first, zone_iterator last, CFG *cfg,
01041 bool trace, bool display)
01042 {
01043 vertex_id new_id = cfg->Total_bb_count();
01044 map<vertex_id, vertex_id> new_to_old;
01045
01046 if (trace) {
01047 fprintf(TFile, "before clone_zone:\n");
01048 print_nodes(g, TFile);
01049 print_edges(g, TFile);
01050 }
01051
01052 for (zone_iterator ri = first; ri != last; ++ri) {
01053
01054 if ((*ri).skip) continue;
01055 if ((*ri).id != (*ri).merged_into) continue;
01056
01057 map<vertex_id, vertex_id> old_to_new;
01058
01059 zone::iterator e;
01060 for (e = (*ri).clone.begin(); e != (*ri).clone.end(); ++e) {
01061 vertex_id from = (*e).first;
01062 vertex_id to = (*e).second;
01063 if (old_to_new.find(from) == old_to_new.end()) {
01064 old_to_new[from] = new_id++;
01065 }
01066 if (old_to_new.find(to) == old_to_new.end()) {
01067 old_to_new[to] = new_id++;
01068 }
01069 edge* old_edge = find_edge(g, from, to);
01070 add_edge(g, edge(old_to_new[from], old_to_new[to],
01071 old_edge->must_fall_thru));
01072 }
01073
01074 for (e = (*ri).exit.begin(); e != (*ri).exit.end(); ++e) {
01075 vertex_id from = (*e).first;
01076 vertex_id to = (*e).second;
01077 if (old_to_new.find(from) == old_to_new.end()) {
01078 old_to_new[from] = new_id++;
01079 }
01080 edge* old_edge = find_edge(g, from, to);
01081 add_edge(g, edge(old_to_new[from], to, old_edge->must_fall_thru));
01082 }
01083 Is_True(new_id == g.size(), ("new_id != g.size()"));
01084
01085
01086 if ( cfg->Feedback() ) {
01087 cfg->Feedback()->Clone_zone( *ri, old_to_new );
01088 }
01089
01090 vertex_id new_preheader = new_id++;
01091 if ((*ri).loop_butterfly) {
01092 vertex_id header = (*ri).loop_butterfly;
01093 connect_butterfly_zone(g, *ri, header, old_to_new[header],
01094 new_preheader, cfg->Feedback());
01095 } else
01096 connect_acyclic_zone(g, *ri, old_to_new, cfg->Feedback());
01097
01098 for (map<vertex_id,vertex_id>::iterator mi = old_to_new.begin();
01099 mi != old_to_new.end();
01100 ++mi) {
01101 vertex_id o = (*mi).first;
01102 vertex_id n = (*mi).second;
01103 new_to_old[n] = o;
01104 }
01105 }
01106
01107 vector<bool> reachable(g.size(), false);
01108 for (vector<vertex_id>::iterator p = entry.begin();
01109 p != entry.end();
01110 ++p)
01111 find_reachable_vertex_set(g, *p, reachable);
01112
01113 vector<edge> g_tmp;
01114 subgraph(g, g_tmp, reachable);
01115 erase(g);
01116 copy(g_tmp, g);
01117
01118 if (trace) {
01119 fprintf(TFile, "after clone_zone:\n");
01120 print_nodes(g, TFile);
01121 print_edges(g, TFile);
01122 fprintf(TFile, "translation: ");
01123 for (vertex_id i = 0; i < g.size(); i++)
01124 if (reachable[i] && new_to_old[i] != 0)
01125 fprintf(TFile, "%d<-%d ", i, new_to_old[i]);
01126 fprintf(TFile, "\n");
01127 if (cfg->Feedback())
01128 cfg->Feedback()->Print(TFile);
01129 }
01130
01131 while (cfg->Total_bb_count() < g.size())
01132 cfg->Create_and_allocate_bb(BB_GOTO);
01133
01134 #ifdef Is_True_On
01135 if (display) show_graph(g);
01136 #endif
01137
01138 vertex_id i;
01139 for (i = 0; i < g.size(); i++)
01140 if (reachable[i] && new_to_old[i] != 0)
01141 cfg->Clone_bb(new_to_old[i] , i );
01142
01143 #ifdef Is_True_On
01144 if (display) {
01145 mark_attr_begin();
01146 for (i = 0; i < g.size(); i++)
01147 if (reachable[i] && new_to_old[i] != 0)
01148 mark_translated_vertex(new_to_old[i], i);
01149 mark_attr_end();
01150 }
01151 #endif
01152 }
01153
01154 void
01155 CFG_transformation(COMP_UNIT *cu, bool do_butterfly, bool trace, bool display)
01156 {
01157 CFG *cfg = cu->Cfg();
01158 cfg->Analyze_loops();
01159
01160 successor_graph g;
01161 vector<vertex_id> entry;
01162 bool ok = build_successor_graph(cfg, g,
01163 insert_iterator<vector<vertex_id> >
01164 (entry, entry.begin()));
01165 if (!ok) {
01166 if (trace)
01167 fprintf(TFile, ("skip CFG transformation because of REGION."));
01168 return;
01169 }
01170 if (trace) {
01171 fprintf(TFile, "Successor graph:\n");
01172 print_nodes(g, TFile);
01173 fprintf(TFile, "edges: \n");
01174 for (successor_graph::iterator e = g.begin(); e != g.end(); ++e)
01175 fprintf(TFile, "(%d,%d)%c ",
01176 first(*e), second(*e), (*e).must_fall_thru?'y':'n');
01177 fprintf(TFile,"\n");
01178 }
01179
01180 vector<zone> zones;
01181 generate_zones(cu, g, zones, do_butterfly, trace, display);
01182 clone_zones(g, entry, zones.begin(), zones.end(), cfg, trace, display);
01183
01184 reconstruct_CFG(g, cfg, trace);
01185
01186 cfg->Invalidate_loops();
01187 cfg->Analyze_loops();
01188 }
01189
01190
01191
01192 void print_succ_graph(successor_graph& g)
01193 {
01194 print_edges(g, stdout);
01195 }
01196
01197 void print_pred_graph(predecessor_graph& g)
01198 {
01199 print_edges(g, stdout);
01200 }
01201
01202
01203 void print_path_type(path_type *p, FILE *fp)
01204 {
01205 fprintf(fp, "path (wt %g): ", (*p).wt);
01206 for (int i = 0; i < (*p).bbs.size(); ++i)
01207 fprintf(fp, "%d ", (*p).bbs[i]);
01208 fprintf(fp, "\n");
01209 }
01210
01211 void print_vertex_set(set<vertex_id> *s, FILE *fp)
01212 {
01213 fprintf(fp, "vertex set: ");
01214 for (set<vertex_id>::iterator si = (*s).begin();
01215 si != (*s).end();
01216 ++si) {
01217 fprintf(fp, "%d ", *si);
01218 }
01219 fprintf(fp, "\n");
01220 }
01221