00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073 #ifdef USE_PCH
00074 #include "opt_pch.h"
00075 #endif // USE_PCH
00076 #pragma hdrstop
00077
00078
00079 #include "opt_cfg.h"
00080 #include "opt_etable.h"
00081 #include "opt_htable.h"
00082 #include "opt_ssa.h"
00083 #include "tracing.h"
00084 #include "config_targ.h"
00085 #include "config_wopt.h"
00086 #include "opt_mu_chi.h"
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096 static BOOL
00097 BB_has_backedge(BB_NODE *bb, BOOL loop_tail = FALSE)
00098 {
00099 Is_True(bb, ("BB_has_backedge: Null BB pointer"));
00100
00101 BB_NODE *bb_pred;
00102 BB_NODE *bb_succ;
00103 BB_LIST_ITER bb_iter;
00104
00105 if (loop_tail) {
00106 FOR_ALL_ELEM(bb_succ, bb_iter, Init(bb->Succ()))
00107 if (bb_succ->Dominates(bb)) return TRUE;
00108 } else {
00109 FOR_ALL_ELEM(bb_pred, bb_iter, Init(bb->Pred()))
00110 if (bb->Dominates(bb_pred)) return TRUE;
00111 }
00112
00113 return FALSE;
00114 }
00115
00116 static BOOL
00117 Exp_phi_is_invariant(ETABLE *etable, EXP_PHI *exp_phi, BOOL forward_pre)
00118 {
00119
00120 Is_True(exp_phi, ("Exp_phi_is_invariant: exp_phi is NULL"));
00121 BOOL is_used_in_loop = FALSE;
00122 BOOL is_invariant;
00123 OPT_POOL_Push(etable->Etable_local_pool(), -1);
00124 {
00125 STACK<EXP_PHI*> phi_stack(etable->Etable_local_pool());
00126 is_invariant = exp_phi->Identity_assignment(is_used_in_loop, exp_phi, forward_pre, phi_stack);
00127 EXP_PHI *t;
00128 while (!phi_stack.Is_Empty()) {
00129 t = phi_stack.Pop();
00130 t->Reset_I_A_Seen();
00131 }
00132 }
00133 OPT_POOL_Pop(etable->Etable_local_pool(), -1);
00134 return ( is_used_in_loop && is_invariant );
00135 }
00136
00137 static BOOL
00138 BB_has_backedge_and_is_invariant(BB_NODE *bb, CODEREP *cr, ETABLE *etable)
00139 {
00140 Is_True(bb,("Has_backedge: Null BB pointer"));
00141
00142 BB_NODE *bb_pred;
00143 BB_LIST_ITER bb_iter;
00144 INT which_pred = 0;
00145 BOOL has_back_edge = FALSE;
00146
00147 FOR_ALL_ELEM(bb_pred, bb_iter, Init(bb->Pred())) {
00148 if (bb->Dominates(bb_pred)) {
00149 has_back_edge = TRUE;
00150 if (cr->Kind() != CK_IVAR) {
00151 for (INT i = 0; i < cr->Kid_count(); ++i) {
00152 CODEREP *kid = cr->Opnd(i);
00153 if ((kid->Kind() == CK_IVAR) && (kid->Opr() == OPR_PARM))
00154 kid = kid->Ilod_base();
00155 if (kid->Kind() == CK_VAR) {
00156 const PHI_NODE *var_phi = etable->Lookup_var_phi(bb, kid->Aux_id());
00157 if (var_phi && (var_phi->RESULT() != var_phi->OPND(which_pred)))
00158 return FALSE;
00159 }
00160 }
00161 }
00162 else {
00163 const CODEREP *vsym = cr->Get_ivar_vsym();
00164 if (vsym) {
00165 const PHI_NODE *var_phi = etable->Lookup_var_phi(bb,vsym->Aux_id());
00166 if (var_phi &&
00167 (vsym->Is_flag_set(CF_IS_ZERO_VERSION) ||
00168 (var_phi->RESULT() != var_phi->OPND(which_pred))))
00169 return FALSE;
00170 }
00171 }
00172 }
00173 which_pred++;
00174 }
00175
00176 return has_back_edge;
00177 }
00178
00179 static
00180 BOOL Is_loop_entry_bb(CFG *cfg, BB_NODE *bb)
00181 {
00182 Is_True(bb != NULL, ("Is_loop_entry_bb, NULL bb"));
00183
00184 const BB_LOOP *loop = cfg->Find_innermost_loop_contains(bb);
00185 return ( loop != NULL && loop->Body() == bb );
00186 }
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197 BOOL
00198 EXP_WORKLST::Propagate_downsafe(ETABLE *etable)
00199 {
00200 BOOL ret_value = TRUE;
00201 INT length = 0;
00202 BOOL is_spre = (etable->Pre_kind() == PK_SPRE);
00203 BOOL is_lpre = (etable->Pre_kind() == PK_LPRE);
00204
00205 BOOL aggcm_candidate = (WOPT_Enable_Aggressive_Code_Motion &&
00206 Exp()->Can_be_speculated(etable->Opt_stab()));
00207
00208 FmtAssert(etable,("EXP_WORKLST::Propagate_downsafe: Etable is NULL"));
00209
00210 Is_Trace(etable->Tracing(),
00211 (TFile, "====== Before EXP_WORKLST::Propagate_downsafe ======\n"));
00212 Is_Trace_cmd(etable->Tracing(), Print(TFile));
00213
00214 OPT_POOL_Push(etable->Etable_local_pool(), -1);
00215 {
00216 EXP_OCCURS *phi_occ;
00217 EXP_OCCURS_ITER phi_iter;
00218 STACK<EXP_OCCURS*> worklist(etable->Etable_local_pool());
00219
00220 FOR_ALL_NODE (phi_occ, phi_iter, Init(Phi_occurs().Head())) {
00221 length = length + 1;
00222 Is_True(phi_occ->Occ_kind() == EXP_OCCURS::OCC_PHI_OCCUR,
00223 ("EXP_WORKLST::Propagate_downsafe: Not a phi occurrence"));
00224 EXP_PHI *phi = phi_occ->Exp_phi();
00225
00226 if (phi->Not_down_safe()) {
00227 if (!aggcm_candidate ||
00228 phi->Dead_phi_region() ||
00229 (is_spre && phi_occ->Occurrence() == NULL) ||
00230 !BB_has_backedge(phi->Bb(),is_spre) ||
00231 !Exp_phi_is_invariant(etable, phi, !is_spre)) {
00232 worklist.Push(phi_occ);
00233 }
00234 else {
00235 Is_True(phi_occ->Occurrence(), ("AGGCM: occurrence of phi is NULL"));
00236 phi->Reset_not_down_safe();
00237 Is_Trace(etable->Tracing(),(TFile, "------ Phi node has backedge ------\n"));
00238 Is_Trace_cmd(etable->Tracing(), phi_occ->Print(TFile));
00239 Is_Trace(etable->Tracing(), (TFile, "------ AGGCM phi ------\n"));
00240 Is_Trace_cmd(etable->Tracing(), phi->Print(TFile));
00241
00242
00243 if (WOPT_Enable_Speculation_Defeats_LFTR) {
00244 Set_no_lftr();
00245 }
00246 }
00247 }
00248 }
00249
00250 for (INT i = 0; i < worklist.Elements(); ++i) {
00251 phi_occ = worklist.Bottom_nth(i);
00252 EXP_PHI *cur_phi = phi_occ->Exp_phi();
00253 Is_True(cur_phi->Not_down_safe(),
00254 ("EXP_WORKLST::Propagate_downsafe: down safe phi occurrence"));
00255 for (INT j = 0; j < cur_phi->Opnd_count(); ++j) {
00256 if (!cur_phi->Has_real_occ(j)) {
00257 EXP_OCCURS *def_occ = cur_phi->Opnd(j);
00258 EXP_PHI *def_phi = (def_occ ? def_occ->Exp_phi() : NULL);
00259
00260 if (def_occ && def_occ->Occ_kind() == EXP_OCCURS::OCC_PHI_OCCUR &&
00261 !def_phi->Not_down_safe()) {
00262 if (!aggcm_candidate ||
00263 def_phi->Dead_phi_region() ||
00264 cur_phi->Dead_phi_region() ||
00265 (is_spre && def_occ->Occurrence() == NULL) ||
00266 !BB_has_backedge(def_phi->Bb(),is_spre) ||
00267 !Exp_phi_is_invariant(etable, def_phi, !is_spre)) {
00268 def_phi->Set_not_down_safe();
00269 if (cur_phi->Dead_phi_region())
00270 def_phi->Set_dead_phi_region();
00271 worklist.Push(def_occ);
00272 }
00273 else {
00274 Is_True(def_occ->Occurrence(), ("AGGCM: occurrence of phi is NULL"));
00275 Is_Trace(etable->Tracing(),(TFile, "------ Phi node has backedge ------\n"));
00276 Is_Trace_cmd(etable->Tracing(), def_occ->Print(TFile));
00277 Is_Trace(etable->Tracing(),(TFile, "------ AGGCM phi ------\n"));
00278 Is_Trace_cmd(etable->Tracing(), def_phi->Print(TFile));
00279
00280
00281 if (WOPT_Enable_Speculation_Defeats_LFTR) {
00282 Set_no_lftr();
00283 }
00284 }
00285 }
00286 }
00287 }
00288 }
00289
00290
00291 if (length == worklist.Elements() &&
00292 Real_occurs().Head() == Real_occurs().Tail() &&
00293 !Real_occurs().Head()->Mult_real()) ret_value = FALSE;
00294 }
00295 OPT_POOL_Pop(etable->Etable_local_pool(), -1);
00296
00297 Is_Trace(etable->Tracing(),
00298 (TFile, "====== After EXP_WORKLST::Propagate_downsafe ======\n"));
00299 Is_Trace_cmd(etable->Tracing(), Print(TFile));
00300
00301 return ret_value;
00302 }
00303
00304
00305
00306
00307
00308 void
00309 EXP_WORKLST::Determine_live_phi(ETABLE *etable)
00310 {
00311 FmtAssert(etable,("EXP_WORKLST::Determine_live_phi: Etable is NULL"));
00312 Is_Trace(etable->Tracing(),
00313 (TFile, "====== Before EXP_WORKLST::Determine_live_phi ======\n"));
00314 Is_Trace_cmd(etable->Tracing(), Print(TFile));
00315
00316 OPT_POOL_Push(etable->Etable_local_pool(), -1);
00317 {
00318 EXP_OCCURS *phi_occ;
00319 EXP_OCCURS_ITER phi_iter;
00320 STACK<EXP_OCCURS*> worklist(etable->Etable_local_pool());
00321
00322 FOR_ALL_NODE (phi_occ, phi_iter, Init(Phi_occurs().Head())) {
00323 Is_True(phi_occ->Occ_kind() == EXP_OCCURS::OCC_PHI_OCCUR,
00324 ("EXP_WORKLST::Determine_live_phi: Not a phi occurrence"));
00325 if (phi_occ->Occurrence() != NULL) {
00326 phi_occ->Exp_phi()->Set_live();
00327 worklist.Push(phi_occ);
00328 }
00329 }
00330
00331 for (INT i = 0; i < worklist.Elements(); ++i) {
00332 phi_occ = worklist.Bottom_nth(i);
00333 EXP_PHI *cur_phi = phi_occ->Exp_phi();
00334 Is_True(cur_phi->Is_live(),
00335 ("EXP_WORKLST::Determine_live_phi: dead phi occurrence"));
00336
00337 for (INT j = 0; j < cur_phi->Opnd_count(); ++j) {
00338 EXP_OCCURS * def_occ = cur_phi->Opnd(j);
00339 if (def_occ &&
00340 def_occ->Occ_kind() == EXP_OCCURS::OCC_PHI_OCCUR &&
00341 !def_occ->Exp_phi()->Is_live()) {
00342 def_occ->Exp_phi()->Set_live();
00343 worklist.Push(def_occ);
00344 }
00345 }
00346 }
00347 }
00348 OPT_POOL_Pop(etable->Etable_local_pool(), -1);
00349
00350 Is_Trace(etable->Tracing(),
00351 (TFile, "====== After EXP_WORKLST::Determine_live_phi ======\n"));
00352 Is_Trace_cmd(etable->Tracing(), Print(TFile));
00353
00354 }
00355