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 #ifdef USE_PCH
00061 #include "be_com_pch.h"
00062 #endif
00063 #pragma hdrstop
00064 #define USE_STANDARD_TYPES
00065
00066 #include <cmplrs/fb.h>
00067 #include <stdlib.h>
00068 #include "wn_util.h"
00069 #include "wn_map.h"
00070 #include "errors.h"
00071 #include "tracing.h"
00072
00073 #include "fb_cfg.h"
00074 #include "fb_whirl.h"
00075 #include "com_whirlview.h"
00076
00077 #include "cxx_graph.h"
00078
00079 #include "DaVinci.h"
00080 #include "wb_util.h"
00081
00082
00083
00084 FB_NODEX
00085 FB_CFG::New_node()
00086 {
00087 FB_NODE new_node;
00088 FB_NODEX new_nodex = _nodes.size();
00089 _nodes.push_back( new_node );
00090 return new_nodex;
00091 }
00092
00093 FB_NODEX
00094 FB_CFG::New_node( FB_EDGE_TYPE node_type, WN *source, FB_FREQ freq_total_in,
00095 FB_FREQ freq_total_out, bool in_out_same )
00096 {
00097 FB_NODE new_node( node_type, source, in_out_same,
00098 freq_total_in, freq_total_out );
00099 FB_NODEX new_nodex = _nodes.size();
00100 _nodes.push_back(new_node);
00101 return new_nodex;
00102 }
00103
00104
00105
00106
00107 void
00108 FB_CFG::Adjust_edge( FB_NODEX nodex)
00109 {
00110 INT s;
00111
00112 for ( INT t = _nodes[nodex].preds.size() - 1; t >= 0; --t ){
00113 FB_NODEX nx_pred = _nodes[nodex].preds[t];
00114 FB_NODE& pred = _nodes[nx_pred];
00115 if(!( _nodes[nodex].one_edge_preds || pred.one_edge_succs)) {
00116
00117 _nodes[nodex].preds.erase(_nodes[nodex].preds.begin() + t);
00118
00119 for ( s = pred.succs.size() - 1; s >= 0; --s ){
00120 FB_NODEX nx_succs = pred.succs[s];
00121 if (nx_succs == nodex) {
00122 FB_NODEX *del_one;
00123 del_one = &(pred.succs[s]);
00124 pred.succs.erase(pred.succs.begin()+s);
00125 _nodes[nx_pred].undelayed_succs -= 1;
00126
00127 break;
00128 }
00129 }
00130
00131 if (s < 0)
00132 DevWarn( "Some thing wrong with edge adjust" );
00133
00134 FB_NODEX nx_tmp = New_node();
00135
00136 if ( ! _nodes[nodex].freq_total_in.Exact() ) {
00137 _nodes[nx_pred].unexact_out -= 1;
00138 if ( ! _nodes[nodex].freq_total_in.Known() )
00139 _nodes[nx_pred].unknown_out -= 1;
00140 }
00141
00142 if ( ! _nodes[nx_pred].freq_total_out.Exact() ) {
00143 _nodes[nodex].unexact_in -= 1;
00144 if ( ! _nodes[nx_pred].freq_total_out.Known() )
00145 _nodes[nodex].unknown_in -= 1;
00146 }
00147
00148 Add_edge(nx_pred, nx_tmp);
00149 Add_edge(nx_tmp, nodex);
00150
00151 _nodes[nodex].one_edge_preds = TRUE;
00152 for ( s = _nodes[nodex].preds.size() - 1; s >= 0; --s ){
00153 FB_NODEX nx_spred = _nodes[nodex].preds[s];
00154 FB_NODE& spred = _nodes[nx_spred];
00155 if (spred.succs.size() >=2 ){
00156 _nodes[nodex].one_edge_preds = FALSE;
00157 break;
00158 }
00159 }
00160 _nodes[nx_pred].one_edge_succs = TRUE;
00161 for ( s = _nodes[nx_pred].succs.size() - 1; s >= 0; --s ){
00162 FB_NODEX nx_succ = _nodes[nx_pred].succs[s];
00163 FB_NODE& succ= _nodes[nx_succ];
00164 if (succ.preds.size() >=2 ){
00165 _nodes[nx_pred].one_edge_succs = FALSE;
00166 break;
00167 }
00168 }
00169
00170 }
00171 }
00172 }
00173
00174 void
00175 FB_CFG::Add_edge( FB_NODEX nx_src, FB_NODEX nx_dst, bool delayed )
00176 {
00177 Is_True( FB_NODEX_VALID( nx_src ),
00178 ( "FB_CFG::Add_edge encountered invalid source node" ) );
00179 Is_True( FB_NODEX_VALID( nx_dst ),
00180 ( "FB_CFG::Add_edge encountered invalid destination node" ) );
00181
00182
00183 _nodes[nx_src].succs.push_back( nx_dst );
00184 if ( ! _nodes[nx_dst].freq_total_in.Exact() ) {
00185 _nodes[nx_src].unexact_out += 1;
00186 if ( ! _nodes[nx_dst].freq_total_in.Known() )
00187 _nodes[nx_src].unknown_out += 1;
00188 }
00189 if ( _nodes[nx_src].succs.size() == 2 ) {
00190 _nodes[_nodes[nx_src].succs[0]].one_edge_preds = FALSE;
00191 }
00192 if ( _nodes[nx_src].succs.size() >= 2 ) {
00193 _nodes[nx_dst].one_edge_preds = FALSE;
00194 }
00195
00196
00197 _nodes[nx_dst].preds.push_back( nx_src );
00198 if ( ! _nodes[nx_src].freq_total_out.Exact() ) {
00199 _nodes[nx_dst].unexact_in += 1;
00200 if ( ! _nodes[nx_src].freq_total_out.Known() )
00201 _nodes[nx_dst].unknown_in += 1;
00202 }
00203 if ( _nodes[nx_dst].preds.size() == 2 ) {
00204 _nodes[_nodes[nx_dst].preds[0]].one_edge_succs = FALSE;
00205 }
00206 if ( _nodes[nx_dst].preds.size() >= 2 ) {
00207 _nodes[nx_src].one_edge_succs = FALSE;
00208 }
00209 if ( ! delayed ) {
00210 _nodes[nx_src].undelayed_succs += 1;
00211 }
00212 }
00213
00214 void
00215 FB_CFG::Add_delayed_edge( FB_NODEX nx_src, WN *wn )
00216 {
00217 #ifdef Is_True_On
00218 if ( ! FB_NODEX_VALID( nx_src ) ) {
00219 DevWarn( "FB_CFG::Add_delayed_edge encountered invalid source node" );
00220 }
00221 #endif
00222
00223 LABEL_IDX lx_dst = WN_label_number(wn);
00224 Is_True( lx_dst > LABEL_IDX_ZERO,
00225 ( "FB_CFG::Add_delayed_edge: lx_dst == %d should be positive",
00226 lx_dst ) );
00227 FB_EDGE_DELAYED new_edge( nx_src, lx_dst );
00228 _delayed_edges.push_back( new_edge );
00229 }
00230
00231 void
00232 FB_CFG::Complete_delayed_edges()
00233 {
00234 while ( ! _delayed_edges.empty() ) {
00235 FB_EDGE_DELAYED new_edge = _delayed_edges.front();
00236 _delayed_edges.pop_front();
00237 LABEL_IDX lx_dst = new_edge.destination;
00238 FB_NODEX nx_dst = _lblx_to_nx[lx_dst];
00239 Add_edge( new_edge.source, nx_dst, TRUE );
00240 }
00241 }
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255 FB_NODEX
00256 FB_CFG::Get_curr()
00257 {
00258 if ( ! FB_NODEX_VALID( Curr() ) ) {
00259 FB_NODEX nx_new = New_node( FB_EDGE_UNINIT, NULL, FB_FREQ_ZERO );
00260 Set_curr( nx_new );
00261 }
00262 return Curr();
00263 }
00264
00265
00266 void
00267 FB_CFG::Walk_WN_expression( WN *wn )
00268 {
00269 OPERATOR opr = WN_operator( wn );
00270
00271 switch ( opr ) {
00272
00273 case OPR_CAND:
00274 case OPR_CIOR:
00275 {
00276 FB_FREQ freq_left, freq_right, freq_neither;
00277 freq_left = Cur_PU_Feedback->Query( wn, FB_EDGE_CIRCUIT_LEFT );
00278 freq_right = Cur_PU_Feedback->Query( wn, FB_EDGE_CIRCUIT_RIGHT );
00279 freq_neither = Cur_PU_Feedback->Query( wn, FB_EDGE_CIRCUIT_NEITHER );
00280
00281
00282 FB_NODEX nx_left = New_node( FB_EDGE_CIRCUIT_LEFT, wn, freq_left );
00283 FB_NODEX nx_not_left = New_node();
00284 if (opr == OPR_CAND) {
00285 Walk_WN_test_expression( WN_kid0(wn), nx_not_left, nx_left );
00286 } else {
00287 Walk_WN_test_expression( WN_kid0(wn), nx_left, nx_not_left );
00288 }
00289
00290
00291 Set_curr( nx_not_left );
00292 FB_NODEX nx_right = New_node( FB_EDGE_CIRCUIT_RIGHT, wn, freq_right );
00293 FB_NODEX nx_neither = New_node( FB_EDGE_CIRCUIT_NEITHER, wn,
00294 freq_neither );
00295 if (opr == OPR_CAND) {
00296 Walk_WN_test_expression( WN_kid1(wn), nx_neither, nx_right );
00297 } else {
00298 Walk_WN_test_expression( WN_kid1(wn), nx_right, nx_neither );
00299 }
00300
00301
00302 FB_NODEX nx_join = New_node();
00303 Add_edge( nx_left, nx_join );
00304 Add_edge( nx_right, nx_join );
00305 Add_edge( nx_neither, nx_join );
00306 Set_curr( nx_join );
00307 }
00308 break;
00309
00310 case OPR_COMMA:
00311 Walk_WN_statement(WN_kid0(wn));
00312 Walk_WN_expression(WN_kid1(wn));
00313 break;
00314
00315 case OPR_RCOMMA:
00316 Walk_WN_expression(WN_kid0(wn));
00317 Walk_WN_statement(WN_kid1(wn));
00318 break;
00319
00320 case OPR_CSELECT:
00321 {
00322 FB_FREQ freq_then, freq_else;
00323 freq_then = Cur_PU_Feedback->Query( wn, FB_EDGE_BRANCH_TAKEN );
00324 freq_else = Cur_PU_Feedback->Query( wn, FB_EDGE_BRANCH_NOT_TAKEN );
00325
00326
00327 FB_NODEX nx_then = New_node( FB_EDGE_BRANCH_TAKEN, wn, freq_then );
00328 FB_NODEX nx_else = New_node( FB_EDGE_BRANCH_NOT_TAKEN, wn, freq_else );
00329 Walk_WN_test_expression( WN_kid0(wn), nx_then, nx_else );
00330
00331
00332 Set_curr( nx_then );
00333 Walk_WN_expression( WN_kid1(wn) );
00334 nx_then = Curr();
00335
00336
00337 Set_curr( nx_else );
00338 Walk_WN_expression( WN_kid2(wn) );
00339 nx_else = Curr();
00340
00341
00342 FB_NODEX nx_join = New_node();
00343 Add_edge( nx_then, nx_join );
00344 Add_edge( nx_else, nx_join );
00345 Set_curr( nx_join );
00346 }
00347 break;
00348
00349 case OPR_CALL:
00350 case OPR_ICALL:
00351 case OPR_VFCALL:
00352 case OPR_PICCALL:
00353 case OPR_INTRINSIC_CALL:
00354
00355 if ( Cur_PU_Feedback->Same_in_out( wn ) ) {
00356
00357
00358 for ( INT t = 0; t < WN_kid_count(wn); ++t )
00359 Walk_WN_expression( WN_kid( wn, t ) );
00360
00361 FB_FREQ freq = Cur_PU_Feedback->Query( wn, FB_EDGE_CALL_INOUTSAME );
00362
00363 FB_NODEX nx_next = New_node( FB_EDGE_CALL_INOUTSAME, wn, freq );
00364 if ( FB_NODEX_VALID( Curr() ) )
00365 Add_edge( Curr(), nx_next );
00366 Set_curr( nx_next );
00367
00368 } else {
00369
00370 FB_FREQ freq_entry = Cur_PU_Feedback->Query( wn, FB_EDGE_CALL_INCOMING );
00371 FB_NODEX nx_next = New_node( FB_EDGE_CALL_INCOMING, wn, freq_entry );
00372 if ( FB_NODEX_VALID( Curr() ) )
00373 Add_edge( Curr(), nx_next );
00374 Set_curr( nx_next );
00375
00376
00377 for ( INT t = 0; t < WN_kid_count(wn); ++t )
00378 Walk_WN_expression( WN_kid( wn, t ) );
00379
00380 FB_FREQ freq_exit = Cur_PU_Feedback->Query( wn, FB_EDGE_CALL_OUTGOING );
00381 nx_next = New_node( FB_EDGE_CALL_OUTGOING, wn,
00382 FB_FREQ_UNKNOWN, freq_exit );
00383 Add_edge( Curr(), nx_next );
00384 Set_curr( nx_next );
00385 }
00386 break;
00387
00388 default:
00389 {
00390
00391 for ( INT t = 0; t < WN_kid_count(wn); ++t )
00392 Walk_WN_expression( WN_kid( wn, t ) );
00393 }
00394 break;
00395 }
00396 }
00397
00398 void
00399 FB_CFG::Walk_WN_test_expression( WN *wn, FB_NODEX nx_true, FB_NODEX nx_false )
00400 {
00401 OPERATOR opr = WN_operator( wn );
00402
00403 switch ( opr ) {
00404
00405 case OPR_CAND:
00406 case OPR_CIOR:
00407 {
00408 FB_NODEX nx_branch, nx_default;
00409 if ( opr == OPR_CAND ) {
00410 nx_branch = nx_false;
00411 nx_default = nx_true;
00412 } else {
00413 nx_branch = nx_true;
00414 nx_default = nx_false;
00415 }
00416
00417 FB_FREQ freq_left, freq_right, freq_neither;
00418 freq_left = Cur_PU_Feedback->Query( wn, FB_EDGE_CIRCUIT_LEFT );
00419 freq_right = Cur_PU_Feedback->Query( wn, FB_EDGE_CIRCUIT_RIGHT );
00420 freq_neither = Cur_PU_Feedback->Query( wn, FB_EDGE_CIRCUIT_NEITHER );
00421
00422
00423 FB_NODEX nx_left = New_node( FB_EDGE_CIRCUIT_LEFT, wn, freq_left );
00424 FB_NODEX nx_not_left = New_node();
00425 if ( opr == OPR_CAND ) {
00426 Walk_WN_test_expression( WN_kid0(wn), nx_not_left, nx_left );
00427 } else {
00428 Walk_WN_test_expression( WN_kid0(wn), nx_left, nx_not_left );
00429 }
00430
00431
00432 Set_curr( nx_not_left );
00433 FB_NODEX nx_right = New_node( FB_EDGE_CIRCUIT_RIGHT, wn, freq_right );
00434 FB_NODEX nx_neither = New_node( FB_EDGE_CIRCUIT_NEITHER, wn,
00435 freq_neither );
00436 if (opr == OPR_CAND) {
00437 Walk_WN_test_expression( WN_kid1(wn), nx_neither, nx_right );
00438 } else {
00439 Walk_WN_test_expression( WN_kid1(wn), nx_right, nx_neither );
00440 }
00441
00442
00443 Add_edge( nx_left, nx_branch );
00444 Add_edge( nx_right, nx_branch );
00445 Add_edge( nx_neither, nx_default );
00446 }
00447 break;
00448
00449 case OPR_CSELECT:
00450 {
00451 FB_FREQ freq_then, freq_else;
00452 freq_then = Cur_PU_Feedback->Query( wn, FB_EDGE_BRANCH_TAKEN );
00453 freq_else = Cur_PU_Feedback->Query( wn, FB_EDGE_BRANCH_NOT_TAKEN );
00454
00455
00456 FB_NODEX nx_then = New_node( FB_EDGE_BRANCH_TAKEN, wn, freq_then );
00457 FB_NODEX nx_else = New_node( FB_EDGE_BRANCH_NOT_TAKEN, wn, freq_else );
00458 Walk_WN_test_expression( WN_kid0(wn), nx_then, nx_else );
00459
00460
00461 Set_curr( nx_then );
00462 FB_NODEX nx_then_true = New_node();
00463 FB_NODEX nx_then_false = New_node();
00464 Walk_WN_test_expression( WN_kid1(wn), nx_then_true, nx_then_false );
00465
00466
00467 Set_curr( nx_else );
00468 FB_NODEX nx_else_true = New_node();
00469 FB_NODEX nx_else_false = New_node();
00470 Walk_WN_test_expression( WN_kid2(wn), nx_else_true, nx_else_false );
00471
00472
00473 Add_edge( nx_then_true, nx_true );
00474 Add_edge( nx_else_true, nx_true );
00475 Add_edge( nx_then_false, nx_false );
00476 Add_edge( nx_else_false, nx_false );
00477 }
00478 break;
00479
00480 case OPR_COMMA:
00481 Walk_WN_statement( WN_kid0(wn) );
00482 Walk_WN_test_expression( WN_kid1(wn), nx_true, nx_false );
00483 break;
00484
00485 case OPR_RCOMMA:
00486 Walk_WN_test_expression( WN_kid0(wn), nx_true, nx_false );
00487 Walk_WN_statement( WN_kid1(wn) );
00488 break;
00489
00490 default:
00491 Walk_WN_expression(wn);
00492 Add_edge(Get_curr(), nx_true);
00493 Add_edge(Curr(), nx_false);
00494
00495 Adjust_edge(nx_true);
00496 Adjust_edge(nx_false);
00497 break;
00498 }
00499 }
00500
00501
00502
00503
00504
00505 void
00506 FB_CFG::Walk_WN_statement( WN *wn )
00507 {
00508 OPERATOR opr = WN_operator( wn );
00509 WN *wn2;
00510 static bool _in_preamble = FALSE;
00511
00512
00513
00514 if ( _in_preamble )
00515 if ( opr == OPR_PRAGMA && WN_pragma( wn ) == WN_PRAGMA_PREAMBLE_END )
00516 _in_preamble = FALSE;
00517 else return;
00518
00519 switch ( opr ) {
00520
00521 case OPR_FUNC_ENTRY:
00522 {
00523
00524 FB_FREQ freq_default =
00525 Cur_PU_Feedback->Query( wn, FB_EDGE_ENTRY_OUTGOING );
00526 FB_NODEX nx_next = New_node( FB_EDGE_ENTRY_OUTGOING, wn,
00527 FB_FREQ_ZERO, freq_default );
00528 Set_curr( nx_next );
00529
00530 WN *body = WN_func_body(wn);
00531 WN *preamble_end = WN_first(body);
00532
00533
00534 while ( preamble_end
00535 && ! ( WN_operator(preamble_end) == OPR_PRAGMA &&
00536 WN_pragma(preamble_end) == WN_PRAGMA_PREAMBLE_END) ) {
00537 preamble_end = WN_next(preamble_end);
00538 }
00539 Is_True( preamble_end != NULL,
00540 ( "FB_CFG::Walk_WN_statement found no PREAMBLE_END PRAGMA" ) );
00541
00542
00543 for ( wn2 = preamble_end; wn2; wn2 = WN_next(wn2) ) {
00544 Walk_WN_statement( wn2 );
00545 }
00546 }
00547 break;
00548
00549 case OPR_ALTENTRY:
00550 {
00551
00552 FB_FREQ freq_default =
00553 Cur_PU_Feedback->Query( wn, FB_EDGE_ENTRY_OUTGOING );
00554 FB_NODEX nx_next = New_node( FB_EDGE_ENTRY_OUTGOING, wn,
00555 FB_FREQ_ZERO, freq_default );
00556 Set_curr( nx_next );
00557
00558
00559 _in_preamble = TRUE;
00560 }
00561 break;
00562
00563 case OPR_PRAGMA:
00564 if ( WN_pragma(wn) == WN_PRAGMA_PREAMBLE_END ) {
00565
00566
00567 FB_FREQ freq_default =
00568 Cur_PU_Feedback->Query( wn, FB_EDGE_OUTGOING );
00569 FB_NODEX nx_next = New_node( FB_EDGE_INCOMING, wn, freq_default );
00570 if ( FB_NODEX_VALID( Curr() ) )
00571 Add_edge( Curr(), nx_next );
00572 Set_curr( nx_next );
00573 }
00574 break;
00575
00576 case OPR_XPRAGMA:
00577
00578 break;
00579
00580 case OPR_BLOCK:
00581
00582 for (wn2 = WN_first(wn); wn2; wn2 = WN_next(wn2)) {
00583 Walk_WN_statement( wn2 );
00584 }
00585 Is_True( ! _in_preamble,
00586 ("FB_CFG::Walk_WN_statement: missing PREAMBLE_END PRAGMA") );
00587 break;
00588
00589
00590
00591 case OPR_DO_LOOP:
00592 {
00593 FB_FREQ freq_exit, freq_iterate;
00594 freq_exit = Cur_PU_Feedback->Query( wn, FB_EDGE_LOOP_EXIT );
00595 freq_iterate = Cur_PU_Feedback->Query( wn, FB_EDGE_LOOP_ITERATE );
00596
00597
00598 Walk_WN_statement( WN_start(wn) );
00599
00600
00601 FB_NODEX nx_test = New_node();
00602 FB_NODEX nx_body = New_node( FB_EDGE_LOOP_ITERATE, wn, freq_iterate );
00603 FB_NODEX nx_next = New_node( FB_EDGE_LOOP_EXIT, wn, freq_exit );
00604 if ( FB_NODEX_VALID( Curr() ) )
00605 Add_edge( Curr(), nx_test );
00606 Set_curr( nx_test );
00607 Walk_WN_test_expression( WN_end(wn), nx_body, nx_next );
00608
00609
00610 Set_curr( nx_body );
00611 Walk_WN_statement( WN_do_body(wn) );
00612 Walk_WN_statement( WN_step(wn) );
00613 if ( FB_NODEX_VALID( Curr() ) )
00614 Add_edge( Curr(), nx_test );
00615 Set_curr( nx_next );
00616 }
00617 break;
00618
00619 case OPR_DO_WHILE:
00620 {
00621 FB_FREQ freq_zero, freq_positive, freq_out, freq_back;
00622 freq_zero = Cur_PU_Feedback->Query( wn, FB_EDGE_LOOP_ZERO );
00623 freq_positive = Cur_PU_Feedback->Query( wn, FB_EDGE_LOOP_POSITIVE );
00624 freq_out = Cur_PU_Feedback->Query( wn, FB_EDGE_LOOP_OUT );
00625 freq_back = Cur_PU_Feedback->Query( wn, FB_EDGE_LOOP_BACK );
00626 Is_True( freq_zero.Zero() || ! freq_zero.Known(),
00627 ("FB_CFG::Walk_WN_statement: DO_WHILE freq_zero == %f nonzero",
00628 freq_zero.Value()) );
00629
00630
00631 FB_NODEX nx_pos = New_node( FB_EDGE_LOOP_POSITIVE, wn, freq_positive );
00632 FB_NODEX nx_body = New_node();
00633 if ( FB_NODEX_VALID( Curr() ) )
00634 Add_edge( Curr(), nx_pos );
00635 Add_edge( nx_pos, nx_body );
00636 Set_curr( nx_body );
00637 Walk_WN_statement( WN_while_body(wn) );
00638
00639
00640 FB_NODEX nx_back = New_node( FB_EDGE_LOOP_BACK, wn, freq_back );
00641 FB_NODEX nx_next = New_node( FB_EDGE_LOOP_OUT , wn, freq_out );
00642 Walk_WN_test_expression( WN_while_test(wn), nx_back, nx_next );
00643 Add_edge( nx_back, nx_body );
00644 Set_curr( nx_next );
00645 }
00646 break;
00647
00648 case OPR_WHILE_DO:
00649 {
00650 FB_FREQ freq_exit, freq_iterate;
00651 freq_exit = Cur_PU_Feedback->Query( wn, FB_EDGE_LOOP_EXIT );
00652 freq_iterate = Cur_PU_Feedback->Query( wn, FB_EDGE_LOOP_ITERATE );
00653
00654
00655 FB_NODEX nx_test = New_node();
00656 FB_NODEX nx_body = New_node( FB_EDGE_LOOP_ITERATE, wn, freq_iterate );
00657 FB_NODEX nx_next = New_node( FB_EDGE_LOOP_EXIT, wn, freq_exit );
00658 if ( FB_NODEX_VALID( Curr() ) )
00659 Add_edge( Curr(), nx_test );
00660 Set_curr( nx_test );
00661 Walk_WN_test_expression( WN_while_test(wn), nx_body, nx_next );
00662
00663
00664 Set_curr( nx_body );
00665 Walk_WN_statement( WN_while_body(wn) );
00666 if ( FB_NODEX_VALID( Curr() ) )
00667 Add_edge( Curr(), nx_test );
00668 Set_curr( nx_next );
00669 }
00670 break;
00671
00672 case OPR_IF:
00673 {
00674 FB_FREQ freq_then, freq_else;
00675 freq_then = Cur_PU_Feedback->Query( wn, FB_EDGE_BRANCH_TAKEN );
00676 freq_else = Cur_PU_Feedback->Query( wn, FB_EDGE_BRANCH_NOT_TAKEN );
00677
00678
00679 FB_NODEX nx_then = New_node( FB_EDGE_BRANCH_TAKEN, wn, freq_then );
00680 FB_NODEX nx_else = New_node( FB_EDGE_BRANCH_NOT_TAKEN, wn, freq_else );
00681 Walk_WN_test_expression( WN_if_test(wn), nx_then, nx_else );
00682
00683
00684 Set_curr( nx_then );
00685 Walk_WN_statement( WN_then(wn) );
00686 nx_then = Curr();
00687
00688
00689 if (! WN_else_is_empty(wn) ) {
00690 Set_curr( nx_else );
00691 Walk_WN_statement( WN_else(wn) );
00692 nx_else = Curr();
00693 }
00694
00695
00696 FB_NODEX nx_join = New_node();
00697 if ( FB_NODEX_VALID( nx_then ) )
00698 Add_edge( nx_then, nx_join );
00699 if ( FB_NODEX_VALID( nx_else ) )
00700 Add_edge( nx_else, nx_join );
00701 Set_curr( nx_join );
00702 }
00703 break;
00704
00705 case OPR_GOTO:
00706 {
00707 FB_FREQ freq_branch =
00708 Cur_PU_Feedback->Query( wn, FB_EDGE_OUTGOING );
00709 FB_NODEX nx_next = New_node( FB_EDGE_OUTGOING, wn, freq_branch );
00710 if ( FB_NODEX_VALID( Curr() ) )
00711 Add_edge( Curr(), nx_next );
00712 Add_delayed_edge( nx_next, wn );
00713 Set_curr( FB_NODEX_UNINIT );
00714 }
00715 break;
00716
00717 case OPR_SWITCH:
00718 case OPR_COMPGOTO:
00719 case OPR_XGOTO:
00720
00721
00722
00723 {
00724 INT32 n_targ = WN_num_entries(wn);
00725 WN *targ_blk = WN_kid1(wn);
00726 INT32 count = 0;
00727 OPERATOR br_opr = (opr == OPR_SWITCH ? OPR_CASEGOTO : OPR_GOTO);
00728 FB_NODEX nx_target;
00729 FB_FREQ freq_branch;
00730
00731 #if defined(TARG_SL) && defined(TARG_SL2)
00732 if(WN_is_compgoto_for_minor ( wn ) || WN_is_compgoto_para ( wn )) {
00733 FB_NODEX head = New_node ( FB_EDGE_SWITCH_DEFAULT, wn, FB_FREQ_UNINIT, FB_FREQ_UNINIT);
00734 Add_edge(Curr(), head);
00735 Set_curr ( head );
00736 }
00737 #endif
00738
00739
00740 Walk_WN_expression(WN_kid0(wn));
00741
00742
00743 for (wn2 = WN_first(targ_blk); wn2; wn2 = WN_next(wn2)) {
00744 Is_True( WN_operator(wn2) == br_opr,
00745 ( "XGOTO/COMPGOTO/SWITCH: expected %s, found %s",
00746 OPERATOR_name(br_opr), OPERATOR_name( WN_operator(wn2)) ) );
00747 freq_branch = Cur_PU_Feedback->Query( wn, FB_EDGE_SWITCH( count ) );
00748
00749 nx_target = New_node( FB_EDGE_SWITCH( count ), wn, freq_branch );
00750 if(FB_NODEX_VALID(Curr()))
00751 Add_edge( Curr(), nx_target );
00752 Add_delayed_edge( nx_target, wn2 );
00753 count += 1;
00754 }
00755
00756 Is_True( count == n_targ, ( "%s: goto_count=%d n_targ=%d",
00757 "XGOTO/COMPGOTO", count, n_targ ) );
00758
00759
00760 if ( ( opr == OPR_COMPGOTO || opr == OPR_SWITCH )
00761 && WN_kid_count(wn) == 3 ) {
00762 wn2 = WN_kid2(wn);
00763 Is_True( WN_operator(wn2) == OPR_GOTO,
00764 ( "COMPGOTO/SWITCH blk, expected GOTO" ) );
00765
00766 freq_branch = Cur_PU_Feedback->Query( wn, FB_EDGE_SWITCH_DEFAULT );
00767 nx_target = New_node( FB_EDGE_SWITCH_DEFAULT, wn, freq_branch );
00768 if(FB_NODEX_VALID(Curr()))
00769 Add_edge( Curr(), nx_target );
00770 Add_delayed_edge( nx_target, wn2 );
00771 }
00772 Set_curr( FB_NODEX_UNINIT );
00773 }
00774 break;
00775
00776
00777
00778
00779 case OPR_TRUEBR:
00780 case OPR_FALSEBR:
00781 {
00782 FB_FREQ freq_branch, freq_default;
00783 freq_branch = Cur_PU_Feedback->Query( wn, FB_EDGE_BRANCH_TAKEN );
00784 freq_default = Cur_PU_Feedback->Query( wn, FB_EDGE_BRANCH_NOT_TAKEN );
00785
00786
00787 FB_NODEX nx_branch = New_node( FB_EDGE_BRANCH_TAKEN, wn, freq_branch );
00788 FB_NODEX nx_next = New_node( FB_EDGE_BRANCH_NOT_TAKEN, wn,
00789 freq_default );
00790 if (opr == OPR_TRUEBR) {
00791 Walk_WN_test_expression( WN_kid0(wn), nx_branch, nx_next );
00792 } else {
00793 Walk_WN_test_expression( WN_kid0(wn), nx_next, nx_branch );
00794 }
00795
00796 Add_delayed_edge( nx_branch, wn );
00797 Set_curr( nx_next );
00798 }
00799 break;
00800
00801 case OPR_RETURN:
00802 case OPR_RETURN_VAL:
00803 #ifdef KEY
00804 case OPR_GOTO_OUTER_BLOCK:
00805 #endif
00806 {
00807 FB_FREQ freq_default =
00808 Cur_PU_Feedback->Query( wn, FB_EDGE_INCOMING );
00809 FB_NODEX nx_next = New_node( FB_EDGE_INCOMING, wn,
00810 freq_default, FB_FREQ_ZERO );
00811 if ( FB_NODEX_VALID( Curr() ) )
00812 Add_edge( Curr(), nx_next );
00813 Set_curr( FB_NODEX_UNINIT );
00814 }
00815 break;
00816
00817 case OPR_LABEL:
00818 {
00819 FB_FREQ freq = Cur_PU_Feedback->Query( wn, FB_EDGE_INCOMING );
00820 FB_NODEX nx_next = New_node( FB_EDGE_INCOMING, wn, freq );
00821 if ( FB_NODEX_VALID( Curr() ) )
00822 Add_edge( Curr(), nx_next );
00823 Set_curr( nx_next );
00824 Add_label( WN_label_number(wn), nx_next );
00825 }
00826 break;
00827
00828 case OPR_CALL:
00829 case OPR_ICALL:
00830 case OPR_VFCALL:
00831 case OPR_PICCALL:
00832 case OPR_INTRINSIC_CALL:
00833
00834 if ( Cur_PU_Feedback->Same_in_out( wn ) ) {
00835
00836
00837 for ( INT t = 0; t < WN_kid_count(wn); ++t )
00838 Walk_WN_expression( WN_kid( wn, t ) );
00839
00840 FB_FREQ freq = Cur_PU_Feedback->Query( wn, FB_EDGE_CALL_INOUTSAME );
00841
00842 FB_NODEX nx_next = New_node( FB_EDGE_CALL_INOUTSAME, wn, freq );
00843 if ( FB_NODEX_VALID( Curr() ) )
00844 Add_edge( Curr(), nx_next );
00845 Set_curr( nx_next );
00846
00847 } else {
00848
00849 FB_FREQ freq_entry = Cur_PU_Feedback->Query( wn, FB_EDGE_CALL_INCOMING );
00850 FB_NODEX nx_next = New_node( FB_EDGE_CALL_INCOMING, wn, freq_entry );
00851 if ( FB_NODEX_VALID( Curr() ) )
00852 Add_edge( Curr(), nx_next );
00853 Set_curr( nx_next );
00854
00855
00856 for ( INT t = 0; t < WN_kid_count(wn); ++t )
00857 Walk_WN_expression( WN_kid( wn, t ) );
00858
00859 FB_FREQ freq_exit = Cur_PU_Feedback->Query( wn, FB_EDGE_CALL_OUTGOING );
00860 nx_next = New_node( FB_EDGE_CALL_OUTGOING, wn,
00861 FB_FREQ_UNKNOWN, freq_exit );
00862 Add_edge( Curr(), nx_next );
00863 Set_curr( nx_next );
00864 }
00865 break;
00866
00867
00868
00869 case OPR_IO:
00870 {
00871
00872 FB_FREQ freq_escape = FB_FREQ_UNINIT;
00873 if ( Cur_PU_Feedback->Same_in_out( wn ) ) {
00874
00875 freq_escape = FB_FREQ_ZERO;
00876 if ( ! FB_NODEX_VALID( Curr() ) ) {
00877 FB_NODEX nx_next = New_node();
00878 Set_curr( nx_next );
00879 }
00880
00881 } else {
00882
00883 FB_FREQ freq_entry = Cur_PU_Feedback->Query( wn,
00884 FB_EDGE_CALL_INCOMING );
00885 FB_NODEX nx_next = New_node( FB_EDGE_CALL_INCOMING, wn, freq_entry );
00886 if ( FB_NODEX_VALID( Curr() ) )
00887 Add_edge( Curr(), nx_next );
00888 Set_curr( nx_next );
00889 }
00890
00891
00892 for ( INT32 iolist = 2; iolist < WN_kid_count( wn ); iolist++ ) {
00893
00894 WN *wn_tmp = WN_kid( wn, iolist );
00895 IOITEM ioitem_tmp = ( IOITEM ) WN_io_item( wn_tmp );
00896
00897 if ( ioitem_tmp == IOC_END ||
00898 ioitem_tmp == IOC_ERR ||
00899 ioitem_tmp == IOC_EOR ) {
00900
00901 FB_NODEX nx_escape = New_node( FB_EDGE_UNINIT, NULL, freq_escape );
00902 Add_edge( Curr(), nx_escape );
00903 Add_delayed_edge( nx_escape, WN_kid0( wn_tmp ) );
00904 }
00905 }
00906
00907
00908 if ( Cur_PU_Feedback->Same_in_out( wn ) ) {
00909
00910 FB_FREQ freq = Cur_PU_Feedback->Query( wn, FB_EDGE_CALL_INOUTSAME );
00911
00912 FB_NODEX nx_next = New_node( FB_EDGE_CALL_INOUTSAME, wn, freq );
00913 Add_edge( Curr(), nx_next );
00914 Set_curr( nx_next );
00915
00916 } else {
00917
00918 FB_FREQ freq_exit = Cur_PU_Feedback->Query( wn,
00919 FB_EDGE_CALL_OUTGOING );
00920 FB_NODEX nx_next = New_node( FB_EDGE_CALL_OUTGOING, wn, freq_exit );
00921 Add_edge( Curr(), nx_next );
00922 Set_curr( nx_next );
00923 }
00924 }
00925 break;
00926
00927 case OPR_EVAL:
00928 case OPR_STID:
00929 Walk_WN_expression( WN_kid0(wn) );
00930 break;
00931
00932 case OPR_ISTORE:
00933 {
00934 for ( INT t = 0; t < WN_kid_count(wn); ++t )
00935 Walk_WN_expression( WN_kid( wn, t ) );
00936 }
00937 break;
00938
00939 case OPR_MSTORE:
00940 {
00941
00942 for ( INT t = 0; t < WN_kid_count(wn); ++t )
00943 Walk_WN_expression( WN_kid( wn, t ) );
00944
00945
00946 FB_FREQ freq_default =
00947 Cur_PU_Feedback->Query( wn, FB_EDGE_OUTGOING );
00948 FB_NODEX nx_next = New_node( FB_EDGE_OUTGOING, wn, freq_default );
00949 if ( FB_NODEX_VALID( Curr() ) )
00950 Add_edge( Curr(), nx_next );
00951 Set_curr( nx_next );
00952 }
00953 break;
00954
00955 case OPR_COMMENT:
00956 break;
00957
00958 #ifdef KEY
00959 case OPR_PREFETCH:
00960 case OPR_PREFETCHX:
00961 break;
00962 case OPR_REGION:
00963 {
00964 #if defined (TARG_SL) && defined(TARG_SL2)
00965 FB_FREQ freq_entry = Cur_PU_Feedback->Query( wn, FB_EDGE_CALL_INCOMING );
00966 FB_NODEX nx_entry = New_node( FB_EDGE_CALL_INCOMING, wn, freq_entry );
00967 if ( FB_NODEX_VALID( Curr() ) )
00968 Add_edge( Curr(), nx_entry );
00969 Set_curr( nx_entry );
00970
00971 Walk_WN_statement( WN_region_body(wn) );
00972
00973 FB_FREQ freq_exit = Cur_PU_Feedback->Query( wn, FB_EDGE_CALL_OUTGOING );
00974 if(Curr() == nx_entry && freq_entry.Initialized() && freq_exit.Initialized()) {
00975
00976 FB_NODEX fn;
00977 if(Cur_PU_Feedback->Same_in_out(wn))
00978 fn = New_node ( FB_EDGE_CALL_OUTGOING, wn, freq_exit);
00979 else
00980 fn = New_node ( FB_EDGE_CALL_OUTGOING, wn, freq_entry, freq_exit);
00981 Add_edge(Curr(), fn);
00982 Set_curr ( fn );
00983 }
00984
00985 FB_NODEX nx_exit = New_node( FB_EDGE_CALL_OUTGOING, wn, freq_exit );
00986 Add_edge( Curr(), nx_exit );
00987 Set_curr( nx_exit );
00988 #else
00989 FB_NODEX nx_body = New_node();
00990 if ( FB_NODEX_VALID( Curr() ) )
00991 Add_edge( Curr(), nx_body );
00992 Set_curr( nx_body );
00993 Walk_WN_statement( WN_region_body(wn) );
00994 #endif
00995 }
00996 break;
00997 #endif
00998
00999
01000
01001
01002
01003
01004
01005
01006
01007 default:
01008 #ifdef Is_True_On
01009 DevWarn( "FB_CFG::Walk_WN_statement, unexpectd opr %s",
01010 OPERATOR_name(opr) );
01011 #endif
01012 break;
01013 }
01014 }
01015
01016
01017
01018 void
01019 FB_CFG::Patch_whirl_frequencies() const
01020 {
01021 FB_NODEX nx;
01022 FB_FREQ freq_old, freq_new;
01023
01024 if ( _trace )
01025 fprintf( TFile, "FB_CFG::Patch_whirl_frequencies:\n" );
01026
01027 for ( nx = _nodes.size() - 1; FB_NODEX_VALID(nx); --nx ) {
01028
01029 WN *wn = _nodes[nx].source;
01030 FB_EDGE_TYPE node_type = _nodes[nx].node_type;
01031 if ( node_type == FB_EDGE_UNINIT ) continue;
01032
01033 freq_old = Cur_PU_Feedback->Query( wn, node_type );
01034
01035 if ( node_type == FB_EDGE_OUTGOING ||
01036 node_type == FB_EDGE_ENTRY_OUTGOING ||
01037 node_type == FB_EDGE_CALL_OUTGOING )
01038 freq_new = _nodes[nx].freq_total_out;
01039 else
01040 freq_new = _nodes[nx].freq_total_in;
01041
01042 if ( freq_new.Better( freq_old ) )
01043 Cur_PU_Feedback->Annot( wn, node_type, freq_new );
01044 }
01045 }
01046
01047
01048
01049
01050
01051
01052
01053
01054 void
01055 FB_CFG::Freq_propagate_node_in( FB_NODEX nx )
01056 {
01057 FB_NODE& node = _nodes[nx];
01058 if ( _trace_prop ) {
01059 fprintf( TFile, "Before FB_CFG::Freq_propagate_node_in for:\n" );
01060 node.Print( TFile, nx );
01061 }
01062
01063 if ( node.one_edge_preds && node.unexact_in > 0 ) {
01064
01065 if ( node.freq_total_in.Exact() ) {
01066
01067
01068
01069 FB_NODEX nx_unexact = FB_NODEX_UNINIT;
01070 FB_FREQ freq_total = FB_FREQ_ZERO;
01071 for ( INT t = node.preds.size() - 1; t >= 0; --t ) {
01072 FB_NODEX nx_pred = node.preds[t];
01073 FB_FREQ freq = _nodes[nx_pred].freq_total_out;
01074 if ( freq.Exact() ) {
01075 freq_total += freq;
01076 } else {
01077 Is_True( nx_unexact == FB_NODEX_UNINIT || node.unexact_in > 1,
01078 ( "FB_CFG::Freq_propagate_node_in[nx%d]"
01079 " found multiple unexact pred freqs", nx ) );
01080 nx_unexact = nx_pred;
01081 }
01082 }
01083 Is_True( nx_unexact != FB_NODEX_UNINIT,
01084 ( "FB_CFG::Freq_propagate_node_in found no unexact freqs"));
01085
01086
01087 FB_FREQ freq_unexact = node.freq_total_in - freq_total;
01088 if ( freq_unexact.Error() ) return;
01089
01090 if ( node.unexact_in == 1 ) {
01091
01092
01093 FB_NODE& pred = _nodes[nx_unexact];
01094 pred.freq_total_out = freq_unexact;
01095 Is_True( pred.unexact_out == 1,
01096 ( "FB_CFG::Freq_propagate_node_in[nx%d] found"
01097 " pred[%d] unexact_out(%d) != 1",
01098 nx, nx_unexact, pred.unexact_out ) );
01099 pred.unexact_out = 0;
01100 pred.unknown_out = 0;
01101 node.unexact_in = 0;
01102 node.unknown_in = 0;
01103 Freq_propagate_node_out( nx_unexact );
01104
01105 } else if ( freq_unexact.Zero() ) {
01106
01107
01108 for ( INT t = node.preds.size() - 1; t >= 0; --t ) {
01109 FB_NODEX nx_pred = node.preds[t];
01110 FB_NODE& pred = _nodes[nx_pred];
01111 if ( ! pred.freq_total_out.Exact() ) {
01112 node.unexact_in -= 1;
01113 if ( ! pred.freq_total_out.Known() )
01114 node.unknown_in -= 1;
01115 pred.freq_total_out = FB_FREQ_ZERO;
01116 pred.unexact_out = 0;
01117 pred.unknown_out = 0;
01118 Freq_propagate_node_out( nx_pred );
01119 }
01120 }
01121 }
01122
01123 } else if ( node.unexact_in == 1 ) {
01124
01125
01126 FB_FREQ freq_total = FB_FREQ_ZERO;
01127 for ( INT t = node.preds.size() - 1; t >= 0; --t ) {
01128 FB_NODEX nx_pred = node.preds[t];
01129 FB_NODE& pred = _nodes[nx_pred];
01130 FB_FREQ freq = pred.freq_total_out;
01131 Is_True( freq.Exact(), ( "FB_CFG::Freq_propagate_node_in[nx%d]"
01132 " found an unexact pred[nx%d] freq",
01133 nx, nx_pred ) );
01134 freq_total += freq;
01135 Is_True( pred.unexact_out == 1,
01136 ( "FB_CFG::Freq_propagate_node_in[nx%d] found"
01137 " pred[nx%d] unexact_out(%d) != 1",
01138 nx, nx_pred, pred.unexact_out ) );
01139 pred.unexact_out = 0;
01140 pred.unknown_out = 0;
01141 }
01142 node.freq_total_in = freq_total;
01143 node.unexact_in = 0;
01144 node.unknown_in = 0;
01145 }
01146
01147 if ( node.unknown_in == 1 ) {
01148
01149 if ( node.freq_total_in.Known() ) {
01150
01151
01152
01153 FB_NODEX nx_unknown = FB_NODEX_UNINIT;
01154 FB_FREQ freq_total = FB_FREQ_ZERO;
01155 for ( INT t = node.preds.size() - 1; t >= 0; --t ) {
01156 FB_NODEX nx_pred = node.preds[t];
01157 FB_FREQ freq = _nodes[nx_pred].freq_total_out;
01158 if ( freq.Known() ) {
01159 freq_total += freq;
01160 } else {
01161 Is_True( nx_unknown == FB_NODEX_UNINIT,
01162 ( "FB_CFG::Freq_propagate_node_in[nx%d]"
01163 " found multiple unknown pred freqs", nx ) );
01164 nx_unknown = nx_pred;
01165 }
01166 }
01167 Is_True( nx_unknown != FB_NODEX_UNINIT,
01168 ( "FB_CFG::Freq_propagate_node_in[nx%d]"
01169 " found no unknown freqs", nx ) );
01170
01171
01172 FB_FREQ freq_unknown = node.freq_total_in - freq_total;
01173 if ( freq_unknown.Error() ) return;
01174
01175 FB_NODE& pred = _nodes[nx_unknown];
01176 pred.freq_total_out = freq_unknown;
01177 Is_True( pred.unknown_out == 1,
01178 ( "FB_CFG::Freq_propagate_node_in[nx%d] found"
01179 " pred[%d] unknown_out(%d) != 1",
01180 nx, nx_unknown, pred.unknown_out ) );
01181 pred.unknown_out = 0;
01182 node.unknown_in = 0;
01183 Freq_propagate_node_out( nx_unknown );
01184
01185 } else {
01186
01187
01188 FB_FREQ freq_total = FB_FREQ_ZERO;
01189 for ( INT t = node.preds.size() - 1; t >= 0; --t ) {
01190 FB_NODEX nx_pred = node.preds[t];
01191 FB_NODE& pred = _nodes[nx_pred];
01192 FB_FREQ freq = pred.freq_total_out;
01193 Is_True( freq.Known(),
01194 ( "FB_CFG::Freq_propagate_node_in[nx%d] found"
01195 " an unknown pred[nx%d] freq", nx, nx_pred ) );
01196 freq_total += freq;
01197 Is_True( pred.unknown_out == 1,
01198 ( "FB_CFG::Freq_propagate_node_in[nx%d] found"
01199 " pred[nx%d] unknown_out(%d) != 1",
01200 nx, nx_pred, pred.unknown_out ) );
01201 pred.unknown_out = 0;
01202 }
01203 node.freq_total_in = freq_total;
01204 node.unknown_in = 0;
01205 }
01206 }
01207 }
01208
01209
01210 if ( node.in_out_same || ( node.freq_total_in.Zero() &&
01211 node.freq_total_in.Exact() &&
01212 node.node_type != FB_EDGE_ENTRY_OUTGOING ) ) {
01213 bool copy_exact =
01214 node.freq_total_in.Exact() && ! node.freq_total_out.Exact();
01215 bool copy_known =
01216 node.freq_total_in.Known() && ! node.freq_total_out.Known();
01217
01218 if ( copy_exact || copy_known ) {
01219
01220 Is_True( copy_known || node.unexact_out > 0,
01221 ( "FB_CFG::Freq_propagate_node_in[nx%d]"
01222 " found unexact_out == 0", nx ) );
01223 Is_True( copy_exact || node.unknown_out > 0,
01224 ( "FB_CFG::Freq_propagate_node_in[nx%d]"
01225 " found unknown_out == 0", nx ) );
01226
01227 node.freq_total_out = node.freq_total_in;
01228
01229 if ( copy_exact ) {
01230 node.unexact_out -= 1;
01231 for ( INT t = node.succs.size() - 1; t >= 0; --t ) {
01232 FB_NODEX nx_succ = node.succs[t];
01233 Is_True( _nodes[nx_succ].unexact_in > 0,
01234 ( "FB_CFG::Freq_propagate_node_in[nx%d] found"
01235 " succ[nx%d].unexact_in == 0", nx, nx_succ ) );
01236 _nodes[nx_succ].unexact_in -= 1;
01237 }
01238 }
01239
01240 if ( copy_known ) {
01241 node.unknown_out -= 1;
01242 for ( INT t = node.succs.size() - 1; t >= 0; --t ) {
01243 FB_NODEX nx_succ = node.succs[t];
01244 Is_True( _nodes[nx_succ].unknown_in > 0,
01245 ( "FB_CFG::Freq_propagate_node_in[nx%d] found"
01246 " succ[nx%d].unknown_in == 0", nx, nx_succ ) );
01247 _nodes[nx_succ].unknown_in -= 1;
01248 }
01249 }
01250
01251 if ( node.one_edge_succs ) {
01252 Freq_propagate_node_out( nx );
01253 } else if ( node.succs.size() > 0 ) {
01254 Freq_propagate_node_in( node.succs[0] );
01255 }
01256 }
01257 }
01258
01259
01260
01261 }
01262
01263
01264
01265
01266
01267 void
01268 FB_CFG::Freq_propagate_node_out( FB_NODEX nx )
01269 {
01270 FB_NODE& node = _nodes[nx];
01271 if ( _trace_prop ) {
01272 fprintf( TFile, "Before FB_CFG::Freq_propagate_node_out for:\n" );
01273 node.Print( TFile, nx );
01274 }
01275
01276 if ( node.one_edge_succs && node.unexact_out > 0 ) {
01277
01278 if ( node.freq_total_out.Exact() ) {
01279
01280
01281
01282 FB_NODEX nx_unexact = FB_NODEX_UNINIT;
01283 FB_FREQ freq_total = FB_FREQ_ZERO;
01284 for ( INT t = node.succs.size() - 1; t >= 0; --t ) {
01285 FB_NODEX nx_succ = node.succs[t];
01286 FB_FREQ freq = _nodes[nx_succ].freq_total_in;
01287 if ( freq.Exact() ) {
01288 freq_total += freq;
01289 } else {
01290 Is_True( nx_unexact == FB_NODEX_UNINIT || node.unexact_out > 1,
01291 ( "FB_CFG::Freq_propagate_node_out[nx%d]"
01292 " found multiple unexact succ freqs", nx ) );
01293 nx_unexact = nx_succ;
01294 }
01295 }
01296 Is_True( nx_unexact != FB_NODEX_UNINIT,
01297 ( "FB_CFG::Freq_propagate_node_out found no unexact freqs"));
01298
01299
01300 FB_FREQ freq_unexact = node.freq_total_out - freq_total;
01301 if ( freq_unexact.Error() ) return;
01302
01303 if ( node.unexact_out == 1 ) {
01304
01305
01306 FB_NODE& succ = _nodes[nx_unexact];
01307 succ.freq_total_in = freq_unexact;
01308 Is_True( succ.unexact_in == 1,
01309 ( "FB_CFG::Freq_propagate_node_out[nx%d] found"
01310 " succ[%d] unexact_in(%d) != 1",
01311 nx, nx_unexact, succ.unexact_in ) );
01312 succ.unexact_in = 0;
01313 succ.unknown_in = 0;
01314 node.unexact_out = 0;
01315 node.unknown_out = 0;
01316 Freq_propagate_node_in( nx_unexact );
01317
01318 } else if ( freq_unexact.Zero() ) {
01319
01320
01321 for ( INT t = node.succs.size() - 1; t >= 0; --t ) {
01322 FB_NODEX nx_succ = node.succs[t];
01323 FB_NODE& succ = _nodes[nx_succ];
01324 if ( ! succ.freq_total_in.Exact() ) {
01325 node.unexact_out -= 1;
01326 if ( ! succ.freq_total_in.Known() )
01327 node.unknown_out -= 1;
01328 succ.freq_total_in = FB_FREQ_ZERO;
01329 succ.unexact_in = 0;
01330 succ.unknown_in = 0;
01331 Freq_propagate_node_in( nx_succ );
01332 }
01333 }
01334 }
01335
01336 } else if ( node.unexact_out == 1 ) {
01337
01338
01339 FB_FREQ freq_total = FB_FREQ_ZERO;
01340 for ( INT t = node.succs.size() - 1; t >= 0; --t ) {
01341 FB_NODEX nx_succ = node.succs[t];
01342 FB_NODE& succ = _nodes[nx_succ];
01343 FB_FREQ freq = succ.freq_total_in;
01344 Is_True( freq.Exact(), ( "FB_CFG::Freq_propagate_node_out[nx%d]"
01345 " found an unexact succ[nx%d] freq",
01346 nx, nx_succ ) );
01347 freq_total += freq;
01348 Is_True( succ.unexact_in == 1,
01349 ( "FB_CFG::Freq_propagate_node_out[nx%d] found"
01350 " succ[nx%d] unexact_in(%d) != 1",
01351 nx, nx_succ, succ.unexact_in ) );
01352 succ.unexact_in = 0;
01353 succ.unknown_in = 0;
01354 }
01355 node.freq_total_out = freq_total;
01356 node.unexact_out = 0;
01357 node.unknown_out = 0;
01358 }
01359
01360 if ( node.unknown_out == 1 ) {
01361
01362 if ( node.freq_total_out.Known() ) {
01363
01364
01365
01366 FB_NODEX nx_unknown = FB_NODEX_UNINIT;
01367 FB_FREQ freq_total = FB_FREQ_ZERO;
01368 for ( INT t = node.succs.size() - 1; t >= 0; --t ) {
01369 FB_NODEX nx_succ = node.succs[t];
01370 FB_FREQ freq = _nodes[nx_succ].freq_total_in;
01371 if ( freq.Known() ) {
01372 freq_total += freq;
01373 } else {
01374 Is_True( nx_unknown == FB_NODEX_UNINIT,
01375 ( "FB_CFG::Freq_propagate_node_out[nx%d] found"
01376 " multiple unknown succ freqs", nx ) );
01377 nx_unknown = nx_succ;
01378 }
01379 }
01380 Is_True( nx_unknown != FB_NODEX_UNINIT,
01381 ( "FB_CFG::Freq_propagate_node_out[nx%d]"
01382 " found no unknown freqs", nx ) );
01383
01384
01385 FB_FREQ freq_unknown = node.freq_total_out - freq_total;
01386 if ( freq_unknown.Error() ) return;
01387
01388 FB_NODE& succ = _nodes[nx_unknown];
01389 succ.freq_total_in = freq_unknown;
01390 Is_True( succ.unknown_in == 1,
01391 ( "FB_CFG::Freq_propagate_node_out[nx%d] found"
01392 " succ[%d] unknown_in(%d) != 1",
01393 nx, nx_unknown, succ.unknown_in ) );
01394 succ.unknown_in = 0;
01395 node.unknown_out = 0;
01396 Freq_propagate_node_in( nx_unknown );
01397
01398 } else {
01399
01400
01401 FB_FREQ freq_total = FB_FREQ_ZERO;
01402 for ( INT t = node.succs.size() - 1; t >= 0; --t ) {
01403 FB_NODEX nx_succ = node.succs[t];
01404 FB_NODE& succ = _nodes[nx_succ];
01405 FB_FREQ freq = succ.freq_total_in;
01406 Is_True( freq.Known(),
01407 ( "FB_CFG::Freq_propagate_node_out[nx%d] found"
01408 " an unknown succ[nx%d] freq", nx, nx_succ ) );
01409 freq_total += freq;
01410 Is_True( succ.unknown_in == 1,
01411 ( "FB_CFG::Freq_propagate_node_out[nx%d] found"
01412 " succ[nx%d] unknown_in(%d) != 1",
01413 nx, nx_succ, succ.unknown_in ) );
01414 succ.unknown_in = 0;
01415 }
01416 node.freq_total_out = freq_total;
01417 node.unknown_out = 0;
01418 }
01419 }
01420 }
01421
01422
01423 if ( node.in_out_same ) {
01424 bool copy_exact =
01425 node.freq_total_out.Exact() && ! node.freq_total_in.Exact();
01426 bool copy_known =
01427 node.freq_total_out.Known() && ! node.freq_total_in.Known();
01428
01429 if ( copy_exact || copy_known ) {
01430
01431 Is_True( copy_known || node.unexact_in > 0,
01432 ( "FB_CFG::Freq_propagate_node_out[nx%d]"
01433 " found unexact_in == 0", nx ) );
01434 Is_True( copy_exact || node.unknown_in > 0,
01435 ( "FB_CFG::Freq_propagate_node_out[nx%d]"
01436 " found unknown_in == 0", nx ) );
01437
01438 node.freq_total_in = node.freq_total_out;
01439
01440 if ( copy_exact ) {
01441 node.unexact_in -= 1;
01442 for ( INT t = node.preds.size() - 1; t >= 0; --t ) {
01443 FB_NODEX nx_pred = node.preds[t];
01444 Is_True( _nodes[nx_pred].unexact_out > 0,
01445 ( "FB_CFG::Freq_propagate_node_out[nx%d] found"
01446 " pred[nx%d].unexact_out == 0", nx, nx_pred ) );
01447 _nodes[nx_pred].unexact_out -= 1;
01448 }
01449 }
01450
01451 if ( copy_known ) {
01452 node.unknown_in -= 1;
01453 for ( INT t = node.preds.size() - 1; t >= 0; --t ) {
01454 FB_NODEX nx_pred = node.preds[t];
01455 Is_True( _nodes[nx_pred].unknown_out > 0,
01456 ( "FB_CFG::Freq_propagate_node_out[nx%d] found"
01457 " pred[nx%d].unknown_out == 0", nx, nx_pred ) );
01458 _nodes[nx_pred].unknown_out -= 1;
01459 }
01460 }
01461
01462 if ( node.one_edge_preds ) {
01463 Freq_propagate_node_in( nx );
01464 } else if ( node.preds.size() > 0 ) {
01465 Freq_propagate_node_out( node.preds[0] );
01466 }
01467 }
01468 }
01469
01470
01471
01472 }
01473
01474
01475 void
01476 FB_CFG::Freq_propagate()
01477 {
01478 FB_NODEX nx;
01479 if ( _trace )
01480 fprintf( TFile, "FB_CFG::Freq_propagate:\n" );
01481
01482
01483
01484
01485
01486 for ( nx = 0; nx < _nodes.size(); ++nx ) {
01487 Freq_propagate_node_in(nx);
01488 Freq_propagate_node_out(nx);
01489 }
01490 }
01491
01492
01493
01494
01495
01496
01497 void
01498 FB_CFG::Guess_unknowns( WN *wn_root, const char *caller )
01499 {
01500 if ( _trace )
01501 fprintf( TFile, "FB_CFG::Guess_unknowns:\n" );
01502
01503 vector<FB_NODEX> unfinished_nodes;
01504
01505
01506 for ( FB_NODEX nx = 0; nx < _nodes.size(); ++nx ) {
01507 const FB_NODE& node = _nodes[nx];
01508 if ( node.unknown_in > 0 || node.unknown_out > 0 )
01509 unfinished_nodes.push_back( nx );
01510 }
01511
01512 if ( unfinished_nodes.empty() ) {
01513 if ( _trace )
01514 fprintf( TFile, " FB_CFG::Guess_unknowns found no unknowns" );
01515 return;
01516 }
01517
01518 bool change;
01519
01520 do {
01521
01522 do {
01523
01524 change = false;
01525
01526
01527
01528 for ( INT t = unfinished_nodes.size() - 1; t >= 0; --t ) {
01529 FB_NODEX nx = unfinished_nodes[t];
01530 FB_NODE& node = _nodes[nx];
01531
01532 if ( node.one_edge_preds && node.freq_total_in.Known() ) {
01533
01534
01535 while ( node.unknown_in > 1 ) {
01536
01537
01538
01539 FB_NODEX nx_unknown = FB_NODEX_UNINIT;
01540 FB_FREQ freq_total = FB_FREQ_ZERO;
01541 for ( INT t1 = node.preds.size() - 1; t1 >= 0; --t1 ) {
01542 FB_NODEX nx_pred = node.preds[t1];
01543 FB_FREQ freq = _nodes[nx_pred].freq_total_out;
01544 if ( freq.Known() )
01545 freq_total += freq;
01546 else
01547 nx_unknown = nx_pred;
01548 }
01549 Is_True( nx_unknown != FB_NODEX_UNINIT,
01550 ( "FB_CFG::Guess_unknowns[nx%d]"
01551 " found no unknown incoming freqs", nx ) );
01552
01553
01554 FB_FREQ freq_guess = node.freq_total_in - freq_total;
01555 if ( freq_guess.Error() )
01556 freq_guess = FB_FREQ( 0.0, false );
01557 else
01558 freq_guess /= node.unknown_in;
01559
01560
01561 FB_NODE& pred = _nodes[nx_unknown];
01562 pred.freq_total_out = freq_guess;
01563 pred.unknown_out = 0;
01564 node.unknown_in -= 1;
01565 if ( freq_guess.Exact() ) {
01566 pred.unexact_out = 0;
01567 node.unexact_in -= 1;
01568 }
01569 Freq_propagate_node_out( nx_unknown );
01570 }
01571
01572
01573 Freq_propagate_node_in( nx );
01574 }
01575
01576 if ( node.unknown_in == 0 && node.unknown_out == 0 ) {
01577
01578
01579 unfinished_nodes[t] = unfinished_nodes.back();
01580 unfinished_nodes.pop_back();
01581 }
01582 }
01583
01584 } while ( change );
01585
01586
01587 for ( INT t = unfinished_nodes.size() - 1; t >= 0; --t ) {
01588 FB_NODEX nx = unfinished_nodes[t];
01589 FB_NODE& node = _nodes[nx];
01590
01591 if ( node.one_edge_succs && node.freq_total_out.Known() ) {
01592
01593
01594 while ( node.unknown_out > 1 ) {
01595
01596
01597
01598 FB_NODEX nx_unknown = FB_NODEX_UNINIT;
01599 FB_FREQ freq_total = FB_FREQ_ZERO;
01600 for ( INT t1 = node.succs.size() - 1; t1 >= 0; --t1 ) {
01601 FB_NODEX nx_succ = node.succs[t1];
01602 FB_FREQ freq = _nodes[nx_succ].freq_total_in;
01603 if ( freq.Known() )
01604 freq_total += freq;
01605 else
01606 nx_unknown = nx_succ;
01607 }
01608 Is_True( nx_unknown != FB_NODEX_UNINIT,
01609 ( "FB_CFG::Guess_unknowns[nx%d]"
01610 " found no unknown outgoing freqs", nx ) );
01611
01612
01613 FB_FREQ freq_guess = node.freq_total_out - freq_total;
01614 if ( freq_guess.Error() )
01615 freq_guess = FB_FREQ( 0.0, false );
01616 else
01617 freq_guess /= node.unknown_out;
01618
01619
01620 FB_NODE& succ = _nodes[nx_unknown];
01621 succ.freq_total_in = freq_guess;
01622 succ.unknown_in = 0;
01623 node.unknown_out -= 1;
01624 if ( freq_guess.Exact() ) {
01625 succ.unexact_in = 0;
01626 node.unexact_out -= 1;
01627 }
01628 Freq_propagate_node_in( nx_unknown );
01629 }
01630
01631
01632 Freq_propagate_node_out( nx );
01633 }
01634
01635 if ( node.unknown_in == 0 && node.unknown_out == 0 ) {
01636
01637
01638 unfinished_nodes[t] = unfinished_nodes.back();
01639 unfinished_nodes.pop_back();
01640 }
01641 }
01642
01643 } while ( change );
01644
01645 if ( ! unfinished_nodes.empty() ) {
01646 DevWarn( "FB_CFG::Guess_unknowns failed to guess all unknowns!" );
01647 }
01648
01649 if ( _trace || _trace_draw ) {
01650 static char title[80];
01651 sprintf( title, "FB_CFG for %s after Guess_unknowns", caller );
01652
01653 if ( _trace ) {
01654 fprintf( TFile, "------------ %s ------------\n", title );
01655 Print( TFile );
01656 }
01657
01658 if ( _trace_draw )
01659 dV_view_fb_cfg( *this, wn_root, title );
01660 }
01661 }
01662
01663
01664
01665
01666
01667
01668 FB_VERIFY_STATUS
01669 FB_CFG::Verify_frequencies() const
01670 {
01671 if ( _trace )
01672 fprintf( TFile, "FB_CFG::Verify_frequencies:\n" );
01673
01674 bool valid = true, balanced = true;
01675
01676 for ( FB_NODEX nx = 0; nx < _nodes.size(); ++nx ) {
01677 const FB_NODE& node = _nodes[nx];
01678
01679
01680 if ( ! node.freq_total_in.Known() ) {
01681 if ( ! node.freq_total_in.Initialized() )
01682 valid = false;
01683 else
01684 balanced = false;
01685 if ( _trace ) {
01686 fprintf( TFile, " Node[%d] has incoming frequency == ", nx );
01687 node.freq_total_in.Print( TFile );
01688 fprintf( TFile, "\n" );
01689 }
01690 }
01691 if ( ! node.freq_total_out.Known() ) {
01692 if ( ! node.freq_total_out.Initialized() )
01693 valid = false;
01694 else
01695 balanced = false;
01696 if ( _trace ) {
01697 fprintf( TFile, " Node[%d] has outgoing frequency == ", nx );
01698 node.freq_total_out.Print( TFile );
01699 fprintf( TFile, "\n" );
01700 }
01701 }
01702
01703
01704 if ( node.in_out_same &&
01705 node.freq_total_in != node.freq_total_out &&
01706 node.freq_total_in.Known() &&
01707 node.freq_total_out.Known() ) {
01708
01709 balanced = false;
01710 if ( _trace ) {
01711 fprintf( TFile, " Node[%d] is unbalanced: incoming == ", nx );
01712 node.freq_total_in.Print( TFile );
01713 fprintf( TFile, ", outgoing == " );
01714 node.freq_total_out.Print( TFile );
01715 fprintf( TFile, "\n" );
01716 }
01717 }
01718
01719
01720 {
01721 INT unknown_in = ( node.freq_total_in.Known() ? 0 : 1 );
01722 INT unexact_in = ( node.freq_total_in.Exact() ? 0 : 1 );
01723 FB_FREQ freq_total = FB_FREQ_ZERO;
01724
01725 for ( INT t = node.preds.size() - 1; t >= 0; --t ){
01726 FB_NODEX nx_pred = node.preds[t];
01727 const FB_NODE& pred = _nodes[nx_pred];
01728
01729
01730 Is_True( find( pred.succs.begin(), pred.succs.end(), nx )
01731 != pred.succs.end(),
01732 ( "FEEDBACK::Verify found disconnected edge nx%d <-- nx%d",
01733 nx_pred, nx ) );
01734 Is_True( node.one_edge_preds || pred.one_edge_succs,
01735 ( "FEEDBACK::Verify found node[%d] and pred[%d] with"
01736 " one_edge_* both false", nx, nx_pred ) );
01737 Is_True( ! node.one_edge_preds || pred.succs.size() == 1,
01738 ( "FEEDBACK::Verify found pred[%d] of node[%d] with %d succs",
01739 nx_pred, nx, pred.succs.size() ) );
01740
01741 FB_FREQ freq_pred = pred.freq_total_out;
01742 freq_total += freq_pred;
01743 if ( ! freq_pred.Known() ) unknown_in += 1;
01744 if ( ! freq_pred.Exact() ) unexact_in += 1;
01745 }
01746
01747
01748 Is_True( node.unknown_in == unknown_in,
01749 ( "FEEDBACK::Verify found unknown_in[%d] miscount (%d != %d)",
01750 nx, node.unknown_in, unknown_in ) );
01751 Is_True( node.unexact_in == unexact_in,
01752 ( "FEEDBACK::Verify found unexact_in[%d] miscount (%d != %d)",
01753 nx, node.unexact_in, unexact_in ) );
01754
01755 if ( node.one_edge_preds && node.freq_total_in != freq_total ) {
01756 balanced = false;
01757 if ( _trace ) {
01758 fprintf( TFile, " Node[%d] has incoming unbalance (", nx );
01759 node.freq_total_in.Print( TFile );
01760 fprintf( TFile, " != " );
01761 freq_total.Print( TFile );
01762 fprintf( TFile, "\n" );
01763 }
01764 }
01765 }
01766
01767
01768 {
01769 INT unknown_out = ( node.freq_total_out.Known() ? 0 : 1 );
01770 INT unexact_out = ( node.freq_total_out.Exact() ? 0 : 1 );
01771 FB_FREQ freq_total = FB_FREQ_ZERO;
01772
01773 for ( INT t = node.succs.size() - 1; t >= 0; --t ){
01774 FB_NODEX nx_succ = node.succs[t];
01775 const FB_NODE& succ = _nodes[nx_succ];
01776
01777
01778 Is_True( find( succ.preds.begin(), succ.preds.end(), nx )
01779 != succ.preds.end(),
01780 ( "FEEDBACK::Verify found disconnected edge nx%d --> nx%d",
01781 nx, nx_succ ) );
01782 Is_True( node.one_edge_succs || succ.one_edge_preds,
01783 ( "FEEDBACK::Verify found node[%d] and succ[%d] with"
01784 " one_edge_* both false", nx, nx_succ ) );
01785 Is_True( ! node.one_edge_succs || succ.preds.size() == 1,
01786 ( "FEEDBACK::Verify found succ[%d] of node[%d] with %d preds",
01787 nx_succ, nx, succ.preds.size() ) );
01788
01789 FB_FREQ freq_succ = succ.freq_total_in;
01790 freq_total += freq_succ;
01791 if ( ! freq_succ.Known() ) unknown_out += 1;
01792 if ( ! freq_succ.Exact() ) unexact_out += 1;
01793 }
01794
01795
01796 Is_True( node.unknown_out == unknown_out,
01797 ( "FEEDBACK::Verify found unknown_out[%d] miscount (%d != %d)",
01798 nx, node.unknown_out, unknown_out ) );
01799 Is_True( node.unexact_out == unexact_out,
01800 ( "FEEDBACK::Verify found unexact_out[%d] miscount (%d != %d)",
01801 nx, node.unexact_out, unexact_out ) );
01802
01803 if ( node.one_edge_succs && node.freq_total_out != freq_total ) {
01804 balanced = false;
01805 if ( _trace ) {
01806 fprintf( TFile, " Node[%d] has outgoing unbalance (", nx );
01807 node.freq_total_out.Print( TFile );
01808 fprintf( TFile, " != " );
01809 freq_total.Print( TFile );
01810 fprintf( TFile, "\n" );
01811 }
01812 }
01813 }
01814 }
01815
01816
01817 if ( _trace ) {
01818 if ( valid )
01819 fprintf( TFile, "FB_CFG valid!\n" );
01820 else
01821 fprintf( TFile, "FB_CFG invalid!\n" );
01822 if ( balanced )
01823 fprintf( TFile, "FB_CFG balanced!\n" );
01824 else
01825 fprintf( TFile, "FB_CFG unbalanced!\n" );
01826 }
01827
01828
01829 if ( ! valid )
01830 return FB_VERIFY_INVALID;
01831 else if ( ! balanced )
01832 return FB_VERIFY_UNBALANCED;
01833 else
01834 return FB_VERIFY_CONSISTENT;
01835 }
01836
01837
01838
01839
01840
01841
01842
01843 void
01844 FB_CFG::Construct_from_whirl( WN *wn_root, const char *caller )
01845 {
01846 static char title[80];
01847
01848 if ( _trace )
01849 fprintf( TFile, "FB_CFG::Construct_from_whirl:\n" );
01850
01851
01852
01853
01854
01855
01856
01857 Walk_WN_statement(wn_root);
01858
01859
01860 Complete_delayed_edges();
01861
01862 if ( _trace_before && ( _trace || _trace_draw ) )
01863 sprintf( title, "FB_CFG for %s before propagation", caller );
01864
01865 if ( _trace_before && _trace ) {
01866 fprintf( TFile, "------------ %s ------------\n", title );
01867 Print( TFile );
01868 }
01869
01870 if ( _trace_draw && _trace_before )
01871 dV_view_fb_cfg( *this, wn_root, title );
01872
01873
01874 Freq_propagate();
01875
01876 if ( _trace || _trace_draw )
01877 sprintf( title, "FB_CFG for %s after propagation", caller );
01878
01879 if ( _trace ) {
01880 fprintf( TFile, "------------ %s ------------\n", title );
01881 Print( TFile );
01882 }
01883
01884 if ( _trace_draw )
01885 dV_view_fb_cfg( *this, wn_root, title );
01886 }
01887
01888
01889
01890
01891
01892 static DaVinci *DV = NULL;
01893 static MEM_POOL DV_fb_mempool;
01894
01895 void
01896 FB_CFG::Print_node( FILE *fp, FB_NODEX nx ) const
01897 {
01898 _nodes[nx].Print( fp, nx );
01899
01900
01901
01902
01903
01904
01905
01906
01907
01908
01909
01910
01911 }
01912
01913 void
01914 FB_CFG::Print_edge( FILE *fp, FB_NODEX src_nx, FB_NODEX dst_nx ) const
01915 {
01916 fprintf( fp, "Edge from %d to %d\n", src_nx, dst_nx );
01917 }
01918
01919 void
01920 FB_CFG::Print( FILE *fp ) const
01921 {
01922 for ( FB_NODEX nx = 0; nx < _nodes.size(); ++nx ) {
01923 _nodes[nx].Print( fp, nx );
01924 }
01925 }
01926
01927 class FB_Callback : public DaVinci_Callback {
01928 private:
01929 const FB_CFG& _cfg;
01930 public:
01931 FB_Callback( const FB_CFG& cfg ) : _cfg( cfg ) {}
01932
01933 virtual void Node_Select( const INT n_ids, const NODE_ID id_array[] );
01934 virtual void Edge_Select( const EDGE_ID& edge_id );
01935 };
01936
01937 void
01938 FB_Callback::Node_Select( const INT n_ids, const NODE_ID id_array[] )
01939 {
01940 for (INT i = 0; i < n_ids; ++i) {
01941 FB_NODEX nx = FB_NODEX(INTPS(id_array[i]));
01942 _cfg.Print_node( stderr, nx );
01943 }
01944 }
01945
01946 void
01947 FB_Callback::Edge_Select( const EDGE_ID& edge_id )
01948 {
01949 FB_NODEX src_nx = FB_NODEX(INTPS(edge_id.src));
01950 FB_NODEX dst_nx = FB_NODEX(INTPS(edge_id.dst));
01951 _cfg.Print_edge( stderr, src_nx, dst_nx );
01952 }
01953
01954 char *
01955 FB_CFG::Node_label( FB_NODEX nx ) const
01956 {
01957 static char label[50];
01958 char *cp = label;
01959
01960
01961 cp += sprintf( cp, "%d: ", nx );
01962 cp += FB_EDGE_TYPE_sprintf( cp, _nodes[nx].node_type );
01963
01964
01965 cp += sprintf( cp, "\\nin = " );
01966 cp += _nodes[nx].freq_total_in.Sprintf( cp );
01967 cp += sprintf( cp, "\\nout = " );
01968 cp += _nodes[nx].freq_total_out.Sprintf( cp );
01969
01970 return label;
01971 }
01972
01973 static BOOL
01974 Node_Unbalanced (const FB_NODE& node,
01975 const vector<FB_NODE, mempool_allocator<FB_NODE> >& _nodes)
01976 {
01977 typedef vector<FB_NODEX>::const_iterator NODEX_ITER;
01978
01979
01980 if ( node.one_edge_preds && node.unknown_in == 0 ) {
01981 FB_FREQ freq_total = FB_FREQ_ZERO;
01982 for (NODEX_ITER i (node.preds.begin ()); i != node.preds.end (); ++i) {
01983 freq_total += _nodes[*i].freq_total_out;
01984 }
01985 if ( freq_total.Known () && node.freq_total_in != freq_total )
01986 return TRUE;
01987 }
01988
01989
01990 if ( node.one_edge_succs && node.unknown_out == 0 ) {
01991 FB_FREQ freq_total = FB_FREQ_ZERO;
01992 for (NODEX_ITER i (node.succs.begin ()); i != node.succs.end (); ++i)
01993 freq_total += _nodes[*i].freq_total_in;
01994 if ( freq_total.Known() && node.freq_total_out != freq_total )
01995 return TRUE;
01996 }
01997 return FALSE;
01998 }
01999
02000
02001 void
02002 FB_CFG::Draw() const
02003 {
02004 NODE_TYPE nt_unbalanced, nt_exact, nt_guess, nt_unknown, nt_change;
02005 EDGE_TYPE et_advancing, et_delayed;
02006 FB_NODEX nx, dst_nx;
02007 INT t;
02008
02009
02010 nt_unbalanced.Color ("light sky blue");
02011 nt_guess.Color( "pink" );
02012 nt_unknown.Color( "orange" );
02013 nt_change.Color( "light green" );
02014 et_delayed.Color( "blue" );
02015
02016 DV->Graph_Begin();
02017
02018 for ( nx = 0; nx < _nodes.size(); ++nx ) {
02019 const FB_NODE& node = _nodes[nx];
02020
02021 FB_FREQ freq = node.freq_total_in + node.freq_total_out;
02022 NODE_TYPE *nt = &nt_exact;
02023 if ( Node_Unbalanced ( node, _nodes ) ) nt = &nt_unbalanced;
02024 else if ( ! node.in_out_same ) nt = &nt_change;
02025 else if ( freq.Guess() ) nt = &nt_guess;
02026 else if ( ! freq.Known() ) nt = &nt_unknown;
02027
02028
02029 DV->Node_Begin( NODE_ID(INTPTR(nx)), Node_label(nx), *nt );
02030 for ( t = 0; t < node.undelayed_succs; ++t ) {
02031 dst_nx = node.succs[t];
02032 DV->Out_Edge( EDGE_ID(NODE_ID(INTPTR(nx)), NODE_ID(INTPTR(dst_nx))),
02033 et_advancing, NODE_ID(INTPTR(dst_nx)) );
02034 }
02035 for ( ; t < node.succs.size(); ++t ) {
02036 dst_nx = node.succs[t];
02037 DV->Out_Edge( EDGE_ID(NODE_ID(INTPTR(nx)), NODE_ID(INTPTR(dst_nx))),
02038 et_delayed, NODE_ID(INTPTR(dst_nx)) );
02039 }
02040 DV->Node_End();
02041
02042 }
02043 DV->Graph_End();
02044 }
02045
02046 void dV_view_fb_cfg( const FB_CFG& cfg, WN *root_wn, const char *caller )
02047 {
02048 const char *trace_fname = getenv( "DV_TRACE_FILE" );
02049 FILE *trace_fp = NULL;
02050 const char *func_name = "<unknown func>";
02051 char title[100];
02052
02053 if ( ! DaVinci::enabled( true ) ) return;
02054
02055 if ( root_wn && WN_operator( root_wn ) == OPR_FUNC_ENTRY ) {
02056 func_name = ST_name( WN_entry_name( root_wn ) );
02057 }
02058 sprintf( title, "fb_whirl FB-CFG display: %s ", func_name );
02059
02060
02061
02062
02063
02064 FmtAssert( DV == NULL, ( "dV_view_fb_cfg: DV is null" ) );
02065 MEM_POOL_Initialize( &DV_fb_mempool, "DV_fb_mempool", FALSE );
02066 MEM_POOL_Push( &DV_fb_mempool );
02067
02068 DV = CXX_NEW( DaVinci( &DV_fb_mempool, trace_fp ), &DV_fb_mempool );
02069
02070 DV->Title( title );
02071 if ( caller ) DV->Show_Status( caller );
02072 cfg.Draw();
02073
02074 FB_Callback callback( cfg );
02075 DV->Event_Loop( &callback );
02076
02077 CXX_DELETE( DV, &DV_fb_mempool );
02078 DV = NULL;
02079
02080 MEM_POOL_Pop( &DV_fb_mempool );
02081 MEM_POOL_Delete( &DV_fb_mempool );
02082
02083 if ( trace_fp ) (void)fclose( trace_fp );
02084 }
02085
02086
02087
02088
02089
02090
02091
02092
02093
02094
02095
02096
02097
02098
02099
02100
02101
02102
02103
02104
02105
02106
02107
02108
02109
02110
02111
02112
02113
02114
02115
02116
02117
02118
02119
02120
02121
02122
02123
02124
02125
02126
02127
02128
02129
02130
02131
02132
02133
02134
02135
02136
02137
02138
02139
02140
02141
02142
02143
02144
02145
02146
02147
02148
02149
02150
02151
02152
02153
02154
02155
02156
02157