00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068 #ifdef USE_PCH
00069 #include "be_com_pch.h"
00070 #endif
00071 #pragma hdrstop
00072 #define USE_STANDARD_TYPES
00073
00074 #define __STDC_LIMIT_MACROS
00075 #include <stdint.h>
00076 #include <cmplrs/fb.h>
00077 #include <stdlib.h>
00078 #include "wn_util.h"
00079 #include "wn_map.h"
00080 #include "errors.h"
00081 #include "ir_reader.h"
00082 #include "tracing.h"
00083 #include "wn_tree_util.h"
00084
00085 #include "fb_whirl.h"
00086 #include "fb_cfg.h"
00087
00088 #include "com_whirlview.h"
00089
00090 #include "cxx_graph.h"
00091
00092 #include "DaVinci.h"
00093 #include "wb_util.h"
00094
00095
00096
00097
00098 void
00099 FB_old_Annotate_whirl(WN *wn)
00100 {
00101 return;
00102 }
00103
00104
00105 ADDRESS_NAME_MAP PU_Addr_Name_Map;
00106 ADDRESS_PUSIZE_MAP PU_Addr_Pusize_Map;
00107
00108 #ifdef KEY
00109 #define IS_VALID_DIV_VALUE(wn) \
00110 ( !WN_operator_is( WN_kid1(wn), OPR_INTCONST ) && \
00111 MTYPE_is_integral( OPCODE_rtype(WN_opcode(wn) ) ) )
00112
00113 #define IS_VALID_MPY_VALUE(wn) \
00114 ( !WN_operator_is( WN_kid1(wn), OPR_CONST ) && \
00115 !MTYPE_is_integral( OPCODE_rtype(WN_opcode(wn) ) ) )
00116 #endif
00117
00118
00119
00120 void
00121 FEEDBACK::FB_hoist_case( WN *wn_switch, vector<FB_FREQ>::size_type wcase)
00122 {
00123 FB_Info_Switch info_switch = Query_switch( wn_switch );
00124 FB_FREQ freq_taken = info_switch[wcase];
00125 info_switch[wcase] = FB_FREQ_ZERO;
00126 Annot_switch( wn_switch, info_switch );
00127 }
00128
00129
00130 FEEDBACK *Cur_PU_Feedback = NULL;
00131
00132 FEEDBACK::FEEDBACK( WN *wn, MEM_POOL *m,
00133 INT32 invoke_size,
00134 INT32 branch_size,
00135 INT32 loop_size,
00136 INT32 circuit_size,
00137 INT32 call_size,
00138 INT32 icall_size,
00139 INT32 switch_size,
00140 #ifdef KEY
00141 INT32 value_size,
00142 INT32 value_fp_bin_size,
00143 UINT64 runtime_fun_address,
00144 #endif
00145 WN_MAP_TAB *maptab ) :
00146 _m( m ),
00147 _maptab( maptab ),
00148 _root_wn( wn ),
00149 _trace( Get_Trace( TP_FEEDBACK, TP_FEEDBACK_WN ) ),
00150 _trace_draw( Get_Trace( TP_FEEDBACK, TP_FEEDBACK_WN_DRAW ) ),
00151
00152 _invokes ( 1, FB_Info_Invoke(), m ),
00153 _branches( 1, FB_Info_Branch(), m ),
00154 _loops ( 1, FB_Info_Loop(), m ),
00155 _circuits( 1, FB_Info_Circuit(), m ),
00156 _calls ( 1, FB_Info_Call(), m ),
00157 _icalls ( 1, FB_Info_Icall(), m ),
00158 #ifdef KEY
00159 _values ( 1, FB_Info_Value(), m ),
00160 _values_fp_bin ( 1, FB_Info_Value_FP_Bin(), m ),
00161 _runtime_func_addr( runtime_fun_address ),
00162 #endif
00163 _switches( 1, FB_Info_Switch(), m )
00164 {
00165 if ( _trace )
00166 fprintf( TFile, "==================================================\n"
00167 "Constructing FEEDBACK for " );
00168
00169 _invokes.reserve (invoke_size);
00170 _branches.reserve (branch_size);
00171 _loops.reserve (loop_size);
00172 _circuits.reserve (circuit_size);
00173 _calls.reserve (call_size);
00174 _icalls.reserve (icall_size);
00175 _switches.reserve (switch_size);
00176 #ifdef KEY
00177 _values.reserve (value_size);
00178 _values_fp_bin.reserve (value_fp_bin_size);
00179 #endif
00180
00181 OPERATOR opr = WN_operator( wn );
00182
00183 FmtAssert( opr == OPR_FUNC_ENTRY || opr == OPR_REGION,
00184 ( "FEEDBACK constructor: unexpected opr %d", opr ) );
00185
00186 if ( _trace ) {
00187 if ( opr == OPR_FUNC_ENTRY )
00188 fprintf( TFile, "FUNC_ENTRY %s", ST_name( WN_entry_name( wn ) ) );
00189 else
00190 fprintf( TFile, "REGION" );
00191 fprintf( TFile, "\n==================================================\n" );
00192 }
00193
00194 if ( _trace_draw ) {
00195 dV_view_whirl( wn );
00196 }
00197 }
00198
00199
00200
00201
00202
00203 INT32
00204 FEEDBACK::Get_index_invoke( const WN *wn ) const
00205 {
00206 Is_True( wn != NULL,
00207 ( "FEEDBACK::Get_index_invoke expects non-NULL wn" ) );
00208 Is_True( FB_valid_opr_invoke( wn ),
00209 ( "FEEDBACK::Get_index_invoke found unexpected operator" ) );
00210
00211 INT32 fb_index = IPA_WN_MAP32_Get( _maptab, WN_MAP_FEEDBACK, wn );
00212 Is_True( fb_index >= 0 && fb_index < _invokes.size(),
00213 ( "FEEDBACK::Get_index_invoke found out of range fb_index" ) );
00214 return fb_index;
00215 }
00216
00217 INT32
00218 FEEDBACK::Get_index_branch( const WN *wn ) const
00219 {
00220 Is_True( wn != NULL,
00221 ( "FEEDBACK::Get_index_branch expects non-NULL wn" ) );
00222 Is_True( FB_valid_opr_branch( wn ),
00223 ( "FEEDBACK::Get_index_branch found unexpected operator" ) );
00224
00225 INT32 fb_index = IPA_WN_MAP32_Get( _maptab, WN_MAP_FEEDBACK, wn );
00226 Is_True( fb_index >= 0 && fb_index < _branches.size(),
00227 ( "FEEDBACK::Get_index_branch found out of range fb_index" ) );
00228 return fb_index;
00229 }
00230
00231 INT32
00232 FEEDBACK::Get_index_loop( const WN *wn ) const
00233 {
00234 Is_True( wn != NULL,
00235 ( "FEEDBACK::Get_index_loop expects non-NULL wn" ) );
00236 Is_True( FB_valid_opr_loop( wn ),
00237 ( "FEEDBACK::Get_index_loop found unexpected operator" ) );
00238
00239 INT32 fb_index = IPA_WN_MAP32_Get( _maptab, WN_MAP_FEEDBACK, wn );
00240 Is_True( fb_index >= 0 && fb_index < _loops.size(),
00241 ( "FEEDBACK::Get_index_loop found out of range fb_index" ) );
00242 return fb_index;
00243 }
00244
00245 INT32
00246 FEEDBACK::Get_index_circuit( const WN *wn ) const
00247 {
00248 Is_True( wn != NULL,
00249 ( "FEEDBACK::Get_index_circuit expects non-NULL wn" ) );
00250 Is_True( FB_valid_opr_circuit( wn ),
00251 ( "FEEDBACK::Get_index_circuit found unexpected operator" ) );
00252
00253 INT32 fb_index = IPA_WN_MAP32_Get( _maptab, WN_MAP_FEEDBACK, wn );
00254 Is_True( fb_index >= 0 && fb_index < _circuits.size(),
00255 ( "FEEDBACK::Get_index_circuit found out of range fb_index" ) );
00256 return fb_index;
00257 }
00258
00259 INT32
00260 FEEDBACK::Get_index_call( const WN *wn ) const
00261 {
00262 Is_True( wn != NULL,
00263 ( "FEEDBACK::Get_index_call expects non-NULL wn" ) );
00264 Is_True( FB_valid_opr_call( wn ),
00265 ( "FEEDBACK::Get_index_call found unexpected operator" ) );
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275 WN * wn_notconst = ( WN * ) wn;
00276 OPERATOR old_opr = WN_operator(wn_notconst);
00277 if (old_opr == OPR_ICALL)
00278 {
00279 WN_set_operator(wn_notconst, OPR_CALL);
00280 }
00281
00282 INT32 fb_index = IPA_WN_MAP32_Get( _maptab, WN_MAP_FEEDBACK, wn_notconst );
00283 Is_True( fb_index >= 0 && fb_index < _calls.size(),
00284 ( "FEEDBACK::Get_index_call found out of range fb_index" ) );
00285
00286 Is_True(WN_operator(wn_notconst) != OPR_ICALL,("WN operator must not be icall! icall has been changed to call."));
00287 if (old_opr == OPR_ICALL)
00288 {
00289 WN_set_operator(wn_notconst, old_opr);
00290 }
00291
00292 return fb_index;
00293 }
00294
00295 INT32
00296 FEEDBACK::Get_index_icall( const WN *wn ) const
00297 {
00298 Is_True( wn != NULL,
00299 ( "FEEDBACK::Get_index_icall expects non-NULL wn" ) );
00300 Is_True( FB_valid_opr_call( wn ),
00301 ( "FEEDBACK::Get_index_icall found unexpected operator" ) );
00302
00303 INT32 fb_index = IPA_WN_MAP32_Get( _maptab, WN_MAP_FEEDBACK, wn );
00304
00305 #ifdef KEY
00306 Is_True( fb_index >= 0 && fb_index < _icalls.size(),
00307 ( "FEEDBACK::Get_index_icall found out of range fb_index" ) );
00308 #endif
00309
00310 if (fb_index >= _icalls.size())
00311 {
00312 DevWarn("FEEDBACK::Get_index_icall found out of range fb_index, suspect it is because call index.");
00313 fb_index = 0;
00314 }
00315 Is_True( fb_index >= 0 && fb_index < _icalls.size(),
00316 ( "FEEDBACK::Get_index_icall found out of range fb_index" ) );
00317 return fb_index;
00318 }
00319
00320 INT32
00321 FEEDBACK::Get_index_switch( const WN *wn ) const
00322 {
00323 Is_True( wn != NULL,
00324 ( "FEEDBACK::Get_index_switch expects non-NULL wn" ) );
00325 Is_True( FB_valid_opr_switch( wn ),
00326 ( "FEEDBACK::Get_index_switch found unexpected operator" ) );
00327
00328 INT32 fb_index = IPA_WN_MAP32_Get( _maptab, WN_MAP_FEEDBACK, wn );
00329 Is_True( fb_index >= 0 && fb_index < _switches.size(),
00330 ( "FEEDBACK::Get_index_switch found out of range fb_index" ) );
00331 return fb_index;
00332 }
00333
00334
00335
00336
00337
00338
00339 INT32
00340 FEEDBACK::Add_index_invoke( WN *wn )
00341 {
00342 INT32 fb_index = Get_index_invoke( wn );
00343 Is_True( fb_index >= 0 && fb_index < _invokes.size(),
00344 ( "FEEDBACK::Add_index_invoke found out of range fb_index" ) );
00345
00346 if ( fb_index == 0 ) {
00347 fb_index = _invokes.size();
00348 _invokes.push_back(FB_Info_Invoke());
00349 IPA_WN_MAP32_Set( _maptab, WN_MAP_FEEDBACK, wn, fb_index );
00350 }
00351 return fb_index;
00352 }
00353
00354 INT32
00355 FEEDBACK::Add_index_branch( WN *wn )
00356 {
00357 INT32 fb_index = Get_index_branch( wn );
00358 Is_True( fb_index >= 0 && fb_index < _branches.size(),
00359 ( "FEEDBACK::Add_index_branch found out of range fb_index" ) );
00360
00361 if ( fb_index == 0 ) {
00362 fb_index = _branches.size();
00363 _branches.push_back(FB_Info_Branch());
00364 IPA_WN_MAP32_Set( _maptab, WN_MAP_FEEDBACK, wn, fb_index );
00365 }
00366 return fb_index;
00367 }
00368
00369 INT32
00370 FEEDBACK::Add_index_loop( WN *wn )
00371 {
00372 INT32 fb_index = Get_index_loop( wn );
00373 Is_True( fb_index >= 0 && fb_index < _loops.size(),
00374 ( "FEEDBACK::Add_index_loop found out of range fb_index" ) );
00375
00376 if ( fb_index == 0 ) {
00377 fb_index = _loops.size();
00378 _loops.push_back(FB_Info_Loop());
00379 IPA_WN_MAP32_Set( _maptab, WN_MAP_FEEDBACK, wn, fb_index );
00380 }
00381 return fb_index;
00382 }
00383
00384 INT32
00385 FEEDBACK::Add_index_circuit( WN *wn )
00386 {
00387 INT32 fb_index = Get_index_circuit( wn );
00388 Is_True( fb_index >= 0 && fb_index < _circuits.size(),
00389 ( "FEEDBACK::Add_index_circuit found out of range fb_index" ) );
00390
00391 if ( fb_index == 0 ) {
00392 fb_index = _circuits.size();
00393 _circuits.push_back(FB_Info_Circuit());
00394 IPA_WN_MAP32_Set( _maptab, WN_MAP_FEEDBACK, wn, fb_index );
00395 }
00396 return fb_index;
00397 }
00398
00399 INT32
00400 FEEDBACK::Add_index_call( WN *wn )
00401 {
00402
00403
00404
00405
00406
00407
00408
00409
00410 OPERATOR old_opr = WN_operator(wn);
00411 if (old_opr == OPR_ICALL)
00412 {
00413 WN_set_operator(wn, OPR_CALL);
00414 }
00415
00416 INT32 fb_index = Get_index_call( wn );
00417 Is_True( fb_index >= 0 && fb_index < _calls.size(),
00418 ( "FEEDBACK::Add_index_call found out of range fb_index" ) );
00419
00420 if (fb_index == 0) {
00421 fb_index = _calls.size();
00422 _calls.push_back(FB_Info_Call());
00423 #ifdef KEY
00424 _icalls.push_back(FB_Info_Icall());
00425 #endif
00426 IPA_WN_MAP32_Set( _maptab, WN_MAP_FEEDBACK, wn, fb_index );
00427 }
00428
00429 Is_True(WN_operator(wn) != OPR_ICALL,("WN operator must not be icall! icall has been changed to call."));
00430 if (old_opr == OPR_ICALL)
00431 {
00432 WN_set_operator(wn, old_opr);
00433 }
00434
00435 return fb_index;
00436 }
00437
00438 INT32
00439 FEEDBACK::Add_index_icall( WN *wn )
00440 {
00441 INT32 fb_index = Get_index_icall( wn );
00442 Is_True( fb_index >= 0 && fb_index < _icalls.size(),
00443 ( "FEEDBACK::Add_index_icall found out of range fb_index" ) );
00444
00445 if (fb_index == 0) {
00446 fb_index = _icalls.size();
00447 _icalls.push_back(FB_Info_Icall());
00448 IPA_WN_MAP32_Set( _maptab, WN_MAP_FEEDBACK, wn, fb_index );
00449 }
00450 return fb_index;
00451 }
00452
00453 INT32
00454 FEEDBACK::Add_index_switch( WN *wn )
00455 {
00456 INT32 fb_index = Get_index_switch( wn );
00457 Is_True( fb_index >= 0 && fb_index < _switches.size(),
00458 ( "FEEDBACK::Add_index_switch found out of range fb_index" ) );
00459
00460 if ( fb_index == 0 ) {
00461 fb_index = _switches.size();
00462 _switches.push_back(FB_Info_Switch());
00463 IPA_WN_MAP32_Set( _maptab, WN_MAP_FEEDBACK, wn, fb_index );
00464 }
00465 return fb_index;
00466 }
00467
00468
00469
00470
00471
00472 bool
00473 FEEDBACK::Same_in_out( const WN *wn ) {
00474 OPERATOR opr = WN_operator( wn );
00475 switch ( opr ) {
00476 case OPR_FUNC_ENTRY: case OPR_ALTENTRY:
00477 case OPR_RETURN: case OPR_RETURN_VAL:
00478 #ifdef KEY
00479 case OPR_GOTO_OUTER_BLOCK:
00480 #endif
00481 return false;
00482
00483 fb_opr_cases_call:
00484 {
00485 INT32 fb_index = Get_index_call( wn );
00486 return _calls[fb_index].in_out_same;
00487 }
00488
00489 default:
00490 break;
00491 }
00492 return true;
00493 }
00494
00495
00496 void
00497 FEEDBACK::FB_set_in_out_same_node( WN *wn )
00498 {
00499
00500 if ( FB_valid_opr_call( wn ) ) {
00501
00502 if ( _trace )
00503 fprintf( TFile, "FEEDBACK::FB_set_in_out_same_node(0x%p):\n", wn );
00504
00505 FB_Info_Call info_call = Query_call( wn );
00506 info_call.in_out_same = true;
00507 Annot_call( wn, info_call );
00508 }
00509 }
00510
00511
00512 void
00513 FEEDBACK::FB_set_in_out_same( WN *wn )
00514 {
00515 if ( _trace )
00516 fprintf( TFile, "FEEDBACK::FB_set_in_out_same(0x%p):\n", wn );
00517
00518 for ( TREE_ITER iter( wn ); iter.Wn() != NULL; ++iter )
00519 FB_set_in_out_same_node( iter.Wn() );
00520 }
00521
00522 #if defined(TARG_SL) && defined(TARG_SL2)
00523 void
00524 FEEDBACK::FB_reset_in_out_same_node( WN *wn )
00525 {
00526
00527 if ( FB_valid_opr_call( wn ) ) {
00528
00529 if ( _trace )
00530 fprintf( TFile, "FEEDBACK::FB_set_in_out_same_node(0x%p):\n", wn );
00531
00532 FB_Info_Call info_call = Query_call( wn );
00533 info_call.in_out_same = false;
00534 Annot_call( wn, info_call );
00535 }
00536 }
00537 #endif
00538
00539
00540
00541
00542
00543 void
00544 FEEDBACK::Print( FILE *fp, const WN *wn ) const
00545 {
00546 if ( wn == NULL ) return;
00547 INT32 fb_index;
00548 OPERATOR opr = WN_operator( wn );
00549 switch ( opr ) {
00550
00551 case OPR_PRAGMA:
00552 if ( WN_pragma( wn ) != WN_PRAGMA_PREAMBLE_END )
00553 break;
00554
00555
00556 fb_opr_cases_invoke:
00557 fb_index = Get_index_invoke( wn );
00558 _invokes[fb_index].Print( fp );
00559 break;
00560
00561 fb_opr_cases_branch:
00562 fb_index = Get_index_branch( wn );
00563 _branches[fb_index].Print( fp );
00564 break;
00565
00566 fb_opr_cases_loop:
00567 fb_index = Get_index_loop( wn );
00568 _loops[fb_index].Print( fp );
00569 break;
00570
00571 fb_opr_cases_circuit:
00572 fb_index = Get_index_circuit( wn );
00573 _circuits[fb_index].Print( fp );
00574 break;
00575
00576 fb_opr_cases_call:
00577 fb_index = Get_index_call( wn );
00578 _calls[fb_index].Print( fp );
00579 #ifdef KEY
00580 if( WN_operator(wn) == OPR_ICALL ){
00581 fb_index = Get_index_icall( wn );
00582 _icalls[fb_index].Print( fp );
00583 }
00584 #endif
00585 break;
00586
00587 fb_opr_cases_switch:
00588 fb_index = Get_index_switch( wn );
00589 _switches[fb_index].Print( fp );
00590 break;
00591
00592 #ifdef KEY
00593 fb_opr_cases_value:
00594 if( IS_VALID_DIV_VALUE( wn ) ){
00595 fb_index = Get_index_value( wn );
00596 _values[fb_index].Print( fp );
00597 }
00598 break;
00599
00600 fb_opr_cases_value_fp_bin:
00601 if( IS_VALID_MPY_VALUE( wn ) ){
00602 fb_index = Get_index_value_fp_bin( wn );
00603 _values_fp_bin[fb_index].Print( fp );
00604 }
00605 break;
00606 #endif
00607
00608 default:
00609 break;
00610 }
00611 }
00612
00613 void
00614 FEEDBACK::Print_with_wn( FILE *fp, WN *wn ) const
00615 {
00616 Print( fp, wn );
00617 fprintf( fp, "\nfor " );
00618 fdump_wn( TFile, wn );
00619 }
00620
00621
00622
00623
00624
00625 const FB_Info_Invoke&
00626 FEEDBACK::Query_invoke( const WN *wn ) const
00627 {
00628 INT32 fb_index = Get_index_invoke( wn );
00629 return _invokes[fb_index];
00630 }
00631
00632 const FB_Info_Branch&
00633 FEEDBACK::Query_branch( const WN *wn ) const
00634 {
00635 INT32 fb_index = Get_index_branch( wn );
00636 return _branches[fb_index];
00637 }
00638
00639 const FB_Info_Loop&
00640 FEEDBACK::Query_loop( const WN *wn ) const
00641 {
00642 INT32 fb_index = Get_index_loop( wn );
00643 return _loops[fb_index];
00644 }
00645
00646 const FB_Info_Circuit&
00647 FEEDBACK::Query_circuit( const WN *wn ) const
00648 {
00649 INT32 fb_index = Get_index_circuit( wn );
00650 return _circuits[fb_index];
00651 }
00652
00653 const FB_Info_Call&
00654 FEEDBACK::Query_call( const WN *wn ) const
00655 {
00656 INT32 fb_index = Get_index_call( wn );
00657 return _calls[fb_index];
00658 }
00659
00660 const FB_Info_Icall&
00661 FEEDBACK::Query_icall( const WN *wn ) const
00662 {
00663 INT32 fb_index = Get_index_icall( wn );
00664 return _icalls[fb_index];
00665 }
00666
00667 const FB_Info_Switch&
00668 FEEDBACK::Query_switch( const WN *wn ) const
00669 {
00670 INT32 fb_index = Get_index_switch( wn );
00671 return _switches[fb_index];
00672 }
00673
00674 #ifdef KEY
00675 const FB_Info_Value&
00676 FEEDBACK::Query_value( const WN *wn ) const
00677 {
00678 if (! IS_VALID_DIV_VALUE(wn))
00679 return _values[0];
00680 INT32 fb_index = Get_index_value( wn );
00681 return _values[fb_index];
00682 }
00683
00684 const FB_Info_Value_FP_Bin&
00685 FEEDBACK::Query_value_fp_bin( const WN *wn ) const
00686 {
00687 if (! IS_VALID_MPY_VALUE(wn))
00688 return _values_fp_bin[0];
00689 INT32 fb_index = Get_index_value_fp_bin( wn );
00690 return _values_fp_bin[fb_index];
00691 }
00692 #endif
00693
00694
00695 FB_FREQ
00696 FEEDBACK::Query( const WN *wn, const FB_EDGE_TYPE type ) const
00697 {
00698 INT32 fb_index;
00699 OPERATOR opr = WN_operator( wn );
00700 FB_FREQ freq = FB_FREQ_UNINIT;
00701
00702 switch( type ) {
00703
00704 case FB_EDGE_UNINIT:
00705 Is_True( false, ( "FEEDBACK::Query found edge type FB_EDGE_UNINT" ) );
00706 break;
00707
00708 case FB_EDGE_INCOMING:
00709 case FB_EDGE_OUTGOING:
00710 case FB_EDGE_ENTRY_OUTGOING:
00711 fb_index = Get_index_invoke( wn );
00712 freq = _invokes[fb_index].freq_invoke;
00713 break;
00714
00715 case FB_EDGE_BRANCH_TAKEN:
00716 fb_index = Get_index_branch( wn );
00717 freq = _branches[fb_index].freq_taken;
00718 break;
00719
00720 case FB_EDGE_BRANCH_NOT_TAKEN:
00721 fb_index = Get_index_branch( wn );
00722 freq = _branches[fb_index].freq_not_taken;
00723 break;
00724
00725 case FB_EDGE_LOOP_ZERO:
00726 fb_index = Get_index_loop( wn );
00727 freq = _loops[fb_index].freq_zero;
00728 break;
00729
00730 case FB_EDGE_LOOP_POSITIVE:
00731 fb_index = Get_index_loop( wn );
00732 freq = _loops[fb_index].freq_positive;
00733 break;
00734
00735 case FB_EDGE_LOOP_OUT:
00736 fb_index = Get_index_loop( wn );
00737 freq = _loops[fb_index].freq_out;
00738 break;
00739
00740 case FB_EDGE_LOOP_BACK:
00741 fb_index = Get_index_loop( wn );
00742 freq = _loops[fb_index].freq_back;
00743 break;
00744
00745 case FB_EDGE_LOOP_EXIT:
00746 fb_index = Get_index_loop( wn );
00747 freq = _loops[fb_index].freq_exit;
00748 break;
00749
00750 case FB_EDGE_LOOP_ITERATE:
00751 fb_index = Get_index_loop( wn );
00752 freq = _loops[fb_index].freq_iterate;
00753 break;
00754
00755 case FB_EDGE_CIRCUIT_LEFT:
00756 fb_index = Get_index_circuit( wn );
00757 freq = _circuits[fb_index].freq_left;
00758 break;
00759
00760 case FB_EDGE_CIRCUIT_RIGHT:
00761 fb_index = Get_index_circuit( wn );
00762 freq = _circuits[fb_index].freq_right;
00763 break;
00764
00765 case FB_EDGE_CIRCUIT_NEITHER:
00766 fb_index = Get_index_circuit( wn );
00767 freq = _circuits[fb_index].freq_neither;
00768 break;
00769
00770 case FB_EDGE_CALL_INCOMING:
00771 fb_index = Get_index_call( wn );
00772 freq = _calls[fb_index].freq_entry;
00773 break;
00774
00775 case FB_EDGE_CALL_OUTGOING:
00776 case FB_EDGE_IO_OUTGOING:
00777 fb_index = Get_index_call( wn );
00778 freq = _calls[fb_index].freq_exit;
00779 break;
00780
00781 case FB_EDGE_CALL_INOUTSAME:
00782 fb_index = Get_index_call( wn );
00783 Is_True( _calls[fb_index].in_out_same,
00784 ( "FEEDBACK::Query found in_out_same discrepancy" ) );
00785 freq = _calls[fb_index].freq_exit;
00786 break;
00787
00788 case FB_EDGE_SWITCH_DEFAULT:
00789 fb_index = Get_index_switch( wn );
00790 freq = _switches[fb_index][0];
00791 break;
00792
00793 default:
00794 if ( type >= FB_EDGE_SWITCH_BASE ) {
00795
00796
00797 fb_index = Get_index_switch( wn );
00798 const INT32 index_target = FB_EDGE_SWITCH_INDEX( type );
00799 freq = _switches[fb_index][index_target];
00800
00801 } else if ( type >= FB_EDGE_IO_ESCAPE_BASE &&
00802 type < FB_EDGE_IO_ESCAPE_BASE + FB_IO_ESCAPE_EDGES_MAX ) {
00803
00804
00805 fb_index = Get_index_call( wn );
00806 freq = ( _calls[fb_index].in_out_same ? FB_FREQ_ZERO : FB_FREQ_UNKNOWN );
00807
00808 } else
00809 Is_True( false, ( "FEEDBACK::Query encounted unexpected edge type" ) );
00810
00811 break;
00812 }
00813
00814 if ( _trace ) {
00815 char buffer[FB_EDGE_TYPE_NAME_LENGTH];
00816 FB_EDGE_TYPE_sprintf( buffer, type );
00817
00818 fprintf( TFile, "FEEDBACK::Query(0x%p, %s) == ", wn, buffer );
00819 freq.Print( TFile );
00820 fprintf( TFile, "\n" );
00821 }
00822 return freq;
00823 }
00824
00825
00826 FB_FREQ
00827 FEEDBACK::Query_prob( const WN *wn, const FB_EDGE_TYPE type ) const
00828 {
00829 INT32 fb_index;
00830 OPERATOR opr = WN_operator( wn );
00831 FB_FREQ freq = FB_FREQ_UNINIT, total = FB_FREQ_UNINIT;
00832
00833 switch( type ) {
00834
00835 case FB_EDGE_UNINIT:
00836 Is_True( false,
00837 ( "FEEDBACK::Query_prob found edge type FB_EDGE_UNINT" ) );
00838 break;
00839
00840 case FB_EDGE_INCOMING:
00841 case FB_EDGE_OUTGOING:
00842 case FB_EDGE_ENTRY_OUTGOING:
00843 fb_index = Get_index_invoke( wn );
00844 freq = _invokes[fb_index].freq_invoke;
00845 total = freq;
00846 break;
00847
00848 case FB_EDGE_BRANCH_TAKEN:
00849 fb_index = Get_index_branch( wn );
00850 freq = _branches[fb_index].freq_taken;
00851 total = _branches[fb_index].Total();
00852 break;
00853
00854 case FB_EDGE_BRANCH_NOT_TAKEN:
00855 fb_index = Get_index_branch( wn );
00856 freq = _branches[fb_index].freq_not_taken;
00857 total = _branches[fb_index].Total();
00858 break;
00859
00860 case FB_EDGE_LOOP_ZERO:
00861 fb_index = Get_index_loop( wn );
00862 freq = _loops[fb_index].freq_zero;
00863 total = _loops[fb_index].freq_exit;
00864 break;
00865
00866 case FB_EDGE_LOOP_POSITIVE:
00867 fb_index = Get_index_loop( wn );
00868 freq = _loops[fb_index].freq_positive;
00869 total = _loops[fb_index].freq_iterate;
00870 break;
00871
00872 case FB_EDGE_LOOP_OUT:
00873 fb_index = Get_index_loop( wn );
00874 freq = _loops[fb_index].freq_out;
00875 total = _loops[fb_index].freq_exit;
00876 break;
00877
00878 case FB_EDGE_LOOP_BACK:
00879 fb_index = Get_index_loop( wn );
00880 freq = _loops[fb_index].freq_back;
00881 total = _loops[fb_index].freq_iterate;
00882 break;
00883
00884 case FB_EDGE_LOOP_EXIT:
00885 fb_index = Get_index_loop( wn );
00886 freq = _loops[fb_index].freq_exit;
00887 total = _loops[fb_index].Total();
00888 break;
00889
00890 case FB_EDGE_LOOP_ITERATE:
00891 fb_index = Get_index_loop( wn );
00892 freq = _loops[fb_index].freq_iterate;
00893 total = _loops[fb_index].Total();
00894 break;
00895
00896 case FB_EDGE_CIRCUIT_LEFT:
00897 fb_index = Get_index_circuit( wn );
00898 freq = _circuits[fb_index].freq_left;
00899 total = _circuits[fb_index].Total();
00900 break;
00901
00902 case FB_EDGE_CIRCUIT_RIGHT:
00903 fb_index = Get_index_circuit( wn );
00904 freq = _circuits[fb_index].freq_right;
00905 total = _circuits[fb_index].Total();
00906 break;
00907
00908 case FB_EDGE_CIRCUIT_NEITHER:
00909 fb_index = Get_index_circuit( wn );
00910 freq = _circuits[fb_index].freq_neither;
00911 total = _circuits[fb_index].Total();
00912 break;
00913
00914 case FB_EDGE_CALL_INCOMING:
00915 case FB_EDGE_CALL_OUTGOING:
00916 case FB_EDGE_CALL_INOUTSAME:
00917 case FB_EDGE_IO_OUTGOING:
00918 fb_index = Get_index_call( wn );
00919 freq = _calls[fb_index].freq_exit;
00920 total = _calls[fb_index].freq_entry;
00921 break;
00922
00923 case FB_EDGE_SWITCH_DEFAULT:
00924 fb_index = Get_index_switch( wn );
00925 freq = _switches[fb_index][0];
00926 total = _switches[fb_index].Total();
00927 break;
00928
00929 default:
00930 if ( type >= FB_EDGE_SWITCH_BASE ) {
00931
00932
00933 fb_index = Get_index_switch( wn );
00934 const INT32 index_target = FB_EDGE_SWITCH_INDEX( type );
00935 freq = _switches[fb_index][index_target];
00936 total = _switches[fb_index].Total();
00937
00938 } else if ( type >= FB_EDGE_IO_ESCAPE_BASE &&
00939 type < FB_EDGE_IO_ESCAPE_BASE + FB_IO_ESCAPE_EDGES_MAX ) {
00940
00941
00942 fb_index = Get_index_call( wn );
00943 freq = ( _calls[fb_index].in_out_same
00944 ? FB_FREQ_ZERO : FB_FREQ_UNKNOWN );
00945 total = _calls[fb_index].freq_entry;
00946
00947 } else
00948 Is_True( false, ( "FEEDBACK::Query encounted unexpected edge type" ) );
00949
00950 break;
00951 }
00952
00953 if ( _trace ) {
00954 char buffer[FB_EDGE_TYPE_NAME_LENGTH];
00955 FB_EDGE_TYPE_sprintf( buffer, type );
00956
00957 fprintf( TFile, "FEEDBACK::Query_prob(0x%p, %s) == ", wn, buffer );
00958 freq.Print( TFile );
00959 fprintf( TFile, ", total = " );
00960 total.Print( TFile );
00961 fprintf(TFile, "\n" );
00962 }
00963 return freq / total;
00964 }
00965
00966
00967 FB_FREQ
00968 FEEDBACK::Query_total_out( const WN *wn ) const
00969 {
00970 Is_True( wn != NULL, ("FEEDBACK::Query_total_out expects non-NULL wn") );
00971
00972 INT32 fb_index;
00973 OPERATOR opr = WN_operator( wn );
00974 FB_FREQ freq = FB_FREQ_UNINIT;
00975
00976 switch( opr ) {
00977
00978 case OPR_PRAGMA:
00979 if ( WN_pragma( wn ) != WN_PRAGMA_PREAMBLE_END )
00980 break;
00981
00982
00983 fb_opr_cases_invoke:
00984 if ( opr == OPR_RETURN || opr == OPR_RETURN_VAL
00985 #ifdef KEY
00986 || opr == OPR_GOTO_OUTER_BLOCK
00987 #endif
00988 )
00989 freq = FB_FREQ_ZERO;
00990 else {
00991 fb_index = Get_index_invoke( wn );
00992 freq = _invokes[fb_index].freq_invoke;
00993 }
00994 break;
00995
00996 fb_opr_cases_branch:
00997 fb_index = Get_index_branch( wn );
00998 freq = _branches[fb_index].Total();
00999 break;
01000
01001 fb_opr_cases_loop:
01002 fb_index = Get_index_loop( wn );
01003 freq = _loops[fb_index].freq_exit;
01004 break;
01005
01006 fb_opr_cases_circuit:
01007 fb_index = Get_index_circuit( wn );
01008 freq = _circuits[fb_index].Total();
01009 break;
01010
01011 fb_opr_cases_call:
01012 fb_index = Get_index_call( wn );
01013 freq = ( opr == OPR_IO
01014 ? _calls[fb_index].freq_entry
01015 : _calls[fb_index].freq_exit );
01016 break;
01017
01018 fb_opr_cases_switch:
01019 fb_index = Get_index_switch( wn );
01020 freq = _switches[fb_index].Total();
01021 break;
01022
01023 #ifdef KEY
01024 fb_opr_cases_value:
01025 if( IS_VALID_DIV_VALUE( wn ) ){
01026 fb_index = Get_index_value( wn );
01027 freq = _values[fb_index].Total();
01028 }
01029 break;
01030
01031 fb_opr_cases_value_fp_bin:
01032 if( IS_VALID_MPY_VALUE( wn ) ){
01033 fb_index = Get_index_value_fp_bin( wn );
01034 freq = _values_fp_bin[fb_index].Total();
01035 }
01036 break;
01037 #endif
01038
01039 default:
01040 break;
01041 }
01042
01043 if ( _trace ) {
01044 fprintf( TFile, "FEEDBACK::Query_total_out(0x%p: %s) == ",
01045 wn, OPERATOR_name(opr) );
01046 freq.Print( TFile );
01047 fprintf( TFile, "\n" );
01048 }
01049 return freq;
01050 }
01051
01052
01053
01054
01055
01056
01057 void
01058 FEEDBACK::Annot_invoke( WN *wn, const FB_Info_Invoke& fb_info )
01059 {
01060 INT32 fb_index = Add_index_invoke( wn );
01061 _invokes[fb_index] = fb_info;
01062
01063 if ( _trace ) {
01064 fprintf( TFile, "FEEDBACK::Annot_invoke(0x%p):\n", wn );
01065 Print_with_wn( TFile, wn );
01066 }
01067 }
01068
01069 void
01070 FEEDBACK::Annot_branch( WN *wn, const FB_Info_Branch& fb_info )
01071 {
01072 INT32 fb_index = Add_index_branch( wn );
01073 _branches[fb_index] = fb_info;
01074
01075 if ( _trace ) {
01076 fprintf( TFile, "FEEDBACK::Annot_branch(0x%p):\n", wn );
01077 Print_with_wn( TFile, wn );
01078 }
01079 }
01080
01081 #ifdef KEY
01082 INT32 FEEDBACK::Get_index_value_fp_bin( const WN *wn ) const
01083 {
01084 Is_True( wn != NULL,
01085 ( "FEEDBACK::Get_index_invoke expects non-NULL wn" ) );
01086 Is_True( FB_valid_opr_value( wn ),
01087 ( "FEEDBACK::Get_index_invoke found unexpected operator" ) );
01088
01089 INT32 fb_index = IPA_WN_MAP32_Get( _maptab, WN_MAP_FEEDBACK, wn );
01090 Is_True( fb_index >= 0 && fb_index < _values_fp_bin.size(),
01091 ( "FEEDBACK::Get_index_invoke found out of range fb_index" ) );
01092 return fb_index;
01093 }
01094
01095 INT32 FEEDBACK::Add_index_value_fp_bin( WN *wn )
01096 {
01097 INT32 fb_index = Get_index_value_fp_bin( wn );
01098 Is_True( fb_index >= 0 && fb_index < _values_fp_bin.size(),
01099 ( "FEEDBACK::Add_index_value_fp_bin found out of range fb_index" ));
01100
01101 if ( fb_index == 0 ) {
01102 fb_index = _values_fp_bin.size();
01103 _values_fp_bin.push_back(FB_Info_Value_FP_Bin());
01104 IPA_WN_MAP32_Set( _maptab, WN_MAP_FEEDBACK, wn, fb_index );
01105 }
01106 return fb_index;
01107 }
01108
01109 void FEEDBACK::Annot_value_fp_bin( WN *wn,
01110 const FB_Info_Value_FP_Bin& fb_info )
01111 {
01112 INT32 fb_index = Add_index_value_fp_bin( wn );
01113 _values_fp_bin[fb_index] = fb_info;
01114
01115 if ( _trace ) {
01116 fprintf( TFile, "FEEDBACK::Annot_value_fp_bin(0x%p):\n", wn );
01117 Print_with_wn( TFile, wn );
01118 }
01119 }
01120
01121 INT32 FEEDBACK::Get_index_value( const WN *wn ) const
01122 {
01123 Is_True( wn != NULL,
01124 ( "FEEDBACK::Get_index_invoke expects non-NULL wn" ) );
01125 Is_True( FB_valid_opr_value( wn ),
01126 ( "FEEDBACK::Get_index_invoke found unexpected operator" ) );
01127
01128 INT32 fb_index = IPA_WN_MAP32_Get( _maptab, WN_MAP_FEEDBACK, wn );
01129 Is_True( fb_index >= 0 && fb_index < _values.size(),
01130 ( "FEEDBACK::Get_index_invoke found out of range fb_index" ) );
01131 return fb_index;
01132 }
01133
01134 INT32 FEEDBACK::Add_index_value( WN *wn )
01135 {
01136 INT32 fb_index = Get_index_value( wn );
01137 Is_True( fb_index >= 0 && fb_index < _values.size(),
01138 ( "FEEDBACK::Add_index_value found out of range fb_index" ) );
01139
01140 if ( fb_index == 0 ) {
01141 fb_index = _values.size();
01142 _values.push_back(FB_Info_Value());
01143 IPA_WN_MAP32_Set( _maptab, WN_MAP_FEEDBACK, wn, fb_index );
01144 }
01145 return fb_index;
01146 }
01147
01148 void FEEDBACK::Annot_value( WN *wn, const FB_Info_Value& fb_info )
01149 {
01150 INT32 fb_index = Add_index_value( wn );
01151 _values[fb_index] = fb_info;
01152
01153 if ( _trace ) {
01154 fprintf( TFile, "FEEDBACK::Annot_value(0x%p):\n", wn );
01155 Print_with_wn( TFile, wn );
01156 }
01157 }
01158 #endif
01159
01160
01161 void
01162 FEEDBACK::Annot_loop( WN *wn, const FB_Info_Loop& fb_info )
01163 {
01164 INT32 fb_index = Add_index_loop( wn );
01165 _loops[fb_index] = fb_info;
01166
01167 if ( _trace ) {
01168 fprintf( TFile, "FEEDBACK::Annot_loop(0x%p):\n", wn );
01169 Print_with_wn( TFile, wn );
01170 }
01171 }
01172
01173 void
01174 FEEDBACK::Annot_circuit( WN *wn, const FB_Info_Circuit& fb_info )
01175 {
01176 INT32 fb_index = Add_index_circuit( wn );
01177 _circuits[fb_index] = fb_info;
01178
01179 if ( _trace ) {
01180 fprintf( TFile, "FEEDBACK::Annot_circuit(0x%p):\n", wn );
01181 Print_with_wn( TFile, wn );
01182 }
01183 }
01184
01185 void
01186 FEEDBACK::Annot_call( WN *wn, const FB_Info_Call& fb_info )
01187 {
01188 INT32 fb_index = Add_index_call( wn );
01189 _calls[fb_index] = fb_info;
01190
01191 if ( _trace ) {
01192 fprintf( TFile, "FEEDBACK::Annot_call(0x%p):\n", wn );
01193 Print_with_wn( TFile, wn );
01194 }
01195 }
01196
01197 void
01198 FEEDBACK::Annot_icall( WN *wn, const FB_Info_Icall& fb_info )
01199 {
01200 INT32 fb_index = Add_index_icall( wn );
01201 _icalls[fb_index] = fb_info;
01202
01203 #if 0
01204 UINT64 counter = 0;
01205 int i;
01206 for( i = 0; i < FB_TNV_SIZE; i++ ){
01207 if( fb_info.tnv._values[i] == 0 )
01208 break;
01209 counter += fb_info.tnv._counters[i];
01210 }
01211
01212 if( i < FB_TNV_SIZE ){
01213 FmtAssert( fb_info.tnv._exec_counter == counter,
01214 ("icall counters don't match") );
01215 } else {
01216 FmtAssert( fb_info.tnv._exec_counter >= counter,
01217 ("icall counters don't match") );
01218 }
01219 #endif // Is_True_On
01220
01221 if ( _trace ) {
01222 fprintf( TFile, "FEEDBACK::Annot_icall(0x%p):\n", wn );
01223 Print_with_wn( TFile, wn );
01224 }
01225 }
01226
01227 void
01228 FEEDBACK::Annot_switch( WN *wn, const FB_Info_Switch& fb_info )
01229 {
01230 INT32 fb_index = Add_index_switch( wn );
01231 _switches[fb_index] = fb_info;
01232
01233 if ( _trace ) {
01234 fprintf( TFile, "FEEDBACK::Annot_switch(0x%p):\n", wn );
01235 Print_with_wn( TFile, wn );
01236 }
01237 }
01238
01239
01240 void
01241 FEEDBACK::Annot( WN *wn, FB_EDGE_TYPE type, FB_FREQ freq )
01242 {
01243 INT32 fb_index;
01244
01245 switch(type) {
01246
01247 case FB_EDGE_UNINIT:
01248 Is_True( false, ( "FEEDBACK::Annot found edge type FB_EDGE_UNINIT" ) );
01249 break;
01250
01251 case FB_EDGE_INCOMING:
01252 case FB_EDGE_OUTGOING:
01253 case FB_EDGE_ENTRY_OUTGOING:
01254 fb_index = Add_index_invoke( wn );
01255 _invokes[fb_index].freq_invoke = freq;
01256 break;
01257
01258 case FB_EDGE_BRANCH_TAKEN:
01259 fb_index = Add_index_branch( wn );
01260 _branches[fb_index].freq_taken = freq;
01261 break;
01262
01263 case FB_EDGE_BRANCH_NOT_TAKEN:
01264 fb_index = Add_index_branch( wn );
01265 _branches[fb_index].freq_not_taken = freq;
01266 break;
01267
01268 case FB_EDGE_LOOP_ZERO:
01269 fb_index = Add_index_loop( wn );
01270 {
01271 FB_Info_Loop& loop = _loops[fb_index];
01272 loop.freq_zero = freq;
01273 if ( ! freq.Known() || loop.freq_out.Known() )
01274 loop.freq_exit = freq + loop.freq_out;
01275 else if ( loop.freq_exit.Known() )
01276 loop.freq_out = loop.freq_exit - freq;
01277 }
01278 break;
01279
01280 case FB_EDGE_LOOP_POSITIVE:
01281 fb_index = Add_index_loop( wn );
01282 {
01283 FB_Info_Loop& loop = _loops[fb_index];
01284 loop.freq_positive = freq;
01285 if ( ! freq.Known() || loop.freq_back.Known() )
01286 loop.freq_iterate = freq + loop.freq_back;
01287 else if ( loop.freq_iterate.Known() )
01288 loop.freq_back = loop.freq_iterate - freq;
01289 }
01290 break;
01291
01292 case FB_EDGE_LOOP_OUT:
01293 fb_index = Add_index_loop( wn );
01294 {
01295 FB_Info_Loop& loop = _loops[fb_index];
01296 loop.freq_out = freq;
01297 if ( ! freq.Known() || loop.freq_zero.Known() )
01298 loop.freq_exit = freq + loop.freq_zero;
01299 else if ( loop.freq_exit.Known() )
01300 loop.freq_zero = loop.freq_exit - freq;
01301 }
01302 break;
01303
01304 case FB_EDGE_LOOP_BACK:
01305 fb_index = Add_index_loop( wn );
01306 {
01307 FB_Info_Loop& loop = _loops[fb_index];
01308 loop.freq_back = freq;
01309 if ( ! freq.Known() || loop.freq_positive.Known() )
01310 loop.freq_iterate = freq + loop.freq_positive;
01311 else if ( loop.freq_iterate.Known() )
01312 loop.freq_positive = loop.freq_iterate - freq;
01313 }
01314 break;
01315
01316 case FB_EDGE_LOOP_EXIT:
01317 fb_index = Add_index_loop( wn );
01318 {
01319 FB_Info_Loop& loop = _loops[fb_index];
01320 loop.freq_exit = freq;
01321 if ( ! freq.Known() )
01322 loop.freq_zero = loop.freq_out = freq;
01323 else if ( loop.freq_zero.Known() )
01324 if ( ! loop.freq_out.Known() )
01325 loop.freq_out = freq - loop.freq_zero;
01326 else if ( loop.freq_out.Known() )
01327 loop.freq_zero = freq - loop.freq_out;
01328 }
01329 break;
01330
01331 case FB_EDGE_LOOP_ITERATE:
01332 fb_index = Add_index_loop( wn );
01333 {
01334 FB_Info_Loop& loop = _loops[fb_index];
01335 loop.freq_iterate = freq;
01336 if ( ! freq.Known() )
01337 loop.freq_positive = loop.freq_back = freq;
01338 else if ( loop.freq_positive.Known() )
01339 if ( ! loop.freq_back.Known() )
01340 loop.freq_back = freq - loop.freq_positive;
01341 else if ( loop.freq_back.Known() )
01342 loop.freq_positive = freq - loop.freq_back;
01343 }
01344 break;
01345
01346 case FB_EDGE_CIRCUIT_LEFT:
01347 fb_index = Add_index_circuit( wn );
01348 _circuits[fb_index].freq_left = freq;
01349 break;
01350
01351 case FB_EDGE_CIRCUIT_RIGHT:
01352 fb_index = Add_index_circuit( wn );
01353 _circuits[fb_index].freq_right = freq;
01354 break;
01355
01356 case FB_EDGE_CIRCUIT_NEITHER:
01357 fb_index = Add_index_circuit( wn );
01358 _circuits[fb_index].freq_neither = freq;
01359 break;
01360
01361 case FB_EDGE_CALL_INCOMING:
01362 {
01363 fb_index = Add_index_call( wn );
01364 FB_Info_Call& fb_info = _calls[fb_index];
01365 fb_info.freq_entry = freq;
01366
01367 if ( ! fb_info.in_out_same &&
01368 fb_info.freq_entry.Exact() &&
01369 fb_info.freq_exit.Exact() &&
01370 fb_info.freq_entry == fb_info.freq_exit )
01371 fb_info.in_out_same = true;
01372 }
01373 break;
01374
01375 case FB_EDGE_CALL_OUTGOING:
01376 case FB_EDGE_IO_OUTGOING:
01377 {
01378 fb_index = Add_index_call( wn );
01379 FB_Info_Call& fb_info = _calls[fb_index];
01380 fb_info.freq_exit = freq;
01381
01382 if ( ! fb_info.in_out_same &&
01383 fb_info.freq_entry.Exact() &&
01384 fb_info.freq_exit.Exact() &&
01385 fb_info.freq_entry == fb_info.freq_exit )
01386 fb_info.in_out_same = true;
01387 }
01388 break;
01389
01390 case FB_EDGE_CALL_INOUTSAME:
01391 fb_index = Add_index_call( wn );
01392 _calls[fb_index].in_out_same = true;
01393 _calls[fb_index].freq_entry = freq;
01394 _calls[fb_index].freq_exit = freq;
01395 break;
01396
01397 case FB_EDGE_SWITCH_DEFAULT:
01398 fb_index = Add_index_switch( wn );
01399 _switches[fb_index][0] = freq;
01400 break;
01401
01402 default:
01403 if ( type >= FB_EDGE_SWITCH_BASE ) {
01404
01405
01406 fb_index = Add_index_switch( wn );
01407 const INT32 index_target = FB_EDGE_SWITCH_INDEX( type );
01408 _switches[fb_index][index_target] = freq;
01409
01410 } else if ( type >= FB_EDGE_IO_ESCAPE_BASE &&
01411 type < FB_EDGE_IO_ESCAPE_BASE + FB_IO_ESCAPE_EDGES_MAX ) {
01412
01413
01414 DevWarn( "Annot called with type FB_EDGE_IO_ESCAPE(br) -- not handled" );
01415
01416 } else
01417 Is_True( false, ( "FEEDBACK::Query encounted unexpected edge type" ) );
01418
01419 break;
01420 }
01421
01422 if ( _trace ) {
01423 char buffer[FB_EDGE_TYPE_NAME_LENGTH];
01424 FB_EDGE_TYPE_sprintf( buffer, type );
01425
01426 fprintf( TFile, "FEEDBACK::Annot(0x%p, %s) = ", wn, buffer );
01427 freq.Print( TFile );
01428 fprintf( TFile, "\n" );
01429 Print_with_wn( TFile, wn );
01430 }
01431 }
01432
01433
01434
01435
01436
01437
01438
01439
01440
01441
01442
01443
01444
01445
01446
01447
01448
01449
01450
01451
01452
01453
01454
01455
01456
01457
01458
01459
01460
01461
01462
01463
01464
01465
01466
01467
01468
01469
01470
01471 void
01472 FEEDBACK::FB_lower_branch( WN *wn_br, WN *wn_branch )
01473 {
01474 if ( _trace )
01475 fprintf( TFile, "FEEDBACK::FB_lower_branch(0x%p, 0x%p):\n",
01476 wn_br, wn_branch );
01477
01478 Is_True( wn_br != NULL,
01479 ( "FEEDBACK::FB_lower_branch expects non-NULL wn_branch" ) );
01480
01481
01482 OPERATOR opr = WN_operator( wn_br );
01483 Is_True( opr == OPR_IF || opr == OPR_CSELECT,
01484 ( "FEEDBACK::FB_lower_branch expects IF or CSELECT wn_br" ) );
01485
01486 if ( wn_branch != NULL ) {
01487 const FB_Info_Branch& info_branch = Query_branch( wn_br );
01488 Annot_branch( wn_branch, FB_Info_Branch( info_branch.freq_taken,
01489 info_branch.freq_not_taken,
01490 WN_operator( wn_branch ) ) );
01491 }
01492
01493 Delete( wn_br );
01494 }
01495
01496
01497
01498
01499
01500 void
01501 FEEDBACK::FB_lower_circuit( WN *wn_circuit, WN *wn_left_br, WN *wn_right_br )
01502 {
01503 if ( _trace )
01504 fprintf( TFile, "FEEDBACK::FB_lower_circuit(0x%p, 0x%p, 0x%p):\n",
01505 wn_circuit, wn_left_br, wn_right_br );
01506
01507 Is_True( wn_circuit != NULL,
01508 ( "FEEDBACK::FB_lower_circuit expects non-NULL wn_circuit" ) );
01509
01510
01511 OPERATOR opr = WN_operator( wn_circuit );
01512 Is_True( opr == OPR_CAND || opr == OPR_CIOR,
01513 ( "FEEDBACK::FB_lower_cand expects CAND wn_circuit" ) );
01514 const FB_Info_Circuit& info_circuit = Query_circuit( wn_circuit );
01515
01516
01517 FB_Info_Branch fb_info_branch;
01518 if ( wn_left_br != NULL ) {
01519 FB_FREQ freq_tkn = info_circuit.freq_left;
01520 FB_FREQ freq_not = info_circuit.freq_right + info_circuit.freq_neither;
01521 OPERATOR opr_br = WN_operator( wn_left_br );
01522 if ( opr == OPR_CAND )
01523 fb_info_branch = FB_Info_Branch( freq_not, freq_tkn, opr_br );
01524 else
01525 fb_info_branch = FB_Info_Branch( freq_tkn, freq_not, opr_br );
01526 Annot_branch( wn_left_br, fb_info_branch );
01527 }
01528
01529
01530 if ( wn_right_br != NULL ) {
01531 FB_FREQ freq_tkn = info_circuit.freq_right;
01532 FB_FREQ freq_not = info_circuit.freq_neither;
01533 OPERATOR opr_br = WN_operator( wn_right_br );
01534 if ( opr == OPR_CAND )
01535 fb_info_branch = FB_Info_Branch( freq_not, freq_tkn, opr_br );
01536 else
01537 fb_info_branch = FB_Info_Branch( freq_tkn, freq_not, opr_br );
01538 Annot_branch( wn_right_br, fb_info_branch );
01539 }
01540
01541 Delete( wn_circuit );
01542 }
01543
01544
01545
01546
01547 void
01548 FEEDBACK::FB_factor_circuit( WN *wn_left, WN *wn_right,
01549 WN *wn_outer, WN *wn_inner )
01550 {
01551 if ( _trace )
01552 fprintf( TFile, "FEEDBACK::FB_factor_circuit(0x%p, 0x%p, 0x%p, 0x%p):\n",
01553 wn_left, wn_right, wn_outer, wn_inner );
01554
01555
01556 const FB_Info_Circuit& info_left = Query_circuit( wn_left );
01557 const FB_Info_Circuit& info_right = Query_circuit( wn_right );
01558
01559
01560 Annot_circuit( wn_outer, FB_Info_Circuit( info_left.freq_left,
01561 info_right.freq_right,
01562 info_left.freq_neither
01563 + info_right.freq_neither ) );
01564 Annot_circuit( wn_inner, FB_Info_Circuit( info_left.freq_neither,
01565 info_right.freq_neither,
01566 info_right.freq_right ) );
01567 Delete( wn_left );
01568 Delete( wn_right );
01569 }
01570
01571
01572
01573
01574
01575
01576
01577
01578
01579
01580
01581
01582
01583
01584
01585
01586
01587
01588
01589
01590
01591
01592
01593
01594
01595
01596
01597
01598
01599 void
01600 FEEDBACK::FB_lower_loop( WN *wn_loop, WN *wn_top_br, WN *wn_back_br )
01601 {
01602 if ( _trace )
01603 fprintf( TFile, "FEEDBACK::FB_lower_loop(0x%p, 0x%p, 0x%p):\n",
01604 wn_loop, wn_top_br, wn_back_br );
01605
01606 Is_True( wn_loop != NULL,
01607 ( "FEEDBACK::FB_lower_loop expects non-NULL wn_loop" ) );
01608
01609
01610 Is_True( FB_valid_opr_loop( wn_loop ),
01611 ( "FEEDBACK::FB_lower_loop expects loop WHIRL operator" ) );
01612 const FB_Info_Loop& info_loop = Query_loop( wn_loop );
01613 if ( WN_operator( wn_loop ) == OPR_DO_WHILE && ! info_loop.freq_zero.Zero() )
01614 DevWarn( "FEEDBACK::FB_lower_loop found freq_zero == %f",
01615 info_loop.freq_zero.Value() );
01616
01617
01618 if ( wn_top_br != NULL )
01619 Annot_branch( wn_top_br, FB_Info_Branch( info_loop.freq_positive,
01620 info_loop.freq_zero,
01621 WN_operator( wn_top_br ) ) );
01622
01623
01624 if ( wn_back_br != NULL ) {
01625 if ( WN_operator( wn_back_br ) == OPR_GOTO )
01626 Annot_invoke( wn_back_br, FB_Info_Invoke( info_loop.freq_back ) );
01627 else
01628 Annot_branch( wn_back_br, FB_Info_Branch( info_loop.freq_back,
01629 info_loop.freq_out,
01630 WN_operator( wn_back_br ) ) );
01631 }
01632
01633
01634 }
01635
01636
01637
01638
01639
01640
01641
01642 void
01643 FEEDBACK::FB_lower_loop_alt ( WN *wn_loop, WN *wn_top_br )
01644 {
01645 if ( _trace )
01646 fprintf( TFile, "FEEDBACK::FB_lower_loop_alt(0x%p, 0x%p):\n",
01647 wn_loop, wn_top_br );
01648
01649 Is_True( wn_loop != NULL,
01650 ( "FEEDBACK::FB_lower_loop_alt expects non-NULL wn_loop" ) );
01651
01652
01653 OPERATOR opr = WN_operator( wn_loop );
01654 Is_True( opr == OPR_WHILE_DO || opr == OPR_DO_LOOP,
01655 ( "FEEDBACK::FB_lower_loop_alt expects"
01656 " WHILE_DO or DO_LOOP wn_loop" ) );
01657 const FB_Info_Loop& info_loop = Query_loop( wn_loop );
01658
01659
01660 if ( wn_top_br != NULL )
01661 Annot_branch( wn_top_br, FB_Info_Branch( info_loop.freq_iterate,
01662 info_loop.freq_exit,
01663 WN_operator( wn_top_br ) ) );
01664
01665
01666 }
01667
01668
01669
01670
01671
01672
01673
01674
01675
01676
01677
01678
01679
01680 void
01681 FEEDBACK::FB_lower_while_do_to_do_while ( WN *wn_loop, WN *wn_top_br )
01682 {
01683
01684 if ( _trace )
01685 fprintf( TFile, "FEEDBACK::FB_lower_while_do(0x%p, 0x%p):\n",
01686 wn_loop, wn_top_br );
01687
01688 Is_True( wn_loop != NULL,
01689 ( "FEEDBACK::FB_lower_while_do expects non-NULL wn_loop" ) );
01690
01691
01692 OPERATOR opr = WN_operator( wn_loop );
01693 Is_True( opr == OPR_WHILE_DO, ( "FEEDBACK::FB_lower_while_do_to_do_while"
01694 " expects WHILE_DO wn_loop" ) );
01695 const FB_Info_Loop& info_loop = Query_loop( wn_loop );
01696
01697
01698 if ( wn_top_br != NULL )
01699 Annot_branch( wn_top_br, FB_Info_Branch( info_loop.freq_positive,
01700 info_loop.freq_zero,
01701 WN_operator( wn_top_br ) ) );
01702
01703
01704 Annot( wn_loop, FB_EDGE_LOOP_ZERO, FB_FREQ_ZERO );
01705 }
01706
01707
01708
01709
01710
01711
01712 void
01713 FEEDBACK::FB_lower_compgoto ( WN *wn_compgoto, WN *wn_xgoto, WN *wn_branch )
01714 {
01715 if ( _trace )
01716 fprintf( TFile, "FEEDBACK::FB_lower_compgoto(0x%p, 0x%p, 0x%p):\n",
01717 wn_compgoto, wn_xgoto, wn_branch );
01718
01719 Is_True( wn_compgoto != NULL,
01720 ( "FEEDBACK::FB_lower_compgoto expects non-NULL wn_compgoto" ) );
01721
01722
01723 OPERATOR opr = WN_operator( wn_compgoto );
01724 Is_True( opr == OPR_COMPGOTO, ( "FEEDBACK::FB_lower_compgoto"
01725 " expects COMPGOTO compgoto" ) );
01726 FB_Info_Switch info_switch = Query_switch( wn_compgoto );
01727
01728
01729 FB_FREQ freq_default = ( WN_kid_count( wn_compgoto ) == 3
01730 ? info_switch[0] : FB_FREQ_UNINIT );
01731 info_switch[0] = FB_FREQ_ZERO;
01732
01733
01734 if ( wn_branch != NULL )
01735 Annot_branch( wn_branch, FB_Info_Branch( freq_default, info_switch.Total(),
01736 WN_operator( wn_branch ) ) );
01737
01738
01739 Annot_switch( wn_xgoto, info_switch );
01740
01741 Delete( wn_compgoto );
01742 }
01743
01744
01745
01746
01747
01748
01749
01750 void
01751 FEEDBACK::FB_lower_call( WN *wn_call, WN *wn_new_call )
01752 {
01753 if ( _trace )
01754 fprintf( TFile, "FEEDBACK::FB_lower_call(0x%p, 0x%p):\n",
01755 wn_call, wn_new_call );
01756
01757 Is_True( wn_call != NULL,
01758 ( "FEEDBACK::FB_lower_call expects non-NULL wn_call" ) );
01759
01760 Is_True( FB_valid_opr_call( wn_call ),
01761 ( "FEEDBACK::FB_lower_call encounted unexpected operator" ) );
01762 FB_Info_Call info_call = Query_call( wn_call );
01763
01764 if ( ! info_call.in_out_same )
01765 info_call.freq_entry = FB_FREQ_UNKNOWN;
01766
01767 Is_True( FB_valid_opr_call( wn_new_call ),
01768 ( "FEEDBACK::FB_lower_call encounted unexpected operator" ) );
01769 Annot_call( wn_new_call, info_call );
01770
01771 if ( wn_call != wn_new_call )
01772 Delete( wn_call );
01773 }
01774
01775 void
01776 FEEDBACK::FB_lower_icall( WN *wn_icall, WN *wn_new_icall, WN * wn_new_call, WN * wn_new_if )
01777 {
01778 if ( _trace )
01779 fprintf( TFile, "FEEDBACK::FB_lower_icall(0x%p, 0x%p, 0x%p, 0x%p):\n",
01780 wn_icall, wn_new_icall, wn_new_call, wn_new_if );
01781
01782 Is_True( wn_icall != NULL,
01783 ( "FEEDBACK::FB_lower_icall expects non-NULL wn_icall" ) );
01784
01785 Is_True( FB_valid_opr_call( wn_icall ),
01786 ( "FEEDBACK::FB_lower_icall encounted unexpected operator" ) );
01787 FB_Info_Call info_call = Query_call( wn_icall );
01788 FB_Info_Icall info_icall = Query_icall( wn_icall );
01789
01790 Is_True( info_call.freq_entry._value >= (float) info_icall.tnv._counters[0],
01791 ("entry count of icall less than counter[0]! impossible!") );
01792
01793 FB_FREQ freq_taken((float)info_icall.tnv._counters[0],true);
01794 FB_FREQ freq_nottaken(info_call.freq_entry._value-(float)info_icall.tnv._counters[0],true);
01795
01796 Is_True( FB_valid_opr_branch(wn_new_if),
01797 ("FEEDBACK::FB_lower_icall encounted unexpected operator") );
01798 Annot_branch(wn_new_if, FB_Info_Branch(freq_taken,freq_nottaken));
01799 Is_True( FB_valid_opr_call( wn_new_icall ),
01800 ( "FEEDBACK::FB_lower_icall encounted unexpected operator" ) );
01801
01802 if ( ! info_call.in_out_same )
01803 {
01804 Annot_call( wn_new_call, FB_Info_Call(freq_taken,FB_FREQ_UNKNOWN,false) );
01805 Annot_call( wn_new_icall, FB_Info_Call(freq_nottaken,FB_FREQ_UNKNOWN,false) );
01806 }
01807 else
01808 {
01809 Annot_call( wn_new_call, FB_Info_Call(freq_taken) );
01810 Annot_call( wn_new_icall, FB_Info_Call(freq_nottaken) );
01811 }
01812
01813 #ifdef KEY
01814 FB_Info_Icall info_new_icall = info_icall;
01815 const UINT64 taken = (UINT64)freq_taken.Value();
01816
01817 info_new_icall.tnv._exec_counter -= taken;
01818 info_new_icall.tnv._counters[0] -= taken;
01819
01820 info_new_icall.tnv._flag = FB_TNV_FLAG_UNINIT;
01821
01822 Annot_icall( wn_new_icall, info_new_icall );
01823 #endif
01824
01825 if ( wn_icall != wn_new_icall )
01826 Delete( wn_icall );
01827 }
01828
01829
01830
01831
01832
01833 void
01834 FEEDBACK::FB_lower_return_val( WN *wn_return_val, WN *wn_return )
01835 {
01836 if ( _trace )
01837 fprintf( TFile, "FEEDBACK::FB_lower_return_val(0x%p, 0x%p):\n",
01838 wn_return_val, wn_return );
01839
01840 Is_True( wn_return_val != NULL,
01841 ( "FEEDBACK::FB_lower_return_val expects non-NULL wn_cselect" ) );
01842
01843 OPERATOR opr = WN_operator( wn_return_val );
01844 Is_True( opr == OPR_RETURN_VAL, ( "FEEDBACK::FB_lower_return_val"
01845 " expects RETURN_VAL wn_return_val" ) );
01846 const FB_Info_Invoke& info_invoke = Query_invoke( wn_return_val );
01847
01848 Annot_invoke( wn_return, info_invoke );
01849
01850 Delete( wn_return_val );
01851 }
01852
01853
01854
01855
01856 void
01857 FEEDBACK::FB_lower_mstore_to_loop ( WN *wn_mstore, WN *wn_loop, INT64 nMoves )
01858 {
01859 if ( _trace )
01860 fprintf( TFile, "FEEDBACK::lower_mstore_to_loop(0x%p, 0x%p, %lld):\n",
01861 wn_mstore, wn_loop, nMoves );
01862
01863 Is_True( wn_mstore != NULL, ( "FEEDBACK::FB_lower_mstore_to_loop"
01864 " expects non-NULL wn_mstore" ) );
01865
01866 Is_True( WN_operator( wn_mstore ) == OPR_MSTORE,
01867 ( "FEEDBACK::FB_lower_mstore_to_loop expects MSTORE" ) );
01868 const FB_Info_Invoke& info_invoke = Query_invoke( wn_mstore );
01869
01870 OPERATOR opr = WN_operator( wn_loop );
01871 FB_Info_Loop info_loop;
01872 if ( opr == OPR_DO_LOOP ) {
01873
01874
01875 Is_True( nMoves > 0, ( "FEEDBACK::lower_mstore_to_loop found"
01876 " non-positive nMoves == %lld", nMoves ) );
01877 info_loop = FB_Info_Loop( FB_FREQ_ZERO,
01878 info_invoke.freq_invoke,
01879 info_invoke.freq_invoke,
01880 FB_FREQ( nMoves - 1, true )
01881 * info_invoke.freq_invoke );
01882 } else {
01883
01884
01885 Is_True( opr == OPR_WHILE_DO, ( "FEEDBACK::FB_lower_mstore_to_loop"
01886 " expects DO_LOOP or WHILE_DO" ) );
01887 info_loop = FB_Info_Loop( info_invoke.freq_invoke, FB_FREQ_UNKNOWN );
01888
01889 }
01890
01891 Annot_loop( wn_loop, info_loop );
01892
01893 Delete( wn_mstore );
01894 }
01895
01896
01897
01898
01899
01900
01901
01902
01903
01904
01905
01906
01907
01908
01909
01910
01911
01912
01913 void
01914 FEEDBACK::FB_move_goto_out( WN *wn_branch, WN *wn_inner_br, WN *wn_outer_br )
01915 {
01916 if ( _trace )
01917 fprintf( TFile, "FEEDBACK::FB_move_goto_out(0x%p, 0x%p, 0x%p):\n",
01918 wn_branch, wn_inner_br, wn_outer_br );
01919
01920 Is_True( wn_branch != NULL,
01921 ( "FEEDBACK::FB_move_goto_out expects non-NULL wn_branch" ) );
01922
01923
01924 FB_FREQ freq_taken, freq_not;
01925 OPERATOR opr = WN_operator( wn_branch );
01926 if ( opr == OPR_GOTO ) {
01927 const FB_Info_Invoke& info_invoke = Query_invoke( wn_branch );
01928 freq_taken = info_invoke.freq_invoke;
01929 freq_not = FB_FREQ_ZERO;
01930 } else {
01931 Is_True( opr == OPR_TRUEBR || opr == OPR_FALSEBR,
01932 ( "FEEDBACK::FB_move_goto_out expects TRUE/FALSEBR wn_branch" ) );
01933 const FB_Info_Branch& info_branch = Query_branch( wn_branch );
01934 freq_taken = info_branch.freq_taken;
01935 freq_not = info_branch.freq_not_taken;
01936 }
01937
01938
01939 if ( wn_inner_br != NULL ) {
01940 opr = WN_operator( wn_inner_br );
01941 Is_True( opr == OPR_IF,
01942 ( "FEEDBACK::FB_move_goto_out expects NULL or IF wn_inner_br" ) );
01943 Annot_branch( wn_inner_br, FB_Info_Branch( freq_not, freq_taken ) );
01944 }
01945
01946
01947 opr = WN_operator( wn_outer_br );
01948 Is_True( opr == OPR_TRUEBR,
01949 ( "FEEDBACK::FB_move_goto_out expects TRUEBR wn_outer_br" ) );
01950 Annot_branch( wn_outer_br, FB_Info_Branch( freq_taken, FB_FREQ_UNKNOWN ) );
01951
01952 Delete( wn_branch );
01953 }
01954
01955
01956
01957
01958
01959
01960
01961 void
01962 FEEDBACK::FB_convert_goto_to_if( WN *wn_branch, WN *wn_if )
01963 {
01964 if ( _trace )
01965 fprintf( TFile, "FEEDBACK::FB_convert_goto_to_if(0x%p, 0x%p):\n",
01966 wn_branch, wn_if );
01967
01968 Is_True( wn_branch != NULL,
01969 ( "FEEDBACK::FB_convert_goto_to_if expects non-NULL wn_branch" ) );
01970
01971
01972 OPERATOR opr = WN_operator( wn_branch );
01973 Is_True( opr == OPR_TRUEBR || opr == OPR_FALSEBR,
01974 ( "FEEDBACK::FB_convert_goto_to_if"
01975 " expects TRUE/FALSEBR wn_branch" ) );
01976 const FB_Info_Branch& info_branch = Query_branch( wn_branch );
01977
01978
01979 opr = WN_operator( wn_if );
01980 Is_True( opr == OPR_IF,
01981 ( "FEEDBACK::FB_convert_goto_to_if expects IF wn_if" ) );
01982 Annot_branch( wn_if, FB_Info_Branch( info_branch.freq_not_taken,
01983 info_branch.freq_taken ) );
01984
01985 Delete( wn_branch );
01986 }
01987
01988
01989
01990
01991
01992
01993
01994 void
01995 FEEDBACK::FB_convert_goto_to_loop( WN *wn_branch, WN *wn_loop )
01996 {
01997 if ( _trace )
01998 fprintf( TFile, "FEEDBACK::FB_convert_goto_to_loop(0x%p, 0x%p):\n",
01999 wn_branch, wn_loop );
02000
02001 Is_True( wn_branch != NULL, ( "FEEDBACK::FB_convert_goto_to_loop"
02002 " expects non-NULL wn_branch" ) );
02003
02004
02005 OPERATOR opr = WN_operator( wn_branch );
02006 Is_True( opr == OPR_GOTO || opr == OPR_TRUEBR || opr == OPR_FALSEBR,
02007 ( "FEEDBACK::FB_convert_goto_to_loop"
02008 " expects GOTO, TRUEBR or FALSEBR wn_branch" ) );
02009
02010 FB_FREQ freq_taken, freq_not_taken;
02011 if ( opr == OPR_GOTO ) {
02012 const FB_Info_Invoke& info_invoke = Query_invoke( wn_branch );
02013 freq_taken = info_invoke.freq_invoke;
02014 freq_not_taken = FB_FREQ_ZERO;
02015 } else {
02016 const FB_Info_Branch& info_branch = Query_branch( wn_branch );
02017 freq_taken = info_branch.freq_taken;
02018 freq_not_taken = info_branch.freq_not_taken;
02019 }
02020
02021
02022 opr = WN_operator( wn_loop );
02023 Is_True( opr == OPR_DO_WHILE,
02024 ( "FEEDBACK::FB_convert_goto_to_loop expects DO_WHILE wn_loop" ) );
02025 Annot_loop( wn_loop, FB_Info_Loop( FB_FREQ_ZERO, FB_FREQ_UNKNOWN,
02026 freq_not_taken, freq_taken ) );
02027
02028 Delete( wn_branch );
02029 }
02030
02031
02032
02033
02034
02035
02036 void
02037 FEEDBACK::FB_simplify_branch_to_goto( WN *wn_branch )
02038 {
02039 if ( _trace )
02040 fprintf( TFile, "FEEDBACK::FB_simplify_branch_to_goto(0x%p):\n",
02041 wn_branch );
02042
02043 Is_True( wn_branch != NULL, ( "FEEDBACK::FB_simplify_branch_to_goto"
02044 " expects non-NULL wn_branch" ) );
02045 OPERATOR opr = WN_operator( wn_branch );
02046 Is_True( opr == OPR_GOTO, ( "FEEDBACK::FB_simplify_branch_to_goto"
02047 " expects GOTO wn_branch" ) );
02048
02049
02050 WN_set_operator( wn_branch, OPR_TRUEBR );
02051 const FB_Info_Branch& info_branch = Query_branch( wn_branch );
02052 WN_set_operator( wn_branch, OPR_GOTO );
02053
02054 Delete( wn_branch );
02055
02056 if ( info_branch.freq_not_taken.Known()
02057 && ! info_branch.freq_not_taken.Zero() ) {
02058 DevWarn( "FEEDBACK::FB_simplify_branch_to_goto: nonzero freq_not_taken" );
02059 }
02060
02061
02062 Annot_invoke( wn_branch, FB_Info_Invoke( info_branch.freq_taken ) );
02063 }
02064
02065
02066
02067
02068
02069
02070 void
02071 FEEDBACK::FB_set_zero_node( WN *wn )
02072 {
02073 switch( WN_operator( wn ) ) {
02074
02075 case OPR_PRAGMA:
02076 if ( WN_pragma( wn ) != WN_PRAGMA_PREAMBLE_END )
02077 break;
02078
02079
02080 fb_opr_cases_invoke:
02081 {
02082 FB_Info_Invoke fb_info( FB_FREQ_ZERO );
02083 Annot_invoke( wn, fb_info );
02084 }
02085 break;
02086
02087 fb_opr_cases_branch:
02088 {
02089 FB_Info_Branch fb_info( FB_FREQ_ZERO, FB_FREQ_ZERO );
02090 Annot_branch( wn, fb_info );
02091 }
02092 break;
02093
02094 fb_opr_cases_loop:
02095 {
02096 FB_Info_Loop fb_info( FB_FREQ_ZERO, FB_FREQ_ZERO, FB_FREQ_ZERO,
02097 FB_FREQ_ZERO, FB_FREQ_ZERO, FB_FREQ_ZERO );
02098 Annot_loop( wn, fb_info );
02099 }
02100 break;
02101
02102 fb_opr_cases_circuit:
02103 {
02104 FB_Info_Circuit fb_info( FB_FREQ_ZERO, FB_FREQ_ZERO, FB_FREQ_ZERO );
02105 Annot_circuit( wn, fb_info );
02106 }
02107 break;
02108
02109 fb_opr_cases_call:
02110 {
02111 FB_Info_Call fb_info( FB_FREQ_ZERO );
02112 Annot_call( wn, fb_info );
02113 #ifdef KEY
02114 if( WN_operator(wn) == OPR_ICALL ){
02115 FB_Info_Icall fb_icall_info;
02116 Annot_icall( wn, fb_icall_info );
02117 }
02118 #endif
02119 }
02120 break;
02121
02122 fb_opr_cases_switch:
02123 {
02124
02125 INT32 number_cases = ( WN_kid_count(wn) == 3 ) ? 1 : 0;
02126 for ( WN *wn1 = WN_first( WN_kid1( wn ) ); wn1; wn1 = WN_next( wn1 ) )
02127 ++number_cases;
02128
02129 FB_Info_Switch fb_info( number_cases );
02130 for (INT32 t = number_cases - 1; t >= 0; --t ) {
02131 fb_info[t] = FB_FREQ_ZERO;
02132 }
02133 Annot_switch( wn, fb_info );
02134 }
02135 break;
02136
02137 #ifdef KEY
02138 fb_opr_cases_value:
02139 if( IS_VALID_DIV_VALUE( wn ) ){
02140 FB_Info_Value fb_info( 0, 0, NULL, NULL );
02141 Annot_value( wn, fb_info );
02142 }
02143 break;
02144
02145 fb_opr_cases_value_fp_bin:
02146 if( IS_VALID_MPY_VALUE( wn ) ){
02147 FB_Info_Value_FP_Bin fb_info( 0, 0, 0, 0, 0 );
02148 Annot_value_fp_bin( wn, fb_info );
02149 break;
02150 }
02151 break;
02152 #endif
02153
02154 default:
02155 break;
02156 }
02157 }
02158
02159
02160 void
02161 FEEDBACK::FB_set_zero( WN *wn )
02162 {
02163 if ( _trace )
02164 fprintf( TFile, "FEEDBACK::FB_set_zero(0x%p):\n", wn );
02165
02166 for ( TREE_ITER iter( wn ); iter.Wn() != NULL; ++iter ) {
02167
02168
02169 FB_set_zero_node( iter.Wn() );
02170 }
02171 }
02172
02173 void
02174 FEEDBACK::FB_set_unknown_node( WN *wn )
02175 {
02176 switch( WN_operator( wn ) ) {
02177
02178 case OPR_PRAGMA:
02179 if ( WN_pragma( wn ) != WN_PRAGMA_PREAMBLE_END )
02180 break;
02181
02182
02183 fb_opr_cases_invoke:
02184 {
02185 FB_Info_Invoke fb_info( FB_FREQ_UNKNOWN );
02186 Annot_invoke( wn, fb_info );
02187 }
02188 break;
02189
02190 fb_opr_cases_branch:
02191 {
02192 FB_Info_Branch fb_info( FB_FREQ_UNKNOWN, FB_FREQ_UNKNOWN );
02193 Annot_branch( wn, fb_info );
02194 }
02195 break;
02196
02197 fb_opr_cases_loop:
02198 {
02199 FB_Info_Loop fb_info( FB_FREQ_UNKNOWN, FB_FREQ_UNKNOWN,
02200 FB_FREQ_UNKNOWN, FB_FREQ_UNKNOWN,
02201 FB_FREQ_UNKNOWN, FB_FREQ_UNKNOWN );
02202 Annot_loop( wn, fb_info );
02203 }
02204 break;
02205
02206 fb_opr_cases_circuit:
02207 {
02208 FB_Info_Circuit fb_info( FB_FREQ_UNKNOWN,
02209 FB_FREQ_UNKNOWN, FB_FREQ_UNKNOWN );
02210 Annot_circuit( wn, fb_info );
02211 }
02212 break;
02213
02214 fb_opr_cases_call:
02215 {
02216 FB_Info_Call fb_info( FB_FREQ_UNKNOWN, FB_FREQ_UNKNOWN );
02217 Annot_call( wn, fb_info );
02218 #ifdef KEY
02219 if( WN_operator(wn) == OPR_ICALL ){
02220 FB_Info_Icall fb_icall_info;
02221 Annot_icall( wn, fb_icall_info );
02222 }
02223 #endif
02224 }
02225 break;
02226
02227 fb_opr_cases_switch:
02228 {
02229
02230 INT32 number_cases = ( WN_kid_count(wn) == 3 ) ? 1 : 0;;
02231 for ( WN *wn1 = WN_first( WN_kid1( wn ) ); wn1; wn1 = WN_next( wn1 ) )
02232 ++number_cases;
02233
02234 FB_Info_Switch fb_info( number_cases );
02235 for (INT32 t = number_cases - 1; t >= 0; --t ) {
02236 fb_info[t] = FB_FREQ_UNKNOWN;
02237 }
02238 Annot_switch( wn, fb_info );
02239 }
02240 break;
02241
02242 #ifdef KEY
02243 fb_opr_cases_value:
02244 if( IS_VALID_DIV_VALUE( wn ) ){
02245 FB_Info_Value fb_info( 0, 0, NULL, NULL );
02246 Annot_value( wn, fb_info );
02247 }
02248 break;
02249
02250 fb_opr_cases_value_fp_bin:
02251 if( IS_VALID_MPY_VALUE( wn ) ){
02252 FB_Info_Value_FP_Bin fb_info( 0, 0, 0, 0, 0 );
02253 Annot_value_fp_bin( wn, fb_info );
02254 }
02255 break;
02256 #endif
02257
02258 default:
02259 break;
02260 }
02261 }
02262
02263
02264 void
02265 FEEDBACK::FB_set_unknown( WN *wn )
02266 {
02267 if ( _trace )
02268 fprintf( TFile, "FEEDBACK::FB_set_unknown(0x%p):\n", wn );
02269
02270 for ( TREE_ITER iter( wn ); iter.Wn() != NULL; ++iter ) {
02271
02272
02273 FB_set_unknown_node( iter.Wn() );
02274 }
02275 }
02276
02277
02278 void
02279 FEEDBACK::FB_scale_node( WN *wn, FB_FREQ freq_scale )
02280 {
02281
02282
02283
02284
02285
02286
02287 switch( WN_operator( wn ) ) {
02288
02289 case OPR_PRAGMA:
02290 if ( WN_pragma( wn ) != WN_PRAGMA_PREAMBLE_END )
02291 break;
02292
02293
02294 fb_opr_cases_invoke:
02295 {
02296 FB_Info_Invoke fb_info = Query_invoke( wn );
02297 fb_info.freq_invoke *= freq_scale;
02298 Annot_invoke( wn, fb_info );
02299 }
02300 break;
02301
02302 fb_opr_cases_branch:
02303 {
02304 FB_Info_Branch fb_info = Query_branch( wn );
02305 fb_info.freq_taken *= freq_scale;
02306 fb_info.freq_not_taken *= freq_scale;
02307 Annot_branch( wn, fb_info );
02308 }
02309 break;
02310
02311 fb_opr_cases_loop:
02312 {
02313 FB_Info_Loop fb_info = Query_loop( wn );
02314 fb_info.freq_zero *= freq_scale;
02315 fb_info.freq_positive *= freq_scale;
02316 fb_info.freq_out *= freq_scale;
02317 fb_info.freq_back *= freq_scale;
02318 fb_info.freq_exit *= freq_scale;
02319 fb_info.freq_iterate *= freq_scale;
02320 Annot_loop( wn, fb_info );
02321 }
02322 break;
02323
02324 fb_opr_cases_circuit:
02325 {
02326 FB_Info_Circuit fb_info = Query_circuit( wn );
02327 fb_info.freq_left *= freq_scale;
02328 fb_info.freq_right *= freq_scale;
02329 fb_info.freq_neither *= freq_scale;
02330 Annot_circuit( wn, fb_info );
02331 }
02332 break;
02333
02334 fb_opr_cases_call:
02335 {
02336 FB_Info_Call fb_info = Query_call( wn );
02337 fb_info.freq_entry *= freq_scale;
02338 fb_info.freq_exit *= freq_scale;
02339 Annot_call( wn, fb_info );
02340 #ifdef KEY
02341 if( WN_operator(wn) == OPR_ICALL ){
02342 FB_Info_Icall fb_icall_info = Query_icall( wn );
02343 const float scale = freq_scale.Value();
02344 fb_icall_info.tnv._exec_counter =
02345 (UINT64)(fb_icall_info.tnv._exec_counter * scale);
02346
02347 for( int i = 0; i < FB_TNV_SIZE; i ++ ){
02348 if( fb_icall_info.tnv._values[i] == 0 )
02349 break;
02350 fb_icall_info.tnv._counters[i] =
02351 (UINT64)(fb_icall_info.tnv._counters[i] * scale);
02352 }
02353
02354 Annot_icall( wn, fb_icall_info );
02355 }
02356 #endif
02357 }
02358 break;
02359
02360 fb_opr_cases_switch:
02361 {
02362 FB_Info_Switch fb_info = Query_switch( wn );
02363 for ( INT t = fb_info.size() - 1; t >= 0; t-- )
02364 fb_info[t] *= freq_scale;
02365 Annot_switch( wn, fb_info );
02366 }
02367 break;
02368
02369 #ifdef KEY
02370 fb_opr_cases_value:
02371 if( IS_VALID_DIV_VALUE( wn ) ){
02372 FB_Info_Value fb_info = Query_value( wn );
02373 fb_info.exe_counter *= freq_scale;
02374 for( int i = 0; i < fb_info.num_values; i++ ){
02375 fb_info.freq[i] *= freq_scale;
02376 }
02377 Annot_value( wn, fb_info );
02378 }
02379 break;
02380
02381 fb_opr_cases_value_fp_bin:
02382 if( IS_VALID_MPY_VALUE( wn ) ){
02383 FB_Info_Value_FP_Bin fb_info = Query_value_fp_bin( wn );
02384 fb_info.exe_counter *= freq_scale;
02385 fb_info.zopnd0 *= freq_scale;
02386 fb_info.zopnd1 *= freq_scale;
02387 fb_info.uopnd0 *= freq_scale;
02388 fb_info.uopnd1 *= freq_scale;
02389 Annot_value_fp_bin( wn, fb_info );
02390 }
02391 break;
02392 #endif
02393
02394 default:
02395 break;
02396 }
02397 }
02398
02399
02400 void
02401 FEEDBACK::FB_scale( WN *wn, FB_FREQ freq_scale )
02402 {
02403 if ( _trace ) {
02404 fprintf( TFile, "FEEDBACK::FB_scale(0x%p, ", wn );
02405 freq_scale.Print( TFile );
02406 fprintf( TFile, "):\n" );
02407 }
02408
02409 for ( TREE_ITER iter( wn ); iter.Wn() != NULL; ++iter ) {
02410
02411
02412 FB_scale_node( iter.Wn(), freq_scale );
02413 }
02414 }
02415
02416
02417 void
02418 FEEDBACK::FB_duplicate_node( WN *wn_origl, WN *wn_dupli )
02419 {
02420
02421 switch( WN_operator( wn_origl ) ) {
02422
02423 case OPR_PRAGMA:
02424 if ( WN_pragma( wn_origl ) != WN_PRAGMA_PREAMBLE_END )
02425 break;
02426
02427
02428 fb_opr_cases_invoke:
02429 {
02430 const FB_Info_Invoke& fb_info = Query_invoke( wn_origl );
02431 Annot_invoke( wn_dupli, fb_info );
02432 }
02433 break;
02434
02435 fb_opr_cases_branch:
02436 {
02437 const FB_Info_Branch& fb_info = Query_branch( wn_origl );
02438 Annot_branch( wn_dupli, fb_info );
02439 }
02440 break;
02441
02442 fb_opr_cases_loop:
02443 {
02444 const FB_Info_Loop& fb_info = Query_loop( wn_origl );
02445 Annot_loop( wn_dupli, fb_info );
02446 }
02447 break;
02448
02449 fb_opr_cases_circuit:
02450 {
02451 const FB_Info_Circuit& fb_info = Query_circuit( wn_origl );
02452 Annot_circuit( wn_dupli, fb_info );
02453 }
02454 break;
02455
02456 fb_opr_cases_call:
02457 {
02458 const FB_Info_Call& fb_info = Query_call( wn_origl );
02459 Annot_call( wn_dupli, fb_info );
02460 #ifdef KEY
02461 if( WN_operator(wn_origl) == OPR_ICALL ){
02462 FB_Info_Icall fb_icall_info = Query_icall( wn_origl );
02463 Annot_icall( wn_dupli, fb_icall_info );
02464 }
02465 #endif
02466 }
02467 break;
02468
02469 fb_opr_cases_switch:
02470 {
02471 const FB_Info_Switch& fb_info = Query_switch( wn_origl );
02472 Annot_switch( wn_dupli, fb_info );
02473 }
02474 break;
02475
02476 #ifdef KEY
02477 fb_opr_cases_value:
02478 if( IS_VALID_DIV_VALUE( wn_origl ) ){
02479 const FB_Info_Value& fb_info = Query_value( wn_origl );
02480 Annot_value( wn_dupli, fb_info );
02481 }
02482 break;
02483
02484 fb_opr_cases_value_fp_bin:
02485 if( IS_VALID_MPY_VALUE( wn_origl ) ){
02486 const FB_Info_Value_FP_Bin& fb_info = Query_value_fp_bin( wn_origl );
02487 Annot_value_fp_bin( wn_dupli, fb_info );
02488 }
02489 break;
02490 #endif
02491
02492 default:
02493 break;
02494 }
02495 }
02496
02497
02498 void
02499 FEEDBACK::FB_duplicate( WN *wn_origl, WN *wn_dupli )
02500 {
02501 if ( _trace )
02502 fprintf( TFile, "FEEDBACK::FB_duplicate(0x%p, 0x%p):\n",
02503 wn_origl, wn_dupli );
02504
02505 for ( TREE_ITER origl( wn_origl ), dupli( wn_dupli );
02506 origl.Wn() != NULL && dupli.Wn() != NULL;
02507 ++origl, ++dupli ) {
02508
02509
02510 FB_duplicate_node( origl.Wn(), dupli.Wn() );
02511 }
02512 }
02513
02514
02515 void
02516 FEEDBACK::FB_recombine_node( WN *wn_origl, WN *wn_extra )
02517 {
02518 switch( WN_operator( wn_origl ) ) {
02519
02520 case OPR_PRAGMA:
02521 if ( WN_pragma( wn_origl ) != WN_PRAGMA_PREAMBLE_END )
02522 break;
02523
02524
02525 fb_opr_cases_invoke:
02526 {
02527 FB_Info_Invoke fb_info_origl = Query_invoke( wn_origl );
02528 const FB_Info_Invoke& fb_info_extra = Query_invoke( wn_extra );
02529 fb_info_origl.freq_invoke += fb_info_extra.freq_invoke;
02530 Annot_invoke( wn_origl, fb_info_origl );
02531 Delete( wn_extra );
02532 }
02533 break;
02534
02535 fb_opr_cases_branch:
02536 {
02537 FB_Info_Branch fb_info_origl = Query_branch( wn_origl );
02538 const FB_Info_Branch& fb_info_extra = Query_branch( wn_extra );
02539 fb_info_origl.freq_taken += fb_info_extra.freq_taken ;
02540 fb_info_origl.freq_not_taken += fb_info_extra.freq_not_taken;
02541 Annot_branch( wn_origl, fb_info_origl );
02542 Delete( wn_extra );
02543 }
02544 break;
02545
02546 fb_opr_cases_loop:
02547 {
02548 FB_Info_Loop fb_info_origl = Query_loop( wn_origl );
02549 const FB_Info_Loop& fb_info_extra = Query_loop( wn_extra );
02550 fb_info_origl.freq_zero += fb_info_extra.freq_zero ;
02551 fb_info_origl.freq_positive += fb_info_extra.freq_positive;
02552 fb_info_origl.freq_out += fb_info_extra.freq_out ;
02553 fb_info_origl.freq_back += fb_info_extra.freq_back ;
02554 fb_info_origl.freq_exit += fb_info_extra.freq_exit ;
02555 fb_info_origl.freq_iterate += fb_info_extra.freq_iterate ;
02556 Annot_loop( wn_origl, fb_info_origl );
02557 Delete( wn_extra );
02558 }
02559 break;
02560
02561 fb_opr_cases_circuit:
02562 {
02563 FB_Info_Circuit fb_info_origl = Query_circuit( wn_origl );
02564 const FB_Info_Circuit& fb_info_extra = Query_circuit( wn_extra );
02565 fb_info_origl.freq_left += fb_info_extra.freq_left ;
02566 fb_info_origl.freq_right += fb_info_extra.freq_right ;
02567 fb_info_origl.freq_neither += fb_info_extra.freq_neither;
02568 Annot_circuit( wn_origl, fb_info_origl );
02569 Delete( wn_extra );
02570 }
02571 break;
02572
02573 fb_opr_cases_call:
02574 {
02575 FB_Info_Call fb_info_origl = Query_call( wn_origl );
02576 const FB_Info_Call& fb_info_extra = Query_call( wn_extra );
02577 fb_info_origl.freq_entry += fb_info_extra.freq_entry;
02578 fb_info_origl.freq_exit += fb_info_extra.freq_exit;
02579 Annot_call( wn_origl, fb_info_origl );
02580 #ifdef KEY
02581 if( WN_operator(wn_origl) == OPR_ICALL ){
02582 FB_Info_Icall fb_icall_info_origl = Query_icall( wn_origl );
02583 const FB_Info_Icall& fb_icall_info_extra = Query_icall( wn_extra );
02584 fb_icall_info_origl.tnv._exec_counter += fb_icall_info_extra.tnv._exec_counter;
02585
02586 for( int i = 0; i < FB_TNV_SIZE; i ++ ){
02587 if( fb_icall_info_origl.tnv._values[i] == 0 )
02588 break;
02589 fb_icall_info_origl.tnv._counters[i] += fb_icall_info_extra.tnv._counters[i];
02590 }
02591
02592 Annot_icall( wn_origl, fb_icall_info_origl );
02593 }
02594 #endif
02595 Delete( wn_extra );
02596 }
02597 break;
02598
02599 fb_opr_cases_switch:
02600 {
02601 FB_Info_Switch fb_info_origl = Query_switch( wn_origl );
02602 const FB_Info_Switch& fb_info_extra = Query_switch( wn_extra );
02603 for ( INT t = fb_info_origl.size() - 1; t >= 0; t-- )
02604 fb_info_origl[t] += fb_info_extra[t];
02605 Annot_switch( wn_origl, fb_info_origl );
02606 Delete( wn_extra );
02607 }
02608 break;
02609
02610 #ifdef KEY
02611 fb_opr_cases_value:
02612 if( IS_VALID_DIV_VALUE( wn_origl ) ){
02613 FB_Info_Value fb_info_origl = Query_value( wn_origl );
02614 const FB_Info_Value& fb_info_extra = Query_value( wn_extra );
02615
02616 fb_info_origl.exe_counter += fb_info_extra.exe_counter;
02617 for( int i = 0; i < fb_info_origl.num_values; i++ ){
02618 fb_info_origl.freq[i] += fb_info_extra.freq[i];
02619 }
02620
02621 Annot_value( wn_origl, fb_info_origl );
02622 Delete( wn_extra );
02623 }
02624 break;
02625
02626 fb_opr_cases_value_fp_bin:
02627 if( IS_VALID_MPY_VALUE( wn_origl ) ){
02628 FB_Info_Value_FP_Bin fb_info_origl = Query_value_fp_bin( wn_origl );
02629 const FB_Info_Value_FP_Bin& fb_info_extra =
02630 Query_value_fp_bin( wn_extra );
02631
02632 fb_info_origl.exe_counter += fb_info_extra.exe_counter;
02633 fb_info_origl.zopnd0 += fb_info_extra.zopnd0;
02634 fb_info_origl.zopnd1 += fb_info_extra.zopnd1;
02635 fb_info_origl.uopnd0 += fb_info_extra.uopnd0;
02636 fb_info_origl.uopnd1 += fb_info_extra.uopnd1;
02637
02638 Annot_value_fp_bin( wn_origl, fb_info_origl );
02639 Delete( wn_extra );
02640 }
02641 break;
02642 #endif
02643
02644 default:
02645 break;
02646 }
02647 }
02648
02649
02650 void
02651 FEEDBACK::FB_recombine( WN *wn_origl, WN *wn_extra )
02652 {
02653 if ( _trace )
02654 fprintf( TFile, "FEEDBACK::FB_recombine(0x%p, 0x%p):\n",
02655 wn_origl, wn_extra );
02656
02657 for ( TREE_ITER origl( wn_origl ), extra(wn_extra);
02658 origl.Wn() != NULL && extra.Wn() != NULL;
02659 ++origl, ++extra ) {
02660
02661
02662 FB_recombine_node( origl.Wn(), extra.Wn() );
02663 }
02664 }
02665
02666
02667 void
02668 FEEDBACK::FB_clone_node( WN *wn_origl, WN *wn_clone, FB_FREQ freq_scale )
02669 {
02670
02671
02672
02673
02674
02675
02676 switch( WN_operator( wn_origl ) ) {
02677
02678 case OPR_PRAGMA:
02679 if ( WN_pragma( wn_origl ) != WN_PRAGMA_PREAMBLE_END )
02680 break;
02681
02682
02683 fb_opr_cases_invoke:
02684 {
02685 FB_Info_Invoke fb_info_origl = Query_invoke( wn_origl );
02686 FB_Info_Invoke fb_info_clone( fb_info_origl.freq_invoke * freq_scale );
02687 fb_info_origl.freq_invoke -= fb_info_clone.freq_invoke;
02688 Annot_invoke( wn_origl, fb_info_origl );
02689 Annot_invoke( wn_clone, fb_info_clone );
02690 }
02691 break;
02692
02693 fb_opr_cases_branch:
02694 {
02695 FB_Info_Branch fb_info_origl = Query_branch( wn_origl );
02696 FB_Info_Branch fb_info_clone( fb_info_origl.freq_taken * freq_scale,
02697 fb_info_origl.freq_not_taken * freq_scale );
02698 fb_info_origl.freq_taken -= fb_info_clone.freq_taken ;
02699 fb_info_origl.freq_not_taken -= fb_info_clone.freq_not_taken;
02700 Annot_branch( wn_origl, fb_info_origl );
02701 Annot_branch( wn_clone, fb_info_clone );
02702 }
02703 break;
02704
02705 fb_opr_cases_loop:
02706 {
02707 FB_Info_Loop fb_info_origl = Query_loop( wn_origl );
02708 FB_Info_Loop fb_info_clone( fb_info_origl.freq_zero * freq_scale,
02709 fb_info_origl.freq_positive * freq_scale,
02710 fb_info_origl.freq_out * freq_scale,
02711 fb_info_origl.freq_back * freq_scale,
02712 fb_info_origl.freq_exit * freq_scale,
02713 fb_info_origl.freq_iterate * freq_scale );
02714 fb_info_origl.freq_zero -= fb_info_clone.freq_zero ;
02715 fb_info_origl.freq_positive -= fb_info_clone.freq_positive;
02716 fb_info_origl.freq_out -= fb_info_clone.freq_out ;
02717 fb_info_origl.freq_back -= fb_info_clone.freq_back ;
02718 fb_info_origl.freq_exit -= fb_info_clone.freq_exit ;
02719 fb_info_origl.freq_iterate -= fb_info_clone.freq_iterate ;
02720 Annot_loop( wn_origl, fb_info_origl );
02721 Annot_loop( wn_clone, fb_info_clone );
02722 }
02723 break;
02724
02725 fb_opr_cases_circuit:
02726 {
02727 FB_Info_Circuit fb_info_origl = Query_circuit( wn_origl );
02728 FB_Info_Circuit fb_info_clone( fb_info_origl.freq_left * freq_scale,
02729 fb_info_origl.freq_right * freq_scale,
02730 fb_info_origl.freq_neither * freq_scale );
02731 fb_info_origl.freq_left -= fb_info_clone.freq_left ;
02732 fb_info_origl.freq_right -= fb_info_clone.freq_right ;
02733 fb_info_origl.freq_neither -= fb_info_clone.freq_neither;
02734 Annot_circuit( wn_origl, fb_info_origl );
02735 Annot_circuit( wn_clone, fb_info_clone );
02736 }
02737 break;
02738
02739 fb_opr_cases_call:
02740 {
02741 FB_Info_Call fb_info_origl = Query_call( wn_origl );
02742 FB_Info_Call fb_info_clone( fb_info_origl.freq_entry * freq_scale,
02743 fb_info_origl.freq_exit * freq_scale,
02744 fb_info_origl.in_out_same );
02745 fb_info_origl.freq_entry -= fb_info_clone.freq_entry;
02746 fb_info_origl.freq_exit -= fb_info_clone.freq_exit;
02747 Annot_call( wn_origl, fb_info_origl );
02748 Annot_call( wn_clone, fb_info_clone );
02749 #ifdef KEY
02750 if( WN_operator(wn_origl) == OPR_ICALL ){
02751 FB_Info_Icall fb_info_origl = Query_icall( wn_origl );
02752 const float scale = freq_scale.Value();
02753 FB_Info_Icall fb_info_clone = fb_info_origl;
02754
02755 fb_info_clone.tnv._exec_counter =
02756 (UINT64)(fb_info_origl.tnv._exec_counter * scale);
02757 fb_info_origl.tnv._exec_counter -= fb_info_clone.tnv._exec_counter;
02758
02759 for( int i = 0; i < FB_TNV_SIZE; i ++ ){
02760 if( fb_info_origl.tnv._values[i] == 0 )
02761 break;
02762 fb_info_clone.tnv._counters[i] =
02763 (UINT64)(fb_info_origl.tnv._counters[i] * scale);
02764 if( fb_info_origl.tnv._counters[i] > fb_info_clone.tnv._counters[i] )
02765 fb_info_origl.tnv._counters[i] -= fb_info_clone.tnv._counters[i];
02766 else
02767 fb_info_origl.tnv._counters[i] = 0;
02768 }
02769
02770 Annot_icall( wn_origl, fb_info_origl );
02771 Annot_icall( wn_clone, fb_info_clone );
02772 }
02773 #endif
02774 }
02775 break;
02776
02777 fb_opr_cases_switch:
02778 {
02779 FB_Info_Switch fb_info_origl = Query_switch( wn_origl );
02780 FB_Info_Switch fb_info_clone = fb_info_origl;
02781 for ( INT t = fb_info_origl.size() - 1; t >= 0; t-- ) {
02782 fb_info_clone[t] *= freq_scale;
02783 fb_info_origl[t] -= fb_info_clone[t];
02784 }
02785 Annot_switch( wn_origl, fb_info_origl );
02786 Annot_switch( wn_clone, fb_info_clone );
02787 }
02788 break;
02789
02790 #ifdef KEY
02791 fb_opr_cases_value:
02792 if( IS_VALID_DIV_VALUE( wn_origl ) ){
02793 FB_Info_Value fb_info_origl = Query_value( wn_origl );
02794 FB_Info_Value fb_info_clone = fb_info_origl;
02795
02796 fb_info_clone.exe_counter *= freq_scale;
02797 fb_info_origl.exe_counter -= fb_info_clone.exe_counter;
02798 for( int i = 0; i < fb_info_origl.num_values; i++ ){
02799 fb_info_clone.freq[i] *= freq_scale;
02800 fb_info_origl.freq[i] -= fb_info_clone.freq[i];
02801 }
02802
02803 Annot_value( wn_origl, fb_info_origl );
02804 Annot_value( wn_clone, fb_info_clone );
02805
02806 }
02807 break;
02808
02809 fb_opr_cases_value_fp_bin:
02810 if( IS_VALID_MPY_VALUE( wn_origl ) ){
02811 FB_Info_Value_FP_Bin fb_info_origl = Query_value_fp_bin( wn_origl );
02812 FB_Info_Value_FP_Bin fb_info_clone = fb_info_origl;
02813
02814 fb_info_clone.exe_counter *= freq_scale;
02815 fb_info_clone.zopnd0 *= freq_scale;
02816 fb_info_clone.zopnd1 *= freq_scale;
02817 fb_info_clone.uopnd0 *= freq_scale;
02818 fb_info_clone.uopnd1 *= freq_scale;
02819 fb_info_origl.exe_counter -= fb_info_clone.exe_counter;
02820 fb_info_origl.zopnd0 -= fb_info_clone.zopnd0;
02821 fb_info_origl.zopnd1 -= fb_info_clone.zopnd1;
02822 fb_info_origl.uopnd0 -= fb_info_clone.uopnd0;
02823 fb_info_origl.uopnd1 -= fb_info_clone.uopnd1;
02824
02825 Annot_value_fp_bin( wn_origl, fb_info_origl );
02826 Annot_value_fp_bin( wn_clone, fb_info_clone );
02827
02828 }
02829 break;
02830 #endif
02831
02832 default:
02833 break;
02834 }
02835 }
02836
02837 void
02838 FEEDBACK::FB_clone( WN *wn_origl, WN *wn_clone, FB_FREQ freq_scale )
02839 {
02840 if ( _trace ) {
02841 fprintf( TFile, "FEEDBACK::FB_clone(0x%p, 0x%p", wn_origl, wn_clone );
02842 freq_scale.Print( TFile );
02843 fprintf( TFile, "):\n" );
02844 }
02845
02846 for ( TREE_ITER origl( wn_origl ), clone( wn_clone );
02847 origl.Wn() != NULL && clone.Wn() != NULL;
02848 ++origl, ++clone ) {
02849
02850
02851 FB_clone_node( origl.Wn(), clone.Wn(), freq_scale );
02852 }
02853 }
02854
02855
02856 void
02857 FEEDBACK::FB_clone_test( WN *wn_origl, WN *wn_clone,
02858 FB_FREQ freq_origl_taken, FB_FREQ freq_origl_not,
02859 FB_FREQ freq_clone_taken, FB_FREQ freq_clone_not )
02860 {
02861 if ( ! ( freq_origl_taken.Known() && freq_origl_not.Known() &&
02862 freq_clone_taken.Known() && freq_clone_not.Known() )) {
02863
02864 DevWarn( "FEEDBACK::FB_clone_test found unknown frequency" );
02865
02866
02867 FB_clone( wn_origl, wn_clone, FB_FREQ( 0.5, false ) );
02868 return;
02869 }
02870
02871
02872 OPERATOR opr = WN_operator( wn_origl );
02873 switch( opr ) {
02874
02875 case OPR_LNOT:
02876 FB_clone_test( WN_kid0( wn_origl ), WN_kid0( wn_clone ),
02877 freq_origl_not, freq_origl_taken,
02878 freq_clone_not, freq_clone_taken );
02879 break;
02880
02881 case OPR_CAND:
02882 {
02883 FB_FREQ freq_scale =
02884 freq_clone_not / ( freq_origl_not + freq_clone_not );
02885 if ( ! freq_scale.Known() )
02886 freq_scale = FB_FREQ( 0.5, false );
02887
02888
02889 FB_Info_Circuit fb_info_origl = Query_circuit( wn_origl );
02890 FB_Info_Circuit fb_info_clone( fb_info_origl.freq_left * freq_scale,
02891 fb_info_origl.freq_right * freq_scale,
02892 freq_clone_taken );
02893 fb_info_origl.freq_left -= fb_info_clone.freq_left ;
02894 fb_info_origl.freq_right -= fb_info_clone.freq_right ;
02895 fb_info_origl.freq_neither -= fb_info_clone.freq_neither;
02896 Annot_circuit( wn_origl, fb_info_origl );
02897 Annot_circuit( wn_clone, fb_info_clone );
02898
02899
02900 FB_clone_test( WN_kid0( wn_origl ), WN_kid0( wn_clone ),
02901 fb_info_origl.freq_right + fb_info_origl.freq_neither,
02902 fb_info_origl.freq_left,
02903 fb_info_clone.freq_right + fb_info_clone.freq_neither,
02904 fb_info_clone.freq_left );
02905 FB_clone_test( WN_kid1( wn_origl ), WN_kid1( wn_clone ),
02906 fb_info_origl.freq_neither, fb_info_origl.freq_right,
02907 fb_info_clone.freq_neither, fb_info_clone.freq_right );
02908 }
02909 break;
02910
02911 case OPR_CIOR:
02912 {
02913 FB_FREQ freq_scale =
02914 freq_clone_taken / ( freq_origl_taken + freq_clone_taken );
02915 if ( ! freq_scale.Known() )
02916 freq_scale = FB_FREQ( 0.5, false );
02917
02918
02919 FB_Info_Circuit fb_info_origl = Query_circuit( wn_origl );
02920 FB_Info_Circuit fb_info_clone( fb_info_origl.freq_left * freq_scale,
02921 fb_info_origl.freq_right * freq_scale,
02922 freq_clone_not );
02923 fb_info_origl.freq_left -= fb_info_clone.freq_left ;
02924 fb_info_origl.freq_right -= fb_info_clone.freq_right ;
02925 fb_info_origl.freq_neither -= fb_info_clone.freq_neither;
02926 Annot_circuit( wn_origl, fb_info_origl );
02927 Annot_circuit( wn_clone, fb_info_clone );
02928
02929
02930 FB_clone_test( WN_kid0( wn_origl ), WN_kid0( wn_clone ),
02931 fb_info_origl.freq_left,
02932 fb_info_origl.freq_right + fb_info_origl.freq_neither,
02933 fb_info_clone.freq_left,
02934 fb_info_clone.freq_right + fb_info_clone.freq_neither );
02935 FB_clone_test( WN_kid1( wn_origl ), WN_kid1( wn_clone ),
02936 fb_info_origl.freq_right, fb_info_origl.freq_neither,
02937 fb_info_clone.freq_right, fb_info_clone.freq_neither );
02938 }
02939 break;
02940
02941 case OPR_COMMA:
02942 FB_clone_test( WN_kid0( wn_origl ), WN_kid0( wn_clone ),
02943 freq_origl_taken, freq_origl_not,
02944 freq_clone_taken, freq_clone_not );
02945 FB_clone_test( WN_kid1( wn_origl ), WN_kid1( wn_clone ),
02946 freq_origl_taken, freq_origl_not,
02947 freq_clone_taken, freq_clone_not );
02948 break;
02949
02950 case OPR_RCOMMA:
02951 FB_clone_test( WN_kid0( wn_origl ), WN_kid0( wn_clone ),
02952 freq_origl_taken, freq_origl_not,
02953 freq_clone_taken, freq_clone_not );
02954 FB_clone_test( WN_kid1( wn_origl ), WN_kid1( wn_clone ),
02955 freq_origl_taken, freq_origl_not,
02956 freq_clone_taken, freq_clone_not );
02957 break;
02958
02959 case OPR_CSELECT:
02960 {
02961
02962 FB_FREQ freq_origl_total = freq_origl_taken + freq_origl_not;
02963 FB_FREQ freq_clone_total = freq_clone_taken + freq_clone_not;
02964 FB_FREQ freq_scale =
02965 freq_clone_total / ( freq_origl_total + freq_clone_total );
02966 if ( ! freq_scale.Known() )
02967 freq_scale = FB_FREQ( 0.5, false );
02968
02969 FB_Info_Branch fb_info_origl = Query_branch( wn_origl );
02970
02971
02972 FB_FREQ freq_scale_kid1 =
02973 fb_info_origl.freq_taken / fb_info_origl.Total();
02974 if ( ! freq_scale_kid1.Known() )
02975 freq_scale_kid1 = FB_FREQ( 0.5, false );
02976
02977
02978 FB_Info_Branch
02979 fb_info_clone( fb_info_origl.freq_taken * freq_scale,
02980 fb_info_origl.freq_not_taken * freq_scale );
02981 fb_info_origl.freq_taken -= fb_info_clone.freq_taken ;
02982 fb_info_origl.freq_not_taken -= fb_info_clone.freq_not_taken;
02983 Annot_branch( wn_origl, fb_info_origl );
02984 Annot_branch( wn_clone, fb_info_clone );
02985
02986
02987 FB_FREQ freq_kid1_origl_taken = freq_origl_taken * freq_scale_kid1;
02988 FB_FREQ freq_kid1_origl_not = freq_origl_not * freq_scale_kid1;
02989 FB_FREQ freq_kid1_clone_taken = freq_clone_taken * freq_scale_kid1;
02990 FB_FREQ freq_kid1_clone_not = freq_clone_not * freq_scale_kid1;
02991 freq_origl_taken -= freq_kid1_origl_taken;
02992 freq_origl_not -= freq_kid1_origl_not;
02993 freq_clone_taken -= freq_kid1_clone_taken;
02994 freq_clone_not -= freq_kid1_clone_not;
02995
02996
02997 FB_clone( WN_kid0( wn_origl ), WN_kid0( wn_clone ), freq_scale );
02998 FB_clone_test( WN_kid1( wn_origl ), WN_kid1( wn_clone ),
02999 freq_kid1_origl_taken, freq_kid1_origl_not,
03000 freq_kid1_clone_taken, freq_kid1_clone_not );
03001
03002 FB_clone_test( WN_kid2( wn_origl ), WN_kid2( wn_clone ),
03003 freq_origl_taken, freq_origl_not,
03004 freq_clone_taken, freq_clone_not );
03005 }
03006 break;
03007
03008 default:
03009 {
03010
03011 FB_FREQ freq_origl_total = freq_origl_taken + freq_origl_not;
03012 FB_FREQ freq_clone_total = freq_clone_taken + freq_clone_not;
03013 FB_FREQ freq_scale =
03014 freq_clone_total / ( freq_origl_total + freq_clone_total );
03015 if ( ! freq_scale.Known() )
03016 freq_scale = FB_FREQ( 0.5, false );
03017
03018 FB_clone( wn_origl, wn_clone, freq_scale );
03019 }
03020 break;
03021 }
03022 }
03023
03024
03025 void
03026 FEEDBACK::FB_clone_loop_test( WN *wn_origl, WN *wn_clone, WN *wn_loop )
03027 {
03028 if ( _trace ) {
03029 fprintf( TFile, "FEEDBACK::FB_clone_loop_test(0x%p, 0x%p, 0x%p):\n",
03030 wn_origl, wn_clone, wn_loop );
03031 Print_with_wn( TFile, wn_origl );
03032 Print_with_wn( TFile, wn_loop );
03033 }
03034 const FB_Info_Loop& fb_info = Query_loop( wn_loop );
03035
03036 if ( fb_info.freq_back.Known() && fb_info.freq_out.Known() &&
03037 fb_info.freq_positive.Known() && fb_info.freq_zero.Known() ) {
03038 FB_clone_test( wn_origl, wn_clone,
03039 fb_info.freq_back, fb_info.freq_out,
03040 fb_info.freq_positive, fb_info.freq_zero );
03041 } else {
03042
03043 FB_clone( wn_origl, wn_clone, FB_FREQ( 0.125, false ) );
03044 }
03045 }
03046
03047
03048
03049
03050
03051
03052 void
03053 FB_IPA_Clone_node( FEEDBACK *feedback_origl, FEEDBACK *feedback_clone,
03054 WN *wn_origl, WN *wn_clone,
03055 FB_FREQ freq_scale )
03056 {
03057
03058
03059
03060
03061
03062
03063
03064 Is_True( feedback_origl != NULL,
03065 ( "FEEDBACK::FB_IPA_Clone_node: feedback_origl == NULL" ) );
03066
03067
03068 switch( WN_operator( wn_origl ) ) {
03069
03070 case OPR_PRAGMA:
03071 if ( WN_pragma( wn_origl ) != WN_PRAGMA_PREAMBLE_END )
03072 break;
03073
03074
03075 fb_opr_cases_invoke:
03076 {
03077 FB_Info_Invoke fb_info_origl = feedback_origl->Query_invoke( wn_origl );
03078 FB_Info_Invoke fb_info_clone( fb_info_origl.freq_invoke * freq_scale );
03079 fb_info_origl.freq_invoke -= fb_info_clone.freq_invoke;
03080 feedback_origl->Annot_invoke( wn_origl, fb_info_origl );
03081 feedback_clone->Annot_invoke( wn_clone, fb_info_clone );
03082 }
03083 break;
03084
03085 fb_opr_cases_branch:
03086 {
03087 FB_Info_Branch fb_info_origl = feedback_origl->Query_branch( wn_origl );
03088 FB_Info_Branch fb_info_clone( fb_info_origl.freq_taken * freq_scale,
03089 fb_info_origl.freq_not_taken * freq_scale );
03090 fb_info_origl.freq_taken -= fb_info_clone.freq_taken ;
03091 fb_info_origl.freq_not_taken -= fb_info_clone.freq_not_taken;
03092 feedback_origl->Annot_branch( wn_origl, fb_info_origl );
03093 feedback_clone->Annot_branch( wn_clone, fb_info_clone );
03094 }
03095 break;
03096
03097 fb_opr_cases_loop:
03098 {
03099 FB_Info_Loop fb_info_origl = feedback_origl->Query_loop( wn_origl );
03100 FB_Info_Loop fb_info_clone( fb_info_origl.freq_zero * freq_scale,
03101 fb_info_origl.freq_positive * freq_scale,
03102 fb_info_origl.freq_out * freq_scale,
03103 fb_info_origl.freq_back * freq_scale,
03104 fb_info_origl.freq_exit * freq_scale,
03105 fb_info_origl.freq_iterate * freq_scale );
03106 fb_info_origl.freq_zero -= fb_info_clone.freq_zero ;
03107 fb_info_origl.freq_positive -= fb_info_clone.freq_positive;
03108 fb_info_origl.freq_out -= fb_info_clone.freq_out ;
03109 fb_info_origl.freq_back -= fb_info_clone.freq_back ;
03110 fb_info_origl.freq_exit -= fb_info_clone.freq_exit ;
03111 fb_info_origl.freq_iterate -= fb_info_clone.freq_iterate ;
03112 feedback_origl->Annot_loop( wn_origl, fb_info_origl );
03113 feedback_clone->Annot_loop( wn_clone, fb_info_clone );
03114 }
03115 break;
03116
03117 fb_opr_cases_circuit:
03118 {
03119 FB_Info_Circuit
03120 fb_info_origl = feedback_origl->Query_circuit( wn_origl );
03121 FB_Info_Circuit
03122 fb_info_clone( fb_info_origl.freq_left * freq_scale,
03123 fb_info_origl.freq_right * freq_scale,
03124 fb_info_origl.freq_neither * freq_scale );
03125 fb_info_origl.freq_left -= fb_info_clone.freq_left ;
03126 fb_info_origl.freq_right -= fb_info_clone.freq_right ;
03127 fb_info_origl.freq_neither -= fb_info_clone.freq_neither;
03128 feedback_origl->Annot_circuit( wn_origl, fb_info_origl );
03129 feedback_clone->Annot_circuit( wn_clone, fb_info_clone );
03130 }
03131 break;
03132
03133 fb_opr_cases_call:
03134 {
03135 FB_Info_Call fb_info_origl = feedback_origl->Query_call( wn_origl );
03136 FB_Info_Call fb_info_clone( fb_info_origl.freq_entry * freq_scale,
03137 fb_info_origl.freq_exit * freq_scale );
03138 fb_info_origl.freq_entry -= fb_info_clone.freq_entry;
03139 fb_info_origl.freq_exit -= fb_info_clone.freq_exit;
03140 feedback_origl->Annot_call( wn_origl, fb_info_origl );
03141 feedback_clone->Annot_call( wn_clone, fb_info_clone );
03142
03143 #ifdef KEY
03144 if( WN_operator(wn_origl) == OPR_ICALL ){
03145 FB_Info_Icall fb_info_origl = feedback_origl->Query_icall( wn_origl );
03146 const float scale = freq_scale.Value();
03147 FB_Info_Icall fb_info_clone = fb_info_origl;
03148
03149 fb_info_clone.tnv._exec_counter =
03150 (UINT64)(fb_info_origl.tnv._exec_counter * scale);
03151 fb_info_origl.tnv._exec_counter -= fb_info_clone.tnv._exec_counter;
03152
03153 for( int i = 0; i < FB_TNV_SIZE; i ++ ){
03154 if( fb_info_origl.tnv._values[i] == 0 )
03155 break;
03156 fb_info_clone.tnv._counters[i] =
03157 (UINT64)(fb_info_origl.tnv._counters[i] * scale);
03158 if( fb_info_origl.tnv._counters[i] > fb_info_clone.tnv._counters[i] )
03159 fb_info_origl.tnv._counters[i] -= fb_info_clone.tnv._counters[i];
03160 else
03161 fb_info_origl.tnv._counters[i] = 0;
03162 }
03163
03164 feedback_origl->Annot_icall( wn_origl, fb_info_origl );
03165 feedback_clone->Annot_icall( wn_clone, fb_info_clone );
03166 }
03167 #endif // KEY
03168 }
03169 break;
03170
03171 fb_opr_cases_switch:
03172 {
03173 FB_Info_Switch fb_info_origl = feedback_origl->Query_switch( wn_origl );
03174 FB_Info_Switch fb_info_clone = fb_info_origl;
03175 for ( INT32 t = fb_info_origl.size() - 1; t >= 0; --t ) {
03176 fb_info_clone[t] *= freq_scale;
03177 fb_info_origl[t] -= fb_info_clone[t];
03178 }
03179 feedback_origl->Annot_switch( wn_origl, fb_info_origl );
03180 feedback_clone->Annot_switch( wn_clone, fb_info_clone );
03181 }
03182 break;
03183
03184 #ifdef KEY
03185 fb_opr_cases_value:
03186 if( IS_VALID_DIV_VALUE( wn_origl ) ){
03187 FB_Info_Value fb_info_origl = feedback_origl->Query_value( wn_origl );
03188 FB_Info_Value fb_info_clone = fb_info_origl;
03189
03190 fb_info_clone.exe_counter = fb_info_origl.exe_counter * freq_scale;
03191 fb_info_origl.exe_counter -= fb_info_clone.exe_counter;
03192
03193 for( int i = 0; i < fb_info_origl.num_values; i++ ){
03194 fb_info_clone.freq[i] = fb_info_origl.freq[i] * freq_scale;
03195 fb_info_origl.freq[i] -= fb_info_clone.freq[i];
03196 }
03197
03198 feedback_origl->Annot_value( wn_origl, fb_info_origl );
03199 feedback_clone->Annot_value( wn_clone, fb_info_clone );
03200
03201 }
03202 break;
03203
03204 fb_opr_cases_value_fp_bin:
03205 if( IS_VALID_MPY_VALUE( wn_origl ) ){
03206 FB_Info_Value_FP_Bin fb_info_origl =
03207 feedback_origl->Query_value_fp_bin( wn_origl );
03208 FB_Info_Value_FP_Bin fb_info_clone = fb_info_origl;
03209
03210 fb_info_clone.exe_counter = fb_info_origl.exe_counter * freq_scale;
03211 fb_info_clone.zopnd0 = fb_info_clone.zopnd0 * freq_scale;
03212 fb_info_clone.zopnd1 = fb_info_clone.zopnd1 * freq_scale;
03213 fb_info_clone.uopnd0 = fb_info_clone.uopnd0 * freq_scale;
03214 fb_info_clone.uopnd1 = fb_info_clone.uopnd1 * freq_scale;
03215 fb_info_origl.exe_counter -= fb_info_clone.exe_counter;
03216 fb_info_origl.zopnd0 -= fb_info_clone.zopnd0;
03217 fb_info_origl.zopnd1 -= fb_info_clone.zopnd1;
03218 fb_info_origl.uopnd0 -= fb_info_clone.uopnd0;
03219 fb_info_origl.uopnd1 -= fb_info_clone.uopnd1;
03220
03221 feedback_origl->Annot_value_fp_bin( wn_origl, fb_info_origl );
03222 feedback_clone->Annot_value_fp_bin( wn_clone, fb_info_clone );
03223
03224 }
03225 break;
03226 #endif // KEY
03227
03228 default:
03229 break;
03230 }
03231 }
03232
03233
03234 void
03235 FB_IPA_Clone( FEEDBACK *feedback_origl, FEEDBACK *feedback_clone,
03236 WN *wn_origl, WN *wn_clone,
03237 FB_FREQ freq_scale )
03238 {
03239
03240
03241
03242
03243
03244
03245
03246 if ( feedback_origl == NULL ) {
03247 if ( freq_scale.Exact() && freq_scale.Zero() ){
03248 #ifdef KEY
03249 if( feedback_clone != NULL )
03250 #endif
03251 feedback_clone->FB_set_zero( wn_clone );
03252 }
03253 return;
03254 }
03255
03256 for ( TREE_ITER origl( wn_origl ), clone( wn_clone );
03257 origl.Wn() != NULL && clone.Wn() != NULL;
03258 ++origl, ++clone ) {
03259
03260
03261 FB_IPA_Clone_node( feedback_origl, feedback_clone,
03262 origl.Wn(), clone.Wn(), freq_scale );
03263 }
03264 }
03265
03266
03267 void
03268 FB_IPA_Inline( FEEDBACK *feedback_origl, FEEDBACK *feedback_inlin,
03269 WN *wn_origl, WN *wn_inlin,
03270 FB_FREQ freq_scale )
03271 {
03272 Is_True( WN_operator( wn_origl ) == OPR_FUNC_ENTRY,
03273 ( "FEEDBACK::FB_IPA_Inline: wn_origl should be FUNC_ENTRY" ) );
03274
03275 FB_FREQ freq_origl = FB_FREQ( 1, true ) - freq_scale;
03276
03277 WN *func_body = WN_func_body( wn_origl );
03278
03279 if ( feedback_origl ) {
03280
03281
03282 FB_Info_Invoke fb_info = feedback_origl->Query_invoke( wn_origl );
03283 fb_info.freq_invoke *= freq_origl;
03284 feedback_origl->Annot_invoke( wn_origl, fb_info );
03285
03286
03287 for ( INT32 t = 0; t < WN_kid_count( wn_origl ); ++t )
03288 if ( WN_kid( wn_origl, t ) != func_body )
03289 feedback_origl->FB_scale( WN_kid( wn_origl, t ), freq_origl );
03290 }
03291
03292
03293 FB_IPA_Clone( feedback_origl, feedback_inlin,
03294 func_body, wn_inlin, freq_scale );
03295 }
03296
03297
03298
03299
03300
03301
03302 void
03303 FB_Transfer_node(FEEDBACK *feedback_origl, FEEDBACK *feedback_new, WN *wn)
03304 {
03305 switch( WN_operator( wn ) ) {
03306
03307 case OPR_PRAGMA:
03308 if ( WN_pragma( wn ) != WN_PRAGMA_PREAMBLE_END )
03309 break;
03310
03311 fb_opr_cases_invoke:
03312 feedback_new->Annot_invoke(wn, feedback_origl->Query_invoke(wn));
03313 feedback_origl->Delete(wn);
03314 break;
03315
03316 fb_opr_cases_branch:
03317 feedback_new->Annot_branch(wn, feedback_origl->Query_branch(wn));
03318 feedback_origl->Delete(wn);
03319 break;
03320
03321 fb_opr_cases_loop:
03322 feedback_new->Annot_loop(wn, feedback_origl->Query_loop(wn));
03323 feedback_origl->Delete(wn);
03324 break;
03325
03326 fb_opr_cases_circuit:
03327 feedback_new->Annot_circuit(wn, feedback_origl->Query_circuit(wn));
03328 feedback_origl->Delete(wn);
03329 break;
03330
03331 fb_opr_cases_call:
03332 feedback_new->Annot_call(wn, feedback_origl->Query_call(wn));
03333 #ifdef KEY
03334 if( WN_operator(wn) == OPR_ICALL ){
03335 feedback_new->Annot_icall(wn, feedback_origl->Query_icall(wn));
03336 }
03337 #endif
03338 feedback_origl->Delete(wn);
03339 break;
03340
03341 fb_opr_cases_switch:
03342 feedback_new->Annot_switch(wn, feedback_origl->Query_switch(wn));
03343 feedback_origl->Delete(wn);
03344 break;
03345
03346 #ifdef KEY
03347 fb_opr_cases_value:
03348 if( IS_VALID_DIV_VALUE( wn ) ){
03349 feedback_new->Annot_value( wn, feedback_origl->Query_value(wn) );
03350 feedback_origl->Delete(wn);
03351 }
03352 break;
03353
03354 fb_opr_cases_value_fp_bin:
03355 if( IS_VALID_MPY_VALUE( wn ) ){
03356 feedback_new->Annot_value_fp_bin(wn,
03357 feedback_origl->Query_value_fp_bin(wn));
03358 feedback_origl->Delete(wn);
03359 }
03360 break;
03361 #endif
03362
03363 default:
03364 break;
03365 }
03366 }
03367
03368
03369 void
03370 FB_Transfer(FEEDBACK *feedback_origl, FEEDBACK *feedback_new, WN *wn)
03371 {
03372 Is_True(feedback_origl, ("NULL feedback_origl"));
03373 Is_True(feedback_new, ("NULL feedback_new"));
03374 Is_True(wn, ("NULL wn"));
03375
03376 for ( TREE_ITER it (wn) ; it.Wn() != NULL; ++it ) {
03377 FB_Transfer_node(feedback_origl, feedback_new, it.Wn());
03378 }
03379
03380 }
03381
03382
03383 void dump_fb ( const FEEDBACK *feedback, const WN *wn )
03384 {
03385 feedback->Print( stdout, wn );
03386 fflush(stdout);
03387 }
03388
03389
03390
03391
03392
03393
03394 FB_VERIFY_STATUS
03395 FEEDBACK::Verify( const char *caller, bool abort_if_error ) const
03396 {
03397 Is_True( this != NULL, ( "FEEDBACK::Verify encountered NULL FEEDBACK" ) );
03398
03399 if ( _trace ) {
03400 fprintf( TFile, "\n===== FEEDBACK::Verify (%s)\n", caller );
03401 fdump_tree_with_freq( TFile, _root_wn, WN_MAP_FEEDBACK );
03402 fprintf( TFile, "\n" );
03403 }
03404
03405 FB_CFG fb_cfg;
03406 fb_cfg.Construct_from_whirl( _root_wn, caller );
03407 FB_VERIFY_STATUS fb_status = fb_cfg.Verify_frequencies();
03408 fb_cfg.Patch_whirl_frequencies();
03409
03410 switch( fb_status ) {
03411 case FB_VERIFY_CONSISTENT:
03412 break;
03413 case FB_VERIFY_UNBALANCED:
03414 DevWarn( "Feedback unbalanced %s", caller );
03415 break;
03416 case FB_VERIFY_INVALID:
03417 DevWarn( "Feedback invalid %s", caller );
03418 break;
03419 default:
03420 Is_True( false, ( "FEEDBACK::Verify found unexpected branch" ) );
03421 break;
03422 }
03423
03424 return fb_status;
03425 }
03426
03427
03428 FB_VERIFY_STATUS
03429 FEEDBACK::Verify_and_guess( const char *caller, bool abort_if_error ) const
03430 {
03431 Is_True( this != NULL,
03432 ( "FEEDBACK::Verify_and_guess encountered NULL FEEDBACK" ) );
03433
03434 if ( _trace ) {
03435 fprintf( TFile, "\n===== FEEDBACK::Verify_and_guess (%s)\n", caller );
03436 fdump_tree_with_freq( TFile, _root_wn, WN_MAP_FEEDBACK );
03437 fprintf( TFile, "\n" );
03438 }
03439
03440 FB_CFG fb_cfg;
03441 fb_cfg.Construct_from_whirl( _root_wn, caller );
03442 fb_cfg.Guess_unknowns( _root_wn, caller );
03443 FB_VERIFY_STATUS fb_status = fb_cfg.Verify_frequencies();
03444 fb_cfg.Patch_whirl_frequencies();
03445
03446 return fb_status;
03447 }
03448
03449
03450 void
03451 FEEDBACK::Display_FB_CFG_From_Whirl( const char *caller )
03452 {
03453 if ( this == NULL || ! DaVinci::enabled( true ) ) {
03454 return;
03455 }
03456 FB_CFG fb_cfg;
03457 fb_cfg.Construct_from_whirl( _root_wn, caller );
03458
03459 dV_view_fb_cfg( fb_cfg, _root_wn, caller );
03460 }
03461
03462
03463
03464
03465
03466
03467 INT
03468 Convert_Feedback_Info (const FEEDBACK* fb, const WN* tree,
03469 PU_Profile_Handle& pu_handle)
03470 {
03471 Is_True (fb != NULL && tree != NULL,
03472 ("Convert_Feedback_Info: invalid FEEDBACK* or WN* "));
03473
03474 INT count = 0;
03475 for ( CONST_TREE_ITER iter (tree); iter.Wn () != NULL; ++iter ) {
03476 const WN* wn = iter.Wn ();
03477
03478 switch ( WN_operator( wn ) ) {
03479
03480 case OPR_PRAGMA:
03481 if ( WN_pragma( wn ) != WN_PRAGMA_PREAMBLE_END )
03482 break;
03483
03484
03485 fb_opr_cases_invoke:
03486 pu_handle.Get_Invoke_Table ().push_back (fb->Query_invoke (wn));
03487 ++count;
03488 break;
03489
03490 fb_opr_cases_branch:
03491 pu_handle.Get_Branch_Table ().push_back (fb->Query_branch (wn));
03492 ++count;
03493 break;
03494
03495 fb_opr_cases_loop:
03496 pu_handle.Get_Loop_Table ().push_back (fb->Query_loop (wn));
03497 ++count;
03498 break;
03499
03500 fb_opr_cases_circuit:
03501 pu_handle.Get_Short_Circuit_Table ().push_back (fb->Query_circuit (wn));
03502 ++count;
03503 break;
03504
03505 fb_opr_cases_call:
03506 pu_handle.Get_Call_Table ().push_back (fb->Query_call (wn));
03507 #ifdef KEY
03508 if( WN_operator(wn) == OPR_ICALL ){
03509 pu_handle.Get_Icall_Table ().push_back (fb->Query_icall (wn));
03510
03511
03512
03513 const FB_Info_Icall& info_icall = Cur_PU_Feedback->Query_icall(wn);
03514
03515 if( !info_icall.Is_uninit() ){
03516 const FB_Info_Call& info_call = Cur_PU_Feedback->Query_call(wn);
03517 FmtAssert( info_icall.tnv._exec_counter >= info_icall.tnv._counters[0],
03518 ("icall exec counters don't match") );
03519 }
03520 }
03521 #endif // KEY
03522 ++count;
03523 break;
03524
03525 fb_opr_cases_switch:
03526 pu_handle.Get_Switch_Table ().push_back (fb->Query_switch (wn));
03527 ++count;
03528 break;
03529
03530 #ifdef KEY
03531 fb_opr_cases_value:
03532 if( IS_VALID_DIV_VALUE( wn ) ){
03533 pu_handle.Get_Value_Table ().push_back (fb->Query_value (wn));
03534 ++count;
03535 break;
03536 }
03537
03538 fb_opr_cases_value_fp_bin:
03539 if( IS_VALID_MPY_VALUE( wn ) ){
03540 pu_handle.Get_Value_FP_Bin_Table().push_back(fb->Query_value_fp_bin (wn));
03541 ++count;
03542 break;
03543 }
03544 #endif
03545
03546 default:
03547 break;
03548 }
03549 }
03550 return count;
03551 }
03552
03553
03554
03555 void
03556 Read_Feedback_Info (FEEDBACK* fb, WN* tree, const Pu_Hdr& pu_hdr)
03557 {
03558 Is_True (fb != NULL && tree != NULL,
03559 ("Read_Feedback_Info: invalid FEEDBACK* or WN* "));
03560
03561 const char * baseaddr = (const char *) (&pu_hdr);
03562 const FB_Info_Invoke* fb_invoke =
03563 (const FB_Info_Invoke*) (baseaddr + pu_hdr.pu_inv_offset);
03564 const FB_Info_Invoke* fb_invoke_last = fb_invoke + pu_hdr.pu_num_inv_entries;
03565
03566 const FB_Info_Branch* fb_branch =
03567 (const FB_Info_Branch*) (baseaddr + pu_hdr.pu_br_offset);
03568 const FB_Info_Branch* fb_branch_last = fb_branch + pu_hdr.pu_num_br_entries;
03569
03570 const FB_FREQ* fb_switch =
03571 (const FB_FREQ*) (baseaddr + pu_hdr.pu_switch_offset);
03572 const INT32* fb_switch_target =
03573 (const INT32*) (baseaddr + pu_hdr.pu_switch_target_offset);
03574 const INT32* fb_switch_target_last =
03575 fb_switch_target + pu_hdr.pu_num_switch_entries;
03576
03577 const FB_Info_Loop* fb_loop =
03578 (const FB_Info_Loop*) (baseaddr + pu_hdr.pu_loop_offset);
03579 const FB_Info_Loop* fb_loop_last = fb_loop + pu_hdr.pu_num_loop_entries;
03580
03581 const FB_Info_Circuit* fb_circuit =
03582 (const FB_Info_Circuit*) (baseaddr + pu_hdr.pu_scircuit_offset);
03583 const FB_Info_Circuit* fb_circuit_last =
03584 fb_circuit + pu_hdr.pu_num_scircuit_entries;
03585
03586 #ifdef KEY
03587 const FB_Info_Icall* fb_icall =
03588 (const FB_Info_Icall*) (baseaddr + pu_hdr.pu_icall_offset);
03589 const FB_Info_Icall* fb_icall_last = fb_icall + pu_hdr.pu_num_icall_entries;
03590
03591 const FB_Info_Value* fb_value =
03592 (const FB_Info_Value*) (baseaddr + pu_hdr.pu_value_offset);
03593 const FB_Info_Value* fb_value_last = fb_value + pu_hdr.pu_num_value_entries;
03594
03595 const FB_Info_Value_FP_Bin* fb_value_fp_bin =
03596 (const FB_Info_Value_FP_Bin*) (baseaddr + pu_hdr.pu_value_fp_bin_offset);
03597 const FB_Info_Value_FP_Bin* fb_value_fp_bin_last = fb_value_fp_bin +
03598 pu_hdr.pu_num_value_fp_bin_entries;
03599 #endif
03600
03601 const FB_Info_Call* fb_call =
03602 (const FB_Info_Call*) (baseaddr + pu_hdr.pu_call_offset);
03603 const FB_Info_Call* fb_call_last = fb_call + pu_hdr.pu_num_call_entries;
03604
03605 INT count = 0;
03606
03607 for ( TREE_ITER iter (tree); iter.Wn () != NULL; ++iter ) {
03608 WN* wn = iter.Wn ();
03609
03610 switch ( WN_operator( wn ) ) {
03611
03612 case OPR_PRAGMA:
03613 if ( WN_pragma( wn ) != WN_PRAGMA_PREAMBLE_END )
03614 break;
03615
03616
03617 fb_opr_cases_invoke:
03618 fb->Annot_invoke( wn, *fb_invoke );
03619 ++fb_invoke;
03620 ++count;
03621 break;
03622
03623 fb_opr_cases_branch:
03624 fb->Annot_branch( wn, *fb_branch );
03625 ++fb_branch;
03626 ++count;
03627 break;
03628
03629 fb_opr_cases_loop:
03630 fb->Annot_loop( wn, *fb_loop );
03631 ++fb_loop;
03632 ++count;
03633 break;
03634
03635 fb_opr_cases_circuit:
03636 fb->Annot_circuit( wn, *fb_circuit );
03637 ++fb_circuit;
03638 ++count;
03639 break;
03640
03641 fb_opr_cases_call:
03642 fb->Annot_call( wn, *fb_call );
03643 ++fb_call;
03644 #ifdef KEY
03645 if( WN_operator(wn) == OPR_ICALL ){
03646 fb->Annot_icall( wn, *fb_icall );
03647 ++fb_icall;
03648 }
03649 #endif // KEY
03650 ++count;
03651 break;
03652
03653 fb_opr_cases_switch:
03654 {
03655 FB_Info_Switch info;
03656 info.freq_targets.insert( info.freq_targets.begin (),
03657 fb_switch, fb_switch + *fb_switch_target );
03658 fb->Annot_switch( wn, info );
03659 fb_switch += *fb_switch_target;
03660 ++fb_switch_target;
03661 ++count;
03662 }
03663 break;
03664
03665 #ifdef KEY
03666 fb_opr_cases_value:
03667 if( IS_VALID_DIV_VALUE( wn ) ){
03668 fb->Annot_value( wn, *fb_value );
03669 ++fb_value;
03670 ++count;
03671 break;
03672 }
03673
03674 fb_opr_cases_value_fp_bin:
03675 if( IS_VALID_MPY_VALUE( wn ) ){
03676 fb->Annot_value_fp_bin( wn, *fb_value_fp_bin );
03677 ++fb_value_fp_bin;
03678 ++count;
03679 break;
03680 }
03681 #endif
03682
03683 default:
03684 break;
03685 }
03686 }
03687
03688 #ifdef KEY
03689 FmtAssert( count == pu_hdr.pu_checksum &&
03690 fb_invoke == fb_invoke_last &&
03691 fb_branch == fb_branch_last &&
03692 fb_value == fb_value_last &&
03693 fb_value_fp_bin == fb_value_fp_bin_last &&
03694 fb_switch_target == fb_switch_target_last &&
03695 fb_loop == fb_loop_last &&
03696 fb_circuit == fb_circuit_last &&
03697 fb_icall == fb_icall_last &&
03698 fb_call == fb_call_last,
03699 ("Feedback data is stale. Please rebuild the feedback data.") );
03700 #else
03701 Is_True( count == pu_hdr.pu_checksum &&
03702 fb_invoke == fb_invoke_last &&
03703 fb_branch == fb_branch_last &&
03704 fb_switch_target == fb_switch_target_last &&
03705 fb_loop == fb_loop_last &&
03706 fb_circuit == fb_circuit_last &&
03707 fb_icall == fb_icall_last &&
03708 fb_call == fb_call_last, ( "Error in reading Feedback info" ) );
03709 #endif // KEY
03710
03711 }
03712
03713 #if 1 && ! defined(BUILD_OS_DARWIN)
03714 #include <sys/types.h>
03715 #if defined(BUILD_OS_DARWIN)
03716 #include <darwin_elf.h>
03717 #else
03718 #include <elf.h>
03719 #endif
03720 #include <sys/types.h>
03721 #include <elf.h>
03722 #include <ctype.h>
03723 #include "wn.h"
03724 #include "wn_map.h"
03725 #include "wn_util.h"
03726 #include <stdio.h>
03727 #include "opt_du.h"
03728 #include "opt_alias_mgr.h"
03729 #include "dep_graph.h"
03730 #include "prompf.h"
03731 #include "ir_reader.h"
03732 #include "wb_util.h"
03733 #include "wb_buffer.h"
03734 #include "wb_carray.h"
03735 #include "wb_browser.h"
03736 #include <wb.h>
03737
03738 void
03739 wb_gwe(WN *wn_root)
03740 {
03741 WB_BROWSER wb;
03742
03743 WB_Set_Phase( WBP_LOWER );
03744 WB_Initialize( &wb, wn_root, &Get_Current_PU(), NULL, NULL, -1 );
03745 wb.Sdebug( "" );
03746 WB_Set_Phase( WBP_NONE );
03747 WB_Terminate( &wb );
03748 }
03749 #endif