Polaris: InterProcConstProp.cc Source File

InterProcConstProp.cc

Go to the documentation of this file.
00001 ///
00002 ///
00003 /// \file InterProcConstProp.cc
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 /// Template instantiations:
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 ///  normalize_func_calls
00040 ///   Normalize the structure of function calls so that they only occur
00041 ///   in assignment statements at the top level.
00042 ///
00043 ///   WARNING: This function assumes that all arguments in an expression
00044 ///            and all expressions in a statement are executed left to right.
00045 
00046 static Expression *
00047 _norm_func_calls1(Expression *expr, Statement &stmt, ProgramUnit &pgm)
00048 {
00049     if (! expr)
00050     return expr;
00051 
00052     /// ...  Don't normalize function calls inside implied DO statements.
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       // Now, check the arguments passed to the CALL.  If any are
00097       // integer constants, assign the constants to variables and
00098       // use the variables instead. This was done to prevent the
00099       // problem where a constant is passed and IPVP places an
00100       // assignment statement inside the routine, assigning the
00101       // constant to the formal parameter (which breaks in some
00102       // backend compilers).
00103       // e.g.  CALL X(1) .... SUBROUTINE X(N) ;  N = 1 ; ..... - jph
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             /// ...  Now, check the arguments passed to the function call.
00149             /// ...  If any are integer constants, assign the constants to
00150             /// ...  variables and use the variables instead.  This was done
00151             /// ...  to prevent the problem where a constant is passed and
00152             /// ...  IPVP places an assignment statement inside the routine,
00153             /// ...  assigning the constant to the formal parameter (which
00154             /// ...  breaks in some backend compilers).
00155         /// ...  e.g.  A= X(1) .... FUNCTION X(N) ;  N = 1 ; ..... - jph
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 /// add_call_returns
00190 ///   Add dummy statements, (represented by label statements), after each
00191 ///   subroutine or function call.  These statements are used by the
00192 ///   constant propagator to hold any new constants generated by these
00193 ///   calls.
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 /// read_dummy_pgms
00212 ///   Read in the program units from DUMMY_PGM_FILE and create IPCPProcData
00213 ///   objects for them.
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 /// compute_toporder
00249 ///   Compute a topological ordering, in respect to the call graph, for
00250 ///   all my program units with IPCPProcData objects.
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 /// compute_constants
00283 ///   Compute the sets of entering symbolic constants for all 
00284 ///   procedures in the program.
00285 
00286 void
00287 InterProcConstProp::_compute_constants()
00288 {
00289     Timer timer;
00290 
00291     /// ...  Move the current constants sets as old constants sets fields.
00292 
00293     KeyIterator<String, IPCPProcData> iter = _pgm_data;
00294  
00295     for ( ; iter.valid(); ++iter)
00296     iter.current_data().make_consts_sets_old();
00297 
00298     /// ...  Compute the new constants sets.
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 /// have_constants_changed
00320 ///   Return True if the constants have changed for any constant set.
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 ///  Constructor
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     /// ...  Normalize all the programs in pgms and determine the main program.
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     /// ...  Read in the set of dummy programs.
00381 
00382     _read_dummy_pgms(intrin_file_name);
00383 
00384     /// ...  Build a IPCPProcData object for each program in pgms.
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     /// ...  Compute the topological order of the call graph of these programs.
00394 
00395     _compute_toporder();
00396 
00397     /// ...  If a main program unit is in the set of programs, mark it as the
00398     /// ...  only externally called program.  Otherwise, mark all program
00399     /// ...  units as externally called.
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     /// ...  Compute the side-effects of all procedures in the program.
00412 
00413     _build_jump_functions();
00414 
00415     /// ...  Compute the sets of entering symbolic constants for all 
00416     /// ...  procedures in the program.
00417 
00418     _compute_constants();
00419 }
00420 
00421 
00422 ///  Destructor
00423 
00424 InterProcConstProp::~InterProcConstProp()
00425 {
00426     delete _pgm_entries;;
00427 
00428     if (_dummy_pgms)
00429     delete _dummy_pgms;
00430 }
00431 
00432 
00433 /// pgms_can_be_called_externally
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 /// pgm_entry
00448 ///   Return the entry statement for the given program unit.
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 ///  get_proc_data_ref
00467 ///    Get the IPCPProcData object associated with the program unit with
00468 ///    the given name.  If the object does not exist, it is created.
00469 ///    If the program unit does not exist, the routine returns NULL.
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 /// _rename_pgm_entry
00498 ///   Rename the entry statement for the given program unit.
00499 ///   This is a little more complicated than it sounds, since we must
00500 ///   make sure that this renamed variable does not conflict with any
00501 ///   other variables in the program.
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     /// ...  Force the symbol table to update the entry variable to its new name.
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 /// build_jump_functions
00537 ///   Build the jump functions for each program unit.
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 /// clone_all_pgms
00561 ///   Clone each program unit with multiple constant sets.
00562 
00563 void
00564 InterProcConstProp::_clone_all_pgms()
00565 {
00566     Timer timer;
00567 
00568     /// ...  silvius: let's see the const sets before cloning:
00569 ///     cerr<<"\n\n\nCONSTANT SETS: ";
00570 ///     print_consts_sets(cerr);
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;     /// ...  Let the original pgm keep the first const set
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 /// propagate_constants
00607 ///   Annotate each program unit with its constant values.  This method
00608 ///   assumes that each program unit has at most one constant set.
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 /// add_maymods
00631 ///   Add maymod assertions to every call site in the program.
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 /// clone_and_propagate
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 /// double_clone_and_propagate
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 /// iter_clone_and_propagate
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 /// expand_all_substituted
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 ///  substitutable_type
00717 ///   Returns true if the given type may be legally substituted
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 ///  print
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 ///  print_consts_sets
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 
 © 1995-2005 University of Illinois, Urbana-Champaign. All rights reserved.  Fri Mar 25 23:05:55 2005