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
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088 #define USE_STANDARD_TYPE
00089 #include "opt_defs.h"
00090 #include "opt_bb.h"
00091 #include "bb_node_set.h"
00092 #include "config_wopt.h"
00093 #include "opt_cfg.h"
00094 #include "opt_fb.h"
00095 #include "opt_cfg_trans.h"
00096 #include "opt_transform.h"
00097 #include "opt_main.h"
00098
00099 #include <iterator>
00100 #include <stack>
00101 #include <queue>
00102
00103 using std::insert_iterator;
00104 using std::priority_queue;
00105 using std::set;
00106 using std::stack;
00107
00108 static bool check_hazardous_op(BB_NODE *bb)
00109 {
00110 STMTREP_ITER stmt_iter(bb->Stmtlist());
00111 STMTREP *stmt;
00112 FOR_ALL_NODE(stmt, stmt_iter, Init()) {
00113 if (OPCODE_is_call(stmt->Op()))
00114 return true;
00115 if (stmt->Op() == OPC_COMPGOTO)
00116 return true;
00117 }
00118 return false;
00119 }
00120
00121 inline bool member_of(int elem, set<int>& set)
00122 {
00123 return (set.find(elem) != set.end());
00124 }
00125
00126
00127 static double path_exit_counts(successor_graph& g, set<vertex_id>& ends,
00128 OPT_FEEDBACK *feedback, bool trace)
00129 {
00130 FB_FREQ coverage = FB_FREQ_ZERO;
00131 for (set<vertex_id>::iterator si = ends.begin();
00132 si != ends.end();
00133 ++si) {
00134 vertex_id bb = *si;
00135 for (predecessor_graph::fast_iterator e = g[bb].begin();
00136 e != g[bb].end();
00137 ++e) {
00138 vertex_id to = (*e).second;
00139 if (! member_of(to, ends)) {
00140 if ( trace ) {
00141 fprintf( TFile, "path_exit_counts: %d->%d, ", bb, to );
00142 feedback->Get_edge_freq( bb, to ).Print( TFile );
00143 fprintf( TFile, "\n" );
00144 }
00145 coverage += feedback->Get_edge_freq(bb, to);
00146 }
00147 }
00148 }
00149 if ( coverage.Known() )
00150 return coverage.Value();
00151 else
00152 return 0.0;
00153 }
00154
00155
00156
00157
00158
00159
00160
00161 static double
00162 butterfly_loop_with_profile(successor_graph& g,
00163 set<vertex_id> orig_loop,
00164 predecessor_graph& loop,
00165 set<vertex_id>& starts,
00166 set<vertex_id>& ends,
00167 OPT_FEEDBACK *feedback,
00168 int min_coverage,
00169 bool trace)
00170 {
00171 priority_queue<path_type*> primary_heap, secondary_heap;
00172 double orig_counts = path_exit_counts(g, orig_loop, feedback, trace);
00173 double total_counts =
00174 path_exit_counts(g, ends, feedback, trace) - orig_counts;
00175 if (!(total_counts > 1.0)) {
00176 if (trace)
00177 fprintf(TFile, "disable loop butterfly because of small counts.\n");
00178 return 0.0;
00179 }
00180 if (trace)
00181 fprintf(TFile,
00182 "<<<begin loop butterfly with initial counts %g\n", total_counts);
00183 double coverage = 0.0;
00184 double exit_counts = 0.0;
00185 for (set<int>::iterator si = starts.begin();
00186 si != starts.end();
00187 ++si) {
00188 path_type *p =
00189 CXX_NEW( path_type( *si, feedback->Get_node_freq_out(*si).Value() ),
00190 &MEM_local_pool );
00191 primary_heap.push(p);
00192 }
00193 set<int> processed;
00194 while (!primary_heap.empty()) {
00195 path_type *p = primary_heap.top();
00196 primary_heap.pop();
00197 vertex_id bb = (*p).last_bb();
00198 if (member_of(bb, ends)) {
00199 for (int i = 0; i < (*p).bbs.size(); ++i)
00200 ends.insert((*p).bbs[i]);
00201 if (trace) {
00202 fprintf(TFile, "adding path with freq %g: ", (*p).wt);
00203 for (int i = 0; i < (*p).bbs.size(); ++i)
00204 fprintf(TFile, "%d ",(*p).bbs[i]);
00205 fprintf(TFile, "\n");
00206 }
00207 } else {
00208 if (member_of(bb, processed))
00209 secondary_heap.push(p);
00210 else {
00211 processed.insert(bb);
00212 for (predecessor_graph::fast_iterator e = loop[bb].begin();
00213 e != loop[bb].end();
00214 ++e) {
00215 vertex_id pred = (*e).first;
00216 path_type *p2 = CXX_NEW(path_type(*p), &MEM_local_pool);
00217 (*p2).add_bb(pred);
00218 (*p2).wt *= feedback->Get_pred_prob(pred, bb);
00219 primary_heap.push(p2);
00220 }
00221 }
00222 }
00223 if (!secondary_heap.empty()) {
00224 path_type *p = secondary_heap.top();
00225 if (member_of((*p).last_bb(), ends)) {
00226 secondary_heap.pop();
00227 primary_heap.push(p);
00228 }
00229 }
00230
00231 exit_counts = path_exit_counts(g, ends, feedback, false) - orig_counts;
00232 coverage = 1.0 - exit_counts/total_counts;
00233 if (coverage * 100 > min_coverage)
00234 goto butterfly_exit;
00235 }
00236
00237 {
00238 exit_counts = path_exit_counts(g, ends, feedback, false) - orig_counts;
00239 coverage = 1.0 - exit_counts/total_counts;
00240 }
00241
00242 butterfly_exit:
00243 if (trace) {
00244
00245 path_exit_counts(g, ends, feedback, true);
00246 fprintf(TFile, ">>> end loop butterfly with coverage %g, exit_count %g\n",
00247 coverage, exit_counts);
00248 }
00249 return coverage;
00250 }
00251
00252
00253
00254 void add_loop_to_zone(CFG *cfg, BB_NODE *header,
00255 set<vertex_id>& new_loop, zone_container& zones)
00256 {
00257 zones.push_back(zone(zones.size()));
00258 zone_container::iterator z = zones.end()-1;
00259 (*z).loop_butterfly = header->Id();
00260 (*z).profit = 10;
00261
00262 BB_NODE *succ, *pred;
00263 BB_LIST_ITER bb_succ_iter;
00264 BB_LIST_ITER bb_pred_iter;
00265 FOR_ALL_ELEM(pred, bb_pred_iter, Init(header->Pred())) {
00266 int pred_id = pred->Id();
00267 (*z).entry.push_back(edge(pred_id, header->Id()));
00268 }
00269 for (set<vertex_id>::iterator p = new_loop.begin();
00270 p != new_loop.end(); ++p) {
00271 int bb_id = *p;
00272 BB_NODE *bb = cfg->Get_bb(bb_id);
00273 FOR_ALL_ELEM(succ, bb_succ_iter, Init(bb->Succ())) {
00274 int succ_id = succ->Id();
00275 if (new_loop.find(succ_id) != new_loop.end())
00276 (*z).clone.push_back(edge(bb_id, succ_id));
00277 else
00278 (*z).exit.push_back(edge(bb_id, succ_id));
00279 }
00280 }
00281
00282 zone::edge_container tmp;
00283 insert_iterator<zone::edge_container> ins_tmp(tmp, tmp.begin());
00284 (*z).canonicalize();
00285 set_difference((*z).entry.begin(), (*z).entry.end(),
00286 (*z).clone.begin(), (*z).clone.end(), ins_tmp);
00287 (*z).entry.erase((*z).entry.begin(),(*z).entry.end());
00288 (*z).entry.insert((*z).entry.begin(),tmp.begin(),tmp.end());
00289 }
00290
00291
00292 static bool loop_should_be_butterflied(BB_LOOP *loop)
00293 {
00294
00295
00296
00297
00298 if (loop->Depth() != loop->Max_depth())
00299 return false;
00300
00301
00302
00303
00304 if (loop->Trip_count_stmt() != NULL ||
00305 loop->Trip_count_expr() != NULL)
00306 return false;
00307
00308
00309 int bb_count_limit = 2 * WOPT_Enable_CFG_Opt_Limit;
00310 if (loop->True_body_set()->Size() > bb_count_limit)
00311 return false;
00312
00313 return true;
00314 }
00315
00316
00317
00318
00319
00320
00321 void generate_loop_butterfly_zones(COMP_UNIT *cu,
00322 successor_graph &g,
00323 vector<zone>& zones,
00324 int min_coverage,
00325 bool trace)
00326 {
00327 CFG *cfg = cu->Cfg();
00328 OPT_FEEDBACK *feedback = NULL;
00329
00330 for (BB_NODE *header = cfg->First_bb();
00331 header != NULL; header = header->Next()) {
00332 BB_LOOP *loop = header->Loop();
00333 if (loop != NULL &&
00334 loop->Header() == header &&
00335 loop->Well_formed() &&
00336 loop_should_be_butterflied(loop)) {
00337 BB_NODE *bb;
00338 BB_NODE_SET_ITER bb_iter;
00339 set<vertex_id> new_loop;
00340 set<vertex_id> orig_loop;
00341
00342
00343 int inserted_count = 0;
00344 int deleted_count = 0;
00345 FOR_ALL_ELEM(bb, bb_iter, Init(loop->True_body_set())) {
00346 if (!check_hazardous_op(bb)) {
00347 new_loop.insert(bb->Id());
00348 inserted_count++;
00349 } else
00350 deleted_count++;
00351 orig_loop.insert(bb->Id());
00352 }
00353 bool need_cfg_trans = inserted_count > 0 && deleted_count > 0;
00354 if (feedback && inserted_count >= 2) {
00355 predecessor_graph loop_pred_graph;
00356 FOR_ALL_ELEM(bb, bb_iter, Init(loop->True_body_set())) {
00357 BB_NODE *pred;
00358 BB_LIST_ITER bb_pred_iter;
00359 if (member_of(bb->Id(), new_loop)) {
00360 FOR_ALL_ELEM(pred, bb_pred_iter, Init(bb->Pred())) {
00361 if (member_of(pred->Id(), new_loop))
00362 add_edge(loop_pred_graph, edge(pred->Id(), bb->Id()));
00363 }
00364 }
00365 }
00366 set<int> starts, ends;
00367 starts.insert(loop->Loopback()->Id());
00368 ends.insert(loop->Header()->Id());
00369 loop_pred_graph.extend(loop->Loopback()->Id());
00370 loop_pred_graph.extend(loop->Header()->Id());
00371 OPT_POOL_Push( &MEM_local_pool, -1);
00372 double coverage =
00373 butterfly_loop_with_profile(g, orig_loop, loop_pred_graph, starts,
00374 ends, feedback, min_coverage, trace);
00375 OPT_POOL_Pop(&MEM_local_pool, -1);
00376 if (trace)
00377 #ifdef KEY
00378 fprintf(TFile, "new_loop size=%ld, butterfly size=%ld\n",
00379 (long) new_loop.size(), (long) ends.size());
00380 #else
00381 fprintf(TFile, "new_loop size=%d, butterfly size=%d\n",
00382 (INT)new_loop.size(), (INT)ends.size());
00383 #endif
00384 if (coverage * 100 >= min_coverage && new_loop.size() > ends.size()) {
00385 if (trace) {
00386 print_vertex_set(&new_loop, TFile);
00387 print_vertex_set(&ends, TFile);
00388 }
00389 new_loop = ends;
00390 need_cfg_trans = true;
00391 }
00392 }
00393 if (need_cfg_trans)
00394 add_loop_to_zone(cfg, loop->Header(), new_loop, zones);
00395 }
00396 }
00397 }
00398
00399
00400