00001
00002
00003
00004
00005 #include "../ProgramUnit.h"
00006 #include "../Statement/Statement.h"
00007 #include "../Statement/GotoStmt.h"
00008 #include "../Statement/AssignmentStmt.h"
00009 #include "../Symbol/Symbol.h"
00010 #include "../Collection/Map.h"
00011 #include "../Collection/Iterator.h"
00012 #include "../Collection/Mutator.h"
00013 #include "../utilities/switches_util.h"
00014 #include "../utilities/removegotos_util.h"
00015 #include "../utilities/expression_util.h"
00016 #include "../utilities/equivalence_util.h"
00017 #include "../IntElem.h"
00018 #include "../IntSet.h"
00019 #include "../Array.h"
00020 #include "../Boolean.h"
00021 #include "../Timer.h"
00022 #include "../p-assert.h"
00023 #include "../macros.h"
00024 #include "../p-setjmp.h"
00025 #include "../interface.h"
00026 #include "../Range/range_dict_util.h"
00027
00028 #include "PropConstWS.h"
00029 #include "PropConstMap.h"
00030 #include "IPCPProcData.h"
00031 #include "constant.h"
00032
00033 static unsigned int _pass_tag;
00034
00035 static int _debug_level = 0;
00036
00037
00038 static Boolean _substituted_var = False;
00039
00040
00041 static Boolean _stmt_substituted_var = False;
00042
00043
00044
00045
00046
00047
00048
00049 static inline Boolean
00050 _substitutable_type(EXPR_TYPE type, PC_REAL_BOOL subst_reals)
00051 {
00052 if (type == INTEGER_TYPE
00053 || type == LOGICAL_TYPE
00054 || (subst_reals == SUBST_REALS
00055 && (type == REAL_TYPE
00056 || type == DOUBLE_PRECISION_TYPE
00057 || type == COMPLEX_TYPE)))
00058 return True;
00059
00060 return False;
00061 }
00062
00063
00064
00065
00066
00067 static void
00068 _add_refs(RefSet<Symbol> &vars, const RefSet<Expression> &refs)
00069 {
00070 Iterator<Expression> iter = refs;
00071
00072 for ( ; iter.valid(); ++iter)
00073 if (iter.current().base_variable_ref())
00074 vars.ins(*iter.current().base_variable_ref());
00075 }
00076
00077
00078
00079
00080
00081
00082 static void
00083 _filter_vars(RefSet<Symbol> &vars, PC_REAL_BOOL subst_reals,
00084 PC_ARRAY_BOOL subst_arrays)
00085 {
00086 Mutator<Symbol> iter = vars;
00087
00088 for ( ; iter.valid(); ++iter) {
00089 const Symbol &var = iter.current();
00090
00091 if (var.sym_class() != VARIABLE_CLASS
00092 || ! _substitutable_type(var.type().data_type(), subst_reals)
00093 || (subst_arrays != SUBST_ARRAYS && var.is_array()))
00094
00095 iter.del();
00096 }
00097 }
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109 static void
00110 _init_candidates(const RefSet<Symbol> &def_vars,
00111 const RefSet<Symbol> &use_vars,
00112 Map<Symbol,IntElem> &def_candidates,
00113 Map<Symbol,IntElem> &use_candidates,
00114 Array<Symbol *> &tag_to_candidate)
00115 {
00116 int tag = 0;
00117 tag_to_candidate.resize(use_vars.entries());
00118
00119
00120
00121 Iterator<Symbol> def_iter = def_vars;
00122
00123 for ( ; def_iter.valid(); ++def_iter) {
00124 Symbol &var = def_iter.current();
00125 tag_to_candidate[tag] = &var;
00126 def_candidates.ins(var, new IntElem(tag++));
00127 }
00128
00129 p_assert(tag == def_candidates.entries(),
00130 "Error in Map<Symbol,IntElem>::entries().");
00131
00132
00133
00134 Iterator<Symbol> use_iter = use_vars;
00135
00136 for ( ; use_iter.valid(); ++use_iter) {
00137 Symbol &var = use_iter.current();
00138 IntElem *var_tag = def_candidates.find_ref(var);
00139
00140 if (var_tag)
00141 use_candidates.ins(var, new IntElem(var_tag->value()));
00142 else {
00143 tag_to_candidate[tag] = &var;
00144 use_candidates.ins(var, new IntElem(tag++));
00145 }
00146 }
00147
00148 p_assert(tag == use_candidates.entries(),
00149 "Error in Map<Symbol,IntElem>::entries().");
00150 }
00151
00152
00153
00154
00155
00156
00157
00158 static void
00159 _collect_candidates(const RefSet<Symbol> &def_vars,
00160 const StmtList &stmts,
00161 const Statement &first_stmt,
00162 const Statement &last_stmt,
00163 Map<Symbol,IntElem> &def_candidates,
00164 Map<Symbol,IntElem> &use_candidates,
00165 Array<Symbol *> &tag_to_candidate)
00166 {
00167 RefSet<Symbol> use_vars = def_vars;
00168 Iterator<Statement> stmt_iter = stmts.iterator(first_stmt, last_stmt);
00169
00170 for ( ; stmt_iter.valid(); ++stmt_iter) {
00171 const Statement &stmt = stmt_iter.current();
00172
00173 if (stmt.stmt_class() == ASSIGNMENT_STMT
00174 && stmt.lhs().op() == ID_OP
00175 && def_vars.member(stmt.lhs().symbol()))
00176
00177 _add_refs(use_vars, stmt.in_refs());
00178 }
00179
00180 _init_candidates(def_vars, use_vars, def_candidates, use_candidates,
00181 tag_to_candidate);
00182 }
00183
00184 static void
00185 _collect_candidates(const StmtList &stmts,
00186 const Statement &first_stmt,
00187 const Statement &last_stmt,
00188 Map<Symbol,IntElem> &def_candidates,
00189 Map<Symbol,IntElem> &use_candidates,
00190 Array<Symbol *> &tag_to_candidate,
00191 PC_REAL_BOOL subst_reals,
00192 PC_ARRAY_BOOL subst_arrays)
00193 {
00194 RefSet<Symbol> def_vars;
00195 RefSet<Symbol> use_vars;
00196 Iterator<Statement> stmt_iter = stmts.iterator(first_stmt, last_stmt);
00197
00198 for ( ; stmt_iter.valid(); ++stmt_iter) {
00199 const Statement &stmt = stmt_iter.current();
00200
00201 if (stmt.stmt_class() == ASSIGNMENT_STMT
00202 && stmt.lhs().op() == ID_OP
00203 && stmt.rhs().is_side_effect_free()) {
00204
00205 const Symbol &var = stmt.lhs().symbol();
00206
00207 if (var.sym_class() == VARIABLE_CLASS
00208 && ! var.is_array()
00209 && _substitutable_type(var.type().data_type(), subst_reals)) {
00210
00211 def_vars.ins(var);
00212 use_vars.ins(var);
00213 _add_refs(use_vars, stmt.in_refs());
00214 }
00215 }
00216 }
00217
00218 _filter_vars(use_vars, subst_reals, subst_arrays);
00219 _init_candidates(def_vars, use_vars, def_candidates, use_candidates,
00220 tag_to_candidate);
00221 }
00222
00223
00224
00225
00226
00227
00228 static List<Statement> *
00229 _create_data_assigns(ProgramUnit &pgm,
00230 const RefSet<Symbol> *candidates,
00231 PC_REAL_BOOL subst_reals)
00232 {
00233 List<Statement> *data_assigns = new List<Statement>;
00234 Iterator<Data> data_iter = pgm.data();
00235
00236 for ( ; data_iter.valid(); ++data_iter) {
00237 Data &data = data_iter.current();
00238
00239 if (data.variable_list().arg_list().entries()
00240 == data.value_list().arg_list().entries()) {
00241
00242 Iterator<Expression> var_iter = data.variable_list().arg_list();
00243 Iterator<Expression> val_iter = data.value_list().arg_list();
00244
00245 for ( ; var_iter.valid(); ++var_iter, ++val_iter) {
00246 Symbol *var = var_iter.current().base_variable_ref();
00247
00248 if (var && ! var->is_array()
00249 && _substitutable_type(var->type().data_type(), subst_reals)
00250 && (! candidates || candidates->member(*var))) {
00251
00252 Statement *data_assign
00253 = new AssignmentStmt(pgm.stmts().new_tag(),
00254 var_iter.current().clone(),
00255 val_iter.current().clone());
00256 data_assigns->ins_last(data_assign);
00257 }
00258 }
00259 }
00260 }
00261
00262 return data_assigns;
00263 }
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273 static void
00274 _add_data_assigns(ProgramUnit &pgm, const RefSet<Symbol> *candidates,
00275 PC_REAL_BOOL subst_reals, RefSet<Statement> &pseudo_stmts)
00276 {
00277 if (pgm.pu_class() == PROGRAM_PU_TYPE) {
00278 List<Statement> *data_assigns
00279 = _create_data_assigns(pgm, candidates, subst_reals);
00280
00281 if (data_assigns->entries() > 0) {
00282 Iterator<Statement> assign_iter = *data_assigns;
00283
00284 for ( ; assign_iter.valid(); ++assign_iter)
00285 pseudo_stmts.ins(assign_iter.current());
00286
00287 Iterator<Statement> entry_iter = pgm.stmts().iterate_entry_points();
00288 p_assert(entry_iter.valid(),
00289 "Main program does not have any entries.");
00290 pgm.stmts().ins_after(data_assigns, &entry_iter.current());
00291 ++entry_iter;
00292 p_assert(! entry_iter.valid(),
00293 "Main program has multiple entries.");
00294 }
00295 else
00296 delete data_assigns;
00297 }
00298 }
00299
00300
00301
00302
00303
00304
00305
00306
00307 static void
00308 _add_control_assigns(StmtList &stmts, const Statement &first_stmt,
00309 const Statement &last_stmt,
00310 const RefSet<Symbol> *candidates,
00311 RefSet<Statement> &pseudo_stmts)
00312 {
00313 Iterator<Statement> stmt_iter = stmts.iterator(first_stmt, last_stmt);
00314
00315 for ( ; stmt_iter.valid(); ++stmt_iter) {
00316 Statement &stmt = stmt_iter.current();
00317
00318 if (stmt.stmt_class() == IF_STMT
00319 && stmt.follow_ref()->stmt_class() != ELSEIF_STMT
00320 && (stmt.expr().op() == ID_OP
00321 || (stmt.expr().op() == NOT_OP
00322 && stmt.expr().expr_guarded().op() == ID_OP)
00323 || stmt.expr().op() == EQ_OP
00324 || stmt.expr().op() == NE_OP)) {
00325
00326
00327
00328 if (stmt.follow_ref()->stmt_class() == ENDIF_STMT) {
00329 Statement *last_then_stmt = stmt.follow_ref()->prev_ref();
00330
00331 if (last_then_stmt->stmt_class() == IMPLIED_GOTO_STMT)
00332 last_then_stmt = last_then_stmt->prev_ref();
00333
00334 stmts.ins_ELSE_after(&stmt, last_then_stmt);
00335 pseudo_stmts.ins(*stmt.follow_ref());
00336 }
00337
00338 p_assert(stmt.follow_ref()->stmt_class() == ELSE_STMT,
00339 "IF statement does not have an ELSE clause.");
00340
00341 Expression *logical_var_expr = &stmt.expr();
00342
00343 if (logical_var_expr->op() == NOT_OP)
00344 logical_var_expr = &logical_var_expr->expr_guarded();
00345
00346 if (logical_var_expr->op() == ID_OP
00347 && logical_var_expr->symbol().type().data_type() == LOGICAL_TYPE
00348 && (! candidates
00349 || candidates->member(logical_var_expr->symbol()))) {
00350
00351
00352
00353 Statement *true_assign
00354 = new AssignmentStmt(stmts.new_tag(),
00355 logical_var_expr->clone(),
00356 constant(".TRUE."));
00357 Statement *false_assign
00358 = new AssignmentStmt(stmts.new_tag(),
00359 logical_var_expr->clone(),
00360 constant(".FALSE."));
00361
00362 if (stmt.expr().op() == NOT_OP) {
00363 stmts.ins_after(false_assign, &stmt);
00364 stmts.ins_after(true_assign, stmt.follow_ref());
00365 }
00366 else {
00367 stmts.ins_after(true_assign, &stmt);
00368 stmts.ins_after(false_assign, stmt.follow_ref());
00369 }
00370
00371 pseudo_stmts.ins(*true_assign);
00372 pseudo_stmts.ins(*false_assign);
00373 }
00374 else if (stmt.expr().op() == EQ_OP || stmt.expr().op() == NE_OP) {
00375
00376
00377 Expression *var_expr = 0;
00378 Expression *const_expr = 0;
00379
00380 if (stmt.expr().left_guarded().op() == ID_OP) {
00381 var_expr = &stmt.expr().left_guarded();
00382 const_expr = &stmt.expr().right_guarded();
00383 }
00384 else {
00385 var_expr = &stmt.expr().right_guarded();
00386 const_expr = &stmt.expr().left_guarded();
00387 }
00388
00389 if (var_expr->op() == ID_OP
00390 && var_expr->symbol().type().data_type() == INTEGER_TYPE
00391 && const_expr->op() == INTEGER_CONSTANT_OP
00392 && (! candidates
00393 || candidates->member(var_expr->symbol()))) {
00394
00395 Statement *const_assign
00396 = new AssignmentStmt(stmts.new_tag(),
00397 var_expr->clone(),
00398 const_expr->clone());
00399 if (stmt.expr().op() == EQ_OP)
00400 stmts.ins_after(const_assign, &stmt);
00401 else
00402 stmts.ins_after(const_assign, stmt.follow_ref());
00403
00404 pseudo_stmts.ins(*const_assign);
00405 }
00406 }
00407 }
00408 }
00409 }
00410
00411
00412
00413
00414
00415
00416
00417 static void
00418 _init_workspaces(StmtList &stmts,
00419 const Statement &first_stmt, const Statement &last_stmt,
00420 const Map<Symbol,IntElem> &def_candidates,
00421 const Map<Symbol,IntElem> &use_candidates,
00422 const Array<Symbol *> &tag_to_candidate)
00423 {
00424 Iterator<Statement> iter = stmts.iterator(first_stmt, last_stmt);
00425
00426 for ( ; iter.valid(); ++iter) {
00427 PropConstWS *my_ws = new PropConstWS(_pass_tag, iter.current(),
00428 def_candidates, use_candidates,
00429 tag_to_candidate);
00430
00431 iter.current().work_stack().push(my_ws);
00432 }
00433 }
00434
00435
00436
00437
00438
00439 static PropConstWS &
00440 _get_workspace(const Statement &stmt)
00441 {
00442 WorkSpace *ws = stmt.work_stack().top_ref(_pass_tag);
00443
00444 p_assert(ws, "Statement doesn't have a ConstPropWS.");
00445
00446 return * (PropConstWS *) ws;
00447 }
00448
00449
00450
00451
00452
00453 static void
00454 _dump_workspaces(ostream &o, const StmtList &stmts,
00455 const Statement &first_stmt, const Statement &last_stmt)
00456 {
00457 Iterator<Statement> iter = stmts.iterator(first_stmt, last_stmt);
00458
00459 for ( ; iter.valid(); ++iter) {
00460 iter.current().structures_OK();
00461 o << iter.current().tag() << ": ";
00462 iter.current().print_debug(o, 0);
00463 o << endl;
00464 _get_workspace(iter.current()).pretty_print(o);
00465 }
00466 }
00467
00468
00469
00470
00471
00472
00473 static void
00474 _make_nonlocals_modified_at_calls(StmtList &stmts,
00475 const Statement &first_stmt,
00476 const Statement &last_stmt,
00477 const Map<Symbol,IntElem> &use_candidates,
00478 const Array<Symbol *> &tag_to_candidate)
00479 {
00480
00481
00482 IntSet non_local_set(tag_to_candidate.entries());
00483
00484 if (switch_value("pc_call_mods") != 1) {
00485 for (int sym_tag = 0; sym_tag < tag_to_candidate.entries(); ++sym_tag) {
00486 Symbol &var = *tag_to_candidate[sym_tag];
00487
00488 if (var.formal() == IS_FORMAL || var.common_ref()) {
00489 non_local_set.ins(sym_tag);
00490
00491
00492
00493
00494 RefSet<Symbol> *aliases = equiv_aliases(var);
00495
00496 if (aliases) {
00497 Iterator<Symbol> alias_iter = *aliases;
00498
00499 for ( ; alias_iter.valid(); ++alias_iter) {
00500 const IntElem *alias_elem
00501 = use_candidates.find_ref(alias_iter.current());
00502
00503 if (alias_elem)
00504 non_local_set.ins(alias_elem->value());
00505 }
00506
00507 delete aliases;
00508 }
00509 }
00510 }
00511 }
00512
00513
00514
00515
00516 Iterator<Statement> iter = stmts.iterator(first_stmt, last_stmt);
00517
00518 for ( ; iter.valid(); ++iter) {
00519 Statement &stmt = iter.current();
00520 PropConstWS &ws = _get_workspace(stmt);
00521
00522 if (ws.unknown_call) {
00523 PropConstMap &const_map = ws.out_const_map;
00524 RefSet<Symbol> *maymods = stmt_maymods(stmt);
00525
00526 if (maymods) {
00527 Iterator<Expression> act_iter = stmt.act_refs();
00528
00529 for ( ; act_iter.valid(); ++act_iter) {
00530 Symbol *var_ref = act_iter.current().base_variable_ref();
00531
00532 if (var_ref) {
00533 const IntElem *tag_elem = use_candidates.find_ref(*var_ref);
00534
00535 if (tag_elem)
00536 ws.mod_set.del(tag_elem->value());
00537 }
00538 }
00539
00540 if (stmt.stmt_class() == ASSIGNMENT_STMT) {
00541 Symbol *var_ref = stmt.lhs().base_variable_ref();
00542
00543 if (var_ref) {
00544 const IntElem *tag_elem = use_candidates.find_ref(*var_ref);
00545
00546 if (tag_elem)
00547 ws.mod_set.ins(tag_elem->value());
00548 }
00549 }
00550
00551 Iterator<Symbol> nl_iter = *maymods;
00552
00553 for ( ; nl_iter.valid(); ++nl_iter) {
00554 const IntElem *tag_elem = use_candidates.find_ref(nl_iter.current());
00555
00556 if (tag_elem) {
00557 int sym_tag = tag_elem->value();
00558 if (sym_tag != ws.lhs_tag()){
00559 const_map[sym_tag].non_const(stmt);
00560 const_map.int_non_const(sym_tag);
00561 }
00562 }
00563 }
00564
00565 delete maymods;
00566 }
00567 else {
00568 ws.mod_set |= non_local_set;
00569
00570 for (int sym_tag = non_local_set.first();
00571 sym_tag != -1;
00572 sym_tag = non_local_set.next(sym_tag)) {
00573
00574 const_map[sym_tag].non_const(stmt);
00575 const_map.int_non_const(sym_tag);
00576 }
00577 }
00578 }
00579 }
00580 }
00581
00582
00583
00584
00585
00586
00587
00588
00589
00590
00591
00592
00593 static void
00594 _patch_flow_graph(StmtList &stmts,
00595 const Statement &first_stmt, const Statement &last_stmt)
00596 {
00597 Iterator<Statement> iter = stmts.iterator(first_stmt, last_stmt);
00598
00599 for ( ; iter.valid(); ++iter) {
00600 Statement &curr = iter.current();
00601
00602 if (curr.stmt_class() == ENDDO_STMT) {
00603 Statement &next = * (Statement *) curr.next_ref();
00604
00605 if (next.work_stack().top_ref(_pass_tag) != 0) {
00606 _get_workspace(curr).succ.ins(next);
00607 _get_workspace(next).pred.ins(curr);
00608 }
00609 }
00610 }
00611 }
00612
00613
00614
00615
00616
00617 static int
00618 _num_stmts_in_block(const StmtList &stmts, const Statement &first_stmt,
00619 const Statement &last_stmt)
00620 {
00621 int entries = 0;
00622
00623 if (stmts.first_ref() == &first_stmt
00624 && stmts.last_ref() == &last_stmt)
00625
00626 entries = stmts.entries();
00627
00628 else {
00629 Iterator<Statement> iter = stmts.iterator(first_stmt, last_stmt);
00630
00631 for ( ; iter.valid(); ++iter)
00632 ++entries;
00633 }
00634
00635 return entries;
00636 }
00637
00638
00639
00640
00641
00642
00643
00644 static void
00645 _determine_entry_points(StmtList &stmts, const Statement &first_stmt,
00646 const Statement &last_stmt,
00647 RefSet<Statement> &entry_points)
00648 {
00649 RefList<Statement> stmts_in_block;
00650 Boolean entire_stmt_list = (stmts.first_ref() == &first_stmt
00651 && stmts.last_ref() == &last_stmt);
00652
00653 if (! entire_stmt_list) {
00654 Iterator<Statement> iter = stmts.iterator(first_stmt, last_stmt);
00655
00656 for ( ; iter.valid(); ++iter)
00657 stmts_in_block.ins_last(iter.current());
00658 }
00659
00660 Iterator<Statement> iter = stmts.iterator(first_stmt, last_stmt);
00661
00662 for ( ; iter.valid(); ++iter) {
00663 Statement &stmt = iter.current();
00664
00665 if (stmt.stmt_class() == ENTRY_STMT
00666 || stmt.stmt_class() == FLOW_ENTRY_STMT)
00667
00668 entry_points.ins(stmt);
00669 else if (! entire_stmt_list) {
00670 PropConstWS &ws = _get_workspace(stmt);
00671 Mutator<Statement> pred_iter = ws.pred;
00672
00673 for ( ; pred_iter.valid(); ++pred_iter)
00674 if (! stmts_in_block.member(pred_iter.current())) {
00675 entry_points.ins(stmt);
00676 pred_iter.del();
00677 }
00678
00679 Mutator<Statement> succ_iter = ws.succ;
00680
00681 for ( ; succ_iter.valid(); ++succ_iter)
00682 if (! stmts_in_block.member(succ_iter.current()))
00683 succ_iter.del();
00684 }
00685 }
00686 }
00687
00688
00689
00690
00691
00692
00693
00694 static void
00695 _calc_toporder1(PropConstWS &my_ws, int &toporder)
00696 {
00697 my_ws.visited(1);
00698
00699 Iterator<Statement> succ_iter = my_ws.succ;
00700
00701 for ( ; succ_iter.valid(); ++succ_iter) {
00702 PropConstWS &succ_ws = _get_workspace(succ_iter.current());
00703
00704 if (! succ_ws.visited())
00705 _calc_toporder1(succ_ws, toporder);
00706 }
00707
00708 my_ws.toporder(toporder--);
00709 }
00710
00711 static void
00712 _calc_toporder(StmtList &stmts, const Statement &first_stmt,
00713 const Statement &last_stmt,
00714 const RefSet<Statement> &entry_points,
00715 Array<Statement *> &toporder_to_stmt)
00716 {
00717
00718
00719 int num_stmts = _num_stmts_in_block(stmts, first_stmt, last_stmt);
00720 int toporder = num_stmts - 1;
00721
00722 if (toporder >= 0) {
00723 Iterator<Statement> entry_iter = entry_points;
00724
00725 for ( ; entry_iter.valid(); ++entry_iter) {
00726 PropConstWS &entry_ws = _get_workspace(entry_iter.current());
00727
00728 if (! entry_ws.visited())
00729 _calc_toporder1(entry_ws, toporder);
00730 }
00731
00732 p_assert(toporder >= -1,
00733 "_calc_toporder visited a stmt more than once.");
00734 }
00735
00736
00737
00738 toporder_to_stmt.resize(num_stmts);
00739
00740 for (int i = 0; i <= toporder; ++i)
00741 toporder_to_stmt[i] = 0;
00742
00743 Iterator<Statement> iter = stmts.iterator(first_stmt, last_stmt);
00744
00745 for ( ; iter.valid(); ++iter) {
00746 int stmt_toporder = _get_workspace(iter.current()).toporder();
00747
00748 if (stmt_toporder >= 0)
00749 toporder_to_stmt[stmt_toporder] = &iter.current();
00750 }
00751 }
00752
00753
00754
00755
00756
00757
00758
00759
00760
00761 static Expression *
00762 _annotate_expr(Expression *expr,
00763 const PropConstMap &orig_const_map,
00764 const PropConstMap &curr_const_map,
00765 const Map<Symbol,IntElem> &use_candidates)
00766 {
00767 if (! expr)
00768 return expr;
00769
00770 if (expr->op() == ID_OP) {
00771 if (! expr->substituted_valid()) {
00772 const IntElem *tag_elem
00773 = use_candidates.find_ref(expr->symbol());
00774 Expression *subst_expr = 0;
00775
00776 if (tag_elem) {
00777 int sym_tag = tag_elem->value();
00778
00779 if (orig_const_map.int_state(sym_tag) == CONST) {
00780 int int_const = orig_const_map.int_const_val(sym_tag);
00781
00782 if (expr->symbol().type().data_type() == LOGICAL_TYPE)
00783 if (int_const == 0)
00784 subst_expr = constant(".FALSE.");
00785 else
00786 subst_expr = constant(".TRUE.");
00787 else
00788 subst_expr = constant(int_const);
00789 }
00790 else {
00791 PropConstElem &curr_const = curr_const_map[sym_tag];
00792 Boolean var_is_poisoned = False;
00793
00794 if (curr_const.state() == CONST) {
00795 PropConstWS &subst_ws = _get_workspace(*curr_const.last_mod());
00796 var_is_poisoned = subst_ws.poisoned_vars[sym_tag];
00797
00798 if (! var_is_poisoned) {
00799 subst_ws.poisoned_vars.ins(sym_tag);
00800 subst_expr = curr_const.expr().clone();
00801 clear_substituted(*subst_expr);
00802 subst_expr = _annotate_expr(subst_expr,
00803 orig_const_map,
00804 subst_ws.in_const_map,
00805 use_candidates);
00806 subst_ws.poisoned_vars.del(sym_tag);
00807 }
00808 }
00809
00810 PropConstElem &orig_const = orig_const_map[sym_tag];
00811
00812 if (var_is_poisoned
00813 || orig_const.last_mod() != curr_const.last_mod()
00814 || orig_const.state() != curr_const.state()) {
00815
00816
00817
00818
00819
00820
00821
00822
00823
00824 delete expr;
00825 return subst_expr;
00826 }
00827 }
00828 }
00829
00830 expr->substituted(subst_expr);
00831 }
00832 else {
00833
00834
00835 expr->substituted(_annotate_expr(expr->grab_substituted(),
00836 orig_const_map, curr_const_map,
00837 use_candidates));
00838 }
00839 }
00840 else {
00841 Mutator<Expression> iter = expr->arg_list();
00842
00843 for ( ; iter.valid(); ++iter) {
00844 Assign<Expression> eas(iter.assign());
00845 Expression *new_expr = _annotate_expr(iter.pull(), orig_const_map,
00846 curr_const_map,
00847 use_candidates);
00848
00849 if (! new_expr) {
00850 delete expr;
00851 return 0;
00852 }
00853 else
00854 eas = new_expr;
00855 }
00856 }
00857
00858 return expr;
00859 }
00860
00861
00862
00863
00864
00865
00866 static Expression *
00867 _annotate_expr(Expression *expr, const PropConstMap &const_map,
00868 const Map<Symbol,IntElem> &use_candidates)
00869 {
00870 Expression *new_expr = _annotate_expr(expr, const_map,
00871 const_map, use_candidates);
00872 p_assert(new_expr,
00873 "Internal Error: _annotate_expr failed for root expression.");
00874
00875 return new_expr;
00876 }
00877
00878 Expression *
00879 _annotate_expr(Expression *expr, const Statement &stmt,
00880 const Map<Symbol,IntElem> &use_candidates)
00881 {
00882 PropConstWS &my_ws = _get_workspace(stmt);
00883 PropConstMap &const_map = my_ws.out_const_map;
00884
00885 return _annotate_expr(expr, const_map, use_candidates);
00886 }
00887
00888
00889
00890
00891
00892
00893 static void
00894 _annotate_assert(Statement &stmt, const PropConstMap &const_map,
00895 const Map<Symbol,IntElem> &use_candidates)
00896 {
00897 Iterator<Assertion> ass_iter = stmt.assertions();
00898
00899 for ( ; ass_iter.valid(); ++ass_iter) {
00900 if (ass_iter.current().arg_list_valid()) {
00901 Mutator<Expression> aexpr_iter
00902 = ass_iter.current().arg_list_guarded();
00903
00904 for ( ; aexpr_iter.valid(); ++aexpr_iter)
00905 if (aexpr_iter.current().op() != ID_OP) {
00906 Assign<Expression> eas(aexpr_iter.assign());
00907 eas = _annotate_expr(aexpr_iter.pull(),
00908 const_map,
00909 use_candidates);
00910 }
00911 }
00912 }
00913 }
00914
00915
00916
00917
00918
00919
00920 static void
00921 _annotate_stmt(Statement &stmt, const Map<Symbol,IntElem> &use_candidates)
00922 {
00923 if (_debug_level >= 5) {
00924 cout << "! Before: ";
00925 stmt.print_debug(cout, 0);
00926 cout << endl;
00927 }
00928
00929
00930
00931
00932 PropConstWS &my_ws = _get_workspace(stmt);
00933 PropConstMap unmodified_const_map(my_ws.in_const_map);
00934
00935 for (int sym_tag = my_ws.mod_set.first();
00936 sym_tag != -1;
00937 sym_tag = my_ws.mod_set.next(sym_tag)) {
00938 unmodified_const_map[sym_tag].non_const(stmt);
00939 unmodified_const_map.int_non_const(sym_tag);
00940 }
00941
00942
00943
00944 if (stmt.stmt_class() == ASSIGNMENT_STMT
00945 && stmt.rhs().is_side_effect_free()) {
00946
00947 Mutator<Expression> iter = stmt.iterate_expressions();
00948
00949
00950 Assign<Expression> eas(iter.assign());
00951 eas = _annotate_expr(iter.pull(), unmodified_const_map,
00952 use_candidates);
00953
00954
00955 ++iter;
00956 Assign<Expression> eas2(iter.assign());
00957 eas2 = _annotate_expr(iter.pull(), my_ws.in_const_map,
00958 use_candidates);
00959 }
00960 else {
00961 Mutator<Expression> iter = stmt.iterate_expressions();
00962
00963 for ( ; iter.valid(); ++iter) {
00964 Assign<Expression> eas3(iter.assign());
00965 eas3 = _annotate_expr(iter.pull(), unmodified_const_map,
00966 use_candidates);
00967 }
00968 }
00969
00970 _annotate_assert(stmt, unmodified_const_map, use_candidates);
00971
00972 if (_debug_level >= 5) {
00973 cout << "! After: ";
00974 stmt.print_debug(cout, 0);
00975 cout << endl;
00976 }
00977 }
00978
00979
00980
00981
00982
00983
00984 static void
00985 _annotate_stmts(StmtList &stmts, const Statement &first_stmt,
00986 const Statement &last_stmt,
00987 const Map<Symbol,IntElem> &use_candidates)
00988 {
00989 Iterator<Statement> iter = stmts.iterator(first_stmt, last_stmt);
00990
00991 for ( ; iter.valid(); ++iter)
00992 _annotate_stmt(iter.current(), use_candidates);
00993 }
00994
00995
00996
00997
00998
00999
01000
01001
01002
01003 void
01004 _kill_bad_join_consts(Statement &stmt, PropConstMap &const_map)
01005 {
01006 PropConstWS &curr_ws = _get_workspace(stmt);
01007
01008 if (curr_ws.pred.entries() < 2)
01009 return;
01010
01011 for (int sym_tag = 0; sym_tag < const_map.entries(); ++sym_tag) {
01012 PropConstElem &const_elem = const_map[sym_tag];
01013
01014 if (const_elem.state() == CONST
01015 && const_elem.last_mod() == &stmt
01016 && const_elem.use_set().entries() > 0) {
01017
01018
01019
01020
01021
01022
01023 Boolean has_modified_use = False;
01024 Iterator<Statement> pred_iter = curr_ws.pred;
01025
01026 for ( ; pred_iter.valid() && ! has_modified_use; ++pred_iter) {
01027 PropConstWS &pred_ws = _get_workspace(pred_iter.current());
01028
01029 if (pred_ws.num_visits() > 0) {
01030 PropConstMap &pred_map = pred_ws.out_const_map;
01031 PropConstElem &pred_elem = pred_map[sym_tag];
01032
01033 if (pred_elem.state() != MAY_BE_CONST) {
01034 p_assert(pred_elem.state() == CONST,
01035 "Predecessor of constant expression is a non-constant.");
01036
01037 PropConstMap &last_mod_map
01038 = _get_workspace(*pred_elem.last_mod()).out_const_map;
01039
01040
01041
01042 for (int use_tag = pred_elem.use_set().first();
01043 use_tag != -1 && ! has_modified_use;
01044 use_tag = pred_elem.use_set().next(use_tag))
01045 if (last_mod_map[use_tag].last_mod()
01046 != pred_map[use_tag].last_mod())
01047
01048 has_modified_use = True;
01049 }
01050 }
01051 }
01052
01053 if (has_modified_use)
01054 const_elem.non_const(stmt);
01055 }
01056 }
01057 }
01058
01059
01060
01061
01062
01063
01064 static Boolean
01065 _const_if_took_then(const Statement &stmt)
01066 {
01067 if (stmt.stmt_class() != IF_STMT && stmt.stmt_class() != ELSEIF_STMT)
01068 return False;
01069
01070 const PropConstWS &ws = _get_workspace(stmt);
01071
01072 if (ws.num_visits() == 0 || ! ws.const_cond)
01073 return False;
01074
01075 return (_get_workspace(*stmt.next_ref()).num_visits() > 0);
01076 }
01077
01078
01079
01080
01081
01082
01083 Statement *
01084 _const_if_succ(Statement &stmt,
01085 const Map<Symbol,IntElem> &use_candidates)
01086 {
01087 if (stmt.stmt_class() != IF_STMT
01088 && stmt.stmt_class() != ELSEIF_STMT
01089 && stmt.stmt_class() != ARITHMETIC_IF_STMT)
01090
01091 return 0;
01092
01093 int cond_result;
01094 const PropConstWS &ws = _get_workspace(stmt);
01095 Statement *succ = 0;
01096
01097 if (int_const_val(stmt.expr(), ws.in_const_map, use_candidates,
01098 cond_result)) {
01099 if (stmt.stmt_class() == IF_STMT || stmt.stmt_class() == ELSEIF_STMT) {
01100 if (cond_result == 0)
01101 succ = stmt.follow_ref();
01102 else
01103 succ = stmt.next_ref();
01104 }
01105 else {
01106 if (cond_result < 0)
01107 succ = &stmt.label_list()[0];
01108 else if (cond_result == 0)
01109 succ = &stmt.label_list()[1];
01110 else
01111 succ = &stmt.label_list()[2];
01112 }
01113 }
01114
01115 return succ;
01116 }
01117
01118
01119
01120
01121
01122 static void
01123 _put_succ_on_work_list(IntSet &work_list, Statement &stmt,
01124 const Map<Symbol,IntElem> &use_candidates)
01125 {
01126 PropConstWS &ws = _get_workspace(stmt);
01127
01128 if (ws.const_cond) {
01129 const Statement *succ = _const_if_succ(stmt, use_candidates);
01130
01131 if (! succ)
01132 ws.const_cond = False;
01133 else {
01134 if (_debug_level >= 5) {
01135 cout << "! Statement: ";
01136 stmt.print_debug(cout, 0);
01137 cout << " has a constant conditional\n";
01138 }
01139
01140 work_list.ins(_get_workspace(*succ).toporder());
01141 }
01142 }
01143
01144 if (! ws.const_cond) {
01145 Iterator<Statement> succ_iter = ws.succ;
01146
01147 for ( ; succ_iter.valid(); ++succ_iter)
01148 work_list.ins(_get_workspace(succ_iter.current()).toporder());
01149 }
01150 }
01151
01152
01153
01154
01155
01156
01157 static void
01158 _iterate_to_fixed_point(StmtList & ,
01159 const Statement & ,
01160 const Statement & ,
01161 const RefSet<Statement> &entry_points,
01162 const Array<Statement *> &toporder_to_stmt,
01163 const Map<Symbol,IntElem> &use_candidates,
01164 const Array<Symbol *> &tag_to_candidate,
01165 const Map<Symbol, Expression> &entering_constants)
01166 {
01167
01168
01169 IntSet work_list(toporder_to_stmt.entries());
01170
01171
01172
01173 Iterator<Statement> entry_iter = entry_points;
01174
01175 for ( ; entry_iter.valid(); ++entry_iter)
01176 work_list.ins(_get_workspace(entry_iter.current()).toporder());
01177
01178
01179
01180 while (work_list.entries() > 0) {
01181
01182
01183 for (int stmt_num = work_list.first();
01184 stmt_num != -1;
01185 stmt_num = work_list.next(stmt_num)) {
01186
01187 Statement &curr = *toporder_to_stmt[stmt_num];
01188 work_list.del(stmt_num);
01189 PropConstWS &curr_ws = _get_workspace(curr);
01190 curr_ws.incr_num_visits();
01191 Boolean changed = False;
01192
01193
01194
01195 PropConstMap new_in_const_map(use_candidates.entries(),
01196 tag_to_candidate);
01197
01198 if (entry_points.member(curr)) {
01199 new_in_const_map.all_non_const(curr);
01200 curr_ws.add_consts(entering_constants);
01201 }
01202 else {
01203 Iterator<Statement> pred_iter = curr_ws.pred;
01204
01205 for ( ; pred_iter.valid(); ++pred_iter) {
01206 PropConstWS &pred_ws = _get_workspace(pred_iter.current());
01207
01208 if (pred_ws.num_visits() > 0
01209 && (curr.stmt_class() != ENDIF_STMT
01210 || ! _const_if_took_then(pred_iter.current())))
01211
01212 new_in_const_map.intersect(pred_ws.out_const_map,
01213 curr);
01214 }
01215 }
01216
01217 _kill_bad_join_consts(curr, new_in_const_map);
01218
01219 if (curr_ws.num_visits() == 1
01220 || new_in_const_map != curr_ws.in_const_map) {
01221
01222
01223
01224
01225
01226 if (_debug_level >= 20) {
01227 cout << "! Statement ";
01228 curr.print_debug(cout, 0);
01229 cout << " was visited and updated.\n";
01230 }
01231
01232 curr_ws.in_const_map = new_in_const_map;
01233 changed = curr_ws.update_out_const_map();
01234
01235 if (! changed
01236 && curr_ws.const_cond
01237 && _const_if_succ(curr, use_candidates) == 0) {
01238
01239 curr_ws.const_cond = False;
01240 changed = True;
01241 }
01242
01243 if (_debug_level >= 30)
01244 curr_ws.pretty_print(cout);
01245
01246 if (changed || curr_ws.num_visits() == 1) {
01247
01248
01249
01250
01251
01252 _put_succ_on_work_list(work_list, curr, use_candidates);
01253 }
01254 }
01255 }
01256 }
01257 }
01258
01259
01260
01261
01262
01263
01264 static Boolean
01265 _is_block_unreachable(const StmtList &stmts,
01266 const Statement &first_stmt,
01267 const Statement &last_stmt)
01268 {
01269
01270
01271
01272
01273 Boolean is_block_unreachable = True;
01274 Iterator<Statement> iter = stmts.iterator(first_stmt, last_stmt);
01275
01276 for ( ; iter.valid() && is_block_unreachable; ++iter)
01277 if (iter.current().stmt_class() != IMPLIED_GOTO_STMT
01278 && _get_workspace(iter.current()).num_visits() > 0)
01279 is_block_unreachable = False;
01280
01281 return is_block_unreachable;
01282 }
01283
01284
01285
01286
01287
01288 static void
01289 _remove_unreachable(StmtList &stmts,
01290 const Statement &first_stmt,
01291 const Statement &last_stmt,
01292 const Map<Symbol,IntElem> &use_candidates)
01293 {
01294 Boolean deleted_a_stmt = False;
01295
01296
01297
01298 Iterator<Statement> iter = stmts.iterator(first_stmt, last_stmt);
01299
01300 for ( ; iter.valid(); ++iter)
01301 if (iter.current_valid()) {
01302 Statement &stmt = iter.current();
01303
01304 if ((stmt.stmt_class() == IF_STMT
01305 || stmt.stmt_class() == ELSEIF_STMT
01306 || stmt.stmt_class() == ARITHMETIC_IF_STMT)
01307 && _get_workspace(stmt).num_visits() > 0
01308 && _get_workspace(stmt).const_cond) {
01309
01310 if (_debug_level >= 5) {
01311 cout << "! If statement: ";
01312 stmt.print_debug(cout, 0);
01313 cout << " is constant. Attempting to remove it.\n";
01314 }
01315
01316 Statement *target = _const_if_succ(stmt, use_candidates);
01317 p_assert(target,
01318 "IF statement does not have a constant conditional.");
01319
01320 if (stmt.stmt_class() == ARITHMETIC_IF_STMT) {
01321
01322
01323
01324 Statement *goto_target = new GotoStmt(stmts.new_tag(),
01325 target);
01326 goto_target->work_stack().push(
01327 new PropConstWS(_get_workspace(stmt)));
01328 stmts.modify(stmt, goto_target);
01329 }
01330 else if (stmt.stmt_class() == ELSEIF_STMT) {
01331
01332 }
01333 else if (stmt.stmt_class() == IF_STMT
01334 && stmt.follow_ref()->stmt_class() == ELSEIF_STMT
01335 && target == stmt.follow_ref()) {
01336
01337
01338
01339 }
01340 else {
01341
01342
01343
01344 if ((target == stmt.next_ref()
01345 && _is_block_unreachable(stmts,
01346 *stmt.follow_ref(),
01347 *stmt.matching_endif_ref()->prev_ref()))
01348 || (target == stmt.follow_ref()
01349 && _is_block_unreachable(stmts,
01350 *stmt.next_ref(),
01351 *stmt.follow_ref()->prev_ref())))
01352 stmts.del(stmt);
01353 else {
01354
01355
01356
01357 if (target == stmt.next_ref()
01358 && stmt.follow_ref()->stmt_class() != ENDIF_STMT)
01359
01360 _get_workspace(*stmt.follow_ref()).incr_num_visits();
01361 }
01362 }
01363
01364 deleted_a_stmt = True;
01365 }
01366 }
01367
01368
01369
01370 RefSet<Statement> unreachable_stmts;
01371
01372 for (iter.reset(); iter.valid(); ++iter)
01373 if (iter.current().stmt_class() != FLOW_ENTRY_STMT
01374 && _get_workspace(iter.current()).num_visits() == 0)
01375 unreachable_stmts.ins(iter.current());
01376
01377 deleted_a_stmt = deleted_a_stmt || unreachable_stmts.entries() > 0;
01378
01379
01380
01381
01382
01383
01384
01385
01386
01387
01388
01389 for (Iterator<Statement> st_iter = unreachable_stmts;
01390 st_iter.valid();
01391 ++st_iter)
01392 {
01393 Statement & stmt = st_iter.current();
01394 if (stmt.stmt_class() == ENDDO_STMT) {
01395 Statement * dostmt = stmt.follow_ref();
01396 if (!unreachable_stmts.member(*dostmt)) {
01397 AssignmentStmt *assign =
01398 new AssignmentStmt(stmts.new_tag(),
01399 dostmt->index().clone(),
01400 dostmt->init().clone());
01401 stmts.ins_before(assign, dostmt);
01402
01403 stmts.ins_IF_after (
01404 ge(dostmt->limit().clone(),
01405 dostmt->index().clone()),
01406 assign,
01407 &stmt);
01408 }
01409 }
01410 }
01411
01412 stmts.del(unreachable_stmts);
01413
01414 if (deleted_a_stmt) {
01415 stmts.create_flow_graph();
01416
01417 }
01418 }
01419
01420
01421
01422
01423
01424
01425
01426 static void
01427 _propagate_constants1(StmtList &stmts,
01428 const Statement &first_stmt,
01429 const Statement &last_stmt,
01430 Map<Symbol,IntElem> &def_candidates,
01431 Map<Symbol,IntElem> &use_candidates,
01432 Array<Symbol *> &tag_to_candidate,
01433 RefSet<Statement> &pseudo_stmts,
01434 PC_UNREACH_BOOL remove_unreachable,
01435 int debug)
01436 {
01437
01438 RefSet<Statement> entry_points;
01439
01440
01441 Array<Statement *> toporder_to_stmt;
01442
01443 _debug_level = debug;
01444 Timer tot_timer;
01445 Timer timer;
01446
01447
01448
01449
01450 _pass_tag = create_pass_tag();
01451 _init_workspaces(stmts, first_stmt, last_stmt, def_candidates,
01452 use_candidates, tag_to_candidate);
01453 _make_nonlocals_modified_at_calls(stmts, first_stmt, last_stmt,
01454 use_candidates, tag_to_candidate);
01455 _patch_flow_graph(stmts, first_stmt, last_stmt);
01456 _determine_entry_points(stmts, first_stmt, last_stmt, entry_points);
01457 _calc_toporder(stmts, first_stmt, last_stmt, entry_points,
01458 toporder_to_stmt);
01459
01460 if (_debug_level > 0) {
01461 cout << "! Initialization: " << timer << endl;
01462 timer.reset();
01463 }
01464
01465
01466
01467
01468 Map<Symbol,Expression> entering_constants;
01469 _iterate_to_fixed_point(stmts, first_stmt, last_stmt, entry_points,
01470 toporder_to_stmt, use_candidates,
01471 tag_to_candidate, entering_constants);
01472
01473 if (_debug_level > 0) {
01474 cout << "! Iterating to fixed point: " << timer << endl;
01475 timer.reset();
01476 }
01477
01478
01479
01480
01481 _annotate_stmts(stmts, first_stmt, last_stmt, use_candidates);
01482
01483 if (_debug_level > 0)
01484 cout << "! Annotating pgm with constants: " << timer << endl;
01485
01486 if (_debug_level >= 10)
01487 _dump_workspaces(cout, stmts, first_stmt, last_stmt);
01488
01489
01490
01491 if (remove_unreachable == REMOVE_UNREACH_CODE) {
01492 stmts.del(pseudo_stmts);
01493 _remove_unreachable(stmts, first_stmt, last_stmt, use_candidates);
01494
01495 if (_debug_level > 0) {
01496 cout << "! Removing unreachable code: " << timer << endl;
01497 timer.reset();
01498 }
01499 }
01500
01501
01502
01503 Iterator<Statement> stmt_iter = stmts.iterator(first_stmt, last_stmt);
01504
01505 for ( ; stmt_iter.valid(); ++stmt_iter)
01506 stmt_iter.current().work_stack().pop(_pass_tag);
01507
01508 if (_debug_level > 0) {
01509 int num_stmts = _num_stmts_in_block(stmts, first_stmt, last_stmt);
01510
01511 cout << "! Total time: " << tot_timer << endl;
01512 cout << "! Number of statements: " << num_stmts << endl;
01513 cout << "! Number of candidate variables: " << use_candidates.entries() << endl;
01514 }
01515 }
01516
01517
01518
01519
01520
01521
01522 static void
01523 _propagate_constants_all_vars(StmtList &stmts,
01524 const Statement &first_stmt,
01525 const Statement &last_stmt,
01526 RefSet<Statement> &pseudo_stmts,
01527 PC_REAL_BOOL subst_reals,
01528 PC_ARRAY_BOOL subst_arrays,
01529 PC_UNREACH_BOOL remove_unreachable,
01530 int debug)
01531 {
01532
01533 Map<Symbol,IntElem> def_candidates;
01534
01535
01536
01537 Map<Symbol,IntElem> use_candidates;
01538
01539
01540 Array<Symbol *> tag_to_candidate;
01541
01542 if (remove_unreachable == REMOVE_UNREACH_CODE)
01543 _add_control_assigns(stmts, first_stmt, last_stmt, 0, pseudo_stmts);
01544
01545 _collect_candidates(stmts, first_stmt, last_stmt, def_candidates,
01546 use_candidates, tag_to_candidate, subst_reals,
01547 subst_arrays);
01548 _propagate_constants1(stmts, first_stmt, last_stmt, def_candidates,
01549 use_candidates, tag_to_candidate,
01550 pseudo_stmts, remove_unreachable, debug);
01551 }
01552
01553
01554
01555
01556
01557
01558 static void
01559 _propagate_constants_some_vars(StmtList &stmts,
01560 const Statement &first_stmt,
01561 const Statement &last_stmt,
01562 const RefSet<Symbol> &candidates,
01563 RefSet<Statement> &pseudo_stmts,
01564 PC_UNREACH_BOOL remove_unreachable,
01565 int debug)
01566 {
01567
01568 Map<Symbol,IntElem> def_candidates;
01569
01570
01571
01572 Map<Symbol,IntElem> use_candidates;
01573
01574
01575 Array<Symbol *> tag_to_candidate;
01576
01577 if (remove_unreachable == REMOVE_UNREACH_CODE)
01578 _add_control_assigns(stmts, first_stmt, last_stmt,
01579 &candidates, pseudo_stmts);
01580
01581 _collect_candidates(candidates, stmts, first_stmt, last_stmt,
01582 def_candidates, use_candidates, tag_to_candidate);
01583 _propagate_constants1(stmts, first_stmt, last_stmt, def_candidates,
01584 use_candidates, tag_to_candidate, pseudo_stmts,
01585 remove_unreachable, debug);
01586 }
01587
01588
01589
01590
01591
01592 void
01593 propagate_constants(StmtList &stmts,
01594 const Statement &first_stmt,
01595 const Statement &last_stmt,
01596 PC_REAL_BOOL subst_reals,
01597 PC_ARRAY_BOOL subst_arrays,
01598 PC_UNREACH_BOOL remove_unreachable,
01599 int debug GIV(0))
01600 {
01601 RefSet<Statement> pseudo_stmts;
01602 _propagate_constants_all_vars(stmts, first_stmt, last_stmt, pseudo_stmts,
01603 subst_reals, subst_arrays,
01604 remove_unreachable, debug);
01605 }
01606
01607 void
01608 propagate_constants(ProgramUnit &pgm,
01609 PC_REAL_BOOL subst_reals,
01610 PC_ARRAY_BOOL subst_arrays,
01611 PC_UNREACH_BOOL remove_unreachable,
01612 int debug GIV(0))
01613 {
01614 if (pgm.stmts().entries() <= 0)
01615 return;
01616
01617 StmtList &stmts = pgm.stmts();
01618 const Statement &first_stmt = *stmts.first_ref();
01619 const Statement &last_stmt = *stmts.last_ref();
01620
01621 RefSet<Statement> pseudo_stmts;
01622 _add_data_assigns(pgm, 0, subst_reals, pseudo_stmts);
01623
01624 _propagate_constants_all_vars(stmts, first_stmt, last_stmt, pseudo_stmts,
01625 subst_reals, subst_arrays,
01626 remove_unreachable, debug);
01627
01628 if (remove_unreachable == REMOVE_UNREACH_CODE)
01629 remove_trivial_gotos(pgm);
01630 }
01631
01632 void
01633 propagate_constants(StmtList &stmts,
01634 const Statement &first_stmt,
01635 const Statement &last_stmt,
01636 const RefSet<Symbol> &candidates,
01637 PC_UNREACH_BOOL remove_unreachable,
01638 int debug GIV(0))
01639 {
01640 RefSet<Statement> pseudo_stmts;
01641 _propagate_constants_some_vars(stmts, first_stmt, last_stmt, candidates,
01642 pseudo_stmts, remove_unreachable, debug);
01643 }
01644
01645 void
01646 propagate_constants(ProgramUnit &pgm,
01647 const RefSet<Symbol> &candidates,
01648 PC_UNREACH_BOOL remove_unreachable,
01649 int debug GIV(0))
01650 {
01651 if (pgm.stmts().entries() <= 0)
01652 return;
01653
01654 StmtList &stmts = pgm.stmts();
01655 const Statement &first_stmt = *stmts.first_ref();
01656 const Statement &last_stmt = *stmts.last_ref();
01657
01658 RefSet<Statement> pseudo_stmts;
01659 _add_data_assigns(pgm, &candidates, SUBST_REALS, pseudo_stmts);
01660
01661 _propagate_constants_some_vars(stmts, first_stmt, last_stmt, candidates,
01662 pseudo_stmts, remove_unreachable, debug);
01663
01664 if (remove_unreachable == REMOVE_UNREACH_CODE)
01665 remove_trivial_gotos(pgm);
01666 }
01667
01668
01669
01670
01671 extern "C" int
01672 propagate_constants_pu(char **data, int *len)
01673 {
01674 P_ASSERT_HANDLER(0);
01675 external_interface_init();
01676
01677 ProgramUnit *pgm = external_program_unit( data, len );
01678 p_assert( pgm, "not a program unit" );
01679
01680 propagate_constants(*pgm,
01681 (PC_REAL_BOOL) switch_value("pc_real"),
01682 (PC_ARRAY_BOOL) switch_value("pc_array"),
01683 (PC_UNREACH_BOOL) switch_value("pc_unreach"));
01684
01685 return setup_to_return_handle( pgm->pu_tag_ref(), data, len);
01686 }
01687
01688
01689
01690
01691
01692
01693
01694 static void
01695 _init_ipcp_workspaces(StmtList &stmts,
01696 const IPCPProcData &proc_data,
01697 const Map<Symbol,IntElem> &def_candidates,
01698 const Map<Symbol,IntElem> &use_candidates,
01699 const Array<Symbol *> &tag_to_candidate)
01700 {
01701 Iterator<Statement> iter = stmts.iterator();
01702
01703 for ( ; iter.valid(); ++iter) {
01704 const Statement &stmt = iter.current();
01705 PropConstWS *my_ws;
01706 const IPCPCallData *call_data = proc_data.call_data(stmt);
01707
01708 if (call_data && call_data->data_ref()) {
01709 my_ws= new PropConstWS(_pass_tag, stmt, stmt,
01710 *call_data->data_ref(), proc_data, True,
01711 def_candidates, use_candidates,
01712 tag_to_candidate);
01713 stmt.work_stack().push(my_ws);
01714 ++iter;
01715 const Statement &call_succ = iter.current();
01716 p_assert(call_succ.stmt_class() == LABEL_STMT,
01717 "Couldn't find dummy label statement after procedure call.");
01718 my_ws= new PropConstWS(_pass_tag, call_succ, stmt,
01719 *call_data->data_ref(), proc_data, False,
01720 def_candidates, use_candidates,
01721 tag_to_candidate);
01722 call_succ.work_stack().push(my_ws);
01723 }
01724 else {
01725 my_ws= new PropConstWS(_pass_tag, stmt,
01726 def_candidates, use_candidates,
01727 tag_to_candidate);
01728 stmt.work_stack().push(my_ws);
01729 }
01730 }
01731 }
01732
01733
01734
01735
01736
01737
01738 static RefSet<Symbol> *
01739 _build_modified_vars(const StmtList &stmts,
01740 const RefSet<Statement> &ignorable_stmts,
01741 const Array<Symbol *> &tag_to_candidate)
01742 {
01743 RefSet<Symbol> *modified_vars = new RefSet<Symbol>;
01744
01745 Iterator<Statement> stmt_iter = stmts.iterator();
01746
01747 for ( ; stmt_iter.valid(); ++stmt_iter) {
01748 Statement &stmt = stmt_iter.current();
01749 PropConstWS &ws = _get_workspace(stmt);
01750
01751 if (! ignorable_stmts.member(stmt) && ws.num_visits() > 0) {
01752 for (int sym_tag = ws.mod_set.first();
01753 sym_tag != -1;
01754 sym_tag = ws.mod_set.next(sym_tag))
01755 modified_vars->ins(*tag_to_candidate[sym_tag]);
01756 }
01757 }
01758
01759 return modified_vars;
01760 }
01761
01762
01763
01764
01765
01766
01767
01768
01769 static void
01770 _alias_consts(RefSet<Symbol> &alias_consts,
01771 RefMap<Symbol,Symbol> &alias_const_map,
01772 const RefList<Symbol> &formals,
01773 const List<Expression> &actuals,
01774 const RefSet<Symbol> &keepable_vars)
01775 {
01776 p_assert(formals.entries() == actuals.entries(),
01777 "JumpFunction::new_values(): The number of formals does not equal the number of actuals.");
01778 Iterator<Symbol> formal_iter = formals;
01779 Iterator<Expression> actual_iter = actuals;
01780
01781 for ( ; formal_iter.valid(); ++formal_iter, ++actual_iter) {
01782 const Symbol &formal = formal_iter.current();
01783
01784 if (actual_iter.current().op() == ID_OP) {
01785 Symbol &actual = actual_iter.current().symbol();
01786
01787 if (! actual.is_array()
01788 && ! keepable_vars.member(actual)
01789 && ! alias_consts.member(actual)
01790 && actual.type() == formal.type()) {
01791
01792 alias_consts.ins(actual);
01793 alias_const_map.ins(actual, formal);
01794 }
01795 }
01796 }
01797 }
01798
01799
01800
01801
01802
01803 static void
01804 _rename_alias_consts(Expression &expr,
01805 const RefMap<Symbol,Symbol> &alias_const_map)
01806 {
01807 if (expr.op() == ID_OP) {
01808 const Symbol *val = alias_const_map.find_ref(expr.symbol());
01809
01810 if (val)
01811 expr.symbol(*val);
01812 }
01813 else {
01814 Iterator<Expression> arg_iter = expr.arg_list();
01815
01816 for ( ; arg_iter.valid(); ++arg_iter)
01817 _rename_alias_consts(arg_iter.current(), alias_const_map);
01818 }
01819 }
01820
01821
01822
01823
01824
01825
01826
01827 static Expression *
01828 _remove_local_effects_from_expr1(Expression *expr,
01829 const PropConstMap &const_map,
01830 const Map<Symbol,IntElem> &candidates)
01831 {
01832 if (! expr)
01833 return expr;
01834
01835 if (expr->op() == ID_OP) {
01836 const IntElem *tag_elem = candidates.find_ref(expr->symbol());
01837 p_assert(tag_elem || expr->symbol().sym_class() != VARIABLE_CLASS,
01838 "_remove_local_effects_from_expr1(): Expression contains a var not in candidates.");
01839
01840 if (tag_elem) {
01841 int sym_tag = tag_elem->value();
01842 PropConstElem &curr_const = const_map[sym_tag];
01843 p_assert(curr_const.last_mod(),
01844 "_remove_local_effects_from_expr1(): Expression contains a var with an undefined constant value.");
01845
01846 if (curr_const.last_mod()->stmt_class() != FLOW_ENTRY_STMT
01847 && curr_const.last_mod()->stmt_class() != ENTRY_STMT) {
01848
01849 Expression *subst_expr = 0;
01850
01851 if (curr_const.state() == CONST) {
01852 PropConstWS &subst_ws = _get_workspace(*curr_const.last_mod());
01853
01854 if (! subst_ws.poisoned_vars[sym_tag]) {
01855 subst_ws.poisoned_vars.ins(sym_tag);
01856 subst_expr = curr_const.expr().clone();
01857 subst_expr
01858 = _remove_local_effects_from_expr1(subst_expr,
01859 subst_ws.in_const_map,
01860 candidates);
01861 subst_ws.poisoned_vars.del(sym_tag);
01862
01863 if (subst_expr && subst_expr->base_variable_ref())
01864 subst_expr = paren(subst_expr);
01865
01866 }
01867 }
01868
01869 delete expr;
01870 expr = subst_expr;
01871 }
01872 }
01873 }
01874 else {
01875 Mutator<Expression> iter = expr->arg_list();
01876
01877 for ( ; iter.valid(); ++iter) {
01878 Assign<Expression> eas(iter.assign());
01879 Expression *new_expr
01880 = _remove_local_effects_from_expr1(iter.pull(),
01881 const_map,
01882 candidates);
01883
01884 if (! new_expr) {
01885 delete expr;
01886 return 0;
01887 }
01888 else
01889 eas = new_expr;
01890 }
01891 }
01892
01893 return expr;
01894 }
01895
01896 static Expression *
01897 _remove_local_effects_from_expr(Expression *expr,
01898 const PropConstMap &const_map,
01899 const Map<Symbol,IntElem> &candidates)
01900 {
01901 Expression *new_expr
01902 = _remove_local_effects_from_expr1(expr, const_map, candidates);
01903
01904 if (! new_expr)
01905 new_expr = omega();
01906
01907 return new_expr;
01908 }
01909
01910
01911
01912
01913
01914 static Map<Symbol, Expression> *
01915 _create_old_const_mods(const Map<Symbol,IntElem> &candidates,
01916 const PropConstMap &const_map,
01917 const RefSet<Symbol> &keepable_vars,
01918 const RefSet<Symbol> *modified_vars_ref)
01919 {
01920 Map<Symbol, Expression> *var_mods = new Map<Symbol, Expression>;
01921 KeyIterator<Symbol,IntElem> cand_iter = candidates;
01922
01923 for ( ; cand_iter.valid(); ++cand_iter) {
01924 Symbol &var = cand_iter.current_key();
01925
01926 if (keepable_vars.member(var)) {
01927 Expression *var_mod = _remove_local_effects_from_expr(id(var),
01928 const_map,
01929 candidates);
01930
01931 if ((var_mod->op() == ID_OP && &var_mod->symbol() == &var)
01932 || (var_mod->op() == OMEGA_OP
01933 && modified_vars_ref
01934 && ! modified_vars_ref->member(var)))
01935 delete var_mod;
01936 else
01937 var_mods->ins(var, var_mod);
01938 }
01939 }
01940
01941 return var_mods;
01942 }
01943
01944
01945
01946
01947
01948
01949 static Expression *
01950 _subst_unkeepable_vars(Expression *expr, const RefSet<Symbol> &keepable_vars)
01951 {
01952 if (! expr)
01953 return expr;
01954 else if (expr->op() == ID_OP) {
01955 if (expr->symbol().sym_class() == VARIABLE_CLASS) {
01956 Expression *subst_expr = 0;
01957
01958 if (expr->substituted_valid()) {
01959 subst_expr = _subst_unkeepable_vars(expr->grab_substituted(),
01960 keepable_vars);
01961
01962 if (subst_expr && subst_expr->base_variable_ref())
01963 subst_expr = paren(subst_expr);
01964 }
01965
01966 if (subst_expr || ! keepable_vars.member(expr->symbol())) {
01967 delete expr;
01968 return subst_expr;
01969 }
01970 }
01971 }
01972 else {
01973 Mutator<Expression> iter = expr->arg_list();
01974
01975 for ( ; iter.valid(); ++iter) {
01976 Assign<Expression> eas(iter.assign());
01977 Expression *new_arg = _subst_unkeepable_vars(iter.pull(),
01978 keepable_vars);
01979
01980 if (new_arg)
01981 eas = new_arg;
01982 else {
01983 delete expr;
01984 return 0;
01985 }
01986 }
01987 }
01988
01989 return expr;
01990 }
01991
01992
01993
01994
01995
01996 static Map<Symbol, Expression> *
01997 _create_new_consts(const Map<Symbol,IntElem> &candidates,
01998 const PropConstMap &const_map,
01999 const RefSet<Symbol> &keepable_vars)
02000 {
02001 Map<Symbol, Expression> *var_mods = new Map<Symbol, Expression>;
02002 KeyIterator<Symbol,IntElem> cand_iter = candidates;
02003
02004 for ( ; cand_iter.valid(); ++cand_iter) {
02005 Symbol &var = cand_iter.current_key();
02006
02007 if (keepable_vars.member(var)) {
02008 Expression *var_expr = _annotate_expr(id(var), const_map, candidates);
02009 Expression *new_const = var_expr->grab_substituted();
02010 delete var_expr;
02011 new_const = _subst_unkeepable_vars(new_const, keepable_vars);
02012
02013 if (new_const)
02014 var_mods->ins(var, new_const);
02015 }
02016 }
02017
02018 return var_mods;
02019 }
02020
02021
02022
02023
02024
02025 static const List<Expression> &
02026 _call_arg_list(const Statement &call_site)
02027 {
02028 const List<Expression> *args = NULL;
02029
02030 if (call_site.stmt_class() == CALL_STMT)
02031 args = &call_site.parameters_guarded().arg_list();
02032 else if (call_site.stmt_class() == ASSIGNMENT_STMT
02033 && call_site.rhs().op() == FUNCTION_CALL_OP)
02034 args = &call_site.rhs().parameters_guarded().arg_list();
02035 else
02036 p_abort("_call_arg_list(): Given statement is not a call statement or function call.");
02037
02038 return *args;
02039 }
02040
02041
02042
02043
02044
02045
02046 static Boolean
02047 _contains_non_candidate_vars(const Expression &expr,
02048 const Map<Symbol, IntElem> &candidates)
02049 {
02050 if (expr.op() == ID_OP) {
02051 return (expr.symbol().sym_class() == VARIABLE_CLASS
02052 && ! candidates.member(expr.symbol()));
02053 }
02054 else {
02055 Iterator<Expression> arg_iter = expr.arg_list();
02056
02057 for ( ; arg_iter.valid(); ++arg_iter)
02058 if (_contains_non_candidate_vars(arg_iter.current(), candidates))
02059 return True;
02060 }
02061
02062 return False;
02063 }
02064
02065
02066
02067
02068
02069 static List<Expression> *
02070 _create_new_actual_consts(const Map<Symbol, IntElem> &candidates,
02071 const Statement &stmt,
02072 const IPCPProcData & ,
02073 const IPCPProcData &call_proc_data,
02074 const RefSet<Symbol> &keepable_vars)
02075 {
02076 PropConstWS &ws = _get_workspace(stmt);
02077 const RefList<Symbol> &call_formals = call_proc_data.param_list();
02078 const List<Expression> &call_actuals = _call_arg_list(stmt);
02079
02080
02081
02082
02083 RefSet<Symbol> alias_consts;
02084 RefMap<Symbol, Symbol> alias_const_map;
02085 _alias_consts(alias_consts, alias_const_map,
02086 call_formals, call_actuals, keepable_vars);
02087 RefSet<Symbol> *my_keepable_vars = new RefSet<Symbol>(keepable_vars);
02088
02089 Iterator<Symbol> aconst_iter = alias_consts;
02090
02091 for ( ; aconst_iter.valid(); ++aconst_iter)
02092 my_keepable_vars->ins(aconst_iter.current());
02093
02094
02095
02096 List<Expression> *actuals = new List<Expression>;
02097
02098 p_assert(call_formals.entries() == call_actuals.entries(),
02099 "JumpFunction::new_values(): The number of formals does not equal the number of actuals.");
02100 Iterator<Symbol> formal_iter = call_formals;
02101 Iterator<Expression> actual_iter = call_actuals;
02102
02103 for ( ; formal_iter.valid(); ++formal_iter, ++actual_iter) {
02104 const Symbol &formal = formal_iter.current();
02105 Expression *actual_expr = actual_iter.current().clone();
02106
02107 if (_contains_non_candidate_vars(*actual_expr, candidates)) {
02108 delete actual_expr;
02109 actual_expr = omega();
02110 }
02111 else {
02112 actual_expr = _annotate_expr(actual_expr, ws.in_const_map,
02113 candidates);
02114 actual_expr = _subst_unkeepable_vars(actual_expr, *my_keepable_vars);
02115
02116 if (actual_expr) {
02117 _rename_alias_consts(*actual_expr, alias_const_map);
02118
02119 if (actual_expr->base_variable_ref() == &formal) {
02120 delete actual_expr;
02121 actual_expr = omega();
02122 }
02123 }
02124 else
02125 actual_expr = omega();
02126 }
02127
02128 actuals->ins_last(actual_expr);
02129 }
02130
02131 delete my_keepable_vars;
02132 return actuals;
02133 }
02134
02135
02136
02137
02138
02139 static void
02140 _build_call_jump_functions(ProgramUnit &pgm, IPCPProcData &proc_data,
02141 const Map<Symbol, IntElem> &candidates,
02142 const RefSet<Symbol> *modified_vars_ref)
02143 {
02144 RefSet<Symbol> keepable_params;
02145
02146 Iterator<Expression> param_iter = proc_data.entry().parameters_guarded().arg_list();
02147
02148 for ( ; param_iter.valid(); ++param_iter)
02149 keepable_params.ins(param_iter.current().symbol());
02150
02151 Iterator<Statement> stmt_iter = pgm.stmts().iterator();
02152
02153 for ( ; stmt_iter.valid(); ++stmt_iter) {
02154 const Statement &stmt = stmt_iter.current();
02155
02156 if (stmt.stmt_class() == CALL_STMT
02157 || (stmt.stmt_class() == ASSIGNMENT_STMT
02158 && stmt.rhs().op() == FUNCTION_CALL_OP)) {
02159 PropConstWS &ws = _get_workspace(stmt);
02160
02161 if (ws.num_visits() > 0) {
02162 const IPCPCallData *c_data = proc_data.call_data(stmt);
02163
02164 if (c_data && c_data->data_ref()) {
02165 const IPCPProcData &call_proc_data = *c_data->data_ref();
02166 RefSet<Symbol> *keepable_vars
02167 = proc_data.local_vars(call_proc_data.usable_global_vars());
02168 *keepable_vars += keepable_params;
02169 proc_data.create_jump_function(
02170 stmt,
02171 _create_old_const_mods(candidates, ws.in_const_map,
02172 *keepable_vars,
02173 modified_vars_ref),
02174 _create_new_consts(candidates, ws.in_const_map,
02175 *keepable_vars),
02176 _create_new_actual_consts(candidates, stmt, proc_data,
02177 call_proc_data,
02178 *keepable_vars));
02179 delete keepable_vars;
02180 }
02181 }
02182 }
02183 }
02184 }
02185
02186
02187
02188
02189
02190
02191 static void
02192 _ipcp_compute_constants(ProgramUnit &pgm, IPCPProcData &proc_data,
02193 const Map<Symbol,IntElem> &def_candidates,
02194 const Map<Symbol,IntElem> &use_candidates,
02195 Array<Symbol *> &tag_to_candidate,
02196 const Map<Symbol, Expression> &entering_constants)
02197 {
02198
02199 RefSet<Statement> entry_points;
02200
02201
02202 Array<Statement *> toporder_to_stmt;
02203
02204 StmtList &stmts = pgm.stmts();
02205 const Statement &first_stmt = *stmts.first_ref();
02206 const Statement &last_stmt = *stmts.last_ref();
02207 Timer timer;
02208
02209 _pass_tag = create_pass_tag();
02210 _init_ipcp_workspaces(stmts, proc_data, def_candidates, use_candidates,
02211 tag_to_candidate);
02212 _make_nonlocals_modified_at_calls(stmts, first_stmt, last_stmt,
02213 use_candidates, tag_to_candidate);
02214 _patch_flow_graph(stmts, first_stmt, last_stmt);
02215 _determine_entry_points(stmts, first_stmt, last_stmt, entry_points);
02216 _calc_toporder(stmts, first_stmt, last_stmt, entry_points,
02217 toporder_to_stmt);
02218
02219 if (_debug_level > 0) {
02220 cout << "! Initialization: " << timer << endl;
02221 timer.reset();
02222 }
02223
02224
02225
02226
02227 _iterate_to_fixed_point(stmts, first_stmt, last_stmt, entry_points,
02228 toporder_to_stmt, use_candidates,
02229 tag_to_candidate, entering_constants);
02230
02231 if (_debug_level > 0) {
02232 cout << "! Iterating to fixed point: " << timer << endl;
02233 timer.reset();
02234 }
02235
02236 if (_debug_level >= 10)
02237 _dump_workspaces(cout, stmts, first_stmt, last_stmt);
02238 }
02239
02240
02241
02242
02243
02244 void
02245 _ipcp_build_jump_functions(ProgramUnit &pgm, IPCPProcData &proc_data,
02246 const RefSet<Symbol> &def_vars,
02247 const RefSet<Symbol> &use_vars,
02248 const Map<Symbol, Expression> &entering_constants,
02249 int debug GIV(0))
02250 {
02251
02252 Map<Symbol,IntElem> def_candidates;
02253
02254
02255
02256 Map<Symbol,IntElem> use_candidates;
02257
02258
02259 Array<Symbol *> tag_to_candidate;
02260
02261
02262
02263 RefSet<Statement> pseudo_stmts;
02264
02265 StmtList &stmts = pgm.stmts();
02266 const Statement &first_stmt = *stmts.first_ref();
02267 const Statement &last_stmt = *stmts.last_ref();
02268
02269 _debug_level = debug;
02270 Timer tot_timer;
02271 Timer timer;
02272
02273
02274
02275 _add_control_assigns(pgm.stmts(), first_stmt, last_stmt, 0, pseudo_stmts);
02276 _init_candidates(def_vars, use_vars, def_candidates, use_candidates,
02277 tag_to_candidate);
02278
02279
02280
02281 _ipcp_compute_constants(pgm, proc_data, def_candidates, use_candidates,
02282 tag_to_candidate, entering_constants);
02283
02284
02285
02286
02287
02288 RefSet<Symbol> *modified_vars = 0;
02289
02290 if (pseudo_stmts.entries() > 0)
02291 modified_vars = _build_modified_vars(pgm.stmts(), pseudo_stmts,
02292 tag_to_candidate);
02293
02294
02295
02296 _build_call_jump_functions(pgm, proc_data, use_candidates,
02297 modified_vars);
02298
02299 p_assert(last_stmt.stmt_class() == FLOW_EXIT_STMT,
02300 "Last statement of program is not a flow-exit statement.");
02301 PropConstWS &flow_exit_ws = _get_workspace(last_stmt);
02302 RefSet<Symbol> *keepable_vars = proc_data.local_vars(proc_data.usable_global_vars());
02303 proc_data.create_return_jump_function(
02304 _create_old_const_mods(use_candidates, flow_exit_ws.in_const_map,
02305 *keepable_vars, modified_vars),
02306 _create_new_consts(use_candidates, flow_exit_ws.in_const_map,
02307 *keepable_vars));
02308 delete keepable_vars;
02309
02310 if (modified_vars)
02311 delete modified_vars;
02312
02313 if (_debug_level > 0) {
02314 cout << "! Building jump functions: " << timer << endl;
02315 timer.reset();
02316 }
02317
02318
02319
02320 pgm.stmts().del(pseudo_stmts);
02321
02322 if (_debug_level > 0) {
02323 cout << "! Removing pseudo-statements: " << timer << endl;
02324 timer.reset();
02325 }
02326
02327 Iterator<Statement> stmt_iter = stmts.iterator(first_stmt, last_stmt);
02328
02329 for ( ; stmt_iter.valid(); ++stmt_iter)
02330 stmt_iter.current().work_stack().pop(_pass_tag);
02331
02332 if (_debug_level > 0) {
02333 int num_stmts = _num_stmts_in_block(stmts, first_stmt, last_stmt);
02334
02335 cout << "! Total time: " << tot_timer << endl;
02336 cout << "! Number of statements: " << num_stmts << endl;
02337 cout << "! Number of candidate variables: " << use_candidates.entries() << endl;
02338 }
02339 }
02340
02341
02342
02343
02344
02345
02346 void
02347 _ipcp_propagate_constants(ProgramUnit &pgm, IPCPProcData &proc_data,
02348 const RefSet<Symbol> &def_vars,
02349 const RefSet<Symbol> &use_vars,
02350 PC_UNREACH_BOOL remove_unreachable,
02351 const Map<Symbol, Expression> &entering_constants,
02352 int debug GIV(0))
02353 {
02354
02355 Map<Symbol,IntElem> def_candidates;
02356
02357
02358
02359 Map<Symbol,IntElem> use_candidates;
02360
02361
02362 Array<Symbol *> tag_to_candidate;
02363
02364
02365
02366 RefSet<Statement> pseudo_stmts;
02367
02368 StmtList &stmts = pgm.stmts();
02369 const Statement &first_stmt = *stmts.first_ref();
02370 const Statement &last_stmt = *stmts.last_ref();
02371
02372 _debug_level = debug;
02373 Timer tot_timer;
02374 Timer timer;
02375
02376
02377
02378 _add_control_assigns(pgm.stmts(), first_stmt, last_stmt, 0, pseudo_stmts);
02379 _init_candidates(def_vars, use_vars, def_candidates, use_candidates,
02380 tag_to_candidate);
02381
02382
02383
02384 _ipcp_compute_constants(pgm, proc_data, def_candidates, use_candidates,
02385 tag_to_candidate, entering_constants);
02386
02387
02388
02389
02390 _annotate_stmts(stmts, first_stmt, last_stmt, use_candidates);
02391
02392 if (_debug_level > 0)
02393 cout << "! Annotating pgm with constants: " << timer << endl;
02394
02395
02396
02397 pgm.stmts().del(pseudo_stmts);
02398
02399 if (remove_unreachable == REMOVE_UNREACH_CODE)
02400 _remove_unreachable(stmts, first_stmt, last_stmt, use_candidates);
02401
02402 if (_debug_level > 0) {
02403 cout << "! Removing unreachable code: " << timer << endl;
02404 timer.reset();
02405 }
02406
02407
02408
02409 Iterator<Statement> stmt_iter = stmts.iterator(first_stmt, last_stmt);
02410
02411 for ( ; stmt_iter.valid(); ++stmt_iter)
02412 stmt_iter.current().work_stack().pop(_pass_tag);
02413
02414 if (_debug_level > 0) {
02415 int num_stmts = _num_stmts_in_block(stmts, first_stmt, last_stmt);
02416
02417 cout << "! Total time: " << tot_timer << endl;
02418 cout << "! Number of statements: " << num_stmts << endl;
02419 cout << "! Number of candidate variables: " << use_candidates.entries() << endl;
02420 }
02421 }
02422
02423
02424
02425
02426
02427
02428 static void
02429 _assert_clear_substituted(Statement &stmt)
02430 {
02431 Iterator<Assertion> ass_iter = stmt.assertions();
02432
02433 for ( ; ass_iter.valid(); ++ass_iter) {
02434 if (ass_iter.current().arg_list_valid()) {
02435 Mutator<Expression> aexpr_iter
02436 = ass_iter.current().arg_list_guarded();
02437
02438 for ( ; aexpr_iter.valid(); ++aexpr_iter)
02439 clear_substituted(aexpr_iter.current());
02440 }
02441 }
02442 }
02443
02444
02445
02446
02447
02448
02449
02450 void
02451 clear_substituted(ProgramUnit &pgm)
02452 {
02453 if (pgm.stmts().entries())
02454 clear_substituted(pgm.stmts(), *pgm.stmts().first_ref(),
02455 *pgm.stmts().last_ref());
02456 }
02457
02458 void
02459 clear_substituted(StmtList &stmts, const Statement &first_stmt,
02460 const Statement &last_stmt)
02461 {
02462 Iterator<Statement> iter = stmts.iterator(first_stmt, last_stmt);
02463
02464 for ( ; iter.valid(); ++iter)
02465 clear_substituted(iter.current());
02466 }
02467
02468 void
02469 clear_substituted(Statement &stmt)
02470 {
02471 Iterator<Expression> iter = stmt.iterate_expressions();
02472
02473 for ( ; iter.valid(); ++iter)
02474 clear_substituted(iter.current());
02475
02476 _assert_clear_substituted(stmt);
02477 }
02478
02479 void
02480 clear_substituted(Expression &expr)
02481 {
02482 if (expr.op() == ID_OP)
02483 expr.substituted(0);
02484 else {
02485 Iterator<Expression> iter = expr.arg_list();
02486
02487 for ( ; iter.valid(); ++iter)
02488 clear_substituted(iter.current());
02489
02490 }
02491 }
02492
02493 extern "C" int
02494 clear_substituted_pu(char **data, int *len)
02495 {
02496 P_ASSERT_HANDLER(0);
02497 external_interface_init();
02498
02499 ProgramUnit *pgm = external_program_unit( data, len );
02500 p_assert( pgm, "not a program unit" );
02501
02502 clear_substituted(*pgm);
02503
02504 return setup_to_return_handle( pgm->pu_tag_ref(), data, len);
02505 }
02506
02507
02508
02509
02510
02511 Boolean
02512 substituted_var()
02513 {
02514 return _substituted_var;
02515 }
02516
02517
02518
02519
02520
02521 void
02522 clear_substituted_var()
02523 {
02524 _substituted_var = False;
02525 }
02526
02527
02528
02529
02530
02531
02532
02533
02534 static void
02535 _assert_expand_substituted(Statement &stmt,
02536 Boolean (* expr_filter)(const Expression &),
02537 Boolean (* const_filter)(const Expression &))
02538 {
02539 Iterator<Assertion> ass_iter = stmt.assertions();
02540
02541 for ( ; ass_iter.valid(); ++ass_iter) {
02542
02543
02544
02545 if ((ass_iter.current().type() == AS_INDUCTION) ||
02546 (ass_iter.current().type() == AS_FIRSTVALUE) ||
02547 (ass_iter.current().type() == AS_RANGEWRITTEN)) continue;
02548
02549 if (ass_iter.current().arg_list_valid()) {
02550 Mutator<Expression> aexpr_iter
02551 = ass_iter.current().arg_list_guarded();
02552
02553 for ( ; aexpr_iter.valid(); ++aexpr_iter) {
02554 Assign<Expression> eas(aexpr_iter.assign());
02555 eas = expr_expand_substituted(aexpr_iter.pull(),
02556 expr_filter, const_filter);
02557 }
02558 }
02559 }
02560 }
02561
02562
02563
02564
02565
02566
02567
02568
02569 static void
02570 _call_args_expand_substituted(Expression &comma_expr,
02571 Boolean (* expr_filter)(const Expression &),
02572 Boolean (* const_filter)(const Expression &))
02573 {
02574 p_assert(comma_expr.op() == COMMA_OP,
02575 "Parameters to subroutine or function call is not a comma expression.");
02576 Mutator<Expression> arg_iter = comma_expr.arg_list();
02577
02578 for ( ; arg_iter.valid(); ++arg_iter)
02579 if (arg_iter.current().op() == ID_OP)
02580 arg_iter.current().substituted(0);
02581 else {
02582 Assign<Expression> eas(arg_iter.assign());
02583 eas = expr_expand_substituted(arg_iter.pull(),
02584 expr_filter,
02585 const_filter);
02586 }
02587 }
02588
02589
02590
02591
02592
02593
02594
02595
02596
02597
02598
02599
02600
02601 void
02602 expand_substituted(ProgramUnit &pgm,
02603 Boolean (* expr_filter)(const Expression &) GIV(0),
02604 Boolean (* const_filter)(const Expression &) GIV(0))
02605 {
02606 if (pgm.stmts().entries())
02607 expand_substituted(pgm.stmts(), *pgm.stmts().first_ref(),
02608 *pgm.stmts().last_ref(), expr_filter, const_filter);
02609 }
02610
02611 void
02612 expand_substituted(StmtList &stmts, const Statement &first_stmt,
02613 const Statement &last_stmt,
02614 Boolean (* expr_filter)(const Expression &) GIV(0),
02615 Boolean (* const_filter)(const Expression &) GIV(0))
02616 {
02617 Iterator<Statement> iter = stmts.iterator(first_stmt, last_stmt);
02618
02619 for ( ; iter.valid(); ++iter)
02620 expand_substituted(iter.current(), expr_filter, const_filter);
02621 }
02622
02623 void
02624 expand_substituted(Statement &stmt,
02625 Boolean (* expr_filter)(const Expression &) GIV(0),
02626 Boolean (* const_filter)(const Expression &) GIV(0))
02627 {
02628 _assert_expand_substituted(stmt, expr_filter, const_filter);
02629
02630 _stmt_substituted_var = False;
02631
02632 if (stmt.stmt_class() == CALL_STMT) {
02633 if (stmt.parameters_valid())
02634 _call_args_expand_substituted(stmt.parameters_guarded(),
02635 expr_filter, const_filter);
02636 }
02637 else {
02638 Mutator<Expression> iter = stmt.iterate_expressions();
02639
02640 for ( ; iter.valid(); ++iter) {
02641 Assign<Expression> eas(iter.assign());
02642 eas = simplify(expr_expand_substituted(iter.pull(), expr_filter,
02643 const_filter));
02644
02645 }
02646 }
02647
02648 if (_stmt_substituted_var)
02649 stmt.build_refs();
02650
02651 stmt.simplify_expressions();
02652 }
02653
02654 extern "C" int
02655 expand_substituted_pu(char **data, int *len)
02656 {
02657 P_ASSERT_HANDLER(0);
02658 external_interface_init();
02659
02660 ProgramUnit *pgm = external_program_unit( data, len );
02661 p_assert( pgm, "not a program unit" );
02662
02663 expand_substituted(*pgm);
02664
02665 return setup_to_return_handle( pgm->pu_tag_ref(), data, len);
02666 }
02667
02668
02669
02670
02671
02672
02673 static Boolean
02674 _is_constant_expr(const Expression &expr)
02675 {
02676 if (expr.arg_list().entries() == 0)
02677 return (expr.op() == INTEGER_CONSTANT_OP
02678 || expr.op() == LOGICAL_CONSTANT_OP);
02679 else if (expr.op() == INTRINSIC_CALL_OP)
02680 return _is_constant_expr(expr.parameters_guarded());
02681 else {
02682 Iterator<Expression> iter = expr.arg_list();
02683
02684 for ( ; iter.valid(); ++iter)
02685 if (! _is_constant_expr(iter.current()))
02686 return False;
02687 }
02688
02689 return True;
02690 }
02691
02692
02693
02694
02695
02696
02697
02698 Expression *
02699 expr_expand_substituted(Expression *expr,
02700 Boolean (* expr_filter)(const Expression &) GIV(0),
02701 Boolean (* const_filter)(const Expression &) GIV(0))
02702 {
02703 if (! expr)
02704 return expr;
02705
02706 Expression *result = expr;
02707
02708 if (! expr_filter || expr_filter(*expr)) {
02709 if (expr->op() == ID_OP) {
02710
02711 if (expr->substituted_valid()) {
02712 expr->substituted(expr_expand_substituted(expr->grab_substituted(),
02713 expr_filter,
02714 const_filter));
02715
02716 if (_is_constant_expr(expr->substituted_guarded()))
02717 expr->substituted(simplify(expr->grab_substituted()));
02718
02719 if (! const_filter
02720 || const_filter(expr->substituted_guarded())) {
02721
02722 result = expr->grab_substituted();
02723 delete expr;
02724 _substituted_var = True;
02725 _stmt_substituted_var = True;
02726 }
02727 }
02728 }
02729 else if (expr->op() == FUNCTION_CALL_OP) {
02730 if (expr->parameters_valid())
02731 _call_args_expand_substituted(expr->parameters_guarded(),
02732 expr_filter, const_filter);
02733 }
02734 else {
02735 Mutator<Expression> iter = expr->arg_list();
02736
02737 for ( ; iter.valid(); ++iter) {
02738 Assign<Expression> eas(iter.assign());
02739 eas = expr_expand_substituted(iter.pull(),
02740 expr_filter,
02741 const_filter);
02742 }
02743 }
02744 }
02745
02746 return result;
02747 }
02748
02749
02750
02751
02752
02753
02754
02755 static inline Boolean
02756 _is_expr_top_linear(const Expression &expr)
02757 {
02758 switch(expr.op()) {
02759
02760 case INTEGER_CONSTANT_OP:
02761 case REAL_CONSTANT_OP:
02762 case HOLLERITH_CONSTANT_OP:
02763 case LOGICAL_CONSTANT_OP:
02764 case COMPLEX_OP:
02765 case ARRAY_REF_OP:
02766 case ID_OP:
02767 case OMEGA_OP:
02768
02769 case NOT_OP:
02770 case EQ_OP:
02771 case NE_OP:
02772 case LT_OP:
02773 case LE_OP:
02774 case GT_OP:
02775 case GE_OP:
02776 case OR_OP:
02777 case AND_OP:
02778 case EQV_OP:
02779 case NEQV_OP:
02780
02781 case U_PLUS_OP:
02782 case U_MINUS_OP:
02783 case PAREN_OP:
02784 case SUB_OP:
02785 case ADD_OP:
02786 case MULT_OP:
02787 case COMMA_OP:
02788 return True;
02789 default:
02790 return False;
02791 }
02792
02793 return False;
02794 }
02795
02796 static Boolean
02797 _linear_const_filter(const Expression &expr)
02798 {
02799 if (! _is_expr_top_linear(expr))
02800 return False;
02801 else {
02802 Iterator<Expression> iter = expr.arg_list();
02803
02804 for ( ; iter.valid(); ++iter)
02805 if (! _linear_const_filter(iter.current()))
02806 return False;
02807 }
02808
02809 return True;
02810 }
02811
02812 void
02813 expand_linear_substituted(ProgramUnit &pgm)
02814 {
02815 expand_substituted(pgm, &_is_expr_top_linear, &_linear_const_filter);
02816 }
02817
02818 void
02819 expand_linear_substituted(StmtList &stmts, const Statement &first_stmt,
02820 const Statement &last_stmt)
02821 {
02822 expand_substituted(stmts, first_stmt, last_stmt,
02823 &_is_expr_top_linear, &_linear_const_filter);
02824 }
02825
02826 void
02827 expand_linear_substituted(Statement &stmt)
02828 {
02829 expand_substituted(stmt, &_is_expr_top_linear, &_linear_const_filter);
02830 }
02831
02832 Expression *
02833 expr_expand_linear_substituted(Expression *expr)
02834 {
02835 return expr_expand_substituted(expr, &_is_expr_top_linear,
02836 &_linear_const_filter);
02837 }
02838
02839
02840
02841
02842
02843
02844 static Boolean
02845 _is_constant_expr_filter(const Expression &expr)
02846 {
02847 if (expr.op() == ID_OP)
02848 return (expr.substituted_valid()
02849 && _is_constant_expr_filter(expr.substituted_guarded()));
02850 else if (expr.arg_list().entries() == 0)
02851 return (expr.op() == INTEGER_CONSTANT_OP
02852 || expr.op() == LOGICAL_CONSTANT_OP);
02853 else if (expr.op() == INTRINSIC_CALL_OP)
02854 return _is_constant_expr_filter(expr.parameters_guarded());
02855 else {
02856 Iterator<Expression> iter = expr.arg_list();
02857
02858 for ( ; iter.valid(); ++iter)
02859 if (! _is_constant_expr_filter(iter.current()))
02860 return False;
02861 }
02862
02863 return True;
02864 }
02865
02866 static Boolean
02867 _small_const_filter(const Expression &expr)
02868 {
02869 return (expr.op() == ID_OP || _is_constant_expr_filter(expr));
02870 }
02871
02872 void
02873 expand_small_substituted(ProgramUnit &pgm)
02874 {
02875 expand_substituted(pgm, 0, &_small_const_filter);
02876 }
02877
02878 void
02879 expand_small_substituted(StmtList &stmts, const Statement &first_stmt,
02880 const Statement &last_stmt)
02881 {
02882 expand_substituted(stmts, first_stmt, last_stmt, 0, &_small_const_filter);
02883 }
02884
02885 void
02886 expand_small_substituted(Statement &stmt)
02887 {
02888 expand_substituted(stmt, 0, &_small_const_filter);
02889 }
02890
02891 Expression *
02892 expr_expand_small_substituted(Expression *expr)
02893 {
02894 return expr_expand_substituted(expr, 0, &_small_const_filter);
02895 }
02896
02897
02898
02899
02900
02901
02902 static Boolean
02903 _has_param_in_expr(const Expression &expr)
02904 {
02905 if (expr.op() == ID_OP) {
02906 return (expr.symbol().sym_class() == SYMBOLIC_CONSTANT_CLASS);
02907 }
02908 else {
02909 Iterator<Expression> iter = expr.arg_list();
02910
02911 for ( ; iter.valid(); ++iter)
02912 if (_has_param_in_expr(iter.current()))
02913 return True;
02914 }
02915
02916 return False;
02917 }
02918
02919
02920
02921
02922
02923
02924 static void
02925 _assert_substitute_parameters(Statement &stmt, PC_REAL_BOOL subst_reals)
02926 {
02927 Iterator<Assertion> ass_iter = stmt.assertions();
02928
02929 for ( ; ass_iter.valid(); ++ass_iter) {
02930 if (ass_iter.current().arg_list_valid()) {
02931 Mutator<Expression> aexpr_iter
02932 = ass_iter.current().arg_list_guarded();
02933
02934 for ( ; aexpr_iter.valid(); ++aexpr_iter) {
02935 Assign<Expression> eas(aexpr_iter.assign());
02936 eas = expr_substitute_parameters(aexpr_iter.pull(),
02937 subst_reals);
02938 }
02939 }
02940 }
02941 }
02942
02943 static void substitute_parameters_data(ProgramUnit &pgm,
02944 PC_REAL_BOOL subst_reals){
02945 for(Iterator<Data> dit=pgm.data(); dit.valid(); ++dit){
02946 Expression* values=dit.current().value_list().clone();
02947 values=expr_substitute_parameters(values, subst_reals);
02948 dit.current().value_list((CommaExpr*)values);
02949 }
02950 }
02951
02952
02953
02954
02955
02956 void
02957 substitute_parameters(ProgramUnit &pgm, PC_REAL_BOOL subst_reals)
02958 {
02959 substitute_parameters(pgm.symtab(), subst_reals);
02960
02961
02962 substitute_parameters_data(pgm, subst_reals);
02963
02964 if (pgm.stmts().entries())
02965 substitute_parameters(pgm.stmts(), *pgm.stmts().first_ref(),
02966 *pgm.stmts().last_ref(), subst_reals);
02967 }
02968
02969 void
02970 substitute_parameters(Symtab &symtab, PC_REAL_BOOL subst_reals)
02971 {
02972 DictionaryIter<Symbol> sym_iter = symtab.iterator();
02973
02974
02975
02976
02977 for ( ; sym_iter.valid(); ++sym_iter) {
02978 Symbol &symbol = sym_iter.current();
02979
02980 if (symbol.sym_class() == SYMBOLIC_CONSTANT_CLASS
02981 && _has_param_in_expr(*symbol.expr_ref())) {
02982
02983 Expression *new_expr
02984 = expr_substitute_parameters(symbol.expr_ref()->clone(),
02985 subst_reals);
02986 new_expr = simplify(new_expr);
02987 symbol.expr(new_expr);
02988 }
02989 }
02990
02991
02992
02993 for ( sym_iter.reset(); sym_iter.valid(); ++sym_iter)
02994 if (sym_iter.current().sym_class() == VARIABLE_CLASS) {
02995 Iterator<ArrayBounds> bound_iter = sym_iter.current().dim();
02996
02997 for ( ; bound_iter.valid(); ++bound_iter) {
02998 ArrayBounds &bound = bound_iter.current();
02999
03000 if (bound.lower_exists()
03001 && bound.lower_ref()->op() != INTEGER_CONSTANT_OP) {
03002
03003 Expression *new_lower
03004 = expr_substitute_parameters(bound.lower_ref()->clone(),
03005 subst_reals);
03006 new_lower = simplify(new_lower);
03007 bound.lower(new_lower);
03008 }
03009
03010 if (bound.upper_exists()
03011 && bound.upper_ref()->op() != INTEGER_CONSTANT_OP) {
03012
03013 Expression *new_upper
03014 = expr_substitute_parameters(bound.upper_ref()->clone(),
03015 subst_reals);
03016 new_upper = simplify(new_upper);
03017 bound.upper(new_upper);
03018 }
03019 }
03020 }
03021 }
03022
03023 void
03024 substitute_parameters(StmtList &stmts, const Statement &first_stmt,
03025 const Statement &last_stmt, PC_REAL_BOOL subst_reals)
03026 {
03027 Iterator<Statement> iter = stmts.iterator(first_stmt, last_stmt);
03028
03029 for ( ; iter.valid(); ++iter)
03030 substitute_parameters(iter.current(), subst_reals);
03031 }
03032
03033 void
03034 substitute_parameters(Statement &stmt, PC_REAL_BOOL subst_reals)
03035 {
03036 _assert_substitute_parameters(stmt, subst_reals);
03037 Mutator<Expression> iter = stmt.iterate_expressions();
03038 _stmt_substituted_var = False;
03039
03040 for ( ; iter.valid(); ++iter) {
03041 Assign<Expression> eas(iter.assign());
03042 eas = expr_substitute_parameters(iter.pull(), subst_reals);
03043 }
03044
03045 if (_stmt_substituted_var)
03046 stmt.build_refs();
03047 }
03048
03049
03050
03051
03052
03053
03054
03055 Expression *
03056 expr_substitute_parameters(Expression *expr, PC_REAL_BOOL subst_reals)
03057 {
03058 if (! expr)
03059 return 0;
03060
03061 Expression *result = expr;
03062
03063 if (expr->op() == ID_OP) {
03064 if (expr->symbol().sym_class() == SYMBOLIC_CONSTANT_CLASS
03065 && _substitutable_type(expr->symbol().type().data_type(),
03066 subst_reals)) {
03067 result = expr->symbol().expr_ref()->clone();
03068 delete expr;
03069 result = expr_substitute_parameters(result, subst_reals);
03070 _stmt_substituted_var = True;
03071 }
03072 else if (expr->substituted_valid())
03073 expr->substituted(expr_substitute_parameters(
03074 expr->grab_substituted(), subst_reals));
03075 }
03076 else {
03077 Mutator<Expression> iter = expr->arg_list();
03078
03079 for ( ; iter.valid(); ++iter) {
03080 Assign<Expression> eas(iter.assign());
03081 eas = expr_substitute_parameters(iter.pull(), subst_reals);
03082 }
03083 }
03084
03085 return result;
03086 }
03087
03088 extern "C" int
03089 substitute_parameters_pu(char **data, int *len)
03090 {
03091 P_ASSERT_HANDLER(0);
03092 external_interface_init();
03093
03094 ProgramUnit *pgm = external_program_unit( data, len );
03095 p_assert( pgm, "not a program unit" );
03096
03097 substitute_parameters(*pgm, (PC_REAL_BOOL) switch_value("sp_real"));
03098
03099 return setup_to_return_handle( pgm->pu_tag_ref(), data, len);
03100 }