00001
00002
00003
00004
00005 #include "../Collection/KeyIterator.h"
00006 #include "../Collection/Mutator.h"
00007 #include "../Directive/Assertion.h"
00008 #include "../Symbol/Symbol.h"
00009 #include "../Symbol/VariableSymbol.h"
00010 #include "../Statement/Statement.h"
00011 #include "../Statement/AssignmentStmt.h"
00012 #include "../Statement/LabelStmt.h"
00013 #include "../Program.h"
00014 #include "../ProgramUnit.h"
00015 #include "../ProgramTag.h"
00016 #include "../EntryPoints.h"
00017 #include "../Symtab.h"
00018 #include "../Timer.h"
00019 #include "../utilities/expression_util.h"
00020 #include "../utilities/entry_util.h"
00021 #include "../utilities/program_util.h"
00022 #include "../utilities/stmt_util.h"
00023 #include "../utilities/loopMark.h"
00024
00025 #include "InterProcConstProp.h"
00026
00027
00028
00029 template class TypedBaseMap<String, IPCPProcData>;
00030 template class ProtoDatabase<String, IPCPProcData>;
00031 template class Database<String, IPCPProcData>;
00032 template ostream & operator << (ostream &,
00033 const Database<String, IPCPProcData> &);
00034 template class KeyIterator<String, IPCPProcData>;
00035
00036 template class Array<IPCPProcData *>;
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046 static Expression *
00047 _norm_func_calls1(Expression *expr, Statement &stmt, ProgramUnit &pgm)
00048 {
00049 if (! expr)
00050 return expr;
00051
00052
00053
00054 if (expr->op() == DO_OP)
00055 return expr;
00056
00057 Mutator<Expression> arg_iter = expr->arg_list();
00058
00059 for ( ; arg_iter.valid(); ++arg_iter) {
00060 Assign<Expression> eas(arg_iter.assign());
00061 eas = _norm_func_calls1(arg_iter.pull(), stmt, pgm);
00062 }
00063
00064 if (expr->op() == FUNCTION_CALL_OP) {
00065 Symbol *func_call_var
00066 = new VariableSymbol("tfc", expr->function().symbol().type(),
00067 NOT_FORMAL, NOT_SAVED);
00068 func_call_var = &pgm.symtab().rename_and_ins(func_call_var);
00069 Statement *func_call_stmt
00070 = new AssignmentStmt(pgm.stmts().new_tag(), id(*func_call_var),
00071 expr);
00072 Iterator<Assertion> as_iter
00073 = assertions_of_type(stmt, AS_SIDE_EFFECT_FREE);
00074 for ( ; as_iter.valid(); ++as_iter) {
00075 Assertion *assert = as_iter.current().clone();
00076 func_call_stmt->assertions().ins_last(assert);
00077 }
00078
00079 pgm.stmts().ins_before(func_call_stmt, &stmt);
00080 expr = id(*func_call_var);
00081 }
00082
00083 return expr;
00084 }
00085
00086 static void
00087 _normalize_func_calls(ProgramUnit &pgm)
00088 {
00089 Iterator<Statement> stmt_iter = pgm.stmts().iterator();
00090
00091 for ( ; stmt_iter.valid(); ++stmt_iter) {
00092 Statement &stmt = stmt_iter.current();
00093
00094 if (stmt.stmt_class() == CALL_STMT) {
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105 for(Mutator<Expression> iter = stmt.parameters_guarded().arg_list();
00106 iter.valid();
00107 ++iter) {
00108
00109 Assign<Expression> eas(iter.assign());
00110 Expression * arg = iter.pull();
00111
00112 if (arg->op() == INTEGER_CONSTANT_OP) {
00113 Symbol *arg_var
00114 = new VariableSymbol("arg", INTEGER_TYPE,
00115 NOT_FORMAL, NOT_SAVED);
00116 arg_var = &pgm.symtab().rename_and_ins(arg_var);
00117 Statement *arg_stmt
00118 = new AssignmentStmt(pgm.stmts().new_tag(), id(*arg_var),
00119 arg->clone());
00120 pgm.stmts().ins_before(arg_stmt, &stmt);
00121 delete arg;
00122 arg = id(*arg_var);
00123 }
00124 eas = arg;
00125 }
00126 }
00127
00128 if (contains_func_call(stmt)) {
00129
00130 if (stmt.stmt_class() == WHILE_STMT){
00131 cerr<<stmt;
00132 }
00133
00134 p_assert(stmt.pred().entries() <= 1
00135 || stmt.stmt_class() == DO_STMT,
00136 "_normalize_func_calls() doesn't know how to move function calls out of statements with multiple predecessors.");
00137
00138 Mutator<Expression> arg_iter = stmt.iterate_expressions();
00139
00140 Statement *prevstmt = stmt.prev_ref();
00141
00142 for ( ; arg_iter.valid(); ++arg_iter) {
00143 Assign<Expression> eas(arg_iter.assign());
00144 eas = _norm_func_calls1(arg_iter.pull(),
00145 stmt, pgm);
00146 }
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157 p_assert((stmt.prev_ref()->stmt_class() == ASSIGNMENT_STMT) &&
00158 (stmt.prev_ref()->rhs().op() == FUNCTION_CALL_OP),
00159 "Prev stmt should be an assignment with an RHS of a function call");
00160
00161 for(Mutator<Expression> iter = stmt.prev_ref()->rhs().parameters_guarded().arg_list();
00162 iter.valid();
00163 ++iter) {
00164
00165 Assign<Expression> eas(iter.assign());
00166 Expression * arg = iter.pull();
00167
00168 if (arg->op() == INTEGER_CONSTANT_OP) {
00169 Symbol *arg_var
00170 = new VariableSymbol("arg", INTEGER_TYPE,
00171 NOT_FORMAL, NOT_SAVED);
00172 arg_var = &pgm.symtab().rename_and_ins(arg_var);
00173 Statement *arg_stmt
00174 = new AssignmentStmt(pgm.stmts().new_tag(), id(*arg_var),
00175 arg->clone());
00176 pgm.stmts().ins_after(arg_stmt, prevstmt);
00177 delete arg;
00178 arg = id(*arg_var);
00179 }
00180 eas = arg;
00181 }
00182
00183 stmt.build_refs();
00184 }
00185 }
00186 }
00187
00188
00189
00190
00191
00192
00193
00194
00195 static void
00196 _add_call_returns(ProgramUnit &pgm)
00197 {
00198 Iterator<Statement> stmt_iter = pgm.stmts().iterator();
00199
00200 for ( ; stmt_iter.valid(); ++stmt_iter) {
00201 Statement &stmt = stmt_iter.current();
00202
00203 if (stmt.stmt_class() == CALL_STMT || contains_func_call(stmt))
00204 pgm.stmts().ins_after(new LabelStmt(pgm.stmts().new_tag(),
00205 pgm.stmts().new_label()),
00206 &stmt);
00207 }
00208 }
00209
00210
00211
00212
00213
00214
00215 void
00216 InterProcConstProp::_read_dummy_pgms(char *intrin_file_name)
00217 {
00218 _dummy_pgms = new Program;
00219
00220 if (intrin_file_name == 0) {
00221 _dummy_pgms->read(DUMMY_PGM_FILE);
00222 } else {
00223 _dummy_pgms->read(intrin_file_name);
00224 }
00225
00226 KeyIterator<String,ProgramUnit> pgm_iter = *_dummy_pgms;
00227
00228 for ( ; pgm_iter.valid(); ++pgm_iter) {
00229 ProgramUnit &pgm = pgm_iter.current_data();
00230
00231 if (! _pgm_entries->member(pgm.routine_name_ref())) {
00232 _normalize_func_calls(pgm);
00233 _add_call_returns(pgm);
00234 Iterator<Statement> entry_iter = pgm.stmts().stmts_of_type(ENTRY_STMT);
00235 p_assert(entry_iter.valid(), "Given program unit does not have an entry statement.");
00236 const Statement &entry = entry_iter.current();
00237 ++entry_iter;
00238 p_assert(! entry_iter.valid(), "InterProcConstProp cannot handle program units with multiple entries.");
00239
00240 IPCPProcData *data = new IPCPProcData(pgm, *this, entry,
00241 _debug_level);
00242 _pgm_data.ins(pgm.routine_name_ref(), data);
00243 }
00244 }
00245 }
00246
00247
00248
00249
00250
00251
00252 void
00253 InterProcConstProp::_compute_toporder()
00254 {
00255 KeyIterator<String, IPCPProcData> iter = _pgm_data;
00256
00257 for ( ; iter.valid(); ++iter)
00258 iter.current_data().init_rtoporder();
00259
00260 int num_proc_datas = 0;
00261
00262 for (iter.reset(); iter.valid(); ++iter)
00263 iter.current_data().compute_rtoporder(num_proc_datas);
00264
00265 _pgm_data_toporder.resize(num_proc_datas);
00266
00267 p_assert(num_proc_datas == _pgm_data.entries(),
00268 "Internal error in InterProcConstProp::_compute_toporder().");
00269
00270 for (int i = 0; i < num_proc_datas; ++i)
00271 _pgm_data_toporder[i] = 0;
00272
00273 for (iter.reset(); iter.valid(); ++iter) {
00274 IPCPProcData &data = iter.current_data();
00275
00276 if (data.rtoporder() >= 0)
00277 _pgm_data_toporder[num_proc_datas - data.rtoporder() - 1] = &data;
00278 }
00279 }
00280
00281
00282
00283
00284
00285
00286 void
00287 InterProcConstProp::_compute_constants()
00288 {
00289 Timer timer;
00290
00291
00292
00293 KeyIterator<String, IPCPProcData> iter = _pgm_data;
00294
00295 for ( ; iter.valid(); ++iter)
00296 iter.current_data().make_consts_sets_old();
00297
00298
00299
00300 for (int i = 0; i < _pgm_data_toporder.entries(); ++i) {
00301 IPCPProcData &data = *_pgm_data_toporder[i];
00302
00303 if (data.is_called_externally()) {
00304 IPCPConstants *no_constants = new IPCPConstants();
00305 List<Expression> non_const_params;
00306
00307 for (int j = 0; j < data.param_list().entries(); ++j)
00308 non_const_params.ins_last(omega());
00309
00310 data.add_constant_set(no_constants, non_const_params);
00311 }
00312 }
00313
00314 if (_debug_level > 0)
00315 cout << "! Computing interprocedural constants: " << timer << endl;
00316 }
00317
00318
00319
00320
00321
00322 Boolean
00323 InterProcConstProp::_have_constants_changed() const
00324 {
00325 KeyIterator<String, IPCPProcData> iter = _pgm_data;
00326
00327 for ( ; iter.valid(); ++iter)
00328 if (iter.current_data().have_consts_sets_changed()) {
00329 if (_debug_level > 0)
00330 cout << "! Constants for routine " << iter.current_key()
00331 << " have changed.\n";
00332
00333 return True;
00334 }
00335
00336 return False;
00337 }
00338
00339
00340
00341
00342 InterProcConstProp::InterProcConstProp(Program &pgms,
00343 PC_REAL_BOOL subst_reals,
00344 PC_ARRAY_BOOL subst_arrays,
00345 char *intrin_file_name,
00346 int debug GIV(0))
00347 {
00348 _pgms = &pgms;
00349 _dummy_pgms = 0;
00350 _subst_reals = subst_reals;
00351 _subst_arrays = subst_arrays;
00352 _debug_level = debug;
00353 Timer timer;
00354
00355
00356
00357 ProgramUnit *main_pgm = 0;
00358 Program *entry_pgms = new Program;
00359 KeyIterator<String,ProgramUnit> pgm_iter = pgms;
00360
00361 for ( ; pgm_iter.valid(); ++pgm_iter) {
00362 ProgramUnit &pgm = pgm_iter.current_data();
00363
00364 if (pgm.pu_class() == PROGRAM_PU_TYPE) {
00365 main_pgm = &pgm;
00366 p_assert(main_pgm->routine_name_ref(),
00367 "InterProcConstProp constructor requires that the main program unit have a name.");
00368 }
00369
00370 move_saved_vars(pgm, *entry_pgms);
00371 _normalize_func_calls(pgm);
00372 _add_call_returns(pgm);
00373 substitute_parameters(pgm, _subst_reals);
00374 split_multiple_entries(pgm, *entry_pgms);
00375 }
00376
00377 pgms.absorb(entry_pgms);
00378 _pgm_entries = pgms.entry_points();
00379
00380
00381
00382 _read_dummy_pgms(intrin_file_name);
00383
00384
00385
00386 for (pgm_iter.reset(); pgm_iter.valid(); ++pgm_iter) {
00387 ProgramUnit &pgm = pgm_iter.current_data();
00388
00389 if (pgm.pu_class() != BLOCK_DATA_PU_TYPE)
00390 (void) _get_proc_data_ref(pgm.routine_name_ref());
00391 }
00392
00393
00394
00395 _compute_toporder();
00396
00397
00398
00399
00400
00401 if (main_pgm)
00402 _get_proc_data_ref(main_pgm->routine_name_ref())->called_externally();
00403 else
00404 pgms_can_be_called_externally();
00405
00406 if (debug > 0) {
00407 cout << "! Initializing data structures: " << timer << endl;
00408 timer.reset();
00409 }
00410
00411
00412
00413 _build_jump_functions();
00414
00415
00416
00417
00418 _compute_constants();
00419 }
00420
00421
00422
00423
00424 InterProcConstProp::~InterProcConstProp()
00425 {
00426 delete _pgm_entries;;
00427
00428 if (_dummy_pgms)
00429 delete _dummy_pgms;
00430 }
00431
00432
00433
00434
00435 void
00436 InterProcConstProp::pgms_can_be_called_externally()
00437 {
00438 for (int i = 0; i < _pgm_data_toporder.entries(); ++i) {
00439 IPCPProcData &data = *_pgm_data_toporder[i];
00440
00441 if (! _dummy_pgms || ! _dummy_pgms->member(data.pgm().tag_ref()))
00442 data.called_externally();
00443 }
00444 }
00445
00446
00447
00448
00449
00450 static Statement &
00451 _pgm_entry(ProgramUnit &pgm)
00452 {
00453 Iterator<Statement> entry_iter = pgm.stmts().stmts_of_type(ENTRY_STMT);
00454
00455 p_assert(entry_iter.valid(),
00456 "Given program unit does not have an entry statement.");
00457 Statement &entry = entry_iter.current();
00458 ++entry_iter;
00459 p_assert(! entry_iter.valid(),
00460 "Given program unit has multiple entries.");
00461
00462 return entry;
00463 }
00464
00465
00466
00467
00468
00469
00470
00471 IPCPProcData *
00472 InterProcConstProp::_get_proc_data_ref(const char *proc_name)
00473 {
00474 IPCPProcData *data = _pgm_data.find_ref(proc_name);
00475
00476 if (! data) {
00477 ProgramUnit *pgm_ref = _pgm_entries->find_ref(proc_name);
00478
00479 if (pgm_ref) {
00480 data = new IPCPProcData(*pgm_ref, *this, _pgm_entry(*pgm_ref),
00481 _debug_level);
00482 _pgm_data.ins(proc_name, data);
00483 }
00484 }
00485
00486
00487 if (! data) {
00488 cerr << "WARNING: InterProcConstProp constructor could not find program unit\n"
00489 << " named " << proc_name << ".\n";
00490 cerr << " Will assume program unit modifies all non-local variables.\n";
00491 }
00492
00493 return data;
00494 }
00495
00496
00497
00498
00499
00500
00501
00502
00503 void
00504 InterProcConstProp::_rename_pgm_entry(ProgramUnit &pgm) const
00505 {
00506 Statement &entry_stmt = _pgm_entry(pgm);
00507 Symbol &entry_var = entry_stmt.routine_guarded().symbol();
00508 String old_entry_name = entry_var.name_ref();
00509 String new_entry_name = old_entry_name;
00510 entry_var.renaming_suggestion(new_entry_name);
00511 Boolean is_name_unique = False;
00512
00513 while (! is_name_unique) {
00514 is_name_unique = True;
00515 KeyIterator<String,IPCPProcData> iter = _pgm_data;
00516
00517 for ( ; iter.valid(); ++iter) {
00518 const ProgramUnit &some_pgm = iter.current_data().pgm();
00519
00520 while (some_pgm.symtab().find_ref(new_entry_name)) {
00521 entry_var.renaming_suggestion(new_entry_name);
00522 is_name_unique = False;
00523 }
00524 }
00525 }
00526
00527
00528
00529 pgm.symtab().grab(entry_var.name_ref());
00530 entry_var.name(new_entry_name);
00531 pgm.symtab().ins(&entry_var);
00532 reset_loop_labels(pgm, old_entry_name, new_entry_name);
00533 }
00534
00535
00536
00537
00538
00539 void
00540 InterProcConstProp::_build_jump_functions()
00541 {
00542 Timer timer;
00543
00544 for (int i = _pgm_data_toporder.entries() - 1; i >= 0; --i) {
00545 _pgm_data_toporder[i]->build_jump_functions(_debug_level);
00546
00547 if (_debug_level > 1) {
00548 cout << "! IPCPProcData = ";
00549 _pgm_data_toporder[i]->print(cout, True);
00550 cout << endl << endl;
00551 }
00552 }
00553
00554
00555 if (_debug_level > 0)
00556 cout << "! Computing jump functions: " << timer << endl;
00557 }
00558
00559
00560
00561
00562
00563 void
00564 InterProcConstProp::_clone_all_pgms()
00565 {
00566 Timer timer;
00567
00568
00569
00570
00571 for (int i = 0; i < _pgm_data_toporder.entries(); ++i) {
00572 IPCPProcData &data = *_pgm_data_toporder[i];
00573
00574 if ((! _dummy_pgms || ! _dummy_pgms->member(data.pgm().tag_ref()))
00575 && data.const_sets().entries() > 1) {
00576
00577 Iterator<IPCPConstants> consts_iter = data.const_sets();
00578 ++consts_iter;
00579
00580 for ( ; consts_iter.valid(); ++consts_iter) {
00581 if (_debug_level > 0)
00582 cout << "! Cloning program unit: "
00583 << data.pgm().routine_name_ref() << endl;
00584
00585 ProgramUnit *pgm_clone = new ProgramUnit(data.pgm());
00586 _rename_pgm_entry(*pgm_clone);
00587 ProgramTag clone_tag;
00588 pgm_clone->rename(clone_tag);
00589 _pgms->absorb(pgm_clone);
00590 IPCPProcData *cloned_data
00591 = new IPCPProcData(*pgm_clone, _pgm_entry(*pgm_clone),
00592 data);
00593 cloned_data->transfer_const_set(consts_iter.current(), data);
00594 _pgm_data.ins(pgm_clone->routine_name_ref(), cloned_data);
00595 }
00596 }
00597 }
00598
00599 _compute_toporder();
00600
00601 if (_debug_level > 0)
00602 cout << "! Cloning program units: " << timer << endl;
00603 }
00604
00605
00606
00607
00608
00609
00610 void
00611 InterProcConstProp::_propagate_constants(PC_UNREACH_BOOL remove_unreachable)
00612 {
00613 Timer timer;
00614 KeyIterator<String, IPCPProcData> iter = _pgm_data;
00615
00616 for ( ; iter.valid(); ++iter) {
00617 IPCPProcData &data = iter.current_data();
00618
00619 if (! _dummy_pgms || ! _dummy_pgms->member(data.pgm().tag_ref())) {
00620 data.add_consts_to_pgm();
00621 data.propagate_constants(remove_unreachable);
00622 }
00623 }
00624
00625 if (_debug_level > 0)
00626 cout << "! Propagating interprocedural constants: " << timer << endl;
00627 }
00628
00629
00630
00631
00632
00633 void
00634 InterProcConstProp::_add_maymods()
00635 {
00636 Timer timer;
00637 KeyIterator<String, IPCPProcData> iter = _pgm_data;
00638
00639 for ( ; iter.valid(); ++iter) {
00640 IPCPProcData &data = iter.current_data();
00641
00642 if (! _dummy_pgms || ! _dummy_pgms->member(data.pgm().tag_ref()))
00643 data.add_maymods();
00644 }
00645
00646 if (_debug_level > 0)
00647 cout << "! Adding MAYMOD assertions: " << timer << endl;
00648 }
00649
00650
00651
00652
00653 void
00654 InterProcConstProp::clone_and_propagate(PC_UNREACH_BOOL remove_unreachable)
00655 {
00656 _clone_all_pgms();
00657 _propagate_constants(remove_unreachable);
00658 _add_maymods();
00659 }
00660
00661
00662
00663
00664 void
00665 InterProcConstProp::double_clone_and_propagate(PC_UNREACH_BOOL remove_unreachable)
00666 {
00667 _clone_all_pgms();
00668 _build_jump_functions();
00669 _compute_constants();
00670 _clone_all_pgms();
00671 _propagate_constants(remove_unreachable);
00672 _add_maymods();
00673 }
00674
00675
00676
00677
00678 void
00679 InterProcConstProp::iter_clone_and_propagate(PC_UNREACH_BOOL remove_unreachable)
00680 {
00681 if (_debug_level > 0)
00682 print_consts_sets(cout);
00683
00684 do {
00685 _clone_all_pgms();
00686 _build_jump_functions();
00687 _compute_constants();
00688
00689 if (_debug_level > 0)
00690 print_consts_sets(cout);
00691
00692 } while (_have_constants_changed());
00693
00694 _clone_all_pgms();
00695 _propagate_constants(remove_unreachable);
00696 _add_maymods();
00697 }
00698
00699
00700
00701
00702 void
00703 InterProcConstProp::expand_all_substituted()
00704 {
00705 KeyIterator<String, IPCPProcData> iter = _pgm_data;
00706
00707 for ( ; iter.valid(); ++iter) {
00708 IPCPProcData &data = iter.current_data();
00709
00710 if (! _dummy_pgms || ! _dummy_pgms->member(data.pgm().tag_ref()))
00711 data.expand_all_substituted();
00712 }
00713 }
00714
00715
00716
00717
00718
00719 Boolean
00720 InterProcConstProp::_is_substitutable(const Symbol &var) const
00721 {
00722 if (_subst_arrays == IGNORE_ARRAYS && var.is_array())
00723 return False;
00724
00725 EXPR_TYPE type = var.type().data_type();
00726
00727 if (type == INTEGER_TYPE
00728 || type == LOGICAL_TYPE
00729 || (_subst_reals == SUBST_REALS
00730 && (type == REAL_TYPE
00731 || type == DOUBLE_PRECISION_TYPE
00732 || type == COMPLEX_TYPE)))
00733 return True;
00734
00735 return False;
00736 }
00737
00738
00739
00740
00741 void
00742 InterProcConstProp::print(ostream &o) const
00743 {
00744 o << "[";
00745 o << "_pgm_data=" << &_pgm_data;
00746 o << ", _global_vars=" << _global_vars;
00747 o << "]";
00748 }
00749
00750
00751
00752
00753 void
00754 InterProcConstProp::print_consts_sets(ostream &o) const
00755 {
00756 KeyIterator<String,IPCPProcData> iter = _pgm_data;
00757
00758 for ( ; iter.valid(); ++iter) {
00759 o << iter.current_key() << ": {";
00760
00761 Iterator<IPCPConstants> const_iter = iter.current_data().const_sets();
00762
00763 if (const_iter.valid()) {
00764 const_iter.current().print_constants(o);
00765 ++const_iter;
00766
00767 for ( ; const_iter.valid(); ++const_iter) {
00768 o << ", ";
00769 const_iter.current().print_constants(o);
00770 }
00771 }
00772
00773 o << "}\n";
00774 }
00775 }
00776