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 #ifdef USE_PCH
00053 #include "opt_pch.h"
00054 #endif // USE_PCH
00055 #pragma hdrstop
00056
00057
00058 #define opt_estr_CXX "opt_estr.cxx"
00059 #ifdef _KEEP_RCS_ID
00060 static char *rcs_id = opt_estr_CXX"$Revision: 1.12 $";
00061 #endif
00062
00063 #include "defs.h"
00064 #include "config.h"
00065 #include "cxx_memory.h"
00066
00067 #include "opt_base.h"
00068 #include "opt_config.h"
00069 #include "opt_bb.h"
00070 #include "opt_cfg.h"
00071 #include "opt_htable.h"
00072 #include "opt_etable.h"
00073 #include "opt_estr.h"
00074 #include "opt_ssa.h"
00075 #include "opt_wn.h"
00076 #include "tracing.h"
00077 #include "opt_cvtl_rule.h"
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174 BOOL
00175 STR_RED::Is_cvt_linear( const CODEREP *cr ) const
00176 {
00177
00178 if (MTYPE_size_min(cr->Dsctyp()) < MTYPE_size_min(MTYPE_I4)) {
00179 if (WOPT_Enable_STR_Short && (MTYPE_size_min(cr->Dsctyp()) == MTYPE_size_min(MTYPE_I2))) {
00180 return TRUE;
00181 }
00182 return FALSE;
00183 }
00184
00185
00186 if (! Allow_wrap_around_opt &&
00187 MTYPE_size_min(cr->Dsctyp()) != MTYPE_size_min(cr->Dtyp()))
00188 return FALSE;
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198 if (cr->Dtyp() == cr->Dsctyp())
00199 return TRUE;
00200
00201 if ((cr->Dtyp() == MTYPE_U8 || cr->Dtyp() == MTYPE_I8) &&
00202 cr->Dsctyp() == MTYPE_I4)
00203 return TRUE;
00204
00205
00206 if (MTYPE_size_min(cr->Dtyp()) < MTYPE_size_min(cr->Dsctyp()))
00207 return TRUE;
00208
00209
00210 if ((cr->Dtyp() == MTYPE_U8 || cr->Dtyp() == MTYPE_I8)
00211 && cr->Dsctyp() == MTYPE_U4) {
00212 #ifndef TARG_X8664
00213 Is_True(cr->Opnd(0)->Kind() == CK_VAR,
00214 ("STR_RED::Is_cvt_linear: invalid str red expr."));
00215 #ifdef TARG_NVISA
00216
00217
00218
00219
00220 if (Htable()->Opt_stab()->Aux_stab_entry(cr->Opnd(0)->Aux_id())->EPRE_temp())
00221 DevWarn("previously would not allow strength reduction on this cvt");
00222 #else
00223 if (!Htable()->Opt_stab()->Aux_stab_entry(cr->Opnd(0)->Aux_id())->EPRE_temp())
00224 #endif
00225 #endif
00226 return TRUE;
00227 }
00228
00229 return FALSE;
00230 }
00231
00232
00233 BOOL
00234 STR_RED::Is_implicit_cvt_linear(MTYPE opc_type, MTYPE opnd_type) const
00235 {
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247 if (! Allow_wrap_around_opt &&
00248 MTYPE_size_min(opc_type) != MTYPE_size_min(opnd_type))
00249 return FALSE;
00250 return TRUE;
00251 }
00252
00253
00254
00255
00256
00257
00258 CODEREP *
00259 STR_RED::Matches_lhs( const CODEREP *lhs, const CODEREP *rhs ) const
00260 {
00261 Is_True( lhs->Kind() == CK_VAR,
00262 ("STR_RED::Matches_lhs: Lhs not a var") );
00263 const IDTYPE lhs_id = lhs->Aux_id();
00264
00265 if ( rhs->Kind() == CK_VAR ) {
00266 if ( lhs_id == rhs->Aux_id() &&
00267 MTYPE_size_min(lhs->Dsctyp()) <= MTYPE_size_min(rhs->Dsctyp()) ) {
00268
00269 return (CODEREP*)rhs;
00270 }
00271 }
00272 else if ( rhs->Kind() == CK_OP ) {
00273 const OPERATOR opr = rhs->Opr();
00274 if (opr == OPR_PAREN)
00275 return Matches_lhs( lhs, rhs->Opnd(0) );
00276
00277
00278 }
00279
00280 return NULL;
00281 }
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297 #define INJURY_USE_FREQ_CUTOFF_RATIO 2.0
00298
00299 BOOL
00300 STR_RED::Update_happens_rarely_enough( BB_NODE *update_bb,
00301 BB_NODE *innermost_use_bb,
00302 const CODEREP *use_expr) const
00303 {
00304 if (Cfg()->Feedback ()) {
00305 FB_FREQ freq1 = Cfg()->Feedback()->Get_node_freq_out (update_bb->Id ());
00306 FB_FREQ freq2 =
00307 Cfg()->Feedback()->Get_node_freq_out (innermost_use_bb->Id ());
00308
00309 if (freq1.Known () && freq2.Known ())
00310 return (freq1 <= freq2 * INJURY_USE_FREQ_CUTOFF_RATIO);
00311 }
00312 return In_same_or_lower_nesting(innermost_use_bb, update_bb);
00313 }
00314
00315
00316
00317
00318
00319
00320 BOOL
00321 STR_RED::Is_const_or_loop_invar( CODEREP *expr, BB_NODE *bb ) const
00322 {
00323 if ( inCODEKIND(expr->Kind(), CK_LDA|CK_CONST|CK_RCONST) ) {
00324 return TRUE;
00325 }
00326 else {
00327 const BB_LOOP *loop = Cfg()->Find_innermost_loop_contains( bb );
00328 if ( loop &&
00329 loop->True_body_set()->MemberP( bb ) ) {
00330
00331
00332 if ( loop->Invariant_cr(expr) ) {
00333
00334
00335 if ( inCODEKIND(expr->Kind(), CK_VAR) ) {
00336 BB_NODE *defbb = expr->Defbb();
00337 if ( !defbb->Dominates(bb) ) {
00338 return FALSE;
00339 }
00340 }
00341
00342 return TRUE;
00343 }
00344 }
00345 }
00346
00347 return FALSE;
00348 }
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359 CODEREP *
00360 STR_RED::Find_real_defs_rhs( const CODEREP *var ) const
00361 {
00362
00363
00364 Is_True( var != NULL,
00365 ("STR_RED::Find_real_def: should not have called this function!") );
00366
00367 Is_True( var->Kind() == CK_VAR,
00368 ("STR_RED::Find_real_def: not a var") );
00369
00370 if ( var->Is_flag_set((CR_FLAG)(CF_DEF_BY_CHI|
00371 CF_IS_ZERO_VERSION)) )
00372 {
00373 FmtAssert( FALSE,
00374 ("STR_RED::Find_real_def: def'd by chi/zero-version") );
00375 }
00376 else if ( var->Is_flag_set(CF_DEF_BY_PHI) ) {
00377 PHI_NODE *phi = var->Defphi();
00378 CODEREP *real_rhs = NULL;
00379 BB_NODE *pred;
00380 BB_LIST_ITER pred_iter;
00381 INT pred_num = 0;
00382 FOR_ALL_ELEM( pred, pred_iter, Init(phi->Bb()->Pred()) ) {
00383
00384 CODEREP *opnd = phi->OPND(pred_num);
00385 CODEREP *tmp_rhs = Find_real_defs_rhs( opnd );
00386
00387
00388 Is_True( real_rhs == NULL || real_rhs->Match(tmp_rhs),
00389 ("STR_RED::Find_real_def: cr's don't match") );
00390
00391 real_rhs = tmp_rhs;
00392
00393 pred_num++;
00394 }
00395
00396 Is_True( real_rhs != NULL,
00397 ("STR_RED::Find_real_defs_rhs: no real_rhs found") );
00398 return real_rhs;
00399 }
00400 else {
00401 STMTREP *vardef = var->Defstmt();
00402 Is_True( OPERATOR_is_scalar_store (vardef->Opr()),
00403 ("STR_RED::Find_real_def: not def'd by store") );
00404
00405 return vardef->Rhs();
00406 }
00407
00408 return NULL;
00409 }
00410
00411
00412
00413
00414
00415 inline CODEREP *
00416 Str_red_get_fixed_operand( const CODEREP *cr, INT which_opnd )
00417 {
00418 Is_True( cr->Kind() == CK_OP,
00419 ("Str_red_get_fixed_operand: not an op") );
00420
00421 CODEREP *opnd = cr->Get_opnd(which_opnd);
00422 return opnd;
00423 }
00424
00425
00426
00427
00428
00429 INT
00430 STR_RED::Local_autoaggstr_reduction_threshold(BB_NODE *bb) const
00431 {
00432 if (! WOPT_Enable_Str_Red_Use_Context)
00433 return WOPT_Enable_Autoaggstr_Reduction_Threshold;
00434 const BB_LOOP *loop = Cfg()->Find_innermost_loop_contains( bb );
00435 if (loop == NULL)
00436 return WOPT_Enable_Autoaggstr_Reduction_Threshold;
00437 return MAX(0,
00438 WOPT_Enable_Autoaggstr_Reduction_Threshold - loop->Size_estimate()/18);
00439 }
00440
00441
00442
00443
00444
00445
00446
00447 BOOL
00448 STR_RED::Find_iv_and_incr( STMTREP *stmt, CODEREP **updated_iv,
00449 CODEREP **incr_amt, BOOL *is_add,
00450 BOOL aggstr_cand ) const
00451 {
00452 CODEREP *lhs = stmt->Lhs();
00453 CODEREP *rhs = stmt->Rhs();
00454
00455 Is_True( lhs->Kind() == CK_VAR,
00456 ("STR_RED::Find_iv_and_incr: Lhs not a var") );
00457
00458 if (aggstr_cand)
00459
00460
00461 if (stmt->Str_red_num() >= Local_autoaggstr_reduction_threshold(stmt->Bb()))
00462 return FALSE;
00463
00464
00465
00466
00467 if ( rhs->Kind() == CK_VAR && stmt->Iv_update() ) {
00468 rhs = Find_real_defs_rhs( rhs );
00469 }
00470
00471 if ( rhs->Kind() == CK_OP ) {
00472 const OPERATOR opr = rhs->Opr();
00473 if ( opr == OPR_ADD ) {
00474 CODEREP *rhs_iv;
00475 if ( (rhs_iv = Matches_lhs( lhs, rhs->Opnd(0) )) != NULL ) {
00476
00477 if ( Is_const_or_loop_invar( rhs->Opnd(1), stmt->Bb() ) ) {
00478 *updated_iv = rhs_iv;
00479 *incr_amt = Str_red_get_fixed_operand(rhs,1);
00480 *is_add = TRUE;
00481 return TRUE;
00482 }
00483 }
00484 else if ( (rhs_iv = Matches_lhs( lhs, rhs->Opnd(1) )) != NULL ) {
00485
00486 if ( Is_const_or_loop_invar( rhs->Opnd(0), stmt->Bb() ) ) {
00487 *updated_iv = rhs_iv;
00488 *incr_amt = Str_red_get_fixed_operand(rhs,0);
00489 *is_add = TRUE;
00490 return TRUE;
00491 }
00492 }
00493 }
00494 else if ( opr == OPR_SUB ) {
00495 CODEREP *rhs_iv;
00496 if ( (rhs_iv = Matches_lhs( lhs, rhs->Opnd(0) )) != NULL ) {
00497
00498 if ( Is_const_or_loop_invar( rhs->Opnd(1), stmt->Bb() ) ) {
00499 *updated_iv = rhs_iv;
00500 *incr_amt = Str_red_get_fixed_operand(rhs,1);
00501 *is_add = FALSE;
00502 return TRUE;
00503 }
00504 }
00505 }
00506 }
00507
00508 return FALSE;
00509 }
00510
00511
00512
00513
00514
00515
00516
00517
00518
00519
00520
00521
00522
00523
00524
00525 BOOL
00526 STR_RED::Determine_iv_update( STMTREP *stmt, CODEREP **updated ) const
00527 {
00528
00529 if ( stmt->Not_iv_update() )
00530 return FALSE;
00531 if ( stmt->Iv_update() ) {
00532
00533 if ( updated == NULL ) {
00534 return TRUE;
00535 }
00536 }
00537
00538
00539
00540
00541 const OPERATOR opr = stmt->Opr();
00542 if (! OPERATOR_is_scalar_store (opr) ||
00543 !MTYPE_is_integral(OPCODE_desc(stmt->Op())) ||
00544 stmt->Volatile_stmt()) {
00545 stmt->Set_not_iv_update();
00546 return FALSE;
00547 }
00548
00549 CODEREP *dummy_iv, *dummy_incr;
00550 BOOL dummy_is_add;
00551 if ( Find_iv_and_incr(stmt, &dummy_iv, &dummy_incr, &dummy_is_add) ) {
00552 stmt->Set_iv_update();
00553 if ( updated ) *updated = dummy_iv;
00554 return TRUE;
00555 }
00556
00557
00558
00559
00560 if ( stmt->Iv_update() ) {
00561 if ( stmt->Rhs()->Kind() == CK_VAR ) {
00562
00563
00564 CODEREP *cur_rhs = stmt->Rhs();
00565 CODEREP *new_rhs = Find_real_defs_rhs( cur_rhs );
00566 stmt->Set_rhs( new_rhs );
00567 BOOL result = Determine_iv_update( stmt, updated );
00568 stmt->Set_rhs( cur_rhs );
00569
00570 Is_True( result,
00571 ("STR_RED::Determine_iv_update: same stmt, diff answer"));
00572
00573 return result;
00574 }
00575 }
00576
00577
00578 if ( stmt->Iv_update() ) {
00579 Is_Trace( Tracing(), (TFile, "STR_RED::Determine_iv_update:\n") );
00580 Is_Trace_cmd( Tracing(), stmt->Print(TFile) );
00581 Is_Trace( Tracing(), (TFile, "#########################\n") );
00582 Is_Trace_cmd( Tracing(), Cfg()->Print(TFile,TRUE) );
00583 }
00584
00585 Is_True( !stmt->Iv_update(),
00586 ("STR_RED::Determine_iv_update: same statement, different answer"));
00587 stmt->Set_not_iv_update();
00588 return FALSE;
00589 }
00590
00591
00592
00593
00594
00595
00596 BOOL
00597 STR_RED::In_same_or_lower_nesting( BB_NODE *bb1, BB_NODE *bb2 ) const
00598 {
00599 const BB_LOOP *loop1 = Cfg()->Find_innermost_loop_contains( bb1 );
00600 const BB_LOOP *loop2 = Cfg()->Find_innermost_loop_contains( bb2 );
00601
00602
00603 if ( loop2 == NULL ) {
00604
00605 return TRUE;
00606 }
00607 else {
00608
00609 return loop2->Contains(loop1);
00610 }
00611 }
00612
00613
00614
00615
00616
00617 BOOL
00618 STR_RED::Determine_iv_update_phi( PHI_NODE *phi,
00619 const CODEREP *cand_expr) const
00620 {
00621
00622 if ( phi->Opnd_not_iv_update() )
00623 return FALSE;
00624 if ( phi->Opnd_iv_update() )
00625 return TRUE;
00626
00627 BOOL iv_update = FALSE;
00628 PHI_OPND_ITER phi_opnd_iter(phi);
00629 CODEREP *opnd;
00630 INT opnd_num = 0;
00631 FOR_ALL_ELEM(opnd, phi_opnd_iter, Init()) {
00632
00633 if ( opnd->Is_flag_set(CF_IS_ZERO_VERSION) ) {
00634 iv_update = FALSE;
00635 break;
00636 }
00637
00638
00639 if ( ! opnd->Is_flag_set((CR_FLAG)(CF_DEF_BY_CHI|CF_DEF_BY_PHI)) ) {
00640 STMTREP *stmt = opnd->Defstmt();
00641 if ( Determine_iv_update( stmt, NULL ) ) {
00642
00643
00644
00645
00646 if (Update_happens_rarely_enough(stmt->Bb(),
00647 phi->Bb()->Nth_pred(opnd_num),
00648 cand_expr)) {
00649 iv_update = TRUE;
00650 }
00651 else {
00652 Is_Trace(Tracing(), (TFile, "STR_RED::Determine_iv_update_phi: "
00653 "loop nest level precludes.\n"));
00654 }
00655 }
00656 }
00657 ++opnd_num;
00658 }
00659
00660 if ( iv_update )
00661 phi->Set_opnd_iv_update();
00662 else
00663 phi->Set_opnd_not_iv_update();
00664
00665 return iv_update;
00666 }
00667
00668
00669
00670
00671
00672
00673 BOOL
00674 STR_RED::Updated_by_iv_update(const CODEREP *first,
00675 const CODEREP *last,
00676 CODEREP *invar,
00677 BB_NODE *innermost_use_bb,
00678 const CODEREP *cand_expr,
00679 BOOL aggstr_cand) const
00680 {
00681 Is_True( first->Kind() == CK_VAR && last->Kind() == CK_VAR,
00682 ("STR_RED::Updated_by_iv_update: non-VARs") );
00683 Is_True( first->Aux_id() == last->Aux_id(),
00684 ("STR_RED::Updated_by_iv_update: non-matching IDs") );
00685
00686
00687 if (last->Is_flag_set((CR_FLAG)( CF_DEF_BY_CHI|
00688 CF_DEF_BY_PHI|
00689 CF_IS_ZERO_VERSION)) )
00690 {
00691 return FALSE;
00692 }
00693
00694 STMTREP *last_def = last->Defstmt();
00695
00696 if (aggstr_cand)
00697
00698
00699 if (last_def->Str_red_num() >= Local_autoaggstr_reduction_threshold(last_def->Bb()))
00700 return FALSE;
00701
00702
00703
00704
00705 if (Update_happens_rarely_enough(last_def->Bb(), innermost_use_bb,
00706 cand_expr) ||
00707 Repaired(last_def)) {
00708 CODEREP *iv_on_rhs;
00709 if ( Determine_iv_update( last_def, &iv_on_rhs ) ) {
00710 Is_True( iv_on_rhs->Kind() == CK_VAR,
00711 ("STR_RED::Updated_by_iv_update: not a var") );
00712
00713
00714
00715 if (invar != NULL &&
00716 !Is_const_or_loop_invar(invar, last_def->Bb())) {
00717 return FALSE;
00718 }
00719
00720 if ( first == iv_on_rhs ) {
00721
00722 return TRUE;
00723 }
00724 else {
00725
00726
00727
00728 return Updated_by_iv_update(first, iv_on_rhs, invar,
00729 innermost_use_bb, cand_expr, aggstr_cand);
00730 }
00731 }
00732 }
00733 else {
00734 Is_Trace(Tracing(), (TFile, "-----\nSTR_RED::Updated_by_iv_update: "
00735 "chain broken by loop nesting\n"));
00736 Is_Trace(Tracing(), (TFile, " innermost use in BB%d\n",
00737 innermost_use_bb->Id()));
00738 Is_Trace(Tracing(), (TFile, " iv update in BB%d\n",
00739 last_def->Bb()->Id()));
00740 }
00741
00742 return FALSE;
00743 }
00744
00745
00746
00747
00748
00749
00750
00751 BOOL
00752 STR_RED::Defined_by_iv_update(const CODEREP *use_cr,
00753 const CODEREP *def_cr,
00754 CODEREP *invar,
00755 BB_NODE *use_bb,
00756 const CODEREP *cand_expr,
00757 BOOL aggstr_cand) const
00758 {
00759 Is_True(use_cr->Kind() != CK_OP, ("STR_RED::Defined_by_iv_update: CK_OP"));
00760
00761
00762 if ( use_cr->Kind() != CK_VAR ||
00763 use_cr->Is_flag_set((CR_FLAG)(CF_DEF_BY_CHI|CF_IS_ZERO_VERSION)))
00764 {
00765 Is_Trace(Tracing() && WOPT_Enable_Verbose,
00766 (TFile, "STR_RED::Defined_by_iv_update: "
00767 "def by chi/zero-ver --> FALSE\n"));
00768 return FALSE;
00769 }
00770
00771
00772 if ( use_cr->Is_flag_set(CF_DEF_BY_PHI) ) {
00773 Is_Trace(Tracing() && WOPT_Enable_Verbose,
00774 (TFile, "STR_RED::Defined_by_iv_update: "
00775 "def by phi\n"));
00776 PHI_NODE *phi = use_cr->Defphi();
00777
00778 if ( Determine_iv_update_phi(phi, cand_expr) ) {
00779
00780
00781 PHI_OPND_ITER phi_opnd_iter(phi);
00782 CODEREP *opnd;
00783 FOR_ALL_ELEM(opnd, phi_opnd_iter, Init()) {
00784 if (Updated_by_iv_update(def_cr, opnd, invar, use_bb, cand_expr, aggstr_cand)) {
00785 return TRUE;
00786 }
00787 }
00788 }
00789 }
00790 else {
00791
00792
00793 Is_Trace(Tracing() && WOPT_Enable_Verbose,
00794 (TFile, "STR_RED::Defined_by_iv_update: "
00795 "checking def:\n"));
00796 Is_Trace_cmd(Tracing() && WOPT_Enable_Verbose,
00797 def_cr->Print(3, TFile));
00798 Is_Trace(Tracing() && WOPT_Enable_Verbose,
00799 (TFile, " use:\n"));
00800 Is_Trace_cmd(Tracing() && WOPT_Enable_Verbose,
00801 use_cr->Print(3, TFile));
00802 if (Updated_by_iv_update(def_cr, use_cr, invar, use_bb, use_cr, aggstr_cand)) {
00803 Is_Trace(Tracing() && WOPT_Enable_Verbose,
00804 (TFile, "STR_RED::Defined_by_iv_update: "
00805 "updated_by_iv_update --> TRUE\n"));
00806 return TRUE;
00807 }
00808 }
00809
00810 Is_Trace(Tracing() && WOPT_Enable_Verbose,
00811 (TFile, "Defined_by_iv_update: FALSE\n"));
00812
00813 return FALSE;
00814 }
00815
00816
00817
00818
00819
00820
00821
00822
00823
00824 BOOL
00825 STR_RED::Defined_by_iv_update_no_def( CODEREP *use_cr,
00826 BB_NODE *def_bb,
00827 CODEREP **def_cr,
00828 CODEREP *invar,
00829 BB_NODE *use_bb,
00830 const CODEREP *cand_expr,
00831 BOOL aggstr_cand) const
00832 {
00833 Is_Trace(Tracing() && WOPT_Enable_Verbose,
00834 (TFile, "STR_RED::Defined_by_iv_update_no_def: use:\n"));
00835 Is_Trace_cmd(Tracing() && WOPT_Enable_Verbose,
00836 use_cr->Print(3, TFile));
00837 Is_Trace(Tracing() && WOPT_Enable_Verbose,
00838 (TFile, "STR_RED::Defined_by_iv_update_no_def: "
00839 "use in BB%d\n", use_bb->Id()));
00840
00841 Is_True(use_cr->Kind() != CK_OP, ("STR_RED::Defined_by_iv_update_no_def: CK_OP"));
00842
00843
00844 if ( use_cr->Kind() != CK_VAR ||
00845 use_cr->Is_flag_set(CF_IS_ZERO_VERSION) )
00846 {
00847 Is_Trace(Tracing() && WOPT_Enable_Verbose,
00848 (TFile, "STR_RED::Defined_by_iv_update_no_def: "
00849 "def by zero-ver --> FALSE\n"));
00850 return FALSE;
00851 }
00852
00853
00854
00855 INT num_iv_updates = 0;
00856
00857 while ( ! use_cr->Is_flag_set( (CR_FLAG) (CF_DEF_BY_CHI|
00858 CF_DEF_BY_PHI|
00859 CF_IS_ZERO_VERSION) ) )
00860 {
00861 Is_Trace(Tracing() && WOPT_Enable_Verbose,
00862 (TFile, "STR_RED::Defined_by_iv_update_no_def: "
00863 "def by real\n"));
00864 STMTREP *use_cr_def = use_cr->Defstmt();
00865
00866
00867
00868
00869
00870
00871 if (use_cr_def->Bb() != def_bb &&
00872 use_cr_def->Bb()->Dominates(def_bb)) {
00873
00874 if ( num_iv_updates > 0 ) {
00875 if ( def_cr != NULL ) *def_cr = use_cr;
00876 Is_Trace(Tracing() && WOPT_Enable_Verbose,
00877 (TFile, "STR_RED::Determine_iv_update_no_def: "
00878 "def dominates with IV updates --> TRUE\n"));
00879 return TRUE;
00880 }
00881
00882 Is_Trace(Tracing() && WOPT_Enable_Verbose,
00883 (TFile, "STR_RED::Determine_iv_update_no_def: "
00884 "def dominates with no IV updates --> FALSE\n"));
00885 return FALSE;
00886 }
00887
00888
00889 if (Determine_iv_update(use_cr_def, NULL)) {
00890 CODEREP *new_use_cr, *dummy_incr;
00891 BOOL dummy_is_add;
00892 if ( Find_iv_and_incr( use_cr_def, &new_use_cr,
00893 &dummy_incr, &dummy_is_add, aggstr_cand ) )
00894 {
00895
00896
00897 if (invar &&
00898 !Is_const_or_loop_invar(invar,use_cr_def->Bb()) )
00899 {
00900 Is_Trace(Tracing() && WOPT_Enable_Verbose,
00901 (TFile, "STR_RED::Determine_iv_update_no_def: "
00902 "invar not const or loop invariant --> FALSE\n"));
00903 return FALSE;
00904 }
00905
00906
00907
00908
00909
00910 if (!Update_happens_rarely_enough(use_cr_def->Bb(),
00911 use_bb, use_cr) &&
00912 !Repaired(use_cr_def)) {
00913 Is_Trace(Tracing(),
00914 (TFile, "STR_RED::Defined_by_iv_update_no_def: "
00915 "chain broken by loop nesting\n"));
00916 Is_Trace(Tracing(), (TFile, " innermost use in BB%d\n",
00917 use_bb->Id()));
00918 Is_Trace(Tracing(), (TFile, " iv update in BB%d\n",
00919 use_cr_def->Bb()->Id()));
00920 return FALSE;
00921 }
00922
00923 use_cr = new_use_cr;
00924 num_iv_updates++;
00925 continue;
00926 }
00927 }
00928
00929
00930 break;
00931 }
00932
00933
00934
00935 BB_NODE *use_cr_def_bb = NULL;
00936 if ( use_cr->Is_flag_set(CF_IS_ZERO_VERSION) ) {
00937 FmtAssert( FALSE,
00938 ("STR_RED::Defined_by_iv_update_no_def: zero-version?") );
00939 return FALSE;
00940 }
00941 else if ( use_cr->Is_flag_set(CF_DEF_BY_PHI) ) {
00942 use_cr_def_bb = use_cr->Defphi()->Bb();
00943
00944
00945
00946
00947 if ( use_cr_def_bb == def_bb ||
00948 use_cr_def_bb->Dominates( def_bb ) )
00949 {
00950
00951 if ( num_iv_updates > 0 ) {
00952 if ( def_cr != NULL ) *def_cr = use_cr;
00953 Is_Trace(Tracing() && WOPT_Enable_Verbose,
00954 (TFile, "STR_RED::Determine_iv_update_no_def: "
00955 "phi def dominates with IV updates --> TRUE\n"));
00956 return TRUE;
00957 }
00958 }
00959 Is_Trace(Tracing() && WOPT_Enable_Verbose,
00960 (TFile, "Defined_by_iv_update_no_def: "
00961 "phi def; no iv updates || non-dominance --> FALSE\n"));
00962 return FALSE;
00963 }
00964 else {
00965 use_cr_def_bb = use_cr->Defstmt()->Bb();
00966 if ( use_cr_def_bb != def_bb &&
00967 use_cr_def_bb->Dominates( def_bb ) )
00968 {
00969
00970 if ( num_iv_updates > 0 ) {
00971 if ( def_cr != NULL ) *def_cr = use_cr;
00972 Is_Trace(Tracing() && WOPT_Enable_Verbose,
00973 (TFile, "STR_RED::Determine_iv_update_no_def: "
00974 "chi or zero-ver def dominates with IV updates --> TRUE\n"));
00975 return TRUE;
00976 }
00977 }
00978 Is_Trace(Tracing() && WOPT_Enable_Verbose,
00979 (TFile, "Defined_by_iv_update_no_def: "
00980 "real def; no iv updates || non-dominance --> FALSE\n"));
00981 return FALSE;
00982 }
00983
00984
00985 FmtAssert( FALSE,
00986 ("STR_RED::Defined_by_iv_update_no_def: didn't find def bb") );
00987
00988
00989 return FALSE;
00990 }
00991
00992
00993
00994
00995
00996
00997
00998
00999
01000
01001
01002
01003
01004
01005
01006
01007
01008
01009
01010
01011 BOOL
01012 STR_RED::Candidate( const CODEREP *cr,
01013 const CODEREP *def_opnd0, const CODEREP *def_opnd1,
01014 BB_NODE *def_bb,
01015 CODEREP *use_opnd0, CODEREP *use_opnd1,
01016 BB_NODE *use_bb ) const
01017 {
01018 #ifdef TARG_NVISA
01019 BB_LOOP *bb_loop = NULL;
01020 Is_Trace(Tracing(), (TFile, "estr candidate Operation: "));
01021 Is_Trace_cmd(Tracing(), cr->Print_node(0,TFile));
01022 Is_Trace(Tracing(), (TFile, "\n"));
01023 if ( def_bb != NULL ) {
01024 bb_loop = def_bb->Innermost();
01025 Is_Trace(Tracing(), (TFile,
01026 "Non-Null BB Node information and Loop Depth=%d\n",
01027 def_bb->Loopdepth()));
01028 }
01029 else {
01030 Is_Trace(Tracing(), (TFile, "Null BB information\n"));
01031 }
01032
01033 if ( bb_loop != NULL ) {
01034 Is_Trace(Tracing(), (TFile,
01035 "Non-Null Loop information, Loop Depth=%d and Max Depth=%d\n",
01036 bb_loop->Depth(), bb_loop->Max_depth() ));
01037 if ( ! WOPT_Enable_Estr_Early_Exit
01038 && bb_loop->Exit_early() && ! WOPT_Enable_Aggressive_Code_Motion)
01039 {
01040
01041
01042
01043
01044
01045
01046 DevWarn("early exit loop and not aggcm, so don't strength reduce?");
01047 return FALSE;
01048 }
01049 } else {
01050 Is_Trace(Tracing(), (TFile, "Null Loop information\n"));
01051 }
01052
01053 if ( ! WOPT_Enable_Estr_Outer_Loop
01054 && bb_loop != NULL && bb_loop->Depth() <= 1 && bb_loop->Max_depth() >=2 )
01055 {
01056
01057 return FALSE;
01058 }
01059 #endif
01060
01061 const OPERATOR opr = cr->Opr();
01062 switch ( opr ) {
01063 case OPR_ADD:
01064 case OPR_SUB:
01065 #ifdef TARG_NVISA
01066 Is_Trace(Tracing(), (TFile,
01067 "Number of uses of this add/sub operation=%d\n", cr->Usecnt()));
01068 if ( ! WOPT_Enable_Estr_Const_Opnds
01069 && ( cr->Get_opnd(0)->Kind() == CK_CONST
01070 || cr->Get_opnd(1)->Kind() == CK_CONST ) )
01071 {
01072
01073 Is_Trace(Tracing(), (TFile, "At least one constant operand\n"));
01074 break;
01075 }
01076 if ( ! WOPT_Enable_Estr_Used_Once && !(cr->Usecnt() > 1) ) {
01077
01078
01079 break;
01080 }
01081
01082 #endif
01083 case OPR_MPY:
01084
01085
01086
01087 if ( Defined_by_iv_update(use_opnd0, def_opnd0,
01088 use_opnd1, use_bb, cr,
01089 opr == OPR_ADD || opr == OPR_SUB))
01090 {
01091 if (Is_cvt_linear(use_opnd0) &&
01092 Is_implicit_cvt_linear(cr->Dtyp(), use_opnd0->Dtyp())) {
01093 return TRUE;
01094 }
01095 }
01096 else
01097
01098
01099
01100 if ( Defined_by_iv_update(use_opnd1, def_opnd1,
01101 use_opnd0, use_bb, cr,
01102 opr == OPR_ADD || opr == OPR_SUB))
01103 {
01104 if (Is_cvt_linear(use_opnd1) &&
01105 Is_implicit_cvt_linear(cr->Dtyp(), use_opnd1->Dtyp())) {
01106 return TRUE;
01107 }
01108 }
01109 break;
01110
01111 case OPR_NEG:
01112 Is_Trace(Tracing(), (TFile,
01113 "Number of uses of this neg operation=%d\n", cr->Usecnt()));
01114 #ifdef TARG_NVISA
01115 if ( ! WOPT_Enable_Estr_Used_Once && !(cr->Usecnt() > 1) ) {
01116
01117
01118 break;
01119 }
01120
01121 #endif
01122 #ifdef TARG_X8664 // avoid U4 due to zero-extension to high-order 32 bits
01123 if (cr->Dtyp() == MTYPE_U4)
01124 return FALSE;
01125 #endif
01126
01127 if (Defined_by_iv_update( use_opnd0, def_opnd0, NULL, use_bb, cr)) {
01128 if (Is_cvt_linear(use_opnd0) &&
01129 Is_implicit_cvt_linear(cr->Dtyp(), use_opnd0->Dtyp())) {
01130 return TRUE;
01131 }
01132 }
01133 break;
01134
01135 case OPR_CVT:
01136
01137 if (Defined_by_iv_update( use_opnd0, def_opnd0, NULL, use_bb, cr)) {
01138 if (Is_cvt_linear(cr) &&
01139 Is_cvt_linear(use_opnd0) &&
01140 Is_implicit_cvt_linear(cr->Dsctyp(), use_opnd0->Dtyp())) {
01141 return TRUE;
01142 }
01143 }
01144 break;
01145 }
01146
01147
01148 return FALSE;
01149 }
01150
01151
01152
01153
01154
01155
01156
01157 BOOL
01158 STR_RED::Candidate_phi_res( const CODEREP *cr,
01159 BB_NODE *def_bb,
01160 CODEREP *use_opnd0, CODEREP *use_opnd1,
01161 BB_NODE *use_bb ) const
01162 {
01163 CODEREP *def_opnd;
01164 const OPERATOR opr = cr->Opr();
01165 switch ( opr ) {
01166 case OPR_ADD:
01167 case OPR_SUB:
01168 case OPR_MPY:
01169
01170
01171
01172 if ( Defined_by_iv_update_no_def(use_opnd0, def_bb, &def_opnd,
01173 use_opnd1, use_bb, cr,
01174 opr == OPR_ADD || opr == OPR_SUB))
01175 {
01176 if (Is_cvt_linear(use_opnd0) &&
01177 Is_implicit_cvt_linear(cr->Dtyp(), use_opnd0->Dtyp())) {
01178 return TRUE;
01179 }
01180 }
01181 else
01182
01183
01184
01185 if ( Defined_by_iv_update_no_def(use_opnd1, def_bb, &def_opnd,
01186 use_opnd0, use_bb, cr,
01187 opr == OPR_ADD || opr == OPR_SUB))
01188 {
01189 if (Is_cvt_linear(use_opnd1) &&
01190 Is_implicit_cvt_linear(cr->Dtyp(), use_opnd1->Dtyp())) {
01191 return TRUE;
01192 }
01193 }
01194 break;
01195
01196 case OPR_NEG:
01197 #ifdef TARG_X8664 // avoid U4 due to zero-extension to high-order 32 bits
01198 if (cr->Dtyp() == MTYPE_U4)
01199 return FALSE;
01200 #endif
01201
01202 if ( Defined_by_iv_update_no_def(use_opnd0, def_bb, &def_opnd,
01203 NULL, use_bb, cr))
01204 {
01205 if (Is_cvt_linear(use_opnd0) &&
01206 Is_implicit_cvt_linear(cr->Dtyp(), use_opnd0->Dtyp())) {
01207 return TRUE;
01208 }
01209 }
01210 break;
01211
01212 case OPR_CVT:
01213 if ( Defined_by_iv_update_no_def(use_opnd0, def_bb, &def_opnd,
01214 NULL, use_bb, cr))
01215 {
01216 if (Is_cvt_linear(cr) &&
01217 Is_cvt_linear(use_opnd0) &&
01218 Is_implicit_cvt_linear(cr->Dsctyp(), use_opnd0->Dtyp())) {
01219 return TRUE;
01220 }
01221 }
01222 break;
01223 }
01224
01225
01226 return FALSE;
01227 }
01228
01229
01230
01231
01232
01233
01234 void
01235 STR_RED::Find_iv_and_mult( const EXP_OCCURS *def, CODEREP **iv_def,
01236 const EXP_OCCURS *use, CODEREP **iv_use,
01237 CODEREP **multiplier ) const
01238 {
01239 Is_True(use->Occ_kind() == EXP_OCCURS::OCC_REAL_OCCUR ||
01240 use->Occ_kind() == EXP_OCCURS::OCC_PHI_PRED_OCCUR,
01241 ("STR_RED::Find_iv_and_mult: use is not real"));
01242
01243
01244 if ( def->Occ_kind() == EXP_OCCURS::OCC_PHI_OCCUR ) {
01245 Find_iv_and_mult_phi_res( def, iv_def, use, iv_use, multiplier );
01246 return;
01247 }
01248
01249 const CODEREP *use_cr = use->Occurrence();
01250 const CODEREP *def_cr = def->Occurrence();
01251 Is_True( use_cr->Kind() == CK_OP,
01252 ("STR_RED::Find_iv_and_mult: use is not op") );
01253
01254
01255 if ( use_cr->Kid_count() == 2 ) {
01256 const OPERATOR opr = use_cr->Opr();
01257 Is_True( opr == OPR_MPY || opr == OPR_ADD || opr == OPR_SUB,
01258 ("STR_RED::Find_iv_and_mult: bad op: %s",
01259 OPCODE_name(use_cr->Op())) );
01260
01261 if ( Defined_by_iv_update(use_cr->Opnd(0), def_cr->Opnd(0),
01262 use_cr->Opnd(1), use->Bb(), use_cr))
01263 {
01264 *iv_use = use_cr->Opnd(0);
01265 *iv_def = def_cr->Opnd(0);
01266
01267 if ( opr == OPR_MPY ) {
01268 *multiplier = Str_red_get_fixed_operand(use_cr,1);
01269 }
01270 else {
01271
01272 *multiplier = NULL;
01273 }
01274 }
01275 else
01276 if ( Defined_by_iv_update(use_cr->Opnd(1), def_cr->Opnd(1),
01277 use_cr->Opnd(0), use->Bb(), use_cr))
01278 {
01279 *iv_use = use_cr->Opnd(1);
01280 *iv_def = def_cr->Opnd(1);
01281
01282 if ( opr == OPR_MPY ) {
01283 *multiplier = Str_red_get_fixed_operand(use_cr,0);
01284 }
01285 else if ( opr == OPR_SUB) {
01286 *multiplier = Htable()->Add_const(OPCODE_rtype(use_cr->Op()),-1);
01287 }
01288 else {
01289
01290 *multiplier = NULL;
01291 }
01292 }
01293 else {
01294 FmtAssert( FALSE,
01295 ("STR_RED::Find_iv_and_mult: not a candidate") );
01296 }
01297 }
01298 else if ( use_cr->Kid_count() == 1 ) {
01299 Is_True( use_cr->Opr() == OPR_NEG || use_cr->Opr() == OPR_CVT,
01300 ("STR_RED::Find_iv_and_mult: single kid op is not neg") );
01301
01302 BOOL found_iv_update = Defined_by_iv_update(use_cr->Opnd(0),
01303 def_cr->Opnd(0),
01304 NULL,
01305 use->Bb(), use_cr);
01306
01307 Is_True(found_iv_update,
01308 ("STR_RED::Find_iv_and_mult: single kid is not iv") );
01309
01310 *iv_use = use_cr->Opnd(0);
01311 *iv_def = def_cr->Opnd(0);
01312 if ( use_cr->Opr() == OPR_NEG ) {
01313 CODEREP *multi = Htable()->Add_const(OPCODE_rtype(use_cr->Op()),-1);
01314 *multiplier = multi;
01315 }
01316 else {
01317
01318 *multiplier = NULL;
01319 }
01320 }
01321 else {
01322 FmtAssert( FALSE,
01323 ("STR_RED::Find_iv_and_mult: invalid sr candidate") );
01324 }
01325 }
01326
01327
01328
01329
01330
01331
01332
01333 void
01334 STR_RED::Find_iv_and_mult_phi_res( const EXP_OCCURS *def, CODEREP **iv_def,
01335 const EXP_OCCURS *use, CODEREP **iv_use,
01336 CODEREP **multiplier ) const
01337 {
01338 Is_True( def->Occ_kind() == EXP_OCCURS::OCC_PHI_OCCUR,
01339 ("STR_RED::Find_iv_and_mult_phi_res: def is not phi") );
01340 Is_True(use->Occ_kind() == EXP_OCCURS::OCC_REAL_OCCUR ||
01341 use->Occ_kind() == EXP_OCCURS::OCC_PHI_PRED_OCCUR,
01342 ("STR_RED::Find_iv_and_mult_phi_res: use is not real"));
01343
01344 const CODEREP *use_cr = use->Occurrence();
01345 Is_True( use_cr->Kind() == CK_OP,
01346 ("STR_RED::Find_iv_and_mult_phi_res: use is not op") );
01347
01348 Is_Trace(Tracing(), (TFile, "def: "));
01349 Is_Trace_cmd(Tracing(), def->Print(TFile));
01350 Is_Trace(Tracing(), (TFile, "use: "));
01351 Is_Trace_cmd(Tracing(), use->Print(TFile));
01352
01353
01354 if ( use_cr->Kid_count() == 2 ) {
01355 const OPERATOR opr = use_cr->Opr();
01356 Is_True( opr == OPR_MPY || opr == OPR_ADD || opr == OPR_SUB,
01357 ("STR_RED::Find_iv_and_mult_phi_res: bad op: %s",
01358 OPCODE_name(use_cr->Op())) );
01359
01360 if ( Defined_by_iv_update_no_def(use_cr->Opnd(0), def->Bb(), iv_def,
01361 use_cr->Opnd(1), use->Bb(), use_cr))
01362 {
01363 *iv_use = use_cr->Opnd(0);
01364
01365
01366 if ( opr == OPR_MPY ) {
01367 *multiplier = use_cr->Opnd(1);
01368 }
01369 else {
01370
01371 *multiplier = NULL;
01372 }
01373 }
01374 else
01375 if ( Defined_by_iv_update_no_def(use_cr->Opnd(1), def->Bb(), iv_def,
01376 use_cr->Opnd(0), use->Bb(), use_cr))
01377 {
01378 *iv_use = use_cr->Opnd(1);
01379
01380
01381 if ( opr == OPR_MPY ) {
01382 *multiplier = use_cr->Opnd(0);
01383 }
01384 else if ( opr == OPR_SUB) {
01385 #ifndef TARG_X8664
01386 *multiplier = Htable()->Add_const(OPCODE_rtype(use_cr->Op()),-1);
01387 #else // bug 4518
01388 *multiplier = Htable()->Add_const(Mtype_TransferSign(MTYPE_I4, OPCODE_rtype(use_cr->Op())),-1);
01389 #endif
01390 }
01391 else {
01392
01393 *multiplier = NULL;
01394 }
01395 }
01396 else {
01397 FmtAssert( FALSE,
01398 ("STR_RED::Find_iv_and_mult_phi_res: not a candidate") );
01399 }
01400 }
01401 else if ( use_cr->Kid_count() == 1 ) {
01402 const OPERATOR opr = use_cr->Opr();
01403 Is_True( opr == OPR_NEG || opr == OPR_CVT,
01404 ("STR_RED::Find_iv_and_mult_phi_res: single kid op is not neg") );
01405
01406 BOOL found_iv_update = Defined_by_iv_update_no_def(use_cr->Opnd(0),
01407 def->Bb(),
01408 iv_def,
01409 NULL,
01410 use->Bb(),
01411 use_cr);
01412 Is_True( found_iv_update,
01413 ("STR_RED::Find_iv_and_mult_phi_res: single kid is not iv") );
01414
01415 *iv_use = use_cr->Opnd(0);
01416
01417 if ( opr == OPR_NEG ) {
01418 #ifndef TARG_X8664
01419 CODEREP *multi = Htable()->Add_const(OPCODE_rtype(use_cr->Op()),-1);
01420 #else // bug 4518
01421 CODEREP *multi = Htable()->Add_const(Mtype_TransferSign(MTYPE_I4, OPCODE_rtype(use_cr->Op())),-1);
01422 #endif
01423 *multiplier = multi;
01424 }
01425 else if ( opr == OPR_CVT ) {
01426
01427 *multiplier = NULL;
01428 }
01429 else {
01430 FmtAssert( FALSE,
01431 ("STR_RED::Find_iv_and_mult_phi_res: wrong op") );
01432 }
01433 }
01434 else {
01435 FmtAssert( FALSE,
01436 ("STR_RED::Find_iv_and_mult_phi_res: invalid sr candidate") );
01437 }
01438
01439 }
01440
01441
01442
01443
01444
01445
01446
01447 #if 0
01448 void
01449 EXP_WORKLST::Exclude_strength_reduction_cands(ETABLE *etable)
01450 {
01451 EXP_OCCURS *exp_occ;
01452 EXP_OCCURS_ITER exp_occ_iter;
01453
01454
01455 if ( ! WOPT_Enable_New_SR ) {
01456 Set_exclude_sr_cand();
01457 return;
01458 }
01459
01460 #ifdef EXCLUDE_IV_RHS_FROM_SR
01461
01462
01463
01464
01465 if ( Exp()->Kind() != CK_OP ) {
01466 return;
01467 }
01468
01469
01470 const OPERATOR exp_opr = Exp()->Opr();
01471 if ( exp_opr != OPR_ADD && exp_opr != OPR_SUB ) {
01472 return;
01473 }
01474
01475
01476
01477 FOR_ALL_NODE (exp_occ, exp_occ_iter, Init(Real_occurs().Head())) {
01478 STMTREP *occ_stmt = exp_occ->Enclosed_in_stmt();
01479 if ( occ_stmt->Rhs() == exp_occ->Occurrence() &&
01480 etable->Str_red()->Determine_iv_update(occ_stmt,NULL) )
01481 {
01482
01483 Set_exclude_sr_cand();
01484
01485 Is_Trace(etable->Tracing(),
01486 (TFile,"Exclude_strength_reduction_cands: excluded iv rhs\n"));
01487
01488 break;
01489 }
01490 }
01491 #endif // EXCLUDE_IV_RHS_FROM_SR
01492
01493 }
01494 #endif
01495
01496 void
01497 STR_RED::Perform_per_expr_cleanup(void)
01498 {
01499 while (!_repaired_statements.Is_Empty()) {
01500 STMTREP *stmt = _repaired_statements.Pop();
01501 Is_True(stmt->Repaired(), ("STR_RED::Perform_per_expr_cleanup: "
01502 "statement must be repaired. Duplicate?"));
01503 stmt->Reset_repaired();
01504 }
01505 }
01506
01507 void
01508 STR_RED::Set_repaired(STMTREP *stmt)
01509 {
01510 stmt->Set_repaired();
01511 _repaired_statements.Push(stmt);
01512 }