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 #include "opt_fb.h"
00060 #include <stack>
00061 #include "opt_htable.h"
00062 #include "DaVinci.h"
00063
00064 using std::map;
00065
00066
00067
00068 #define VALIDATE_NODEX( nx, s ) \
00069 Is_True( nx != IDTYPE_NULL, ( "OPT_FEEDBACK::" s " invalid node") )
00070
00071 #define VALIDATE_EDGEX( ex, s ) \
00072 Is_True( ex != IDTYPE_NULL, ( "OPT_FEEDBACK::" s " invalid edge") )
00073
00074 #define VALIDATE_EDGE( nx_src, nx_dst, s ) \
00075 Is_True( nx_src != IDTYPE_NULL && nx_dst != IDTYPE_NULL, \
00076 ( "OPT_FEEDBACK::" s " invalid edge ( %d --> %d)", nx_src, nx_dst) )
00077
00078
00079
00080
00081
00082
00083 bool
00084 OPT_FEEDBACK::Edge_has_freq( IDTYPE nx_src, IDTYPE nx_dst ) const
00085 {
00086 VALIDATE_EDGE( nx_src, nx_dst, "Edge_has_freq" );
00087
00088 const OPT_FB_NODE& node = _fb_opt_nodes[nx_src];
00089 for ( INT t = node.outgoing_edges.size() - 1; t >= 0; t-- ) {
00090 IDTYPE ex = node.outgoing_edges[t];
00091 if ( _fb_opt_edges[ex].destination == nx_dst ) {
00092 return true;
00093 }
00094 }
00095 return false;
00096 }
00097
00098
00099 IDTYPE
00100 OPT_FEEDBACK::Find_edge_by_type( IDTYPE nx, FB_EDGE_TYPE edge_type ) const
00101 {
00102 VALIDATE_NODEX( nx, "Find_edge_by_type" );
00103
00104 const OPT_FB_NODE& node = _fb_opt_nodes[nx];
00105 for ( INT t = node.outgoing_edges.size() - 1; t >= 0; t-- ) {
00106 IDTYPE ex = node.outgoing_edges[t];
00107 if ( _fb_opt_edges[ex].edge_type == edge_type ) {
00108 return ex;
00109 }
00110 }
00111 return IDTYPE_NULL;
00112 }
00113
00114
00115 FB_FREQ
00116 OPT_FEEDBACK::Get_edge_freq_by_type( IDTYPE nx, FB_EDGE_TYPE edge_type ) const
00117 {
00118 VALIDATE_NODEX( nx, "Get_edge_freq_by_type" );
00119
00120 const OPT_FB_NODE& node = _fb_opt_nodes[nx];
00121 for ( INT t = node.outgoing_edges.size() - 1; t >= 0; t-- ) {
00122 IDTYPE ex = node.outgoing_edges[t];
00123 if ( _fb_opt_edges[ex].edge_type == edge_type ) {
00124 return _fb_opt_edges[ex].freq;
00125 }
00126 }
00127 Is_True( false, ( "OPT_FEEDBACK::Get_edge_freq_by_type: edge not found" ) );
00128 return FB_FREQ_UNINIT;
00129 }
00130
00131
00132
00133 FB_FREQ
00134 OPT_FEEDBACK::Get_edge_freq( IDTYPE nx_src, IDTYPE nx_dst ) const
00135 {
00136 VALIDATE_EDGE( nx_src, nx_dst, "Get_edge_freq" );
00137 Is_True( Edge_has_freq( nx_src, nx_dst ),
00138 ( "OPT_FEEDBACK::Get_edge_freq: edge (%d --> %d) not found",
00139 nx_src, nx_dst ) );
00140
00141 const OPT_FB_NODE& node = _fb_opt_nodes[nx_src];
00142 FB_FREQ freq = FB_FREQ_ZERO;
00143 for ( INT t = node.outgoing_edges.size() - 1; t >= 0; t-- ) {
00144 IDTYPE ex = node.outgoing_edges[t];
00145 const OPT_FB_EDGE& edge = _fb_opt_edges[ex];
00146 if (edge.destination == nx_dst)
00147 freq += edge.freq;
00148 }
00149 return freq;
00150 }
00151
00152
00153
00154 IDTYPE
00155 OPT_FEEDBACK::Get_node_successor( IDTYPE nx ) const
00156 {
00157 VALIDATE_NODEX( nx, "Get_node_successor" );
00158
00159 IDTYPE nx_succ = IDTYPE_NULL;
00160 const OPT_FB_NODE& node = _fb_opt_nodes[nx];
00161 for ( INT t = node.outgoing_edges.size() - 1; t >= 0; t-- ) {
00162 IDTYPE ex = node.outgoing_edges[t];
00163 IDTYPE nx_dst = _fb_opt_edges[ex].destination;
00164 Is_True( nx_succ == IDTYPE_NULL || nx_succ == nx_dst,
00165 ( "OPT_FEEDBACK::Get_node_successor:"
00166 " node %d has multiple successors", nx ) );
00167 nx_succ = nx_dst;
00168 }
00169 return nx_succ;
00170 }
00171
00172
00173 float
00174 OPT_FEEDBACK::Get_pred_prob( IDTYPE nx_src, IDTYPE nx_dst ) const
00175 {
00176 if ( ! Edge_has_freq( nx_src, nx_dst ) )
00177 return 0.0;
00178 else {
00179 const OPT_FB_NODE& node = _fb_opt_nodes[nx_dst];
00180 FB_FREQ freq = Get_edge_freq( nx_src, nx_dst );
00181 freq /= node.freq_total_in;
00182 if ( freq.Known() )
00183 return freq.Value();
00184 else
00185 return 1.0 / node.incoming_edges.size();
00186 }
00187 }
00188
00189
00190 float
00191 OPT_FEEDBACK::Get_succ_prob( IDTYPE nx_src, IDTYPE nx_dst ) const
00192 {
00193 if ( ! Edge_has_freq( nx_src, nx_dst ) )
00194 return 0.0;
00195 else {
00196 const OPT_FB_NODE& node = _fb_opt_nodes[nx_src];
00197 FB_FREQ freq = Get_edge_freq( nx_src, nx_dst );
00198 freq /= node.freq_total_out;
00199 if ( freq.Known() )
00200 return freq.Value();
00201 else
00202 return 1.0 / node.outgoing_edges.size();
00203 }
00204 }
00205
00206
00207
00208
00209
00210
00211
00212
00213 void
00214 OPT_FEEDBACK::Add_node( IDTYPE nx_new )
00215 {
00216 if ( _trace )
00217 fprintf( TFile, " OPT_FEEDBACK::Add_node(%d)\n", nx_new );
00218 VALIDATE_NODEX( nx_new, "Add_node" );
00219
00220
00221 if ( nx_new >= _fb_opt_nodes.size() )
00222 _fb_opt_nodes.insert( _fb_opt_nodes.end(),
00223 nx_new - _fb_opt_nodes.size() + 1,
00224 OPT_FB_NODE( _mem_pool ) );
00225 }
00226
00227
00228
00229 void
00230 OPT_FEEDBACK::Add_edge( IDTYPE nx_src, IDTYPE nx_dst,
00231 FB_EDGE_TYPE edge_type, FB_FREQ freq )
00232 {
00233 if ( _trace )
00234 fprintf( TFile, " OPT_FEEDBACK::Add_edge(%d --> %d)\n", nx_src, nx_dst );
00235 VALIDATE_EDGE( nx_src, nx_dst, "Add_edge" );
00236 Is_True( Find_edge_by_type( nx_src, edge_type ) == IDTYPE_NULL,
00237 ( "OPT_FEEDBACK::Add_edge: redundant edge" ) );
00238
00239 OPT_FB_NODE& node_src = _fb_opt_nodes[nx_src];
00240 OPT_FB_NODE& node_dst = _fb_opt_nodes[nx_dst];
00241
00242
00243 OPT_FB_EDGE new_edge( nx_src, nx_dst, edge_type, freq );
00244 IDTYPE ex_new = _fb_opt_edges.size();
00245 _fb_opt_edges.push_back( new_edge );
00246 node_src.outgoing_edges.push_back( ex_new );
00247 node_dst.incoming_edges.push_back( ex_new );
00248
00249
00250 if ( ! freq.Exact() ) {
00251 node_src.unexact_out += 1;
00252 node_dst.unexact_in += 1;
00253
00254 if ( ! freq.Known() ) {
00255 node_src.unknown_out += 1;
00256 node_dst.unknown_in += 1;
00257 }
00258 }
00259 node_src.freq_total_out += freq;
00260 node_dst.freq_total_in += freq;
00261 }
00262
00263
00264
00265
00266 inline void
00267 remove_ex( vector<IDTYPE, mempool_allocator<IDTYPE> >& ex_list, IDTYPE ex )
00268 {
00269 INT last = ex_list.size() - 1;
00270 for ( INT t = last; t >= 0; t-- ) {
00271 if ( ex_list[t] == ex ) {
00272 ex_list[t] = ex_list[last];
00273 ex_list.pop_back();
00274 return;
00275 }
00276 }
00277 Is_True( false, ( "remove_ex (in opt_fb.cxx): ex == %d not found", ex ) );
00278 }
00279
00280
00281
00282 inline void
00283 replace_ex( vector<IDTYPE, mempool_allocator<IDTYPE> >& ex_list,
00284 IDTYPE ex_old, IDTYPE ex_new )
00285 {
00286 for ( INT t = ex_list.size() - 1; t >= 0; t-- ) {
00287 if ( ex_list[t] == ex_old ) {
00288 ex_list[t] = ex_new;
00289 return;
00290 }
00291 }
00292 Is_True( false,
00293 ( "replace_ex (in opt_fb.cxx): ex_old == %d not found", ex_old ) );
00294 }
00295
00296
00297
00298
00299
00300
00301
00302 void
00303 OPT_FEEDBACK::Remove_edge( IDTYPE ex )
00304 {
00305 if ( _trace )
00306 fprintf( TFile, " OPT_FEEDBACK::Remove_edge(ex %d)\n", ex );
00307 VALIDATE_EDGEX( ex, "Remove_edge" );
00308 OPT_FB_EDGE& edge = _fb_opt_edges[ex];
00309 OPT_FB_NODE& node_src = _fb_opt_nodes[edge.source];
00310 OPT_FB_NODE& node_dst = _fb_opt_nodes[edge.destination];
00311 FB_FREQ freq_old = edge.freq;
00312
00313
00314 remove_ex( node_src.outgoing_edges, ex );
00315 remove_ex( node_dst.incoming_edges, ex );
00316
00317
00318 IDTYPE ex_last = _fb_opt_edges.size() - 1;
00319 if ( ex != ex_last ) {
00320 OPT_FB_EDGE &edge_last = _fb_opt_edges[ex_last];
00321 replace_ex( _fb_opt_nodes[edge_last.source].outgoing_edges, ex_last, ex );
00322 replace_ex( _fb_opt_nodes[edge_last.destination].incoming_edges,
00323 ex_last, ex );
00324 _fb_opt_edges[ex] = edge_last;
00325 }
00326
00327
00328 _fb_opt_edges.pop_back();
00329
00330
00331 if ( ! freq_old.Exact() ) {
00332 node_src.unexact_out -= 1;
00333 node_dst.unexact_in -= 1;
00334
00335 if ( ! freq_old.Known() ) {
00336 node_src.unknown_out -= 1;
00337 node_dst.unknown_in -= 1;
00338 }
00339 }
00340 node_src.freq_total_out -= freq_old;
00341 node_dst.freq_total_in -= freq_old;
00342 }
00343
00344
00345
00346 void
00347 OPT_FEEDBACK::Change_edge_freq( IDTYPE ex, FB_FREQ freq_new )
00348 {
00349 if ( _trace )
00350 fprintf( TFile, " OPT_FEEDBACK::Change_edge_freq(ex %d)\n", ex );
00351 VALIDATE_EDGEX( ex, "Change_edge_freq" );
00352
00353 OPT_FB_EDGE& edge = _fb_opt_edges[ex];
00354 OPT_FB_NODE& node_src = _fb_opt_nodes[edge.source];
00355 OPT_FB_NODE& node_dst = _fb_opt_nodes[edge.destination];
00356
00357
00358 FB_FREQ freq_old = edge.freq;
00359 edge.freq = freq_new;
00360
00361
00362 if ( ! freq_old.Exact() ) {
00363 node_src.unexact_out -= 1;
00364 node_dst.unexact_in -= 1;
00365
00366 if ( ! freq_old.Known() ) {
00367 node_src.unknown_out -= 1;
00368 node_dst.unknown_in -= 1;
00369 }
00370 }
00371 node_src.freq_total_out -= freq_old;
00372 node_dst.freq_total_in -= freq_old;
00373
00374
00375 if ( ! freq_new.Exact() ) {
00376 node_src.unexact_out += 1;
00377 node_dst.unexact_in += 1;
00378
00379 if ( ! freq_new.Known() ) {
00380 node_src.unknown_out += 1;
00381 node_dst.unknown_in += 1;
00382 }
00383 }
00384 node_src.freq_total_out += freq_new;
00385 node_dst.freq_total_in += freq_new;
00386 }
00387
00388
00389
00390
00391
00392 void
00393 OPT_FEEDBACK::Set_edge_dest( IDTYPE ex, IDTYPE nx_dst_new ) {
00394 if ( _trace )
00395 fprintf( TFile, " OPT_FEEDBACK::Set_edge_dest(ex %d, nx_dst %d)\n",
00396 ex, nx_dst_new );
00397 VALIDATE_EDGEX( ex, "Set_edge_dest" );
00398 VALIDATE_NODEX( nx_dst_new, "Set_edge_dest" );
00399
00400 OPT_FB_EDGE& edge = _fb_opt_edges[ex];
00401 IDTYPE nx_dst_old = edge.destination;
00402 FB_FREQ freq_edge = edge.freq;
00403
00404 OPT_FB_NODE& node_dst_old = _fb_opt_nodes[nx_dst_old];
00405 OPT_FB_NODE& node_dst_new = _fb_opt_nodes[nx_dst_new];
00406
00407
00408 edge.destination = nx_dst_new;
00409 remove_ex( node_dst_old.incoming_edges, ex );
00410 node_dst_new.incoming_edges.push_back( ex );
00411
00412
00413 if ( ! freq_edge.Known() ) {
00414 node_dst_old.unknown_in -= 1;
00415 node_dst_new.unknown_in += 1;
00416 }
00417 if ( ! freq_edge.Exact() ) {
00418 node_dst_old.unexact_in -= 1;
00419 node_dst_new.unexact_in += 1;
00420 }
00421 node_dst_old.freq_total_in -= freq_edge;
00422 node_dst_new.freq_total_in += freq_edge;
00423 }
00424
00425
00426
00427
00428
00429
00430 void
00431 OPT_FEEDBACK::Freq_propagate_edge_in ( OPT_FB_NODE& node,
00432 IDTYPE edge_id, FB_FREQ freq )
00433 {
00434 Change_edge_freq (edge_id, freq);
00435 node.freq_total_in = node.freq_total_out;
00436 const OPT_FB_EDGE& edge = _fb_opt_edges[edge_id];
00437 const OPT_FB_NODE& pred = _fb_opt_nodes[edge.source];
00438 if ( pred.unknown_out < 2 ) {
00439 Freq_propagate_node_out( edge.source );
00440 }
00441 }
00442
00443
00444 void
00445 OPT_FEEDBACK::Freq_propagate_edge_out (OPT_FB_NODE& node,
00446 IDTYPE edge_id, FB_FREQ freq)
00447 {
00448 Change_edge_freq (edge_id, freq);
00449 node.freq_total_out = node.freq_total_in;
00450 const OPT_FB_EDGE& edge = _fb_opt_edges[edge_id];
00451 const OPT_FB_NODE& succ = _fb_opt_nodes[edge.destination];
00452 if (succ.unknown_in < 2)
00453 Freq_propagate_node_in (edge.destination);
00454
00455 }
00456
00457
00458
00459
00460
00461 void
00462 OPT_FEEDBACK::Freq_propagate_node_in( IDTYPE nx )
00463 {
00464 OPT_FB_NODE& node = _fb_opt_nodes[nx];
00465
00466 if ( _trace_prop ) {
00467 fprintf( TFile, "OPT_FEEDBACK::Freq_propagate_node_in for:\n" );
00468 node.Print( nx, TFile );
00469 }
00470
00471 Is_True( node.unknown_in < 2,
00472 ( "OPT_FEEDBACK::Freq_propagate_node_in: unknown_in"
00473 "[nx%d](uk%d) > 1", nx, node.unknown_in ) );
00474
00475 if ( node.in_out_same &&
00476 node.freq_total_out.Known() && node.unknown_in > 0 ) {
00477
00478
00479
00480 INT unknown_count = 0;
00481 IDTYPE ex_unknown = IDTYPE_NULL;
00482 FB_FREQ freq_total = FB_FREQ_ZERO;
00483 for (OPT_FB_NODE::EDGES_ITER iter (node.incoming_edges.begin ());
00484 iter != node.incoming_edges.end (); ++iter) {
00485 FB_FREQ freq = _fb_opt_edges[*iter].freq;
00486 if ( freq.Known() ) {
00487 freq_total += freq;
00488 } else {
00489 ++unknown_count;
00490 Is_True( unknown_count <= node.unknown_in,
00491 ( "OPT_FEEDBACK::Freq_propagate_node_in[nx%d]"
00492 " found multiple unknown incoming freqs", nx ) );
00493 ex_unknown = *iter;
00494 }
00495 }
00496 Is_True( unknown_count == node.unknown_in,
00497 ( "OPT_FEEDBACK::Freq_propagate_node_in[nx%d]"
00498 " found no unknown outgoing edge freqs", nx ) );
00499
00500 if (unknown_count == 1) {
00501
00502 FB_FREQ freq_found = node.freq_total_out - freq_total;
00503 if ( freq_found.Error() ) return;
00504 Is_True( freq_found.Known(),
00505 ( "OPT_FEEDBACK::Freq_propagate_node_in[nx%d]"
00506 " subtract yields unknown freq", nx ) );
00507 Freq_propagate_edge_in (node, ex_unknown, freq_found);
00508
00509 } else if (freq_total == node.freq_total_out) {
00510
00511
00512 for (OPT_FB_NODE::EDGES_ITER iter (node.incoming_edges.begin ());
00513 iter != node.incoming_edges.end (); ++iter) {
00514
00515 if (! _fb_opt_edges[*iter].freq.Known ())
00516 Freq_propagate_edge_in (node, *iter, FB_FREQ_ZERO);
00517 }
00518 }
00519
00520 } else if ( node.in_out_same &&
00521 node.freq_total_out.Exact() && node.unexact_in > 0 ) {
00522
00523
00524
00525 INT unexact_count = 0;
00526 IDTYPE ex_unexact = IDTYPE_NULL;
00527 FB_FREQ freq_total = FB_FREQ_ZERO;
00528 for (OPT_FB_NODE::EDGES_ITER iter (node.incoming_edges.begin ());
00529 iter != node.incoming_edges.end (); ++iter) {
00530 FB_FREQ freq = _fb_opt_edges[*iter].freq;
00531 if ( freq.Exact() ) {
00532 freq_total += freq;
00533 } else {
00534 ++unexact_count;
00535 Is_True( unexact_count <= node.unexact_in,
00536 ( "OPT_FEEDBACK::Freq_propagate_node_in[nx%d]"
00537 " found multiple unexact incoming freqs", nx ) );
00538 ex_unexact = *iter;
00539 }
00540 }
00541 Is_True( unexact_count == node.unexact_in,
00542 ( "OPT_FEEDBACK::Freq_propagate_node_in"
00543 " found no unexact outgoing edge freqs" ) );
00544
00545 if (unexact_count == 1) {
00546
00547 FB_FREQ freq_found = node.freq_total_out - freq_total;
00548 if ( freq_found.Error() ) return;
00549 Is_True( freq_found.Exact(),
00550 ( "OPT_FEEDBACK::Freq_propagate_node_in[nx%d]"
00551 " subtract yields unexact freq", nx ) );
00552 Freq_propagate_edge_in (node, ex_unexact, freq_found);
00553
00554 } else if (freq_total == node.freq_total_out) {
00555
00556
00557 for (OPT_FB_NODE::EDGES_ITER iter (node.incoming_edges.begin ());
00558 iter != node.incoming_edges.end (); ++iter) {
00559
00560 if (! _fb_opt_edges[*iter].freq.Exact ())
00561 Freq_propagate_edge_in (node, *iter, FB_FREQ_ZERO);
00562 }
00563 }
00564 } else if ( ( node.unknown_in == 0 && ! node.freq_total_in.Known() ) ||
00565 ( node.unexact_in == 0 && ! node.freq_total_in.Exact() ) ) {
00566
00567
00568 FB_FREQ freq_total = FB_FREQ_ZERO;
00569 for (OPT_FB_NODE::EDGES_ITER iter (node.incoming_edges.begin ());
00570 iter != node.incoming_edges.end (); ++iter) {
00571 freq_total += _fb_opt_edges[*iter].freq;
00572 }
00573 Is_True( freq_total.Known(),
00574 ( "OPT_FEEDBACK::Freq_propagate_node_in[nx%d]"
00575 " found an unknown incoming edge freq", nx ) );
00576 Is_True( freq_total.Exact() || node.unexact_in > 0,
00577 ( "OPT_FEEDBACK::Freq_propagate_node_in[nx%d]"
00578 " found an unexact incoming edge freq", nx ) );
00579 node.freq_total_in = freq_total;
00580
00581
00582 if ( node.in_out_same &&
00583 ( node.unknown_out == 1 ||
00584 ( freq_total.Exact() && node.unexact_out == 1 ) ) )
00585 Freq_propagate_node_out( nx );
00586 }
00587 }
00588
00589
00590
00591
00592
00593 void
00594 OPT_FEEDBACK::Freq_propagate_node_out( IDTYPE nx )
00595 {
00596 OPT_FB_NODE& node = _fb_opt_nodes[nx];
00597
00598 if ( _trace_prop ) {
00599 fprintf( TFile, "OPT_FEEDBACK::Freq_propagate_node_out for:\n" );
00600 node.Print( nx, TFile );
00601 }
00602
00603 Is_True( node.unknown_out < 2,
00604 ( "OPT_FEEDBACK::Freq_propagate_node_out: unknown_out"
00605 "[nx%d](uk%d) > 1", nx, node.unknown_out ) );
00606
00607 if ( node.in_out_same &&
00608 node.freq_total_in.Known() && node.unknown_out > 0) {
00609
00610
00611
00612 INT unknown_count = 0;
00613 IDTYPE ex_unknown = IDTYPE_NULL;
00614 FB_FREQ freq_total = FB_FREQ_ZERO;
00615 for (OPT_FB_NODE::EDGES_ITER iter (node.outgoing_edges.begin ());
00616 iter != node.outgoing_edges.end (); ++iter) {
00617 FB_FREQ freq = _fb_opt_edges[*iter].freq;
00618 if ( freq.Known() ) {
00619 freq_total += freq;
00620 } else {
00621 ++unknown_count;
00622 Is_True( unknown_count <= node.unknown_out,
00623 ( "OPT_FEEDBACK::Freq_propagate_node_out[nx%d]"
00624 " found multiple unknown outgoing freqs", nx ) );
00625 ex_unknown = *iter;
00626 }
00627 }
00628 Is_True( unknown_count == node.unknown_out,
00629 ( "OPT_FEEDBACK::Freq_propagate_node_out[nx%d]"
00630 " found no unknown incoming edge freqs", nx ) );
00631
00632 if (unknown_count == 1) {
00633
00634 FB_FREQ freq_found = node.freq_total_in - freq_total;
00635 if ( freq_found.Error() ) return;
00636 Is_True( freq_found.Known(),
00637 ( "OPT_FEEDBACK::Freq_propagate_node_out[nx%d]"
00638 " subtract yields unknown freq", nx ) );
00639 Freq_propagate_edge_out (node, ex_unknown, freq_found);
00640
00641 } else if (freq_total == node.freq_total_in) {
00642
00643 for (OPT_FB_NODE::EDGES_ITER iter (node.outgoing_edges.begin ());
00644 iter != node.outgoing_edges.end (); ++iter) {
00645
00646 if (! _fb_opt_edges[*iter].freq.Known ())
00647 Freq_propagate_edge_out (node, *iter, FB_FREQ_ZERO);
00648 }
00649 }
00650 } else if ( node.in_out_same &&
00651 node.freq_total_in.Exact() && node.unexact_out > 0 ) {
00652
00653
00654
00655 INT unexact_count = 0;
00656 IDTYPE ex_unexact = IDTYPE_NULL;
00657 FB_FREQ freq_total = FB_FREQ_ZERO;
00658 for (OPT_FB_NODE::EDGES_ITER iter (node.outgoing_edges.begin ());
00659 iter != node.outgoing_edges.end (); ++iter) {
00660 FB_FREQ freq = _fb_opt_edges[*iter].freq;
00661 if ( freq.Exact() ) {
00662 freq_total += freq;
00663 } else {
00664 ++unexact_count;
00665 Is_True( unexact_count <= node.unexact_out,
00666 ( "OPT_FEEDBACK::Freq_propagate_node_out[nx%d]"
00667 " found multiple unexact outgoing freqs", nx ) );
00668 ex_unexact = *iter;
00669 }
00670 }
00671 Is_True( unexact_count == node.unexact_out,
00672 ( "OPT_FEEDBACK::Freq_propagate_node_out"
00673 " found no unexact incoming edge freqs" ) );
00674
00675 if (unexact_count == 1) {
00676
00677 FB_FREQ freq_found = node.freq_total_in - freq_total;
00678 if ( freq_found.Error() ) return;
00679 Is_True( freq_found.Exact(),
00680 ( "OPT_FEEDBACK::Freq_propagate_node_out[nx%d]"
00681 " subtract yields unexact freq", nx ) );
00682 Freq_propagate_edge_out (node, ex_unexact, freq_found);
00683
00684 } else if (freq_total == node.freq_total_in) {
00685
00686 for (OPT_FB_NODE::EDGES_ITER iter (node.outgoing_edges.begin ());
00687 iter != node.outgoing_edges.end (); ++iter) {
00688
00689 if (! _fb_opt_edges[*iter].freq.Exact ())
00690 Freq_propagate_edge_out (node, *iter, FB_FREQ_ZERO);
00691 }
00692 }
00693 } else if ( ( node.unknown_out == 0 && ! node.freq_total_out.Known() ) ||
00694 ( node.unexact_out == 0 && ! node.freq_total_out.Exact() ) ) {
00695
00696
00697 FB_FREQ freq_total = FB_FREQ_ZERO;
00698 for ( INT t = 0; t < node.outgoing_edges.size(); t++ ) {
00699 IDTYPE ex = node.outgoing_edges[t];
00700 FB_FREQ freq = _fb_opt_edges[ex].freq;
00701 freq_total += freq;
00702 }
00703 Is_True( freq_total.Known(),
00704 ( "OPT_FEEDBACK::Freq_propagate_node_out[nx%d]"
00705 " found an unknown outgoing edge freq", nx ) );
00706 Is_True( freq_total.Exact() || node.unexact_out > 0,
00707 ( "OPT_FEEDBACK::Freq_propagate_node_out[nx%d]"
00708 " found an unexact outgoing edge freq", nx ) );
00709 node.freq_total_out = freq_total;
00710
00711
00712 if ( node.in_out_same &&
00713 ( node.unknown_in == 1 ||
00714 ( freq_total.Exact() && node.unexact_in == 1 ) ) )
00715 Freq_propagate_node_in( nx );
00716 }
00717 }
00718
00719
00720 void
00721 OPT_FEEDBACK::Freq_propagate()
00722 {
00723 for ( IDTYPE nx = _fb_opt_nodes.size() - 1; nx > 0; nx-- ) {
00724 OPT_FB_NODE& node = _fb_opt_nodes[nx];
00725 if ( node.unknown_in < 2 ) {
00726 Freq_propagate_node_in( nx );
00727 }
00728 if ( node.unknown_out < 2 ) {
00729 Freq_propagate_node_out( nx );
00730 }
00731 }
00732 }
00733
00734
00735
00736
00737
00738
00739 OPT_FEEDBACK::OPT_FEEDBACK( CFG *cfg, MEM_POOL *pool )
00740 : _mem_pool( pool ),
00741 _trace( Get_Trace(TP_FEEDBACK, TP_OPT_FEEDBACK ) ),
00742 _trace_draw( Get_Trace(TP_FEEDBACK, TP_OPT_FEEDBACK_DRAW ) ),
00743 _trace_before( Get_Trace(TP_FEEDBACK, TP_OPT_FEEDBACK_BEFORE) ),
00744 _trace_prop( Get_Trace(TP_FEEDBACK, TP_OPT_FEEDBACK_PROP ) ),
00745 _fb_opt_nodes( mempool_allocator<OPT_FB_NODE>( pool ) ),
00746 _fb_opt_edges( mempool_allocator<OPT_FB_EDGE>( pool ) )
00747 {
00748
00749 _fb_opt_nodes.insert( _fb_opt_nodes.end(), cfg->Last_bb_id() + 1,
00750 OPT_FB_NODE( _mem_pool ) );
00751 _fb_opt_edges.reserve( 2 * cfg->Last_bb_id() );
00752 OPT_FB_EDGE dummy_edge( IDTYPE_NULL, IDTYPE_NULL );
00753 _fb_opt_edges.push_back( dummy_edge );
00754
00755
00756
00757
00758
00759 for ( BB_NODE *bb = cfg->First_bb(); bb != NULL; bb = bb->Next() ) {
00760
00761
00762 if ( ! cfg->Removable_bb( bb ) )
00763 continue;
00764
00765
00766 Is_True( bb->Id() < _fb_opt_nodes.size(),
00767 ( "OPT_FEEDBACK::OPT_FEEDBACK: Last_bb_id is not largest id" ) );
00768 OPT_FB_NODE& node = _fb_opt_nodes[bb->Id()];
00769
00770 if ( bb->Kind() == BB_ENTRY || bb->Kind() == BB_EXIT )
00771 node.in_out_same = false;
00772 else {
00773 STMT_ITER stmt_iter;
00774 WN *wn;
00775 FOR_ALL_ELEM ( wn, stmt_iter, Init( bb->Firststmt(), bb->Laststmt() ) ) {
00776 if ( WN_operator( wn ) != OPR_IO &&
00777 ! Cur_PU_Feedback->Same_in_out( wn ) ) {
00778 node.in_out_same = false;
00779 break;
00780 }
00781 #if defined (TARG_SL) && defined(TARG_SL2)
00782 else if (WN_operator( wn ) != OPR_IO &&
00783 (WN_is_compgoto_for_minor ( wn ) || WN_is_compgoto_para ( wn ))) {
00784 node.in_out_same = false;
00785 break;
00786 }
00787 #endif
00788 }
00789 }
00790
00791
00792
00793 FB_FREQ freq = FB_FREQ_UNINIT;
00794 WN *wn_last;
00795 if ( bb->Kind() == BB_ENTRY )
00796 wn_last = bb->Entrywn();
00797 else
00798 wn_last = bb->Laststmt();
00799
00800 if ( wn_last == NULL ) {
00801 #if defined(TARG_SL) && defined(TARG_SL2)
00802 if(bb->Kind()==BB_REGIONSTART) {
00803 RID* rid=bb->Regioninfo()->Rid();
00804 if(rid!=NULL) {
00805 WN* rgn=bb->Regioninfo()->Orig_wn();
00806 if( rgn!=NULL && WN_operator(rgn)==OPR_REGION) {
00807 FB_FREQ in_freq = Cur_PU_Feedback->Query( rgn, FB_EDGE_CALL_INCOMING );
00808 if ( bb->Succ() )
00809 Add_edge( bb->Id(), bb->Nth_succ(0)->Id(), FB_EDGE_OUTGOING, in_freq);
00810 }
00811 }
00812 }
00813 else if (bb->Kind()==BB_REGIONEXIT) {
00814 RID* rid=bb->Regioninfo()->Rid();
00815 if(rid!=NULL) {
00816 WN* rgn=bb->Regioninfo()->Orig_wn();
00817 if( rgn!=NULL && WN_operator(rgn)==OPR_REGION) {
00818 FB_FREQ out_freq = Cur_PU_Feedback->Query( rgn, FB_EDGE_CALL_OUTGOING);
00819 if ( bb->Succ() )
00820 Add_edge( bb->Id(), bb->Nth_succ(0)->Id(), FB_EDGE_OUTGOING, out_freq);
00821 }
00822 }
00823 }
00824 else if (! cfg->Removable_bb( bb->Nth_succ(0) ) )
00825 Add_edge( bb->Id(), bb->Nth_succ(0)->Id(), FB_EDGE_OUTGOING, FB_FREQ_ZERO );
00826 else
00827 #endif
00828
00829
00830 if ( bb->Succ() )
00831 Add_edge( bb->Id(), bb->Nth_succ(0)->Id(), FB_EDGE_OUTGOING,
00832 FB_FREQ_UNINIT );
00833 } else {
00834
00835 OPERATOR opr = WN_operator( wn_last );
00836
00837 #ifdef KEY
00838 node.orig_wn = NULL;
00839
00840 if( opr == OPR_ICALL ){
00841 node.orig_wn = wn_last;
00842
00843 } else if( !cfg->Calls_break() ){
00844 STMT_ITER stmt_iter;
00845 WN* wn = NULL;
00846 int num_icalls = 0;
00847 FOR_ALL_ELEM ( wn, stmt_iter, Init( bb->Firststmt(), bb->Laststmt() ) ) {
00848 if( WN_operator( wn ) == OPR_ICALL ){
00849 node.orig_wn = wn;
00850 num_icalls++;
00851 }
00852 }
00853
00854 if( num_icalls > 1 ){
00855
00856 DevWarn( "OPT_FEEDBACK::OPT_FEEDBACK(ICALL) more than one icall in a bb" );
00857 node.orig_wn = NULL;
00858 }
00859 }
00860 #endif
00861
00862 switch ( opr ) {
00863
00864 case OPR_PRAGMA:
00865 if ( WN_pragma( wn_last ) != WN_PRAGMA_PREAMBLE_END ) {
00866 Add_edge( bb->Id(), bb->Nth_succ(0)->Id(),
00867 FB_EDGE_OUTGOING, FB_FREQ_UNINIT );
00868 break;
00869 }
00870
00871
00872 case OPR_GOTO:
00873 case OPR_FUNC_ENTRY:
00874 case OPR_ALTENTRY:
00875 freq = Cur_PU_Feedback->Query( wn_last, FB_EDGE_OUTGOING );
00876 Add_edge( bb->Id(), bb->Nth_succ(0)->Id(), FB_EDGE_OUTGOING, freq );
00877 break;
00878
00879 case OPR_RETURN:
00880 case OPR_RETURN_VAL:
00881 #ifdef KEY
00882 case OPR_GOTO_OUTER_BLOCK:
00883 #endif
00884 break;
00885
00886 case OPR_TRUEBR:
00887 case OPR_FALSEBR:
00888
00889 if ( ! cfg->Lower_fully() ) {
00890
00891 if ( bb->Kind() == BB_REPEATEND ) {
00892
00893
00894 WN *wn_loop = bb->Loop()->Orig_wn();
00895
00896 IDTYPE nx_bb = bb->Id();
00897 IDTYPE nx_merge = bb->Loop()->Merge()->Id();
00898 IDTYPE nx_body = bb->Loop()->Body()->Id();
00899
00900 FB_FREQ freq_out =
00901 Cur_PU_Feedback->Query( wn_loop, FB_EDGE_LOOP_OUT );
00902 FB_FREQ freq_back =
00903 Cur_PU_Feedback->Query( wn_loop, FB_EDGE_LOOP_BACK );
00904
00905 Add_edge( nx_bb, nx_merge, FB_EDGE_LOOP_OUT, freq_out );
00906 Add_edge( nx_bb, nx_body, FB_EDGE_LOOP_BACK, freq_back );
00907 break;
00908 }
00909
00910 if ( bb->Kind() == BB_DOEND || bb->Kind() == BB_WHILEEND ) {
00911
00912
00913 WN *wn_loop = bb->Loop()->Orig_wn();
00914
00915 FB_FREQ freq_zero =
00916 Cur_PU_Feedback->Query( wn_loop, FB_EDGE_LOOP_ZERO );
00917 FB_FREQ freq_positive =
00918 Cur_PU_Feedback->Query( wn_loop, FB_EDGE_LOOP_POSITIVE );
00919 FB_FREQ freq_out =
00920 Cur_PU_Feedback->Query( wn_loop, FB_EDGE_LOOP_OUT );
00921 FB_FREQ freq_back =
00922 Cur_PU_Feedback->Query( wn_loop, FB_EDGE_LOOP_BACK );
00923 FB_FREQ freq_exit =
00924 Cur_PU_Feedback->Query( wn_loop, FB_EDGE_LOOP_EXIT );
00925 FB_FREQ freq_iterate =
00926 Cur_PU_Feedback->Query( wn_loop, FB_EDGE_LOOP_ITERATE );
00927
00928 IDTYPE nx_bb = bb->Id();
00929 IDTYPE nx_merge = bb->Loop()->Merge()->Id();
00930 IDTYPE nx_body = bb->Loop()->Body()->Id();
00931
00932 if ( freq_zero.Known() || freq_out.Known() ) {
00933 Add_edge( nx_bb, nx_merge, FB_EDGE_LOOP_ZERO, freq_zero );
00934 Add_edge( nx_bb, nx_merge, FB_EDGE_LOOP_OUT, freq_out );
00935 } else {
00936 Add_edge( nx_bb, nx_merge, FB_EDGE_LOOP_EXIT, freq_exit );
00937 }
00938
00939 if ( freq_positive.Known() || freq_back.Known() ) {
00940 Add_edge( nx_bb, nx_body, FB_EDGE_LOOP_POSITIVE, freq_positive );
00941 Add_edge( nx_bb, nx_body, FB_EDGE_LOOP_BACK, freq_back );
00942 } else {
00943 Add_edge( nx_bb, nx_body, FB_EDGE_LOOP_ITERATE, freq_iterate );
00944 }
00945
00946 break;
00947 }
00948 }
00949
00950 {
00951
00952 FB_FREQ freq_taken =
00953 Cur_PU_Feedback->Query( wn_last, FB_EDGE_BRANCH_TAKEN );
00954 FB_FREQ freq_not_taken =
00955 Cur_PU_Feedback->Query( wn_last, FB_EDGE_BRANCH_NOT_TAKEN );
00956 INT32 label_num = WN_label_number(wn_last);
00957 BB_NODE *bb_branch = cfg->Get_bb_from_label(label_num);
00958 Add_edge( bb->Id(), bb->Next()->Id(),
00959 FB_EDGE_BRANCH_NOT_TAKEN, freq_not_taken );
00960 Add_edge( bb->Id(), bb_branch->Id(),
00961 FB_EDGE_BRANCH_TAKEN, freq_taken );
00962 }
00963 break;
00964
00965 case OPR_REGION:
00966 #if defined (TARG_SL) && defined(TARG_SL2)
00967 {
00968 BB_LIST* succs = bb->Succ();
00969 INT succ_count=0;
00970 while(succs!=NULL) {
00971 succ_count++;
00972 BB_NODE* succbb=succs->Node();
00973 if(succbb->Kind() == BB_EXIT)
00974
00975
00976 Add_edge ( bb->Id(), succbb->Id(), FB_EDGE_OUTGOING, FB_FREQ_ZERO);
00977 else {
00978 FB_FREQ freq_out = Cur_PU_Feedback->Query( wn_last, FB_EDGE_CALL_OUTGOING );
00979 Add_edge ( bb->Id(), succbb->Id(), FB_EDGE_CALL_OUTGOING, FB_FREQ_UNINIT);
00980 }
00981 succs=succs->Next();
00982 }
00983 }
00984 break;
00985 case OPR_REGION_EXIT:
00986 {
00987 RID* rid=bb->Regioninfo()->Rid();
00988 if(rid!=NULL) {
00989 WN* rgn=bb->Regioninfo()->Orig_wn();
00990 if( rgn!=NULL && WN_operator(rgn)==OPR_REGION ) {
00991 FB_FREQ freq_out = Cur_PU_Feedback->Query( rgn, FB_EDGE_CALL_OUTGOING );
00992 if(bb->Succ()) {
00993 Add_edge( bb->Id(), bb->Nth_succ(0)->Id(), FB_EDGE_OUTGOING,freq_out);
00994 }
00995 }
00996 }
00997 }
00998 break;
00999 #endif
01000 case OPR_PICCALL:
01001 case OPR_CALL:
01002 case OPR_ICALL:
01003 case OPR_INTRINSIC_CALL:
01004 freq = Cur_PU_Feedback->Query( wn_last, FB_EDGE_CALL_OUTGOING );
01005 if ( bb->Succ() != NULL ) {
01006 Add_edge( bb->Id(), bb->Nth_succ(0)->Id(), FB_EDGE_OUTGOING, freq );
01007 }
01008 break;
01009
01010 case OPR_IO:
01011 {
01012 freq = Cur_PU_Feedback->Query( wn_last, FB_EDGE_CALL_OUTGOING );
01013
01014 if ( bb->Kind() != BB_IO ) {
01015
01016
01017 Add_edge( bb->Id(), bb->Nth_succ(0)->Id(),
01018 FB_EDGE_IO_OUTGOING, freq );
01019
01020 } else {
01021
01022
01023 BB_NODE *next = bb->Next();
01024 Add_edge( bb->Id(), next->Id(), FB_EDGE_IO_OUTGOING, freq );
01025
01026
01027 freq = FB_FREQ_UNKNOWN;
01028 if ( Cur_PU_Feedback->Same_in_out( wn_last ) )
01029 freq = FB_FREQ_ZERO;
01030
01031 BB_LIST_ITER bb_iter;
01032 BB_NODE *succ;
01033 INT32 branch = 0;
01034 FOR_ALL_ELEM( succ, bb_iter, Init( bb->Succ() ) ) {
01035 if ( succ == next ) continue;
01036
01037 Add_edge( bb->Id(), succ->Id(),
01038 FB_EDGE_IO_ESCAPE( branch ), freq );
01039 ++branch;
01040 }
01041 }
01042 }
01043 break;
01044
01045 case OPR_COMPGOTO:
01046 case OPR_XGOTO:
01047 case OPR_SWITCH:
01048 {
01049 for ( INT32 branch = 0; branch < bb->Switchentries(); ++branch ) {
01050 freq = Cur_PU_Feedback->Query( wn_last, FB_EDGE_SWITCH(branch) );
01051 Add_edge( bb->Id(), bb->Switchcase(branch)->Id(),
01052 FB_EDGE_SWITCH(branch), freq );
01053 }
01054
01055 if ( bb->Switchdefault() != NULL ) {
01056 freq = Cur_PU_Feedback->Query( wn_last, FB_EDGE_SWITCH_DEFAULT );
01057 Add_edge( bb->Id(), bb->Switchdefault()->Id(),
01058 FB_EDGE_SWITCH_DEFAULT, freq );
01059 }
01060 }
01061 break;
01062
01063 default:
01064 #if defined (TARG_SL)
01065 if ( bb->Succ() )
01066 #endif
01067 Add_edge( bb->Id(), bb->Nth_succ(0)->Id(),
01068 FB_EDGE_OUTGOING, FB_FREQ_UNINIT );
01069 break;
01070 }
01071 }
01072 }
01073
01074
01075 if ( _trace_before && _trace ) {
01076 fprintf( TFile, "Before initial frequency propagation:\n" );
01077 Print( TFile );
01078 }
01079
01080
01081 Freq_propagate();
01082
01083
01084 if ( _trace ) {
01085 fprintf( TFile, "After initial frequency propagation:\n" );
01086 Print( TFile );
01087 }
01088 }
01089
01090 OPT_FEEDBACK::~OPT_FEEDBACK()
01091 {
01092 if ( _trace ) Print( TFile );
01093 }
01094
01095
01096
01097
01098
01099 void
01100 OPT_FEEDBACK::Emit_feedback( WN *wn, BB_NODE *bb ) const
01101 {
01102 IDTYPE nx = bb->Id();
01103 const OPT_FB_NODE& node = _fb_opt_nodes[nx];
01104 OPERATOR opr = WN_operator( wn );
01105
01106 if ( _trace ) {
01107 fprintf( TFile, "OPT_FEEDBACK::Emit_feedback bb->Id() = %3d, opr = %s:\n",
01108 nx, OPERATOR_name( opr ) );
01109 }
01110
01111 switch ( opr ) {
01112
01113 case OPR_LABEL:
01114 Cur_PU_Feedback->Annot( wn, FB_EDGE_INCOMING, node.freq_total_in );
01115 break;
01116
01117 case OPR_PRAGMA:
01118 if ( WN_pragma( wn ) == WN_PRAGMA_PREAMBLE_END )
01119 Cur_PU_Feedback->Annot( wn, FB_EDGE_OUTGOING, node.freq_total_in );
01120 break;
01121
01122 case OPR_GOTO:
01123 Cur_PU_Feedback->Annot( wn, FB_EDGE_OUTGOING, node.freq_total_out );
01124 break;
01125
01126 case OPR_FUNC_ENTRY:
01127 case OPR_ALTENTRY:
01128 Cur_PU_Feedback->Annot( wn, FB_EDGE_OUTGOING, node.freq_total_out );
01129 break;
01130
01131 case OPR_RETURN:
01132 case OPR_RETURN_VAL:
01133 #ifdef KEY
01134 case OPR_GOTO_OUTER_BLOCK:
01135 #endif
01136 {
01137
01138 FB_FREQ freq_guess = node.freq_total_in;
01139 if ( freq_guess.Exact() )
01140 freq_guess = FB_FREQ( freq_guess.Value(), false );
01141 Cur_PU_Feedback->Annot( wn, FB_EDGE_INCOMING, freq_guess );
01142 }
01143 break;
01144
01145 case OPR_TRUEBR:
01146 case OPR_FALSEBR:
01147 {
01148 FB_FREQ freq_not = Get_edge_freq( nx, bb->Next()->Id() );
01149 FB_FREQ freq_tkn = _fb_opt_nodes[nx].freq_total_out - freq_not;
01150
01151
01152
01153
01154
01155
01156
01157
01158
01159
01160
01161
01162
01163 Cur_PU_Feedback->Annot( wn, FB_EDGE_BRANCH_TAKEN, freq_tkn );
01164 Cur_PU_Feedback->Annot( wn, FB_EDGE_BRANCH_NOT_TAKEN, freq_not );
01165 }
01166 break;
01167
01168 case OPR_IF:
01169 {
01170 BB_NODE *bb_then = bb->If_then();
01171 BB_NODE *bb_else = bb->If_else();
01172 if ( bb_then == bb_else ) {
01173 DevWarn( "OPT_FEEDBACK::Emit_feedback(IF) identical targets" );
01174 }
01175 FB_FREQ freq_then = Get_edge_freq( nx, bb_then->Id() );
01176 FB_FREQ freq_else = Get_edge_freq( nx, bb_else->Id() );
01177 Cur_PU_Feedback->Annot( wn, FB_EDGE_BRANCH_TAKEN, freq_then );
01178 Cur_PU_Feedback->Annot( wn, FB_EDGE_BRANCH_NOT_TAKEN, freq_else );
01179 }
01180 break;
01181
01182 case OPR_CSELECT:
01183 Cur_PU_Feedback->Annot( wn, FB_EDGE_BRANCH_TAKEN, FB_FREQ_UNKNOWN );
01184 Cur_PU_Feedback->Annot( wn, FB_EDGE_BRANCH_NOT_TAKEN, FB_FREQ_UNKNOWN );
01185 break;
01186
01187 case OPR_DO_LOOP:
01188 case OPR_WHILE_DO:
01189 {
01190
01191 IDTYPE ex_zero = Find_edge_by_type( nx, FB_EDGE_LOOP_ZERO );
01192 IDTYPE ex_pos = Find_edge_by_type( nx, FB_EDGE_LOOP_POSITIVE );
01193 IDTYPE ex_out = Find_edge_by_type( nx, FB_EDGE_LOOP_OUT );
01194 IDTYPE ex_back = Find_edge_by_type( nx, FB_EDGE_LOOP_BACK );
01195
01196 if ( ex_zero > IDTYPE_NULL && ex_pos > IDTYPE_NULL &&
01197 ex_out > IDTYPE_NULL && ex_back > IDTYPE_NULL ) {
01198
01199 FB_FREQ freq_zero = _fb_opt_edges[ex_zero].freq;
01200 FB_FREQ freq_pos = _fb_opt_edges[ex_pos ].freq;
01201 FB_FREQ freq_out = _fb_opt_edges[ex_out ].freq;
01202 FB_FREQ freq_back = _fb_opt_edges[ex_back].freq;
01203 Cur_PU_Feedback->Annot( wn, FB_EDGE_LOOP_ZERO, freq_zero );
01204 Cur_PU_Feedback->Annot( wn, FB_EDGE_LOOP_POSITIVE, freq_pos );
01205 Cur_PU_Feedback->Annot( wn, FB_EDGE_LOOP_OUT, freq_out );
01206 Cur_PU_Feedback->Annot( wn, FB_EDGE_LOOP_BACK, freq_back );
01207
01208 } else {
01209
01210 BB_NODE *bb_body = bb->Loopbody();
01211 FB_FREQ freq_iterate = Get_edge_freq( nx, bb_body->Id() );
01212 FB_FREQ freq_exit = _fb_opt_nodes[nx].freq_total_out - freq_iterate;
01213 Cur_PU_Feedback->Annot( wn, FB_EDGE_LOOP_EXIT, freq_exit );
01214 Cur_PU_Feedback->Annot( wn, FB_EDGE_LOOP_ITERATE, freq_iterate );
01215 }
01216 }
01217 break;
01218
01219 case OPR_DO_WHILE:
01220 {
01221
01222 IDTYPE ex_back = Find_edge_by_type( nx, FB_EDGE_LOOP_BACK );
01223 IDTYPE ex_out = Find_edge_by_type( nx, FB_EDGE_LOOP_OUT );
01224 if ( ex_back == IDTYPE_NULL || ex_out == IDTYPE_NULL ) {
01225 DevWarn("OPT_FEEDBACK::Emit_feedback(DO_WHILE) edge missing" );
01226 }
01227 FB_FREQ freq_back = _fb_opt_edges[ex_back].freq;
01228 FB_FREQ freq_out = _fb_opt_edges[ex_out ].freq;
01229 Cur_PU_Feedback->Annot( wn, FB_EDGE_LOOP_ZERO, FB_FREQ_ZERO );
01230 Cur_PU_Feedback->Annot( wn, FB_EDGE_LOOP_POSITIVE, FB_FREQ_UNKNOWN );
01231 Cur_PU_Feedback->Annot( wn, FB_EDGE_LOOP_OUT, freq_out );
01232 Cur_PU_Feedback->Annot( wn, FB_EDGE_LOOP_BACK, freq_back );
01233 }
01234 break;
01235
01236 case OPR_CAND:
01237 case OPR_CIOR:
01238 Cur_PU_Feedback->Annot( wn, FB_EDGE_CIRCUIT_LEFT, FB_FREQ_UNKNOWN );
01239 Cur_PU_Feedback->Annot( wn, FB_EDGE_CIRCUIT_RIGHT, FB_FREQ_UNKNOWN );
01240 Cur_PU_Feedback->Annot( wn, FB_EDGE_CIRCUIT_NEITHER, FB_FREQ_UNKNOWN );
01241 break;
01242
01243 case OPR_REGION:
01244 case OPR_PICCALL:
01245 case OPR_CALL:
01246 case OPR_ICALL:
01247 case OPR_INTRINSIC_CALL:
01248 if ( node.in_out_same )
01249 Cur_PU_Feedback->Annot( wn, FB_EDGE_CALL_INOUTSAME, node.freq_total_in );
01250 else {
01251
01252 FB_FREQ freq_guess_in = node.freq_total_in;
01253 FB_FREQ freq_guess_out = node.freq_total_out;
01254 if ( bb->Kind() == BB_EXIT )
01255 freq_guess_out = freq_guess_in;
01256 if ( freq_guess_in.Exact() )
01257 freq_guess_in = FB_FREQ( freq_guess_in.Value(), false );
01258 if ( freq_guess_out.Exact() )
01259 freq_guess_out = FB_FREQ( freq_guess_out.Value(), false );
01260
01261 Cur_PU_Feedback->Annot( wn, FB_EDGE_CALL_INCOMING, freq_guess_in );
01262 Cur_PU_Feedback->Annot( wn, FB_EDGE_CALL_OUTGOING, freq_guess_out );
01263
01264
01265
01266 }
01267 #ifdef KEY
01268 if( opr == OPR_ICALL &&
01269 node.orig_wn != NULL ){
01270 FB_Info_Icall fb_info_icall = Cur_PU_Feedback->Query_icall(node.orig_wn);
01271 Cur_PU_Feedback->Annot_icall( wn, fb_info_icall );
01272
01273 if( !fb_info_icall.Is_uninit() ){
01274 FmtAssert( fb_info_icall.tnv._exec_counter >= fb_info_icall.tnv._counters[0],
01275 ("icall execution counter is invalid") );
01276
01277
01278
01279
01280
01281
01282
01283
01284
01285
01286
01287 }
01288 }
01289 #endif // KEY
01290 break;
01291
01292 case OPR_IO:
01293 {
01294 IDTYPE ex_outgoing = Find_edge_by_type( nx, FB_EDGE_IO_OUTGOING );
01295 if ( ex_outgoing == IDTYPE_NULL ) {
01296
01297
01298 FB_FREQ freq_io = node.freq_total_in;
01299 if ( ! node.in_out_same && freq_io.Exact() )
01300 freq_io = FB_FREQ( freq_io.Value(), false );
01301 Cur_PU_Feedback->Annot( wn, FB_EDGE_CALL_INOUTSAME, freq_io );
01302
01303 } else {
01304
01305
01306 FB_FREQ freq_outgoing = _fb_opt_edges[ex_outgoing].freq;
01307
01308
01309 FB_FREQ freq_escape = FB_FREQ_ZERO;
01310 for ( INT32 br = 0; br < FB_IO_ESCAPE_EDGES_MAX; ++br ) {
01311
01312 IDTYPE ex_escape = Find_edge_by_type( nx, FB_EDGE_IO_ESCAPE(br) );
01313 if ( ex_escape == IDTYPE_NULL )
01314 break;
01315 freq_escape += _fb_opt_edges[ex_escape].freq;
01316 }
01317
01318 if ( freq_escape.Exact() && freq_escape.Zero() )
01319 Cur_PU_Feedback->Annot( wn, FB_EDGE_CALL_INOUTSAME, freq_outgoing );
01320 else {
01321 FB_FREQ freq_incoming = freq_outgoing + freq_escape;
01322 Cur_PU_Feedback->Annot( wn, FB_EDGE_CALL_INCOMING, freq_outgoing );
01323 Cur_PU_Feedback->Annot( wn, FB_EDGE_CALL_OUTGOING, freq_outgoing );
01324 }
01325 }
01326 }
01327 break;
01328
01329 case OPR_COMPGOTO:
01330 case OPR_XGOTO:
01331 case OPR_SWITCH:
01332 {
01333 for ( INT t = 0; t < node.outgoing_edges.size(); t++ ) {
01334 IDTYPE ex = node.outgoing_edges[t];
01335 const OPT_FB_EDGE& edge = _fb_opt_edges[ex];
01336 Cur_PU_Feedback->Annot( wn, edge.edge_type, edge.freq );
01337 }
01338 }
01339 break;
01340
01341 default:
01342 break;
01343 }
01344 }
01345
01346
01347
01348
01349
01350
01351
01352
01353
01354 void
01355 OPT_FEEDBACK::Delete_edge( IDTYPE nx_src, IDTYPE nx_dst ) {
01356 if ( _trace )
01357 fprintf( TFile, "OPT_FEEDBACK::Delete_edge(%d --> %d)\n",
01358 nx_src, nx_dst );
01359 VALIDATE_EDGE( nx_src, nx_dst, "Delete_edge" );
01360
01361 bool match = false;
01362 const OPT_FB_NODE& node = _fb_opt_nodes[nx_src];
01363 for ( INT t = node.outgoing_edges.size() - 1; t >= 0; t-- ) {
01364 IDTYPE ex = node.outgoing_edges[t];
01365 if ( _fb_opt_edges[ex].destination == nx_dst ) {
01366 match = true;
01367 Remove_edge( ex );
01368 }
01369 }
01370 if (! match)
01371 DevWarn ("OPT_FEEDBACK::Delete_edge: edge (%d --> %d) not found",
01372 nx_src, nx_dst);
01373 }
01374
01375
01376
01377
01378 void
01379 OPT_FEEDBACK::Move_edge_dest( IDTYPE nx_src,
01380 IDTYPE nx_dst_old, IDTYPE nx_dst_new )
01381 {
01382 if ( _trace )
01383 fprintf( TFile, "OPT_FEEDBACK::Move_edge_dest(%d --> %d, %d)\n",
01384 nx_src, nx_dst_old, nx_dst_new );
01385 VALIDATE_EDGE( nx_src, nx_dst_old, "Move_edge_dest" );
01386 VALIDATE_NODEX( nx_dst_new, "Move_edge_dest" );
01387
01388
01389 bool match = false;
01390 const OPT_FB_NODE& node = _fb_opt_nodes[nx_src];
01391 for ( INT t = node.outgoing_edges.size() - 1; t >= 0; t-- ) {
01392 IDTYPE ex = node.outgoing_edges[t];
01393 if ( _fb_opt_edges[ex].destination == nx_dst_old ) {
01394 match = true;
01395 Set_edge_dest( ex, nx_dst_new );
01396 }
01397 }
01398 Is_True( match, ( "OPT_FEEDBACK::Move_edge_dest: edge (%d --> %d) not found",
01399 nx_src, nx_dst_old ) );
01400 }
01401
01402
01403 void
01404 OPT_FEEDBACK::Move_incoming_edges_dest( IDTYPE nx_dst_old, IDTYPE nx_dst_new )
01405 {
01406 if ( _trace )
01407 fprintf( TFile, "OPT_FEEDBACK::Move_incoming_edges_dest(%d, %d)\n",
01408 nx_dst_old, nx_dst_new );
01409 VALIDATE_NODEX( nx_dst_old, "Move_incoming_edges_dest" );
01410 VALIDATE_NODEX( nx_dst_new, "Move_incoming_edges_dest" );
01411
01412
01413 const OPT_FB_NODE& node = _fb_opt_nodes[nx_dst_old];
01414 for ( INT t = node.incoming_edges.size() - 1; t >= 0; t-- ) {
01415 IDTYPE ex = node.incoming_edges[t];
01416 Set_edge_dest( ex, nx_dst_new );
01417 }
01418 }
01419
01420
01421
01422
01423 void
01424 OPT_FEEDBACK::Merge_outgoing_edges( IDTYPE nx_src, IDTYPE nx_dst_new )
01425 {
01426 if ( _trace )
01427 fprintf( TFile, "OPT_FEEDBACK::Merge_outgoing_paths(%d, %d)\n",
01428 nx_src, nx_dst_new );
01429 VALIDATE_NODEX( nx_src, "Merge_outgoing_edges" );
01430 VALIDATE_NODEX( nx_dst_new, "Merge_outgoing_edges" );
01431
01432
01433 const OPT_FB_NODE& node = _fb_opt_nodes[nx_src];
01434 FB_FREQ freq_outgoing = node.freq_total_out;
01435
01436
01437 for ( INT t = node.outgoing_edges.size() - 1; t >= 0; t-- ) {
01438 IDTYPE ex = node.outgoing_edges[t];
01439 Remove_edge( ex );
01440 }
01441
01442
01443 Add_edge( nx_src, nx_dst_new, FB_EDGE_OUTGOING, freq_outgoing );
01444 }
01445
01446
01447
01448 void
01449 OPT_FEEDBACK::Delete_node( IDTYPE nx ) {
01450 if ( _trace )
01451 fprintf( TFile, "OPT_FEEDBACK::Delete_node(%d)\n", nx );
01452 VALIDATE_NODEX( nx, "Delete_node" );
01453
01454 const OPT_FB_NODE& node = _fb_opt_nodes[nx];
01455
01456
01457 for ( INT t1 = node.incoming_edges.size() - 1; t1 >= 0; --t1 ) {
01458 IDTYPE ex = node.incoming_edges[t1];
01459 Remove_edge( ex );
01460 }
01461
01462
01463 for ( INT t2 = node.outgoing_edges.size() - 1; t2 >= 0; --t2 ) {
01464 IDTYPE ex = node.outgoing_edges[t2];
01465 Remove_edge( ex );
01466 }
01467 }
01468
01469
01470
01471
01472 void
01473 OPT_FEEDBACK::Split_edge( IDTYPE nx_src, IDTYPE nx_mid, IDTYPE nx_dst )
01474 {
01475 if ( _trace )
01476 fprintf( TFile, "OPT_FEEDBACK::Split_edge(%d --> %d --> %d)\n",
01477 nx_src, nx_mid, nx_dst );
01478 VALIDATE_EDGE( nx_src, nx_dst, "Split_edge" );
01479 VALIDATE_NODEX( nx_mid, "Split_edge" );
01480
01481
01482 Add_node( nx_mid );
01483
01484
01485 Move_edge_dest( nx_src, nx_dst, nx_mid );
01486
01487
01488 Add_edge( nx_mid, nx_dst, FB_EDGE_OUTGOING,
01489 _fb_opt_nodes[nx_mid].freq_total_in );
01490 }
01491
01492
01493
01494
01495 void
01496 OPT_FEEDBACK::Split_node( IDTYPE nx_old, IDTYPE nx_new )
01497 {
01498 if ( _trace )
01499 fprintf( TFile, "OPT_FEEDBACK::Split_node(nx_old %d, nx_new %d)\n",
01500 nx_old, nx_new );
01501 VALIDATE_NODEX( nx_old, "Split_node" );
01502 VALIDATE_NODEX( nx_new, "Split_node" );
01503
01504 Add_node( nx_new );
01505 OPT_FB_NODE &node_old = _fb_opt_nodes[nx_old];
01506 OPT_FB_NODE &node_new = _fb_opt_nodes[nx_new];
01507
01508
01509 for ( INT t = node_old.incoming_edges.size() - 1; t >= 0; t-- ) {
01510 IDTYPE ex = node_old.incoming_edges[t];
01511 _fb_opt_edges[ex].destination = nx_new;
01512 }
01513
01514
01515 node_new.incoming_edges.swap(node_old.incoming_edges);
01516 node_new.freq_total_in = node_old.freq_total_in;
01517 node_old.freq_total_in = FB_FREQ_ZERO;
01518 node_new.unknown_in = node_old.unknown_in;
01519 node_old.unknown_in = 0;
01520 node_new.unexact_in = node_old.unexact_in;
01521 node_old.unexact_in = 0;
01522
01523
01524 Add_edge( nx_new, nx_old, FB_EDGE_OUTGOING, node_new.freq_total_in );
01525 }
01526
01527
01528
01529 void
01530 OPT_FEEDBACK::Clone_edge( IDTYPE nx_src_old, IDTYPE nx_dst_old,
01531 IDTYPE nx_src_new, IDTYPE nx_dst_new,
01532 float scale )
01533 {
01534 if ( _trace )
01535 fprintf( TFile, "OPT_FEEDBACK::Clone_edge(%d --> %d, %d --> %d)\n",
01536 nx_src_old, nx_dst_old, nx_src_new, nx_dst_new );
01537 VALIDATE_EDGE( nx_src_old, nx_dst_old, "Clone_edge" );
01538 VALIDATE_EDGE( nx_src_new, nx_dst_new, "Clone_edge" );
01539 Is_True( scale >= 0.0 && scale <= 1.0,
01540 ( "OPT_FEEDBACK::Clone_edge: scale == %f", scale ) );
01541
01542 bool match = false;
01543 OPT_FB_NODE& node_src = _fb_opt_nodes[nx_src_old];
01544 OPT_FB_NODE& node_dst = _fb_opt_nodes[nx_dst_old];
01545 for ( INT t = node_src.outgoing_edges.size() - 1; t >= 0; t-- ) {
01546 IDTYPE ex = node_src.outgoing_edges[t];
01547 const OPT_FB_EDGE& edge = _fb_opt_edges[ex];
01548 if ( edge.destination == nx_dst_old ) {
01549 match = true;
01550 OPT_FB_EDGE& edge = _fb_opt_edges[ex];
01551
01552
01553 FB_FREQ freq_clone = edge.freq * scale;
01554 FB_FREQ freq_origl = edge.freq - freq_clone;
01555 Change_edge_freq( ex, freq_origl );
01556 Add_edge( nx_src_new, nx_dst_new, edge.edge_type, freq_clone );
01557 }
01558 }
01559 Is_True( match, ( "OPT_FEEDBACK::Clone_edge: edge (%d --> %d) not found",
01560 nx_src_old, nx_dst_old ) );
01561 }
01562
01563
01564
01565
01566
01567
01568 struct compare_edge_topological_order {
01569 map<vertex_id, int> topo_pos;
01570 bool operator()(const edge& x, const edge& y) {
01571 if ( topo_pos[x.first] < topo_pos[y.first] ) return true;
01572 if ( topo_pos[x.first] == topo_pos[y.first] &&
01573 topo_pos[x.second] < topo_pos[y.second] ) return true;
01574 return false;
01575 }
01576 compare_edge_topological_order( compare_edge_topological_order &c ):
01577 topo_pos( c.topo_pos ) {}
01578
01579 template <class Container>
01580 compare_edge_topological_order( Container& topo_order ) {
01581 int pos = 0;
01582 for ( typename Container::iterator iv = topo_order.begin();
01583 iv != topo_order.end();
01584 ++iv ) {
01585 vertex_id v = ( *iv );
01586 topo_pos[v] = pos++;
01587 }
01588 }
01589 };
01590
01591
01592
01593
01594
01595
01596
01597
01598
01599
01600
01601
01602
01603 void
01604 OPT_FEEDBACK::Clone_zone( zone& z,
01605 map<vertex_id, vertex_id>& nx_old_to_new )
01606 {
01607 if ( _trace )
01608 fprintf( TFile, "OPT_FEEDBACK::Clone_zone\n" );
01609
01610
01611 vector<vertex_id> topo_order;
01612 edge e = *( z.entry.begin() );
01613 topological_sort( z.clone, e.second, topo_order );
01614
01615 if ( _trace ) {
01616 fprintf( TFile, " topo order for zone: " );
01617 for ( INT i = 0; i < topo_order.size(); ++i )
01618 fprintf( TFile, "%d ", topo_order[i] );
01619 fprintf( TFile, "\n" );
01620 }
01621
01622
01623 compare_edge_topological_order cmp( topo_order );
01624 vector<edge> edge_in_topo_order = z.clone;
01625 sort( edge_in_topo_order.begin(), edge_in_topo_order.end(), cmp );
01626
01627
01628 vector<IDTYPE> edges_clone;
01629 INT i;
01630 for ( i = 0; i < edge_in_topo_order.size(); ++i ) {
01631
01632
01633
01634 const OPT_FB_NODE& node = _fb_opt_nodes[ edge_in_topo_order[i].first ];
01635 vertex_id second = edge_in_topo_order[i].second;
01636 for ( INT t = node.outgoing_edges.size() - 1; t >= 0; t-- ) {
01637 IDTYPE ex = node.outgoing_edges[t];
01638 if ( _fb_opt_edges[ex].destination == second )
01639 edges_clone.push_back( ex );
01640 }
01641 }
01642
01643
01644 vector<IDTYPE> edges_exit;
01645 for ( zone::iterator ie = z.exit.begin(); ie != z.exit.end(); ++ie ) {
01646
01647
01648
01649 const OPT_FB_NODE& node = _fb_opt_nodes[ (*ie).first ];
01650 vertex_id second = (*ie).second;
01651 for ( INT t = node.outgoing_edges.size() - 1; t >= 0; t-- ) {
01652 IDTYPE ex = node.outgoing_edges[t];
01653 const OPT_FB_EDGE& edge = _fb_opt_edges[ex];
01654 if ( edge.destination == second )
01655 edges_exit.push_back( ex );
01656 }
01657 }
01658
01659
01660
01661
01662
01663
01664
01665
01666
01667 map<IDTYPE, FB_FREQ> freq_transfer_node;
01668 map<IDTYPE, FB_FREQ> freq_transfer_edge;
01669
01670
01671 for ( i = 0; i < edges_clone.size(); ++i ) {
01672 IDTYPE ex = edges_clone[i];
01673 const OPT_FB_EDGE& edge = _fb_opt_edges[ex];
01674 freq_transfer_node[ edge.source ] = FB_FREQ_ZERO;
01675 freq_transfer_node[ edge.destination ] = FB_FREQ_ZERO;
01676 }
01677 for ( i = 0; i < edges_exit.size(); ++i ) {
01678 IDTYPE ex = edges_exit[i];
01679 const OPT_FB_EDGE& edge = _fb_opt_edges[ex];
01680 freq_transfer_node[ edge.source ] = FB_FREQ_ZERO;
01681 }
01682
01683
01684 if ( z.loop_butterfly ) {
01685 vertex_id header = z.loop_butterfly;
01686 freq_transfer_node[header] = Get_node_freq_out( header );
01687 } else {
01688 for ( zone::iterator ie = z.entry.begin(); ie != z.entry.end(); ++ie ) {
01689 freq_transfer_node[(*ie).second] +=
01690 Get_edge_freq( (*ie).first, (*ie).second );
01691 }
01692 }
01693
01694
01695 for ( i = 0; i < edges_clone.size(); ++i ) {
01696 IDTYPE ex = edges_clone[i];
01697 const OPT_FB_EDGE& edge = _fb_opt_edges[ex];
01698 IDTYPE nx_src = edge.source;
01699 IDTYPE nx_dst = edge.destination;
01700 OPT_FB_NODE& node = _fb_opt_nodes[nx_src];
01701
01702
01703 FB_FREQ scale = freq_transfer_node[nx_src] / node.freq_total_in;
01704 FB_FREQ freq_transfer = edge.freq * scale;
01705 freq_transfer_edge[ex] = freq_transfer;
01706
01707
01708
01709
01710 if (! (z.loop_butterfly && z.loop_butterfly == nx_dst))
01711 freq_transfer_node[nx_dst] += freq_transfer;
01712 }
01713
01714
01715 for ( i = 0; i < edges_exit.size(); ++i ) {
01716 IDTYPE ex = edges_exit[i];
01717 const OPT_FB_EDGE& edge = _fb_opt_edges[ex];
01718 IDTYPE nx_src = edge.source;
01719 OPT_FB_NODE& node = _fb_opt_nodes[nx_src];
01720
01721
01722 FB_FREQ scale = freq_transfer_node[nx_src] / node.freq_total_in;
01723 FB_FREQ freq_transfer = edge.freq * scale;
01724 freq_transfer_edge[ex] = freq_transfer;
01725 }
01726
01727
01728 if ( _trace ) {
01729 fprintf( TFile, " freq_transfer_node:");
01730 for ( map<IDTYPE, FB_FREQ>::iterator iv = freq_transfer_node.begin();
01731 iv != freq_transfer_node.end(); ++iv ) {
01732 fprintf( TFile, " %d_", (*iv).first );
01733 (*iv).second.Print( TFile );
01734 }
01735 fprintf( TFile, "\n freq_transfer_edge:" );
01736 for ( map<IDTYPE, FB_FREQ>::iterator ie = freq_transfer_edge.begin();
01737 ie != freq_transfer_edge.end(); ++ie ) {
01738 IDTYPE ex = (*ie).first;
01739 const OPT_FB_EDGE& edge = _fb_opt_edges[ex];
01740 fprintf( TFile, " (%d,%d)_", edge.source, edge.destination );
01741 (*ie).second.Print( TFile );
01742 }
01743 fprintf( TFile, "\n" );
01744 }
01745
01746 map<vertex_id, vertex_id>::const_iterator map_iter;
01747
01748
01749 IDTYPE nx_largest = 0;
01750 if ( ! nx_old_to_new.empty() ) {
01751 map_iter = nx_old_to_new.end();
01752 map_iter--;
01753 nx_largest = map_iter->second;
01754 for ( map_iter = nx_old_to_new.begin();
01755 map_iter != nx_old_to_new.end(); map_iter++ ) {
01756 IDTYPE nx_new = map_iter->second;
01757 if ( nx_new > nx_largest )
01758 nx_largest = nx_new;
01759 }
01760 }
01761
01762
01763
01764 if ( _trace )
01765 fprintf( TFile, " Clone the nodes\n" );
01766 Add_node(nx_largest);
01767 for ( map_iter = nx_old_to_new.begin();
01768 map_iter != nx_old_to_new.end(); map_iter++ ) {
01769 OPT_FB_NODE& node_old = _fb_opt_nodes[map_iter->first];
01770 OPT_FB_NODE& node_new = _fb_opt_nodes[map_iter->second];
01771 node_new.update_count = node_old.update_count;
01772 node_new.in_out_same = node_old.in_out_same;
01773 }
01774
01775
01776 if ( _trace )
01777 fprintf( TFile, " Clone the zone.clone edges\n" );
01778 for ( i = 0; i < edges_clone.size(); ++i ) {
01779 IDTYPE ex = edges_clone[i];
01780 const OPT_FB_EDGE& edge = _fb_opt_edges[ex];
01781
01782
01783 FB_FREQ freq_clone = freq_transfer_edge[ex];
01784 FB_FREQ freq_origl = edge.freq - freq_clone;
01785 Change_edge_freq( ex, freq_origl );
01786 Add_edge( nx_old_to_new[edge.source], nx_old_to_new[edge.destination],
01787 edge.edge_type, freq_clone );
01788 }
01789
01790
01791 if ( _trace )
01792 fprintf( TFile, " Clone the zone.exit edges\n" );
01793 for ( i = 0; i < edges_exit.size(); ++i ) {
01794 IDTYPE ex = edges_exit[i];
01795 const OPT_FB_EDGE& edge = _fb_opt_edges[ex];
01796
01797
01798 FB_FREQ freq_clone = freq_transfer_edge[ex];
01799 FB_FREQ freq_origl = edge.freq - freq_clone;
01800 Change_edge_freq( ex, freq_origl );
01801 Add_edge( nx_old_to_new[edge.source], edge.destination,
01802 edge.edge_type, freq_clone );
01803 }
01804 }
01805
01806
01807
01808
01809
01810
01811
01812
01813
01814
01815
01816
01817
01818
01819
01820 void
01821 OPT_FEEDBACK::Print( FILE *fp ) const
01822 {
01823 fprintf( fp, "OPT_FEEDBACK annotation:\n" );
01824
01825
01826 #ifdef KEY
01827 fprintf( fp, "%ld nodes:\n", (long) (_fb_opt_nodes.size() - 1) );
01828 #else
01829 fprintf( fp, "%d nodes:\n", (INT)(_fb_opt_nodes.size() - 1) );
01830 #endif
01831 for ( IDTYPE nx = 1; nx < _fb_opt_nodes.size(); nx++ ) {
01832 _fb_opt_nodes[nx].Print( nx, fp );
01833 }
01834
01835
01836 #ifdef KEY
01837 fprintf( fp, "%ld edges:\n", (long) (_fb_opt_edges.size() - 1) );
01838 #else
01839 fprintf( fp, "%d edges:\n", (INT)(_fb_opt_edges.size() - 1) );
01840 #endif
01841 for ( IDTYPE ex = 1; ex < _fb_opt_edges.size(); ex++ ) {
01842 _fb_opt_edges[ex].Print( ex, fp );
01843 }
01844 }
01845
01846
01847 FB_VERIFY_STATUS
01848 OPT_FEEDBACK::Verify( CFG *cfg, const char *const phase )
01849 {
01850 Freq_propagate();
01851
01852 if ( _trace )
01853 fprintf( TFile, "OPT_FEEDBACK::Verify %s:\n", phase );
01854
01855 bool valid = true, balanced = true;
01856
01857
01858 for ( IDTYPE ex = 1; ex < _fb_opt_edges.size(); ++ex ) {
01859 const OPT_FB_EDGE& edge = _fb_opt_edges[ex];
01860
01861 if ( ! edge.freq.Known() ) {
01862 if ( ! edge.freq.Initialized() )
01863 valid = false;
01864 else
01865 balanced = false;
01866 if ( _trace ) {
01867 fprintf( TFile, " Edge[%d] has incoming frequency == ", ex );
01868 edge.freq.Print( TFile );
01869 fprintf( TFile, "\n" );
01870 }
01871 }
01872 }
01873
01874 for ( IDTYPE nx = 1; nx < _fb_opt_nodes.size(); ++nx ) {
01875 const OPT_FB_NODE& node = _fb_opt_nodes[nx];
01876
01877
01878 INT t, unknown_in = 0, unexact_in = 0;
01879 FB_FREQ freq_total = FB_FREQ_ZERO;
01880 for ( t = 0; t < node.incoming_edges.size(); ++t ) {
01881 IDTYPE ex = node.incoming_edges[t];
01882 const OPT_FB_EDGE& edge = _fb_opt_edges[ex];
01883
01884 Is_True( edge.destination == nx,
01885 ( "OPT_FEEDBACK::Verify found edge[ex%d] destination mismatch"
01886 " (nx%d != nx%d)", ex, edge.destination, nx ) );
01887
01888 freq_total += edge.freq;
01889 if ( ! edge.freq.Known() ) unknown_in += 1;
01890 if ( ! edge.freq.Exact() ) unexact_in += 1;
01891 }
01892
01893 Is_True( node.unknown_in == unknown_in,
01894 ( "OPT_FEEDBACK::Verify found unknown_in[%d] miscount (%d != %d)",
01895 nx, node.unknown_in, unknown_in ) );
01896 Is_True( node.unexact_in == unexact_in,
01897 ( "OPT_FEEDBACK::Verify found unexact_in[%d] miscount (%d != %d)",
01898 nx, node.unexact_in, unexact_in ) );
01899
01900 if ( node.freq_total_in != freq_total ) {
01901 balanced = false;
01902 DevWarn( "OPT_FEEDBACK::Verify found node[%d]"
01903 " freq_total_in mismatch!\n", nx );
01904 }
01905
01906
01907 INT unknown_out = 0, unexact_out = 0;
01908 freq_total = FB_FREQ_ZERO;
01909 for ( t = 0; t < node.outgoing_edges.size(); t++ ) {
01910 IDTYPE ex = node.outgoing_edges[t];
01911 const OPT_FB_EDGE& edge = _fb_opt_edges[ex];
01912
01913 Is_True( edge.source == nx,
01914 ( "OPT_FEEDBACK::Verify found edge[ex%d] source mismatch"
01915 " (nx%d != nx%d)", ex, edge.source, nx ) );
01916
01917 freq_total += edge.freq;
01918 if ( ! edge.freq.Known() ) unknown_out += 1;
01919 if ( ! edge.freq.Exact() ) unexact_out += 1;
01920 }
01921
01922 Is_True( node.unknown_out == unknown_out,
01923 ( "OPT_FEEDBACK::Verify found unknown_out[%d] miscount"
01924 " (%d != %d)", nx, node.unknown_out, unknown_out ) );
01925 Is_True( node.unexact_out == unexact_out,
01926 ( "OPT_FEEDBACK::Verify found unexact_out[%d] miscount"
01927 " (%d != %d)", nx, node.unexact_out, unexact_out ) );
01928
01929 if ( node.freq_total_out != freq_total ) {
01930 balanced = false;
01931 DevWarn( " OPT_FEEDBACK::Verify found node[%d]"
01932 " freq_total_out mismatch\n", nx );
01933 }
01934
01935
01936 if ( node.in_out_same &&
01937 node.freq_total_in != node.freq_total_out &&
01938 node.freq_total_in.Known() &&
01939 node.freq_total_out.Known() ) {
01940
01941 balanced = false;
01942 if ( _trace ) {
01943 fprintf( TFile, " Node[%d] is unbalanced: incoming == ", nx );
01944 node.freq_total_in.Print( TFile );
01945 fprintf( TFile, ", outgoing == " );
01946 node.freq_total_out.Print( TFile );
01947 fprintf( TFile, "\n" );
01948 }
01949 }
01950 }
01951
01952
01953 for ( BB_NODE *bb = cfg->First_bb(); bb != NULL; bb = bb->Next() ) {
01954
01955 if ( ! cfg->Removable_bb( bb ) )
01956 continue;
01957
01958 if ( bb->Id() >= _fb_opt_nodes.size() ) {
01959 valid = false;
01960 if ( _trace )
01961 #ifdef KEY
01962 fprintf( TFile, " CFG bb%d missing feedback! (_fb_opt_nodes.size()"
01963 " = %ld)\n", bb->Id(), (long) _fb_opt_nodes.size() );
01964 #else
01965 fprintf( TFile, " CFG bb%d missing feedback! (_fb_opt_nodes.size()"
01966 " = %d)\n", bb->Id(), (INT)_fb_opt_nodes.size() );
01967 #endif
01968 }
01969 const OPT_FB_NODE& node = _fb_opt_nodes[bb->Id()];
01970
01971 BB_LIST_ITER bb_iter;
01972 BB_NODE *succ;
01973 FOR_ALL_ELEM( succ, bb_iter, Init(bb->Succ()) ) {
01974 if ( ! Edge_has_freq( bb->Id(), succ->Id() )
01975 && cfg->Removable_bb( succ ) ) {
01976 valid = false;
01977 if ( _trace )
01978 fprintf( TFile, " CFG edge (bb%d --> bb%d) missing feedback!\n",
01979 bb->Id(), succ->Id() );
01980 }
01981 }
01982 }
01983
01984 if ( ! valid )
01985 DevWarn ( "OPT_FEEDBACK failed validation!" );
01986
01987
01988 if ( _trace ) {
01989 if ( valid )
01990 fprintf( TFile, "OPT_FEEDBACK valid %s\n", phase );
01991 else
01992 fprintf( TFile, "OPT_FEEDBACK invalid %s\n", phase );
01993 if ( balanced )
01994 fprintf( TFile, "OPT_FEEDBACK balanced %s\n", phase );
01995 else
01996 fprintf( TFile, "OPT_FEEDBACK unbalanced %s\n", phase );
01997 }
01998
01999
02000 if ( ! valid ) {
02001 DevWarn( "OPT Feedback invalid" );
02002 return FB_VERIFY_INVALID;
02003 } else if ( ! balanced ) {
02004 DevWarn( "OPT Feedback unbalanced" );
02005 return FB_VERIFY_UNBALANCED;
02006 } else
02007 return FB_VERIFY_CONSISTENT;
02008 }
02009
02010
02011
02012
02013
02014
02015 static DaVinci *DV = NULL;
02016 static MEM_POOL DV_fb_mempool;
02017
02018 void
02019 OPT_FEEDBACK::Print_node( FILE *fp, IDTYPE nx ) const
02020 {
02021 _fb_opt_nodes[nx].Print( nx, fp );
02022 }
02023
02024 void
02025 OPT_FEEDBACK::Print_edge( FILE *fp, IDTYPE nx_src, IDTYPE nx_dst ) const
02026 {
02027 const OPT_FB_NODE& node = _fb_opt_nodes[nx_src];
02028 for ( INT t = 0; t < node.outgoing_edges.size(); t++ ) {
02029 IDTYPE ex = node.outgoing_edges[t];
02030 const OPT_FB_EDGE& edge = _fb_opt_edges[ex];
02031 if ( edge.destination == nx_dst )
02032 _fb_opt_edges[ex].Print( ex, fp );
02033 }
02034 }
02035
02036 class OPT_FB_Callback : public DaVinci_Callback {
02037 private:
02038 const OPT_FEEDBACK& _cfg;
02039 public:
02040 OPT_FB_Callback( const OPT_FEEDBACK& cfg ) : _cfg( cfg ) {}
02041
02042 virtual void Node_Select( const INT n_ids, const NODE_ID id_array[] );
02043 virtual void Edge_Select( const EDGE_ID& edge_id );
02044 };
02045
02046 void
02047 OPT_FB_Callback::Node_Select( const INT n_ids, const NODE_ID id_array[] )
02048 {
02049 for (INT i = 0; i < n_ids; ++i) {
02050 IDTYPE nx = IDTYPE(INTPS(id_array[i]));
02051 _cfg.Print_node( stderr, nx );
02052 }
02053 }
02054
02055 void
02056 OPT_FB_Callback::Edge_Select( const EDGE_ID& edge_id )
02057 {
02058 IDTYPE nx_src = IDTYPE(INTPS(edge_id.src));
02059 IDTYPE nx_dst = IDTYPE(INTPS(edge_id.dst));
02060 _cfg.Print_edge( stderr, nx_src, nx_dst );
02061 }
02062
02063 char *
02064 OPT_FEEDBACK::Node_label( IDTYPE nx ) const
02065 {
02066 static char label[50];
02067 char *cp = label;
02068
02069 const OPT_FB_NODE& node = _fb_opt_nodes[nx];
02070
02071
02072 cp += sprintf( cp, "%d: ", nx );
02073 cp += sprintf( cp, "\\nin = " );
02074 cp += node.freq_total_in.Sprintf( cp );
02075 cp += sprintf( cp, "\\nout = " );
02076 cp += node.freq_total_out.Sprintf( cp );
02077
02078 return label;
02079 }
02080
02081
02082 void
02083 OPT_FEEDBACK::Draw() const
02084 {
02085 NODE_TYPE nt_unbalanced, nt_exact, nt_guess, nt_unknown, nt_change;
02086 EDGE_TYPE et_exact, et_guess, et_unknown, et_uninit;
02087
02088
02089 nt_unbalanced.Color ("light sky blue");
02090 nt_guess.Color( "pink" );
02091 nt_unknown.Color( "orange" );
02092 nt_change.Color( "light green" );
02093 et_guess.Color( "red" );
02094 et_unknown.Color( "orange" );
02095 et_uninit.Color( "blue" );
02096
02097 DV->Graph_Begin();
02098
02099 for ( IDTYPE nx = 1; nx < _fb_opt_nodes.size(); nx++ ) {
02100 const OPT_FB_NODE& node = _fb_opt_nodes[nx];
02101
02102 FB_FREQ freq = node.freq_total_in + node.freq_total_out;
02103 NODE_TYPE *nt = &nt_exact;
02104 if ( ! node.in_out_same ) nt = &nt_change;
02105 else if ( ! freq.Known() ) nt = &nt_unknown;
02106 else if ( node.freq_total_in != node.freq_total_out )
02107 nt = &nt_unbalanced;
02108 else if ( freq.Guess() ) nt = &nt_guess;
02109
02110
02111 DV->Node_Begin( NODE_ID(INTPTR(nx)), Node_label(nx), *nt );
02112 for ( INT t = 0; t < node.outgoing_edges.size(); t++ ) {
02113 IDTYPE ex = node.outgoing_edges[t];
02114 const OPT_FB_EDGE& edge = _fb_opt_edges[ex];
02115 FB_FREQ freq = edge.freq;
02116
02117 EDGE_TYPE *et = &et_uninit;
02118 if ( edge.freq.Exact() ) et = &et_exact;
02119 else if ( edge.freq.Guess() ) et = &et_guess;
02120 else if ( edge.freq.Initialized() ) et = &et_unknown;
02121
02122 IDTYPE nx_dst = edge.destination;
02123 DV->Out_Edge( EDGE_ID(NODE_ID(INTPTR(nx)), NODE_ID(INTPTR(nx_dst))),
02124 *et, NODE_ID(INTPTR(nx_dst)) );
02125 }
02126 DV->Node_End();
02127
02128 }
02129 DV->Graph_End();
02130 }
02131
02132
02133 void dV_view_fb_opt_cfg( const OPT_FEEDBACK& cfg,
02134 WN *wn_tree, const char *caller )
02135 {
02136 const char *trace_fname = getenv( "DV_TRACE_FILE" );
02137 FILE *trace_fp = NULL;
02138 const char *func_name = "<unknown func>";
02139 char title[100];
02140
02141 if ( ! DaVinci::enabled( true ) ) return;
02142
02143 if ( wn_tree && WN_operator( wn_tree ) == OPR_FUNC_ENTRY ) {
02144 func_name = ST_name( WN_entry_name( wn_tree ) );
02145 }
02146 sprintf( title, "OPT_FEEDBACK display: %s ", func_name );
02147
02148 FmtAssert( DV == NULL, ( "dV_view_fb_cfg: DV is null" ) );
02149 MEM_POOL_Initialize( &DV_fb_mempool, "DV_fb_mempool", FALSE );
02150 MEM_POOL_Push( &DV_fb_mempool );
02151
02152 DV = CXX_NEW( DaVinci( &DV_fb_mempool, trace_fp ), &DV_fb_mempool );
02153
02154 DV->Title( title );
02155 if ( caller ) DV->Show_Status( caller );
02156 cfg.Draw();
02157
02158 OPT_FB_Callback callback( cfg );
02159 DV->Event_Loop( &callback );
02160
02161 CXX_DELETE( DV, &DV_fb_mempool );
02162 DV = NULL;
02163
02164 MEM_POOL_Pop( &DV_fb_mempool );
02165 MEM_POOL_Delete( &DV_fb_mempool );
02166
02167 if ( trace_fp ) (void) fclose( trace_fp );
02168 }
02169
02170
02171 void
02172 OPT_FEEDBACK::Display( WN *wn_tree, const char *caller ) const
02173 {
02174 static char title[80];
02175
02176 if ( _trace_draw ) {
02177 sprintf( title, "OPT_FEEDBACK for %s", caller );
02178 dV_view_fb_opt_cfg( *this, wn_tree, title );
02179 }
02180 }
02181
02182
02183
02184
02185
02186
02187
02188
02189
02190
02191
02192
02193
02194
02195
02196
02197
02198
02199
02200
02201
02202
02203
02204
02205
02206
02207
02208
02209
02210
02211
02212
02213
02214
02215
02216
02217
02218
02219
02220
02221
02222
02223
02224
02225
02226
02227
02228
02229
02230
02231
02232
02233
02234
02235
02236
02237
02238
02239
02240
02241
02242
02243
02244
02245
02246
02247
02248
02249
02250
02251
02252
02253
02254
02255
02256
02257
02258
02259
02260
02261
02262
02263
02264
02265
02266
02267
02268
02269
02270
02271
02272
02273
02274
02275
02276
02277
02278
02279
02280
02281
02282
02283
02284
02285
02286
02287
02288
02289
02290
02291
02292
02293
02294
02295
02296
02297
02298
02299
02300
02301
02302
02303
02304
02305
02306
02307
02308
02309
02310
02311
02312
02313
02314
02315
02316
02317
02318
02319
02320
02321
02322
02323
02324
02325
02326
02327
02328
02329
02330
02331
02332
02333
02334
02335
02336
02337
02338
02339
02340
02341
02342
02343
02344
02345
02346
02347
02348
02349
02350
02351
02352
02353
02354
02355
02356
02357
02358
02359
02360
02361
02362
02363
02364
02365
02366
02367
02368
02369
02370
02371
02372
02373
02374
02375
02376
02377
02378
02379
02380
02381
02382
02383
02384
02385
02386
02387
02388
02389
02390
02391
02392
02393
02394
02395
02396
02397
02398
02399
02400
02401
02402
02403
02404
02405
02406
02407
02408
02409
02410
02411
02412
02413
02414
02415
02416
02417
02418
02419
02420
02421
02422
02423
02424
02425
02426
02427
02428
02429
02430
02431
02432
02433
02434
02435
02436
02437
02438
02439
02440
02441
02442
02443
02444
02445
02446
02447
02448
02449
02450
02451
02452
02453
02454
02455
02456
02457
02458
02459
02460
02461
02462
02463
02464
02465
02466
02467
02468
02469
02470
02471
02472
02473
02474
02475
02476
02477
02478
02479
02480
02481
02482
02483
02484
02485
02486
02487
02488
02489
02490
02491
02492
02493
02494
02495