00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083 #ifdef USE_PCH
00084 #include "be_com_pch.h"
00085 #endif
00086
00087 #pragma hdrstop
00088 #define USE_STANDARD_TYPES
00089
00090 #include <stdlib.h>
00091 #include <algorithm>
00092 #include <vector>
00093 #include <stack>
00094 #include <list>
00095 #include <set>
00096 #include <map>
00097
00098
00099 #include "mempool.h"
00100 #include "cxx_memory.h"
00101 #include "tracing.h"
00102 #include "config_opt.h"
00103 #include "defs.h"
00104 #include "wn.h"
00105 #include "wn_map.h"
00106 #include "wn_util.h"
00107 #include "profile_com.h"
00108 #include "instr_reader.h"
00109 #include "targ_sim.h"
00110 #include "wn_pragmas.h"
00111 #include "ir_reader.h"
00112 #include "glob.h"
00113 #include "errors.h"
00114 #include "be_symtab.h"
00115 #include "vho_lower.h"
00116 #include "fb_whirl.h"
00117 #include "wn_instrument.h"
00118 #include "erglob.h"
00119
00120
00121
00122
00123 #define Instrumenter_DEBUG 0
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142 #ifdef KEY
00143 static WN* pu_wn = NULL;
00144 #endif
00145
00146
00147 #define TNV_N 10
00148
00149 class WN_INSTRUMENT_WALKER {
00150 private:
00151
00152
00153
00154
00155
00156
00157
00158
00159 MEM_POOL * _mempool;
00160
00161
00162
00163
00164 PROFILE_PHASE _phase;
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175 BOOL _instrumenting;
00176 BOOL _vho_lower;
00177 BOOL _in_preamble;
00178
00179
00180
00181 UINT32 _count_invoke;
00182 UINT32 _count_branch;
00183 UINT32 _count_loop;
00184 UINT32 _count_circuit;
00185 UINT32 _count_call;
00186 UINT32 _count_icall;
00187 UINT32 _count_switch;
00188 UINT32 _count_compgoto;
00189 UINT32 _fb_count_icall;
00190 #ifdef KEY
00191 UINT32 _count_value;
00192 UINT32 _count_value_fp_bin;
00193 #endif
00194
00195
00196
00197
00198 UINT32 _instrument_count;
00199
00200
00201
00202
00203 ST *_pu_handle;
00204 PU_PROFILE_HANDLES _fb_handle;
00205
00206 PU_PROFILE_HANDLE _fb_handle_merged;
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220 typedef mempool_allocator<WN *> ALLOC_TYPE;
00221 typedef std::deque<WN *, ALLOC_TYPE > DEQUE_TYPE;
00222 typedef std::stack<WN *, DEQUE_TYPE > STACK_TYPE;
00223
00224 WN * _entry_pragma_stmt;
00225 WN * _entry_pragma_block;
00226 STACK_TYPE _other_entry_pragmas;
00227
00228
00229
00230
00231
00232
00233
00234
00235 vector<WN *, mempool_allocator<WN *> > _instrumentation_nodes;
00236
00237
00238
00239 vector<INT32, mempool_allocator<INT32> > _switch_num_targets;
00240 vector<INT64, mempool_allocator<INT64> > _switch_case_values;
00241 vector<INT32, mempool_allocator<INT32> > _compgoto_num_targets;
00242
00243
00244
00245
00246
00247 WN_INSTRUMENT_WALKER(void);
00248 WN_INSTRUMENT_WALKER(const WN_INSTRUMENT_WALKER&);
00249 WN_INSTRUMENT_WALKER& operator=(const WN_INSTRUMENT_WALKER&);
00250
00251
00252
00253
00254 WN *PU_Handle() const {
00255 return WN_Ldid( Pointer_type, 0, _pu_handle, MTYPE_To_TY(Pointer_type));
00256 }
00257
00258
00259 PU_PROFILE_HANDLES& FB_Handle() { return _fb_handle; }
00260
00261
00262 public:
00263 BOOL FB_Handle_Empty() { return _fb_handle.empty(); }
00264 private:
00265
00266
00267 void Set_VHO_Lower_Tree() { _vho_lower = TRUE; }
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293 BOOL Entry_List_Empty() const { return _entry_pragma_stmt == NULL; }
00294 WN * Entry_Pragma() const { return _entry_pragma_stmt; }
00295 WN * Entry_Block() const { return _entry_pragma_block; }
00296
00297 void Pop_Entry_Pragma() {
00298 if ( _other_entry_pragmas.empty() )
00299 _entry_pragma_stmt = _entry_pragma_block = NULL;
00300 else {
00301 _entry_pragma_stmt = _other_entry_pragmas.top();
00302 _other_entry_pragmas.pop();
00303 _entry_pragma_block = _other_entry_pragmas.top();
00304 _other_entry_pragmas.pop();
00305 }
00306 }
00307
00308 void Push_Entry_Pragma( WN *stmt, WN *block ) {
00309 Is_True( stmt != NULL, ( "WN_INSTRUMENT_WALKER::Push_Entry_Pragma"
00310 " stmt is NULL" ) );
00311 if ( _entry_pragma_stmt == NULL ) {
00312 _entry_pragma_stmt = stmt;
00313 _entry_pragma_block = block;
00314 } else {
00315 _other_entry_pragmas.push( block );
00316 _other_entry_pragmas.push( stmt );
00317 }
00318 }
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338 void Record_Instrument_Node( WN *wn ) {
00339 _instrumentation_nodes.push_back( wn );
00340 }
00341
00342 BOOL Test_Instrument_Node( WN *wn ) {
00343 INT t, last = _instrumentation_nodes.size() - 1;
00344
00345
00346 for ( t = last; t >= 0; --t )
00347 if ( _instrumentation_nodes[t] == wn ) {
00348 _instrumentation_nodes[t] = _instrumentation_nodes[last];
00349 _instrumentation_nodes.pop_back();
00350 return TRUE;
00351 }
00352 return FALSE;
00353 }
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379 BOOL Is_Return_Store_Stmt( WN *wn );
00380 BOOL Is_Return_Store_Comma( WN *wn );
00381 BOOL Test_Dedicated_Reg( WN *wn );
00382
00383 void Instrument_Before( WN *call, WN *current_stmt, WN *block );
00384 void Instrument_After( WN *call, WN *current_stmt, WN *block );
00385 void Instrument_Entry( WN *call );
00386
00387 WN *Create_Comma_Kid( WN *wn, INT kid_idx );
00388
00389
00390
00391
00392
00393 void Instrument_Invoke( WN *wn, INT32 id, WN *block );
00394 void Initialize_Instrumenter_Invoke( INT32 count );
00395 void Annotate_Invoke( WN *wn, INT32 id );
00396 void Instrument_Branch( WN *wn, INT32 id, WN *block );
00397 void Instrument_Cselect( WN *wn, INT32 id );
00398 void Initialize_Instrumenter_Branch( INT32 count );
00399 void Annotate_Branch( WN *wn, INT32 id );
00400 void Instrument_Loop( WN *wn, INT32 id, WN *block );
00401 void Initialize_Instrumenter_Loop( INT32 count );
00402 void Annotate_Loop( WN *wn, INT32 id );
00403 void Instrument_Circuit( WN *wn, INT32 id );
00404 void Initialize_Instrumenter_Circuit( INT32 count );
00405 void Annotate_Circuit( WN *wn, INT32 id );
00406 void Instrument_Call( WN *wn, INT32 id, WN *block );
00407 void Initialize_Instrumenter_Call( INT32 count );
00408 void Annotate_Call( WN *wn, INT32 id );
00409 void Instrument_Icall( WN *wn, INT32 id, WN *block );
00410 void Initialize_Instrumenter_Icall( INT32 count );
00411 void Annotate_Icall( WN *wn, INT32 id );
00412 void Instrument_Switch( WN *wn, INT32 id, WN *block );
00413 void Initialize_Instrumenter_Switch( INT32 count );
00414 void Annotate_Switch( WN *wn, INT32 id );
00415 void Instrument_Compgoto( WN *wn, INT32 id, WN *block );
00416 void Initialize_Instrumenter_Compgoto( INT32 count );
00417 void Annotate_Compgoto( WN *wn, INT32 id );
00418 #ifdef KEY
00419 void Initialize_Instrumenter_Value( INT32 count );
00420 void Instrument_Value( WN *wn, INT32 id, WN *block );
00421 void Annotate_Value( WN *wn, INT32 id );
00422 void Initialize_Instrumenter_Value_FP_Bin( INT32 count );
00423 void Instrument_Value_FP_Bin( WN *wn, INT32 id, WN *block, WN *parent,
00424 WN *stmt );
00425 void Annotate_Value_FP_Bin( WN *wn, INT32 id );
00426 #endif
00427
00428
00429
00430
00431 #ifndef KEY
00432 void Tree_Walk_Node( WN *wn, WN *stmt, WN *block );
00433 #else
00434 void Tree_Walk_Node( WN *wn, WN *stmt, WN *block, WN* parent = NULL );
00435 #endif
00436
00437 protected:
00438 void Merge_Icall_Feedback();
00439
00440
00441
00442
00443
00444 public:
00445
00446
00447
00448
00449
00450 WN_INSTRUMENT_WALKER( BOOL instrumenting, PROFILE_PHASE phase,
00451 MEM_POOL *local_mempool,
00452 PU_PROFILE_HANDLES fb_handles );
00453 ~WN_INSTRUMENT_WALKER() {}
00454
00455
00456
00457 void Tree_Walk( WN *wn );
00458 };
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468 WN *
00469 Gen_Call_Shell( const char *name, TYPE_ID rtype, INT32 argc )
00470 {
00471 TY_IDX ty = Make_Function_Type( MTYPE_To_TY( rtype ) );
00472 ST *st = Gen_Intrinsic_Function( ty, name );
00473
00474 Clear_PU_no_side_effects( Pu_Table[ST_pu( st )] );
00475 Clear_PU_is_pure( Pu_Table[ST_pu( st )] );
00476 Set_PU_no_delete( Pu_Table[ST_pu( st )] );
00477
00478 WN *wn_call = WN_Call( rtype, MTYPE_V, argc, st );
00479
00480 WN_Set_Call_Default_Flags( wn_call );
00481
00482
00483
00484 return wn_call;
00485 }
00486
00487
00488 WN *
00489 Gen_Call( const char *name, TYPE_ID rtype = MTYPE_V )
00490 {
00491 WN *call = Gen_Call_Shell( name, rtype, 0 );
00492 return call;
00493 }
00494
00495
00496 inline WN *
00497 Gen_Param( WN *arg, UINT32 flag )
00498 {
00499 return WN_CreateParm( WN_rtype( arg ), arg,
00500 MTYPE_To_TY( WN_rtype( arg ) ), flag );
00501 }
00502
00503
00504 WN *
00505 Gen_Call( const char *name, WN *arg1, TYPE_ID rtype = MTYPE_V )
00506 {
00507 WN *call = Gen_Call_Shell( name, rtype, 1 );
00508 WN_actual( call, 0 ) = Gen_Param( arg1, WN_PARM_BY_VALUE );
00509 return call;
00510 }
00511
00512
00513 WN *
00514 Gen_Call( const char *name, WN *arg1, WN *arg2, TYPE_ID rtype = MTYPE_V )
00515 {
00516 WN *call = Gen_Call_Shell( name, rtype, 2 );
00517 WN_actual( call, 0 ) = Gen_Param( arg1, WN_PARM_BY_VALUE );
00518 WN_actual( call, 1 ) = Gen_Param( arg2, WN_PARM_BY_VALUE );
00519 return call;
00520 }
00521
00522
00523 WN *
00524 Gen_Call( const char *name, WN *arg1, WN *arg2, WN *arg3, TYPE_ID rtype = MTYPE_V )
00525 {
00526 WN *call = Gen_Call_Shell( name, rtype, 3 );
00527 WN_actual( call, 0 ) = Gen_Param( arg1, WN_PARM_BY_VALUE );
00528 WN_actual( call, 1 ) = Gen_Param( arg2, WN_PARM_BY_VALUE );
00529 WN_actual( call, 2 ) = Gen_Param( arg3, WN_PARM_BY_VALUE );
00530 return call;
00531 }
00532
00533
00534 WN *
00535 Gen_Call( const char *name, WN *arg1, WN *arg2, WN *arg3, WN *arg4,
00536 TYPE_ID rtype = MTYPE_V )
00537 {
00538 WN *call = Gen_Call_Shell( name, rtype, 4 );
00539 WN_actual( call, 0 ) = Gen_Param( arg1, WN_PARM_BY_VALUE );
00540 WN_actual( call, 1 ) = Gen_Param( arg2, WN_PARM_BY_VALUE );
00541 WN_actual( call, 2 ) = Gen_Param( arg3, WN_PARM_BY_VALUE );
00542 WN_actual( call, 3 ) = Gen_Param( arg4, WN_PARM_BY_VALUE );
00543 return call;
00544 }
00545
00546
00547 WN *
00548 Gen_Call( const char *name, WN *arg1, WN *arg2, WN *arg3, WN *arg4,
00549 WN *arg5, TYPE_ID rtype = MTYPE_V )
00550 {
00551 WN *call = Gen_Call_Shell( name, rtype, 5 );
00552 WN_actual( call, 0 ) = Gen_Param( arg1, WN_PARM_BY_VALUE );
00553 WN_actual( call, 1 ) = Gen_Param( arg2, WN_PARM_BY_VALUE );
00554 WN_actual( call, 2 ) = Gen_Param( arg3, WN_PARM_BY_VALUE );
00555 WN_actual( call, 3 ) = Gen_Param( arg4, WN_PARM_BY_VALUE );
00556 WN_actual( call, 4 ) = Gen_Param( arg5, WN_PARM_BY_VALUE );
00557 return call;
00558 }
00559
00560
00561 WN *
00562 Gen_Call( const char *name, WN *arg1, WN *arg2, WN *arg3, WN *arg4,
00563 WN *arg5, WN *arg6, TYPE_ID rtype = MTYPE_V )
00564 {
00565 WN *call = Gen_Call_Shell( name, rtype, 6 );
00566 WN_actual( call, 0 ) = Gen_Param( arg1, WN_PARM_BY_VALUE );
00567 WN_actual( call, 1 ) = Gen_Param( arg2, WN_PARM_BY_VALUE );
00568 WN_actual( call, 2 ) = Gen_Param( arg3, WN_PARM_BY_VALUE );
00569 WN_actual( call, 3 ) = Gen_Param( arg4, WN_PARM_BY_VALUE );
00570 WN_actual( call, 4 ) = Gen_Param( arg5, WN_PARM_BY_VALUE );
00571 WN_actual( call, 5 ) = Gen_Param( arg6, WN_PARM_BY_VALUE );
00572 return call;
00573 }
00574
00575
00576
00577
00578
00579 WN *
00580 Gen_Call_ref3( const char *name, WN *arg1, WN *arg2, WN *arg3,
00581 TYPE_ID rtype = MTYPE_V )
00582 {
00583 WN *call = Gen_Call_Shell( name, rtype, 3 );
00584 WN_actual( call, 0 ) = Gen_Param( arg1, WN_PARM_BY_VALUE );
00585 WN_actual( call, 1 ) = Gen_Param( arg2, WN_PARM_BY_VALUE );
00586 WN_actual( call, 2 ) = Gen_Param( arg3, WN_PARM_BY_REFERENCE );
00587 return call;
00588 }
00589
00590
00591 WN *
00592 Gen_Call_ref35( const char *name, WN *arg1, WN *arg2, WN *arg3, WN *arg4,
00593 WN *arg5, TYPE_ID rtype = MTYPE_V )
00594 {
00595 WN *call = Gen_Call_Shell( name, rtype, 5 );
00596 WN_actual( call, 0 ) = Gen_Param( arg1, WN_PARM_BY_VALUE );
00597 WN_actual( call, 1 ) = Gen_Param( arg2, WN_PARM_BY_VALUE );
00598 WN_actual( call, 2 ) = Gen_Param( arg3, WN_PARM_BY_REFERENCE );
00599 WN_actual( call, 3 ) = Gen_Param( arg4, WN_PARM_BY_VALUE );
00600 WN_actual( call, 4 ) = Gen_Param( arg5, WN_PARM_BY_REFERENCE );
00601 return call;
00602 }
00603
00604
00605
00606
00607
00608 WN_INSTRUMENT_WALKER::WN_INSTRUMENT_WALKER( BOOL instrumenting,
00609 PROFILE_PHASE phase,
00610 MEM_POOL *local_mempool,
00611 PU_PROFILE_HANDLES fb_handles )
00612 : _mempool( local_mempool ),
00613 _phase( phase ),
00614 _instrumenting( instrumenting ),
00615 _vho_lower( FALSE ),
00616 _in_preamble( FALSE ),
00617 _count_invoke( 0 ),
00618 _count_branch( 0 ),
00619 _count_loop( 0 ),
00620 _count_circuit( 0 ),
00621 _count_call( 0 ),
00622 _count_icall( 0 ),
00623 _count_switch( 0 ),
00624 _count_compgoto( 0 ),
00625 #ifdef KEY
00626 _count_value( 0 ),
00627 _count_value_fp_bin( 0 ),
00628 #endif
00629 _instrument_count( 0 ),
00630 _pu_handle( NULL ),
00631 _fb_handle( fb_handles ),
00632 _fb_handle_merged( NULL ),
00633 _entry_pragma_stmt( NULL ),
00634 _entry_pragma_block( NULL ),
00635 _other_entry_pragmas( DEQUE_TYPE( ALLOC_TYPE( local_mempool ) ) ),
00636 _instrumentation_nodes( local_mempool ),
00637 _switch_num_targets( local_mempool ),
00638 _switch_case_values( local_mempool ),
00639 _compgoto_num_targets( local_mempool )
00640 {
00641 if ( _instrumenting )
00642 _pu_handle = Gen_Temp_Symbol(MTYPE_To_TY(Pointer_type), "pu_instrument_handle");
00643 }
00644
00645
00646
00647
00648
00649
00650
00651
00652
00653 BOOL
00654 WN_INSTRUMENT_WALKER::Is_Return_Store_Stmt( WN *wn )
00655 {
00656 if ( wn && WN_operator( wn ) == OPR_STID ) {
00657 WN *val = WN_kid( wn, 0 );
00658 if ( WN_operator( val ) == OPR_LDID ) {
00659 ST *st = WN_st( val );
00660 if ( ST_sym_class( st ) == CLASS_PREG
00661 && ( Is_Return_Preg( WN_offset( val ) )
00662 || st == Return_Val_Preg ) )
00663 return TRUE;
00664 }
00665 }
00666
00667 return FALSE;
00668 }
00669
00670
00671 BOOL
00672 WN_INSTRUMENT_WALKER::Is_Return_Store_Comma( WN *wn )
00673 {
00674 if ( wn && WN_operator( wn ) == OPR_COMMA ) {
00675 WN *val = WN_kid( wn, 1 );
00676 if ( WN_operator( val ) == OPR_LDID ) {
00677 ST *st = WN_st( val );
00678 if ( ST_sym_class( st ) == CLASS_PREG
00679 && ( Is_Return_Preg( WN_offset( val ) )
00680 || st == Return_Val_Preg ) )
00681 return TRUE;
00682 }
00683 }
00684
00685 return FALSE;
00686 }
00687
00688
00689 BOOL
00690 WN_INSTRUMENT_WALKER::Test_Dedicated_Reg( WN *wn )
00691 {
00692 if ( wn == NULL )
00693 return FALSE;
00694
00695 OPERATOR opr = WN_operator( wn );
00696
00697 if ( opr == OPR_LDID ) {
00698 ST *st = WN_st( wn );
00699 if ( ST_sym_class( st ) == CLASS_PREG
00700 && Preg_Is_Dedicated( WN_offset( wn ) ) )
00701 return TRUE;
00702 }
00703
00704
00705 if ( opr == OPR_BLOCK ) {
00706
00707 WN *node;
00708 for ( node = WN_first( wn ); node; node = WN_next( node ) )
00709 if ( Test_Dedicated_Reg( node ) )
00710 return TRUE;
00711 }
00712 else {
00713 for ( INT32 i = 0; i < WN_kid_count( wn ); i++ )
00714 if ( Test_Dedicated_Reg( WN_kid( wn, i ) ) )
00715 return TRUE;
00716 }
00717 return FALSE;
00718 }
00719
00720
00721 void
00722 WN_INSTRUMENT_WALKER::Instrument_Before( WN *wn, WN *current_stmt,
00723 WN *block )
00724 {
00725 if ( Test_Dedicated_Reg( current_stmt ) ) {
00726 DevWarn( "Instrumenter Warning: Hardware registers used in "
00727 "instrumented node - program may behave differently!" );
00728
00729 }
00730
00731 WN *stmt_prev = WN_prev( current_stmt );
00732 WN_INSERT_BlockAfter( block, stmt_prev, wn );
00733 }
00734
00735
00736 void
00737 WN_INSTRUMENT_WALKER::Instrument_After( WN *wn, WN *current_stmt,
00738 WN *block )
00739 {
00740 WN *stmt = WN_next( current_stmt );
00741
00742
00743
00744 int i = 0;
00745 if ( OPCODE_is_call( WN_opcode( current_stmt ) ) )
00746 while ( stmt && Is_Return_Store_Stmt( stmt ) ) {
00747 if ( WN_rtype( current_stmt ) == MTYPE_V ) {
00748 DevWarn( "Instrumenter Warning: Should NOT have skipped!" );
00749
00750
00751 }
00752 i++;
00753 stmt = WN_next( stmt );
00754 }
00755
00756 if ( WN_rtype( current_stmt ) != MTYPE_V && i == 0 ) {
00757 DevWarn( "Instrumenter Warning: Should have skipped!" );
00758
00759
00760 }
00761
00762 WN_INSERT_BlockBefore( block, stmt, wn );
00763
00764 Record_Instrument_Node( wn );
00765 }
00766
00767
00768 void
00769 WN_INSTRUMENT_WALKER::Instrument_Entry( WN *wn )
00770 {
00771 WN_INSERT_BlockBefore( Entry_Block(), Entry_Pragma(), wn );
00772 }
00773
00774
00775 WN *
00776 WN_INSTRUMENT_WALKER::Create_Comma_Kid( WN *wn, INT kid_idx ) {
00777 WN *wn_comma;
00778 WN *wn_kid = WN_kid( wn, kid_idx );
00779 OPERATOR opr_kid = OPCODE_operator( WN_opcode( wn_kid ) );
00780 if ( opr_kid == OPR_COMMA ) {
00781 wn_comma = wn_kid;
00782 } else {
00783 wn_comma = WN_Create( OPR_COMMA, WN_rtype( wn_kid ), MTYPE_V, 2 );
00784 WN_kid( wn_comma, 0 ) = WN_CreateBlock();
00785 WN_kid( wn_comma, 1 ) = wn_kid;
00786 WN_kid( wn, kid_idx ) = wn_comma;
00787 }
00788 _vho_lower = TRUE;
00789 return wn_comma;
00790 }
00791
00792
00793
00794
00795
00796
00797
00798
00799
00800
00801
00802
00803
00804
00805
00806
00807
00808
00809
00810
00811
00812
00813
00814 void
00815 WN_INSTRUMENT_WALKER::Instrument_Invoke( WN *wn, INT32 id, WN *block )
00816 {
00817 WN *instr = Gen_Call( INVOKE_INSTRUMENT_NAME,
00818 PU_Handle(), WN_Intconst( MTYPE_I4, id ) );
00819 Instrument_After( instr, wn, block );
00820 }
00821
00822
00823 void
00824 WN_INSTRUMENT_WALKER::Initialize_Instrumenter_Invoke( INT32 count )
00825 {
00826 if ( count == 0 ) return;
00827
00828 WN *total_invokes = WN_Intconst( MTYPE_I4, count );
00829
00830 Instrument_Entry( Gen_Call( INVOKE_INIT_NAME,
00831 PU_Handle(), total_invokes ) );
00832 }
00833
00834
00835 void
00836 WN_INSTRUMENT_WALKER::Annotate_Invoke( WN *wn, INT32 id )
00837 {
00838
00839 PU_PROFILE_HANDLES& handles = FB_Handle();
00840 FB_Info_Invoke info_invoke( FB_FREQ_ZERO );
00841 for ( PU_PROFILE_ITERATOR i( handles.begin() );
00842 i != handles.end (); ++i ) {
00843 FB_Info_Invoke& info = Get_Invoke_Profile( *i, id );
00844 info_invoke.freq_invoke += info.freq_invoke;
00845 }
00846
00847
00848 Cur_PU_Feedback->Annot_invoke( wn, info_invoke );
00849 }
00850
00851
00852
00853
00854
00855 void
00856 WN_INSTRUMENT_WALKER::Instrument_Branch( WN *wn, INT32 id, WN *block )
00857 {
00858
00859 TYPE_ID cond_type = WN_rtype( WN_kid0( wn ) );
00860 PREG_NUM cond = Create_Preg( cond_type, "__branch_cond" );
00861 Instrument_Before( WN_StidIntoPreg( cond_type, cond,
00862 MTYPE_To_PREG( cond_type ),
00863 WN_kid0( wn ) ),
00864 wn, block );
00865
00866
00867 WN_kid0( wn ) = WN_LdidPreg( cond_type, cond );
00868
00869
00870
00871 OPERATOR opr = OPCODE_operator( WN_opcode( wn ) );
00872 WN *taken = WN_Relational( ( opr == OPR_FALSEBR ) ? OPR_EQ : OPR_NE,
00873 MTYPE_I4, WN_LdidPreg( cond_type, cond ),
00874 WN_Intconst( MTYPE_I4, 0 ) );
00875 WN *instr = Gen_Call( BRANCH_INSTRUMENT_NAME, PU_Handle(),
00876 WN_Intconst( MTYPE_I4, id ), taken );
00877 Instrument_Before( instr, wn, block );
00878 }
00879
00880
00881 void
00882 WN_INSTRUMENT_WALKER::Instrument_Cselect( WN *wn, INT32 id )
00883 {
00884
00885 WN *comma = Create_Comma_Kid( wn, 0 );
00886
00887
00888 TYPE_ID cond_type = WN_rtype( WN_kid( comma, 1 ) );
00889 PREG_NUM cond = Create_Preg( cond_type, "__cselect_cond" );
00890 WN *stid = WN_StidIntoPreg( cond_type, cond, MTYPE_To_PREG( cond_type ),
00891 WN_kid( comma, 1 ) );
00892 WN_INSERT_BlockLast( WN_kid( comma, 0 ), stid );
00893
00894
00895 WN_kid( comma, 1 ) = WN_LdidPreg( cond_type, cond );
00896
00897
00898 WN *taken = WN_Relational( OPR_NE, MTYPE_I4,
00899 WN_LdidPreg( cond_type, cond ),
00900 WN_Intconst( MTYPE_I4, 0 ) );
00901 WN *instr = Gen_Call( BRANCH_INSTRUMENT_NAME, PU_Handle(),
00902 WN_Intconst( MTYPE_I4, id ), taken );
00903 WN_INSERT_BlockLast( WN_kid( comma, 0 ), instr );
00904 }
00905
00906
00907 void
00908 WN_INSTRUMENT_WALKER::Initialize_Instrumenter_Branch( INT32 count )
00909 {
00910 if ( count == 0 ) return;
00911
00912
00913 WN *total_branches = WN_Intconst( MTYPE_I4, count );
00914 Instrument_Entry( Gen_Call( BRANCH_INIT_NAME,
00915 PU_Handle(), total_branches ) );
00916 }
00917
00918
00919 void
00920 WN_INSTRUMENT_WALKER::Annotate_Branch(WN *wn, INT32 id)
00921 {
00922 PU_PROFILE_HANDLES& handles = FB_Handle();
00923 FB_Info_Branch info_branch( FB_FREQ_ZERO, FB_FREQ_ZERO );
00924 for (PU_PROFILE_ITERATOR i( handles.begin() ); i != handles.end(); ++i ) {
00925 FB_Info_Branch& info = Get_Branch_Profile( *i, id );
00926 Is_True(&info, ("Branch id invalid"));
00927 info_branch.freq_taken += info.freq_taken;
00928 info_branch.freq_not_taken += info.freq_not_taken;
00929 }
00930
00931 Cur_PU_Feedback->Annot_branch( wn, info_branch );
00932 }
00933
00934
00935
00936
00937
00938 void
00939 WN_INSTRUMENT_WALKER::Instrument_Loop( WN *wn, INT32 id, WN *block )
00940 {
00941 OPERATOR opr = OPCODE_operator( WN_opcode( wn ) );
00942
00943
00944 Instrument_Before( Gen_Call( LOOP_INSTRUMENT_NAME,
00945 PU_Handle(),
00946 WN_Intconst( MTYPE_I4, id ) ),
00947 wn, block );
00948
00949
00950 WN *body = ( opr == OPR_DO_LOOP
00951 ? WN_do_body( wn ) : WN_while_body( wn ) );
00952 WN *iter_call = Gen_Call( LOOP_INST_ITER_NAME,
00953 PU_Handle(),
00954 WN_Intconst( MTYPE_I4, id ) );
00955 WN_INSERT_BlockFirst( body, iter_call );
00956 Record_Instrument_Node( iter_call );
00957 }
00958
00959
00960 void
00961 WN_INSTRUMENT_WALKER::Initialize_Instrumenter_Loop( INT32 count )
00962 {
00963 if ( count == 0 ) return;
00964
00965 WN *total_loops = WN_Intconst( MTYPE_I4, count );
00966
00967 Instrument_Entry( Gen_Call( LOOP_INIT_NAME,
00968 PU_Handle(), total_loops ) );
00969 }
00970
00971
00972 void
00973 WN_INSTRUMENT_WALKER::Annotate_Loop( WN *wn, INT32 id )
00974 {
00975 PU_PROFILE_HANDLES& handles = FB_Handle();
00976 FB_Info_Loop info_loop( FB_FREQ_ZERO, FB_FREQ_ZERO, FB_FREQ_ZERO,
00977 FB_FREQ_ZERO, FB_FREQ_ZERO, FB_FREQ_ZERO );
00978 for ( PU_PROFILE_ITERATOR i( handles.begin() ); i != handles.end(); ++i ) {
00979 FB_Info_Loop& info = Get_Loop_Profile ( *i, id );
00980 info_loop.freq_zero += info.freq_zero;
00981 info_loop.freq_positive += info.freq_positive;
00982 info_loop.freq_out += info.freq_out;
00983 info_loop.freq_back += info.freq_back;
00984 info_loop.freq_exit += info.freq_exit;
00985 info_loop.freq_iterate += info.freq_iterate;
00986 }
00987
00988 Cur_PU_Feedback->Annot_loop( wn, info_loop );
00989 }
00990
00991
00992
00993
00994
00995
00996
00997
00998
00999
01000
01001
01002
01003
01004
01005
01006
01007
01008
01009
01010
01011
01012
01013
01014 void
01015 WN_INSTRUMENT_WALKER::Instrument_Circuit( WN *wn, INT32 id )
01016 {
01017
01018
01019
01020 WN *comma = Create_Comma_Kid( wn, 1 );
01021
01022
01023 TYPE_ID cond_type = WN_rtype( WN_kid( comma, 1 ) );
01024 PREG_NUM cond = Create_Preg( cond_type, "__circuit_cond" );
01025 WN *stid = WN_StidIntoPreg( cond_type, cond, MTYPE_To_PREG( cond_type ),
01026 WN_kid( comma, 1 ) );
01027 WN_INSERT_BlockLast( WN_kid( comma, 0 ), stid );
01028
01029
01030 WN_kid( comma, 1 ) = WN_LdidPreg( cond_type, cond );
01031
01032
01033
01034 OPERATOR opr = OPCODE_operator( WN_opcode( wn ) );
01035 WN *taken = WN_Relational( opr == OPR_CAND ? OPR_EQ : OPR_NE,
01036 MTYPE_I4, WN_LdidPreg( cond_type, cond ),
01037 WN_Intconst( MTYPE_I4, 0 ) );
01038 WN *instr = Gen_Call( SHORT_CIRCUIT_INST_NAME, PU_Handle(),
01039 WN_Intconst( MTYPE_I4, id ), taken );
01040 WN_INSERT_BlockLast( WN_kid( comma, 0 ), instr );
01041 }
01042
01043
01044 void
01045 WN_INSTRUMENT_WALKER::Initialize_Instrumenter_Circuit( INT32 count )
01046 {
01047 if ( count == 0 ) return;
01048
01049 WN *total_short_circuits = WN_Intconst( MTYPE_I4, count );
01050
01051 Instrument_Entry( Gen_Call( SHORT_CIRCUIT_INIT_NAME,
01052 PU_Handle(), total_short_circuits ) );
01053 }
01054
01055
01056 void
01057 WN_INSTRUMENT_WALKER::Annotate_Circuit( WN *wn, INT32 id )
01058 {
01059 PU_PROFILE_HANDLES& handles = FB_Handle();
01060 FB_Info_Circuit info_circuit( FB_FREQ_ZERO, FB_FREQ_ZERO, FB_FREQ_ZERO );
01061 for (PU_PROFILE_ITERATOR i( handles.begin () ); i != handles.end(); ++i ) {
01062 FB_Info_Circuit& info = Get_Short_Circuit_Profile( *i, id );
01063 info_circuit.freq_left += info.freq_left;
01064 info_circuit.freq_right += info.freq_right;
01065 info_circuit.freq_neither += info.freq_neither;
01066 }
01067
01068 Cur_PU_Feedback->Annot_circuit( wn, info_circuit );
01069 }
01070
01071
01072
01073
01074
01075 void
01076 WN_INSTRUMENT_WALKER::Instrument_Call( WN *wn, INT32 id, WN *block )
01077 {
01078
01079 WN *called_func_name;
01080 if ( WN_has_sym( wn ) ) {
01081 char *name = ST_name( WN_st( wn ) );
01082 called_func_name = WN_LdaString( name, 0, strlen( name ) + 1 );
01083 } else
01084 called_func_name = WN_Zerocon( Pointer_type );
01085
01086
01087 Instrument_Before( Gen_Call( CALL_INST_ENTRY_NAME,
01088 PU_Handle(),
01089 WN_Intconst( MTYPE_I4, id ),
01090 called_func_name ),
01091 wn, block );
01092
01093
01094 Instrument_After( Gen_Call( CALL_INST_EXIT_NAME,
01095 PU_Handle(),
01096 WN_Intconst( MTYPE_I4, id ),
01097 WN_COPY_Tree( called_func_name ) ),
01098 wn, block );
01099 }
01100
01101 void
01102 WN_INSTRUMENT_WALKER::Instrument_Icall( WN *wn, INT32 id, WN *block )
01103 {
01104
01105 WN* orig_wn = WN_kid( wn, WN_kid_count(wn)-1 );
01106
01107
01108 if (WN_operator (orig_wn) == OPR_COMMA)
01109 WN_kid( wn, WN_kid_count(wn)-1 ) = WN_kid1 (orig_wn);
01110 WN* called_func_address = WN_COPY_Tree( orig_wn );
01111
01112 if( !WN_Rename_Duplicate_Labels( orig_wn,
01113 called_func_address,
01114 pu_wn,
01115 _mempool ) ){
01116 FmtAssert( FALSE, ("external labels renamed") );
01117 }
01118
01119
01120
01121
01122 Instrument_Before( Gen_Call( ICALL_INSTRUMENT_NAME,
01123 PU_Handle(),
01124 WN_Intconst( MTYPE_I4, id ),
01125 called_func_address ),
01126 wn, block );
01127 }
01128
01129 void
01130 WN_INSTRUMENT_WALKER::Initialize_Instrumenter_Call( INT32 count )
01131 {
01132 if ( count == 0 ) return;
01133
01134 WN *total_calls = WN_Intconst( MTYPE_I4, count );
01135
01136 Instrument_Entry( Gen_Call( CALL_INIT_NAME,
01137 PU_Handle(), total_calls ) );
01138 }
01139
01140 void
01141 WN_INSTRUMENT_WALKER::Initialize_Instrumenter_Icall( INT32 count )
01142 {
01143 if ( count == 0 ) return;
01144
01145 WN *total_icalls = WN_Intconst( MTYPE_I4, count );
01146
01147 Instrument_Entry( Gen_Call( ICALL_INIT_NAME,
01148 PU_Handle(), total_icalls ) );
01149 }
01150
01151 #ifdef KEY
01152 void WN_INSTRUMENT_WALKER::Initialize_Instrumenter_Value_FP_Bin( INT32 count )
01153 {
01154 if ( count == 0 ) return;
01155
01156 WN* total_values = WN_Intconst( MTYPE_I4, count );
01157
01158 Instrument_Entry( Gen_Call( VALUE_FP_BIN_INIT_NAME,
01159 PU_Handle(), total_values ) );
01160 }
01161
01162
01163 static BOOL Is_Array_Exp ( WN *wn )
01164 {
01165 if (WN_operator(wn) == OPR_ARRAYEXP)
01166 return TRUE;
01167
01168 for (INT kid = 0; kid < WN_kid_count(wn); kid ++)
01169 if (Is_Array_Exp(WN_kid(wn, kid))) return TRUE;
01170
01171 return FALSE;
01172 }
01173
01174 void WN_INSTRUMENT_WALKER::Instrument_Value_FP_Bin( WN *wn, INT32 id,
01175 WN *block, WN *parent,
01176 WN *stmt )
01177 {
01178 if ( !stmt ||
01179
01180 WN_operator(stmt) == OPR_IO )
01181 return;
01182
01183 INT kid_num = -1;
01184 for ( INT kid = 0; kid < WN_kid_count(parent); kid ++ )
01185 if ( WN_kid(parent, kid) == wn ) {
01186 kid_num = kid; break;
01187 }
01188 if (kid_num == -1) return;
01189
01190
01191
01192 if (Is_Array_Exp(WN_kid0(wn)) || Is_Array_Exp(WN_kid1(wn)))
01193 return;
01194
01195 WN* comma = Create_Comma_Kid ( parent, kid_num );
01196 WN* expr0 = WN_kid0(wn);
01197 WN* expr1 = WN_kid1(wn);
01198
01199 const TYPE_ID opnd_type = MTYPE_F8;
01200 PREG_NUM preg0 = Create_Preg( opnd_type, "__value_fp_0_prof" );
01201 PREG_NUM preg1 = Create_Preg( opnd_type, "__value_fp_1_prof" );
01202 WN* stid0 = WN_StidIntoPreg( opnd_type, preg0, MTYPE_To_PREG( opnd_type ),
01203 expr0 );
01204 WN* stid1 = WN_StidIntoPreg( opnd_type, preg1, MTYPE_To_PREG( opnd_type ),
01205 expr1 );
01206 WN* instr = Gen_Call( VALUE_FP_BIN_INSTRUMENT_NAME, PU_Handle(),
01207 WN_Intconst( MTYPE_I4, id ),
01208 WN_LdidPreg( opnd_type, preg0 ),
01209 WN_LdidPreg( opnd_type, preg1 ) );
01210
01211 WN_INSERT_BlockLast( WN_kid( comma, 0 ), stid0 );
01212 WN_INSERT_BlockLast( WN_kid( comma, 0 ), stid1 );
01213 WN_INSERT_BlockLast( WN_kid( comma, 0 ), instr );
01214
01215 WN_kid0( wn ) = WN_LdidPreg( opnd_type, preg0 );
01216 WN_kid1( wn ) = WN_LdidPreg( opnd_type, preg1 );
01217 }
01218
01219 void WN_INSTRUMENT_WALKER::Annotate_Value_FP_Bin( WN *wn, INT32 id )
01220 {
01221 PU_PROFILE_HANDLES& handles = FB_Handle();
01222
01223 if( handles.size() == 1 ){
01224 Cur_PU_Feedback->Annot_value_fp_bin(wn,
01225 Get_Value_FP_Bin_Profile(handles[0],id));
01226 return;
01227 }
01228 }
01229
01230
01231 void WN_INSTRUMENT_WALKER::Initialize_Instrumenter_Value( INT32 count )
01232 {
01233 if ( count == 0 ) return;
01234
01235 WN* total_values = WN_Intconst( MTYPE_I4, count );
01236
01237 Instrument_Entry( Gen_Call( VALUE_INIT_NAME,
01238 PU_Handle(), total_values ) );
01239 }
01240
01241
01242 void WN_INSTRUMENT_WALKER::Instrument_Value( WN *wn, INT32 id, WN *block )
01243 {
01244
01245 WN *comma = Create_Comma_Kid( wn, 1 );
01246
01247 #if defined(TARG_SL)
01248 const TYPE_ID divisor_type = MTYPE_I4;
01249 #else
01250 const TYPE_ID divisor_type = MTYPE_I8;
01251 #endif
01252
01253 const TYPE_ID to_type = Mtype_TransferSize( divisor_type,
01254 WN_rtype( WN_kid(comma,1) ) );
01255 WN* kid1 = WN_Type_Conversion( WN_kid(comma,1), to_type );
01256
01257 PREG_NUM divisor = Create_Preg( divisor_type, "__value_prof" );
01258
01259 WN* stid = WN_StidIntoPreg( divisor_type, divisor, MTYPE_To_PREG( divisor_type ),
01260 kid1 );
01261 WN_INSERT_BlockLast( WN_kid( comma, 0 ), stid );
01262
01263
01264 WN_kid( comma, 1 ) = WN_LdidPreg( divisor_type, divisor );
01265
01266
01267
01268 WN* instr = Gen_Call( VALUE_INSTRUMENT_NAME, PU_Handle(),
01269 WN_Intconst( MTYPE_I4, id ),
01270 WN_LdidPreg( divisor_type, divisor ) );
01271
01272 WN_INSERT_BlockLast( WN_kid( comma, 0 ), instr );
01273 }
01274
01275 typedef std::map<INT64, FB_FREQ> V2F_MAP;
01276 typedef V2F_MAP::iterator V2F_ITERATOR;
01277 static V2F_MAP v2f_map;
01278
01279 struct Sort_Value_by_Freq {
01280 const V2F_MAP& v2f;
01281 bool operator()(INT64 i, INT64 j) {
01282
01283 return v2f_map[i] > v2f_map[j];
01284 }
01285 Sort_Value_by_Freq( const V2F_MAP& v2f_map ) : v2f(v2f_map) {}
01286 };
01287
01288
01289 void WN_INSTRUMENT_WALKER::Annotate_Value( WN *wn, INT32 id )
01290 {
01291 PU_PROFILE_HANDLES& handles = FB_Handle();
01292
01293 if( handles.size() == 1 ){
01294 Cur_PU_Feedback->Annot_value( wn, Get_Value_Profile( handles[0], id ) );
01295 return;
01296 }
01297
01298
01299 FB_FREQ exe_counter(0.0);
01300 Is_True( v2f_map.empty(), ("v2f_map is not empty") );
01301
01302
01303
01304 for( PU_PROFILE_ITERATOR i( handles.begin () ); i != handles.end(); ++i ){
01305 const FB_Info_Value& src_info = Get_Value_Profile( *i, id );
01306
01307 exe_counter += src_info.exe_counter;
01308
01309 for( int i = 0; i < src_info.num_values; i++ ){
01310 const INT64 new_value = src_info.value[i];
01311 const FB_FREQ new_freq = src_info.freq[i];
01312
01313 if( v2f_map.find( new_value ) == v2f_map.end() ){
01314 v2f_map[new_value] = new_freq;
01315
01316 } else {
01317 v2f_map[new_value] = v2f_map[new_value] + new_freq;
01318 }
01319 }
01320 }
01321
01322
01323 vector<INT64> sorted_value;
01324 for( V2F_ITERATOR i = v2f_map.begin(); i != v2f_map.end(); i++ ){
01325 sorted_value.push_back( i->first );
01326 }
01327
01328 sort( sorted_value.begin(), sorted_value.end(), Sort_Value_by_Freq( v2f_map ) );
01329
01330
01331 FB_Info_Value dest_info;
01332
01333 dest_info.num_values = MIN( TNV, sorted_value.size() );
01334 dest_info.exe_counter = exe_counter;
01335
01336 for( int i = 0; i < dest_info.num_values; i++ ){
01337 const INT64 value = sorted_value[i];
01338 dest_info.value[i] = value;
01339 dest_info.freq[i] = v2f_map[value];
01340 }
01341
01342
01343
01344 Cur_PU_Feedback->Annot_value( wn, dest_info );
01345
01346 v2f_map.clear();
01347 }
01348 #endif
01349
01350 void
01351 WN_INSTRUMENT_WALKER::Annotate_Call( WN *wn, INT32 id )
01352 {
01353 PU_PROFILE_HANDLES& handles = FB_Handle();
01354 FB_Info_Call info_call( FB_FREQ_ZERO );
01355 for (PU_PROFILE_ITERATOR i( handles.begin() ); i != handles.end (); ++i) {
01356 FB_Info_Call& info = Get_Call_Profile( *i, id );
01357 info_call.freq_entry += info.freq_entry;
01358 info_call.freq_exit += info.freq_exit;
01359 }
01360
01361 info_call.in_out_same = ( info_call.freq_entry == info_call.freq_exit );
01362
01363
01364 Cur_PU_Feedback->Annot_call( wn, info_call );
01365 }
01366
01367 void
01368 WN_INSTRUMENT_WALKER::Annotate_Icall( WN *wn, INT32 id )
01369 {
01370 FB_Icall_Vector icall_table = _fb_handle_merged->Get_Icall_Table();
01371 FB_Info_Icall & info_icall = icall_table[id];
01372
01373
01374 Cur_PU_Feedback->Annot_icall( wn, info_icall );
01375 }
01376
01377
01378
01379
01380 void
01381 WN_INSTRUMENT_WALKER::Instrument_Switch( WN *wn, INT32 id, WN *block )
01382 {
01383
01384 _switch_num_targets.push_back( WN_num_entries( wn ) );
01385
01386
01387 for ( WN *wn_casegoto = WN_first( WN_kid1( wn ) );
01388 wn_casegoto != NULL;
01389 wn_casegoto = WN_next( wn_casegoto ) ) {
01390 _switch_case_values.push_back( WN_const_val( wn_casegoto ) );
01391 }
01392
01393
01394 TYPE_ID cond_type = WN_rtype( WN_kid0( wn ) );
01395 PREG_NUM cond = Create_Preg( cond_type, "__switch_cond" );
01396
01397 Instrument_Before( WN_StidIntoPreg( cond_type, cond,
01398 MTYPE_To_PREG( cond_type ),
01399 WN_kid0( wn ) ),
01400 wn, block );
01401 WN_kid0( wn ) = WN_LdidPreg( cond_type, cond );
01402
01403
01404 WN *instr = Gen_Call( SWITCH_INSTRUMENT_NAME, PU_Handle(),
01405 WN_Intconst( MTYPE_I4, id ),
01406 WN_LdidPreg( cond_type, cond ),
01407 WN_Intconst( MTYPE_I4,
01408 WN_num_entries( wn ) ) );
01409 Instrument_Before( instr, wn, block );
01410 }
01411
01412
01413 void
01414 WN_INSTRUMENT_WALKER::Initialize_Instrumenter_Switch( INT32 count )
01415 {
01416 if ( count == 0 ) return;
01417
01418
01419 INT32 num_switches = count;
01420
01421 TY_IDX arrayTY = Make_Array_Type( MTYPE_I4, 1, num_switches );
01422 ST *arrayST = New_ST( CURRENT_SYMTAB );
01423 ST_Init( arrayST, Save_Str( "switch_num_targets" ),
01424 CLASS_VAR, SCLASS_PSTATIC, EXPORT_LOCAL, arrayTY );
01425
01426
01427
01428 for ( INT32 i = 0; i < num_switches; i++ ) {
01429 WN *st = WN_Stid(MTYPE_I4, i * MTYPE_RegisterSize( MTYPE_I4 ),
01430 arrayST, arrayTY,
01431 WN_Intconst( MTYPE_I4, _switch_num_targets[i] ) );
01432 Instrument_Entry( st );
01433 }
01434
01435 WN *total_switches = WN_Intconst( MTYPE_I4, num_switches );
01436 WN *switch_num_targets = WN_Lda( Pointer_type, 0, arrayST );
01437
01438
01439
01440 INT32 num_case_values = _switch_case_values.size();
01441
01442 #if defined(TARG_SL)
01443 arrayTY = Make_Array_Type( MTYPE_I4, 1, num_case_values );
01444 #else
01445 arrayTY = Make_Array_Type( MTYPE_I8, 1, num_case_values );
01446 #endif
01447
01448 arrayST = New_ST( CURRENT_SYMTAB );
01449 ST_Init( arrayST, Save_Str( "switch_case_values" ),
01450 CLASS_VAR, SCLASS_PSTATIC, EXPORT_LOCAL, arrayTY );
01451
01452
01453
01454 for ( INT32 j = 0; j < num_case_values; j++ ) {
01455 #if defined(TARG_SL)
01456 WN *st = WN_Stid( MTYPE_I4, j * MTYPE_RegisterSize( MTYPE_I4 ),
01457 arrayST, arrayTY,
01458 WN_Intconst( MTYPE_I4, _switch_case_values[j] ) );
01459 #else
01460 WN *st = WN_Stid( MTYPE_I8, j * MTYPE_RegisterSize( MTYPE_I8 ),
01461 arrayST, arrayTY,
01462 WN_Intconst( MTYPE_I8, _switch_case_values[j] ) );
01463 #endif
01464 Instrument_Entry( st );
01465 }
01466
01467 WN *total_case_values = WN_Intconst( MTYPE_I4, num_case_values );
01468 WN *switch_case_values = WN_Lda( Pointer_type, 0, arrayST );
01469
01470
01471 WN *instr = Gen_Call_ref35( SWITCH_INIT_NAME, PU_Handle(),
01472 total_switches, switch_num_targets,
01473 total_case_values, switch_case_values );
01474 Instrument_Entry( instr );
01475 }
01476
01477
01478 static inline void
01479 Handle_Switch_Profile( PU_PROFILE_HANDLES& handles, WN* wn, INT32 id,
01480 FB_Info_Switch& (*get_profile) ( PU_PROFILE_HANDLE,
01481 INT32 ) )
01482 {
01483 FB_Info_Switch& info = (*get_profile) ( handles[0], id );
01484 if ( handles.size() == 1 ) {
01485
01486 Cur_PU_Feedback->Annot_switch( wn, info );
01487 } else {
01488 FB_Info_Switch info_switch;
01489 info_switch.freq_targets.insert( info_switch.freq_targets.begin(),
01490 info.freq_targets.begin(),
01491 info.freq_targets.end() );
01492 PU_PROFILE_ITERATOR i (handles.begin ());
01493 for (++i; i != handles.end (); ++i) {
01494 FB_Info_Switch& info = (*get_profile) (*i, id);
01495 FmtAssert( info.size () == info_switch.size (),
01496 ("Inconsistent profile data from different files"));
01497 transform( info.freq_targets.begin(),
01498 info.freq_targets.end(),
01499 info_switch.freq_targets.begin(),
01500 info_switch.freq_targets.begin(),
01501 std::plus<FB_FREQ>() );
01502 }
01503 Cur_PU_Feedback->Annot_switch( wn, info_switch );
01504 }
01505 }
01506
01507
01508 void
01509 WN_INSTRUMENT_WALKER::Annotate_Switch( WN *wn, INT32 id )
01510 {
01511 Handle_Switch_Profile( FB_Handle(), wn, id, Get_Switch_Profile );
01512 }
01513
01514
01515
01516
01517
01518 void
01519 WN_INSTRUMENT_WALKER::Instrument_Compgoto( WN *wn, INT32 id, WN *block )
01520 {
01521 _compgoto_num_targets.push_back( WN_num_entries( wn ) );
01522
01523
01524 TYPE_ID cond_type = WN_rtype( WN_kid0( wn ) );
01525 PREG_NUM cond = Create_Preg( cond_type, "__compgoto_cond" );
01526
01527 WN *target = WN_StidIntoPreg( cond_type, cond,
01528 MTYPE_To_PREG( cond_type ),
01529 WN_kid0( wn ) );
01530 Instrument_Before( target, wn, block );
01531 WN_kid0( wn ) = WN_LdidPreg( cond_type, cond );
01532
01533
01534 WN *instr = Gen_Call( COMPGOTO_INSTRUMENT_NAME, PU_Handle(),
01535 WN_Intconst( MTYPE_I4, id ),
01536 WN_LdidPreg( cond_type, cond ),
01537 WN_Intconst( MTYPE_I4,
01538 WN_num_entries( wn ) ) );
01539 Instrument_Before( instr, wn, block );
01540 }
01541
01542
01543 void
01544 WN_INSTRUMENT_WALKER::Initialize_Instrumenter_Compgoto( INT32 count )
01545 {
01546 if ( count == 0 ) return;
01547
01548
01549 INT32 num_compgotos = count;
01550
01551 TY_IDX arrayTY = Make_Array_Type( MTYPE_I4, 1, num_compgotos );
01552 ST *arrayST = New_ST( CURRENT_SYMTAB );
01553 ST_Init( arrayST, Save_Str( "compgoto_num_targets" ),
01554 CLASS_VAR, SCLASS_PSTATIC, EXPORT_LOCAL, arrayTY );
01555
01556
01557
01558 for ( INT32 i = 0; i < num_compgotos; i++ ) {
01559 WN *st = WN_Stid( MTYPE_I4, i * MTYPE_RegisterSize( MTYPE_I4 ),
01560 arrayST, arrayTY,
01561 WN_Intconst( MTYPE_I4, _compgoto_num_targets[i] ) );
01562 Instrument_Entry( st );
01563 }
01564
01565 WN *total_compgotos = WN_Intconst( MTYPE_I4, num_compgotos );
01566 WN *compgoto_num_targets = WN_Lda( Pointer_type, 0, arrayST );
01567
01568
01569 Instrument_Entry( Gen_Call_ref3( COMPGOTO_INIT_NAME, PU_Handle(),
01570 total_compgotos,
01571 compgoto_num_targets ) );
01572 }
01573
01574
01575 void
01576 WN_INSTRUMENT_WALKER::Annotate_Compgoto( WN *wn, INT32 id )
01577 {
01578 Handle_Switch_Profile( FB_Handle(), wn, id, Get_Compgoto_Profile );
01579 }
01580
01581
01582
01583
01584
01585
01586
01587
01588
01589
01590
01591
01592
01593
01594
01595
01596
01597 #ifndef KEY
01598 void
01599 WN_INSTRUMENT_WALKER::Tree_Walk_Node( WN *wn, WN *stmt, WN *block )
01600 #else
01601 void
01602 WN_INSTRUMENT_WALKER::Tree_Walk_Node( WN *wn, WN *stmt, WN *block,
01603 WN* parent )
01604 #endif
01605 {
01606 OPERATOR opr = WN_operator( wn );
01607
01608
01609
01610
01611 if ( opr == OPR_ALTENTRY ) {
01612 Is_True( ! _in_preamble, ( "WN_INSTRUMENT_WALKER::Tree_Walk_Node found"
01613 " no WN_PRAGMA_PREAMBLE_END pragma" ) );
01614 _in_preamble = TRUE;
01615 }
01616
01617
01618
01619
01620 else if ( opr == OPR_PRAGMA
01621 && WN_pragma( wn ) == WN_PRAGMA_PREAMBLE_END ) {
01622 Is_True( _in_preamble, ( "WN_INSTRUMENT_WALKER::Tree_Walk_Node found"
01623 " extra WN_PRAGMA_PREAMBLE_END pragma" ) );
01624 _in_preamble = FALSE;
01625 Push_Entry_Pragma( wn, block );
01626 }
01627
01628 else if ( opr == OPR_REGION
01629 #ifdef KEY
01630 && _instrumenting
01631 #endif
01632 ) {
01633
01634
01635 WN *regn_prag = WN_first( WN_region_pragmas( wn ) );
01636 if ( regn_prag ) {
01637 switch ( WN_pragma( regn_prag ) ) {
01638 case WN_PRAGMA_PARALLEL_BEGIN:
01639 case WN_PRAGMA_PARALLEL_SECTIONS:
01640 case WN_PRAGMA_PARALLEL_DO:
01641 case WN_PRAGMA_DOACROSS:
01642 {
01643 WN *prag = WN_CreatePragma( WN_PRAGMA_SHARED, _pu_handle, 0, 0 );
01644 WN_set_pragma_compiler_generated( prag );
01645 WN_INSERT_BlockLast( WN_region_pragmas ( wn ), prag );
01646 }
01647 break;
01648 default:
01649 break;
01650 }
01651 }
01652 }
01653
01654
01655
01656 if ( _in_preamble || Test_Instrument_Node( wn ) )
01657 return;
01658
01659
01660 if ( opr == OPR_BLOCK ) {
01661
01662
01663 WN *node;
01664 for ( node = WN_first( wn ); node; node = WN_next( node ) )
01665 Tree_Walk_Node( node, node, wn );
01666
01667 Is_True( ! _in_preamble, ( "WN_INSTRUMENT_WALKER::Tree_Walk_Node found"
01668 " no WN_PRAGMA_PREAMBLE_END pragma" ) );
01669
01670 } else if ( OPERATOR_is_expression( opr ) ) {
01671
01672
01673 if ( Is_Return_Store_Comma( wn ) ) {
01674
01675
01676
01677
01678
01679
01680
01681
01682
01683
01684
01685
01686
01687 TYPE_ID val_type = WN_rtype( WN_kid( wn, 1 ) );
01688 WN *ldidpreg = WN_kid(wn, 1);
01689 WN *stid;
01690 #ifdef KEY // bug 12245: preg cannot be used for complex types
01691 if (MTYPE_is_complex(val_type)) {
01692 ST *val_st = Gen_Temp_Symbol(MTYPE_TO_TY_array[val_type],"_call_comma");
01693 stid = WN_Stid(val_type, 0, val_st, WN_ty(ldidpreg), ldidpreg );
01694 WN_INSERT_BlockLast( WN_kid( wn, 0 ), stid );
01695
01696
01697 WN_kid( wn, 1 ) = WN_Ldid(val_type, 0, val_st, WN_ty(ldidpreg));
01698 }
01699 else {
01700 #endif
01701 PREG_NUM val = Create_Preg( val_type, "__call_comma" );
01702 stid = WN_StidIntoPreg( val_type, val, MTYPE_To_PREG( val_type ),
01703 ldidpreg );
01704 WN_INSERT_BlockLast( WN_kid( wn, 0 ), stid );
01705
01706
01707 WN_kid( wn, 1 ) = WN_LdidPreg( val_type, val );
01708 #ifdef KEY // bug 12245
01709 }
01710 #endif
01711 }
01712
01713
01714 for ( INT32 i = 0; i < WN_kid_count( wn ); i++ )
01715 #ifndef KEY
01716 Tree_Walk_Node( WN_kid( wn, i ), stmt, block );
01717 #else
01718 Tree_Walk_Node( WN_kid( wn, i ), stmt, block, wn );
01719 #endif
01720
01721 } else {
01722
01723
01724 for ( INT32 i = 0; i < WN_kid_count( wn ); i++ )
01725 #ifndef KEY
01726 Tree_Walk_Node( WN_kid( wn, i ), wn, block );
01727 #else
01728 Tree_Walk_Node( WN_kid( wn, i ), wn, block, wn );
01729 #endif
01730 }
01731
01732
01733 switch ( opr ) {
01734
01735 #ifdef KEY
01736 case OPR_MPY:
01737 if (! OPT_FP_Value_Instr)
01738 break;
01739 if( OPCODE_rtype(WN_opcode(wn)) == MTYPE_F8 ) {
01740 _instrument_count++;
01741 const INT32 id = _count_value_fp_bin++;
01742 if( _instrumenting )
01743 Instrument_Value_FP_Bin( wn, id, block, parent, stmt );
01744 else
01745 Annotate_Value_FP_Bin( wn, id );
01746 }
01747 break;
01748 case OPR_REM:
01749 case OPR_DIV:
01750 case OPR_MOD:
01751 if (! OPT_Int_Value_Instr)
01752 break;
01753 if( !WN_operator_is( WN_kid1(wn), OPR_INTCONST ) &&
01754 MTYPE_is_integral( OPCODE_rtype(WN_opcode(wn) ) ) ){
01755 _instrument_count++;
01756 const INT32 id = _count_value++;
01757 if( _instrumenting )
01758 Instrument_Value( wn, id, block );
01759 else
01760 Annotate_Value( wn, id );
01761 }
01762 break;
01763 #endif
01764
01765 case OPR_PRAGMA:
01766 if ( WN_pragma( wn ) != WN_PRAGMA_PREAMBLE_END )
01767 break;
01768 {
01769 _instrument_count++;
01770 INT32 id = _count_invoke++;
01771 if ( _instrumenting )
01772 Instrument_Invoke( wn, id, block );
01773 else
01774 Annotate_Invoke( wn, id );
01775 }
01776 break;
01777
01778 case OPR_TRUEBR:
01779 case OPR_FALSEBR:
01780 case OPR_IF:
01781 {
01782 _instrument_count++;
01783 INT32 id = _count_branch++;
01784 if ( _instrumenting )
01785 Instrument_Branch( wn, id, block );
01786 else
01787 Annotate_Branch( wn, id );
01788 }
01789 break;
01790
01791 case OPR_CSELECT:
01792 {
01793 _instrument_count++;
01794 INT32 id = _count_branch++;
01795 if ( _instrumenting )
01796 Instrument_Cselect( wn, id );
01797 else
01798 Annotate_Branch( wn, id );
01799 }
01800 break;
01801
01802 case OPR_DO_LOOP:
01803 case OPR_WHILE_DO:
01804 case OPR_DO_WHILE:
01805 {
01806 _instrument_count++;
01807 INT32 id = _count_loop++;
01808 if ( _instrumenting )
01809 Instrument_Loop( wn, id, block );
01810 else
01811 Annotate_Loop( wn, id );
01812 }
01813 break;
01814
01815 case OPR_CAND:
01816 case OPR_CIOR:
01817 {
01818 _instrument_count++;
01819 INT32 id = _count_circuit++;
01820 if ( _instrumenting )
01821 Instrument_Circuit( wn, id );
01822 else
01823 Annotate_Circuit( wn, id );
01824 }
01825 break;
01826
01827 case OPR_PICCALL:
01828 case OPR_CALL:
01829 case OPR_INTRINSIC_CALL:
01830 case OPR_IO:
01831 {
01832 _instrument_count++;
01833 INT32 id = _count_call++;
01834 if ( _instrumenting )
01835 Instrument_Call( wn, id, block );
01836 else
01837 Annotate_Call( wn, id );
01838 }
01839 break;
01840
01841 case OPR_ICALL:
01842 {
01843 _instrument_count++;
01844 INT32 idcall = _count_call++;
01845 INT32 idicall;
01846 #ifdef KEY
01847 if (OPT_Icall_Instr)
01848 #endif
01849 idicall = _count_icall++;
01850 if (_instrumenting)
01851 {
01852 Instrument_Call( wn, idcall, block);
01853 #ifdef KEY
01854 if (OPT_Icall_Instr)
01855 #endif
01856 Instrument_Icall( wn, idicall, block);
01857 }
01858 else
01859 {
01860 Annotate_Call( wn, idcall);
01861 #ifdef KEY
01862 if (OPT_Icall_Instr)
01863 #endif
01864 Annotate_Icall( wn, idicall);
01865 }
01866 }
01867 break;
01868
01869 case OPR_SWITCH:
01870 {
01871 _instrument_count++;
01872 INT32 id = _count_switch++;
01873 if ( _instrumenting )
01874 Instrument_Switch( wn, id, block );
01875 else
01876 Annotate_Switch( wn, id );
01877 }
01878 break;
01879
01880 case OPR_COMPGOTO:
01881 case OPR_XGOTO:
01882 {
01883 _instrument_count++;
01884 INT32 id = _count_compgoto++;
01885 if ( _instrumenting )
01886 Instrument_Compgoto( wn, id, block );
01887 else
01888 Annotate_Compgoto( wn, id );
01889 }
01890 break;
01891 }
01892
01893
01894 if ( opr == OPR_REGION ) {
01895 if ( _vho_lower ) {
01896 WN_region_body( wn ) = VHO_Lower( WN_region_body( wn ) );
01897 #ifndef KEY
01898 _vho_lower = FALSE;
01899 #endif
01900 }
01901 }
01902 }
01903
01904 void
01905 WN_INSTRUMENT_WALKER::Merge_Icall_Feedback()
01906 {
01907 if (_fb_handle_merged)
01908 {
01909 DevWarn("Icall feecback data already merged!\n");
01910 return;
01911 }
01912 if (_fb_handle.size() == 0)
01913 {
01914 DevWarn("no Icall feedback data for current PU.\n");
01915 _fb_handle_merged = NULL;
01916 return;
01917 }
01918
01919
01920 _fb_handle_merged = CXX_NEW(PU_Profile_Handle(NULL, 0), _mempool);
01921 FB_Icall_Vector & fb_merged_value_vector = _fb_handle_merged->Get_Icall_Table();
01922 INT fb_handle_num;
01923 fb_handle_num = _fb_handle.size();
01924 PU_PROFILE_HANDLE the_largest_fb;
01925 PU_PROFILE_ITERATOR pu_prof_itr = _fb_handle.begin();
01926 the_largest_fb = *pu_prof_itr;
01927 _fb_count_icall = the_largest_fb->Get_Icall_Table().size();
01928 for (pu_prof_itr= ( _fb_handle.begin() ); pu_prof_itr != _fb_handle.end (); ++pu_prof_itr)
01929 {
01930 PU_Profile_Handle * handle=*pu_prof_itr;
01931 if ( _fb_count_icall != handle->Icall_Profile_Table.size() )
01932 DevWarn("Icall_Profile_Table.size() differ in feedback files!");
01933 if ( _fb_count_icall < handle->Icall_Profile_Table.size() )
01934 {
01935 the_largest_fb = handle;
01936 _fb_count_icall = the_largest_fb->Icall_Profile_Table.size();
01937 }
01938 }
01939
01940 fb_merged_value_vector.resize(_fb_count_icall);
01941 if (_fb_count_icall==0)
01942 {
01943 return;
01944 }
01945
01946 UINT64 * values = TYPE_MEM_POOL_ALLOC_N(UINT64, _mempool, TNV_N*fb_handle_num);
01947 UINT64 * counters = TYPE_MEM_POOL_ALLOC_N(UINT64, _mempool, TNV_N*fb_handle_num);
01948 INT i, j, k, m, n;
01949 for ( i=0; i<_fb_count_icall; i++ )
01950 {
01951 memset(values, 0, TNV_N*fb_handle_num*sizeof(UINT64));
01952 memset(counters, 0, TNV_N*fb_handle_num*sizeof(UINT64));
01953 INT32 cur_id = the_largest_fb->Icall_Profile_Table[i].tnv._id;
01954 if (cur_id != i)
01955 {
01956 Is_True( cur_id == 0, ("cur_id should either be 0(means not executed) or i"));
01957 cur_id = i;
01958 }
01959 UINT64 cur_exec_counter = 0;
01960 INT cur_flag = the_largest_fb->Icall_Profile_Table[i].tnv._flag;
01961 for (pu_prof_itr = _fb_handle.begin(); pu_prof_itr != _fb_handle.end (); ++pu_prof_itr)
01962 {
01963 if ( i >= (*pu_prof_itr)->Get_Icall_Table().size() )
01964 continue;
01965 FB_Info_Icall & fb_info_value = Get_Icall_Profile( *pu_prof_itr, i );
01966 if (fb_info_value.tnv._id != cur_id)
01967 {
01968
01969
01970 Is_True( fb_info_value.tnv._id == 0 ,("_id not consitent between feedback files"));
01971 continue;
01972 }
01973 cur_exec_counter += fb_info_value.tnv._exec_counter;
01974 Is_True(fb_info_value.tnv._flag == cur_flag,("_flag not consitent between feedback files"));
01975 for ( j=0; j<TNV_N; j++ )
01976 {
01977 if ( fb_info_value.tnv._counters[j] == 0 )
01978 break;
01979 for ( m=0;m<TNV_N*fb_handle_num;m++)
01980 {
01981 if (counters[m] == 0)
01982 {
01983 values[m] = fb_info_value.tnv._values[j];
01984 counters[m] += fb_info_value.tnv._counters[j];
01985 break;
01986 }
01987 else if ( fb_info_value.tnv._values[j] == values[m] )
01988 {
01989 counters[m] += fb_info_value.tnv._counters[j];
01990 break;
01991 }
01992 }
01993 }
01994 }
01995 for ( m=0; m<TNV_N*fb_handle_num; m++ )
01996 for ( n=m+1; n<TNV_N*fb_handle_num; n++)
01997 {
01998 if (counters[m] < counters[n])
01999 {
02000 INT tmp;
02001 tmp = counters[m];
02002 counters[m] = counters[n];
02003 counters[n] = tmp;
02004 }
02005 }
02006 fb_merged_value_vector[i].tnv._id = cur_id;
02007 fb_merged_value_vector[i].tnv._exec_counter = cur_exec_counter;
02008 fb_merged_value_vector[i].tnv._flag = cur_flag;
02009 for ( m=0; m<TNV_N; m++ )
02010 {
02011 fb_merged_value_vector[i].tnv._values[m] = values[m];
02012 fb_merged_value_vector[i].tnv._counters[m] = counters[m];
02013 }
02014 }
02015 }
02016
02017 INT32
02018 WN_node_count(WN * wn)
02019 {
02020 INT32 count = 0;
02021 for (WN_ITER * wni=WN_WALK_TreeIter(wn); wni; wni=WN_WALK_TreeNext(wni))
02022 {
02023 count++;
02024 }
02025 return count;
02026 }
02027
02028 void
02029 WN_INSTRUMENT_WALKER::Tree_Walk( WN *root )
02030 {
02031
02032 Is_True( WN_operator( root ) == OPR_FUNC_ENTRY,
02033 ( "WN_INSTRUMENT_WALKER::Tree_Walk:"
02034 " OPR_FUNC_ENTRY expected at top of PU tree." ) );
02035
02036
02037 Is_True( _instrumenting || Cur_PU_Feedback,
02038 ( "WN_INSTRUMENT_WALKER::Tree_Walk:"
02039 " NULL Cur_PU_Feedbackduring annotation" ) );
02040
02041
02042 Is_True( _instrumenting || ! _fb_handle.empty (),
02043 ( "WN_INSTRUMENT_WALKER::Tree_Walk: No feedback info for"
02044 " program unit %s in file %s.", Cur_PU_Name, Src_File_Name ) );
02045
02046
02047
02048
02049
02050
02051
02052 #if Instrumenter_DEBUG
02053 fdump_tree( TFile, root );
02054 #endif
02055
02056 if ( !_instrumenting )
02057 {
02058 Is_True(_fb_handle_merged == NULL, ("Merged Feedback data for Icall should be NULL before anyone merge it!"));
02059 Merge_Icall_Feedback();
02060 if (_fb_handle_merged == NULL)
02061 {
02062 DevWarn("There is no Icall feedback data for current PU!");
02063 }
02064 }
02065
02066 #ifdef KEY
02067 pu_wn = root;
02068 #endif
02069
02070
02071
02072 _in_preamble = TRUE;
02073 WN* body = WN_func_body( root );
02074 INT32 pusize_est = WN_node_count(body);
02075 WN* stmt;
02076 for ( stmt = WN_first( body ); stmt; stmt = WN_next( stmt ) )
02077 Tree_Walk_Node( stmt, stmt, body );
02078 Is_True( ! _in_preamble, ( "WN_INSTRUMENT_WALKER::Tree_Walk found"
02079 " no WN_PRAGMA_PREAMBLE_END pragma" ) );
02080
02081
02082 if ( _instrumenting && _instrument_count > 0 ) {
02083
02084
02085 while ( ! Entry_List_Empty() ) {
02086
02087
02088
02089 WN *output_file_name
02090 = WN_LdaString( Instrumentation_File_Name, 0,
02091 strlen( Instrumentation_File_Name ) + 1 );
02092 WN *phasenum = WN_Intconst( MTYPE_I4, _phase );
02093
02094 WN *unique_output = WN_Intconst( MTYPE_I4,
02095 Instrumentation_Unique_Output );
02096
02097
02098 Instrument_Entry( Gen_Call( INST_INIT_NAME, output_file_name,
02099 phasenum, unique_output ) );
02100
02101
02102 WN *src_file_name = WN_LdaString ( Src_File_Name, 0,
02103 strlen( Src_File_Name ) + 1 );
02104 WN *pu_name = WN_LdaString ( Cur_PU_Name, 0, strlen( Cur_PU_Name ) + 1 );
02105 WN *pc = WN_Lda( Pointer_type, 0, WN_st( root ) );
02106 WN *pusize = WN_Intconst( MTYPE_I4, pusize_est );
02107 WN *checksum = WN_Intconst( MTYPE_I4, _instrument_count );
02108
02109
02110 #ifdef KEY
02111
02112
02113
02114
02115 if( PU_is_extern_inline(Get_Current_PU()) ){
02116 pc = WN_Zerocon( Pointer_type );
02117 }
02118 #endif
02119 Instrument_Entry( Gen_Call( PU_INIT_NAME, src_file_name,
02120 pu_name, pc, pusize, checksum, Pointer_type ) );
02121
02122
02123 PREG_NUM rreg1, rreg2;
02124
02125 if ( WHIRL_Return_Info_On ) {
02126
02127 RETURN_INFO return_info
02128 = Get_Return_Info( Be_Type_Tbl( Pointer_type ), Use_Simulated
02129 #ifdef TARG_X8664
02130 , PU_ff2c_abi(Get_Current_PU())
02131 #endif
02132 );
02133
02134 if ( RETURN_INFO_count( return_info ) <= 2 ) {
02135 rreg1 = RETURN_INFO_preg( return_info, 0 );
02136 rreg2 = RETURN_INFO_preg( return_info, 1 );
02137 } else
02138 Fail_FmtAssertion( "WN_Instrumenter::WN_tree_init:"
02139 " more than 2 return registers");
02140 } else {
02141 Get_Return_Pregs( Pointer_type, MTYPE_UNKNOWN, &rreg1, &rreg2 );
02142 }
02143
02144
02145 Instrument_Entry( WN_Stid(Pointer_type, 0, _pu_handle,
02146 MTYPE_To_TY(Pointer_type),
02147 WN_LdidPreg( Pointer_type, rreg1 ) ) );
02148
02149
02150 Initialize_Instrumenter_Invoke( _count_invoke );
02151 Initialize_Instrumenter_Branch( _count_branch );
02152 Initialize_Instrumenter_Loop( _count_loop );
02153 Initialize_Instrumenter_Circuit( _count_circuit );
02154 Initialize_Instrumenter_Call( _count_call );
02155 Initialize_Instrumenter_Icall( _count_icall );
02156 Initialize_Instrumenter_Switch( _count_switch );
02157 Initialize_Instrumenter_Compgoto( _count_compgoto );
02158 #ifdef KEY
02159 Initialize_Instrumenter_Value( _count_value );
02160 #if !defined(TARG_SL)
02161 Initialize_Instrumenter_Value_FP_Bin( _count_value_fp_bin );
02162 #endif
02163 #endif
02164 Pop_Entry_Pragma();
02165 }
02166
02167
02168 if ( _vho_lower ) {
02169 WN_func_body( root ) = VHO_Lower( WN_func_body( root ) );
02170 _vho_lower = FALSE;
02171 }
02172
02173 } else if ( ! _instrumenting ) {
02174
02175
02176 for ( PU_PROFILE_ITERATOR i( _fb_handle.begin() );
02177 i != _fb_handle.end(); ++i ) {
02178
02179 UINT32 checksum = Get_PU_Checksum( *i );
02180
02181 #ifdef KEY
02182 if (_instrument_count != checksum)
02183 ErrMsg(EC_FB_File_Old, (*i)->fb_name);
02184 #else
02185 FmtAssert( _instrument_count == checksum,
02186 ( "Instrumenter Error: (Phase %d) Suspected obsolete feedback file %s has "
02187 "invalid checksum for program unit %s in file %s. "
02188 "Computed = %d, In file = %d.",
02189 _phase, (*i)->fb_name, Cur_PU_Name, Src_File_Name,
02190 _instrument_count, checksum ) );
02191 #endif
02192 }
02193 }
02194
02195 #if Instrumenter_DEBUG
02196 fdump_tree(TFile, root);
02197 #endif
02198 }
02199
02200
02201
02202
02203
02204
02205
02206
02207
02208
02209
02210
02211
02212
02213
02214
02215
02216
02217
02218
02219 void
02220 WN_Instrument( WN *wn, PROFILE_PHASE phase )
02221 {
02222 Set_Error_Phase( "WN_Instrument" );
02223 if ( Instrumenter_DEBUG )
02224 DevWarn( "WN_Instrument, phase == %d", phase );
02225
02226
02227 MEM_POOL local_mempool;
02228 MEM_POOL_Initialize( &local_mempool, "WN_INSTRUMENT_WALKER_Pool", FALSE );
02229 MEM_POOL_Push( &local_mempool );
02230 {
02231
02232 PU_PROFILE_HANDLES fb_handles;
02233 WN_INSTRUMENT_WALKER wiw( TRUE, phase, &local_mempool, fb_handles );
02234 wiw.Tree_Walk( wn );
02235 }
02236
02237 MEM_POOL_Pop( &local_mempool );
02238 MEM_POOL_Delete( &local_mempool );
02239 }
02240
02241 void
02242 WN_Clean_Mapid_for_Calls(WN * wn)
02243 {
02244 for (WN_ITER * wni=WN_WALK_TreeIter(wn); wni; wni=WN_WALK_TreeNext(wni))
02245 {
02246 WN * wntmp = WN_ITER_wn(wni);
02247 OPCODE opcode;
02248 OPERATOR opr;
02249 opcode = WN_opcode (wntmp);
02250 opr = WN_operator(wntmp);
02251
02252 if ( opr == OPR_CALL || opr == OPR_ICALL )
02253 {
02254 if (WN_map_id(wntmp) != -1)
02255 {
02256 WN_set_map_id(wntmp, -1);
02257 }
02258 }
02259 }
02260 }
02261
02262 void
02263 WN_Annotate( WN *wn, PROFILE_PHASE phase, MEM_POOL *MEM_pu_pool )
02264 {
02265 Set_Error_Phase( "WN_Annotate" );
02266 if ( Instrumenter_DEBUG )
02267 DevWarn( "WN_Annotate, phase == %d", phase );
02268
02269 WN_Clean_Mapid_for_Calls(wn);
02270
02271
02272
02273
02274 PU_PROFILE_HANDLES fb_handles
02275 = Get_PU_Profile( Cur_PU_Name, Src_File_Name,
02276 Feedback_File_Info[phase] );
02277 if ( fb_handles.empty() ) {
02278 #ifdef KEY
02279 DevWarn( "Function %s() is not called in the training run", Cur_PU_Name );
02280 #else
02281 DevWarn( "Cannot find expected feedback data - function not called?" );
02282 #endif
02283 return;
02284 } else {
02285
02286 if ( Cur_PU_Feedback == NULL )
02287 Cur_PU_Feedback = CXX_NEW( FEEDBACK( wn, MEM_pu_pool ), MEM_pu_pool );
02288 }
02289
02290
02291 MEM_POOL local_mempool;
02292 MEM_POOL_Initialize( &local_mempool, "WN_INSTRUMENT_WALKER_Pool", FALSE );
02293 MEM_POOL_Push( &local_mempool );
02294 {
02295
02296 WN_INSTRUMENT_WALKER wiw( FALSE, phase, &local_mempool, fb_handles );
02297 wiw.Tree_Walk( wn );
02298 }
02299
02300 MEM_POOL_Pop( &local_mempool );
02301 MEM_POOL_Delete( &local_mempool );
02302
02303 #ifdef KEY
02304 Cur_PU_Feedback->Set_Runtime_Func_Addr( 0 );
02305
02306 for( PU_PROFILE_ITERATOR i( fb_handles.begin() );
02307 i != fb_handles.end(); ++i ){
02308 const PU_PROFILE_HANDLE h = *i;
02309 const UINT64 addr = Cur_PU_Feedback->Get_Runtime_Func_Addr();
02310
02311 if( addr == 0 ){
02312 Cur_PU_Feedback->Set_Runtime_Func_Addr( h->runtime_fun_address );
02313
02314 } else if( addr != h->runtime_fun_address ){
02315 Cur_PU_Feedback->Set_Runtime_Func_Addr( 0 );
02316 break;
02317 }
02318 }
02319 #endif
02320
02321 Cur_PU_Feedback->Verify("after annotation");
02322 }
02323
02324
02325 void
02326 Set_Instrumentation_File_Name( char *fname )
02327 {
02328 if ( fname ) {
02329 Instrumentation_File_Name
02330 = (char *) malloc( sizeof( char ) *
02331 ( strlen(fname)
02332 + Instrumentation_Phase_Num / 10 + 2 ) );
02333 sprintf( Instrumentation_File_Name, "%s%d", fname,
02334 Instrumentation_Phase_Num );
02335
02336 } else {
02337 DevWarn( "Instrumenter Warning: Invalid instrumentation file name." );
02338 Instrumentation_File_Name = const_cast<char*>("");
02339 }
02340 }
02341
02342
02343