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 #include <set>
00067 #include <map>
00068
00069 #define USE_STANDARD_TYPE
00070 #include "opt_defs.h"
00071 #include "opt_cfg_trans.h"
00072 #include "opt_transform.h"
00073 #include "opt_dce.h"
00074 #include "opt_main.h"
00075
00076 using std::set;
00077
00078 typedef set<int> Paths;
00079
00080 struct cond_const_path {
00081 CODEREP *cr;
00082 Paths paths;
00083 BB_NODE *entry;
00084
00085 void print(FILE *fp);
00086
00087 cond_const_path(CODEREP *c, BB_NODE *e):
00088 cr(c), entry(e) {}
00089 };
00090
00091 typedef vector<cond_const_path> Set_of_paths;
00092
00093
00094 static void print_paths(FILE *fp, Paths &paths)
00095 {
00096 for (Paths::iterator p = paths.begin(); p != paths.end(); ++p) {
00097 fprintf(fp, "%d ", *p);
00098 }
00099 fprintf(fp, "\n");
00100 }
00101
00102
00103 void cond_const_path::print(FILE *fp)
00104 {
00105 if (cr->Kind() == CK_VAR) {
00106 fprintf(fp, " paths from cr%d in BB%d (value 0x%llx): ",
00107 cr->Coderep_id(),
00108 cr->Defstmt()->Bb()->Id(),
00109 cr->Defstmt()->Rhs()->Const_val());
00110 } else {
00111 fprintf(fp, " paths for cr%d: ", cr->Coderep_id());
00112 }
00113 print_paths(fp, paths);
00114 }
00115
00116
00117 void print_set_of_paths(FILE *fp, Set_of_paths& set_of_paths)
00118 {
00119 for (Set_of_paths::iterator s = set_of_paths.begin();
00120 s != set_of_paths.end();
00121 ++s) {
00122 (*s).print(fp);
00123 }
00124 }
00125
00126
00127
00128
00129
00130
00131 static void trace_paths(BB_NODE *bb, BB_NODE *def_bb, Paths &paths)
00132 {
00133 Is_True(def_bb->Dominates(bb), ("trace_paths: Definition must dominate use."));
00134
00135 pair<Paths::iterator, bool> res = paths.insert(bb->Id());
00136 if (!res.second)
00137 return;
00138 if (bb == def_bb)
00139 return;
00140
00141 BB_NODE *pred;
00142 BB_LIST_ITER bb_pred_iter;
00143 FOR_ALL_ELEM( pred, bb_pred_iter, Init(bb->Pred()))
00144 trace_paths(pred, def_bb, paths);
00145 }
00146
00147
00148
00149
00150 static bool find_conditional_const(BB_NODE *bb, CODEREP *cr,
00151 Set_of_paths &set_of_paths,
00152 vector<bool>& visited,
00153 BB_LOOP *loop,
00154 bool trace)
00155 {
00156 if (visited[bb->Id()]) return false;
00157 visited[bb->Id()] = true;
00158
00159 if (!cr->Is_flag_set(CF_DEF_BY_PHI)) return false;
00160
00161 PHI_NODE *phi = cr->Defphi();
00162 BB_NODE *bbp = phi->Bb();
00163
00164
00165 if (bbp->Innermost() != loop) return false;
00166
00167
00168 if (bbp->Loop() && bbp->Loop()->Header() == bbp) return false;
00169
00170 bool found_conditional_const = false;
00171
00172 for (INT i = 0; i < phi->Size(); ++i) {
00173 CODEREP *opnd = phi->OPND(i);
00174 if (!opnd->Is_flag_set(CF_IS_ZERO_VERSION) &&
00175 !opnd->Is_flag_set(CF_DEF_BY_PHI) &&
00176 !opnd->Is_flag_set(CF_DEF_BY_CHI)) {
00177
00178 if (opnd->Defstmt() != NULL &&
00179 opnd->Defstmt()->Rhs()->Kind() == CK_CONST) {
00180 set_of_paths.push_back(cond_const_path(opnd, phi->Bb()->Nth_pred(i)));
00181 found_conditional_const = true;
00182 }
00183 } else if (opnd->Is_flag_set(CF_DEF_BY_PHI)) {
00184 if (find_conditional_const(phi->Bb()->Nth_pred(i), opnd, set_of_paths, visited, loop, trace))
00185 found_conditional_const = true;
00186 }
00187 }
00188 if (found_conditional_const) {
00189 Paths paths;
00190 trace_paths(bb, phi->Bb(), paths);
00191 for (Set_of_paths::iterator p = set_of_paths.begin();
00192 p != set_of_paths.end();
00193 ++p) {
00194 Paths *cur_paths = &(*p).paths;
00195 (*cur_paths).insert(paths.begin(), paths.end());
00196 }
00197 }
00198 return found_conditional_const;
00199 }
00200
00201
00202
00203
00204
00205
00206
00207 static bool is_redundant_cmp(CODEREP *cmp, BB_NODE *bb, BB_NODE *pred,
00208 STMTREP *context_sr, BB_NODE *context_bb)
00209 {
00210 Is_True(context_sr->Op() == OPC_TRUEBR || context_sr->Op() == OPC_FALSEBR,
00211 ("is_redundant_cmp: expecting OPC_TRUEBR or OPC_FALSEBR"));
00212
00213 BB_NODE *found_succ = NULL;
00214 BB_NODE *search_succ = (pred == context_bb) ? bb : pred;
00215
00216 BB_LIST_ITER bb_iter;
00217 BB_NODE *succ;
00218 FOR_ALL_ELEM( succ, bb_iter, Init(context_bb->Succ()) ) {
00219 if (search_succ->Postdominates(succ)) {
00220 found_succ = succ;
00221 break;
00222 }
00223 }
00224
00225 if (!found_succ) return false;
00226
00227 COND_EVAL ce;
00228 if (context_sr->Op() == OPC_TRUEBR)
00229 ce = (found_succ == context_bb->Next()) ? EVAL_FALSE : EVAL_TRUE;
00230 else
00231 ce = (found_succ == context_bb->Next()) ? EVAL_TRUE : EVAL_FALSE;
00232
00233 COND_EVAL res = Eval_redundant_cond_br( cmp, context_sr->Rhs(), ce);
00234 return (res == EVAL_TRUE || res == EVAL_FALSE);
00235 }
00236
00237
00238 static bool find_redundant_br(STMTREP *stmt, BB_NODE *bb, Set_of_paths &set_of_paths)
00239 {
00240 BB_NODE *dom = bb->Idom();
00241 BB_NODE *pred;
00242 BB_LIST_ITER bb_pred_iter;
00243
00244 bool found_redundant_br = false;
00245 FOR_ALL_ELEM( pred, bb_pred_iter, Init(bb->Pred())) {
00246 BB_NODE *cur = pred;
00247 while (cur && dom->Dominates(cur)) {
00248 STMTREP *br = cur->Branch_stmtrep();
00249 if (br && (br->Op() == OPC_TRUEBR || br->Op() == OPC_FALSEBR)) {
00250 if (is_redundant_cmp(stmt->Rhs(), bb, pred, br, cur)) {
00251 set_of_paths.push_back(cond_const_path(stmt->Rhs(), pred));
00252 (*(set_of_paths.end()-1)).paths.insert(bb->Id());
00253 found_redundant_br = true;
00254 break;
00255 }
00256 }
00257 cur = cur->Idom();
00258 }
00259 }
00260 return found_redundant_br;
00261 }
00262
00263 static void add_to_zone_container(CFG *cfg, Set_of_paths &set_of_paths, zone_container& zones)
00264 {
00265 for (Set_of_paths::iterator s = set_of_paths.begin();
00266 s != set_of_paths.end();
00267 ++s) {
00268 CODEREP *cr = (*s).cr;
00269 Paths *paths = &(*s).paths;
00270 BB_NODE *entry = (*s).entry;
00271 zones.push_back(zone(zones.size()));
00272 zone_container::iterator cur_zone = zones.end()-1;
00273
00274 BB_LIST_ITER bb_succ_iter;
00275 BB_LIST_ITER bb_pred_iter;
00276 BB_NODE *succ;
00277 BB_NODE *pred;
00278 int entry_id = entry->Id();
00279 FOR_ALL_ELEM(succ, bb_succ_iter, Init(entry->Succ())) {
00280 int succ_id = succ->Id();
00281 if ((*paths).find(succ_id) != (*paths).end())
00282 (*cur_zone).entry.push_back(edge(entry_id, succ_id));
00283 }
00284 for (Paths::iterator p = (*paths).begin(); p != (*paths).end(); ++p) {
00285 int bb_id = *p;
00286 BB_NODE *bb = cfg->Get_bb(bb_id);
00287 FOR_ALL_ELEM(succ, bb_succ_iter, Init(bb->Succ())) {
00288 int succ_id = succ->Id();
00289 if ((*paths).find(succ_id) != (*paths).end())
00290 (*cur_zone).clone.push_back(edge(bb_id, succ_id));
00291 else
00292 (*cur_zone).exit.push_back(edge(bb_id, succ_id));
00293 }
00294 FOR_ALL_ELEM(pred, bb_pred_iter, Init(bb->Pred())) {
00295 int pred_id = pred->Id();
00296 if (pred_id != entry_id &&
00297 (*paths).find(pred_id) == (*paths).end())
00298 (*cur_zone).side_entry.push_back(edge(pred_id, bb_id));
00299 }
00300 }
00301 }
00302 }
00303
00304
00305 struct CONDITIONAL_CONST : public NULL_TRANSFORM {
00306 const char *Name() const { return "Scanning for conditional constant"; }
00307 COMP_UNIT *cu;
00308 zone_container *zones;
00309 bool trace;
00310 bool do_cond_const;
00311
00312 CODEREP *Apply_cr(CODEREP *cr, bool is_mu, STMTREP *stmt, BB_NODE *bb, CODEMAP *htable) const
00313 {
00314 if (!do_cond_const) return NULL;
00315
00316 if (cr->Kind() == CK_VAR && !is_mu) {
00317 Set_of_paths set_of_paths;
00318 vector<bool> visited(cu->Cfg()->Total_bb_count(), false);
00319 bool found = find_conditional_const(bb, cr, set_of_paths, visited, bb->Innermost(), trace);
00320 if (found && trace) {
00321 fprintf(TFile, "CONDITIONAL CONST found for cr%d in BB%d\n", cr->Coderep_id(), bb->Id());
00322 print_set_of_paths(TFile, set_of_paths);
00323 }
00324 if (found)
00325 add_to_zone_container(cu->Cfg(), set_of_paths, *zones);
00326 }
00327 return NULL;
00328 }
00329
00330 void Apply_sr(STMTREP *stmt, BB_NODE *bb, CODEMAP *htable)
00331 {
00332 do_cond_const = false;
00333 if (stmt->Op() == OPC_TRUEBR || stmt->Op() == OPC_FALSEBR) {
00334 do_cond_const = true;
00335 Set_of_paths set_of_paths;
00336 BOOL found = find_redundant_br(stmt, bb, set_of_paths);
00337 if (found && trace) {
00338 fprintf(TFile, "REDUNDANT BR found in BB%d\n", bb->Id());
00339 print_set_of_paths(TFile, set_of_paths);
00340 }
00341 if (found)
00342 add_to_zone_container(cu->Cfg(), set_of_paths, *zones);
00343 }
00344 }
00345
00346
00347 void Setup(PER_BB_CACHE *, DONT_TRACK_CUR_VERSION *) {}
00348
00349 CONDITIONAL_CONST(COMP_UNIT *c, zone_container *r, bool t):
00350 cu(c),zones(r),trace(t) {}
00351 };
00352
00353
00354 void generate_conditional_const_zones(COMP_UNIT *cu, successor_graph &g, vector<zone>& zones, bool trace)
00355 {
00356 CONDITIONAL_CONST conditional_const(cu, &zones, trace);
00357 UPDATE<CONDITIONAL_CONST, PER_BB_CACHE>
00358 SCAN_conditional_const(cu, &conditional_const, trace);
00359 SCAN_conditional_const.Process_PU();
00360 }