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 #ifdef USE_PCH
00060 #include "opt_pch.h"
00061 #endif // USE_PCH
00062 #pragma hdrstop
00063
00064
00065 #define opt_cse_CXX "opt_cse.cxx"
00066
00067 #include "defs.h"
00068 #include "errors.h"
00069 #include "erglob.h"
00070 #include "tracing.h"
00071 #include "opt_defs.h"
00072 #include "opt_base.h"
00073 #include "cxx_memory.h"
00074 #include "opt_bb.h"
00075 #include "opt_fold.h"
00076 #include "opt_htable.h"
00077 #include "opt_ssa.h"
00078 #include "opt_sym.h"
00079 #include "opt_etable.h"
00080 #include "opt_lftr2.h"
00081 #include "opt_estr.h"
00082 #include "opt_sys.h"
00083 #include "opt_cvtl_rule.h"
00084 #include "config_wopt.h"
00085
00086 class CSE {
00087 private:
00088 MEM_POOL _mempool;
00089 ETABLE *_etable;
00090 EXP_WORKLST *_worklist;
00091 STR_RED *_str_red;
00092 BOOL _tracing;
00093
00094 CSE(void);
00095 CSE(const CSE&);
00096 CSE& operator = (const CSE&);
00097
00098 ETABLE *Etable(void) const { return _etable; }
00099 EXP_WORKLST *Worklist(void) const { return _worklist; }
00100 CODEMAP *Htable(void) const { return _etable->Htable(); }
00101 STR_RED *Str_red(void) const { return _str_red; }
00102 BOOL Tracing(void) const { return _tracing; }
00103
00104 void Save_real_occurrence(EXP_OCCURS *occur);
00105 void Save_hoisted_occurrence(EXP_OCCURS *occur);
00106 void Save_occurrence_as_l_value(EXP_OCCURS *occur);
00107 void Save_shrunk_lr_def(EXP_OCCURS *occur);
00108
00109 #if 0
00110 CODEREP *Save_and_replace(EXP_OCCURS *);
00111 #endif
00112
00113
00114 CODEREP *Get_new_temp_cr(void) const;
00115 CODEREP *Find_injury_update( CODEREP *iv, CODEREP *temp ) const;
00116 CODEREP *Repair_injury_real_real( EXP_OCCURS *def, EXP_OCCURS *use,
00117 CODEREP *temp, BOOL temp_is_owner) const;
00118 CODEREP *Repair_injury_real_phi_opnd( EXP_OCCURS *def, EXP_OCCURS *use,
00119 CODEREP *temp ) const;
00120 CODEREP *Repair_injury_phi_real( EXP_OCCURS *def, EXP_OCCURS *use,
00121 CODEREP *temp, BOOL temp_is_owner) const;
00122 CODEREP *Repair_injury_phi_phi_opnd( EXP_OCCURS *def, EXP_OCCURS *use,
00123 CODEREP *temp ) const;
00124 CODEREP *Repair_injury_rec( CODEREP *iv_def, CODEREP *iv_use,
00125 CODEREP *multiplier, CODEREP *temp,
00126 CODEREP *temp_owner_cr)const;
00127 void Generate_injury_repair( STMTREP *injury, CODEREP *new_temp,
00128 CODEREP *old_temp, CODEREP *multiplier ) const;
00129
00130 public:
00131 CSE(ETABLE *etable, EXP_WORKLST *worklist);
00132 ~CSE(void);
00133
00134 void Do_cse_pass_1(void);
00135 void Do_cse_pass_2(void);
00136
00137 };
00138
00139
00140
00141
00142 STMTREP *
00143 ETABLE::Generate_stid_to_preg( CODEREP *lhs, CODEREP *rhs, MTYPE rhs_type,
00144 BB_NODE *bb, SRCPOS linenum ) const
00145 {
00146 CODEREP *new_cr = Alloc_stack_cr(0);
00147 #ifndef KEY // bug 3022
00148 if (Split_64_Bit_Int_Ops) {
00149 if (MTYPE_size_min(rhs->Dtyp()) == 64 &&
00150 MTYPE_size_min(lhs->Dsctyp()) == 32) {
00151 new_cr->Init_expr(OPC_U4U8CVT, rhs);
00152 rhs = Rehash_exp(new_cr, Gvn(rhs));
00153 }
00154 else if (MTYPE_size_min(rhs->Dtyp()) == 32 &&
00155 MTYPE_size_min(lhs->Dsctyp()) == 64 &&
00156 inCODEKIND(rhs->Kind(), CK_VAR|CK_IVAR)) {
00157 #if 1
00158 if (MTYPE_signed(rhs->Dtyp()))
00159 new_cr->Init_expr(OPC_I8I4CVT, rhs);
00160 else new_cr->Init_expr(OPC_U8U4CVT, rhs);
00161 rhs = Rehash_exp(new_cr, Gvn(rhs));
00162 #else // this is no good because U4U4LDID to U8U4LDID contradicts sign_extd bit
00163 rhs->Set_dtyp(Mtype_TransferSize(MTYPE_A8, rhs->Dtyp()));
00164 #endif
00165 }
00166 }
00167 #endif
00168
00169 STMTREP *savestmt;
00170 savestmt = CXX_NEW(STMTREP, Htable()->Mem_pool());
00171 savestmt->Init( lhs, rhs,
00172 OPCODE_make_op(OPR_STID, MTYPE_V, lhs->Dsctyp()));
00173 savestmt->Set_chi_list(NULL);
00174
00175 lhs->Set_defstmt(savestmt);
00176
00177 savestmt->Set_bb( bb );
00178 savestmt->Set_linenum( linenum );
00179 savestmt->Set_live_stmt();
00180
00181 if (WOPT_Enable_Verbose && Tracing()) {
00182 fprintf(TFile, "generate_stid_to_preg:\n");
00183 savestmt->Print(TFile);
00184 }
00185 return savestmt;
00186 }
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198 BOOL
00199 No_truncation_by_value_size(MTYPE to_mtype,
00200 BOOL sign_extd,
00201 CODEREP *rhs,
00202 OPT_STAB *opt_stab,
00203 BOOL trace_phi)
00204
00205 {
00206 FmtAssert(rhs->Kind() == CK_VAR,
00207 ("No_truncation_by_value_size: Invalid input"));
00208
00209
00210 AUX_STAB_ENTRY *aux_entry = opt_stab->Aux_stab_entry(rhs->Aux_id());
00211 if ( ST_class(aux_entry->St()) == CLASS_PREG &&
00212 aux_entry->Value_size() > 0)
00213 return ((aux_entry->Value_size() <= MTYPE_size_min(to_mtype)) &&
00214 (sign_extd && aux_entry->Is_sign_extd() ||
00215 !sign_extd && aux_entry->Is_zero_extd()));
00216
00217
00218 if (rhs->Is_flag_set(CF_DEF_BY_CHI) || rhs->Is_flag_set(CF_IS_ZERO_VERSION))
00219 return FALSE;
00220
00221 if (trace_phi && rhs->Is_flag_set(CF_DEF_BY_PHI)) {
00222 PHI_NODE *defphi = rhs->Defphi();
00223 if (!defphi || defphi->Is_size_visited()) return FALSE;
00224 defphi->Set_size_visited();
00225 for (INT i = 0; i < defphi->Size(); ++i) {
00226 CODEREP *opnd = defphi->OPND(i);
00227 if (opnd->Is_flag_set(CF_IS_ZERO_VERSION) ||
00228 ! MTYPE_is_integral(opnd->Dtyp()) ||
00229 ! No_truncation_by_value_size(to_mtype, sign_extd, opnd, opt_stab, trace_phi)) {
00230 defphi->Reset_size_visited();
00231 return FALSE;
00232 }
00233 }
00234 defphi->Reset_size_visited();
00235 return TRUE;
00236 }
00237
00238 STMTREP *stmt = rhs->Defstmt();
00239 if ( stmt != NULL ) {
00240 if (stmt->Is_size_visited()) return FALSE;
00241
00242 if (OPERATOR_is_scalar_store (stmt->Opr())) {
00243 CODEREP *rhs_new = stmt->Rhs();
00244 INT signess = 0;
00245 INT vsize = Actual_data_size( rhs_new, opt_stab, signess );
00246 if ( vsize > 0 && vsize <= MTYPE_size_min( to_mtype ) &&
00247 (sign_extd && (signess & SIGN_1_EXTD) ||
00248 !sign_extd && (signess & SIGN_0_EXTD)) ) return TRUE;
00249 if (rhs_new->Kind() == CK_VAR &&
00250 MTYPE_is_integral(rhs_new->Dtyp())) {
00251 stmt->Set_size_visited();
00252 BOOL retv = No_truncation_by_value_size(to_mtype, sign_extd, rhs_new, opt_stab, trace_phi);
00253 stmt->Reset_size_visited();
00254 return retv;
00255 }
00256 }
00257 } else {
00258 return ( MTYPE_size_min( rhs->Dsctyp() ) <= MTYPE_size_min( to_mtype ) &&
00259 sign_extd == rhs->Is_sign_extd() );
00260 }
00261
00262 return FALSE;
00263 }
00264
00265
00266
00267
00268
00269
00270
00271
00272 STMTREP *
00273 ETABLE::Save_replace_rhs_by_preg(STMTREP *stmt,
00274 CODEREP *pregcr,
00275 EXP_WORKLST *wk)
00276 {
00277 CODEREP *rhs = stmt->Rhs();
00278 CODEREP *lhs = stmt->Lhs();
00279 const UINT32 gvn = Gvn(rhs);
00280
00281
00282
00283 if (wk != NULL &&
00284 MTYPE_size_min(wk->Exp()->Dsctyp()) <= MTYPE_size_min(MTYPE_I4) &&
00285 lhs->Is_integral_load_store()) {
00286
00287 if (WOPT_Enable_Min_Type &&
00288 MTYPE_is_integral(rhs->Dtyp()) &&
00289 (rhs->Kind() == CK_VAR
00290 #ifdef TARG_X8664 // bug 8056: I4I2LDID of PREG is valid when ASM uses
00291
00292 && !Opt_stab()->Aux_stab_entry(rhs->Aux_id())->Is_preg()
00293 #endif
00294 ||
00295 (rhs->Kind() == CK_IVAR && rhs->Ivar_has_e_num())) &&
00296 MTYPE_size_min(wk->Exp()->Dsctyp()) == MTYPE_size_min(rhs->Dsctyp()) &&
00297 wk->Sign_extd() == rhs->Is_sign_extd())
00298 ;
00299 else {
00300
00301 CODEREP *cr = Alloc_stack_cr(0);
00302
00303 FOLD ftmp;
00304
00305
00306
00307 OPCODE opc;
00308 MTYPE dsctyp = Mtype_TransferSign(wk->Sign_extd() ?
00309 MTYPE_I2 : MTYPE_U2,
00310 wk->Exp()->Dsctyp());
00311 INT cvt_kind = Need_type_conversion(rhs->Dtyp(), dsctyp, &opc);
00312
00313 if (WOPT_Enable_Min_Type &&
00314 rhs->Kind() == CK_VAR &&
00315 MTYPE_is_integral(rhs->Dtyp()) &&
00316 MTYPE_is_signed(dsctyp)==MTYPE_is_signed(rhs->Dtyp()) &&
00317 No_truncation_by_value_size(dsctyp, wk->Sign_extd(), rhs, Htable()->Sym()))
00318 cvt_kind = NOT_AT_ALL;
00319
00320 switch (cvt_kind) {
00321 case NOT_AT_ALL:
00322 break;
00323 case NEED_CVT:
00324 if (opc != OPC_U4U8CVT) {
00325 cr->Init_expr(opc, rhs);
00326
00327
00328
00329
00330
00331
00332
00333
00334 rhs = Rehash_exp(cr, gvn);
00335
00336 break;
00337 }
00338 opc = OPC_U8CVTL;
00339
00340 case NEED_CVTL:
00341 cr->Init_expr(opc, rhs);
00342 cr->Set_offset(MTYPE_size_min(dsctyp));
00343
00344
00345 rhs = Rehash_exp(cr, gvn);
00346 break;
00347 }
00348 }
00349 }
00350
00351
00352 STMTREP *savestmt = Generate_stid_to_preg( pregcr,
00353 rhs, rhs->Dtyp(), stmt->Bb(), stmt->Linenum() );
00354
00355 Deferred_cfold_stmts()->Push(savestmt);
00356
00357
00358 savestmt->Set_stmt_id(stmt->Stmt_id());
00359
00360 savestmt->Bb()->Stmtlist()->Insert_Before(savestmt, stmt);
00361
00362 if (Pre_kind() == PK_VNFRE)
00363 VNFRE::move_rhs_occurs(stmt, savestmt);
00364
00365
00366 stmt->Set_rhs(pregcr);
00367
00368
00369 stmt->Reset_volatile_stmt();
00370 stmt->Rhs()->Set_defstmt(savestmt);
00371 pregcr->IncUsecnt();
00372
00373 return savestmt;
00374 }
00375
00376
00377
00378
00379
00380
00381
00382 void
00383 CSE::Save_occurrence_as_l_value(EXP_OCCURS *occur)
00384 {
00385 STMTREP *savestmt = Etable()->Save_replace_rhs_by_preg(occur->Stmt(), occur->Temp_cr(), Worklist());
00386
00387
00388 Str_red()->Determine_iv_update(savestmt, NULL);
00389
00390 Worklist()->Inc_reload_count();
00391
00392
00393 occur->Stmt()->Set_RHS_saved(); savestmt->Set_saved_RHS();
00394 }
00395
00396
00397
00398
00399
00400
00401 void
00402 CSE::Save_real_occurrence(EXP_OCCURS *occur)
00403 {
00404 CODEREP *tempcr = occur->Temp_cr();
00405 CODEREP *rhs = occur->Occurrence();
00406
00407
00408
00409 if (Etable()->Pre_kind() != PK_VNFRE
00410 && (occur->Occ_kind() != EXP_OCCURS::OCC_PHI_PRED_OCCUR ||
00411 !occur->Inserted_computation())
00412 && Worklist()->Exp()->Is_integral_load_store()) {
00413 rhs = Worklist()->Save_use_cr(Etable(), rhs);
00414 }
00415
00416
00417
00418 STMTREP *savestmt =
00419 Etable()->Generate_stid_to_preg(tempcr,
00420 rhs, rhs->Dtyp(), occur->Bb(),
00421 (occur->Occ_kind() == EXP_OCCURS::OCC_REAL_OCCUR ?
00422 occur->Stmt()->Linenum() :
00423 (occur->Bb()->Last_stmtrep() == NULL ?
00424 occur->Bb()->Linenum() :
00425 occur->Bb()->Last_stmtrep()->Linenum())) );
00426
00427
00428 BOOL is_iv_update = Str_red()->Determine_iv_update(savestmt, NULL);
00429
00430 rhs->IncUsecnt();
00431
00432 LFTR *lftr = Etable()->Lftr();
00433
00434 if (occur->Occ_kind() == EXP_OCCURS::OCC_REAL_OCCUR) {
00435
00436 savestmt->Set_stmt_id(occur->Stmt()->Stmt_id());
00437 savestmt->Bb()->Stmtlist()->Insert_Before(savestmt, occur->Stmt());
00438
00439
00440
00441 if (lftr->Lftr_on() && lftr->Is_comparison(occur->Occurrence())) {
00442 lftr->Update_comp_occur_stmt(occur, savestmt);
00443 }
00444 }
00445 else {
00446 Is_True(occur->Inserted_computation(),
00447 ("CSE::Save_real_occurrence: saved non-real occurrence "
00448 "must be phi-pred"));
00449
00450 IDX_32 sid = (savestmt->Bb()->Last_stmtrep() != NULL ?
00451 savestmt->Bb()->Last_stmtrep()->Stmt_id() :
00452 Etable()->Cfg()->Get_stmt_id());
00453 savestmt->Set_stmt_id(sid);
00454 savestmt->Bb()->Append_stmt_before_branch(savestmt);
00455 occur->Set_enclose_stmt(savestmt);
00456 occur->Set_encl_stmt_set();
00457
00458 Is_Trace(Tracing(), (TFile, "CSE::Save_real_occurrence: Inserted\n"));
00459 Is_Trace_cmd(Tracing(), savestmt->Print(TFile));
00460
00461
00462
00463
00464 lftr->Insert_comp_occurrence(occur->Occurrence(),savestmt,0);
00465
00466 if (is_iv_update) {
00467 FmtAssert(FALSE, ("CSE: saving insertion, is_iv_udpate must be FALSE"));
00468 }
00469
00470
00471
00472
00473
00474 Etable()->Schedule_for_ocopy(occur);
00475 }
00476
00477 if (Etable()->Pre_kind() == PK_VNFRE)
00478 VNFRE::new_occurs(savestmt);
00479 }
00480
00481
00482
00483
00484
00485
00486
00487 void
00488 CSE::Save_hoisted_occurrence(EXP_OCCURS *occur)
00489 {
00490 CODEREP *tempcr = occur->Temp_cr();
00491 CODEREP *rhs = occur->Occurrence();
00492
00493
00494
00495 if (rhs->Is_integral_load_store() && Worklist()->Exp()->Is_integral_load_store()) {
00496 rhs = Worklist()->Save_use_cr(Etable(), rhs);
00497 }
00498
00499
00500
00501 STMTREP *savestmt = Etable()->Generate_stid_to_preg( tempcr,
00502 rhs, rhs->Dtyp(), occur->Bb(), occur->Bb()->Linenum() );
00503
00504 LFTR *lftr = Etable()->Lftr();
00505
00506
00507 IDX_32 sid = savestmt->Bb()->Last_stmtrep() != NULL ?
00508 savestmt->Bb()->Last_stmtrep()->Stmt_id() : Etable()->Cfg()->Get_stmt_id();
00509 savestmt->Set_stmt_id(sid);
00510 savestmt->Bb()->Append_stmt_before_branch(savestmt);
00511
00512
00513
00514
00515 lftr->Insert_comp_occurrence(occur->Occurrence(),savestmt,0);
00516
00517
00518 occur->Set_enclose_stmt(savestmt);
00519 occur->Reset_hoisted();
00520
00521
00522
00523 Etable()->Schedule_for_ocopy(occur);
00524
00525 if (Etable()->Pre_kind() == PK_VNFRE)
00526 VNFRE::new_occurs(savestmt);
00527 }
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537 void
00538 CSE::Save_shrunk_lr_def(EXP_OCCURS *occur)
00539 {
00540 CODEREP *tempcr = occur->Temp_cr();
00541 CODEREP *rhs = occur->Occurrence()->Defstmt()->Rhs();
00542 const UINT32 gvn = Etable()->Gvn(rhs);
00543
00544
00545
00546 if (MTYPE_is_integral(rhs->Dtyp()) &&
00547 MTYPE_size_min(Worklist()->Exp()->Dsctyp()) <= MTYPE_size_min(MTYPE_I4)) {
00548 CODEREP *cr = Alloc_stack_cr(0);
00549 FOLD ftmp;
00550 OPCODE opc;
00551 MTYPE dsctyp = Mtype_TransferSign(Worklist()->Sign_extd() ? MTYPE_I2 : MTYPE_U2,
00552 Worklist()->Exp()->Dsctyp());
00553 INT cvt_kind = Need_type_conversion(rhs->Dtyp(), dsctyp, &opc);
00554
00555 switch (cvt_kind) {
00556 case NOT_AT_ALL:
00557 break;
00558 case NEED_CVT:
00559 if (opc != OPC_U4U8CVT) {
00560 cr->Init_expr(opc, rhs);
00561 if (rhs->Kind() == CK_CONST) {
00562 rhs = ftmp.Fold_Expr(cr);
00563 if (!rhs) {
00564 rhs = Etable()->Rehash_exp(cr, gvn);
00565 }
00566 } else {
00567 rhs = Etable()->Rehash_exp(cr, gvn);
00568 }
00569 break;
00570 }
00571 opc = OPC_U8CVTL;
00572
00573 case NEED_CVTL:
00574 cr->Init_expr(opc, rhs);
00575 cr->Set_offset(MTYPE_size_min(dsctyp));
00576 if (rhs->Kind() == CK_CONST) {
00577 rhs = ftmp.Fold_Expr(cr);
00578 if (!rhs) {
00579 rhs = Etable()->Rehash_exp(cr, gvn);
00580 }
00581 } else {
00582 rhs = Etable()->Rehash_exp(cr, gvn);
00583 }
00584 break;
00585 }
00586 }
00587
00588
00589 rhs->IncUsecnt();
00590
00591 STMTREP *savestmt;
00592 if (occur->Occ_kind() == EXP_OCCURS::OCC_REAL_OCCUR) {
00593 STMTREP *curstmt = occur->Stmt();
00594 BB_NODE *bb = curstmt->Bb();
00595 savestmt = Etable()->Generate_stid_to_preg(tempcr, rhs, rhs->Dtyp(), bb,
00596 curstmt->Linenum());
00597 savestmt->Set_stmt_id(curstmt->Stmt_id());
00598
00599 bb->Stmtlist()->Insert_Before(savestmt, curstmt);
00600 }
00601 else {
00602 BB_NODE *bb = occur->Bb();
00603 savestmt = Etable()->Generate_stid_to_preg(tempcr, rhs,
00604 rhs->Dtyp(), bb,
00605 (bb->Last_stmtrep() == NULL ?
00606 bb->Linenum() :
00607 bb->Last_stmtrep()->Linenum()) );
00608 IDX_32 sid = (bb->Last_stmtrep() != NULL ? bb->Last_stmtrep()->Stmt_id() :
00609 Etable()->Cfg()->Get_stmt_id());
00610 savestmt->Set_stmt_id(sid);
00611 bb->Append_stmt_before_branch(savestmt);
00612 occur->Set_enclose_stmt(savestmt);
00613 occur->Set_encl_stmt_set();
00614 }
00615
00616 if (Etable()->Pre_kind() == PK_VNFRE)
00617 VNFRE::new_occurs(savestmt);
00618 }
00619
00620
00621
00622
00623
00624
00625
00626 CODEREP *
00627 CSE::Get_new_temp_cr( void ) const
00628 {
00629 Is_True(_worklist->Preg() != 0,
00630 ("CSE::Get_new_temp_cr: current temp PREG must not be zero"));
00631
00632 CODEREP *new_temp =
00633 Htable()->Add_def(_worklist->Preg(),
00634 _worklist->Cur_e_version(), NULL,
00635 _worklist->Exp()->Dtyp(), _worklist->Exp()->Dtyp(),
00636 Htable()->Sym()->St_ofst(_worklist->Preg()),
00637 ST_type(MTYPE_To_PREG(_worklist->Exp()->Dtyp())),
00638 0, TRUE);
00639 _worklist->New_e_version();
00640
00641 if (Etable()->Pre_kind() == PK_VNFRE)
00642 VNFRE::add_valnum(new_temp, _worklist->E_num());
00643
00644 return new_temp;
00645 }
00646
00647
00648
00649
00650
00651 static void
00652 Change_expr_to_temp(CODEREP *cr, EXP_WORKLST *wk, CODEMAP *htable)
00653 {
00654 Is_True(cr != NULL && cr->Kind() != CK_VAR,
00655 ("EXP_OCCURS::Change_expr_to_temp_cr: already a var node"));
00656 if (wk->Preg() == 0)
00657 wk->Set_preg(htable->Sym()->Create_preg(wk->Exp()->Dtyp()));
00658
00659 htable->Remove(cr);
00660
00661 UINT coderep_id_save = cr->Coderep_id();
00662 cr->Init_var(wk->Exp()->Dtyp(), wk->Preg(), wk->Cur_e_version(),
00663 wk->Exp()->Dtyp(), htable->Sym()->St_ofst(wk->Preg()),
00664 ST_type(MTYPE_To_PREG(wk->Exp()->Dtyp())),
00665 wk->Exp()->Field_id());
00666 if (wk->Exp()->Bit_field_valid())
00667 cr->Set_bit_field_valid();
00668 cr->Set_coderep_id(coderep_id_save);
00669 cr->Set_sign_extension_flag();
00670 cr->Set_defstmt(NULL);
00671
00672
00673 AUX_STAB_ENTRY *aux = htable->Sym()->Aux_stab_entry(wk->Preg());
00674 aux->Set_cr_list(aux->Cr_list()->Prepend(cr));
00675
00676 wk->New_e_version();
00677 wk->Inc_temp_owner_count();
00678 }
00679
00680
00681
00682
00683
00684
00685 CODEREP *
00686 CSE::Find_injury_update( CODEREP *iv, CODEREP *temp ) const
00687 {
00688 Is_True( !iv->Is_flag_set((CR_FLAG)(CF_DEF_BY_CHI|
00689 CF_DEF_BY_PHI|
00690 CF_IS_ZERO_VERSION)),
00691 ("CSE::Find_injury_update: iv not defined by stmt") );
00692
00693 STMTREP *iv_def = iv->Defstmt();
00694 Is_True( iv_def->Repaired(),
00695 ("CSE::Find_injury_update: iv's def still injured") );
00696
00697
00698 for ( STMTREP *tmp_def = iv_def->Next();
00699 tmp_def != NULL;
00700 tmp_def = tmp_def->Next() )
00701 {
00702 if (OPERATOR_is_scalar_store (tmp_def->Opr())) {
00703 if ( tmp_def->Lhs()->Aux_id() == temp->Aux_id() ) {
00704 return tmp_def->Lhs();
00705 }
00706 }
00707 }
00708
00709 return NULL;
00710 }
00711
00712
00713
00714
00715
00716 void
00717 CSE::Generate_injury_repair( STMTREP *injury, CODEREP *new_temp,
00718 CODEREP *old_temp, CODEREP *multiplier ) const
00719 {
00720 CODEREP *updated_iv;
00721 CODEREP *incr_amt;
00722 BOOL is_add;
00723
00724 if ( !Str_red()->Find_iv_and_incr(injury, &updated_iv,
00725 &incr_amt, &is_add))
00726 {
00727 FmtAssert( FALSE,
00728 ("CSE::Generate_injury_repair: injury is not iv update") );
00729 }
00730
00731 CODEREP *temp_incr;
00732 if ( multiplier == NULL ) {
00733
00734
00735 if ( Worklist()->Exp()->Kind() == CK_OP &&
00736 Worklist()->Exp()->Opr() == OPR_CVT )
00737 {
00738
00739
00740
00741
00742 OPCODE cvt_opc;
00743 #ifndef KEY
00744 INT type_conversion = Need_type_conversion(incr_amt->Dtyp(),
00745 old_temp->Dtyp(), &cvt_opc);
00746 #else // bug 7858: it is safer to keep the increment amount as signed
00747 INT type_conversion = Need_type_conversion(incr_amt->Dtyp(),
00748 Mtype_TransferSign(MTYPE_I8, old_temp->Dtyp()), &cvt_opc);
00749 #endif
00750 if ( type_conversion == NEED_CVT ) {
00751 temp_incr = Htable()->Add_unary_node_and_fold(cvt_opc,incr_amt);
00752 }
00753 else if ( type_conversion == NEED_CVTL ) {
00754 FmtAssert( FALSE, ("CSE::Generate_injury_repair: need cvtl") );
00755 }
00756 else {
00757 Is_True( type_conversion == NOT_AT_ALL,
00758 ("CSE::Generate_injury_repair: type_conversion=%d",
00759 type_conversion) );
00760
00761 temp_incr = incr_amt;
00762 }
00763
00764 }
00765 else {
00766
00767
00768 temp_incr = incr_amt;
00769 }
00770 }
00771 else if ( incr_amt == NULL ) {
00772
00773
00774 temp_incr = multiplier;
00775 }
00776 else {
00777
00778
00779
00780
00781 OPCODE mpy_opc;
00782 mpy_opc = OPCODE_make_op(OPR_MPY,
00783
00784 old_temp->Dtyp(),
00785 MTYPE_V);
00786
00787 if (MTYPE_signed(incr_amt->Dtyp()))
00788 mpy_opc = OPCODE_make_op(OPR_MPY,
00789 Mtype_TransferSign(MTYPE_I8, old_temp->Dtyp()),
00790 MTYPE_V);
00791
00792 temp_incr = Htable()->Add_bin_node_and_fold( mpy_opc,
00793 multiplier, incr_amt );
00794 }
00795
00796 OPCODE incr_opc = OPCODE_make_op( (is_add?OPR_ADD:OPR_SUB),
00797 old_temp->Dtyp(), MTYPE_V );
00798 CODEREP *new_rhs = Htable()->Add_bin_node_and_fold( incr_opc,
00799 old_temp, temp_incr );
00800
00801 STMTREP *new_stid = Etable()->Generate_stid_to_preg( new_temp, new_rhs,
00802 OPCODE_rtype(incr_opc), injury->Bb(), injury->Linenum() );
00803
00804
00805 Etable()->Insert_stmtrep_after( new_stid, injury );
00806
00807
00808
00809
00810
00811
00812 if ( new_rhs->Kind() == CK_OP ) {
00813 for ( INT k = 0; k < new_rhs->Kid_count(); k++ ) {
00814 CODEREP *rhs_kid = new_rhs->Opnd(k);
00815
00816
00817
00818
00819 if ( rhs_kid->Contains(old_temp) ) {
00820 Is_Trace(Tracing(),
00821 (TFile, "CSE::Generate_injury_repair: "
00822 "Exclude new expr (kid of rhs):\n"));
00823 Is_Trace_cmd(Tracing(), rhs_kid->Print(4, TFile));
00824 }
00825 else {
00826
00827
00828 Is_Trace(Tracing(),
00829 (TFile, "CSE::Generate_injury_repair: "
00830 "New leaf expression (kid of rhs):\n"));
00831 Is_Trace_cmd(Tracing(), rhs_kid->Print(4, TFile));
00832
00833 Etable()->Bottom_up_cr( new_stid, 0, rhs_kid, FALSE,
00834 ETABLE::URGENT_INSERT, 0,
00835 OPCODE_UNKNOWN, FALSE);
00836 }
00837 }
00838 }
00839
00840
00841
00842
00843 if (MTYPE_IS_INTEGER(OPCODE_desc(new_stid->Op()))
00844 #ifdef KEY // bug 5029
00845 && new_rhs->Kind() == CK_OP
00846 #endif
00847 ) {
00848 new_stid->Set_iv_update();
00849 }
00850
00851
00852 Str_red()->Set_repaired(injury);
00853
00854 if ( Tracing() ) {
00855 fprintf( TFile, "CSE::Generate_injury_repair in BB:%d\n",
00856 injury->Bb()->Id() );
00857 new_stid->Print(TFile);
00858 }
00859
00860 if (Etable()->Pre_kind() == PK_VNFRE)
00861 VNFRE::new_occurs(new_stid);
00862 }
00863
00864
00865
00866
00867
00868
00869
00870 CODEREP *
00871 CSE::Repair_injury_rec(CODEREP *iv_def, CODEREP *iv_use,
00872 CODEREP *multiplier, CODEREP *temp,
00873 CODEREP *temp_owner_cr) const
00874 {
00875 if ( iv_use->Is_flag_set(CF_DEF_BY_CHI) ) {
00876 FmtAssert( FALSE, ("CSE::Repair_injury_rec: injured by chi") );
00877 return NULL;
00878 }
00879 else if ( iv_use->Is_flag_set(CF_DEF_BY_PHI) ) {
00880 FmtAssert( FALSE,
00881 ("CSE::Repair_injury_rec: unimplemented injured by phi") );
00882 return NULL;
00883 }
00884 else {
00885 CODEREP *new_temp = NULL;
00886 CODEREP *old_temp = temp;
00887 STMTREP *injury = iv_use->Defstmt();
00888
00889 Is_True( injury->Iv_update(),
00890 ("CSE::Repair_injury_rec: injury is not an iv_use update") );
00891
00892 if ( !Str_red()->Repaired(injury) ) {
00893
00894 CODEREP *injury_rhs = injury->Rhs();
00895
00896 if ( injury_rhs->Kind() == CK_VAR ) {
00897 injury_rhs = Str_red()->Find_real_defs_rhs(injury_rhs);
00898 }
00899
00900
00901
00902
00903
00904 if ( ! injury_rhs->Contains( iv_def ) ) {
00905
00906
00907
00908
00909 CODEREP *iv_rhs;
00910 if ( !Str_red()->Determine_iv_update( injury, &iv_rhs ) ) {
00911 FmtAssert( FALSE,
00912 ("CSE::Repair_injury_rec: injury is not iv_update") );
00913 }
00914
00915 old_temp = Repair_injury_rec(iv_def, iv_rhs, multiplier, old_temp, NULL);
00916 }
00917
00918
00919 if (temp_owner_cr == NULL)
00920 new_temp = Get_new_temp_cr();
00921 else {
00922 Is_True(temp_owner_cr->Coderep_id() != 0,
00923 ("CSE::Repair_injury_rec: temp owner has 0 coderep id"));
00924 Change_expr_to_temp(temp_owner_cr, _worklist, _etable->Htable());
00925 new_temp = temp_owner_cr;
00926 }
00927 Generate_injury_repair( injury, new_temp, old_temp, multiplier );
00928 if (_worklist->Exp()->Kind() == CK_OP &&
00929 (_worklist->Exp()->Opr() == OPR_ADD ||
00930 _worklist->Exp()->Opr() == OPR_SUB))
00931 injury->Inc_str_red_num();
00932 }
00933 else {
00934
00935
00936 new_temp = Find_injury_update( injury->Lhs(), temp );
00937 }
00938
00939 return new_temp;
00940 }
00941 }
00942
00943
00944
00945
00946
00947
00948
00949
00950
00951
00952 CODEREP *
00953 CSE::Repair_injury_real_real( EXP_OCCURS *def, EXP_OCCURS *use, CODEREP *temp,
00954 BOOL temp_is_owner) const
00955 {
00956 if ( def->Occurrence() == use->Occurrence() ) {
00957
00958
00959 return temp;
00960 }
00961 else {
00962 CODEREP *iv_def, *iv_use, *multiplier;
00963 Str_red()->Find_iv_and_mult(def,&iv_def, use, &iv_use, &multiplier);
00964
00965 if ( Tracing() ) {
00966 fprintf( TFile, "Repair_injury_real_real: iv_def: " );
00967 iv_def->Print(0,TFile);
00968 fprintf( TFile, "Repair_injury_real_real: iv_use: " );
00969 iv_use->Print(0,TFile);
00970 fprintf( TFile, "Repair_injury_real_real: multi: " );
00971 if ( multiplier != NULL )
00972 multiplier->Print(0,TFile);
00973 else
00974 fprintf( TFile, "1\n" );
00975 }
00976
00977 CODEREP *new_t = Repair_injury_rec(iv_def,iv_use, multiplier, temp,
00978 temp_is_owner ? use->Occurrence() : NULL);
00979 return new_t;
00980 }
00981 }
00982
00983
00984
00985
00986
00987
00988
00989
00990
00991
00992 CODEREP *
00993 CSE::Repair_injury_real_phi_opnd( EXP_OCCURS *def, EXP_OCCURS *use, CODEREP *temp ) const
00994 {
00995 Is_True( use->Occ_kind() == EXP_OCCURS::OCC_PHI_PRED_OCCUR,
00996 ("CSE::Repair_injury_real_phi_opnd: not phi-pred-occur") );
00997
00998
00999
01000
01001
01002 if ( def->Occurrence() == use->Occurrence() ) {
01003
01004 Is_Trace(Tracing(), (TFile,
01005 "CSE::Repair_injury_real_phi_opnd: def/use match\n"));
01006 return temp;
01007 }
01008 #if 0
01009 if (use->Occurrence() == NULL) {
01010
01011 CODEREP *pred_occur = Etable()->Phi_pred_cr( use->Bb() );
01012 use->Set_occurrence( pred_occur );
01013 }
01014 #endif
01015 CODEREP *iv_def, *iv_use, *multiplier;
01016 Str_red()->Find_iv_and_mult( def, &iv_def, use, &iv_use, &multiplier);
01017 #if 0
01018 if (use->Occurrence()->Coderep_id() == 0)
01019
01020 use->Set_occurrence( NULL );
01021 #endif
01022 if ( Tracing() ) {
01023 fprintf( TFile, "Repair_injury_real_phi_opnd: iv_def: " );
01024 iv_def->Print(0,TFile);
01025 fprintf( TFile, "Repair_injury_real_phi_opnd: iv_use: " );
01026 iv_use->Print(0,TFile);
01027 fprintf( TFile, "Repair_injury_real_phi_opnd: multi: " );
01028 if ( multiplier != NULL )
01029 multiplier->Print(0,TFile);
01030 else
01031 fprintf( TFile, "1\n" );
01032 }
01033
01034 CODEREP *new_t = Repair_injury_rec( iv_def, iv_use, multiplier, temp, NULL);
01035 return new_t;
01036 }
01037
01038
01039
01040
01041
01042
01043
01044
01045
01046
01047 CODEREP *
01048 CSE::Repair_injury_phi_real( EXP_OCCURS *def, EXP_OCCURS *use, CODEREP *temp,
01049 BOOL temp_is_owner) const
01050 {
01051 CODEREP *iv_def, *iv_use, *multiplier;
01052
01053
01054 Str_red()->Find_iv_and_mult( def, &iv_def, use, &iv_use, &multiplier);
01055
01056 if ( Tracing() ) {
01057 fprintf( TFile, "Repair_injury_phi_real: iv_def: " );
01058 iv_def->Print(0,TFile);
01059 fprintf( TFile, "Repair_injury_phi_real: iv_use: " );
01060 iv_use->Print(0,TFile);
01061 fprintf( TFile, "Repair_injury_phi_real: multi: " );
01062 if ( multiplier != NULL )
01063 multiplier->Print(0,TFile);
01064 else
01065 fprintf( TFile, "1\n" );
01066 }
01067
01068 CODEREP *new_t = Repair_injury_rec( iv_def, iv_use, multiplier, temp,
01069 temp_is_owner ? use->Occurrence() : NULL);
01070 return new_t;
01071 }
01072
01073
01074
01075
01076
01077
01078
01079
01080
01081
01082 CODEREP *
01083 CSE::Repair_injury_phi_phi_opnd( EXP_OCCURS *def, EXP_OCCURS *use,
01084 CODEREP *temp ) const
01085 {
01086 Is_True( use->Occ_kind() == EXP_OCCURS::OCC_PHI_PRED_OCCUR,
01087 ("CSE::Repair_injury_phi_phi_opnd: not phi-pred-occur") );
01088
01089 CODEREP *iv_def, *iv_use, *multiplier;
01090 #if 0
01091 if (use->Occurrence() == NULL) {
01092
01093 CODEREP *pred_occur = Etable()->Phi_pred_cr( use->Bb() );
01094 use->Set_occurrence( pred_occur );
01095 }
01096 #endif
01097
01098 Str_red()->Find_iv_and_mult( def, &iv_def, use, &iv_use, &multiplier);
01099 #if 0
01100 if (use->Occurrence()->Coderep_id() == 0)
01101
01102 use->Set_occurrence( NULL );
01103 #endif
01104 if ( Tracing() ) {
01105 fprintf(TFile, "Repair_injury_phi_phi_opnd: phi-pred in BB%d\n",
01106 use->Bb()->Id());
01107 fprintf( TFile, "Repair_injury_phi_phi_opnd: iv_def: " );
01108 iv_def->Print(0,TFile);
01109 fprintf( TFile, "Repair_injury_phi_phi_opnd: iv_use: " );
01110 iv_use->Print(0,TFile);
01111 fprintf( TFile, "Repair_injury_phi_phi_opnd: multi: " );
01112 if ( multiplier != NULL )
01113 multiplier->Print(0,TFile);
01114 else
01115 fprintf( TFile, "1\n" );
01116 }
01117
01118 CODEREP *new_t = Repair_injury_rec( iv_def, iv_use, multiplier, temp, NULL);
01119 return new_t;
01120 }
01121
01122 #if 0
01123
01124
01125
01126 CODEREP *
01127 CSE::Save_and_replace(EXP_OCCURS *tos)
01128 {
01129 CODEREP *temp_cr = tos->Get_temp_cr(_worklist, _etable->Htable());
01130 if (temp_cr->Defstmt() == NULL) {
01131 Is_True(tos->Save_to_temp(),
01132 ("CSE::Save_and_replace: Incorrect Save_to_temp() from step 5"));
01133
01134 if (tos->Occurs_as_lvalue()) {
01135 Save_occurrence_as_l_value(tos);
01136 } else {
01137 Save_real_occurrence(tos);
01138
01139 Etable()->Replace_by_temp(tos, tos->Temp_cr());
01140 }
01141 _worklist->Inc_save_count();
01142 }
01143 return temp_cr;
01144 }
01145 #endif
01146
01147
01148
01149
01150
01151
01152
01153
01154 void
01155 CSE::Do_cse_pass_1(void)
01156 {
01157
01158 EXP_ALL_OCCURS_ITER exp_occ_iter(_worklist->Real_occurs().Head(),
01159 NULL,
01160 _worklist->Phi_occurs().Head(),
01161 _worklist->Phi_pred_occurs().Head(),
01162 _etable->Exit_occurs().Head());
01163
01164 EXP_OCCURS *occur, *tos;
01165 CODEREP *tempcr;
01166 STMTREP *savestmt;
01167
01168 FOR_ALL_NODE(occur, exp_occ_iter, Init()) {
01169
01170 switch (occur->Occ_kind()) {
01171
01172 case EXP_OCCURS::OCC_REAL_OCCUR:
01173 if (occur->Occurrence()->Is_flag_set(CF_OWNED_BY_TEMP)) {
01174 BOOL dont_rehash;
01175 if (occur->Save_to_temp()) {
01176 if (occur->T_ver_owns_coderep())
01177 occur->Set_temp_cr(occur->Occurrence());
01178
01179 dont_rehash = occur->Occurs_as_hoisted() ||
01180 occur->T_ver_owns_coderep();
01181 Etable()->No_replace(occur, dont_rehash);
01182 }
01183 else if (occur->Delete_comp()) {
01184 if (!occur->Occurs_as_hoisted()) {
01185 tos = occur->Def_occur();
01186 if (! tos->T_ver_owns_coderep())
01187 Etable()->No_replace(occur, FALSE);
01188 }
01189 }
01190 else Etable()->No_replace(occur, FALSE);
01191 }
01192 break;
01193
01194 case EXP_OCCURS::OCC_PHI_PRED_OCCUR:
01195 break;
01196
01197 case EXP_OCCURS::OCC_PHI_OCCUR:
01198 {
01199 EXP_PHI *exp_phi = occur->Exp_phi();
01200 if (exp_phi->Will_b_avail()) {
01201 if (!exp_phi->Identity()) {
01202 if (occur->Occurrence()->Is_flag_set(CF_OWNED_BY_TEMP)) {
01203 if (occur->T_ver_owns_coderep())
01204 occur->Set_temp_cr(occur->Occurrence());
01205 Etable()->No_replace(occur, TRUE);
01206 }
01207 }
01208 }
01209 }
01210 break;
01211
01212 case EXP_OCCURS::OCC_EXIT_OCCUR:
01213 break;
01214
01215 default:
01216 Is_True(FALSE, ("CSE::Do_cse_pass_1, unknown occurrence kind: %d",
01217 occur->Occ_kind()));
01218 break;
01219 }
01220 }
01221 }
01222
01223
01224
01225
01226
01227
01228 void
01229 CSE::Do_cse_pass_2(void)
01230 {
01231
01232 EXP_ALL_OCCURS_ITER exp_occ_iter(_worklist->Real_occurs().Head(),
01233 NULL,
01234 _worklist->Phi_occurs().Head(),
01235 _worklist->Phi_pred_occurs().Head(),
01236 _etable->Exit_occurs().Head());
01237
01238 EXP_OCCURS *occur, *tos;
01239 CODEREP *tempcr;
01240 STMTREP *savestmt;
01241
01242 FOR_ALL_NODE(occur, exp_occ_iter, Init()) {
01243
01244 switch (occur->Occ_kind()) {
01245
01246 case EXP_OCCURS::OCC_REAL_OCCUR:
01247 if (occur->Sunk_lvalue()) {
01248 if (occur->Occurs_as_lvalue()) {
01249
01250 }
01251 else {
01252
01253 occur->Set_temp_cr(NULL);
01254 occur->Get_temp_cr(_worklist, _etable->Htable());
01255 Save_shrunk_lr_def(occur);
01256
01257 Etable()->Replace_by_temp(occur, occur->Temp_cr());
01258 _worklist->Inc_save_count();
01259 }
01260 }
01261 else if (occur->Save_to_temp()) {
01262
01263 if ( occur->Injured_occ() ) {
01264
01265
01266 Is_Trace( Tracing(),
01267 (TFile, "CSE::Do_cse_pass_2: ignore 'saved' injured"
01268 " real in bb:%d\n", occur->Bb()->Id()) );
01269 }
01270
01271 if (! occur->T_ver_owns_coderep())
01272 occur->Get_temp_cr(_worklist, _etable->Htable());
01273 else
01274 Change_expr_to_temp(occur->Temp_cr(), _worklist, _etable->Htable());
01275
01276 if (occur->Occurs_as_lvalue()) {
01277 Is_True(_worklist->Exp()->Kind() == CK_IVAR || _worklist->Exp()->Kind() == CK_VAR,
01278 ("CSE::Do_cse_pass_2: only ivars/vars can be marked OCC_AS_L_VALUE"));
01279 Save_occurrence_as_l_value(occur);
01280 _worklist->Inc_save_count();
01281 } else if (occur->Occurs_as_hoisted()) {
01282 Save_hoisted_occurrence(occur);
01283 _worklist->Inc_save_count();
01284 }
01285 else {
01286 Save_real_occurrence(occur);
01287 if (! occur->T_ver_owns_coderep()) {
01288
01289 Etable()->Replace_by_temp(occur, occur->Temp_cr());
01290 }
01291 else {
01292
01293
01294 _etable->Find_new_1st_order_exprs(occur, occur->Temp_cr());
01295 }
01296 _worklist->Inc_save_count();
01297
01298
01299 occur->Set_enclose_stmt(occur->Temp_cr()->Defstmt());
01300
01301
01302
01303
01304
01305
01306
01307 }
01308 }
01309 else if (occur->Delete_comp()) {
01310 if (!occur->Occurs_as_hoisted()) {
01311 tos = occur->Def_occur();
01312
01313
01314 _worklist->Inc_reload_count();
01315 tempcr = tos->Temp_cr();
01316 Is_True(tempcr != NULL, ("CSE::Do_cse_pass_2: wrong logic"));
01317 if (tos->Occ_kind() == EXP_OCCURS::OCC_REAL_OCCUR) {
01318
01319 Is_True(tempcr->Defstmt() != NULL,
01320 ("CSE::Do_cse_pass_2: at a reload location, temp cr has no Defstmt"));
01321
01322 if ( occur->Injured_occ() ) {
01323
01324 if (occur->Occurrence()->Kind() == CK_VAR)
01325
01326 tempcr = occur->Occurrence();
01327 else tempcr = Repair_injury_real_real( tos, occur, tempcr,
01328 tos->T_ver_owns_coderep());
01329 }
01330 } else {
01331 Is_True(tos->Occ_kind() == EXP_OCCURS::OCC_PHI_OCCUR,
01332 ("CSE::Do_cse_pass_2: version that is same but not defined by "
01333 "real occurrence must be defined by phi occurrence"));
01334
01335 if ( occur->Injured_occ() ) {
01336
01337 if (occur->Occurrence()->Kind() == CK_VAR)
01338
01339 tempcr = occur->Occurrence();
01340 else tempcr = Repair_injury_phi_real( tos, occur, tempcr,
01341 tos->T_ver_owns_coderep());
01342 }
01343 }
01344
01345 if (Etable()->Pre_kind() == PK_LPRE &&
01346 (occur->Stmt()->Op() == OPC_TRUEBR ||
01347 occur->Stmt()->Op() == OPC_FALSEBR) &&
01348 occur->Bb()->Loop() != NULL) {
01349 BB_NODE *end_bb = occur->Bb()->Loop()->End();
01350 if (end_bb) {
01351 STMTREP *term_test = end_bb->Branch_stmtrep();
01352 if (term_test != NULL &&
01353 occur->Bb() == end_bb &&
01354 occur->Stmt() == term_test &&
01355 (occur->Occurrence() == term_test->Rhs() ||
01356 occur->Occurrence() == term_test->Rhs()->Opnd(0)))
01357 occur->Bb()->Loop()->Set_iv_replacement(tempcr);
01358 }
01359 }
01360
01361 if (!tos->T_ver_owns_coderep()) {
01362
01363 Etable()->Replace_by_temp(occur, tempcr);
01364 }
01365 else {
01366
01367
01368 _etable->Find_new_1st_order_exprs(occur, tempcr);
01369 }
01370 }
01371 }
01372 break;
01373
01374 case EXP_OCCURS::OCC_PHI_PRED_OCCUR:
01375 {
01376 if (occur->Save_to_temp()) {
01377 Is_True(occur->Def_occur() == NULL,
01378 ("CSE::Do_cse_pass_2: at a save location, version's OCCUR not NULL"));
01379 if (occur->Occurrence()->Is_flag_set(CF_OWNED_BY_TEMP)) {
01380
01381 Etable()->No_replace(occur, TRUE);
01382 }
01383
01384
01385 occur->Get_temp_cr(_worklist, _etable->Htable());
01386 Save_real_occurrence(occur);
01387 }
01388 else if (occur->Sunk_lvalue()) {
01389 occur->Get_temp_cr(_worklist, _etable->Htable());
01390 Save_shrunk_lr_def(occur);
01391 _worklist->Inc_save_count();
01392 }
01393
01394
01395 BB_LIST_ITER bb_iter;
01396 BB_NODE *phi_bb;
01397 BB_NODE *pred_bb = occur->Bb();
01398
01399 tos = NULL;
01400
01401 FOR_ALL_ELEM (phi_bb, bb_iter, Init(pred_bb->Succ())) {
01402 if (phi_bb->Dom_dfs_id() > pred_bb->Dom_dfs_id())
01403 continue;
01404 EXP_PHI *exp_phi = _etable->Lookup_exp_phi(phi_bb,
01405 _worklist->Exp());
01406 if (exp_phi != NULL) {
01407 INT32 opnd_num = phi_bb->Pred()->Pos(pred_bb);
01408 if (exp_phi->Opnd(opnd_num) != NULL &&
01409 exp_phi->Will_b_avail()) {
01410
01411 Is_True(tos == NULL ||
01412 tos == exp_phi->Opnd(opnd_num),
01413 ("CSE::Do_cse_pass_2: TOS disagreement"));
01414 tos = exp_phi->Opnd(opnd_num);
01415 tempcr = NULL;
01416 if (tos->Occ_kind() == EXP_OCCURS::OCC_REAL_OCCUR ||
01417 tos->Occ_kind() == EXP_OCCURS::OCC_PHI_PRED_OCCUR) {
01418
01419 Is_True(tos->Temp_cr()->Defstmt() != NULL,
01420 ("CSE::Do_cse_pass_2: at a phi_pred location, temp cr "
01421 "has no Defstmt"));
01422
01423 if ( exp_phi->Injured(opnd_num) ) {
01424
01425 Is_True(!tos->Injured_occ(),
01426 ("CSE::Do_cse_pass_2: avail_def's "
01427 "injury flag should have been reset"));
01428 if (occur->Occurrence()->Kind() == CK_VAR)
01429
01430 tempcr = occur->Occurrence();
01431 else tempcr = Repair_injury_real_phi_opnd( tos, occur, tos->Temp_cr() );
01432 }
01433 }
01434 else {
01435 Is_True(tos->Occ_kind() == EXP_OCCURS::OCC_PHI_OCCUR,
01436 ("CSE::Do_cse_pass_2: version that is same but not "
01437 "defined by real occurrence must be defined "
01438 "by phi occurrence"));
01439 Is_True(tos->Temp_cr() != NULL,
01440 ("CSE::Do_cse_pass_2: wrong logic"));
01441
01442 if ( exp_phi->Injured(opnd_num) ) {
01443
01444 if (occur->Occurrence()->Kind() == CK_VAR)
01445
01446 tempcr = occur->Occurrence();
01447 else tempcr = Repair_injury_phi_phi_opnd( tos, occur, tos->Temp_cr() );
01448 }
01449 }
01450
01451
01452 if (!exp_phi->Identity()) {
01453
01454 PHI_NODE *tempphi = _etable->Lookup_var_phi(
01455 phi_bb, tos->Temp_cr()->Aux_id());
01456 if ( exp_phi->Injured(opnd_num) ) {
01457 Is_True( tempcr != NULL,
01458 ("CSE::Do_cse_pass_2: no injured tempcr"));
01459 tempphi->Set_opnd(opnd_num, tempcr);
01460 }
01461 else if (tempphi->Opnd(opnd_num) == 0)
01462 tempphi->Set_opnd(opnd_num, tos->Temp_cr());
01463 else Is_True(tempphi->OPND(opnd_num) == tos->Temp_cr(),
01464 ("CSE::Do_cse_pass_2: contradicatory temp phi operand"));
01465 }
01466 }
01467 }
01468 }
01469 break;
01470 }
01471
01472 case EXP_OCCURS::OCC_PHI_OCCUR:
01473 {
01474 EXP_PHI *exp_phi = occur->Exp_phi();
01475 if (
01476 exp_phi->Will_b_avail()) {
01477 if (!exp_phi->Identity()) {
01478 #if 0
01479
01480 if (WOPT_Enable_Avoid_Rehash &&
01481 _etable->Lftr()->Is_lftr_exp(_worklist->Exp()) &&
01482 occur->Occurrence()->Is_flag_set(CF_OWNED_BY_TEMP)) {
01483
01484 CODEREP *newcr = CXX_NEW_VARIANT(CODEREP(*occur->Occurrence()),
01485 occur->Occurrence()->Extra_space_used(), &_mempool);
01486 occur->Set_occurrence(newcr);
01487 }
01488 #endif
01489 if (!occur->T_ver_owns_coderep()) {
01490 Is_True(occur->Temp_cr() == NULL,
01491 ("CSE::Do_cse_pass_1: at expression phi, temp_cr of result not NULL"));
01492 occur->Get_temp_cr(_worklist, _etable->Htable());
01493 }
01494 else {
01495 Change_expr_to_temp(occur->Temp_cr(), _worklist, _etable->Htable());
01496 }
01497
01498
01499 PHI_NODE *tempphi = exp_phi->Bb()->Phi_list()->
01500 New_phi_node(_worklist->Preg(),
01501 _etable->Htable()->Ssa()->Mem_pool(),
01502 exp_phi->Bb());
01503 if (exp_phi->Is_live()) tempphi->Set_live();
01504 tempphi->Set_res_is_cr();
01505 tempphi->Set_incomplete();
01506 tempphi->Set_result(exp_phi->Result()->Temp_cr());
01507 for (INT32 i = 0; i < tempphi->Size(); i++) {
01508 if (exp_phi->Pred(i)->Bb()->Dom_dfs_id() >=
01509 exp_phi->Bb()->Dom_dfs_id())
01510
01511
01512
01513 continue;
01514 tos = exp_phi->Opnd(i);
01515 Is_True(tos != NULL, ("CSE::Do_cse_pass_2: NULL exp phi operand"));
01516 if ( exp_phi->Injured(i) ) {
01517 if (tos->Occ_kind() == EXP_OCCURS::OCC_REAL_OCCUR ||
01518 tos->Occ_kind() == EXP_OCCURS::OCC_PHI_PRED_OCCUR) {
01519 if (exp_phi->Pred(i)->Occurrence()->Kind() == CK_VAR)
01520
01521 tempcr = exp_phi->Pred(i)->Occurrence();
01522 else tempcr = Repair_injury_real_phi_opnd( tos, exp_phi->Pred(i),
01523 tos->Temp_cr() );
01524 }
01525 else {
01526 Is_True(tos->Occ_kind() == EXP_OCCURS::OCC_PHI_OCCUR,
01527 ("CSE::Do_cse_pass_2: version that is same but "
01528 "not defined by real occurrence must be defined "
01529 "by phi occurrence"));
01530 if (exp_phi->Pred(i)->Occurrence()->Kind() == CK_VAR)
01531
01532 tempcr = exp_phi->Pred(i)->Occurrence();
01533 else tempcr = Repair_injury_phi_phi_opnd( tos, exp_phi->Pred(i),
01534 tos->Temp_cr() );
01535 }
01536 tempphi->Set_opnd(i, tempcr);
01537 }
01538 else {
01539 Is_True(tos->Temp_cr() != NULL,
01540 ("CSE::Do_cse_pass_2: temp_cr not set for exp phi operand"));
01541 tempphi->Set_opnd(i, tos->Temp_cr());
01542 }
01543 }
01544
01545
01546 _etable->Htable()->Enter_var_phi_hash(tempphi);
01547 occur->Temp_cr()->Set_flag(CF_DEF_BY_PHI);
01548 occur->Temp_cr()->Set_defphi(tempphi);
01549 _worklist->Inc_temp_phi_count();
01550 }
01551 else {
01552
01553
01554
01555
01556
01557
01558
01559
01560
01561
01562 if (exp_phi->Identity_injured()) {
01563
01564 if (exp_phi->Any_opnd_injured()) {
01565 if (occur->Occurrence()->Kind() == CK_VAR) {
01566
01567 tempcr = exp_phi->Result()->Occurrence();
01568 }
01569 else {
01570 INT32 i;
01571
01572 for (i = 0; i < exp_phi->Opnd_count(); i++) {
01573 if (exp_phi->Injured(i)) {
01574 break;
01575 }
01576 }
01577 FmtAssert(i < exp_phi->Opnd_count(),
01578 ("CSE::Do_cse_pass_2: cannot find "
01579 "injured operand"));
01580 tos = exp_phi->Opnd(i);
01581
01582 Is_Trace(Tracing(), (TFile, "Found inj opnd; Tos is :\n"));
01583 Is_Trace_cmd(Tracing(), tos->Print(TFile));
01584
01585 if (tos->Occ_kind() == EXP_OCCURS::OCC_REAL_OCCUR ||
01586 tos->Occ_kind() == EXP_OCCURS::OCC_PHI_PRED_OCCUR) {
01587 tempcr = Repair_injury_real_phi_opnd(tos,
01588 exp_phi->Pred(i),
01589 tos->Temp_cr());
01590 }
01591 else {
01592 Is_True(tos->Occ_kind() == EXP_OCCURS::OCC_PHI_OCCUR,
01593 ("CSE::Do_cse_pass_2: same version "
01594 "not def by real must be def by phi"));
01595 tempcr = Repair_injury_phi_phi_opnd(tos,
01596 exp_phi->Pred(i),
01597 tos->Temp_cr());
01598 }
01599 }
01600 }
01601 else {
01602 INT32 i;
01603 tempcr = NULL;
01604 for (i = 0; i < exp_phi->Opnd_count(); i++) {
01605 Is_True(tempcr == NULL ||
01606 exp_phi->Opnd(i)->Temp_cr() == NULL ||
01607 exp_phi->Opnd(i)->Temp_cr() == tempcr,
01608 ("CSE::Do_cse_pass_2: operands of identity phi "
01609 "must have same temp"));
01610
01611 tempcr = exp_phi->Opnd(i)->Temp_cr();
01612 if (tempcr != NULL) {
01613 break;
01614 }
01615 }
01616 FmtAssert(tempcr != NULL,
01617 ("CSE::Do_cse_pass_2: Can't find injured "
01618 "opnd w/known identity"));
01619
01620
01621
01622 for (i = 0; i < exp_phi->Opnd_count(); i++) {
01623 Is_True(exp_phi->Opnd(i)->Temp_cr() == NULL ||
01624 exp_phi->Opnd(i)->Temp_cr() == tempcr,
01625 ("CSE::Do_cse_pass_2: operands of identity phi "
01626 "must have same temp"));
01627 }
01628 }
01629 Is_True(tempcr != NULL, ("CSE::Do_cse_pass_2: "
01630 "injured tempcr must not be NULL"));
01631 occur->Set_temp_cr(tempcr);
01632 }
01633 else {
01634
01635 occur->Set_temp_cr(exp_phi->Identical_to()->Temp_cr());
01636 }
01637 Is_True(occur->Temp_cr() != NULL,
01638 ("CSE::Do_cse_pass_2: temp identity must be known; "
01639 "tempcr=0x%lx", tempcr));
01640 }
01641 }
01642 }
01643 break;
01644
01645 case EXP_OCCURS::OCC_EXIT_OCCUR:
01646 break;
01647
01648
01649 default:
01650 Is_True(FALSE, ("CSE::Do_cse_pass_2, unknown occurrence kind: %d",
01651 occur->Occ_kind()));
01652 break;
01653 }
01654 }
01655
01656
01657 if (_etable->Lftr()->Lftr_on() && !_worklist->No_lftr()) {
01658 EXP_OCCURS_PAIR *comp_list = _etable->Lftr()->Exp_hash(_worklist);
01659 if (!comp_list->Is_Empty()) {
01660 Is_Trace(_etable->Lftr()->Trace(),
01661 (TFile,"\n====== 2nd Step 6 loop: LFTR ======\n"));
01662 EXP_ALL_REAL_ITER exp_iter(NULL, comp_list);
01663 FOR_ALL_NODE(occur, exp_iter, Init()) {
01664
01665 Is_True(occur->Occ_kind() == EXP_OCCURS::OCC_COMP_OCCUR,
01666 ("CSE::Do_cse_no_stack, illegal occur kind"));
01667 _etable->Lftr()->
01668 Replace_comparison(occur,
01669 WOPT_Enable_New_SR &&
01670 Str_red()->Candidate_opc(_worklist->
01671 Exp()->Op()));
01672 }
01673 }
01674 }
01675
01676
01677 _etable->Inc_cse_reloads(_worklist->Reload_count());
01678 _etable->Inc_cse_saves(_worklist->Save_count());
01679 _etable->Inc_inserted_saves(_worklist->Insert_count());
01680 _etable->Inc_temp_phis(_worklist->Temp_phi_count());
01681 _etable->Inc_temp_owners(_worklist->Temp_owner_count());
01682 }
01683
01684
01685
01686
01687 CSE::CSE(ETABLE *etable, EXP_WORKLST *worklist)
01688 {
01689 OPT_POOL_Initialize(&_mempool, "pre cse mempool", FALSE, -1);
01690 OPT_POOL_Push(&_mempool, -1);
01691
01692 _etable = etable;
01693 _worklist = worklist;
01694 _str_red = etable->Str_red();
01695 _tracing = etable->Tracing();
01696 }
01697
01698
01699
01700
01701 CSE::~CSE(void)
01702 {
01703 OPT_POOL_Pop(&_mempool, -1);
01704 OPT_POOL_Delete(&_mempool, -1);
01705 }
01706
01707
01708
01709
01710 void
01711 EXP_WORKLST::Generate_save_reload(ETABLE *etable)
01712 {
01713 CSE cse(etable, this);
01714 if (WOPT_Enable_Avoid_Rehash) {
01715 cse.Do_cse_pass_1();
01716 if (_exp->Is_flag_set(CF_OWNED_BY_TEMP)) {
01717
01718 CODEREP *x = _exp;
01719
01720 switch (x->Kind()) {
01721 case CK_VAR:
01722 break;
01723 case CK_IVAR:
01724 x->Ilod_base()->IncUsecnt();
01725 if (x->Opr() == OPR_MLOAD)
01726 x->Mload_size()->IncUsecnt();
01727 else if (x->Opr() == OPR_ILOADX)
01728 x->Index()->IncUsecnt();
01729 break;
01730 default:
01731 for (INT32 i = 0; i < x->Kid_count(); i++)
01732 x->Opnd(i)->IncUsecnt();
01733 }
01734 _exp = etable->Rehash_exp(x, etable->Gvn(x));
01735 _exp->Set_e_num(x->E_num());
01736 _exp->DecUsecnt();
01737 }
01738 }
01739 cse.Do_cse_pass_2();
01740
01741
01742
01743
01744
01745
01746
01747 etable->Perform_deferred_ocopy_and_get_new_exprs(this);
01748
01749 if (etable->Tracing()) {
01750 fprintf(TFile, "====== After ETABLE::Generate_save_reload ======\n");
01751 Print(TFile);
01752 }
01753 }