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 #ifdef USE_PCH
00048 #include "opt_pch.h"
00049 #endif // USE_PCH
00050 #pragma hdrstop
00051
00052
00053 #include "id_map.h"
00054
00055 #include "opt_vertab.h"
00056 #include "opt_etable.h"
00057 #include "opt_htable.h"
00058 #include "opt_efinalize.h"
00059 #include "opt_ssa.h"
00060 #include "opt_mu_chi.h"
00061 #include "opt_fold.h"
00062 #include "opt_verify.h"
00063 #include "tracing.h"
00064
00065 #include "opt_config.h"
00066
00067
00068 void
00069 EXP_WORKLST::Insert_one_operand( ETABLE *const etable,
00070 CODEMAP *const htable,
00071 EXP_PHI *const phi,
00072 const INT opnd_num)
00073 {
00074 const CODEREP *op = phi->Result()->Occurrence();
00075 const EXP_OCCURS *opnd = phi->Opnd(opnd_num);
00076
00077
00078 Is_True(!phi->Not_down_safe(),
00079 ("Insertion for opnd %d of phi in BB%d must be down-safe",
00080 opnd_num, phi->Bb()->Id()));
00081 FmtAssert(!phi->Not_down_safe(),
00082 ("Insertion must be down-safe"));
00083 FmtAssert(op != NULL,
00084 ("Occurrence() coderep must be non-NULL "
00085 "for down-safe phi"));
00086
00087
00088 CODEREP *insert_cr =
00089 etable->Alloc_and_generate_cur_expr(op, phi->Bb(),
00090 opnd_num, etable->Per_expr_pool(),
00091 TRUE );
00092
00093 #if Is_True_On
00094 BOOL was_integral_load_store = FALSE;
00095 #endif
00096
00097
00098
00099 if (insert_cr->Is_integral_load_store()) {
00100 insert_cr = Save_use_cr(etable, insert_cr);
00101 #if Is_True_On
00102 was_integral_load_store = TRUE;
00103 #endif
00104 }
00105
00106
00107
00108
00109
00110
00111
00112 BOOL tree_changed = FALSE;
00113 insert_cr = htable->Rehash_tree(insert_cr, FALSE ,
00114 &tree_changed,
00115 phi->Pred(opnd_num)->Bb());
00116
00117
00118
00119
00120 Is_Trace(etable->Tracing(), (TFile, "EXP_WORKLST::Insert_one_operand\n"));
00121 Is_Trace(etable->Tracing(), (TFile, "Inserted expression:\n"));
00122 Is_Trace_cmd(etable->Tracing(), insert_cr->Print(3, TFile));
00123 Is_Trace(etable->Tracing(), (TFile, "CFG \n"));
00124 Is_Trace_cmd(etable->Tracing(), etable->Cfg()->Print(TFile));
00125 Is_True(Is_the_same_as(insert_cr) ||
00126 (was_integral_load_store &&
00127 Is_the_same_as(insert_cr->Opnd(0))),
00128 ("EXP_WORKLST::Insert_one_operand: Rehashing must not "
00129 "change expression"));
00130 Is_Trace(etable->Tracing(), (TFile, "Inserted expression:\n"));
00131 Is_Trace_cmd(etable->Tracing(), insert_cr->Print(3, TFile));
00132
00133 Is_True(Def_before_use(insert_cr,
00134 phi->Bb()->Nth_pred(opnd_num)),
00135 ("EXP_WORKLST::Insert_one_operand: "
00136 "Inserted use before def"));
00137
00138
00139
00140
00141
00142
00143
00144
00145 ++_insert_cnt;
00146
00147
00148
00149
00150 EXP_OCCURS *insert_occ = phi->Pred(opnd_num);
00151 insert_occ->Set_inserted();
00152 insert_occ->Set_occurrence(insert_cr);
00153 if (tree_changed) {
00154 insert_occ->Set_rehash_changed_expr();
00155 }
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165 insert_occ->Set_save_to_temp();
00166 insert_occ->Set_def_occur(NULL);
00167
00168 if (phi->Opnd(opnd_num) == NULL) {
00169 insert_occ->Set_e_version(Cur_e_version());
00170 New_e_version();
00171 }
00172 else {
00173 insert_occ->Set_e_version(phi->Opnd(opnd_num)->E_version());
00174 }
00175
00176
00177
00178 phi->Set_opnd(opnd_num, insert_occ);
00179
00180
00181
00182
00183
00184
00185 phi->Reset_injured(opnd_num);
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196 }
00197
00198 BOOL
00199 EXP_PHI::Need_insertion(INT opnd_num) const
00200 {
00201 Is_True(Will_b_avail(),
00202 ("EXP_PHI::Need_insertion: *this must be Will_b_avail()"));
00203
00204 const EXP_OCCURS *const opnd = Opnd(opnd_num);
00205 return (opnd == NULL ||
00206 (opnd->Occ_kind() == EXP_OCCURS::OCC_PHI_OCCUR &&
00207 !Has_real_occ(opnd_num) &&
00208 !opnd->Exp_phi()->Will_b_avail()));
00209 }
00210
00211
00212
00213 static inline void
00214 Check_restore_sunk_lvalue_def(E_VER_TAB *e_ver_tab, EXP_OCCURS *occ)
00215 {
00216 IDTYPE e_vers = occ->E_version();
00217 EXP_OCCURS *defocc = e_ver_tab->Avail_def(e_vers);
00218 if (defocc == NULL)
00219 return;
00220 if (defocc->Bb()->Dominates(occ->Bb()))
00221 return;
00222 if (defocc->Occurs_as_lvalue())
00223 return;
00224 if (defocc->Sunk_lvalue()) {
00225 defocc = defocc->Def_occur();
00226 e_ver_tab->Set_real_avail_def(e_vers, defocc);
00227 }
00228 }
00229
00230
00231 BOOL
00232 EXP_WORKLST::Determine_inserts_saves_deletions(CODEMAP *htable,
00233 ETABLE *etable,
00234 E_VER_TAB *e_ver_tab,
00235 EXP_OCCURS_PAIR *comp_occurs)
00236 {
00237 BOOL optimization_happened = FALSE;
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251 ID_MAP<REHASH_INFO *, INT32> id_map(Cur_e_version() / 4,
00252 NULL,
00253 etable->Etable_local_pool(),
00254 etable->Tracing());
00255
00256 if (WOPT_Enable_Avoid_Rehash) {
00257 id_map.Init();
00258 }
00259 else {
00260
00261 }
00262
00263
00264
00265
00266
00267 EXP_ALL_OCCURS_ITER occ_iter(Real_occurs().Head(),
00268 comp_occurs,
00269 Phi_occurs().Head(),
00270 Phi_pred_occurs().Head(),
00271 NULL);
00272 EXP_OCCURS *occ;
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283 FOR_ALL_NODE(occ, occ_iter, Init()) {
00284 switch (occ->Occ_kind()) {
00285 case EXP_OCCURS::OCC_PHI_OCCUR:
00286 if (occ->Exp_phi()->Will_b_avail()) {
00287
00288
00289
00290 Is_True(e_ver_tab->Avail_def(occ->E_version()) == NULL,
00291 ("e-version %d already has an available definition",
00292 occ->E_version()));
00293 e_ver_tab->Set_avail_def(occ->E_version(), occ);
00294 }
00295 else {
00296
00297
00298 }
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308 occ->Exp_phi()->Set_identical_to(NULL);
00309 if (WOPT_Enable_SSA_Minimization) {
00310 occ->Exp_phi()->Set_identity();
00311 }
00312 break;
00313 case EXP_OCCURS::OCC_REAL_OCCUR:
00314 {
00315 if (LR_shrink_cand())
00316 Check_restore_sunk_lvalue_def(e_ver_tab, occ);
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334 EXP_OCCURS *def = e_ver_tab->Avail_def(occ->E_version());
00335
00336 if (def == NULL || !def->Bb()->Dominates(occ->Bb())) {
00337
00338
00339
00340
00341
00342
00343
00344
00345 e_ver_tab->Set_real_avail_def(occ->E_version(), occ);
00346 occ->Set_def_occur(NULL);
00347
00348
00349
00350
00351
00352
00353 occ->Reset_injured_occ();
00354 if (LR_shrink_cand() &&
00355 occ->Occurs_as_lvalue() &&
00356 inCODEKIND(occ->Stmt()->Rhs()->Kind(), CK_LDA|CK_RCONST|CK_CONST))
00357 occ->Set_sunk_lvalue();
00358
00359 if (WOPT_Enable_Avoid_Rehash) {
00360
00361
00362
00363
00364
00365
00366 if (occ->Temp_eligible_as_owner(this)) {
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377 Is_True(!occ->Occurrence()->Is_flag_set(CF_OWNED_BY_TEMP),
00378 ("EXP_WORKLST::Determine_inserts_saves_deletions: "
00379 "Lvalue coderep must not be owned by temp"));
00380 occ->Render_coderep_unownable(etable, id_map);
00381 }
00382 else {
00383 occ->Bid_for_coderep(etable, id_map, occ->Rehash_cost());
00384 }
00385 }
00386
00387
00388 if (occ->Mult_real()) {
00389 e_ver_tab->Note_version_use(occ->E_version());
00390 optimization_happened = TRUE;
00391 }
00392 }
00393 else {
00394
00395
00396
00397
00398
00399 Is_True(def->Occ_kind() == EXP_OCCURS::OCC_PHI_OCCUR ||
00400 (def->Occ_kind() == EXP_OCCURS::OCC_REAL_OCCUR &&
00401 e_ver_tab->Occ_count(occ->E_version()) >= 1),
00402 ("Inconsistent occurrence count for e-version %d",
00403 occ->E_version()));
00404 Is_True(!occ->Occurs_as_lvalue(),
00405 ("EXP_WORKLST::Determine_inserts_saves_deletions: "
00406 "Lvalue must not be reload"));
00407
00408 occ->Set_def_occur(def);
00409 if (def->Occurs_as_lvalue() && def->Sunk_lvalue()) {
00410 e_ver_tab->Set_real_avail_def(occ->E_version(), occ);
00411 occ->Set_sunk_lvalue();
00412
00413 }
00414 else {
00415
00416
00417
00418 occ->Set_delete_comp();
00419 }
00420
00421 if (WOPT_Enable_Avoid_Rehash) {
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434 if (def->Occurrence() == occ->Occurrence()) {
00435 def->Bid_for_coderep(etable, id_map, occ->Rehash_cost());
00436 }
00437 else {
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449 if (def->Occurrence()->Kind() == CK_IVAR) {
00450
00451
00452
00453
00454 DevWarn("Same-value / different CODEREP* limits "
00455 "avoid_rehash in SSAPRE");
00456
00457 def->Render_coderep_unownable(etable, id_map);
00458 }
00459 else {
00460
00461
00462
00463 FmtAssert(WOPT_Enable_New_SR,
00464 ("EXP_WORKLST::Determine_inserts_saves_deletions: "
00465 "D/U occurrence codereps must match"));
00466
00467 Warn_todo("Injured occurrences should take part in "
00468 "coderep auction");
00469 }
00470 }
00471 }
00472
00473 e_ver_tab->Note_version_use(occ->E_version(),
00474 (occ->Mult_real() ? 2 : 1));
00475 optimization_happened = TRUE;
00476 }
00477 }
00478 break;
00479 case EXP_OCCURS::OCC_COMP_OCCUR:
00480 if (occ->E_version() != EXP_OCCURS::ILLEGAL_E_VERSION &&
00481 e_ver_tab->Avail_def(occ->E_version()) != NULL &&
00482 e_ver_tab->Avail_def(occ->E_version())->Bb()->Dominates(occ->Bb())) {
00483 occ->Set_def_occur(e_ver_tab->Avail_def(occ->E_version()));
00484 }
00485 else {
00486 Is_True(occ->Def_occur() == NULL,
00487 ("EXP_WORKLST::Determine_inserts_saves_deletions: "
00488 "Comparison must not have trashed Def_occur()"));
00489 }
00490 break;
00491 case EXP_OCCURS::OCC_PHI_PRED_OCCUR:
00492 {
00493
00494
00495
00496
00497
00498
00499
00500 BB_LIST_ITER succ_bb_iter;
00501 BB_NODE *succ_bb;
00502 BB_NODE *occ_bb = occ->Bb();
00503 #if Is_True_On
00504 BOOL found_phi = FALSE;
00505 #endif
00506 FOR_ALL_ELEM(succ_bb, succ_bb_iter, Init(occ_bb->Succ())) {
00507 EXP_PHI *phi = etable->Lookup_exp_phi(succ_bb, Exp());
00508
00509 if (phi != NULL) {
00510 Is_True(phi->Bb() == succ_bb,
00511 ("EXP_WORKLST::Determine_inserts_saves_deletions: "
00512 "ETABLE::Lookup_exp_phi failed"));
00513
00514
00515 #if Is_True_On
00516 found_phi = TRUE;
00517 #endif
00518 if (phi->Will_b_avail()) {
00519
00520
00521
00522 const INT32 opnd_num = succ_bb->Pred()->Pos(occ_bb);
00523 EXP_OCCURS *const opnd = phi->Opnd(opnd_num);
00524
00525 Is_True(phi->Pred(opnd_num) == occ,
00526 ("EXP_WORKLST::Determine_inserts_saves_deletions: "
00527 "phi->Pred() / phi-pred inconsistency"));
00528
00529 if (phi->Need_insertion(opnd_num)) {
00530 BOOL opnd_had_e_version = phi->Opnd(opnd_num) != NULL;
00531
00532
00533 Insert_one_operand(etable, htable, phi, opnd_num);
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551 if (opnd_had_e_version) {
00552
00553 }
00554 }
00555 else {
00556
00557
00558
00559
00560
00561
00562
00563 optimization_happened = TRUE;
00564 if (LR_shrink_cand())
00565 Check_restore_sunk_lvalue_def(e_ver_tab, opnd);
00566 EXP_OCCURS *def = e_ver_tab->Avail_def(opnd->E_version());
00567 if (def->Occurs_as_lvalue() && def->Sunk_lvalue()
00568 #if defined(TARG_SL) //PARA_EXTENSION
00569 && !occ_bb->SL2_para_region()
00570 #endif
00571 ) {
00572
00573
00574 occ->Set_sunk_lvalue();
00575 occ->Set_occurrence(def->Occurrence());
00576 phi->Set_opnd(opnd_num, occ);
00577 }
00578 else {
00579 #if defined(TARG_SL) //PARA_EXTENSION
00580 if(occ_bb->SL2_para_region() && def->Sunk_lvalue())
00581 def->Reset_sunk_lvalue();
00582 #endif
00583 e_ver_tab->Note_version_use(opnd->E_version());
00584
00585 phi->Set_opnd(opnd_num,
00586 e_ver_tab->Avail_def(opnd->E_version()));
00587 }
00588 }
00589 }
00590 }
00591 }
00592 Is_True(found_phi,
00593 ("EXP_WORKLST::Determine_inserts_saves_deletions: "
00594 "phi-pred must have successor phi"));
00595 }
00596 break;
00597 default:
00598 FmtAssert(FALSE, ("EXP_WORKLST::Determine_inserts_saves_deletions: "
00599 "Bad occurrence kind"));
00600 }
00601 }
00602 return optimization_happened;
00603 }
00604
00605 #if Is_True_On
00606 static inline BOOL bxor(const BOOL a, const BOOL b)
00607 {
00608 return (a && !b) || (!a && b);
00609 }
00610
00611 void
00612 EXP_WORKLST::Verify_saved_occurs(E_VER_TAB *e_ver_tab)
00613 {
00614 EXP_OCCURS_ITER real_occ_iter;
00615 EXP_OCCURS *real_occ;
00616
00617
00618
00619 Is_Trace(e_ver_tab->Tracing(),
00620 (TFile, "================ Version table: ==========\n"));
00621 UINT ver;
00622 for (ver = 1; ver < e_ver_tab->N_versions(); ver++) {
00623 if (e_ver_tab->Avail_def(ver) != NULL) {
00624 Is_Trace(e_ver_tab->Tracing(),
00625 (TFile, "Version %d: Occ_count() == %d; Avail_def()%s:\n",
00626 ver, e_ver_tab->Occ_count(ver),
00627 e_ver_tab->Redefined(ver) ? " (redefined)" : ""));
00628 Is_Trace_cmd(e_ver_tab->Tracing(),
00629 e_ver_tab->Avail_def(ver)->Print(TFile));
00630 }
00631 else {
00632 Is_Trace(e_ver_tab->Tracing(),
00633 (TFile, "Version %d: Occ_count() == %d; "
00634 "Avail_def() is NULL\n", ver, e_ver_tab->Occ_count(ver)));
00635 }
00636 }
00637
00638
00639 FOR_ALL_NODE(real_occ, real_occ_iter, Init(Real_occurs().Head())) {
00640 if (real_occ->Save_to_temp()) {
00641 Is_True(!real_occ->Delete_comp(),
00642 ("EXP_WORKLST::Verify_saved_occurs: Saved occurrence "
00643 "must not be deleted"));
00644 Is_True((real_occ ==
00645 e_ver_tab->Avail_def(real_occ->E_version())) ||
00646 e_ver_tab->Redefined(real_occ->E_version()),
00647 ("EXP_WORKLST::Verify_saved_occurs: Saved occurrence "
00648 "must be avail_def if version not redef"));
00649 Is_True((e_ver_tab->Occ_count(real_occ->E_version()) > 1) ||
00650 e_ver_tab->Redefined(real_occ->E_version()),
00651 ("EXP_WORKLST::Verify_saved_occurs: Saved occurrence "
00652 "must have Occ_count > 1"));
00653 }
00654 if (real_occ->Delete_comp()) {
00655 Is_True(real_occ != e_ver_tab->Avail_def(real_occ->E_version()),
00656 ("EXP_WORKLST::Verify_saved_occurs: Deleted occurrence "
00657 "must not be avail_def"));
00658 }
00659 if (real_occ != e_ver_tab->Avail_def(real_occ->E_version())) {
00660 Is_True((real_occ->Def_occur() ==
00661 e_ver_tab->Avail_def(real_occ->E_version())) ||
00662 e_ver_tab->Redefined(real_occ->E_version()),
00663 ("EXP_WORKST::Verify_saved_occurs: Non-avail_def real "
00664 "occ must have avail_def as its Def_occur()"));
00665 }
00666 }
00667
00668
00669 for (ver = 1; ver < e_ver_tab->N_versions(); ver++) {
00670 if (e_ver_tab->Avail_def(ver) != NULL) {
00671 Is_True((e_ver_tab->Avail_def(ver)->Occ_kind() ==
00672 EXP_OCCURS::OCC_PHI_OCCUR) ||
00673 !e_ver_tab->Avail_def(ver)->Delete_comp(),
00674 ("EXP_WORKLST::Verify_saved_occurs: Real avail_def must not "
00675 "be deleted"));
00676 Is_True((e_ver_tab->Avail_def(ver)->Occ_kind() ==
00677 EXP_OCCURS::OCC_PHI_OCCUR) ||
00678 (e_ver_tab->Avail_def(ver)->Def_occur() == NULL) ||
00679 e_ver_tab->Avail_def(ver)->Sunk_lvalue(),
00680 ("EXP_WORKLST::Verify_saved_occurs: Avail_def real occurrence "
00681 "must have Def_occur() == NULL"));
00682
00683
00684
00685
00686
00687 Is_True(bxor((e_ver_tab->Avail_def(ver)->Occ_kind() ==
00688 EXP_OCCURS::OCC_PHI_OCCUR) &&
00689 e_ver_tab->Avail_def(ver)->Exp_phi()->Will_b_avail(),
00690 (e_ver_tab->Avail_def(ver)->Occ_kind() ==
00691 EXP_OCCURS::OCC_REAL_OCCUR) &&
00692 bxor(e_ver_tab->Avail_def(ver)->Save_to_temp() &&
00693 (e_ver_tab->Occ_count(ver) > 1),
00694 !e_ver_tab->Avail_def(ver)->Save_to_temp() &&
00695 (e_ver_tab->Occ_count(ver) == 1))),
00696 ("EXP_WORKLST::Verify_saved_occurs: Avail_def(%d) "
00697 "inconsistent", ver));
00698 }
00699 else {
00700 Is_True(e_ver_tab->Occ_count(ver) == 0,
00701 ("EXP_WORKLST::Verify_saved_occurs: Occ_count must be zero"));
00702 }
00703 }
00704 }
00705 #endif
00706
00707
00708
00709
00710
00711
00712 BOOL
00713 EXP_WORKLST::Compute_save_delete(
00714 CODEMAP *htable,
00715
00716
00717 ETABLE *etable,
00718 EXP_OCCURS_PAIR *comp_occurs)
00719 {
00720
00721 OPT_POOL_Push(etable->Etable_local_pool(), -1);
00722
00723 E_VER_TAB *e_ver_tab =
00724 CXX_NEW(E_VER_TAB(etable->Etable_local_pool(),
00725 Cur_e_version(),
00726 etable->Tracing()),
00727 etable->Etable_local_pool());
00728
00729 BOOL optimization_happened =
00730 Determine_inserts_saves_deletions(htable, etable, e_ver_tab,
00731 comp_occurs);
00732
00733 Is_Trace(etable->Tracing(),
00734 (TFile,
00735 "==== After EXP_WORKLST::Determine_inserts_saves_deletions\n"));
00736 Is_Trace_cmd(etable->Tracing(), Print(TFile, comp_occurs));
00737
00738 #if Is_True_On
00739 Verify_saved_occurs(e_ver_tab);
00740 #endif
00741
00742 CXX_DELETE(e_ver_tab, etable->Etable_local_pool());
00743
00744 OPT_POOL_Pop(etable->Etable_local_pool(), -1);
00745
00746 return optimization_happened;
00747 }