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 #ifdef USE_PCH
00067 #include "opt_pch.h"
00068 #endif // USE_PCH
00069 #pragma hdrstop
00070
00071
00072 #define opt_ssu_CXX "opt_ssu.cxx"
00073
00074 #include "defs.h"
00075 #include "config.h"
00076 #include "errors.h"
00077 #include "erglob.h"
00078 #include "glob.h"
00079 #include "bb_node_set.h"
00080 #include "idx_32_set.h"
00081 #include "tracing.h"
00082
00083 #include "opt_defs.h"
00084 #include "opt_config.h"
00085 #include "opt_htable.h"
00086 #include "opt_util.h"
00087 #include "opt_ssa.h"
00088 #include "opt_mu_chi.h"
00089 #include "opt_wn.h"
00090 #include "opt_prop.h"
00091 #include "wn.h"
00092 #include "opt_alias_rule.h"
00093 #include "opt_etable.h"
00094 #include "opt_ssu.h"
00095
00096 #ifdef KEY
00097 static void
00098
00099
00100
00101
00102 Fix_var_mtypes(CODEREP *x, AUX_STAB_ENTRY *aux) {
00103 CODEREP_ITER cr_iter;
00104 CODEREP *cr;
00105 FOR_ALL_NODE(cr, cr_iter, Init(aux->Cr_list()))
00106 if (cr->Dtyp() != MTYPE_V && cr->Dtyp() != MTYPE_UNKNOWN) {
00107 x->Set_dtyp(cr->Dtyp());
00108 x->Set_dsctyp(cr->Dsctyp());
00109 }
00110 }
00111 #endif
00112
00113
00114
00115
00116
00117 EXP_WORKLST * SSU::SPRE_candidate(CODEREP *cr)
00118 {
00119 Is_True(cr->Kind() == CK_VAR,
00120 ("SSU::SPRE_candidate: parameter must be CK_VAR node"));
00121 AUX_STAB_ENTRY *aux= Opt_stab()->Aux_stab_entry( cr->Aux_id() );
00122 EXP_WORKLST *wk = aux->Spre_node();
00123 if (wk)
00124 return wk;
00125 if (aux->No_spre()) return NULL;
00126 if (!aux->Is_real_var() ||
00127 aux->No_register() ||
00128 !aux->Has_store_in_PU() ||
00129 aux->Is_volatile() ||
00130 ST_class(aux->St()) == CLASS_PREG ||
00131 cr->Is_flag_set(CF_IS_ZERO_VERSION) ||
00132 Opt_stab()->Is_varargs_func() && ST_sclass(aux->St()) == SCLASS_FORMAL) {
00133 aux->Set_no_spre();
00134 return NULL;
00135 }
00136
00137 wk = Etable()->Get_worklst(cr);
00138 aux->Set_spre_node(wk);
00139
00140
00141 if (aux->Home_sym() == 0) {
00142 #ifndef KEY
00143 Is_True(cr->Dtyp() != MTYPE_V && cr->Dtyp() != MTYPE_UNKNOWN,
00144 ("SSU::SPRE_candidate: dtyp is void or unknown"));
00145 #else
00146
00147 if (cr->Dtyp() == MTYPE_V || cr->Dtyp() == MTYPE_UNKNOWN ||
00148 cr->Dsctyp() == MTYPE_V || cr->Dsctyp() == MTYPE_UNKNOWN)
00149 Fix_var_mtypes(cr, aux);
00150 #endif
00151 WN *home_wn = cr->Rvi_home_wn(Opt_stab());
00152 AUX_ID home_auxid = Opt_stab()->Create_preg(cr->Dtyp(),aux->St_name(),home_wn);
00153
00154 aux = Opt_stab()->Aux_stab_entry( cr->Aux_id() );
00155 aux->Set_home_sym(home_auxid);
00156 Opt_stab()->Aux_stab_entry(home_auxid)->Set_home_sym(cr->Aux_id());
00157
00158 if (cr->Is_sign_extd())
00159 wk->Set_sign_extd();
00160 }
00161 else {
00162 if (Opt_stab()->Aux_stab_entry(aux->Home_sym())->LPRE_sign_extd())
00163 wk->Set_sign_extd();
00164 }
00165 wk->Set_preg(aux->Home_sym());
00166 if (wk->Iphi_bbs() == NULL) {
00167 wk->Set_iphi_bbs(CXX_NEW(BB_NODE_SET(Cfg()->Last_bb_id()+1, Cfg(),
00168 Loc_pool(), BBNS_EMPTY), Loc_pool()));
00169 wk->Set_temp_id(0);
00170 }
00171 return wk;
00172 }
00173
00174
00175
00176
00177
00178
00179 void SSU::Insert_iphis_recursive(EXP_WORKLST *wk, BB_NODE *bb)
00180 {
00181 EXP_OCCURS *iphi;
00182 BB_NODE *bby;
00183 BB_NODE_SET_ITER bns_iter;
00184
00185 if (wk->Temp_id() == bb->Id())
00186 return;
00187
00188
00189 FOR_ALL_ELEM (bby, bns_iter, Init(bb->Rcfg_dom_frontier())) {
00190 if (wk->Iphi_bbs()->MemberP(bby))
00191 continue;
00192 wk->Iphi_bbs()->Union1D(bby);
00193 iphi = Etable()->New_phi_occurrence(wk, Mem_pool(), bby);
00194 iphi->Exp_phi()->Set_reverse_phi();
00195 bby->Iphi_list()->Append(iphi->Exp_phi());
00196
00197 Insert_iphis_recursive(wk, bby);
00198 }
00199 }
00200
00201
00202
00203
00204
00205 inline void SSU::Make_non_postdominated_iphi_opnd_null(BB_NODE *iphibb,
00206 EXP_PHI *iphi)
00207 {
00208 BB_NODE *bbsucc;
00209 BB_LIST_ITER bb_list_iter;
00210 INT32 pos = 0;
00211 FOR_ALL_ELEM(bbsucc, bb_list_iter, Init(iphibb->Succ())) {
00212 if (! iphibb->Postdominates(bbsucc)) {
00213 iphi->Set_null_ssu_version(pos);
00214 }
00215 pos++;
00216 }
00217 }
00218
00219
00220
00221
00222
00223
00224
00225 BOOL SSU::Find_intervening_iphi(EXP_WORKLST *wk,
00226 CODEREP *v,
00227 BB_NODE *usebb)
00228 {
00229 if (wk == NULL)
00230 return FALSE;
00231 if (v->Is_flag_set(CF_DEF_BY_CHI)) {
00232 STMTREP *stmt = v->Defstmt();
00233 if (! OPERATOR_is_scalar_store (stmt->Opr()))
00234 return FALSE;
00235 }
00236 EXP_PHI *iphi;
00237 EXP_PHI_LIST_ITER iphi_iter;
00238 BB_NODE *bby;
00239 BB_NODE_SET_ITER bns_iter;
00240 BB_NODE *defbb = v->Defbb();
00241 BOOL found = FALSE;
00242
00243
00244 FOR_ALL_ELEM (bby, bns_iter, Init(defbb->Rcfg_dom_frontier())) {
00245 if (bby->Postdominates(defbb) && usebb->Postdominates(bby) && bby != usebb){
00246 if (wk->Iphi_bbs()->MemberP(bby)) {
00247 found = TRUE;
00248
00249 FOR_ALL_NODE(iphi, iphi_iter, Init(bby->Iphi_list())) {
00250 if (iphi->Result()->Spre_wk() == wk)
00251 break;
00252 }
00253 Make_non_postdominated_iphi_opnd_null(bby, iphi);
00254 }
00255 }
00256 }
00257 return found;
00258 }
00259
00260
00261
00262
00263
00264
00265
00266 void SSU::Make_diff_ssu_version_at_phi(EXP_WORKLST *wk,
00267 BB_NODE *defbb,
00268 PHI_NODE *phi)
00269 {
00270 BB_NODE *bbpred;
00271 BB_LIST_ITER bb_list_iter;
00272 EXP_PHI *iphi;
00273 EXP_PHI_LIST_ITER iphi_iter;
00274 CODEREP *opnd;
00275 POINTS_TO *points_to = Opt_stab()->Points_to(phi->Aux_id());
00276 INT32 pos = 0;
00277 phi->Set_null_ssu_processed();
00278 FOR_ALL_ELEM(bbpred, bb_list_iter, Init(defbb->Pred())) {
00279 if (wk->Iphi_bbs()->MemberP(bbpred)) {
00280
00281
00282 INT32 pos2 = bbpred->Succ()->Pos(defbb);
00283
00284 FOR_ALL_NODE(iphi, iphi_iter, Init(bbpred->Iphi_list())) {
00285 EXP_WORKLST *wk2 = iphi->Result()->Spre_wk();
00286 if (wk2 == wk)
00287 iphi->Set_null_ssu_version(pos2);
00288 else {
00289 POINTS_TO *iphi_points_to = Opt_stab()->Points_to(wk2->Exp()->Aux_id());
00290 if (Opt_stab()->Rule()->Aliased_Memop_By_Analysis(points_to,
00291 iphi_points_to))
00292 iphi->Set_null_ssu_version(pos2);
00293 }
00294 }
00295 }
00296 else {
00297 opnd = phi->OPND(pos);
00298 Make_diff_ssu_version(wk, opnd, bbpred, FALSE);
00299 }
00300 pos++;
00301 }
00302 }
00303
00304
00305
00306
00307 void SSU::Check_iphi_presence(EXP_WORKLST *wk, BB_NODE *iphibb)
00308 {
00309 if (! wk->Iphi_bbs()->MemberP(iphibb)) {
00310
00311 wk->Iphi_bbs()->Union1D(iphibb);
00312 EXP_OCCURS *iphiocc = Etable()->New_phi_occurrence(wk, Mem_pool(), iphibb);
00313 EXP_PHI *iphi = iphiocc->Exp_phi();
00314 iphi->Set_reverse_phi();
00315 iphibb->Iphi_list()->Append(iphi);
00316
00317 Insert_iphis_recursive(wk, iphibb);
00318 }
00319 }
00320
00321
00322
00323
00324
00325
00326 void SSU::Make_null_ssu_version_in_iphi_for_e_num_set(BB_NODE *iphibb,
00327 BB_NODE *usebb)
00328 {
00329 EXP_PHI *iphi;
00330 EXP_PHI_LIST_ITER iphi_iter;
00331 EXP_WORKLST *wk;
00332
00333 BB_NODE *bbsucc;
00334 BB_LIST_ITER bb_list_iter;
00335 INT32 pos = 0;
00336
00337 FOR_ALL_ELEM(bbsucc, bb_list_iter, Init(iphibb->Succ())) {
00338 if (usebb->Postdominates(bbsucc)) {
00339
00340
00341 FOR_ALL_NODE(iphi, iphi_iter, Init(iphibb->Iphi_list())) {
00342 wk = iphi->Result()->Spre_wk();
00343 if (_e_num_set->MemberP(wk->E_num())) {
00344 iphi->Set_null_ssu_version(pos);
00345 #ifdef Is_True_On
00346 if (Get_Trace(TP_GLOBOPT, SPRE_DUMP_FLAG))
00347 fprintf(TFile,
00348 "SSU: E_num %d iphi at BB%d pos %d made null ssu version\n",
00349 wk->E_num(), iphibb->Id(), pos);
00350 #endif
00351 }
00352 }
00353 }
00354 pos++;
00355 }
00356 }
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368 void SSU::Make_diff_ssu_version(EXP_WORKLST *wk,
00369 CODEREP *v,
00370 BB_NODE *usebb,
00371 BOOL only_itself)
00372 {
00373 STMTREP *stmt;
00374 CHI_NODE *cnode;
00375 CHI_LIST_ITER chi_iter;
00376 EXP_WORKLST *wk2;
00377
00378 if (v->Is_flag_set(CF_IS_ZERO_VERSION))
00379 return;
00380 BB_NODE *defbb = v->Defbb();
00381 if (defbb == NULL) {
00382 Is_True(v->Is_var_volatile(),
00383 ("SSU::Make_diff_ssu_version: variable has no def"));
00384 return;
00385 }
00386 if (usebb->Postdominates(defbb) || wk == NULL) {
00387 if (v->Is_flag_set(CF_DEF_BY_PHI)) {
00388 PHI_NODE *phi = v->Defphi();
00389
00390 if (wk == NULL) {
00391 if (! phi->Null_ssu_processed()) {
00392 phi->Set_null_ssu_processed();
00393
00394 BB_LIST_ITER bb_list_iter;
00395 BB_NODE *bbpred;
00396 CODEREP *opnd;
00397 INT32 pos = 0;
00398 FOR_ALL_ELEM(bbpred, bb_list_iter, Init(defbb->Pred())) {
00399 opnd = phi->OPND(pos);
00400 Make_diff_ssu_version(NULL, opnd, bbpred, FALSE);
00401 pos++;
00402 }
00403 }
00404 return;
00405 }
00406
00407 if (! phi->Null_ssu_processed() &&
00408 ! Find_intervening_iphi(wk, v, usebb))
00409 Make_diff_ssu_version_at_phi(wk, defbb, phi);
00410 }
00411 else if (v->Is_flag_set(CF_DEF_BY_CHI)) {
00412 stmt = v->Defstmt();
00413 if (OPERATOR_is_scalar_store (stmt->Opr()) &&
00414 ! stmt->Is_diff_ssu_version()) {
00415 CODEREP *lhs = stmt->Lhs();
00416 wk2 = Opt_stab()->Aux_stab_entry(lhs->Aux_id())->Spre_node();
00417 if (! Find_intervening_iphi(wk2, lhs, usebb))
00418 stmt->Set_diff_ssu_version();
00419 }
00420 BOOL first_one = TRUE;
00421 FOR_ALL_NODE(cnode, chi_iter, Init(stmt->Chi_list())) {
00422 if (! only_itself || only_itself && cnode->RESULT() == v) {
00423 if (cnode->Ssu_processed() || ! cnode->Live() ||
00424 cnode->Aux_id() == Opt_stab()->Return_vsym() ||
00425 cnode->RESULT()->Is_flag_set(CF_IS_ZERO_VERSION) ||
00426 cnode->RESULT()->Is_flag_set(CF_INCOMPLETE_USES))
00427 continue;
00428 wk2 = Opt_stab()->Aux_stab_entry(cnode->Aux_id())->Spre_node();
00429 if (wk2 == NULL) {
00430
00431 cnode->Set_ssu_processed(TRUE);
00432 Make_diff_ssu_version(NULL, cnode->OPND(), defbb, ! first_one);
00433 first_one = FALSE;
00434 }
00435 else if (! Find_intervening_iphi(wk2, cnode->RESULT(), usebb)) {
00436 cnode->Set_ssu_processed(TRUE);
00437
00438 Make_diff_ssu_version(wk2, cnode->OPND(), defbb, ! first_one);
00439 first_one = FALSE;
00440 }
00441 if (only_itself)
00442 break;
00443 }
00444 }
00445 }
00446 else {
00447 stmt = v->Defstmt();
00448 if (wk != NULL && ! stmt->Is_iphi_inserted()) {
00449 Insert_iphis_recursive(wk, defbb);
00450 stmt->Set_iphi_inserted();
00451 }
00452 if (! stmt->Is_diff_ssu_version() &&
00453 ! Find_intervening_iphi(wk, v, usebb))
00454 stmt->Set_diff_ssu_version();
00455 if (! only_itself) {
00456 BOOL first_one = TRUE;
00457 FOR_ALL_NODE(cnode, chi_iter, Init(stmt->Chi_list())) {
00458 if (cnode->Ssu_processed() || ! cnode->Live() ||
00459 cnode->RESULT()->Is_flag_set(CF_IS_ZERO_VERSION) ||
00460 cnode->RESULT()->Is_flag_set(CF_INCOMPLETE_USES) ||
00461 Opt_stab()->Is_virtual(cnode->Aux_id()) &&
00462 ! Opt_stab()->Is_real_var(cnode->Aux_id()))
00463 continue;
00464 wk2 = Opt_stab()->Aux_stab_entry(cnode->Aux_id())->Spre_node();
00465 if (! Find_intervening_iphi(wk2, cnode->RESULT(), usebb)) {
00466 cnode->Set_ssu_processed(TRUE);
00467
00468 Make_diff_ssu_version(wk2, cnode->OPND(), defbb, ! first_one);
00469 first_one = FALSE;
00470 }
00471 }
00472 }
00473 }
00474 }
00475 else {
00476 if (_make_diff_ssu_version_called_in_bb[usebb->Id()]->MemberP(v->Aux_id()))
00477 return;
00478
00479 _e_num_set->ClearD();
00480
00481
00482 BB_NODE *iphibb;
00483 BB_NODE_SET_ITER bns_iter;
00484 if (wk != NULL) {
00485 _e_num_set->Union1D(wk->E_num());
00486
00487 FOR_ALL_ELEM(iphibb, bns_iter, Init(usebb->Rcfg_dom_frontier()))
00488 Check_iphi_presence(wk, iphibb);
00489 }
00490
00491 if (only_itself || wk == NULL || v->Points_to(Opt_stab())->No_alias())
00492 ;
00493 else {
00494 AUX_ID st_idx = v->Aux_id();
00495 AUX_STAB_ENTRY *aux= Opt_stab()->Aux_stab_entry(st_idx);
00496
00497 if (aux->Is_real_var()) {
00498 AUX_ID cur_idx = aux->St_group();
00499
00500 while (cur_idx && cur_idx != st_idx) {
00501 aux = Opt_stab()->Aux_stab_entry(cur_idx);
00502 wk2 = aux->Spre_node();
00503 if (wk2 != NULL) {
00504 _e_num_set->Union1D(wk2->E_num());
00505 _make_diff_ssu_version_called_in_bb[usebb->Id()]->Union1D(cur_idx);
00506 FOR_ALL_ELEM(iphibb, bns_iter, Init(usebb->Rcfg_dom_frontier()))
00507 Check_iphi_presence(wk2, iphibb);
00508 }
00509 cur_idx = aux->St_group();
00510 }
00511 }
00512
00513 if (aux->Is_virtual() && aux->Aux_id_list() != NULL) {
00514 AUX_ID_LIST_ITER id_list_iter;
00515 AUX_ID_NODE *id_node;
00516 FOR_ALL_ELEM(id_node, id_list_iter, Init(aux->Aux_id_list())) {
00517 if ( (IDX_32)(id_node->Aux_id()) != ILLEGAL_BP ) {
00518 aux = Opt_stab()->Aux_stab_entry(id_node->Aux_id());
00519 wk2 = aux->Spre_node();
00520 if (wk2 != NULL) {
00521 _e_num_set->Union1D(wk2->E_num());
00522 _make_diff_ssu_version_called_in_bb[usebb->Id()]->Union1D(id_node->Aux_id());
00523 FOR_ALL_ELEM(iphibb, bns_iter, Init(usebb->Rcfg_dom_frontier()))
00524 Check_iphi_presence(wk2, iphibb);
00525 }
00526 }
00527 }
00528 }
00529 _make_diff_ssu_version_called_in_bb[usebb->Id()]->Union1D(st_idx);
00530 }
00531
00532
00533
00534
00535 FOR_ALL_ELEM(iphibb, bns_iter, Init(usebb->Rcfg_dom_frontier()))
00536 Make_null_ssu_version_in_iphi_for_e_num_set(iphibb, usebb);
00537 }
00538 }
00539
00540
00541
00542
00543 void SSU::Traverse_mu_read(MU_LIST *mu_list, BB_NODE *bb)
00544 {
00545 Is_True(mu_list != NULL, ("SSU::Traverse_mu_read: Null mu_list ptr"));
00546
00547 MU_LIST_ITER mu_iter;
00548 MU_NODE *mnode;
00549
00550 FOR_ALL_NODE( mnode, mu_iter, Init(mu_list) ) {
00551 if (mnode->Aux_id() == Opt_stab()->Return_vsym())
00552 continue;
00553 EXP_WORKLST *wk = SPRE_candidate(mnode->OPND());
00554 if (wk != NULL) {
00555 Make_diff_ssu_version(wk, mnode->OPND(), bb, FALSE);
00556 if (wk->Temp_id() != bb->Id() &&
00557 ! mnode->OPND()->Is_flag_set(CF_IS_ZERO_VERSION))
00558
00559 wk->Set_temp_id(bb->Id());
00560 }
00561 else Make_diff_ssu_version(NULL, mnode->OPND(), bb, FALSE);
00562 }
00563 }
00564
00565
00566
00567
00568
00569
00570
00571
00572 void SSU::Traverse_cr_rw(CODEREP *cr,
00573 BB_NODE *bb,
00574 BOOL is_store)
00575 {
00576 switch (cr->Kind()) {
00577
00578 case CK_CONST:
00579 case CK_RCONST:
00580 case CK_LDA:
00581 break;
00582
00583 case CK_VAR:
00584 { EXP_WORKLST *wk = SPRE_candidate(cr);
00585 if (wk != NULL) {
00586 if (is_store && ! cr->Defstmt()->Is_iphi_inserted()) {
00587 Insert_iphis_recursive(wk, bb);
00588 cr->Defstmt()->Set_iphi_inserted();
00589 }
00590 if (! is_store)
00591 Make_diff_ssu_version(wk, cr, bb, FALSE);
00592
00593 if (wk->Temp_id() != bb->Id())
00594
00595 wk->Set_temp_id(bb->Id());
00596 }
00597 else if (! is_store && ! cr->Points_to(Opt_stab())->No_alias())
00598 Make_diff_ssu_version(NULL, cr, bb, FALSE);
00599 break;
00600 }
00601
00602 case CK_IVAR:
00603 {
00604 #ifdef KEY
00605 Traverse_cr_rw( ! is_store ?
00606 #else
00607 Traverse_cr_rw( cr->Ilod_base() ?
00608 #endif
00609 cr->Ilod_base() : cr->Istr_base(), bb, FALSE);
00610 if ( cr->Opr() == OPR_MLOAD ) {
00611 Traverse_cr_rw( cr->Mload_size() ?
00612 cr->Mload_size() : cr->Mstore_size(), bb, FALSE);
00613 }
00614 if ( cr->Opr() == OPR_ILOADX ) {
00615 Traverse_cr_rw( cr->Index(), bb, FALSE);
00616 }
00617 if ( cr->Ivar_mu_node() != NULL ) {
00618 MU_LIST mu_list( cr->Ivar_mu_node() );
00619 Traverse_mu_read( &mu_list, bb );
00620 }
00621 }
00622 break;
00623
00624 case CK_OP:
00625 {
00626 for ( INT32 i = 0; i < cr->Kid_count(); ++i ) {
00627 Traverse_cr_rw( cr->Opnd(i), bb, FALSE);
00628 }
00629 }
00630 break;
00631 default:
00632 Is_True(0, ("SSU::Traverse_cr_rw: unexpected kind 0x%x", cr->Kind()));
00633 }
00634
00635 }
00636
00637
00638
00639
00640
00641
00642
00643
00644
00645
00646
00647
00648
00649
00650
00651 void SSU::Iphi_insertion(void)
00652 {
00653 DPOBB_ITER cfg_iter(Cfg(), TRUE);
00654 BB_NODE *bb;
00655 EXP_WORKLST *wk;
00656
00657 FOR_ALL_ELEM ( bb, cfg_iter, Init() ) {
00658 STMTREP_ITER stmt_iter(bb->Stmtlist());
00659 STMTREP *stmt;
00660 FOR_ALL_NODE ( stmt, stmt_iter, Init() ) {
00661
00662 if (stmt->Has_mu()) {
00663 MU_LIST *mu_list = stmt->Mu_list();
00664 if ( mu_list != NULL ) {
00665 Traverse_mu_read( mu_list, bb );
00666 }
00667 }
00668
00669 CODEREP *rhs = stmt->Rhs();
00670 CODEREP *lhs = stmt->Lhs();
00671
00672
00673 if ( rhs )
00674 Traverse_cr_rw( stmt->Rhs(), bb, FALSE);
00675
00676
00677 if ( lhs ) {
00678 Traverse_cr_rw( lhs, bb, TRUE);
00679
00680 if (OPERATOR_is_scalar_store (stmt->Opr()))
00681 stmt->Reset_RHS_saved_saved_RHS();
00682 }
00683
00684
00685 if (stmt->Has_chi()) {
00686 CHI_LIST_ITER chi_iter;
00687 CHI_NODE *cnode;
00688 CHI_LIST *chi_list = stmt->Chi_list();
00689 FOR_ALL_NODE( cnode, chi_iter, Init(chi_list)) {
00690 if (! cnode->Live() ||
00691 ! (cnode->RESULT()->Is_flag_set(CF_IS_ZERO_VERSION) ||
00692 cnode->RESULT()->Is_flag_set(CF_INCOMPLETE_USES)))
00693 continue;
00694 stmt->Set_diff_ssu_version();
00695 wk = SPRE_candidate(cnode->OPND());
00696 Make_diff_ssu_version(wk, cnode->OPND(), bb, FALSE);
00697
00698
00699 }
00700 }
00701 }
00702
00703
00704 BB_LIST_ITER bb_iter;
00705 BB_NODE *succ;
00706 FOR_ALL_ELEM(succ, bb_iter, Init(bb->Succ())) {
00707 PHI_NODE *phi;
00708 PHI_LIST_ITER phi_iter;
00709 INT32 pos = succ->Pred()->Pos(bb);
00710 FOR_ALL_ELEM (phi, phi_iter, Init(succ->Phi_list())) {
00711 if (phi->Live() &&
00712 (phi->RESULT()->Is_flag_set(CF_IS_ZERO_VERSION) ||
00713 phi->RESULT()->Is_flag_set(CF_INCOMPLETE_USES))) {
00714 wk = SPRE_candidate(phi->OPND(pos));
00715 Make_diff_ssu_version(wk, phi->OPND(pos), bb, FALSE);
00716 }
00717 }
00718 }
00719 }
00720 }
00721
00722
00723
00724
00725 void
00726 inline SSU::Reset_tos_downsafe(void)
00727 {
00728
00729
00730
00731 EXP_WORKLST *wk;
00732 EXP_WORKLST_ITER worklst_iter(Etable()->Exp_worklst());
00733 FOR_ALL_NODE(wk, worklst_iter, Init()) {
00734 if (! wk->Spre_stack()->Is_Empty() &&
00735 wk->Spre_stack()->Top()->Occ_kind() == EXP_OCCURS::OCC_PHI_OCCUR )
00736 wk->Spre_stack()->Top()->Exp_phi()->Set_not_down_safe();
00737 }
00738 }
00739
00740
00741
00742
00743
00744 void
00745 SSU::Propagate_occurrences(EXP_OCCURS *iphi_occ, CODEREP *cr)
00746 {
00747 EXP_PHI *iphi = iphi_occ->Exp_phi();
00748 for (INT opnd_num = 0; opnd_num < iphi->Opnd_count(); opnd_num++) {
00749 EXP_OCCURS *opnd = iphi->Opnd(opnd_num);
00750 if (opnd != NULL && opnd->Occ_kind() == EXP_OCCURS::OCC_PHI_OCCUR &&
00751 opnd->Occurrence() == NULL) {
00752 opnd->Set_occurrence(cr);
00753 Propagate_occurrences(opnd, cr);
00754 }
00755 }
00756 }
00757
00758
00759
00760
00761
00762 void SSU::Rename(BB_NODE *bb)
00763 {
00764 BB_LIST_ITER bb_iter;
00765 BB_NODE *pred, *pdom_bb;
00766 BB_LIST_ITER pdom_bb_iter;
00767 INT32 pos;
00768 STMTREP *stmt;
00769 STMTREP_ITER stmt_iter(bb->Stmtlist());
00770 EXP_PHI *iphi;
00771 EXP_PHI_LIST_ITER iphi_iter;
00772 EXP_OCCURS *occur;
00773 EXP_OCCURS *tos;
00774 AUX_STAB_ENTRY *psym;
00775 EXP_WORKLST *wk;
00776
00777
00778 FOR_ALL_NODE(iphi, iphi_iter, Init(bb->Iphi_list())) {
00779 occur = iphi->Result();
00780 wk = occur->Spre_wk();
00781 if (wk->Spre_stack() != NULL) {
00782
00783 occur->Set_e_version(wk->Cur_e_version());
00784 wk->New_e_version();
00785
00786 wk->Spre_stack()->Push(occur);
00787
00788 wk->SPRE_append_occurrence(occur);
00789 }
00790 }
00791
00792
00793
00794 FOR_ALL_NODE_REVERSE(stmt, stmt_iter, Init()) {
00795
00796 if (OPERATOR_is_scalar_store (stmt->Opr())) {
00797 psym = Opt_stab()->Aux_stab_entry(stmt->Lhs()->Aux_id());
00798 wk = psym->Spre_node();
00799 if (wk != NULL) {
00800 Is_True(stmt->Lhs()->Aux_id() == wk->Exp()->Aux_id(),
00801 ("SSU::Rename: inconsistent aux_id found"));
00802 if (! wk->Spre_stack()->Is_Empty())
00803 tos = wk->Spre_stack()->Top();
00804 else tos = NULL;
00805
00806 if (tos != NULL && tos->Occ_kind() == EXP_OCCURS::OCC_PHI_OCCUR &&
00807 tos->Occurrence() == NULL)
00808 tos->Set_occurrence(stmt->Lhs());
00809 if (stmt->Is_diff_ssu_version() || tos == NULL) {
00810
00811 if (tos != NULL && tos->Occ_kind() == EXP_OCCURS::OCC_PHI_OCCUR)
00812 tos->Exp_phi()->Set_not_down_safe();
00813
00814 occur = _etable->Append_spre_real_occurrence(stmt, wk);
00815 wk->Spre_stack()->Push(occur);
00816
00817 occur->Set_e_version(wk->Cur_e_version());
00818 wk->New_e_version();
00819 }
00820 else {
00821
00822 occur = _etable->Append_spre_real_occurrence(stmt, wk);
00823 occur->Set_e_version(tos->E_version());
00824 occur->Set_def_occur(tos);
00825
00826 if (tos->Occ_kind() == EXP_OCCURS::OCC_PHI_OCCUR) {
00827 wk->Spre_stack()->Push(occur);
00828 }
00829 else {
00830
00831
00832 if (tos->Def_occur() != NULL)
00833 occur->Set_def_occur(tos->Def_occur());
00834 }
00835 }
00836 }
00837 }
00838
00839 if (stmt->Has_chi()) {
00840 CHI_LIST_ITER chi_iter;
00841 CHI_NODE *cnode;
00842 CHI_LIST *chi_list = stmt->Chi_list();
00843 FOR_ALL_NODE( cnode, chi_iter, Init(chi_list)) {
00844 psym = Opt_stab()->Aux_stab_entry(cnode->Aux_id());
00845 wk = psym->Spre_node();
00846 if (wk == NULL)
00847 continue;
00848
00849 if (! wk->Spre_stack()->Is_Empty()) {
00850
00851 EXP_OCCURS *item = wk->Spre_stack()->Top();
00852 if (item->Occ_kind() == EXP_OCCURS::OCC_PHI_OCCUR) {
00853 if (cnode->Live() && item->Occurrence() == NULL)
00854 item->Set_occurrence(cnode->RESULT());
00855
00856 item->Exp_phi()->Set_not_down_safe();
00857 item->Exp_phi()->Set_dead_phi_region();
00858
00859 }
00860 }
00861 }
00862 }
00863 }
00864
00865
00866 PHI_NODE *phi;
00867 PHI_LIST_ITER phi_iter;
00868 FOR_ALL_ELEM(phi, phi_iter, Init(bb->Phi_list())) {
00869 psym = Opt_stab()->Aux_stab_entry(phi->Aux_id());
00870 wk = psym->Spre_node();
00871 if (wk == NULL)
00872 continue;
00873 if (! wk->Spre_stack()->Is_Empty()) {
00874
00875 EXP_OCCURS *item = wk->Spre_stack()->Top();
00876 if (item->Occ_kind() == EXP_OCCURS::OCC_PHI_OCCUR) {
00877 if (! phi->Live() ||
00878 phi->RESULT()->Is_flag_set(CF_IS_ZERO_VERSION) ||
00879 phi->RESULT()->Is_flag_set(CF_INCOMPLETE_USES)) {
00880
00881
00882 item->Exp_phi()->Set_not_down_safe();
00883 item->Exp_phi()->Set_dead_phi_region();
00884 }
00885 else if (item->Occurrence() == NULL) {
00886 item->Set_occurrence(phi->RESULT());
00887
00888 PHI_OPND_ITER phi_opnd_iter(phi);
00889 CODEREP *opnd;
00890 FOR_ALL_ELEM(opnd, phi_opnd_iter, Init()) {
00891 if (opnd->Is_flag_set(CF_IS_ZERO_VERSION)) {
00892 item->Exp_phi()->Set_not_down_safe();
00893 break;
00894 }
00895 }
00896 }
00897 }
00898 }
00899 }
00900
00901 if (bb == Cfg()->Fake_exit_bb()) {
00902 }
00903 else if (bb->Pred() == NULL) {
00904
00905
00906
00907
00908
00909 Reset_tos_downsafe();
00910 }
00911 else {
00912
00913 FOR_ALL_ELEM(pred, bb_iter, Init(bb->Pred())) {
00914 pos = pred->Succ()->Pos(bb);
00915 FOR_ALL_NODE(iphi, iphi_iter, Init(pred->Iphi_list())) {
00916 occur = iphi->Result();
00917 wk = occur->Spre_wk();
00918 STACK<EXP_OCCURS*> *spre_stack = wk->Spre_stack();
00919 if (spre_stack != NULL) {
00920 if (iphi->Null_ssu_version(pos)) {
00921 if (! spre_stack->Is_Empty() &&
00922 spre_stack->Top()->Occ_kind() == EXP_OCCURS::OCC_PHI_OCCUR)
00923 spre_stack->Top()->Exp_phi()->Set_not_down_safe();
00924 }
00925 else {
00926
00927 Is_True(occur->Exp_phi()->Opnd(pos) == NULL,
00928 ("SSU::Rename: at iphi succ, iphi operand not null"));
00929 if (! spre_stack->Is_Empty()) {
00930 occur->Exp_phi()->Set_opnd(pos, spre_stack->Top());
00931
00932
00933 if (spre_stack->Top()->Occ_kind()==EXP_OCCURS::OCC_REAL_OCCUR) {
00934 occur->Exp_phi()->Set_has_real_occ(pos);
00935 if (spre_stack->Top()->Def_occur() != NULL)
00936 occur->Exp_phi()->Set_opnd(pos, spre_stack->Top()->Def_occur());
00937 }
00938 }
00939 #if 0
00940
00941
00942 _etable->Append_iphi_succ_occurrence(bb, wk);
00943 #endif
00944 }
00945 }
00946 }
00947 }
00948 }
00949
00950
00951 FOR_ALL_ELEM(pdom_bb, pdom_bb_iter, Init(bb->Pdom_bbs())) {
00952 Rename(pdom_bb);
00953 }
00954
00955
00956 EXP_WORKLST_ITER worklst_iter(Etable()->Exp_worklst());
00957 FOR_ALL_NODE(wk, worklst_iter, Init()) {
00958 BOOL done = FALSE;
00959 while (! (done || wk->Spre_stack()->Is_Empty()) ) {
00960 occur = wk->Spre_stack()->Top();
00961 switch (occur->Occ_kind()) {
00962 case EXP_OCCURS::OCC_REAL_OCCUR:
00963 if (occur->Spre_store()->Bb() == bb)
00964 wk->Spre_stack()->Pop();
00965 else done = TRUE;
00966 break;
00967 case EXP_OCCURS::OCC_PHI_OCCUR:
00968 if (occur->Exp_phi()->Bb() == bb)
00969 wk->Spre_stack()->Pop();
00970 done = TRUE;
00971 break;
00972 default: Is_True(FALSE, ("SSU::Rename: bad item on spre rename stack"));
00973 }
00974 }
00975 }
00976 }
00977
00978
00979
00980
00981 struct REMOVE_EMPTY_WORKLIST {
00982 OPT_STAB *_opt_stab;
00983 BOOL _trace;
00984
00985 REMOVE_EMPTY_WORKLIST(OPT_STAB *opt_stab, BOOL trace)
00986 { _opt_stab = opt_stab; _trace = trace; }
00987
00988 BOOL operator()(EXP_WORKLST *wk)
00989 {
00990 if (wk->Real_occurs().Head() == NULL) {
00991 Is_True(wk->Exp()->Kind() == CK_VAR, ("REMOVE_EMPTY_WORKLIST(): not CK_VAR."));
00992 AUX_STAB_ENTRY *psym = _opt_stab->Aux_stab_entry(wk->Exp()->Aux_id());
00993
00994 Is_True(psym->Spre_node() == NULL || psym->Spre_node() == wk,
00995 ("REMOVE_EMPTY_WORKLIST(): psym->Spre_node() is inconsistent."));
00996
00997 Is_Trace(_trace,
00998 (TFile, "REMOVE_EMPTY_WORKLIST: remove worklist for auxid %d\n", wk->Exp()->Aux_id()));
00999 psym->Set_spre_node(NULL);
01000 wk->Set_spre_stack(NULL);
01001 return TRUE;
01002 }
01003 return FALSE;
01004 }
01005 };
01006
01007
01008
01009
01010 void SSU::Construct(void)
01011 {
01012
01013 BB_NODE *bb;
01014 CFG_ITER cfg_iter;
01015 AUX_ID var;
01016 VER_ID du;
01017 AUX_STAB_ITER opt_stab_iter(Opt_stab());
01018
01019 STMTREP *dummy_exit_stmt = CXX_NEW(STMTREP, Mem_pool());
01020 dummy_exit_stmt->Set_bb(Cfg()->Exit_bb());
01021
01022 OPT_POOL_Push(Loc_pool(), SSA_DUMP_FLAG);
01023 {
01024 FOR_ALL_NODE(var, opt_stab_iter, Init()) {
01025 Opt_stab()->Aux_stab_entry(var)->Set_spre_node(NULL);
01026 }
01027
01028
01029 FOR_ALL_ELEM ( bb, cfg_iter, Init(Cfg()) )
01030 bb->Set_iphi_list(CXX_NEW(EXP_PHI_LIST(bb->Succ()->Len()),
01031 Mem_pool()));
01032
01033
01034 SET_OPT_PHASE("SPRE: Iphi Insertion");
01035 Iphi_insertion();
01036 }
01037 OPT_POOL_Pop(Loc_pool(), SSA_DUMP_FLAG);
01038
01039 Opt_stab()->Reset_def_bbs();
01040
01041 OPT_POOL_Push(Loc_pool(), SSA_DUMP_FLAG);
01042 {
01043 SET_OPT_PHASE("SPRE: SSU Renaming");
01044
01045
01046 EXP_WORKLST *wk;
01047 EXP_WORKLST_ITER worklst_iter(_etable->Exp_worklst());
01048
01049 FOR_ALL_NODE(wk, worklst_iter, Init()) {
01050 wk->Set_spre_stack(CXX_NEW(STACK<EXP_OCCURS*>(Loc_pool()), Loc_pool()));
01051 AUX_STAB_ENTRY *psym = Opt_stab()->Aux_stab_entry(wk->Exp()->Aux_id());
01052 if (psym->Points_to()->Local()) {
01053 EXP_OCCURS *occur =
01054 _etable->Append_spre_real_occurrence(dummy_exit_stmt, wk);
01055 wk->Spre_stack()->Push(occur);
01056 occur->Set_fake_store();
01057
01058 occur->Set_e_version(wk->Cur_e_version());
01059 wk->New_e_version();
01060 }
01061
01062 }
01063
01064
01065 Rename(_cfg->Exit_bb());
01066
01067
01068 EXP_OCCURS *occur;
01069 EXP_OCCURS_ITER phi_occur_iter;
01070 FOR_ALL_NODE(wk, worklst_iter, Init(_etable->Exp_worklst())) {
01071 FOR_ALL_NODE(occur, phi_occur_iter, Init(wk->Phi_occurs().Head())) {
01072 if (occur->Occurrence() != NULL)
01073 Propagate_occurrences(occur, occur->Occurrence());
01074 }
01075 }
01076
01077
01078 }
01079
01080
01081 {
01082 REMOVE_EMPTY_WORKLIST predicate(Opt_stab(), Get_Trace(TP_GLOBOPT, SPRE_DUMP_FLAG));
01083 Remove_if(*_etable->Exp_worklst(), predicate);
01084 }
01085
01086 OPT_POOL_Pop(Loc_pool(), SSA_DUMP_FLAG);
01087
01088 #if 0
01089 if ( Get_Trace(TP_GLOBOPT, SSU_DUMP_FLAG)) {
01090
01091 fprintf(TFile, "IPHI INSERTION: \n");
01092 FOR_ALL_ELEM (bb, cfg_iter, Init(cfg))
01093 if (bb->Iphi_list()->Len() > 0) {
01094 fprintf(TFile, "BB%d: \n", bb->Id());
01095 bb->Iphi_list()->PRINT(TFile);
01096 }
01097 }
01098 #endif
01099 }