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 <iomanip>
00040 #include <algorithm>
00041 #include "proceduredb.h"
00042 #include "memoryblock.h"
00043
00044 procedureDB::procedureDB()
00045 : Walker(Preorder, Subtree),
00046 _procedures(),
00047 _callgraph(0),
00048 _need_reanalysis(),
00049 _root(0),
00050 _callstack(),
00051 _worklist()
00052 {}
00053
00054 procedureDB::~procedureDB()
00055 {
00056 clear();
00057 }
00058
00059 void procedureDB::build(procNode * root, Linker & linker)
00060 {
00061
00062
00063
00064 if (pointerOptions::Verbose)
00065 cout << "procedureDB::build " << root->decl()->name() << endl;
00066
00067
00068
00069 _callgraph = new callGraph(root, linker);
00070
00071
00072
00073 const proc_decl_map & procs = linker.procedures();
00074 for (proc_decl_map_cp p = procs.begin();
00075 p != procs.end();
00076 ++p)
00077 add_procedure((*p).second);
00078
00079
00080
00081 for (proc_info_map_p p = _procedures.begin();
00082 p != _procedures.end();
00083 ++p)
00084 {
00085 procNode * proc = (*p).first;
00086 procedureInfo * info = (*p).second;
00087
00088
00089
00090 callGraphNode * node = _callgraph->lookup(proc);
00091
00092
00093
00094 callgraph_node_set cg_ancestors;
00095 node->ancestors(cg_ancestors);
00096
00097
00098
00099 procedureinfo_set ancestors;
00100
00101 for (callgraph_node_set_p q = cg_ancestors.begin();
00102 q != cg_ancestors.end();
00103 ++q)
00104 {
00105 callGraphNode * cg_ancestor = *q;
00106
00107
00108
00109 procedureInfo * ancestor = lookup(cg_ancestor->proc());
00110 ancestors.insert(ancestor);
00111 }
00112
00113
00114
00115 info->add_ancestor_set(ancestors);
00116
00117
00118
00119 if (ancestors.find(info) != ancestors.end()) {
00120 info->set_recursive();
00121 cout << " + " << info->qualified_name() << " is recursive" << endl;
00122 }
00123 }
00124
00125
00126
00127 _root = lookup(root);
00128 }
00129
00130 void procedureDB::clear()
00131 {
00132 for (proc_info_map_p p = _procedures.begin();
00133 p != _procedures.end();
00134 ++p) {
00135 delete (*p).second;
00136 }
00137
00138 _procedures.clear();
00139
00140 delete _callgraph;
00141 _callgraph = 0;
00142 }
00143
00144
00145
00146
00147
00148
00149 void procedureDB::add_procedure(procNode * proc)
00150 {
00151 string & name = proc->decl()->name();
00152
00153 if (pointerOptions::Verbose)
00154 cout << "procedureDB: Add procedure " << name << endl;
00155
00156 _procedures[proc] = new procedureInfo(proc);
00157 }
00158
00159 procedureInfo * procedureDB::lookup(procNode * proc)
00160 {
00161 proc_info_map_p p = _procedures.find(proc);
00162 if (p != _procedures.end())
00163 return (*p).second;
00164 else
00165 return 0;
00166 }
00167
00173 bool procedureDB::is_recursive_call(procedureInfo * callee,
00174 int & num_instances)
00175 {
00176
00177
00178
00179
00180
00181
00182 bool result = false;
00183 num_instances = 0;
00184
00185
00186
00187 for (procedurecall_stack_p p = _callstack.begin();
00188 p != _callstack.end();
00189 ++p)
00190 {
00191 procedureInfo * current = (*p).second;
00192 if (current == callee) {
00193 result = true;
00194 num_instances++;
00195 }
00196 }
00197
00198 if (result && ( ! callee->is_recursive())) {
00199
00200
00201
00202
00203
00204
00205
00206 callee->set_recursive();
00207 }
00208
00209 return result;
00210 }
00211
00218 void procedureDB::call_to(stmtLocation * callsite, procedureInfo * callee)
00219 {
00220
00221
00222
00223 procedurecall_pair cp(callsite, callee);
00224 _callstack.push_back(cp);
00225 }
00226
00232 void procedureDB::return_from()
00233 {
00234
00235
00236 _callstack.pop_back();
00237 }
00238
00243 void procedureDB::setup_analysis()
00244 {
00245 for (proc_info_map_p p = _procedures.begin();
00246 p != _procedures.end();
00247 ++p)
00248 {
00249 procedureInfo * info = (*p).second;
00250 if (info != _root)
00251 _need_reanalysis.insert(info);
00252 }
00253 }
00254
00255 bool procedureDB::is_visible_to_caller(procedureInfo * info,
00256 memoryBlock * block)
00257 {
00258
00259
00260
00261 procNode * proc = block->local_to();
00262
00263 if ( ! proc)
00264 return true;
00265
00266 if ( ! info)
00267 return false;
00268
00269
00270
00271
00272 if (proc == info->proc())
00273 return false;
00274
00275
00276
00277 procedureInfo * owner = lookup(proc);
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298 procedurecall_stack_p p = _callstack.begin();
00299 while (p != _callstack.end()) {
00300
00301 procedureInfo * cur = (*p).second;
00302
00303
00304
00305 if (cur == info)
00306 return false;
00307
00308
00309
00310 if (cur == owner)
00311 return true;
00312
00313 ++p;
00314 }
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327 return false;
00328 }
00329
00336 bool procedureDB::is_visible_to(procedureInfo * info,
00337 memoryBlock * block)
00338 {
00339
00340
00341
00342 procNode * proc = block->local_to();
00343
00344 if ( ! proc)
00345 return true;
00346
00347 if ( ! info)
00348 return false;
00349
00350
00351
00352 if (proc == info->proc())
00353 return true;
00354
00355
00356
00357 procedureInfo * owner = lookup(proc);
00358
00359
00360
00361 const procedureinfo_set & ancestors = info->ancestors();
00362
00363 procedureinfo_set_cp found = ancestors.find(owner);
00364
00365 if (found != ancestors.end())
00366 return true;
00367 else
00368 return false;
00369 }
00370
00375 procedureInfo * procedureDB::current_caller()
00376 {
00377
00378
00379 procedurecall_stack::reverse_iterator p = _callstack.rbegin();
00380
00381
00382
00383 p++;
00384
00385
00386
00387 if ( ! (p == _callstack.rend()) )
00388 return (*p).second;
00389 else
00390 return 0;
00391 }
00392
00397 void procedureDB::clear_call_stack()
00398 {
00399 _callstack.clear();
00400
00401
00402
00403 procedurecall_pair root_entry((stmtLocation *)0, _root);
00404 _callstack.push_back(root_entry);
00405 }
00406
00407
00408 void procedureDB::print_call_stack(ostream & out)
00409 {
00410 bool first = true;
00411
00412 if (_callstack.empty())
00413 out << "(empty)";
00414 else {
00415
00416 for (procedurecall_stack_p p = _callstack.begin();
00417 p != _callstack.end();
00418 ++p)
00419 {
00420 stmtLocation * s = (*p).first;
00421
00422 if (s) {
00423 s->print_callsite(cout);
00424 cout << '/';
00425 }
00426 }
00427
00428 procedureInfo * top = _callstack.back().second;
00429 cout << top->name();
00430 }
00431 }
00432
00433 void procedureDB::progress_meter(ostream & out)
00434 {
00435 for (procedurecall_stack_p p = _callstack.begin();
00436 p != _callstack.end();
00437 ++p)
00438 {
00439 procedureInfo * current = (*p).second;
00440
00441 out << current->qualified_name();
00442 }
00443 }
00444
00451 void procedureDB::mark_for_reanalysis(procedureInfo * info,
00452 stmtLocation * callsite,
00453 bool include_self)
00454 {
00455
00456 pair< procedureinfo_set_p, bool> res;
00457
00458 if (pointerOptions::Verbose) {
00459 cout << " Mark for reanalysis: " << info->name();
00460
00461 if (callsite)
00462 cout << " at " << *callsite << endl;
00463 else
00464 cout << " (no callsite)" << endl;
00465 }
00466
00467
00468
00469 if (include_self)
00470 _need_reanalysis.insert(info);
00471
00472
00473
00474 procedureInfo * current = info;
00475 while (current->first_caller()) {
00476
00477 procedureInfo * first_caller = current->first_caller();
00478
00479 res = _need_reanalysis.insert(first_caller);
00480 if (pointerOptions::Verbose) {
00481 if (res.second)
00482 cout << " + " << first_caller->name() << endl;
00483 else
00484 cout << " - " << first_caller->name() << endl;
00485 }
00486
00487 current = first_caller;
00488 }
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506 }
00507
00512 void procedureDB::mark_one_for_reanalysis(procedureInfo * info)
00513 {
00514
00515
00516 pair< procedureinfo_set_p, bool> res = _need_reanalysis.insert(info);
00517 }
00518
00525 bool procedureDB::is_reanalysis_required(procedureInfo * info)
00526 {
00527 if (pointerOptions::Verbose)
00528 cout << "Is analysis for " << info->name() << " mandatory?" << endl;
00529
00530
00531
00532 procedureinfo_set_p p = _need_reanalysis.find(info);
00533
00534
00535
00536 if (p != _need_reanalysis.end()) {
00537 _need_reanalysis.erase(p);
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562 if (pointerOptions::Verbose)
00563 cout << " ....yes" << endl;
00564
00565 return true;
00566 }
00567 else {
00568
00569 if (pointerOptions::Verbose)
00570 cout << " ....no" << endl;
00571
00572 return false;
00573 }
00574 }
00575
00578 void procedureDB::print_leftovers()
00579 {
00580 cout << "Procedures that still need analysis:" << endl;
00581 for (procedureinfo_set_p p = _need_reanalysis.begin();
00582 p != _need_reanalysis.end();
00583 ++p)
00584 {
00585 if ((*p)->analysis_count() > 0)
00586 cout << " +" << (*p)->name() << endl;
00587 }
00588 }
00589
00590 int procedureDB::times_called(procedureInfo * info)
00591 {
00592 callGraphNode * node = _callgraph->lookup(info->proc());
00593 return node->times_called();
00594 }
00595
00596 void procedureDB::stats(ostream & out)
00597 {
00598
00599 if (pointerOptions::Show_procedures) {
00600
00601 out.width(20);
00602 out << "Procedure";
00603
00604 out.width(6);
00605 out << "CI";
00606
00607 out.width(6);
00608 out << "Rec";
00609
00610 out.width(8);
00611 out << "Sites";
00612
00613 out.width(8);
00614 out << "X in";
00615
00616 out.width(8);
00617 out << "X out";
00618
00619 out.width(8);
00620 out << "Anc";
00621
00622 out.width(8);
00623 out << "Calls";
00624
00625 out.width(12);
00626 out << "Time (self)";
00627
00628 out.width(12);
00629 out << "Time (total)";
00630
00631 out.width(8);
00632 out << "Cont";
00633
00634 out.width(8);
00635 out << "Size";
00636
00637 out << endl;
00638
00639 for (proc_info_map_p p = _procedures.begin();
00640 p != _procedures.end();
00641 ++p)
00642 {
00643 procedureInfo * info = (*p).second;
00644
00645 if ( ! info->is_library_routine())
00646 info->stats(out);
00647 }
00648
00649 out.width(0);
00650 }
00651 }
00652
00655 void procedureDB::number_of_procedures(int & total, int & analyzed,
00656 int & context_insensitive,
00657 int & recursive,
00658 int & unanalyzed,
00659 int & program_size)
00660 {
00661 total = 0;
00662 analyzed = 0;
00663 context_insensitive = 0;
00664 recursive = 0;
00665 program_size = 0;
00666 unanalyzed = 0;
00667
00668 for (proc_info_map_p p = _procedures.begin();
00669 p != _procedures.end();
00670 ++p)
00671 {
00672 procedureInfo * info = (*p).second;
00673
00674 total++;
00675
00676 if (info->analysis_count() > 0) {
00677 analyzed++;
00678
00679 if (info->is_context_insensitive()) {
00680
00681 context_insensitive++;
00682
00683 if (info->is_recursive())
00684
00685 recursive++;
00686 }
00687
00688 program_size += info->procedure_size();
00689 }
00690 else
00691 if ( ! info->is_library_routine())
00692 unanalyzed++;
00693 }
00694 }
00695
00696
00697
00698
00699
00700
00701 procedureInfo::procedureInfo(procNode * the_proc)
00702 : _proc(the_proc),
00703 _worklist(),
00704 _forward_worklist_order(),
00705 _forward_basicblock_order(),
00706 _backward_worklist_order(),
00707 _backward_basicblock_order(),
00708 _merge_points(),
00709 _dominance_frontiers(new DFPreds(the_proc)),
00710 _loops(new loopTree(the_proc)),
00711 _callsites(),
00712 _return_variable(0),
00713 _return_stmt(0),
00714 _never_returns(false),
00715 _context_insensitive(false),
00716 _prefer_context_sensitive(false),
00717 _only_context(0),
00718 _external_inputs(),
00719 _external_outputs(),
00720 _ancestors(),
00721 _first_caller(0),
00722 _calls(),
00723 _is_recursive(false),
00724 _blocks_to_skip(),
00725 _active_edges(),
00726 _true_branches(),
00727 _analysis_count(0),
00728 _verbose(false)
00729 {
00730
00731
00732
00733
00734 basicblock_set visited;
00735 basicblock_list order;
00736
00737
00738
00739
00740 basicblock_list rpo_order;
00741
00742 visited.clear();
00743 reverse_post_order(Forward, _proc->entry(), visited, rpo_order);
00744
00745
00746
00747 visited.clear();
00748 dfs_dominators(Forward, _proc->entry(), visited, order, rpo_order);
00749
00750 int size = order.size();
00751
00752
00753
00754
00755
00756 _forward_basicblock_order.resize(size);
00757 int cur = 0;
00758 for (basicblock_list_p p = order.begin();
00759 p != order.end();
00760 ++p)
00761 {
00762 basicblockNode * block = *p;
00763 _forward_basicblock_order[cur] = block;
00764 _forward_worklist_order[block] = cur;
00765 cur++;
00766 }
00767
00768
00769
00770 visited.clear();
00771 order.clear();
00772 reverse_post_order(Backward, _proc->exit(), visited, order);
00773
00774 _backward_basicblock_order.resize(size);
00775 cur = 0;
00776 for (basicblock_list_p p = order.begin();
00777 p != order.end();
00778 ++p)
00779 {
00780 basicblockNode * block = *p;
00781 _backward_basicblock_order[cur] = block;
00782 _backward_worklist_order[block] = cur;
00783 cur++;
00784 }
00785
00786
00787
00788 _worklist.max_size(size);
00789
00790
00791
00792
00793 basicblockNode * bb = _proc->exit();
00794 stmtNode * statement = bb->stmts().back();
00795
00796 if (statement->typ() == Return) {
00797 returnNode * ret = (returnNode *) statement;
00798 _return_stmt = ret;
00799 if (ret->expr() &&
00800 ret->expr()->typ() == Id)
00801 {
00802 idNode * id = (idNode *) ret->expr();
00803 _return_variable = id->decl();
00804 }
00805 }
00806
00807
00808
00809 typedef map< stmtNode *, basicblockNode * > label_location_map;
00810 typedef label_location_map::iterator label_location_map_p;
00811
00812 label_location_map labels;
00813
00814 for (basicblock_list_p p = order.begin();
00815 p != order.end();
00816 ++p)
00817 {
00818 basicblockNode * block = *p;
00819
00820
00821
00822 for (stmt_list_p q = block->stmts().begin();
00823 q != block->stmts().end();
00824 ++q)
00825 {
00826 stmtNode * stmt = *q;
00827
00828
00829
00830 if (stmt->typ() == Label) {
00831 labels[stmt] = block;
00832 labelNode * l = (labelNode *)stmt;
00833 }
00834 }
00835 }
00836
00837 for (basicblock_list_p p = order.begin();
00838 p != order.end();
00839 ++p)
00840 {
00841 basicblockNode * block = *p;
00842
00843
00844
00845 for (stmt_list_p q = block->stmts().begin();
00846 q != block->stmts().end();
00847 ++q)
00848 {
00849 stmtNode * stmt = *q;
00850
00851 if (stmt->typ() == Condition) {
00852 conditiongotoNode * cond = (conditiongotoNode *) stmt;
00853 labelNode * lab = cond->label();
00854 label_location_map_p ll = labels.find(lab);
00855 if (ll == labels.end())
00856 cout << "ERROR: No label " << lab->name() << " in " << name() << endl;
00857 else
00858 _true_branches[block] = (*ll).second;
00859 }
00860 }
00861 }
00862
00863
00864
00865 str_set_p cs = pointerOptions::Context_sensitive_procedures.find(_proc->decl()->name());
00866 if (cs != pointerOptions::Context_sensitive_procedures.end())
00867 _prefer_context_sensitive = true;
00868
00869
00870
00871 str_set_p vb = pointerOptions::Verbose_procedures.find(_proc->decl()->name());
00872 if (vb != pointerOptions::Verbose_procedures.end())
00873 _verbose = true;
00874 }
00875
00876 procedureInfo::~procedureInfo()
00877 {
00878 delete _dominance_frontiers;
00879 delete _loops;
00880 delete _only_context;
00881 }
00882
00883 void procedureInfo::add_ancestor_set(procedureinfo_set & ancestors)
00884 {
00885 _ancestors = ancestors;
00886 }
00887
00888 void procedureInfo::setup_call_at(procedureInfo * caller,
00889 stmtLocation * callsite,
00890 bool is_recursive_call,
00891 bool multiple_target_call)
00892 {
00893
00894
00895
00896
00897
00898
00899
00900
00901
00902
00903
00904
00905
00906
00907
00908
00909
00910
00911 bool make_context_insensitive = false;
00912
00913 if ((callsite->calls() &&
00914 (callsite->calls()->proc() != proc())) ||
00915 is_recursive() && !pointerOptions::Recursion_Context_sensitive ||
00916 multiple_target_call ||
00917 (pointerOptions::Context_insensitive &&
00918
00919 ! prefer_context_sensitive()))
00920 make_context_insensitive = true;
00921
00922
00923
00924 if (make_context_insensitive &&
00925 ! is_context_insensitive())
00926 {
00927
00928
00929 _context_insensitive = true;
00930
00931
00932
00933 stmtLocation * first_callsite = 0;
00934 bool multiple_callsites = false;
00935
00936 if (_callsites.size() > 1)
00937 multiple_callsites = true;
00938 else {
00939 if (_callsites.size() == 1) {
00940
00941
00942
00943 first_callsite = (* _callsites.begin()).first;
00944 }
00945 }
00946
00947 if (first_callsite)
00948 _only_context = first_callsite->remove_call();
00949 else
00950 _only_context = new procLocation(callsite, proc(), true);
00951
00952 if (pointerOptions::Verbose) {
00953 cout << "--> Make " << qualified_name() << " context-insensitive at " << * callsite << endl;
00954 if (multiple_callsites)
00955 cout << " ** Multiple callsites exist: this could be a problem" << endl;
00956 }
00957 }
00958
00959
00960
00961 if ( ! is_context_insensitive()) {
00962
00963
00964
00965 callsite->setup_cs_call(proc());
00966 }
00967
00968
00969
00970 _callsites[callsite] = caller;
00971
00972
00973
00974 caller->_calls.insert(this);
00975
00976
00977
00978 if ( ! _first_caller)
00979 _first_caller = caller;
00980 }
00981
00987 string procedureInfo::qualified_name()
00988 {
00989 string nm(name());
00990
00991 if (is_context_insensitive()) {
00992 if (is_recursive())
00993 nm += "(R)";
00994 else
00995 nm += "(I)";
00996 }
00997 else
00998 nm += "(S)";
00999
01000 if (never_returns())
01001 nm += "!";
01002
01003 char temp[200];
01004
01005 sprintf(temp, "[%d,%d,%d,%6.2f/%6.2f]",
01006 _callsites.size(),
01007 _external_inputs.size(),
01008 _external_outputs.size(),
01009 self_timer(), total_timer());
01010
01011 nm += temp;
01012
01013 return nm;
01014 }
01015
01065 void procedureInfo::set_pending_changes(stmtLocation * callsite, memoryblock_set & changes)
01066 {
01067
01068
01069 _pending_changes[callsite].insert(changes.begin(), changes.end());
01070 }
01071
01078 void procedureInfo::get_pending_changes(stmtLocation * callsite, memoryblock_set & changes)
01079 {
01080
01081
01082 callsite_changes_map_p p = _pending_changes.find(callsite);
01083
01084 if (p != _pending_changes.end()) {
01085
01086
01087
01088 memoryblock_set & new_changes = (*p).second;
01089
01090
01091
01092 for (memoryblock_set_p q = new_changes.begin();
01093 q != new_changes.end();
01094 ++q)
01095 {
01096 memoryBlock * pending_change = (*q);
01097
01098
01099
01100
01101 pending_change->set_current_def_use(callsite);
01102
01103
01104
01105 changes.insert(pending_change);
01106 }
01107
01108
01109
01110 _pending_changes.erase(p);
01111 }
01112 }
01113
01118 procedureInfo * procedureInfo::caller_at(stmtLocation * callsite)
01119 {
01120 callsite_map_p p = _callsites.find(callsite);
01121 if (p != _callsites.end())
01122 return (*p).second;
01123
01124 return 0;
01125 }
01126
01131 bool procedureInfo::is_ancestor(procedureInfo * other)
01132 {
01133 procedureinfo_set_p p = _ancestors.find(other);
01134
01135 return (p != other->_ancestors.end());
01136 }
01137
01144 procLocation * procedureInfo::procedure_location(stmtLocation * callsite)
01145 {
01146 if (is_context_insensitive())
01147 return _only_context;
01148
01149 return callsite->calls();
01150 }
01151
01152
01153
01154
01155
01156 bool procedureInfo::add_external_input(memoryBlock * block)
01157 {
01158
01159
01160 if (_external_inputs.find(block) == _external_inputs.end()) {
01161
01162 _external_inputs.insert(block);
01163
01164 if (pointerOptions::Verbose)
01165 cout << " Added external input " << block->name() << endl;
01166
01167 return true;
01168 }
01169 else
01170 return false;
01171 }
01172
01173 bool procedureInfo::add_external_output(memoryBlock * block)
01174 {
01175 bool found_new_output = false;
01176
01177
01178
01179 if (_external_outputs.find(block) == _external_outputs.end()) {
01180
01181 _external_outputs.insert(block);
01182
01183 if (pointerOptions::Verbose) {
01184 cout << " New external output " << block->name() << endl;
01185 }
01186
01187
01188
01189
01190 if (block->current_def() &&
01191 (block->current_def()->is_weak()))
01192 {
01193 if (add_external_input(block)) {
01194 found_new_output = true;
01195 if (pointerOptions::Verbose)
01196 cout << " (Caused by weak update)" << endl;
01197 }
01198 }
01199
01200 return found_new_output;
01201 }
01202 else
01203 return false;
01204 }
01205
01206
01207
01208
01209
01210 void procedureInfo::setup_merge_point(memoryBlock * block_to_merge,
01211 basicblockLocation * cur)
01212 {
01213
01214
01215 if ( ! block_to_merge->is_flow_sensitive())
01216 return;
01217
01218
01219
01220
01221
01222
01223
01224
01225
01226
01227
01228 procLocation * proc_loc = cur->proc_location();
01229
01230
01231
01232
01233 bool found_dominance_frontier = false;
01234
01235 basicblock_set_map_map_p p = _dominance_frontiers->find(cur->block());
01236 if ((p != _dominance_frontiers->end()) &&
01237 ! (*p).second.empty()) {
01238
01239 found_dominance_frontier = true;
01240
01241
01242
01243 basicblock_set_map & df = (*p).second;
01244
01245
01246
01247
01248 for (basicblock_set_map_p bbq = df.begin();
01249 bbq != df.end();
01250 ++bbq)
01251 {
01252 basicblockNode * merge_basicblock = (*bbq).first;
01253 basicblockLocation * merge_location = proc_loc->lookup_block(merge_basicblock);
01254 basicblock_set & predecessors = (*bbq).second;
01255
01256
01257
01258
01259
01260 memoryDef * cur_def = block_to_merge->current_def();
01261 memoryDef * def;
01262
01263 if ( cur_def )
01264 def = cur_def;
01265 else
01266 def = block_to_merge->nearest_def_at(cur->last());
01267
01268 if ( ! def ) {
01269
01270
01271
01272
01273
01274
01275
01276
01277
01278
01279
01280
01281
01282
01283
01284
01285
01286
01287
01288
01289
01290
01291 }
01292 else {
01293
01294
01295
01296 block_to_merge->setup_merge_uses_at(merge_location, def, predecessors);
01297 _merge_points[merge_location].insert(block_to_merge);
01298
01299 if (pointerOptions::Verbose)
01300 cout << " Merge " << block_to_merge->name() << " at "
01301 << * merge_location << endl;
01302 }
01303 }
01304 }
01305
01306 if (pointerOptions::Verbose && found_dominance_frontier)
01307 cout << endl;
01308 }
01309
01310
01311
01312
01313 memoryblock_set * procedureInfo::lookup_merge_point(basicblockLocation * merge_location)
01314 {
01315 if (pointerOptions::Verbose) {
01316 cout << " Lookup merge: " << *merge_location << endl;
01317 }
01318
01319 mergepoint_map_p p = _merge_points.find(merge_location);
01320 if (p == _merge_points.end()) {
01321 if (pointerOptions::Verbose) {
01322 cout << " None found." << endl;
01323 cout << endl;
01324 }
01325 return 0;
01326 }
01327 else {
01328 if (pointerOptions::Verbose) {
01329 memoryblock_set & objects = (*p).second;
01330 for (memoryblock_set_cp q = objects.begin();
01331 q != objects.end();
01332 ++q)
01333 cout << " Merge: " << (*q)->name() << endl;
01334 }
01335
01336 if (pointerOptions::Verbose)
01337 cout << endl;
01338
01339 return &((*p).second);
01340 }
01341 }
01342
01343 void procedureInfo::check_merge_point(memoryBlock * block_to_merge,
01344 basicblockLocation * cur)
01345 {
01346
01347
01348 if ( ! block_to_merge->is_flow_sensitive())
01349 return;
01350
01351 procLocation * proc_loc = cur->proc_location();
01352
01353
01354
01355
01356 bool found_dominance_frontier = false;
01357
01358 basicblock_set_map_map_p p = _dominance_frontiers->find(cur->block());
01359 if ((p != _dominance_frontiers->end()) &&
01360 ! (*p).second.empty()) {
01361
01362 found_dominance_frontier = true;
01363
01364
01365
01366 basicblock_set_map & df = (*p).second;
01367
01368
01369
01370
01371 for (basicblock_set_map_p bbq = df.begin();
01372 bbq != df.end();
01373 ++bbq)
01374 {
01375 basicblockNode * merge_basicblock = (*bbq).first;
01376 basicblockLocation * merge_location = proc_loc->lookup_block(merge_basicblock);
01377 basicblock_set & predecessors = (*bbq).second;
01378
01379
01380
01381
01382
01383 memoryDef * cur_def = block_to_merge->current_def();
01384 memoryDef * def;
01385
01386 if ( cur_def )
01387 def = cur_def;
01388 else
01389 def = block_to_merge->last_def_at(cur);
01390
01391
01392
01393
01408 }
01409 }
01410
01411 if (pointerOptions::Verbose && found_dominance_frontier)
01412 cout << endl;
01413 }
01414
01415
01416
01417
01418
01419 void procedureInfo::reverse_post_order(Direction dir,
01420 basicblockNode * cur,
01421 basicblock_set & visited,
01422 basicblock_list & order)
01423 {
01424
01425
01426 if (visited.find(cur) == visited.end()) {
01427 visited.insert(cur);
01428
01429
01430
01431
01432
01433
01434
01435 basicblock_list & children = (dir == Forward) ? cur->succs() : cur->preds();
01436
01437
01438
01439 for (basicblock_list::reverse_iterator p = children.rbegin();
01440 p != children.rend();
01441 ++p)
01442 {
01443 basicblockNode * child = *p;
01444 if (_loops->classifyEdge(cur, child) != loopTree::BackEdge)
01445 reverse_post_order(dir, child, visited, order);
01446 }
01447
01448 for (basicblock_list::reverse_iterator p = children.rbegin();
01449 p != children.rend();
01450 ++p)
01451 {
01452 basicblockNode * child = *p;
01453 if (_loops->classifyEdge(cur, child) == loopTree::BackEdge)
01454 reverse_post_order(dir, child, visited, order);
01455 }
01456
01457
01458
01459
01460 order.push_front(cur);
01461 }
01462 }
01463
01464 void procedureInfo::dfs_dominators(Direction dir,
01465 basicblockNode * cur,
01466 basicblock_set & visited,
01467 basicblock_list & order,
01468 basicblock_list & rpo_order)
01469 {
01470
01471
01472 if (visited.find(cur) == visited.end()) {
01473 visited.insert(cur);
01474 order.push_back(cur);
01475
01476
01477
01478 const basicblock_list & children = cur->children();
01479
01480
01481
01482
01483 for (basicblock_list_p p = rpo_order.begin();
01484 p != rpo_order.end();
01485 ++p)
01486 {
01487 basicblockNode * child = *p;
01488
01489 if (find(children.begin(), children.end(), child) != children.end())
01490 dfs_dominators(dir, child, visited, order, rpo_order);
01491 }
01492
01493
01494
01495
01496
01497
01498
01499
01500
01501
01502
01503
01504
01505
01506
01507
01508
01509 }
01510 }
01511
01512 basicblockNode * procedureInfo::get_next_block(Direction dir)
01513 {
01514
01515
01516 if (_worklist.is_empty())
01517 return 0;
01518
01519 basicblockNode * next_block = block_at(_worklist.get_next_block(), dir);
01520
01521
01522
01523 return next_block;
01524 }
01525
01526 void procedureInfo::add_block(basicblockNode * block, Direction dir)
01527 {
01528
01529
01530 int position = block_position(block, dir);
01531
01532
01533
01534 _worklist.add_block(position);
01535
01536
01537
01538 basicblock_set_p p = _blocks_to_skip.find(block);
01539 if (p != _blocks_to_skip.end())
01540 _blocks_to_skip.erase(p);
01541
01542
01543
01544
01545 }
01546
01547 void procedureInfo::add_reachable_blocks(basicblockNode * block, Direction dir)
01548 {
01549
01550
01551 worklist_set temp;
01552
01553
01554
01555
01556
01557
01558 add_reachable_blocks_rec(dir, block, temp, true);
01559
01560
01561
01562
01563
01564
01565 }
01566
01567 void procedureInfo::add_reachable_blocks_rec(Direction dir,
01568 basicblockNode * cur,
01569 worklist_set & temp, bool first)
01570 {
01571
01572
01573 int position = block_position(cur, dir);
01574
01575
01576
01577 if ( temp.test(position))
01578 return;
01579
01580
01581
01582 if (! first)
01583 add_block(cur, dir);
01584
01585
01586
01587 if (! first)
01588 temp.set(position);
01589
01590
01591
01592 basicblock_list & children = (dir == Forward) ? cur->succs() : cur->preds();
01593
01594 for (basicblock_list_p p = children.begin();
01595 p != children.end();
01596 ++p)
01597 {
01598 basicblockNode * cur_child = *p;
01599 add_reachable_blocks_rec(dir, cur_child, temp, false);
01600 }
01601 }
01602
01603 void procedureInfo::add_all_blocks()
01604 {
01605 _worklist.add_all_blocks();
01606
01607 _blocks_to_skip.clear();
01608
01609 _active_edges.clear();
01610 }
01611
01612 void procedureInfo::add_start_block(Direction dir)
01613 {
01614
01615
01616
01617 if (dir == Forward)
01618 add_block(proc()->entry(), dir);
01619 else
01620 add_block(proc()->exit(), dir);
01621
01622
01623 }
01624
01625 bool procedureInfo::is_empty() const
01626 {
01627 return _worklist.is_empty();
01628 }
01629
01635 void procedureInfo::remove_branch_blocks(basicblockNode * cond,
01636 basicblockNode * branch_taken,
01637 basicblockNode * branch_not_taken)
01638 {
01639
01640
01641
01642 int size = _forward_basicblock_order.size();
01643
01644 for (int i = 0; i < size; i++) {
01645
01646 basicblockNode * block = _forward_basicblock_order[i];
01647
01648 if (Dominators::dominates(branch_not_taken, block) &&
01649 ( ! Dominators::dominates(cond, block)))
01650 {
01651
01652
01653 int position = block_position(block, Forward);
01654
01655
01656
01657 _worklist.remove_block(position);
01658
01659
01660
01661 _blocks_to_skip.insert(block);
01662 }
01663 }
01664
01665
01666
01667
01668 _blocks_to_skip.insert(cond);
01669 }
01670
01675 void procedureInfo::update_conditional_worklist(basicblockNode * block,
01676 bool has_truth_value,
01677 bool which_branch)
01678 {
01679 if (pointerOptions::Verbose)
01680 cout << "Conditional analysis:" << endl;
01681
01682 if (has_truth_value &&
01683 (block->succs().size() == 2)) {
01684
01685
01686
01687 true_branch_map_p p = _true_branches.find(block);
01688 if (p == _true_branches.end()) {
01689 cout << "ERROR: at basic block " << block->dfn() << " could not find true branch" << endl;
01690 return;
01691 }
01692
01693 basicblockNode * true_branch = (*p).second;
01694
01695 basicblockNode * false_branch;
01696 basicblockNode * one = block->succs().front();
01697 basicblockNode * two = block->succs().back();
01698
01699 if (true_branch == one)
01700 false_branch = two;
01701 else
01702 false_branch = one;
01703
01704
01705
01706 basicblockNode * branch_taken = 0;
01707 basicblockNode * branch_not_taken = 0;
01708
01709 if (which_branch) {
01710
01711
01712
01713 branch_taken = true_branch;
01714 branch_not_taken = false_branch;
01715 }
01716 else {
01717
01718
01719
01720 branch_taken = false_branch;
01721 branch_not_taken = true_branch;
01722 }
01723
01724
01725
01726 cfg_edge_pair edge(block, branch_taken);
01727 _active_edges.insert(edge);
01728
01729 if (pointerOptions::Verbose) {
01730 cout << " + Add edge: " << block->dfn() << " -> " << branch_taken->dfn() << endl;
01731 cout << " (skipping: " << block->dfn() << " -> " << branch_not_taken->dfn() << ")" << endl;
01732 }
01733
01734
01735
01736
01737 cfg_edge_pair edge_not_taken(block, branch_not_taken);
01738 cfg_edge_set_p q = _active_edges.find(edge_not_taken);
01739
01740 if (q == _active_edges.end())
01741 remove_branch_blocks(block, branch_taken, branch_not_taken);
01742 }
01743 else {
01744
01745 if (pointerOptions::Verbose)
01746 cout << " - No constant branch: add all edges:" << endl;
01747
01748
01749
01750
01751 for (basicblock_list_p p = block->succs().begin();
01752 p != block->succs().end();
01753 ++p)
01754 {
01755 basicblockNode * succ = *p;
01756
01757 cfg_edge_pair edge(block, succ);
01758 _active_edges.insert(edge);
01759
01760 if (pointerOptions::Verbose)
01761 cout << " + Add edge: " << block->dfn() << " -> " << succ->dfn() << endl;
01762 }
01763 }
01764 }
01765
01766
01767 int procedureInfo::block_position(basicblockNode * block, Direction dir)
01768 {
01769
01770
01771 worklist_order_map & ordering = (dir == Forward) ? _forward_worklist_order : _backward_worklist_order;
01772
01773
01774
01775 worklist_order_map_p p = ordering.find(block);
01776 if (p == ordering.end()) {
01777
01778 cout << "---------------------------------------------------------" << endl;
01779 cout << "Looking for block: " << block << endl;
01780 output_context oc(cout);
01781 block->output(oc, (Node *)0);
01782
01783 cout << "---------------------------------------------------------" << endl;
01784 cout << "Found:" << endl;
01785
01786 for (p = ordering.begin();
01787 p != ordering.end();
01788 ++p)
01789 {
01790 basicblockNode * bb = (*p).first;
01791
01792 cout << bb << endl;
01793 bb->output(oc, (Node *)0);
01794 }
01795
01796 return -1;
01797 }
01798 else
01799 return (*p).second;
01800 }
01801
01802 basicblockNode * procedureInfo::block_at(int position, Direction dir)
01803 {
01804 if (dir == Forward)
01805 return _forward_basicblock_order[position];
01806 else
01807 return _backward_basicblock_order[position];
01808 }
01809
01810 void procedureInfo::print(ostream & out)
01811 {
01812 out << "Procedure: " << _proc->decl()->name() << endl;
01813 }
01814
01820 void procedureInfo::stats(ostream & out)
01821 {
01822 out << std::setw(20) << _proc->decl()->name().c_str();
01823
01824 if (is_context_insensitive())
01825 out << std::setw(6) << "true";
01826 else
01827 out << std::setw(6) << "false";
01828
01829 if (_is_recursive)
01830 out << std::setw(6) << "true";
01831 else
01832 out << std::setw(6) << "false";
01833
01834 out << std::setw(8) << _callsites.size();
01835 out << std::setw(8) << _external_inputs.size();
01836 out << std::setw(8) << _external_outputs.size();
01837 out << std::setw(8) << _ancestors.size();
01838 out << std::setw(8) << _calls.size();
01839
01840 char temp[100];
01841 sprintf(temp, "%10.4f %10.4f", self_timer(), total_timer());
01842
01843 out << std::setw(20) << temp;
01844
01845 out << std::setw(8) << count_calling_contexts();
01846 out << std::setw(8) << procedure_size();
01847
01848 out << endl;
01849
01850
01851
01852
01853
01854
01855
01856
01857
01858
01859 }
01860
01865 int procedureInfo::count_calling_contexts()
01866 {
01867 proc_int_map counts;
01868
01869
01870
01871
01872
01873 return count_calling_contexts_rec(counts, (stmtNode *)0);
01874 }
01875
01880 int procedureInfo::count_calling_contexts_rec(proc_int_map & counts,
01881 stmtNode * callsite)
01882 {
01883
01884
01885 if (is_recursive()) {
01886
01887
01888
01889
01890
01891
01892
01893 return 1;
01894 }
01895
01896
01897
01898
01899 proc_int_map_p p = counts.find(this);
01900 if (p != counts.end()) {
01901
01902
01903
01904
01905
01906
01907
01908 return (*p).second;
01909 }
01910
01911
01912
01913 const callsite_map & sites = callsites();
01914
01915
01916
01917 if (sites.empty())
01918 return 1;
01919
01920
01921
01922
01923
01924
01925 typedef pair< procedureInfo *, stmtNode * > call_site_pair;
01926 typedef set< call_site_pair> stmt_set;
01927 typedef stmt_set::iterator stmt_set_p;
01928
01929 stmt_set stmts;
01930
01931 for (callsite_map_cp q = sites.begin();
01932 q != sites.end();
01933 ++q)
01934 {
01935 procedureInfo * caller = (*q).second;
01936 stmtNode * stmt = ((*q).first)->stmt();
01937
01938 call_site_pair call_site(caller, stmt);
01939 stmts.insert(call_site);
01940 }
01941
01942
01943 int total = 0;
01944
01945 counts[this] = total;
01946
01947 for (stmt_set_p w = stmts.begin();
01948 w != stmts.end();
01949 ++w)
01950 {
01951 procedureInfo * caller = (*w).first;
01952 stmtNode * call_site = (*w).second;
01953
01954 total += caller->count_calling_contexts_rec(counts, call_site);
01955 }
01956
01957
01958
01959 counts[this] = total;
01960
01961
01962
01963
01964
01965
01966
01967
01968
01969 return total;
01970 }
01971
01977 int procedureInfo::procedure_size()
01978 {
01979 blockNode * body = proc()->body();
01980
01981 int total = 0;
01982
01983 for (stmt_list_p p = body->stmts().begin();
01984 p != body->stmts().end();
01985 ++p)
01986 {
01987 basicblockNode * bb = (basicblockNode *) (*p);
01988
01989 total += bb->stmts().size();
01990 }
01991
01992 return total;
01993 }
01994
01995
01996