00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083 #ifdef USE_PCH
00084 #include "opt_pch.h"
00085 #endif // USE_PCH
00086 #pragma hdrstop
00087
00088 #define __STDC_LIMIT_MACROS
00089 #include <stdint.h>
00090 #include <stack>
00091
00092 #include "defs.h"
00093 #include "erglob.h"
00094 #include "opcode.h"
00095 #include "errors.h"
00096 #include "mtypes.h"
00097 #include "cxx_memory.h"
00098 #include "wn_util.h"
00099 #include "targ_const.h"
00100 #include "const.h"
00101
00102 #include "opt_config.h"
00103 #include "opt_wn.h"
00104 #include "opt_util.h"
00105 #include "opt_cfg.h"
00106 #include "opt_htable.h"
00107 #include "opt_main.h"
00108 #include "opt_mu_chi.h"
00109 #include "opt_etable.h"
00110 #include "opt_lftr2.h"
00111 #include "opt_vn.h"
00112 #include "opt_vn_ivc.h"
00113
00114
00115
00116
00117 using std::stack;
00118
00119 static inline void dummy(...)
00120 {
00121 }
00122
00123 #ifdef DO_VNFRE_TRACE
00124 #define VNFRE_TRACE fprintf
00125 #else
00126 #define VNFRE_TRACE dummy
00127 #endif // VNFRE_TRACE
00128
00129
00130
00131
00132
00133 typedef mempool_allocator<EXP_WORKLST*> WORKLST_ALLOCATOR;
00134 typedef vector<EXP_WORKLST*, WORKLST_ALLOCATOR> VALNUM_TO_WORKLST;
00135
00136
00137
00138
00139 typedef mempool_allocator<EXP_OCCURS *> OCCURS_ALLOCATOR;
00140 typedef vector<EXP_OCCURS*, OCCURS_ALLOCATOR> OCCURS_VECTOR;
00141 typedef stack<EXP_OCCURS *, OCCURS_VECTOR> OCCURS_STACK;
00142
00143
00144
00145 typedef mempool_allocator<INT8> INT8_ALLOCATOR;
00146 typedef vector<INT8, INT8_ALLOCATOR> INT8_VECTOR;
00147
00148
00149
00150
00151
00152
00153 class Match_Cr
00154 {
00155 private:
00156 const CODEREP *_cr;
00157 public:
00158 Match_Cr(const CODEREP *cr): _cr(cr) {}
00159 BOOL operator () (const CODEREP *candidate_cr) const
00160 {
00161 return (candidate_cr == _cr);
00162 }
00163 };
00164
00165 class Match_Vn
00166 {
00167 private:
00168 VN *_vn;
00169 VN_VALNUM _valnum;
00170 public:
00171 Match_Vn(VN *vn, VN_VALNUM valnum): _vn(vn), _valnum(valnum) {}
00172 BOOL operator () (CODEREP *candidate_cr) const
00173 {
00174 return (_vn->expr_valnum(candidate_cr->Coderep_id()) == _valnum);
00175 }
00176 };
00177
00178 template <class Match_test>
00179 pair<INT32,CODEREP*> Count_occurs(CODEREP *cr,
00180 const Match_test &matches,
00181 BOOL is_store_lhs)
00182 {
00183
00184
00185
00186
00187
00188
00189
00190 INT32 counter = 0;
00191 CODEREP *occurs_cr = NULL;
00192 pair<INT32,CODEREP*> counted_occurs;
00193
00194
00195
00196
00197 switch (cr->Kind())
00198 {
00199 case CK_LDA:
00200 case CK_VAR:
00201 if (matches(cr) && !is_store_lhs)
00202 {
00203 counter = 1;
00204 occurs_cr = cr;
00205 }
00206 break;
00207
00208 case CK_CONST:
00209 case CK_RCONST:
00210
00211
00212
00213
00214 break;
00215
00216 case CK_IVAR:
00217 if (matches(cr) && cr->Opr() != OPR_PARM)
00218 {
00219 counter = 1;
00220 occurs_cr = cr;
00221 }
00222 else
00223 {
00224 CODEREP *size_cr =
00225 (is_store_lhs? cr->Mstore_size() : cr->Mload_size());
00226 if (cr->Opr() == OPR_ILOADX)
00227 size_cr = cr->Index();
00228 CODEREP *base_cr =
00229 (is_store_lhs? cr->Istr_base() : cr->Ilod_base());
00230
00231 if (cr->Opr() == OPR_MLOAD || cr->Opr() == OPR_ILOADX)
00232 {
00233 counted_occurs = Count_occurs(size_cr, matches, FALSE);
00234 counter = counted_occurs.first;
00235 occurs_cr = counted_occurs.second;
00236 }
00237 counted_occurs = Count_occurs(base_cr, matches, FALSE);
00238 counter += counted_occurs.first;
00239 if (occurs_cr == NULL)
00240 occurs_cr = counted_occurs.second;
00241 }
00242 break;
00243
00244 case CK_OP:
00245 Is_True(cr->Opr() != OPR_ARRAY,
00246 ("Count_occurs: found an OPR_ARRAY node; should be lowered"));
00247
00248 if (matches(cr) &&
00249 cr->Opr() != OPR_PARM &&
00250 !OPERATOR_is_volatile(cr->Opr()))
00251 {
00252 counter = 1;
00253 occurs_cr = cr;
00254 }
00255 else
00256 {
00257 for (INT32 i=0; i<cr->Kid_count(); i++)
00258 {
00259 counted_occurs = Count_occurs(cr->Opnd(i), matches, FALSE);
00260 counter += counted_occurs.first;
00261 if (occurs_cr == NULL)
00262 occurs_cr = counted_occurs.second;
00263 }
00264 }
00265 break;
00266
00267 default:
00268 Is_True(FALSE, ("Count_occurs: bad coderep kind"));
00269 break;
00270 }
00271 return pair<INT32,CODEREP*>(counter,occurs_cr);
00272 }
00273
00274
00275
00276
00277
00278
00279 class VALNUM_FRE
00280 {
00281 private:
00282
00283 static VALNUM_FRE *_current;
00284 ETABLE *_etable;
00285 COMP_UNIT *_comp_unit;
00286 MEM_POOL *_lpool;
00287 MEM_POOL *_vpool;
00288 MEM_POOL *_gpool;
00289 BOOL _tracing;
00290
00291 VN *_vn;
00292 VALNUM_TO_EXPR_LIST *_vn_to_exprid;
00293 VALNUM_TO_WORKLST _vn_to_worklst;
00294 VN::BIT_VECTOR _vn_removed;
00295 VN::BIT_VECTOR _cr_removed;
00296 VN::BIT_VECTOR _do_fre;
00297 EXP_OCCURS_CONTAINER _exit_occurs;
00298
00299
00300
00301 INT32 _phi_placement_phase;
00302 INT32 _valnum_renaming_phase;
00303 INT32 _avail_insert_phase;
00304 INT32 _finalize_phase;
00305 INT32 _codemotion_phase;
00306 INT32 _ssa_min_phase;
00307 INT32 _worklst_prune_phase;
00308 INT32 _vnfre_misc_phase;
00309 INT32 _vnfre_delete_occurs_phase;
00310 INT32 _vnfre_ivc_phase;
00311
00312
00313
00314 typedef EXP_WORKLST * EXP_WORKLST_REF;
00315
00316 BOOL _user_enabled(VN_VALNUM v)
00317 {
00318 return (v.ordinal() > WOPT_Enable_Vnfre_After &&
00319 v.ordinal() < WOPT_Enable_Vnfre_Before);
00320 }
00321
00322 EXP_WORKLST_REF &_worklst(VN_VALNUM v)
00323 {
00324 Is_True(v.ordinal() < _vn_to_worklst.size(),
00325 ("Out of range access VALNUM_FRE::_worklst: (%d > %d)",
00326 v.ordinal(), _vn_to_worklst.size()));
00327 return _vn_to_worklst[v.ordinal()];
00328 }
00329
00330 const EXP_WORKLST_REF &_worklst(VN_VALNUM v) const
00331 {
00332 Is_True(v.ordinal() < _vn_to_worklst.size(),
00333 ("Out of range access VALNUM_FRE::_worklst: (%d > %d)",
00334 v.ordinal(), _do_fre.size()));
00335 return _vn_to_worklst[v.ordinal()];
00336 }
00337
00338 BOOL _cr_maybe_removed(VN::EXPRID id)
00339 {
00340 if (id < _cr_removed.size())
00341 return BOOL(_cr_removed[id]);
00342 else
00343 return FALSE;
00344 }
00345
00346 void _set_cr_maybe_removed(VN::EXPRID id, BOOL maybe_removed)
00347 {
00348 if (id >= _cr_removed.size())
00349 _grow_exprid_maps(id);
00350 _cr_removed[id] = bool(maybe_removed);
00351 }
00352
00353 BOOL _vn_maybe_removed(VN_VALNUM v)
00354 {
00355 Is_True(v.ordinal() < _vn_removed.size(),
00356 ("Out of range access VALNUM_FRE::_vn_maybe_removed: (%d > %d)",
00357 v.ordinal(), _vn_removed.size()));
00358 return BOOL(_vn_removed[v.ordinal()]);
00359 }
00360
00361 void _set_vn_maybe_removed(VN_VALNUM v, BOOL maybe_removed)
00362 {
00363 Is_True(v.ordinal() < _vn_removed.size(),
00364 ("Out of range VALNUM_FRE::_set_vn_maybe_removed: (%d > %d)",
00365 v.ordinal(), _vn_removed.size()));
00366 _vn_removed[v.ordinal()] = bool(maybe_removed);
00367 }
00368
00369 BOOL _do_vnfre(VN_VALNUM v) const
00370 {
00371 Is_True(v.ordinal() < _do_fre.size(),
00372 ("Out of range access VALNUM_FRE::_do_vnfre: (%d > %d)",
00373 v.ordinal(), _do_fre.size()));
00374 return BOOL(_do_fre[v.ordinal()]);
00375 }
00376
00377 void _set_do_vnfre(VN_VALNUM v, BOOL doit)
00378 {
00379 Is_True(v.ordinal() < _do_fre.size(),
00380 ("Out of range access VALNUM_FRE::_do_vnfre: (%d > %d)",
00381 v.ordinal(), _do_fre.size()));
00382 _do_fre[v.ordinal()] = bool(doit);
00383 }
00384
00385
00386 BOOL _is_dedicated_preg(CODEREP *cr)
00387 {
00388 Is_True(cr->Kind() == CK_VAR,
00389 ("Expected CK_VAR in VALNUM_FRE::_is_dedicated_preg"));
00390
00391 return (_etable->Opt_stab()->
00392 Aux_stab_entry(cr->Aux_id())->Is_dedicated_preg());
00393 }
00394
00395 BOOL _is_real_var(CODEREP *cr)
00396 {
00397 Is_True(cr->Kind() == CK_VAR,
00398 ("Expected CK_VAR in VALNUM_FRE::_is_real_var"));
00399
00400 return (_etable->Opt_stab()->
00401 Aux_stab_entry(cr->Aux_id())->Is_real_var());
00402 }
00403
00404 EXP_OCCURS *_first_real_occur(EXP_WORKLST *w) const
00405 {
00406 return w->Real_occurs().Head();
00407 }
00408
00409 EXP_OCCURS *_last_real_occur(EXP_WORKLST *w) const
00410 {
00411 return w->Real_occurs().Tail();
00412 }
00413
00414 BOOL _has_an_occur(EXP_WORKLST *w) const
00415 {
00416 return w != NULL && _first_real_occur(w) != NULL;
00417 }
00418
00419 BOOL _num_occurs(EXP_WORKLST *w) const
00420 {
00421 INT32 i = 0;
00422 EXP_OCCURS * occ;
00423 EXP_OCCURS_ITER occ_iter;
00424 FOR_ALL_NODE(occ, occ_iter, Init(_first_real_occur(w)))
00425 {
00426 i += (occ->Mult_real()? 2 : 1);
00427 }
00428 return i;
00429 }
00430
00431 BOOL _is_fully_avail(EXP_PHI *value_phi) const
00432 {
00433 return !value_phi->Not_user_avail();
00434 }
00435
00436 EXP_OCCURS *_def_occur(EXP_OCCURS *occ) const
00437 {
00438
00439
00440
00441 return (occ->Occ_kind() == EXP_OCCURS::OCC_REAL_OCCUR?
00442 occ->Def_occur() : NULL);
00443 }
00444
00445 CODEREP * _get_occur_cr(const EXP_OCCURS *occur) const;
00446
00447
00448
00449 void _trace_header();
00450
00451
00452
00453 void _grow_exprid_maps(VN::EXPRID id);
00454 void _grow_valnum_maps(VN_VALNUM v);
00455
00456
00457
00458 BOOL _disabled_expr(const VN_EXPR::CONST_PTR vexpr) const;
00459 BOOL _has_valid_stmtrep_occurrence(VN_VALNUM v);
00460 BOOL _may_be_redundant_expr(VN_VALNUM v, VN_EXPR::CONST_PTR vexpr);
00461 void _select_for_valnum_list(VN_VALNUM v,
00462 VN::BIT_VECTOR &visited,
00463 VN::VALNUM_VECTOR &valnum_list);
00464 void _select_and_sort_valnums(VN::VALNUM_VECTOR &valnum_list);
00465
00466
00467
00468
00469 BOOL _contains_undef_val(CODEREP *cr, STMTREP *stmt) const;
00470 BOOL _subsumable_by_branch(VN_VALNUM valnum,
00471 STMTREP *stmt,
00472 CODEREP *cr) const;
00473
00474 EXP_OCCURS *_create_real_occurrence(CODEREP *cr,
00475 STMTREP *stmt,
00476 INT stmt_kid_num,
00477 UINT depth);
00478
00479 EXP_OCCURS *_copy_real_occurrence(EXP_OCCURS *occ)
00480 {
00481 return _create_real_occurrence(occ->Occurrence(),
00482 occ->Enclosed_in_stmt(),
00483 occ->Stmt_kid_num(),
00484 occ->Rehash_cost());
00485 }
00486
00487 void _append_real_occurrence(CODEREP *cr,
00488 STMTREP *stmt,
00489 INT stmt_kid_num,
00490 UINT depth);
00491
00492 void _append_exit_occurrence(BB_NODE *bb);
00493
00494 void _insert_a_cr_occurrence(CODEREP *cr,
00495 STMTREP *stmt,
00496 INT stmt_kid_num,
00497 UINT depth);
00498 void _collect_all_real_occurrences();
00499 void _verify_and_remove_occurs(EXP_WORKLST *worklist,
00500 VN_VALNUM valnum);
00501
00502
00503
00504 BOOL _all_same_occurs(CODEREP *cr,
00505 BOOL lhs_of_store,
00506 VN_VALNUM valnum,
00507 const CODEREP *occ_cr) const;
00508 BOOL _same_var_occurs(EXP_OCCURS *occ,
00509 const CODEREP *var_cr) const;
00510 void _get_worklist_info(EXP_WORKLST *w,
00511 BOOL &same_var_occurs,
00512 BOOL &save_use_occurs,
00513 BOOL &disabled_occurs) const;
00514 BOOL _is_vnfre_candidate(EXP_WORKLST *w) const;
00515
00516
00517
00518
00519 EXP_OCCURS *_append_phi_occurrence(EXP_PHI *phi,
00520 EXP_WORKLST *worklist);
00521 EXP_OCCURS *_append_phi_pred_occurrence(BB_NODE *bb,
00522 EXP_WORKLST *worklist);
00523 void _insert_valnum_phi(EXP_WORKLST *worklist);
00524
00525
00526
00527 pair<CODEREP*,STMTREP*> _save_to_temp(BB_NODE *in_bb,
00528 STMTREP *after_stmt,
00529 BOOL when_not_after_append,
00530 CODEREP *rhs);
00531 CODEREP* _ivc_insert_initval_diff(BB_NODE *init_bb,
00532 CODEREP *init_cr,
00533 CODEREP *base_cr);
00534 void _remove_ivc_incr_occurs(PHI_NODE *phi);
00535 void _ivc_substitute(BB_NODE *loop_header,
00536 STMTREP *base_stmt,
00537 CODEREP *base_cr,
00538 VN_IVC &vn_ivc,
00539 EQCLASS_MEMBER &base,
00540 EQCLASS_MEMBER &memb);
00541 void _ivc_classify(BB_NODE *loop_header, VN_IVC &vn_ivc);
00542 void _ivc_coalesce(BB_NODE *loop_header, VN_IVC &vn_ivc);
00543 void _ivc();
00544
00545
00546
00547
00548 void _create_new_version(EXP_OCCURS *occur,
00549 OCCURS_STACK &occurs_stack,
00550 EXP_WORKLST &worklist);
00551 void _rename_valnums(EXP_WORKLST &worklist, BOOL &renamed_ok);
00552
00553
00554
00555 void _propagate_flags(EXP_WORKLST &worklist, BOOL &found_redundancy);
00556
00557
00558
00559 void _remove_redundant_phi_nodes();
00560 void _substitute_literal(VN_VALNUM v);
00561 void _expression_redundancy_elimination(VN_VALNUM v);
00562
00563
00564
00565 void _remove_nested_occurs(const CODEREP *enclosing_cr,
00566 VN_VALNUM remove_valnum,
00567 BOOL is_istr_lhs,
00568 BOOL within_valnum);
00569
00570
00571
00572 BOOL _check_cr_compatible (VN_VALNUM valnum);
00573
00574 #ifdef KEY // bug 9114
00575 BOOL _ivc_loop_variant(BB_NODE *, VN_VALNUM);
00576 #endif
00577
00578 public:
00579
00580 static VALNUM_FRE *Current() {return _current;}
00581 static void Set_current(VALNUM_FRE *fre) {_current = fre;}
00582
00583
00584
00585 VALNUM_FRE(VN &vn, ETABLE &etable, COMP_UNIT *comp_unit):
00586 _etable(&etable),
00587 _comp_unit(comp_unit),
00588 _lpool(etable.Etable_local_pool()),
00589 _vpool(etable.Per_expr_pool()),
00590 _gpool(etable.Etable_pool()),
00591 _tracing(etable.Tracing()),
00592 _vn(&vn),
00593 _vn_to_exprid(NULL),
00594 _vn_to_worklst(vn.last_valnum().ordinal()+1,
00595 (EXP_WORKLST *) NULL,
00596 VALNUM_TO_WORKLST::allocator_type(_gpool)),
00597 _vn_removed(vn.last_valnum().ordinal()+1,
00598 bool(FALSE),
00599 VN::BVECTOR_ALLOCATOR(_gpool)),
00600 _cr_removed(comp_unit->Htable()->Coderep_id_cnt(),
00601 bool(FALSE),
00602 VN::BVECTOR_ALLOCATOR(_gpool)),
00603 _do_fre(vn.last_valnum().ordinal()+1,
00604 bool(FALSE),
00605 VN::BVECTOR_ALLOCATOR(_gpool)),
00606 _exit_occurs(),
00607 _phi_placement_phase(0),
00608 _valnum_renaming_phase(0),
00609 _avail_insert_phase(0),
00610 _finalize_phase(0),
00611 _codemotion_phase(0),
00612 _ssa_min_phase(0),
00613 _worklst_prune_phase(0),
00614 _vnfre_misc_phase(0),
00615 _vnfre_delete_occurs_phase(0),
00616 _vnfre_ivc_phase(0)
00617 {}
00618
00619
00620
00621 void apply();
00622
00623
00624
00625 VN::EXPRID last_exprid() const
00626 {
00627 return _vn->last_exprid();
00628 }
00629
00630 VN_VALNUM last_valnum() const
00631 {
00632 return _vn->last_valnum();
00633 }
00634
00635 VN_VALNUM get_valnum(VN::EXPRID id) const
00636 {
00637 return _vn->expr_valnum(id);
00638 }
00639
00640 EXP_WORKLST *get_worklst(VN_VALNUM valnum) const
00641 {
00642 return _worklst(valnum);
00643 }
00644
00645 INT32 num_real_occurs(VN_VALNUM valnum) const
00646 {
00647 return _num_occurs(get_worklst(valnum));
00648 }
00649
00650 VN_VALNUM compute_valnum(const CODEREP *cr)
00651 {
00652 VN_VALNUM v;
00653
00654 if (cr->Coderep_id() > last_exprid() ||
00655 get_valnum(cr->Coderep_id()).is_bottom())
00656 {
00657 v = _vn->invent_unique_valnum();
00658 _grow_valnum_maps(v);
00659 VNFRE::add_valnum(cr, v.ordinal());
00660 }
00661 else
00662 {
00663 v = get_valnum(cr->Coderep_id());
00664 }
00665 return v;
00666 }
00667
00668 void new_cr(const CODEREP *cr, VN_VALNUM valnum)
00669 {
00670
00671
00672
00673 Is_True(
00674 cr->Coderep_id() > last_exprid(),
00675 ("Illegal call to VALNUM_FRE::new_cr()"));
00676 _vn->new_cr(cr, valnum);
00677 }
00678
00679 void reset_valnum(const CODEREP *cr, VN_VALNUM valnum);
00680
00681 void replace_cr_in_stmt(const CODEREP *old_cr,
00682 CODEREP *new_cr,
00683 const STMTREP *stmt);
00684
00685 void move_rhs_occurs(const STMTREP *old_stmt,
00686 STMTREP *new_stmt);
00687
00688 void delete_all_occurs(const EXP_OCCURS *occur,
00689 const CODEREP *cr);
00690
00691 void insert_cr_occurrences(CODEREP *cr,
00692 STMTREP *stmt,
00693 INT stmt_kid_num,
00694 BOOL is_store,
00695 UINT depth);
00696 void collect_cr_occurrences(CODEREP *cr,
00697 STMTREP *stmt,
00698 INT stmt_kid_num,
00699 BOOL is_store,
00700 UINT depth);
00701
00702 };
00703
00704
00705
00706
00707
00708
00709 VALNUM_FRE *VALNUM_FRE::_current = NULL;
00710
00711
00712
00713
00714
00715 class INSERT_CR_OCCURS
00716 {
00717 VALNUM_FRE *_vnfre;
00718 public:
00719 INSERT_CR_OCCURS(VALNUM_FRE *vnfre) : _vnfre(vnfre) {}
00720 void operator () (CODEREP *cr, STMTREP *stmt, INT32 kidno)
00721 {
00722 _vnfre->insert_cr_occurrences(cr, stmt, kidno,
00723 (stmt->Lhs() == cr &&
00724 OPCODE_is_store(stmt->Op())),
00725 0);
00726 }
00727 };
00728
00729
00730 class COLLECT_CR_OCCURS
00731 {
00732 VALNUM_FRE *_vnfre;
00733 public:
00734 COLLECT_CR_OCCURS(VALNUM_FRE *vnfre) : _vnfre(vnfre) {}
00735 void operator () (CODEREP *cr, STMTREP *stmt, INT32 kidno)
00736 {
00737 _vnfre->collect_cr_occurrences(cr, stmt, kidno,
00738 (stmt->Lhs() == cr &&
00739 OPCODE_is_store(stmt->Op())),
00740 0);
00741 }
00742 };
00743
00744
00745 class GET_NUM_OCCURS
00746 {
00747 VALNUM_FRE *_vnfre;
00748 public:
00749 GET_NUM_OCCURS(VALNUM_FRE *vnfre) : _vnfre(vnfre) {}
00750 INT32 operator () (VN_VALNUM valnum)
00751 {
00752 return _vnfre->num_real_occurs(valnum);
00753 }
00754 };
00755
00756
00757
00758
00759
00760
00761 void
00762 VALNUM_FRE::apply(void)
00763 {
00764
00765
00766
00767
00768 _trace_header();
00769
00770 OPT_POOL_Push(_lpool, -1);
00771 {
00772 INT32 i;
00773
00774 SET_OPT_REPEAT_PHASE(_vnfre_misc_phase, "VNFRE: miscellaneous");
00775
00776
00777
00778
00779
00780
00781
00782 _remove_redundant_phi_nodes();
00783
00784
00785
00786
00787
00788
00789
00790
00791
00792
00793
00794
00795 VN::VALNUM_VECTOR valnum_list(0,
00796 VN_VALNUM::Bottom(),
00797 VN::VALNUM_VECTOR::allocator_type(_lpool));
00798 valnum_list.reserve(_vn->last_valnum().ordinal()+1);
00799 #ifdef KEY // bug 9114 : this code moved from inside _select_and_sort_valnums
00800 VALNUM_TO_EXPR_LIST vn_to_exprid(*_vn, _lpool);
00801 _vn_to_exprid = &vn_to_exprid;
00802 #endif
00803 _select_and_sort_valnums(valnum_list);
00804
00805
00806
00807
00808
00809
00810 _exit_occurs.Init();
00811 _collect_all_real_occurrences();
00812
00813
00814
00815
00816 VNFRE_TRACE(stderr, "Valnums considered = {");
00817 for (i = valnum_list.size() - 1; i >= 0; i--)
00818 {
00819 const VN_VALNUM v = valnum_list[i];
00820 const BOOL has_occ = _has_an_occur(_worklst(v));
00821
00822 VNFRE_TRACE(stderr, "%d[%c] ", v.ordinal(), (has_occ? 'y' : 'n'));
00823 _set_do_vnfre(v, has_occ);
00824 }
00825 VNFRE_TRACE(stderr, "}\n");
00826
00827
00828
00829
00830
00831 SET_OPT_REPEAT_PHASE(_vnfre_ivc_phase, "VNFRE: ivc");
00832 _ivc();
00833 #ifdef KEY // bug 9114 : this code moved from inside _select_and_sort_valnums
00834 _vn_to_exprid = NULL;
00835 #endif
00836 SET_OPT_REPEAT_PHASE(_vnfre_misc_phase, "VNFRE: miscellaneous");
00837
00838
00839
00840
00841 for (i = valnum_list.size() - 1; i >= 0; i--)
00842 {
00843 const VN_VALNUM valnum = valnum_list[i];
00844
00845
00846
00847 OPT_POOL_Push(_lpool, -1);
00848 OPT_POOL_Push(_vpool, -1);
00849
00850
00851
00852 if (_check_cr_compatible(valnum)) {
00853 _set_do_vnfre(valnum, FALSE);
00854 continue;
00855 }
00856 if (_do_vnfre(valnum))
00857 {
00858 EXP_WORKLST *worklst = _worklst(valnum);
00859
00860 if (_vn_maybe_removed(valnum))
00861 {
00862 SET_OPT_REPEAT_PHASE(_vnfre_delete_occurs_phase,
00863 "VNFRE: delete occurs");
00864 _verify_and_remove_occurs(worklst, valnum);
00865 SET_OPT_REPEAT_PHASE(_vnfre_misc_phase, "VNFRE: miscellaneous");
00866 }
00867
00868 const BOOL is_vnfre_candidate = _is_vnfre_candidate(worklst);
00869 const BOOL is_const_prop_candidate =
00870 (_vn->valnum_expr(valnum) != NULL &&
00871 _vn->valnum_expr(valnum)->get_kind() == VN_EXPR::LITERAL &&
00872 _has_an_occur(worklst));
00873
00874
00875
00876
00877 _set_do_vnfre(valnum, FALSE);
00878
00879 if (!_user_enabled(valnum))
00880 {
00881 if (is_const_prop_candidate || is_vnfre_candidate)
00882 DevWarn("VNFRE: skip valnum %d", (int)valnum.ordinal());
00883 }
00884 else if (is_const_prop_candidate)
00885 {
00886
00887
00888
00889
00890 VNFRE_TRACE(stderr, "CONST_PROP[%d]\n", valnum.ordinal());
00891 _substitute_literal(valnum);
00892 }
00893 else if (is_vnfre_candidate)
00894 {
00895
00896
00897
00898
00899 VNFRE_TRACE(stderr, "REDUN_ELIM[%d] %s\n",
00900 valnum.ordinal(),
00901 (_vn->valnum_expr(valnum) != NULL?
00902 "expr" : "chi/phi"));
00903 _expression_redundancy_elimination(valnum);
00904 }
00905 else
00906 {
00907
00908
00909
00910
00911
00912 VNFRE_TRACE(stderr, "IGNORED[%d]\n", valnum.ordinal());
00913 }
00914
00915
00916
00917
00918 CXX_DELETE(_worklst(valnum), _gpool);
00919 _worklst(valnum) = NULL;
00920 }
00921 OPT_POOL_Pop(_lpool, -1);
00922 OPT_POOL_Pop(_vpool, -1);
00923 }
00924 }
00925 OPT_POOL_Pop(_lpool, -1);
00926 }
00927
00928
00929 void
00930 VALNUM_FRE::reset_valnum(const CODEREP *cr, VN_VALNUM to_valnum)
00931 {
00932
00933
00934
00935
00936 const VN_VALNUM from_valnum = get_valnum(cr->Coderep_id());
00937 EXP_WORKLST *from_worklist = _worklst(from_valnum);
00938
00939 Is_True(
00940 from_valnum != to_valnum,
00941 ("Illegal call to VALNUM_FRE::reset_valnum()"));
00942
00943
00944
00945
00946 _vn->reset_valnum(cr, to_valnum);
00947
00948
00949
00950
00951
00952 if (from_worklist != NULL &&
00953 !(from_valnum.is_bottom() || from_valnum.is_top()))
00954 {
00955
00956
00957
00958
00959 _set_vn_maybe_removed(from_valnum, TRUE);
00960
00961
00962
00963
00964 if (_do_vnfre(to_valnum))
00965 {
00966 EXP_WORKLST *to_worklist = _worklst(to_valnum);
00967 EXP_OCCURS *occ;
00968 EXP_OCCURS_ITER occ_iter;
00969 FOR_ALL_NODE(occ, occ_iter, Init(from_worklist->Real_occurs().Head()))
00970 {
00971 EXP_OCCURS *tail_occ = to_worklist->Real_occurs().Tail();
00972 pair<INT32,CODEREP*> counted_occurs =
00973 Count_occurs(_get_occur_cr(occ), Match_Cr(cr), FALSE);
00974
00975 if (counted_occurs.first > 0)
00976 {
00977 EXP_OCCURS *new_occ = _copy_real_occurrence(occ);
00978
00979 if (counted_occurs.first > 1)
00980 new_occ->Set_mult_real();
00981 else
00982 new_occ->Reset_mult_real();
00983
00984 if (tail_occ == NULL || tail_occ->Is_DPO_less_than(new_occ))
00985 to_worklist->Append_occurrence(new_occ);
00986 else
00987 to_worklist->Insert_occurrence(new_occ, _etable);
00988 }
00989 }
00990 }
00991 }
00992 }
00993
00994
00995 void
00996 VALNUM_FRE::replace_cr_in_stmt(const CODEREP *old_cr,
00997 CODEREP *new_cr,
00998 const STMTREP *stmt)
00999 {
01000
01001
01002
01003
01004
01005
01006
01007
01008 VN_VALNUM old_valnum = get_valnum(old_cr->Coderep_id());
01009
01010 Is_True(old_cr != new_cr && old_valnum == get_valnum(new_cr->Coderep_id()),
01011 ("Illegal call to VALNUM_FRE::replace_cr_in_stmt()"));
01012
01013
01014
01015
01016
01017
01018
01019
01020 if (_do_vnfre(old_valnum))
01021 {
01022 EXP_WORKLST *worklist = _worklst(old_valnum);
01023 EXP_OCCURS *occ;
01024 EXP_OCCURS_ITER occ_iter;
01025 FOR_ALL_NODE(occ, occ_iter, Init(worklist->Real_occurs().Head()))
01026 {
01027 if (occ->Occurrence() == old_cr && occ->Stmt() == stmt)
01028 occ->Set_occurrence(new_cr);
01029 }
01030 }
01031 }
01032
01033
01034 void
01035 VALNUM_FRE::move_rhs_occurs(const STMTREP *old_stmt,
01036 STMTREP *new_stmt)
01037 {
01038
01039
01040
01041
01042
01043 const VN_VALNUM num_valnums = VN_VALNUM::Next(_vn->last_valnum());
01044
01045 Is_True(OPCODE_is_store(old_stmt->Op()),
01046 ("Unexpected operand to VALNUM_FRE::move_rhs_occurs()"));
01047
01048 for (VN_VALNUM v = VN_VALNUM::First();
01049 v != num_valnums;
01050 v = VN_VALNUM::Next(v))
01051 {
01052 EXP_WORKLST *worklist = _worklst(v);
01053 EXP_OCCURS *occ;
01054 EXP_OCCURS_ITER occ_iter;
01055 FOR_ALL_NODE(occ, occ_iter, Init(worklist->Real_occurs().Head()))
01056 {
01057 if (occ->Stmt() == old_stmt && occ->Stmt_kid_num() == 0)
01058 occ->Set_enclose_stmt(new_stmt);
01059 }
01060 }
01061 }
01062
01063
01064 void
01065 VALNUM_FRE::delete_all_occurs(const EXP_OCCURS *occur,
01066 const CODEREP *cr)
01067 {
01068
01069
01070
01071
01072
01073
01074
01075
01076
01077
01078 STMTREP * const stmt = occur->Stmt();
01079 const VN_VALNUM valnum = get_valnum(occur->Occurrence()->Coderep_id());
01080
01081 if ((OPCODE_operator(stmt->Op()) == OPR_MSTORE ||
01082 OPCODE_operator(stmt->Op()) == OPR_ISTORE ||
01083 OPCODE_operator(stmt->Op()) == OPR_ISTOREX) &&
01084 cr->Coderep_id() == stmt->Lhs()->Coderep_id())
01085 _remove_nested_occurs(cr, valnum,
01086 TRUE, FALSE);
01087 else
01088 _remove_nested_occurs(cr, valnum,
01089 FALSE, FALSE);
01090 }
01091
01092
01093
01094
01095
01096
01097 CODEREP *
01098 VALNUM_FRE::_get_occur_cr(const EXP_OCCURS *occur) const
01099 {
01100 STMTREP * const stmt = occur->Stmt();
01101 const INT32 kid_num = occur->Stmt_kid_num();
01102 CODEREP * cr = NULL;
01103
01104
01105
01106 if (OPCODE_is_fake(stmt->Op()))
01107 cr = stmt->Rhs()->Opnd(kid_num);
01108 else if (OPCODE_is_store(stmt->Op()))
01109 switch (kid_num)
01110 {
01111 case 0:
01112 cr = stmt->Rhs();
01113 break;
01114 case 1:
01115 cr = stmt->Lhs()->Istr_base();
01116 break;
01117 case 3:
01118 cr = stmt->Lhs()->Mstore_size();
01119 break;
01120 default:
01121 Is_True(FALSE,
01122 ("VALNUM_FRE::_get_occur_cr: bad stmt_kid_num"));
01123 break;
01124 }
01125 else if (OPCODE_operator(stmt->Op()) == OPR_PREFETCH)
01126 cr = stmt->Rhs()->Ilod_base();
01127 else
01128 cr = stmt->Rhs();
01129
01130 return cr;
01131 }
01132
01133
01134 void
01135 VALNUM_FRE::_remove_nested_occurs(const CODEREP *enclosing_cr,
01136 VN_VALNUM remove_valnum,
01137 BOOL is_istr_lhs,
01138 BOOL within_valnum)
01139 {
01140
01141
01142
01143
01144
01145
01146
01147
01148
01149
01150
01151 if (!_cr_maybe_removed(enclosing_cr->Coderep_id()))
01152 {
01153 VN_VALNUM valnum = get_valnum(enclosing_cr->Coderep_id());
01154
01155 if (within_valnum)
01156 {
01157 if (_do_vnfre(valnum))
01158 {
01159
01160
01161 _set_vn_maybe_removed(valnum, TRUE);
01162 _set_cr_maybe_removed(enclosing_cr->Coderep_id(), TRUE);
01163 }
01164 }
01165 else if (!is_istr_lhs && valnum == remove_valnum)
01166 {
01167
01168
01169
01170
01171
01172
01173
01174 within_valnum = TRUE;
01175 }
01176
01177
01178
01179 switch (enclosing_cr->Kind())
01180 {
01181 case CK_LDA:
01182 case CK_VAR:
01183 case CK_CONST:
01184 case CK_RCONST:
01185 break;
01186
01187 case CK_IVAR:
01188 if (enclosing_cr->Opr() == OPR_MLOAD)
01189 _remove_nested_occurs((is_istr_lhs?
01190 enclosing_cr->Mstore_size():
01191 enclosing_cr->Mload_size()),
01192 remove_valnum,
01193 FALSE,
01194 within_valnum);
01195 else if (enclosing_cr->Opr() == OPR_ILOADX)
01196 _remove_nested_occurs(enclosing_cr->Index(),
01197 remove_valnum,
01198 FALSE,
01199 within_valnum);
01200
01201 _remove_nested_occurs((is_istr_lhs?
01202 enclosing_cr->Istr_base():
01203 enclosing_cr->Ilod_base()),
01204 remove_valnum,
01205 FALSE,
01206 within_valnum);
01207 break;
01208
01209 case CK_OP:
01210 Is_True(enclosing_cr->Opr() != OPR_ARRAY,
01211 ("VNFRE::_remove_nested_occurs: an OPR_ARRAY node,"
01212 " this is a bug in the lowering process"));
01213 {
01214 for (INT32 i=0; i < enclosing_cr->Kid_count(); i++)
01215 _remove_nested_occurs(enclosing_cr->Opnd(i),
01216 remove_valnum,
01217 FALSE,
01218 within_valnum);
01219 }
01220 break;
01221
01222 default:
01223 Is_True(FALSE,
01224 ("VALNUM_FRE::_remove_nested_occurs: bad coderep kind"));
01225 break;
01226 }
01227 }
01228 }
01229
01230
01231
01232
01233
01234
01235
01236
01237 BOOL
01238 VALNUM_FRE::_check_cr_compatible (VN_VALNUM valnum)
01239 {
01240 BOOL has_uncompatible_cr = FALSE;
01241 BOOL mtype_bool = FALSE;
01242 BOOL mtype_non_bool = FALSE;
01243
01244 EXP_WORKLST *worklist = _worklst(valnum);
01245 EXP_OCCURS *occ;
01246 EXP_OCCURS_ITER occ_iter;
01247
01248 if (worklist == NULL)
01249 return has_uncompatible_cr;
01250 FOR_ALL_NODE(occ, occ_iter, Init(worklist->Real_occurs().Head()))
01251 {
01252 CODEREP *cr = occ->Occurrence();
01253 if (cr->Dtyp() == MTYPE_B && cr->Dsctyp() == MTYPE_B)
01254 mtype_bool = TRUE;
01255 else if (cr->Dtyp() != MTYPE_B && cr->Dsctyp() != MTYPE_B)
01256
01257 mtype_non_bool = TRUE;
01258
01259 if (mtype_bool == TRUE && mtype_non_bool == TRUE) {
01260 has_uncompatible_cr = TRUE;
01261 }
01262 }
01263
01264 return has_uncompatible_cr;
01265 }
01266
01267
01268
01269
01270
01271
01272 template <class ETYPE, class ALLOCATOR>
01273 void VALNUM_FRE_grow_vector(vector<ETYPE,ALLOCATOR> &vec,
01274 ETYPE init_val,
01275 UINT32 to_size)
01276 {
01277
01278
01279
01280 if (vec.capacity() < to_size)
01281 {
01282 UINT32 growth_incr = vec.capacity()/3;
01283
01284 if (growth_incr == 0)
01285 growth_incr = 64;
01286
01287 const UINT32 growth_factor = 1 + (to_size - vec.capacity())/growth_incr;
01288
01289 vec.reserve(vec.capacity() + growth_factor*growth_incr + 1);
01290 }
01291 while (to_size > vec.size())
01292 {
01293 vec.push_back(init_val);
01294 }
01295 }
01296
01297
01298 void
01299 VALNUM_FRE::_grow_exprid_maps(VN::EXPRID id)
01300 {
01301
01302
01303 VALNUM_FRE_grow_vector(_cr_removed, bool(FALSE), (UINT32)id+1);
01304 }
01305
01306
01307 void
01308 VALNUM_FRE::_grow_valnum_maps(VN_VALNUM v)
01309 {
01310 #ifndef KEY // bug 9114
01311 Is_True(_vn_to_exprid == NULL,
01312 ("Unexpected map in VALNUM_FRE::_grow_valnum_maps()"));
01313 #endif
01314
01315 VALNUM_FRE_grow_vector(_vn_to_worklst,
01316 (EXP_WORKLST*)NULL, (UINT32)v.ordinal()+1);
01317 VALNUM_FRE_grow_vector(_vn_removed,
01318 bool(FALSE), (UINT32)v.ordinal()+1);
01319 VALNUM_FRE_grow_vector(_do_fre,
01320 bool(FALSE), (UINT32)v.ordinal()+1);
01321 }
01322
01323
01324
01325
01326
01327
01328 inline BOOL
01329 VALNUM_FRE::_disabled_expr(const VN_EXPR::CONST_PTR vexpr) const
01330 {
01331
01332
01333
01334
01335
01336 return (vexpr != NULL &&
01337 (vexpr->get_kind() == VN_EXPR::LDA_ADDR ||
01338 (vexpr->get_kind() == VN_EXPR::MEMLOC &&
01339 vexpr->get_dsctype() == MTYPE_M)));
01340 }
01341
01342
01343 BOOL
01344 VALNUM_FRE::_has_valid_stmtrep_occurrence(VN_VALNUM v)
01345 {
01346
01347
01348
01349
01350
01351
01352
01353
01354
01355
01356 BOOL found = FALSE;
01357 VALNUM_TO_EXPR_LIST::EXPR_ITERATOR expr_end(_vn_to_exprid->end(v));
01358
01359 for (VALNUM_TO_EXPR_LIST::EXPR_ITERATOR expr_itr(_vn_to_exprid->begin(v));
01360 !found && expr_itr != expr_end;
01361 expr_itr++)
01362 {
01363 found = !_vn->expr_stmts(*expr_itr)->empty();
01364 }
01365 return found;
01366 }
01367
01368
01369 BOOL
01370 VALNUM_FRE::_may_be_redundant_expr(VN_VALNUM v, VN_EXPR::CONST_PTR vexpr)
01371 {
01372
01373
01374
01375
01376
01377 const UINT32 num_codereps = _vn_to_exprid->size(v);
01378 const BOOL is_disabled = _disabled_expr(vexpr);
01379 BOOL may_be_redundant = !is_disabled && num_codereps > 1;
01380
01381 if (vexpr != NULL && !is_disabled && num_codereps == 1)
01382 {
01383
01384
01385 if (vexpr->get_kind() == VN_EXPR::LITERAL)
01386 {
01387
01388
01389 CODEREP *cr = _vn->expr_cr(_vn_to_exprid->front(v));
01390
01391 if (cr->Kind() != CK_CONST && cr->Kind() != CK_RCONST)
01392 may_be_redundant = TRUE;
01393 }
01394 else if (vexpr->get_kind() == VN_EXPR::INTR_OP)
01395 {
01396
01397
01398
01399
01400 may_be_redundant = TRUE;
01401 }
01402 else if (VN_IVC::Is_Induction_Var(_vn, v))
01403 {
01404
01405
01406
01407 may_be_redundant = TRUE;
01408 }
01409 }
01410 return may_be_redundant;
01411 }
01412
01413
01414 void
01415 VALNUM_FRE::_select_for_valnum_list(VN_VALNUM v,
01416 VN::BIT_VECTOR &visited,
01417 VN::VALNUM_VECTOR &valnum_list)
01418 {
01419
01420
01421
01422
01423
01424
01425
01426
01427
01428
01429
01430
01431
01432
01433
01434
01435
01436
01437
01438
01439 if (!visited[v.ordinal()])
01440 {
01441 VN_EXPR::CONST_PTR vn_expr = _vn->valnum_expr(v);
01442
01443 visited[v.ordinal()] = TRUE;
01444 if (_has_valid_stmtrep_occurrence(v) &&
01445 _may_be_redundant_expr(v, vn_expr))
01446 {
01447 if (vn_expr != NULL)
01448 {
01449 if (vn_expr->get_kind() == VN_EXPR::MEMLOC)
01450 {
01451
01452
01453
01454 _select_for_valnum_list(vn_expr->get_bytesize(),
01455 visited, valnum_list);
01456 _select_for_valnum_list(vn_expr->get_offset(),
01457 visited, valnum_list);
01458 _select_for_valnum_list(vn_expr->get_base_addr(),
01459 visited, valnum_list);
01460 _select_for_valnum_list(vn_expr->get_vsym(),
01461 visited, valnum_list);
01462 }
01463 else if (vn_expr->get_kind() != VN_EXPR::PHI)
01464 {
01465
01466
01467
01468
01469
01470
01471
01472 for (INT32 opnd = 0; opnd < vn_expr->get_num_opnds(); opnd++)
01473 _select_for_valnum_list(vn_expr->get_opnd(opnd),
01474 visited, valnum_list);
01475 }
01476 }
01477 _set_do_vnfre(v, TRUE);
01478 valnum_list.push_back(v);
01479 }
01480 }
01481 }
01482
01483
01484 void
01485 VALNUM_FRE::_select_and_sort_valnums(VN::VALNUM_VECTOR &valnum_list)
01486 {
01487
01488
01489
01490
01491
01492
01493
01494
01495
01496
01497
01498
01499
01500
01501
01502
01503 OPT_POOL_Push(_lpool, -1);
01504 {
01505 const VN_VALNUM last_valnum = _vn->last_valnum();
01506 #ifndef KEY // bug 9114 : this code moved to caller
01507 VALNUM_TO_EXPR_LIST vn_to_exprid(*_vn, _lpool);
01508 #endif
01509 VN::BIT_VECTOR visited(last_valnum.ordinal()+1,
01510 bool(FALSE),
01511 VN::BVECTOR_ALLOCATOR(_lpool));
01512
01513 #ifndef KEY // bug 9114 : this code moved to caller
01514 _vn_to_exprid = &vn_to_exprid;
01515 #endif
01516
01517 for (VN_VALNUM v = VN_VALNUM::First();
01518 v <= last_valnum;
01519 v = VN_VALNUM::Next(v))
01520 {
01521 _select_for_valnum_list(v, visited, valnum_list);
01522 }
01523
01524 #ifndef KEY // bug 9114 : this code moved to caller
01525 _vn_to_exprid = NULL;
01526 #endif
01527 }
01528 OPT_POOL_Pop(_lpool, -1);
01529 }
01530
01531
01532
01533
01534
01535
01536 pair<CODEREP*,STMTREP*>
01537 VALNUM_FRE::_save_to_temp(BB_NODE *in_bb,
01538 STMTREP *after_stmt,
01539 BOOL when_not_after_append,
01540 CODEREP *rhs)
01541 {
01542
01543
01544
01545
01546
01547
01548
01549
01550 const MTYPE dtype = rhs->Dtyp();
01551 CODEREP *lhs =
01552 _etable->New_temp_cr(dtype,
01553 rhs->Check_if_result_is_address(_etable->Htable()->Sym()),
01554 rhs);
01555
01556 VNFRE::add_valnum(lhs, get_valnum(rhs->Coderep_id()).ordinal());
01557
01558
01559
01560 STMTREP *savestmt =
01561 _etable->Generate_stid_to_preg(lhs, rhs, dtype, in_bb, in_bb->Linenum());
01562 savestmt->Set_stmt_id(_etable->Cfg()->Get_stmt_id());
01563
01564
01565
01566 if (after_stmt == NULL)
01567 {
01568 if (when_not_after_append)
01569 in_bb->Append_stmt_before_branch(savestmt);
01570 else
01571 in_bb->Prepend_stmtrep(savestmt);
01572 }
01573 else
01574 in_bb->Insert_stmtrep_after(savestmt, after_stmt);
01575
01576 Is_Trace(_tracing,
01577 (TFile,
01578 "----> VALNUM_FRE::_save_to_temp in bb%d\n", in_bb->Id()));
01579 Is_Trace_cmd(_tracing, savestmt->Print(TFile));
01580 Is_Trace(_tracing, (TFile, "----------------------- \n"));
01581
01582 return pair<CODEREP*,STMTREP*>(lhs,savestmt);
01583 }
01584
01585
01586 CODEREP*
01587 VALNUM_FRE::_ivc_insert_initval_diff(BB_NODE *init_bb,
01588 CODEREP *init_cr,
01589 CODEREP *base_cr)
01590 {
01591
01592
01593
01594 const OPCODE opc = OPCODE_make_op(OPR_SUB, init_cr->Dtyp(), MTYPE_V);
01595 CODEREP * const rhs = _etable->Htable()->Add_bin_node(opc,init_cr,base_cr);
01596
01597 (void)compute_valnum(rhs);
01598
01599
01600
01601
01602 pair<CODEREP*,STMTREP*> saved =
01603 _save_to_temp(init_bb, NULL, TRUE, rhs);
01604
01605
01606
01607 return saved.first;
01608 }
01609
01610
01611 void
01612 VALNUM_FRE::_remove_ivc_incr_occurs(PHI_NODE *phi)
01613 {
01614
01615
01616
01617
01618
01619
01620
01621
01622 const IDTYPE aux_id = phi->RESULT()->Aux_id();
01623 EXP_WORKLST *worklist = _worklst(get_valnum(phi->RESULT()->Coderep_id()));
01624
01625 Is_True(phi->Size()==2 && phi->RESULT()->Kind() == CK_VAR,
01626 ("Unexpected kind of PHI node (Size==%d) "
01627 "VALNUM_FRE::_remove_ivc_incr_occurs()", phi->Size()));
01628
01629 EXP_OCCURS *occ, *next_occ, *prev_occ = NULL;
01630 EXP_OCCURS_ITER occ_iter;
01631 occ_iter.Init(_first_real_occur(worklist));
01632 for (occ = occ_iter.First(); !occ_iter.Is_Empty(); occ = next_occ)
01633 {
01634 STMTREP * const stmt = occ->Stmt();
01635
01636
01637
01638 next_occ = occ_iter.Next();
01639
01640
01641
01642
01643 if (OPCODE_operator(stmt->Op()) == OPR_STID &&
01644 occ->Stmt_kid_num() == 0 &&
01645 (stmt->Lhs()->Aux_id() == aux_id ||
01646 stmt->Lhs()->Aux_id() == aux_id))
01647 {
01648
01649
01650 worklist->Real_occurs().Remove(prev_occ, occ);
01651 _etable->Add_to_occ_freelist(occ);
01652 }
01653 else
01654 {
01655 prev_occ = occ;
01656 }
01657 }
01658 }
01659
01660
01661 void
01662 VALNUM_FRE::_ivc_substitute(BB_NODE *loop_header,
01663 STMTREP *base_stmt,
01664 CODEREP *base_cr,
01665 VN_IVC &vn_ivc,
01666 EQCLASS_MEMBER &base,
01667 EQCLASS_MEMBER &memb)
01668 {
01669
01670
01671
01672 if (vn_ivc.num_hits(memb) > 0)
01673 {
01674 const MTYPE dtype = base_cr->Dtyp();
01675 BOOL delay_substitution_until_vnfre = FALSE;
01676 VN_VALNUM valnum = vn_ivc.indvar_valnum(memb);
01677 CODEREP *ofst_expr_cr = base_cr;
01678
01679 Is_True(MTYPE_size_min(dtype) >= 32,
01680 ("Unexpected dtype (size = %d) in VALNUM_FRE::_ivc_substitute",
01681 MTYPE_size_min(dtype)));
01682
01683 Is_Trace(_tracing, (TFile, "---> IVC substitution for:\n"));
01684 Is_Trace(_tracing, (TFile, "---> "));
01685 Is_Trace_cmd(_tracing, vn_ivc.print(base, memb, TFile));
01686
01687 if (!vn_ivc.indvar_is_literal_ofst(memb) ||
01688 vn_ivc.indvar_literal_ofst(memb) != 0LL)
01689 {
01690
01691
01692
01693
01694 CODEMAP * const htable = _etable->Htable();
01695 CODEREP * ofst_cr;
01696 OPERATOR ofst_opr;
01697
01698 if (vn_ivc.indvar_is_literal_ofst(memb))
01699 {
01700 INT64 ofst = vn_ivc.indvar_literal_ofst(memb);
01701
01702 ofst_opr = (ofst >=0 ? OPR_ADD : OPR_SUB);
01703 ofst = (ofst >=0 ? ofst : (-ofst));
01704 ofst_cr = htable->Add_const(dtype, ofst);
01705 }
01706 else
01707 {
01708 ofst_opr = OPR_ADD;
01709 ofst_cr = _ivc_insert_initval_diff(vn_ivc.indvar_init_bb(base),
01710 vn_ivc.indvar_init_cr(memb),
01711 vn_ivc.indvar_init_cr(base));
01712 }
01713
01714 ofst_expr_cr =
01715 htable->Add_bin_node(OPCODE_make_op(ofst_opr, dtype, MTYPE_V),
01716 base_cr,
01717 ofst_cr);
01718
01719
01720
01721
01722
01723
01724
01725
01726
01727
01728
01729
01730
01731
01732
01733
01734
01735
01736 _set_do_vnfre(valnum, FALSE);
01737 VNFRE::add_valnum(ofst_expr_cr, valnum.ordinal());
01738 _set_do_vnfre(valnum, TRUE);
01739
01740
01741
01742
01743
01744
01745
01746
01747
01748
01749 if (vn_ivc.num_occurs(memb) > 1)
01750 {
01751 if (IVC_Maximize_Live_Ranges())
01752 {
01753
01754
01755
01756 const pair<CODEREP*,STMTREP*> save_info =
01757 _save_to_temp(loop_header,
01758 base_stmt,
01759 FALSE,
01760 ofst_expr_cr);
01761
01762 ofst_expr_cr = save_info.first;
01763 }
01764 else
01765 {
01766
01767
01768
01769
01770
01771
01772
01773 EXP_OCCURS * occ;
01774 EXP_OCCURS_ITER occ_iter;
01775 FOR_ALL_NODE(occ,
01776 occ_iter,
01777 Init(_first_real_occur(_worklst(valnum))))
01778 {
01779
01780
01781 occ->Set_occurrence(ofst_expr_cr);
01782 occ->Set_mult_real();
01783 }
01784 _worklst(valnum)->Set_ivc_cand();
01785
01786
01787
01788 delay_substitution_until_vnfre = TRUE;
01789 }
01790 }
01791 }
01792 if (!delay_substitution_until_vnfre)
01793 {
01794
01795
01796 if (_vn_maybe_removed(valnum))
01797 {
01798 SET_OPT_REPEAT_PHASE(_vnfre_delete_occurs_phase,
01799 "VNFRE: delete occurs");
01800 _verify_and_remove_occurs(_worklst(valnum), valnum);
01801 SET_OPT_REPEAT_PHASE(_vnfre_ivc_phase, "VNFRE: ivc");
01802 }
01803
01804
01805
01806
01807 _set_do_vnfre(valnum, FALSE);
01808
01809
01810
01811
01812 EXP_OCCURS * const first_real_occ =
01813 _first_real_occur(_worklst(valnum));
01814
01815 EXP_OCCURS * occ;
01816 EXP_OCCURS_ITER occ_iter;
01817 FOR_ALL_NODE(occ, occ_iter, Init(first_real_occ))
01818 {
01819
01820
01821 _etable->Replace_by_temp(occ, ofst_expr_cr);
01822 }
01823
01824
01825
01826
01827 CXX_DELETE(_worklst(valnum), _gpool);
01828 _worklst(valnum) = NULL;
01829
01830 }
01831 }
01832 }
01833
01834 #ifdef KEY // bug 9114
01835 BOOL
01836 VALNUM_FRE::_ivc_loop_variant(BB_NODE *loop_header, VN_VALNUM valnum)
01837 {
01838
01839
01840
01841
01842 VALNUM_TO_EXPR_LIST::EXPR_ITERATOR itr = _vn_to_exprid->begin(valnum);
01843 VALNUM_TO_EXPR_LIST::EXPR_ITERATOR end = _vn_to_exprid->end(valnum);
01844 CODEREP *cr;
01845 while (itr != end) {
01846 cr = _vn->expr_cr(*itr);
01847 if (cr->Kind() == CK_VAR && cr->Defbb() != loop_header)
01848 return FALSE;
01849 itr++;
01850 }
01851 return TRUE;
01852 }
01853 #endif
01854
01855 void
01856 VALNUM_FRE::_ivc_classify(BB_NODE *loop_header, VN_IVC &vn_ivc)
01857 {
01858
01859
01860
01861
01862 WN *index = loop_header->Loop()->Index();
01863 PHI_NODE *phi;
01864 PHI_LIST_ITER phi_iter;
01865
01866
01867
01868
01869 FOR_ALL_ELEM(phi, phi_iter, Init(loop_header->Phi_list()))
01870 {
01871 if (phi->Live() &&
01872 phi->Size() == 2)
01873 {
01874 CODEREP * const phi_result = phi->RESULT();
01875
01876
01877
01878
01879 if (!_is_dedicated_preg(phi_result) &&
01880 _is_real_var(phi_result))
01881 {
01882 VN_VALNUM result_valnum =
01883 _vn->expr_valnum(phi_result->Coderep_id());
01884 VN_EXPR::PTR result_vn_expr = _vn->valnum_expr(result_valnum);
01885
01886 if (_user_enabled(result_valnum) &&
01887 _do_vnfre(result_valnum) &&
01888 !result_valnum.is_bottom() &&
01889 result_vn_expr != NULL &&
01890 result_vn_expr->get_kind() == VN_EXPR::PHI &&
01891 result_vn_expr->get_num_opnds() == 2)
01892 {
01893 #ifdef KEY // bug 9114 : without this, could falsely identify class for the
01894
01895 if (! _ivc_loop_variant(loop_header, result_valnum))
01896 continue;
01897 #endif
01898 if (index != NULL &&
01899 WN_st(index) ==
01900 _etable->Opt_stab()->St(phi_result->Aux_id()) &&
01901 WN_idname_offset(index) ==
01902 _etable->Opt_stab()->St_ofst(phi_result->Aux_id()))
01903 {
01904 vn_ivc.classify(phi, result_valnum, TRUE);
01905 index = NULL;
01906 }
01907 else
01908 {
01909 vn_ivc.classify(phi, result_valnum, FALSE);
01910 }
01911 }
01912 }
01913 }
01914 }
01915 }
01916
01917
01918 void
01919 VALNUM_FRE::_ivc_coalesce(BB_NODE *loop_header, VN_IVC &vn_ivc)
01920 {
01921
01922
01923
01924
01925
01926
01927
01928
01929
01930
01931
01932
01933
01934
01935
01936
01937 for (INT32 i = 0; i < vn_ivc.num_eqclasses(); i++)
01938 {
01939 VN_IVC::members_iterator memb_it_start = vn_ivc.members_begin(i);
01940
01941 if (vn_ivc.num_members(i) > 1 ||
01942 (vn_ivc.num_members(i) == 1 &&
01943 vn_ivc.num_hits(*memb_it_start) > 1))
01944 {
01945 VN_IVC::members_iterator memb_it_end = vn_ivc.members_end();
01946 VN_IVC::members_iterator memb_it;
01947
01948
01949
01950
01951
01952 VN_IVC::members_iterator base_memb =
01953 VN_IVC_choose_eqclass_base_indvar(GET_NUM_OCCURS(this),
01954 vn_ivc,
01955 memb_it_start,
01956 memb_it_end);
01957
01958
01959
01960
01961
01962 INT32 num_candidates =
01963 vn_ivc.finalize_for_coalescing(*base_memb,
01964 memb_it_start,
01965 memb_it_end,
01966 IVC_Aggressive());
01967
01968 Is_True(vn_ivc.indvar_is_literal_ofst(*base_memb) &&
01969 vn_ivc.indvar_literal_ofst(*base_memb) == 0,
01970 ("Unexpected offset for coalescing base in "
01971 "VALNUM_FRE::_ivc_coalesce()"));
01972
01973 if (_tracing)
01974 {
01975 fprintf(TFile, "====> IVC for BB %d <====\n", loop_header->Id());
01976 for (memb_it = memb_it_start; memb_it != memb_it_end; ++memb_it)
01977 vn_ivc.print(*base_memb, *memb_it, TFile);
01978 }
01979
01980 if (num_candidates > 1)
01981 {
01982
01983
01984 Is_Trace(_tracing,
01985 (TFile, "Base induction variable = vn%d!\n",
01986 (INT32)vn_ivc.indvar_valnum(*base_memb).ordinal()));
01987
01988
01989
01990
01991 const pair<CODEREP*,STMTREP*> temp_info =
01992 _save_to_temp(loop_header,
01993 NULL,
01994 FALSE,
01995 vn_ivc.indvar_phi(*base_memb)->RESULT());
01996
01997
01998
01999
02000
02001
02002
02003
02004 _remove_ivc_incr_occurs(vn_ivc.indvar_phi(*base_memb));
02005
02006
02007
02008
02009
02010
02011
02012 CODEREP * const base_cr = temp_info.first;
02013 STMTREP * const base_stmt = temp_info.second;
02014
02015 for (memb_it = memb_it_start; memb_it != memb_it_end; ++memb_it)
02016 {
02017 _ivc_substitute(loop_header,
02018 base_stmt,
02019 base_cr,
02020 vn_ivc,
02021 *base_memb,
02022 *memb_it);
02023 }
02024 }
02025 }
02026 }
02027 }
02028
02029
02030 void
02031 VALNUM_FRE::_ivc()
02032 {
02033
02034
02035 if (IVC_Enabled())
02036 {
02037 DPOBB_ITER dpo_iter(_etable->Cfg());
02038 BB_NODE *bb;
02039
02040 FOR_ALL_ELEM (bb, dpo_iter, Init())
02041 {
02042
02043
02044
02045 if (bb->Loop() != NULL &&
02046 bb->Loop()->Well_formed() &&
02047 bb->Loop()->Header() == bb)
02048 {
02049
02050
02051 OPT_POOL_Push(_lpool, -1);
02052 {
02053 VN_IVC vn_ivc((IVC_LoopInvariant_Diff()?
02054 VN_IVC::IVC_INVARIANT_DIFF:
02055 VN_IVC::IVC_CONST_DIFF),
02056 _vn, _lpool);
02057
02058 _ivc_classify(bb, vn_ivc);
02059 _ivc_coalesce(bb, vn_ivc);
02060 }
02061 OPT_POOL_Pop(_lpool, -1);
02062 }
02063 }
02064 }
02065 }
02066
02067
02068
02069
02070
02071
02072 BOOL
02073 VALNUM_FRE::_contains_undef_val(CODEREP *cr, STMTREP *stmt) const
02074 {
02075
02076
02077
02078
02079
02080
02081
02082 BOOL undef = FALSE;
02083
02084 switch (cr->Kind())
02085 {
02086 case CK_CONST:
02087 case CK_RCONST:
02088 case CK_LDA:
02089 break;
02090
02091 case CK_VAR:
02092 undef = cr->Is_var_volatile() || cr->Is_flag_set(CF_IS_ZERO_VERSION);
02093 break;
02094
02095 case CK_IVAR:
02096 if (cr->Is_ivar_volatile())
02097 undef = TRUE;
02098 else
02099 {
02100 CODEREP *const vsym = cr->Get_ivar_vsym();
02101
02102 if (cr->Opr() == OPR_ILOADX)
02103 Warn_todo("VALNUM_FRE::_contains_undef_val: Indexed load.");
02104
02105 if (vsym != NULL &&
02106 (vsym->Is_var_volatile() ||
02107 vsym->Is_flag_set(CF_IS_ZERO_VERSION)))
02108 {
02109 undef = TRUE;
02110 }
02111 else
02112 {
02113
02114
02115
02116 if (cr == stmt->Lhs() && OPCODE_is_store(stmt->Op()))
02117 {
02118 if (cr->Opr() == OPR_MLOAD)
02119 undef = _contains_undef_val(cr->Mstore_size(), stmt);
02120 else if (cr->Opr() == OPR_ILOADX)
02121 undef = _contains_undef_val(cr->Index(), stmt);
02122 if (!undef)
02123 undef = _contains_undef_val(cr->Istr_base(), stmt);
02124 }
02125 else
02126 {
02127 if (cr->Opr() == OPR_MLOAD)
02128 undef = _contains_undef_val(cr->Mload_size(), stmt);
02129 else if (cr->Opr() == OPR_ILOADX)
02130 undef = _contains_undef_val(cr->Index(), stmt);
02131 if (!undef)
02132 undef = _contains_undef_val(cr->Ilod_base(), stmt);
02133 }
02134 }
02135 }
02136 break;
02137
02138 case CK_OP:
02139 if (OPERATOR_is_volatile(cr->Opr()))
02140 undef = TRUE;
02141 else
02142 {
02143 for (INT32 i=0; i<cr->Kid_count(); i++)
02144 undef = undef || _contains_undef_val(cr->Opnd(i), stmt);
02145 }
02146 break;
02147
02148 case CK_DELETED:
02149 default:
02150 FmtAssert(FALSE,
02151 ("VNFRE::_contains_undef_val(), unexpected kind 0x%x",
02152 cr->Kind()));
02153 break;
02154 }
02155 return undef;
02156 }
02157
02158
02159 inline BOOL
02160 VALNUM_FRE::_subsumable_by_branch(VN_VALNUM valnum,
02161 STMTREP *stmt,
02162 CODEREP *cr) const
02163 {
02164
02165
02166
02167
02168 VN_EXPR::PTR expr = _vn->valnum_expr(valnum);
02169
02170 return ((stmt->Op() == OPC_TRUEBR || stmt->Op() == OPC_FALSEBR) &&
02171 cr == stmt->Rhs() &&
02172 (expr == NULL || expr->get_kind() != VN_EXPR::LITERAL) &&
02173 Subsumable_by_branch(cr));
02174 }
02175
02176
02177 EXP_OCCURS *
02178 VALNUM_FRE::_create_real_occurrence(CODEREP *cr,
02179 STMTREP *stmt,
02180 INT stmt_kid_num,
02181 UINT depth)
02182 {
02183
02184
02185 EXP_OCCURS *occurs = _etable->Alloc_vnfre_occurs_node();
02186 occurs->Set_occurrence(cr);
02187 occurs->Set_kind(EXP_OCCURS::OCC_REAL_OCCUR);
02188 occurs->Set_enclose_stmt(stmt);
02189 occurs->Set_stmt_kid_num(stmt_kid_num);
02190 occurs->Set_rehash_cost(depth);
02191 return occurs;
02192 }
02193
02194
02195 void
02196 VALNUM_FRE::_append_real_occurrence(CODEREP *cr,
02197 STMTREP *stmt,
02198 INT stmt_kid_num,
02199 UINT depth)
02200 {
02201
02202
02203
02204
02205
02206
02207
02208
02209
02210
02211
02212
02213
02214
02215
02216
02217
02218 VN_VALNUM valnum = get_valnum(cr->Coderep_id());
02219
02220 if (_do_vnfre(valnum) && !_subsumable_by_branch(valnum, stmt, cr))
02221 {
02222 if (_worklst(valnum) == NULL)
02223 {
02224 _worklst(valnum) = CXX_NEW(EXP_WORKLST(valnum.ordinal(),
02225 cr, PK_VNFRE),
02226 _gpool);
02227 }
02228
02229
02230
02231
02232
02233
02234
02235
02236 EXP_OCCURS *tail_occ = _worklst(valnum)->Real_occurs().Tail();
02237 if (tail_occ != NULL &&
02238 tail_occ->Enclosed_in_stmt() == stmt &&
02239 tail_occ->Stmt_kid_num() == stmt_kid_num)
02240 {
02241 tail_occ->Set_mult_real();
02242 if (tail_occ->Rehash_cost() < depth)
02243 tail_occ->Set_rehash_cost(depth);
02244 }
02245 else
02246 {
02247
02248
02249 EXP_OCCURS *occurs =
02250 _create_real_occurrence(cr, stmt, stmt_kid_num, depth);
02251 _worklst(valnum)->Append_occurrence(occurs);
02252
02253
02254
02255 cr->Set_e_num(_worklst(valnum)->E_num());
02256
02257 VNFRE_TRACE(stderr,
02258 "appending to worklst[%d]: stmt = %p, kid_num = %d\n",
02259 valnum.ordinal(), stmt, stmt_kid_num);
02260 }
02261 }
02262 }
02263
02264
02265 void
02266 VALNUM_FRE::_append_exit_occurrence(BB_NODE *bb)
02267 {
02268
02269
02270 EXP_OCCURS *occurs = _etable->Alloc_vnfre_occurs_node();
02271 occurs->Set_occurrence(NULL);
02272 occurs->Set_kind(EXP_OCCURS::OCC_EXIT_OCCUR);
02273 occurs->Set_enclose_bb(bb);
02274
02275
02276
02277 _exit_occurs.Append(occurs);
02278 }
02279
02280
02281 void
02282 VALNUM_FRE::_insert_a_cr_occurrence(CODEREP *cr,
02283 STMTREP *stmt,
02284 INT stmt_kid_num,
02285 UINT depth)
02286 {
02287
02288
02289 const VN_VALNUM valnum = get_valnum(cr->Coderep_id());
02290
02291 if (_do_vnfre(valnum) && !_subsumable_by_branch(valnum, stmt, cr))
02292 {
02293 EXP_WORKLST *worklist = _worklst(valnum);
02294 EXP_OCCURS *occurs =
02295 _create_real_occurrence(cr, stmt, stmt_kid_num, depth);
02296
02297 Is_True(worklist != NULL,
02298 ("Undefined worklist for valnum in "
02299 "VALNUM_FRE::_insert_a_cr_occurrence()"));
02300
02301
02302
02303
02304 worklist->Insert_occurrence(occurs, _etable);
02305 VNFRE_TRACE(stderr,
02306 "inserting to worklst[%d]: stmt = %p, kid_num = %d\n",
02307 valnum.ordinal(), stmt, stmt_kid_num);
02308 }
02309 }
02310
02311
02312 void
02313 VALNUM_FRE::insert_cr_occurrences(CODEREP *cr,
02314 STMTREP *stmt,
02315 INT stmt_kid_num,
02316 BOOL is_store,
02317 UINT depth)
02318 {
02319
02320
02321
02322
02323
02324 Is_True(cr != NULL, ("VALNUM_FRE::insert_cr_occurrences, cr == NULL"));
02325
02326
02327
02328
02329
02330
02331 switch (cr->Kind())
02332 {
02333 case CK_CONST:
02334 case CK_RCONST:
02335 break;
02336
02337 case CK_LDA:
02338 _insert_a_cr_occurrence(cr, stmt, stmt_kid_num, depth);
02339 break;
02340
02341 case CK_VAR:
02342 if (!is_store)
02343 _insert_a_cr_occurrence(cr, stmt, stmt_kid_num, depth);
02344 break;
02345
02346 case CK_IVAR:
02347 if (cr->Opr() == OPR_ILOADX)
02348 Warn_todo("VALNUM_FRE::insert_cr_occurrences: Indexed load.");
02349
02350
02351
02352
02353 if (!is_store)
02354 {
02355 if (cr->Opr() == OPR_MLOAD)
02356 insert_cr_occurrences(cr->Mload_size(), stmt, stmt_kid_num,
02357 FALSE, depth+1);
02358 else if (cr->Opr() == OPR_ILOADX)
02359 insert_cr_occurrences(cr->Index(), stmt, stmt_kid_num,
02360 FALSE, depth+1);
02361 insert_cr_occurrences(cr->Ilod_base(), stmt, stmt_kid_num,
02362 FALSE, depth+1);
02363
02364 if (cr->Opr() != OPR_PARM)
02365 _insert_a_cr_occurrence(cr, stmt, stmt_kid_num, depth);
02366 }
02367 else
02368 {
02369 if (cr->Opr() == OPR_MLOAD)
02370 insert_cr_occurrences(cr->Mstore_size(), stmt, stmt_kid_num,
02371 FALSE, depth+1);
02372 else if (cr->Opr() == OPR_ILOADX)
02373 insert_cr_occurrences(cr->Index(), stmt, stmt_kid_num,
02374 FALSE, depth+1);
02375 insert_cr_occurrences(cr->Istr_base(), stmt, stmt_kid_num,
02376 FALSE, depth+1);
02377 }
02378 break;
02379
02380 case CK_OP:
02381
02382
02383
02384
02385
02386
02387
02388
02389
02390
02391
02392
02393 Is_True(cr->Opr() != OPR_ARRAY,
02394 ("VNFRE::insert_cr_occurrences: reach an OPR_ARRAY node,"
02395 " this is a bug in the lowering process"));
02396 {
02397 for (INT32 i=0; i<cr->Kid_count(); i++)
02398 {
02399 insert_cr_occurrences(cr->Opnd(i), stmt, stmt_kid_num,
02400 FALSE, depth+1);
02401 }
02402 }
02403
02404
02405
02406
02407
02408
02409
02410 if (cr->Opr() != OPR_PARM)
02411 _insert_a_cr_occurrence(cr, stmt, stmt_kid_num, depth);
02412 break;
02413
02414 case CK_DELETED:
02415 default:
02416 FmtAssert(FALSE,
02417 ("VNFRE::insert_cr_occurrences(), unexpected kind 0x%x",
02418 cr->Kind()));
02419 break;
02420 }
02421 }
02422
02423
02424 void
02425 VALNUM_FRE::collect_cr_occurrences(CODEREP *cr,
02426 STMTREP *stmt,
02427 INT stmt_kid_num,
02428 BOOL is_store_lhs,
02429 UINT depth)
02430 {
02431
02432
02433
02434
02435
02436
02437
02438
02439 Is_True(cr != NULL, ("VALNUM_FRE::collect_cr_occurrences, cr == NULL"));
02440 Is_True(cr != NULL, ("VALNUM_FRE::collect_cr_occurrences, cr == NULL"));
02441
02442 #ifdef KEY
02443 if (stmt->Opr() == OPR_ASM_STMT && (cr->Kind() == CK_VAR || cr->Kind() == CK_IVAR)){
02444 CODEREP *asm_rep = stmt->Rhs();
02445 for (INT32 i=0; i<asm_rep->Kid_count(); i++){
02446 CODEREP *kid = asm_rep->Opnd(i);
02447 if (kid->Opr() == OPR_ASM_INPUT && kid->Opnd(0) == cr)
02448 return;
02449 }
02450 }
02451 #endif
02452
02453
02454
02455
02456
02457 switch (cr->Kind())
02458 {
02459 case CK_CONST:
02460 case CK_RCONST:
02461 break;
02462
02463 case CK_LDA:
02464 _append_real_occurrence(cr, stmt, stmt_kid_num, depth);
02465 break;
02466
02467 case CK_VAR:
02468 if (!is_store_lhs)
02469 _append_real_occurrence(cr, stmt, stmt_kid_num, depth);
02470 break;
02471
02472 case CK_IVAR:
02473 if (cr->Opr() == OPR_ILOADX)
02474 Warn_todo("VALNUM_FRE::collect_cr_occurrences: Indexed load.");
02475
02476
02477
02478
02479 if (!is_store_lhs)
02480 {
02481 if (cr->Opr() == OPR_MLOAD)
02482 collect_cr_occurrences(cr->Mload_size(), stmt, stmt_kid_num,
02483 FALSE, depth+1);
02484 else if (cr->Opr() == OPR_ILOADX)
02485 collect_cr_occurrences(cr->Index(), stmt, stmt_kid_num,
02486 FALSE, depth+1);
02487 collect_cr_occurrences(cr->Ilod_base(), stmt, stmt_kid_num,
02488 FALSE, depth+1);
02489 if (cr->Opr() != OPR_PARM)
02490 _append_real_occurrence(cr, stmt, stmt_kid_num, depth);
02491 }
02492 else
02493 {
02494 if (cr->Opr() == OPR_MLOAD)
02495 collect_cr_occurrences(cr->Mstore_size(), stmt, stmt_kid_num,
02496 FALSE, depth+1);
02497 else if (cr->Opr() == OPR_ILOADX)
02498 collect_cr_occurrences(cr->Index(), stmt, stmt_kid_num,
02499 FALSE, depth+1);
02500 collect_cr_occurrences(cr->Istr_base(), stmt, stmt_kid_num,
02501 FALSE, depth+1);
02502 }
02503 break;
02504
02505 case CK_OP:
02506
02507
02508
02509
02510
02511
02512
02513
02514
02515
02516
02517
02518 Is_True(cr->Opr() != OPR_ARRAY,
02519 ("VNFRE::collect_cr_occurrences: reach an OPR_ARRAY node,"
02520 " this is a bug in the lowering process"));
02521 {
02522 for (INT32 i=0; i<cr->Kid_count(); i++)
02523 {
02524 collect_cr_occurrences(cr->Opnd(i), stmt, stmt_kid_num,
02525 FALSE, depth+1);
02526 }
02527
02528
02529
02530
02531
02532 OPERATOR opr = cr->Opr();
02533 if (opr != OPR_PARM && !OPERATOR_is_volatile(opr)) {
02534 if (!WOPT_Enable_CSE_FP_comparison &&
02535 (opr == OPR_EQ || opr == OPR_NE ||
02536 opr == OPR_LT || opr == OPR_LE ||
02537 opr == OPR_GT || opr == OPR_GE) &&
02538 MTYPE_is_float(cr->Dsctyp())) {
02539
02540 } else
02541 _append_real_occurrence(cr, stmt, stmt_kid_num, depth);
02542 }
02543
02544 }
02545 break;
02546
02547 case CK_DELETED:
02548 default:
02549 FmtAssert(FALSE,
02550 ("VNFRE::collect_cr_occurrences(), unexpected kind 0x%x",
02551 cr->Kind()));
02552 break;
02553 }
02554 }
02555
02556
02557 void
02558 VALNUM_FRE::_collect_all_real_occurrences()
02559 {
02560
02561
02562
02563
02564
02565
02566 DPOBB_ITER dpo_iter(_etable->Cfg());
02567 BB_NODE *bb;
02568
02569 FOR_ALL_ELEM (bb, dpo_iter, Init())
02570 {
02571 COLLECT_CR_OCCURS cr_collector(this);
02572 STMTREP_ITER stmt_iter(bb->Stmtlist());
02573 STMTREP *stmt;
02574
02575 FOR_ALL_NODE(stmt, stmt_iter, Init())
02576 {
02577 stmt->Set_stmt_id(_etable->Cfg()->Get_stmt_id());
02578 stmt->Reset_RHS_saved();
02579 stmt->Reset_saved_RHS();
02580
02581 traverseSR(stmt, cr_collector);
02582 }
02583
02584 if (bb->Kind() == BB_EXIT && bb != _etable->Cfg()->Fake_exit_bb())
02585 _append_exit_occurrence(bb);
02586
02587 }
02588 }
02589
02590
02591 void
02592 VALNUM_FRE::_verify_and_remove_occurs(EXP_WORKLST *worklist,
02593 VN_VALNUM valnum)
02594 {
02595
02596
02597
02598
02599
02600
02601 EXP_OCCURS *occ, *next_occ, *prev_occ = NULL;
02602 EXP_OCCURS_ITER occ_iter;
02603 occ_iter.Init(worklist->Real_occurs().Head());
02604 for (occ = occ_iter.First(); !occ_iter.Is_Empty(); occ = next_occ)
02605 {
02606
02607
02608
02609 pair<INT32,CODEREP*> counted_occurs =
02610 Count_occurs(_get_occur_cr(occ), Match_Vn(_vn, valnum), FALSE);
02611
02612
02613
02614 next_occ = occ_iter.Next();
02615
02616 if (counted_occurs.first == 0)
02617 {
02618
02619
02620 worklist->Real_occurs().Remove(prev_occ, occ);
02621 _etable->Add_to_occ_freelist(occ);
02622 }
02623 else
02624 {
02625
02626
02627
02628
02629
02630 occ->Set_occurrence(counted_occurs.second);
02631
02632 if (worklist->Ivc_cand() || counted_occurs.first > 1)
02633 occ->Set_mult_real();
02634 else
02635 occ->Reset_mult_real();
02636
02637 prev_occ = occ;
02638 }
02639 }
02640 }
02641
02642
02643
02644
02645
02646
02647 BOOL
02648 VALNUM_FRE::_all_same_occurs(CODEREP *cr,
02649 BOOL lhs_of_store,
02650 VN_VALNUM valnum,
02651 const CODEREP *occ_cr) const
02652 {
02653
02654
02655
02656 BOOL same = (get_valnum(cr->Coderep_id()) != valnum ||
02657 cr == occ_cr);
02658
02659 if (same)
02660 {
02661
02662
02663 switch (cr->Kind())
02664 {
02665 case CK_CONST:
02666 case CK_RCONST:
02667 case CK_LDA:
02668 case CK_VAR:
02669 break;
02670
02671 case CK_IVAR:
02672 if (!lhs_of_store)
02673 {
02674 if (cr->Opr() == OPR_MLOAD)
02675 same =
02676 _all_same_occurs(cr->Mload_size(), FALSE, valnum, occ_cr);
02677 else if (cr->Opr() == OPR_ILOADX)
02678 same =
02679 _all_same_occurs(cr->Index(), FALSE, valnum, occ_cr);
02680 if (same)
02681 same =
02682 _all_same_occurs(cr->Ilod_base(), FALSE, valnum, occ_cr);
02683 }
02684 else
02685 {
02686 if (cr->Opr() == OPR_MLOAD)
02687 same =
02688 _all_same_occurs(cr->Mstore_size(), FALSE, valnum, occ_cr);
02689 else if (cr->Opr() == OPR_ILOADX)
02690 same =
02691 _all_same_occurs(cr->Index(), FALSE, valnum, occ_cr);
02692 if (same)
02693 same =
02694 _all_same_occurs(cr->Istr_base(), FALSE, valnum, occ_cr);
02695 }
02696 break;
02697
02698 case CK_OP:
02699 Is_True(cr->Opr() != OPR_ARRAY,
02700 ("VNFRE::all_same_occurs: reach an OPR_ARRAY node,"
02701 " this is a bug in the lowering process"));
02702 {
02703 for (INT32 i=0; same && i<cr->Kid_count(); i++)
02704 same = _all_same_occurs(cr->Opnd(i), FALSE, valnum, occ_cr);
02705 }
02706 break;
02707
02708 case CK_DELETED:
02709 default:
02710 FmtAssert(FALSE,
02711 ("VALNUM_FRE::_all_same_occurs(), unexpected kind 0x%x",
02712 cr->Kind()));
02713 break;
02714 }
02715 }
02716
02717 return same;
02718
02719 }
02720
02721
02722 BOOL
02723 VALNUM_FRE::_same_var_occurs(EXP_OCCURS *occ, const CODEREP *var_cr) const
02724 {
02725 BOOL same = (occ->Occurrence() == var_cr);
02726
02727 if (same && occ->Mult_real())
02728 {
02729
02730
02731
02732 VN_VALNUM valnum = get_valnum(occ->Occurrence()->Coderep_id());
02733 CODEREP *enclosure = _get_occur_cr(occ);
02734 STMTREP *stmt = occ->Stmt();
02735 BOOL lhs_of_store = (stmt->Lhs() == enclosure &&
02736 OPCODE_is_store(stmt->Op()));
02737
02738 same = _all_same_occurs(enclosure, lhs_of_store, valnum, var_cr);
02739 }
02740 return same;
02741 }
02742
02743
02744 void
02745 VALNUM_FRE::_get_worklist_info(EXP_WORKLST *w,
02746 BOOL &same_var_occurs,
02747 BOOL &save_use_occurs,
02748 BOOL &disabled_occurs) const
02749 {
02750
02751
02752
02753
02754
02755
02756
02757
02758
02759
02760
02761
02762
02763
02764
02765
02766
02767
02768
02769 EXP_OCCURS * const head_occ = _first_real_occur(w);
02770 CODEREP * const head_cr = head_occ->Occurrence();
02771 STMTREP * const head_stmt = head_occ->Enclosed_in_stmt();
02772 CODEREP * const head_stmt_lhs = head_stmt->Lhs();
02773
02774
02775
02776 disabled_occurs = (head_cr->Kind() == CK_LDA ||
02777 head_cr->Dtyp() == MTYPE_M);
02778 same_var_occurs = (head_cr->Kind() == CK_VAR &&
02779 _same_var_occurs(head_occ, head_cr));
02780 save_use_occurs = (head_occ != _last_real_occur(w) &&
02781 OPCODE_operator(head_stmt->Op()) == OPR_STID &&
02782 head_occ->Occurrence() == head_stmt->Rhs() &&
02783 head_stmt_lhs->Kind() == CK_VAR);
02784
02785 if (same_var_occurs || save_use_occurs || !disabled_occurs)
02786 {
02787
02788
02789 for (EXP_OCCURS *occ = head_occ->Next();
02790 (occ != NULL &&
02791 (same_var_occurs || save_use_occurs || !disabled_occurs));
02792 occ = occ->Next())
02793 {
02794 CODEREP * const cr = occ->Occurrence();
02795
02796 if (cr != head_stmt_lhs)
02797 save_use_occurs = FALSE;
02798 if (!_same_var_occurs(occ, head_cr))
02799 same_var_occurs = FALSE;
02800 if (cr->Kind() == CK_LDA || cr->Dtyp() == MTYPE_M)
02801 disabled_occurs = TRUE;
02802 }
02803 }
02804 }
02805
02806
02807 BOOL
02808 VALNUM_FRE::_is_vnfre_candidate(EXP_WORKLST *w) const
02809 {
02810
02811
02812
02813 const BOOL multiple_occurs =
02814 (_has_an_occur(w) &&
02815 (_first_real_occur(w) != _last_real_occur(w) ||
02816 _first_real_occur(w)->Mult_real()));
02817
02818 if (multiple_occurs)
02819 {
02820 BOOL same_var_occurs;
02821 BOOL save_use_occurs;
02822 BOOL disabled_occurs;
02823
02824 _get_worklist_info(w, same_var_occurs, save_use_occurs, disabled_occurs);
02825
02826 return (!same_var_occurs &&
02827 !save_use_occurs &&
02828 !disabled_occurs);
02829 }
02830 else
02831 {
02832 return FALSE;
02833 }
02834 }
02835
02836
02837
02838
02839
02840
02841 EXP_OCCURS *
02842 VALNUM_FRE::_append_phi_occurrence(EXP_PHI *phi, EXP_WORKLST *worklist)
02843 {
02844
02845
02846 EXP_OCCURS *occurs = _etable->Alloc_vnfre_occurs_node();
02847 occurs->Set_occurrence(worklist->Exp());
02848 occurs->Set_kind(EXP_OCCURS::OCC_PHI_OCCUR);
02849 occurs->Set_exp_phi(phi);
02850 _etable->Set_phi_result(phi, occurs);
02851
02852
02853
02854 worklist->Append_occurrence(occurs);
02855 return occurs;
02856 }
02857
02858
02859 EXP_OCCURS *
02860 VALNUM_FRE::_append_phi_pred_occurrence(BB_NODE *bb, EXP_WORKLST *worklist)
02861 {
02862
02863
02864 EXP_OCCURS *occurs = _etable->Alloc_vnfre_occurs_node();
02865 occurs->Set_occurrence(worklist->Exp());
02866 occurs->Set_kind(EXP_OCCURS::OCC_PHI_PRED_OCCUR);
02867 occurs->Set_enclose_bb(bb);
02868
02869
02870
02871 worklist->Append_occurrence(occurs);
02872 return occurs;
02873 }
02874
02875
02876 void
02877 VALNUM_FRE::_insert_valnum_phi(EXP_WORKLST *worklist)
02878 {
02879
02880
02881
02882
02883
02884
02885
02886 Is_True(worklist->Pre_kind() == PK_VNFRE,
02887 ("VALNUM_FRE::_insert_valnum_phi: Wrong kind"));
02888
02889 Is_Trace(_tracing,
02890 (TFile, "====== VALNUM_FRE::_insert_valnum_phi ======\n"));
02891 Is_Trace(_tracing,
02892 (TFile, "The real occurrence list is:\n"));
02893 Is_Trace_cmd(_tracing, worklist->Real_occurs().Print(TFile));
02894
02895 OPT_POOL_Push(_lpool, -1);
02896 {
02897 BB_NODE_SET &phi_list = _etable->Reuse_phi_list();
02898 BB_LIST_CONTAINER bb_worklist;
02899 EXP_OCCURS *exp_occ;
02900 EXP_OCCURS_ITER exp_occ_iter;
02901 BB_NODE *bb_orig;
02902 BB_NODE *bb_phi;
02903 BB_NODE_SET_ITER df_iter;
02904
02905
02906
02907
02908 FOR_ALL_NODE (exp_occ, exp_occ_iter,
02909 Init(worklist->Real_occurs().Head()))
02910 {
02911 bb_orig = exp_occ->Bb();
02912 FOR_ALL_ELEM (bb_phi, df_iter, Init(bb_orig->Dom_frontier()))
02913 {
02914 if (!phi_list.MemberP(bb_phi->Dom_dfs_id()))
02915 {
02916 Is_Trace(_tracing,
02917 (TFile, "------ Enter Phi-node: %d ------\n",
02918 bb_phi->Id()));
02919 phi_list.Union1D(bb_phi->Dom_dfs_id());
02920 bb_worklist.Append(bb_phi, _lpool);
02921 }
02922 }
02923 }
02924
02925
02926
02927 while (bb_orig = bb_worklist.Remove_head(_lpool))
02928 {
02929 FOR_ALL_ELEM (bb_phi, df_iter, Init(bb_orig->Dom_frontier()))
02930 {
02931 if (!phi_list.MemberP(bb_phi->Dom_dfs_id()))
02932 {
02933 Is_Trace(_tracing,
02934 (TFile, "------ Enter Phi-node: %d ------\n",
02935 bb_phi->Id()));
02936 phi_list.Union1D(bb_phi->Dom_dfs_id());
02937 bb_worklist.Append(bb_phi, _lpool);
02938 }
02939 }
02940 }
02941
02942
02943
02944
02945
02946
02947
02948
02949 IDTYPE dpo_id;
02950 FOR_ALL_NODE (dpo_id, df_iter, Init(&phi_list))
02951 {
02952 bb_phi = _etable->Cfg()->Dpo_Bb(dpo_id);
02953
02954 Is_Trace(_tracing,
02955 (TFile,
02956 "------ Generate EXP_PHI: %d ------\n", bb_phi->Id()));
02957
02958 EXP_PHI *new_phi =
02959 CXX_NEW(EXP_PHI(worklist->E_num() ,
02960 bb_phi->Phi_list()->In_degree(),
02961 bb_phi,
02962 _vpool),
02963 _vpool);
02964 EXP_OCCURS *new_occ = _append_phi_occurrence(new_phi, worklist);
02965
02966
02967
02968
02969 _etable->Set_dpo_phi_occurs(bb_phi, new_occ);
02970 bb_phi->Set_exp_phi(new_phi);
02971 }
02972
02973
02974
02975
02976 BB_LIST_ITER bb_iter;
02977 phi_list.ClearD();
02978 FOR_ALL_NODE (exp_occ,
02979 exp_occ_iter, Init(worklist->Phi_occurs().Head()))
02980 {
02981 bb_orig = exp_occ->Bb();
02982 FOR_ALL_ELEM (bb_phi, bb_iter, Init(bb_orig->Pred()))
02983 {
02984 Is_Trace(_tracing, (TFile, "------ Enter Phi-pred %d ------\n",
02985 bb_phi->Id()));
02986 phi_list.Union1D(bb_phi->Dom_dfs_id());
02987 }
02988 }
02989
02990
02991
02992
02993 FOR_ALL_NODE (dpo_id, df_iter, Init(&phi_list))
02994 {
02995 bb_orig = _etable->Cfg()->Dpo_Bb(dpo_id);
02996 Is_Trace(_tracing,
02997 (TFile,"------ Generate Phi-pred occurrence %d ------\n",
02998 bb_orig->Id()));
02999 EXP_OCCURS *phi_pred = _append_phi_pred_occurrence(bb_orig, worklist);
03000 FOR_ALL_ELEM (bb_phi, bb_iter, Init(bb_orig->Succ()))
03001 {
03002 EXP_PHI *exp_phi = bb_phi->Exp_phi();
03003 if (exp_phi != NULL)
03004 {
03005 INT32 opnd_num = bb_phi->Pred()->Pos(bb_orig);
03006 exp_phi->Set_pred(opnd_num, phi_pred);
03007 }
03008 }
03009 }
03010 }
03011 OPT_POOL_Pop(_lpool, -1);
03012 }
03013
03014
03015
03016
03017
03018
03019 inline void
03020 VALNUM_FRE::_create_new_version(EXP_OCCURS *occur,
03021 OCCURS_STACK &occurs_stack,
03022 EXP_WORKLST &worklist)
03023 {
03024 occur->Set_e_version(worklist.Cur_e_version());
03025 occurs_stack.push(occur);
03026 worklist.New_e_version();
03027 }
03028
03029
03030 void
03031 VALNUM_FRE::_rename_valnums(EXP_WORKLST &worklist, BOOL &renamed_ok)
03032 {
03033
03034
03035
03036
03037
03038
03039
03040
03041
03042
03043
03044
03045
03046
03047
03048
03049 OPT_STAB *opt_stab = _etable->Opt_stab();
03050 CODEREP *cr = worklist.Real_occurs().Head()->Occurrence();
03051
03052 renamed_ok = TRUE;
03053 OPT_POOL_Push(_lpool, -1);
03054 {
03055 OCCURS_VECTOR occurs_vec(0, (EXP_OCCURS*) NULL,
03056 OCCURS_VECTOR::allocator_type(_lpool));
03057 OCCURS_STACK occurs_stack(occurs_vec);
03058
03059
03060
03061 worklist.Init_e_version();
03062
03063
03064
03065 EXP_ALL_OCCURS_ITER exp_occ_iter(worklist.Real_occurs().Head(),
03066 NULL,
03067 worklist.Phi_occurs().Head(),
03068 worklist.Phi_pred_occurs().Head(),
03069 _etable->Exit_occurs().Head());
03070
03071 BOOL undef = FALSE;
03072 EXP_OCCURS *occur;
03073 FOR_ALL_NODE(occur, exp_occ_iter, Init())
03074 {
03075
03076
03077
03078 while (!occurs_stack.empty() &&
03079 !occurs_stack.top()->Bb()->Dominates(occur->Bb()))
03080 occurs_stack.pop();
03081
03082 switch (occur->Occ_kind())
03083 {
03084 case EXP_OCCURS::OCC_PHI_OCCUR:
03085
03086
03087
03088
03089 Is_True(occur->Exp_phi()->Result() == occur,
03090 ("OCC_PHI_OCCUR phi result is wrong."));
03091 _create_new_version(occur, occurs_stack, worklist);
03092 occur->Exp_phi()->Set_not_down_safe();
03093 break;
03094
03095 case EXP_OCCURS::OCC_REAL_OCCUR:
03096
03097
03098
03099
03100
03101
03102 if (_contains_undef_val(occur->Occurrence(), occur->Stmt()))
03103 {
03104 #ifdef Is_True_On
03105 Is_Trace(_tracing,
03106 (TFile, "-----------> "
03107 "VNFRE renaming undefined occurrence (Sid%d)\n",
03108 occur->Stmt()->Stmt_id()));
03109 Is_Trace_cmd(_tracing, occur->Occurrence()->Print(2, TFile));
03110 Is_Trace(_tracing, (TFile, "-----------\n"));
03111 Is_Trace_cmd(_tracing, fflush(TFile));
03112 #endif // Is_True_On
03113
03114
03115
03116
03117
03118 if (undef || occur->Mult_real())
03119 renamed_ok = FALSE;
03120 else
03121 undef = TRUE;
03122 }
03123
03124 if (occurs_stack.empty())
03125 _create_new_version(occur, occurs_stack, worklist);
03126 else
03127 {
03128
03129
03130 EXP_OCCURS *tos = occurs_stack.top();
03131 occur->Set_e_version(tos->E_version());
03132 occur->Set_def_occur(_def_occur(tos) != NULL?
03133 _def_occur(tos) : tos);
03134
03135
03136
03137
03138
03139
03140 if (tos->Occ_kind() != EXP_OCCURS::OCC_REAL_OCCUR)
03141 occurs_stack.push(occur);
03142 }
03143 break;
03144
03145 case EXP_OCCURS::OCC_PHI_PRED_OCCUR:
03146 {
03147
03148
03149
03150
03151 EXP_OCCURS *tos =
03152 (occurs_stack.empty()? NULL : occurs_stack.top());
03153
03154 BB_LIST_ITER bb_iter;
03155 BB_NODE *bb_phi;
03156 BB_NODE *bb_pred = occur->Bb();
03157
03158 FOR_ALL_ELEM (bb_phi, bb_iter, Init(bb_pred->Succ()))
03159 {
03160 INT opnd_num = bb_phi->Pred()->Pos(bb_pred);
03161 EXP_PHI *exp_phi = bb_phi->Exp_phi();
03162
03163
03164
03165 if (exp_phi != NULL)
03166 {
03167
03168
03169
03170
03171
03172 Is_True(exp_phi->E_num() == worklist.E_num(),
03173 ("ETABLE::Add_to_occ_freelist() did not "
03174 "correctly set bb->Exp_phi(); error in "
03175 "VALNUM_FRE::_rename_valnums!"));
03176
03177 if (tos != NULL)
03178 {
03179 if (tos->Occ_kind() == EXP_OCCURS::OCC_REAL_OCCUR)
03180 exp_phi->Set_has_real_occ(opnd_num);
03181
03182
03183
03184
03185 if (_def_occur(tos) != NULL)
03186 exp_phi->Set_opnd(opnd_num, _def_occur(tos));
03187 else
03188 exp_phi->Set_opnd(opnd_num, tos);
03189 }
03190 }
03191 }
03192 }
03193 break;
03194
03195 case EXP_OCCURS::OCC_EXIT_OCCUR:
03196 Is_True(occur->Bb()->Kind() == BB_EXIT, ("not an exit BB."));
03197
03198
03199
03200 break;
03201
03202 default:
03203 Is_True(FALSE,
03204 ("VALNUM_FRE::_rename_valnums, "
03205 "unknown occurrence kind: %d", occur->Occ_kind()));
03206 break;
03207 }
03208 }
03209 }
03210 OPT_POOL_Pop(_lpool, -1);
03211 }
03212
03213
03214
03215
03216
03217
03218 void
03219 VALNUM_FRE::_propagate_flags(EXP_WORKLST &worklist,
03220 BOOL &found_redundancy)
03221 {
03222
03223
03224
03225
03226
03227
03228
03229
03230
03231
03232
03233
03234
03235
03236
03237
03238
03239
03240
03241
03242
03243
03244
03245
03246
03247
03248
03249
03250
03251
03252
03253
03254
03255
03256
03257
03258
03259
03260
03261 worklist.Compute_fully_avail(_etable);
03262 worklist.Compute_fully_avail_stops(_etable, found_redundancy);
03263
03264 if (found_redundancy)
03265 {
03266 EXP_OCCURS *occ;
03267 EXP_OCCURS_ITER occ_iter;
03268
03269
03270
03271
03272 FOR_ALL_NODE (occ, occ_iter, Init(worklist.Phi_occurs().Head()))
03273 {
03274 EXP_PHI * const phi = occ->Exp_phi();
03275
03276
03277
03278 if (_is_fully_avail(phi))
03279 {
03280 if (!phi->Stops())
03281 {
03282 phi->Set_not_user_avail();
03283 phi->Set_cant_be_avail();
03284 }
03285 else
03286 {
03287 phi->Set_partial_avail();
03288 }
03289 }
03290 else
03291 {
03292 phi->Set_cant_be_avail();
03293 }
03294 }
03295 }
03296
03297 }
03298
03299
03300
03301
03302
03303
03304 void
03305 VALNUM_FRE::_remove_redundant_phi_nodes()
03306 {
03307
03308 Warn_todo("VALNUM_FRE::_remove_redundant_phi_nodes");
03309 }
03310
03311
03312
03313
03314
03315
03316 void
03317 VALNUM_FRE::_substitute_literal(VN_VALNUM v)
03318 {
03319
03320
03321
03322
03323
03324 VN_EXPR::PTR expr = _vn->valnum_expr(v);
03325 EXP_OCCURS * const head = _worklst(v)->Real_occurs().Head();
03326
03327 Is_True(head != NULL &&
03328 expr != NULL && expr->get_kind() == VN_EXPR::LITERAL,
03329 ("Erroneous application of VALNUM_FRE::_substitute_literal"));
03330
03331 TCON tcon = expr->get_tcon();
03332 EXP_OCCURS * occ;
03333 EXP_OCCURS_ITER occ_iter;
03334 FOR_ALL_NODE(occ, occ_iter, Init(head))
03335 {
03336 _etable->Replace_by_const(occ, tcon);
03337
03338 }
03339 }
03340
03341
03342
03343
03344
03345
03346 void
03347 VALNUM_FRE::_trace_header()
03348 {
03349 WN * const wn_tree = _comp_unit->Input_tree();
03350 const char * pu_name =
03351 (WN_opcode(wn_tree) == OPC_FUNC_ENTRY?
03352 ST_name(WN_st(wn_tree)) : "<region>");
03353
03354 if (pu_name == NULL)
03355 pu_name = "<unnamed pu>";
03356
03357 Is_Trace(_tracing,
03358 (TFile, "%sVNFRE (%s)\n%s", DBar, pu_name, DBar));
03359 VNFRE_TRACE(stderr, "%sVNFRE (%s)\n%s", DBar, pu_name, DBar);
03360 }
03361
03362
03363
03364
03365
03366
03367
03368 void
03369 VALNUM_FRE::_expression_redundancy_elimination(VN_VALNUM v)
03370 {
03371
03372
03373
03374
03375
03376
03377
03378
03379
03380
03381
03382
03383
03384
03385
03386
03387
03388
03389
03390
03391
03392
03393 EXP_WORKLST * const worklist = _worklst(v);
03394
03395
03396
03397
03398
03399 _etable->Init_vnfre_worklist(worklist, _exit_occurs);
03400
03401
03402
03403 SET_OPT_REPEAT_PHASE(_phi_placement_phase, "VNFRE: Valnum phi placement");
03404 _insert_valnum_phi(worklist);
03405
03406
03407
03408 SET_OPT_REPEAT_PHASE(_valnum_renaming_phase, "VNFRE: Valnum rename");
03409 BOOL renamed_ok;
03410 _rename_valnums(*worklist, renamed_ok);
03411
03412
03413
03414
03415 OPT_POOL_Push(_lpool, -1);
03416 if (renamed_ok)
03417 {
03418 BOOL found_redundancy;
03419
03420 SET_OPT_REPEAT_PHASE(_avail_insert_phase,
03421 "VNFRE: Valnum flag setting and propagation");
03422 _propagate_flags(*worklist, found_redundancy);
03423
03424 if (found_redundancy)
03425 {
03426 if (WOPT_Enable_Worklist_Pruning)
03427 {
03428 SET_OPT_REPEAT_PHASE(_worklst_prune_phase,
03429 "VNFRE: Phi/phi-pred pruning");
03430 worklist->Prune_phi_phi_pred(_etable);
03431 }
03432
03433
03434
03435 SET_OPT_REPEAT_PHASE(_finalize_phase,
03436 "VNFRE: Compute var save/reload");
03437
03438 BOOL optimization_needed =
03439 worklist->Compute_save_delete(_etable->Htable(), _etable, NULL);
03440
03441 if (optimization_needed)
03442 {
03443 if (WOPT_Enable_SSA_Minimization)
03444 {
03445 SET_OPT_REPEAT_PHASE(_ssa_min_phase, "VNFRE: SSA minimization");
03446 worklist->Minimize_temp_ssa(_etable, _tracing);
03447 }
03448
03449
03450
03451 SET_OPT_REPEAT_PHASE(_codemotion_phase, "VNFRE: CodeMotion");
03452 worklist->Generate_save_reload(_etable);
03453 SET_OPT_REPEAT_PHASE(_vnfre_misc_phase, "VNFRE: miscellaneous");
03454
03455
03456
03457 if (WOPT_Enable_Verify >= 4)
03458 {
03459 Is_True(_comp_unit->Verify_CODEMAP(), ("CODEMAP corrupted."));
03460 _comp_unit->Verify_version();
03461 }
03462 }
03463 else
03464 {
03465 VNFRE_TRACE(stderr,
03466 "VNFRE::expression_redundancy_elimination: "
03467 "skipping code motion step for valnum %d\n",
03468 v.ordinal());
03469 }
03470 }
03471 else
03472 {
03473 VNFRE_TRACE(stderr,
03474 "VNFRE::expression_redundancy_elimination: "
03475 "No redundancy for valnum %d\n",
03476 v.ordinal());
03477 }
03478 }
03479 else
03480 {
03481 Is_Trace(_tracing,
03482 (TFile, "---> VNFRE::expression_redundancy_elimination: "
03483 "Renaming failed for valnum %d\n",
03484 v.ordinal()));
03485 }
03486 OPT_POOL_Pop(_lpool, -1);
03487
03488
03489
03490
03491 _etable->Reset_vnfre_worklist();
03492
03493 }
03494
03495
03496
03497
03498
03499
03500
03501 void
03502 VNFRE::remove_redundancies(VN &vn,
03503 ETABLE &etable,
03504 COMP_UNIT *comp_unit)
03505 {
03506
03507
03508
03509
03510
03511
03512
03513 VALNUM_FRE fre(vn, etable, comp_unit);
03514
03515 VALNUM_FRE::Set_current(&fre);
03516 fre.apply();
03517 VALNUM_FRE::Set_current(NULL);
03518
03519 }
03520
03521
03522 UINT32
03523 VNFRE::get_valnum(const CODEREP *cr)
03524 {
03525 const VN::EXPRID id = cr->Coderep_id();
03526
03527 if (id == 0 || id > VALNUM_FRE::Current()->last_exprid())
03528 return VALNUM_FRE::Current()->compute_valnum(cr).ordinal();
03529 else
03530 return VALNUM_FRE::Current()->get_valnum(id).ordinal();
03531 }
03532
03533
03534 void
03535 VNFRE::add_valnum(const CODEREP *cr, UINT32 valnum)
03536 {
03537 const VN::EXPRID id = cr->Coderep_id();
03538
03539 Is_True(id != 0 &&
03540 valnum <= VALNUM_FRE::Current()->last_valnum().ordinal(),
03541 ("Illegal attempt to map coderep (%u) to valnum (%u) in VNFRE",
03542 id, VALNUM_FRE::Current()->last_valnum().ordinal()));
03543
03544 if (id > VALNUM_FRE::Current()->last_exprid())
03545 VALNUM_FRE::Current()->new_cr(cr, VN_VALNUM::Vn(valnum));
03546 else if (VALNUM_FRE::Current()->get_valnum(id).ordinal() != valnum)
03547 VALNUM_FRE::Current()->reset_valnum(cr, VN_VALNUM::Vn(valnum));
03548 }
03549
03550
03551 void
03552 VNFRE::replace_occurs(const CODEREP *old_cr,
03553 CODEREP *new_cr,
03554 const STMTREP *stmt)
03555 {
03556 if (old_cr != new_cr && !(old_cr->Non_leaf() && old_cr->Opr() == OPR_PARM))
03557 {
03558 VALNUM_FRE::Current()->replace_cr_in_stmt(old_cr, new_cr, stmt);
03559 }
03560 }
03561
03562
03563 void
03564 VNFRE::move_rhs_occurs(const STMTREP *old_stmt,
03565 STMTREP *new_stmt)
03566 {
03567 VALNUM_FRE::Current()->move_rhs_occurs(old_stmt, new_stmt);
03568 }
03569
03570
03571 void
03572 VNFRE::new_occurs(STMTREP *new_stmt)
03573 {
03574 INSERT_CR_OCCURS cr_inserter(VALNUM_FRE::Current());
03575 traverseSR(new_stmt, cr_inserter);
03576 }
03577
03578
03579 void
03580 VNFRE::delete_occurs(const EXP_OCCURS *occur,
03581 const CODEREP *within_cr)
03582 {
03583 VALNUM_FRE::Current()->delete_all_occurs(occur, within_cr);
03584 }
03585
03586
03587 EXP_WORKLST *
03588 VNFRE::get_worklst(const CODEREP *cr)
03589 {
03590 return
03591 (VALNUM_FRE::Current()->
03592 get_worklst(VALNUM_FRE::Current()->
03593 get_valnum(cr->Coderep_id())));
03594 }
03595
03596
03597
03598
03599
03600
03601 void COMP_UNIT::Do_vnfre(BOOL before_epre)
03602 {
03603
03604
03605 BOOL doit;
03606
03607 switch (WOPT_Enable_Value_Numbering)
03608 {
03609 case VNFRE_AFTER_EPRE:
03610 case VNFRE_SINGLE_PASS_AFTER_EPRE:
03611 doit = !before_epre;
03612 break;
03613 case VNFRE_BEFORE_AND_AFTER_EPRE:
03614 case VNFRE_SINGLE_PASS_BEFORE_AND_AFTER_EPRE:
03615 doit = TRUE;
03616 break;
03617 default:
03618 doit = FALSE;
03619 break;
03620 }
03621
03622 if (doit)
03623 {
03624 MEM_POOL etable_pool, phi_pool, etable_local_pool;
03625
03626 OPT_POOL_Initialize(&etable_pool, "etable pool", FALSE, -1);
03627 OPT_POOL_Initialize(&phi_pool, "phi pool", FALSE, -1);
03628 OPT_POOL_Initialize(&etable_local_pool, "etable local pool", FALSE, -1);
03629 OPT_POOL_Push(&etable_pool, -1);
03630 OPT_POOL_Push(&phi_pool, -1);
03631 OPT_POOL_Push(&etable_local_pool, -1);
03632
03633 {
03634 ETABLE etable(Cfg(), Opt_stab(), Htable(), Arule(), 10,
03635 &etable_pool, &phi_pool, &etable_local_pool,
03636 this, PK_VNFRE);
03637
03638 etable.Perform_VNFRE_optimization();
03639 }
03640
03641 OPT_POOL_Pop(&etable_local_pool, -1);
03642 OPT_POOL_Pop(&phi_pool, -1);
03643 OPT_POOL_Pop(&etable_pool, -1);
03644 OPT_POOL_Delete(&etable_local_pool, -1);
03645 OPT_POOL_Delete(&phi_pool, -1);
03646 OPT_POOL_Delete(&etable_pool, -1);
03647 }
03648 }
03649
03650
03651 void
03652 ETABLE::Perform_VNFRE_optimization(void)
03653 {
03654
03655
03656 const INT orig_coderep_id_cnt = Htable()->Coderep_id_cnt();
03657
03658 Is_True(Pre_kind() == PK_VNFRE,
03659 ("Illegal method EPRE::Perform_VNFRE_optimization"));
03660
03661
03662
03663
03664
03665 _lftr = CXX_NEW(LFTR(this, Htable(), Cfg(), LFTR_HASH_SIZE), Etable_pool());
03666 _str_red = NULL;
03667
03668 Cfg()->Dpo_vec();
03669 Cfg()->Reset_stmt_id();
03670
03671 SET_OPT_PHASE("Offline value numbering");
03672 {
03673
03674
03675 VN::VN_ALGORITHM vn_algo;
03676 switch (WOPT_Enable_Value_Numbering)
03677 {
03678 case VNFRE_AFTER_EPRE:
03679 case VNFRE_BEFORE_AND_AFTER_EPRE:
03680 vn_algo = VN::ITERATIVE;
03681 break;
03682 case VNFRE_SINGLE_PASS_AFTER_EPRE:
03683 case VNFRE_SINGLE_PASS_BEFORE_AND_AFTER_EPRE:
03684 vn_algo = VN::SINGLE_PASS;
03685 break;
03686 default:
03687 FmtAssert(FALSE,
03688 ("Unexpected VN_ALGORITHM in "
03689 "ETABLE::Perform_VNFRE_optimization()"));
03690 break;
03691 }
03692
03693
03694
03695 VN vn(vn_algo, Cfg(), Htable(), Etable_local_pool(), Etable_pool());
03696
03697
03698
03699
03700 if (Get_Trace(TP_GLOBOPT, CR_DUMP_FLAG))
03701 {
03702 vn.print(TFile);
03703 }
03704
03705
03706
03707 SET_OPT_PHASE("VNFRE");
03708 VNFRE::remove_redundancies(vn, *this, _comp_unit);
03709 }
03710
03711
03712
03713 if (Tracing())
03714 {
03715 fprintf(TFile, "%sAfter VNFRE\n%s", DBar, DBar);
03716 fprintf(TFile, "Statistics (all expressions): Insert Count %d, "
03717 "Save Count %d, Reload Count %d, Temp Phi Count %d, "
03718 "Hoisted Count %d\n",
03719 _num_inserted_saves, _num_cse_saves, _num_cse_reloads,
03720 _num_temp_phis, _num_hoisted);
03721 fprintf(TFile, "Coderep Statistics (entire PU): previous count: "
03722 "%d new count: %d\n",
03723 orig_coderep_id_cnt, Htable()->Coderep_id_cnt());
03724 fprintf(TFile, " Expr nodes changed to temps without rehashing: "
03725 "%d\n",
03726 _num_temp_owners);
03727 Cfg()->Print(TFile);
03728 #ifdef Is_True_On
03729 if (Get_Trace(TKIND_ALLOC, TP_WOPT1)) {
03730 MEM_Trace();
03731 }
03732 #endif
03733 }
03734
03735
03736 CXX_DELETE(_lftr,_etable_pool);
03737
03738 }
03739
03740
03741 static void
03742 Propagate_stops_for_fully_avail(EXP_PHI *phi)
03743 {
03744
03745
03746
03747 if (!phi->Not_user_avail() && !phi->Stops())
03748 {
03749 phi->Set_stops();
03750
03751 for (INT i = phi->Opnd_count() - 1; i >= 0; i--)
03752 {
03753 EXP_OCCURS *def = phi->Opnd(i);
03754
03755 if (def != NULL && def->Occ_kind() == EXP_OCCURS::OCC_PHI_OCCUR)
03756 Propagate_stops_for_fully_avail(def->Exp_phi());
03757 }
03758 }
03759 }
03760
03761
03762 void
03763 EXP_WORKLST::Compute_fully_avail_stops(ETABLE *etable, BOOL &found_redundancy)
03764 {
03765
03766
03767
03768 EXP_OCCURS *occ;
03769 EXP_OCCURS_ITER occ_iter;
03770
03771 FOR_ALL_NODE (occ, occ_iter, Init(Phi_occurs().Head()))
03772 occ->Exp_phi()->Reset_has_real_use();
03773
03774
03775
03776
03777 found_redundancy = FALSE;
03778 FOR_ALL_NODE (occ, occ_iter, Init(Real_occurs().Head()))
03779 {
03780 EXP_OCCURS * const def = occ->Def_occur();
03781
03782 if (occ->Mult_real())
03783 found_redundancy = TRUE;
03784
03785 if (def != NULL)
03786 {
03787 if (def->Occ_kind() == EXP_OCCURS::OCC_REAL_OCCUR)
03788 {
03789 if (def != occ)
03790 found_redundancy = TRUE;
03791 }
03792 else
03793 {
03794 EXP_PHI *phi = def->Exp_phi();
03795
03796 Propagate_stops_for_fully_avail(phi);
03797
03798 if (!phi->Not_user_avail())
03799 found_redundancy = TRUE;
03800 else if (phi->Has_real_use())
03801 found_redundancy = TRUE;
03802 else
03803 phi->Set_has_real_use();
03804 }
03805 }
03806 }
03807 }