Open64 (mfef90, whirl2f, and IR tools)  TAG: version-openad; SVN changeset: 916
fb_info.h
Go to the documentation of this file.
00001 /*
00002 
00003   Copyright (C) 2000, 2001 Silicon Graphics, Inc.  All Rights Reserved.
00004 
00005   This program is free software; you can redistribute it and/or modify it
00006   under the terms of version 2 of the GNU General Public License as
00007   published by the Free Software Foundation.
00008 
00009   This program is distributed in the hope that it would be useful, but
00010   WITHOUT ANY WARRANTY; without even the implied warranty of
00011   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
00012 
00013   Further, this software is distributed without any warranty that it is
00014   free of the rightful claim of any third person regarding infringement 
00015   or the like.  Any license provided herein, whether implied or 
00016   otherwise, applies only to this software file.  Patent licenses, if 
00017   any, provided herein do not apply to combinations of this program with 
00018   other software, or any other product whatsoever.  
00019 
00020   You should have received a copy of the GNU General Public License along
00021   with this program; if not, write the Free Software Foundation, Inc., 59
00022   Temple Place - Suite 330, Boston MA 02111-1307, USA.
00023 
00024   Contact information:  Silicon Graphics, Inc., 1600 Amphitheatre Pky,
00025   Mountain View, CA 94043, or:
00026 
00027   http://www.sgi.com
00028 
00029   For further information regarding this notice, see:
00030 
00031   http://oss.sgi.com/projects/GenInfo/NoticeExplan
00032 
00033 */
00034 
00035 
00036 //-*-c++-*-
00037 // ====================================================================
00038 // ====================================================================
00039 //
00040 //
00041 // Description:
00042 //
00043 // During instrumentation, certain events associated with program
00044 // control flow (such as the number of times a particular branch is
00045 // taken, or not taken) are counted.  During subsequent compilations,
00046 // this data may be retrieved and used to guide optimization decisions.
00047 //
00048 // fb_info.h defines data structs used to store this feedback data for
00049 // various types of whirl nodes.  These structures are used by the
00050 // FEEDBACK class (defined in fb_whirl.h) and by the instrumentation runtime
00051 //
00052 // ====================================================================
00053 // ====================================================================
00054 
00055 #ifndef fb_info_INCLUDED
00056 #define fb_info_INCLUDED
00057 
00058 #include "fb_freq.h"
00059 
00060 #include <vector>
00061 
00062 using namespace std;
00063 
00064 #ifdef MONGOOSE_BE
00065 
00066 #ifndef mempool_allocator_INCLUDED
00067 #include "mempool_allocator.h"
00068 #endif
00069 
00070 #ifndef wn_INCLUDED
00071 #include "wn.h"
00072 #endif
00073 
00074 #endif // MONGOOSE_BE
00075 
00076 
00077 // data structures shared by both the instrumentation runtime and the back
00078 // end. 
00079 
00080 struct FB_Info_Invoke {
00081 
00082   FB_FREQ freq_invoke;    // number of times statement invoked
00083 
00084   FB_Info_Invoke( FB_FREQ invoke)
00085     : freq_invoke( invoke ) {}
00086 
00087   FB_Info_Invoke() :
00088 
00089 /* Solaris workaround
00090  * compiler encountered error because there's no definition of
00091  * FB_FREQ(const FB_FREQ) constructor, see fb_freq.h --
00092  * seems like it should call the constructor - FB_FREQ(
00093  * FB_FREQ_TYPE_UNINIT) instead.
00094  */
00095 freq_invoke( FB_FREQ_TYPE_UNINIT ) { }
00096 
00097   void Print( FILE *fp ) const {
00098     fprintf( fp, "FB---> invoke = " );
00099     freq_invoke.Print( fp );
00100   }
00101 };
00102 
00103 struct FB_Info_Branch {
00104 
00105   FB_FREQ freq_taken;     // number of times branch taken
00106                           // (then clause for IF, Kid0 for CSELECT)
00107   FB_FREQ freq_not_taken; // number of times branch not taken
00108                           // (else clause for IF, Kid1 for CSELECT)
00109 
00110   FB_Info_Branch( FB_FREQ taken, FB_FREQ not_taken )
00111     : freq_taken(     taken ),
00112       freq_not_taken( not_taken ) {}
00113 
00114 #ifdef MONGOOSE_BE
00115   FB_Info_Branch( FB_FREQ taken, FB_FREQ not_taken, OPERATOR opr )
00116     : freq_taken(     opr != OPR_FALSEBR ? taken : not_taken ),
00117       freq_not_taken( opr != OPR_FALSEBR ? not_taken : taken ) {
00118     // if opr == OPR_FALSEBR, then reverse taken and not_taken
00119     Is_True( opr == OPR_TRUEBR || opr == OPR_FALSEBR
00120              || opr == OPR_IF || opr == OPR_CSELECT,
00121              ( "FB_Info_Branch found unexpected operator" ) );
00122   }
00123 #endif // MONGOOSE_BE
00124 
00125 
00126 /*
00127  * Same change, see before
00128  */
00129 FB_Info_Branch()
00130     : freq_taken(     FB_FREQ_TYPE_UNINIT ),
00131       freq_not_taken( FB_FREQ_TYPE_UNINIT ) {}
00132 
00133   void Print( FILE *fp ) const {
00134     fprintf( fp, "FB---> taken = " );
00135     freq_taken.Print( fp );
00136     fprintf( fp, ", not_taken = " );
00137     freq_not_taken.Print( fp );
00138   }
00139 
00140   FB_FREQ Total() const {
00141     return ( freq_taken + freq_not_taken );
00142   }
00143 };
00144 
00145 // ====================================================================
00146 
00147 // Feedback info for a loop node
00148 //         ___|__
00149 //        | test |
00150 //        |______|
00151 //          /  \
00152 //     zero/N  Y\positive
00153 //        /      \    ____
00154 //        |      _\__/_   \
00155 //        |     | body |   |
00156 //        |     |______|   |        exit    = zero     + out
00157 //        |     | test |   |        iterate = positive + back
00158 //        |     |______|   |
00159 //        |       /  \    /         In a DO_WHILE loop, zero = 0.
00160 //        |   out/N  Y\__/
00161 //         \    /     back
00162 //         _\__/_
00163 //        |      |
00164 
00165 
00166 struct FB_Info_Loop {
00167 
00168   FB_FREQ freq_zero;
00169   FB_FREQ freq_positive;
00170   FB_FREQ freq_out;
00171   FB_FREQ freq_back;
00172   FB_FREQ freq_exit;
00173   FB_FREQ freq_iterate;
00174 
00175   FB_Info_Loop( FB_FREQ zero, FB_FREQ positive, FB_FREQ out, FB_FREQ back,
00176                 FB_FREQ exit, FB_FREQ iterate )
00177     : freq_zero(     zero ),
00178       freq_positive( positive ),
00179       freq_out(      out ),
00180       freq_back(     back ),
00181       freq_exit(     exit ),
00182       freq_iterate(  iterate ) {}
00183 
00184   FB_Info_Loop( FB_FREQ zero, FB_FREQ positive, FB_FREQ out, FB_FREQ back )
00185     : freq_zero(     zero ),
00186       freq_positive( positive ),
00187       freq_out(      out ),
00188       freq_back(     back ),
00189       freq_exit(     zero + out ),
00190       freq_iterate(  positive + back ) {}
00191 
00192   FB_Info_Loop( FB_FREQ exit, FB_FREQ iterate )
00193     : freq_zero(     FB_FREQ_UNKNOWN ),
00194       freq_positive( FB_FREQ_UNKNOWN ),
00195       freq_out(      FB_FREQ_UNKNOWN ),
00196       freq_back(     FB_FREQ_UNKNOWN ),
00197       freq_exit(     exit ),
00198       freq_iterate(  iterate ) {}
00199  
00200 /*
00201  * Same change, see before
00202  */ 
00203   FB_Info_Loop()
00204     : freq_zero(     FB_FREQ_TYPE_UNINIT ),
00205       freq_positive( FB_FREQ_TYPE_UNINIT ),
00206       freq_out(      FB_FREQ_TYPE_UNINIT ),
00207       freq_back(     FB_FREQ_TYPE_UNINIT ),
00208       freq_exit(     FB_FREQ_TYPE_UNINIT ),
00209       freq_iterate(  FB_FREQ_TYPE_UNINIT ) {}
00210 
00211 
00212 
00213   void Print( FILE *fp ) const {
00214     fprintf( fp, "FB---> zero = " );
00215     freq_zero.Print( fp );
00216     fprintf( fp, ", positive = " );
00217     freq_positive.Print( fp );
00218     fprintf( fp, ", out = " );
00219     freq_out.Print( fp );
00220     fprintf( fp, ", back = " );
00221     freq_back.Print( fp );
00222     fprintf( fp, "\n       exit = " );
00223     freq_exit.Print( fp );
00224     fprintf( fp, ", iterate = " );
00225     freq_iterate.Print( fp );
00226   }
00227 
00228   FB_FREQ Total() const {
00229     return ( freq_exit + freq_iterate );
00230   }
00231 
00232   float Loop_lower_scale() const {
00233     FB_FREQ freq_scale = ( freq_zero + freq_positive ) / Total();
00234     if ( freq_scale.Known() )
00235       return freq_scale.Value();
00236     else
00237       return 0.1;  // This is a wild guess!!
00238   }
00239 };
00240 
00241 struct FB_Info_Circuit {
00242 
00243   FB_FREQ freq_left;   // "taken" means false for CAND, true for CIOR
00244   FB_FREQ freq_right;
00245   FB_FREQ freq_neither;
00246 
00247   FB_Info_Circuit( FB_FREQ left, FB_FREQ right, FB_FREQ neither )
00248     : freq_left(    left    ),
00249       freq_right(   right   ),
00250       freq_neither( neither ) {}
00251 
00252 /*
00253  * same change, see before
00254  */
00255   FB_Info_Circuit()
00256     : freq_left(    FB_FREQ_TYPE_UNINIT ),
00257     freq_right(   FB_FREQ_TYPE_UNINIT ),
00258     freq_neither( FB_FREQ_TYPE_UNINIT ) {}
00259 
00260 
00261   void Print( FILE *fp ) const {
00262     fprintf( fp, "FB---> left = " );
00263     freq_left.Print( fp );
00264     fprintf( fp, ", right = " );
00265     freq_right.Print( fp );
00266     fprintf( fp, ", neither = " );
00267     freq_neither.Print( fp );
00268   }
00269 
00270   FB_FREQ Total() const {
00271     return ( freq_left + freq_right + freq_neither );
00272   }
00273 };
00274 
00275 
00276 struct FB_Info_Call {
00277   FB_FREQ freq_entry;
00278   FB_FREQ freq_exit;
00279   BOOL    in_out_same;  // TRUE iff freq_entry and freq_exit must be ==
00280   BOOL    dummy_buffer; // FB_Info_Call size must be 0 mod 64bits for
00281                         //   consistent feedback file alignment in IA32/64
00282 
00283   FB_Info_Call( FB_FREQ entry, FB_FREQ exit, BOOL same = FALSE )
00284     : freq_entry(  entry ),
00285       freq_exit(   exit  ),
00286       in_out_same( same ) {
00287     Is_True( freq_entry == freq_exit || ! in_out_same,
00288              ( "FEEDBACK::Annot_call: in_out_same failure" ) );
00289   }
00290 
00291   FB_Info_Call( FB_FREQ entry_and_exit )
00292     : freq_entry(  entry_and_exit ),
00293       freq_exit(   entry_and_exit ),
00294       in_out_same( TRUE  ) {}
00295 
00296 /* 
00297  * same change, see before
00298  */
00299   FB_Info_Call() :
00300     freq_entry(FB_FREQ_TYPE_UNINIT),
00301     freq_exit(FB_FREQ_TYPE_UNINIT),
00302     in_out_same(FALSE) {}
00303 
00304 
00305   void Print( FILE *fp ) const {
00306     fprintf( fp, "FB---> entry = " );
00307     freq_entry.Print( fp );
00308     fprintf( fp, ", exit = " );
00309     freq_exit.Print( fp );
00310     fprintf( fp, ", in_out_same = %c", in_out_same ? 'Y' : 'N' );
00311   }
00312 };
00313 
00314 
00315 struct FB_Info_Switch {
00316 
00317   vector<FB_FREQ> freq_targets;
00318 
00319   FB_Info_Switch() {}
00320 
00321 /*
00322  * NOTE: these two lines look strange ???
00323  */
00324   FB_Info_Switch( const vector<FB_FREQ>::size_type n )
00325     : freq_targets( vector<FB_FREQ>( n, FB_FREQ_UNINIT ) ) {}
00326 
00327   FB_FREQ& operator[] ( const vector<FB_FREQ>::size_type n ) {
00328     if ( n >= freq_targets.size() ) {
00329       freq_targets.insert( freq_targets.end(), n - freq_targets.size() + 1,
00330                            FB_FREQ_UNINIT );
00331     }
00332     return freq_targets[n];
00333   }
00334 
00335   const FB_FREQ& operator[] ( const vector<FB_FREQ>::size_type n ) const {
00336     return ( n >= freq_targets.size() ? FB_FREQ_UNINIT : freq_targets[n] );
00337   }
00338     
00339   vector<FB_FREQ>::size_type size() const {
00340     return freq_targets.size();
00341   }
00342 
00343   vector<FB_FREQ>::const_reference back() const {
00344     return freq_targets.back();
00345   }
00346 
00347   void pop_back() {
00348     freq_targets.pop_back();
00349   }
00350 
00351   void Print( FILE *fp ) const {
00352     fprintf( fp, "FB---> targets = %d", (INT) freq_targets.size() );
00353     for ( INT t = 0; t < freq_targets.size(); t++ ) {
00354       fprintf( fp, ", %d: ", t );
00355       freq_targets[t].Print( fp );
00356     }
00357   }
00358 
00359   FB_FREQ Total() const {
00360     vector<FB_FREQ>::const_iterator iter;
00361     FB_FREQ freq = FB_FREQ_ZERO;
00362     for ( iter = freq_targets.begin(); iter != freq_targets.end(); iter++ ) {
00363       freq += *iter;
00364     }
00365     return freq;
00366   }
00367 };
00368 
00369 
00370 // Print the entire FB_Info vector
00371 template <class T>
00372 void
00373 FB_Info_Print (const T& info, const char* name, FILE *fp)
00374 {
00375     size_t size = info.size ();
00376 
00377     if (size != 0)
00378         fprintf (fp, "%s Profile:\n", name);
00379     for (size_t i = 0; i < size; i++) {
00380         fprintf(fp, "\t%s id = %d\t", name, i);
00381         info[i].Print (fp);
00382         fputc ('\n', fp);
00383     }
00384 }
00385 
00386 
00387 // utilities and definitions only used by the back end (and not by the
00388 // instrumentation runtime
00389 #ifdef MONGOOSE_BE
00390 
00391 typedef vector<FB_Info_Invoke, mempool_allocator<FB_Info_Invoke> >
00392                                         FB_Invoke_Vector;
00393 typedef vector<FB_Info_Branch, mempool_allocator<FB_Info_Branch> >
00394                                         FB_Branch_Vector;
00395 typedef vector<FB_Info_Loop, mempool_allocator<FB_Info_Loop> >
00396                                         FB_Loop_Vector;
00397 typedef vector<FB_Info_Circuit, mempool_allocator<FB_Info_Circuit> >
00398                                         FB_Circuit_Vector;
00399 typedef vector<FB_Info_Call, mempool_allocator<FB_Info_Call> >
00400                                         FB_Call_Vector;
00401 typedef vector<FB_Info_Switch, mempool_allocator<FB_Info_Switch> >
00402                                         FB_Switch_Vector;
00403 
00404 // ====================================================================
00405 // FB_EDGE_TYPE -- Indicates the source of a node's frequency data
00406 //
00407 // Frequency values are assigned to edges in the control flow graph.
00408 // ====================================================================
00409 
00410 // FB_IO_ESCAPE_EDGES_MAX is the maximum number of labels that can appear
00411 //   within the ITEMs pf an IO as branch targets.
00412 
00413 #define FB_IO_ESCAPE_EDGES_MAX 3
00414 
00415 enum FB_EDGE_TYPE {
00416   FB_EDGE_UNINIT           =  0,  // NOTE: If any of these are changed, then
00417   FB_EDGE_INCOMING         =  1,  // the array FB_EDGE_NAMES in fb_info.cxx
00418   FB_EDGE_OUTGOING         =  2,  // must also be updated!
00419   FB_EDGE_ENTRY_OUTGOING   =  3,
00420   FB_EDGE_BRANCH_TAKEN     =  4,
00421   FB_EDGE_BRANCH_NOT_TAKEN =  5,
00422   FB_EDGE_LOOP_ZERO        =  6,
00423   FB_EDGE_LOOP_POSITIVE    =  7,
00424   FB_EDGE_LOOP_OUT         =  8,
00425   FB_EDGE_LOOP_BACK        =  9,
00426   FB_EDGE_LOOP_EXIT        = 10,  // EXIT    == ZERO     + OUT
00427   FB_EDGE_LOOP_ITERATE     = 11,  // ITERATE == POSITIVE + BACK
00428   FB_EDGE_CIRCUIT_LEFT     = 12,
00429   FB_EDGE_CIRCUIT_RIGHT    = 13,
00430   FB_EDGE_CIRCUIT_NEITHER  = 14,
00431   FB_EDGE_CALL_INCOMING    = 15,
00432   FB_EDGE_CALL_OUTGOING    = 16,
00433   FB_EDGE_CALL_INOUTSAME   = 17,
00434   FB_EDGE_IO_OUTGOING      = 18,
00435   FB_EDGE_IO_ESCAPE_BASE   = 19,
00436   FB_EDGE_SWITCH_DEFAULT   = 22,  // 19 + FB_IO_ESCAPE_EDGES_MAX
00437   FB_EDGE_SWITCH_BASE      = 23   // must be last
00438 };
00439 
00440 // IO     branch br is BASE + br; 0 <= br < FB_IO_ESCAPE_EDGES_MAX
00441 // SWITCH branch br is BASE + br; 0 <= br
00442 
00443 #define FB_EDGE_IO_ESCAPE(br) ( FB_EDGE_TYPE( FB_EDGE_IO_ESCAPE_BASE + (br) ) )
00444 
00445 #define FB_EDGE_SWITCH(br)    ( FB_EDGE_TYPE( FB_EDGE_SWITCH_BASE    + (br) ) )
00446 #define FB_EDGE_SWITCH_INDEX(typ)  ( INT32( (typ) - FB_EDGE_SWITCH_BASE + 1 ) )
00447 
00448 #define FB_EDGE_TYPE_NAME_LENGTH 20  // buffer length required for
00449                                      //   FB_EDGE_TYPE_sprintf
00450 
00451 extern const char *FB_EDGE_NAMES[];
00452 
00453 void FB_EDGE_TYPE_fprintf( FILE *fp,     const FB_EDGE_TYPE fb_type );
00454 INT  FB_EDGE_TYPE_sprintf( char *buffer, const FB_EDGE_TYPE fb_type );
00455 
00456 
00457 // ====================================================================
00458 // The following structures hold feedback info for the incoming and
00459 // outgoing edges of various kinds of whirl nodes.
00460 // ====================================================================
00461 
00462 // Minimal feedback info for label, goto, entry and return nodes, and
00463 // the WN_PRAGMA_PREAMBLE_END PRAGMA node
00464 
00465 #define fb_opr_cases_invoke \
00466   case OPR_LABEL:           \
00467   case OPR_GOTO:            \
00468   case OPR_MSTORE:          \
00469   case OPR_FUNC_ENTRY:      \
00470   case OPR_ALTENTRY:        \
00471   case OPR_RETURN:          \
00472   case OPR_RETURN_VAL
00473 // Note that OPR_PRAGMA is not included in fb_opr_cases_invoke
00474 
00475 inline bool FB_valid_opr_invoke(const WN *wn) {
00476   OPERATOR opr = WN_operator( wn );
00477   switch ( opr ) {
00478   fb_opr_cases_invoke:
00479     return true;
00480   case OPR_PRAGMA:
00481     return ( WN_pragma( wn ) == WN_PRAGMA_PREAMBLE_END );
00482   default:
00483     return false;
00484   }
00485 }
00486 
00487 
00488 // ====================================================================
00489 
00490 // Feedback info for a branch node
00491 // IDEA: Within a loop test expression, distinguish for CSELECT between
00492 //       first and later trips
00493 
00494 #define fb_opr_cases_branch \
00495   case OPR_TRUEBR:          \
00496   case OPR_FALSEBR:         \
00497   case OPR_IF:              \
00498   case OPR_CSELECT
00499 
00500 inline bool FB_valid_opr_branch(const WN *wn) {
00501   OPERATOR opr = WN_operator( wn );
00502   switch ( opr ) {
00503   fb_opr_cases_branch:
00504     return true;
00505   default:
00506     return false;
00507   }
00508 }
00509 
00510 
00511 // ====================================================================
00512 
00513 #define fb_opr_cases_loop \
00514   case OPR_DO_LOOP:       \
00515   case OPR_WHILE_DO:      \
00516   case OPR_DO_WHILE
00517 
00518 inline bool FB_valid_opr_loop(const WN *wn) {
00519   OPERATOR opr = WN_operator( wn );
00520   switch ( opr ) {
00521   fb_opr_cases_loop:
00522     return true;
00523   default:
00524     return false;
00525   }
00526 }
00527 
00528 // ====================================================================
00529 
00530 // Feedback info for OPR_CAND and/or OPR_CIOR
00531 // IDEA: Within a loop test expression, distinguish between first and later
00532 //       trips
00533 
00534 #define fb_opr_cases_circuit \
00535   case OPR_CAND:             \
00536   case OPR_CIOR
00537 
00538 inline bool FB_valid_opr_circuit(const WN *wn) {
00539   OPERATOR opr = WN_operator( wn );
00540   switch ( opr ) {
00541   fb_opr_cases_circuit:
00542     return true;
00543   default:
00544     return false;
00545   }
00546 }
00547 
00548 
00549 // ====================================================================
00550 // Feedback info for a call
00551 
00552 #define fb_opr_cases_call  \
00553   case OPR_PICCALL:        \
00554   case OPR_CALL:           \
00555   case OPR_ICALL:          \
00556   case OPR_INTRINSIC_CALL: \
00557   case OPR_IO
00558 // case OPR_REGION:
00559 
00560 inline bool FB_valid_opr_call(const WN *wn) {
00561   OPERATOR opr = WN_operator( wn );
00562   switch ( opr ) {
00563   fb_opr_cases_call:
00564     return true;
00565   default:
00566     return false;
00567   }
00568 }
00569 
00570 
00571 // ====================================================================
00572 
00573 // Feedback info for a OPR_SWITCH or OPR_XGOTO or OPR_SWITCH
00574 // A frequency count is given for each possible jump target
00575 
00576 #define fb_opr_cases_switch \
00577   case OPR_SWITCH:          \
00578   case OPR_COMPGOTO:        \
00579   case OPR_XGOTO
00580 
00581 inline bool FB_valid_opr_switch (const WN *wn) {
00582   OPERATOR opr = WN_operator( wn );
00583   switch ( opr ) {
00584   fb_opr_cases_switch:
00585     return true;
00586   default:
00587     return false;
00588   }
00589 }
00590 
00591 #endif // MONGOOSE_BE
00592 // ====================================================================
00593 
00594 #endif
00595 
00596 
00597 
00598 
00599 
00600 
00601 
00602 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines