fb_freq.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 // Frequencies are stored as float in order to permit scaling.
00049 //
00050 // A frequency value is stored as a FB_FREQ data type, which can have
00051 // one of the following values:
00052 // - an EXACT nonnegative float value
00053 // - a  GUESS nonnegative float value
00054 // - UNKNOWN - an unknown frequency; its value may be computable from
00055 //             other frequency data
00056 // - UNINIT  - an uninitialized frequency
00057 // - ERROR   - the result of dividing by zero, or subtracting a larger
00058 //             from a smaller frequency value.
00059 //
00060 // EXACT values give an exactly correct count of the number of times
00061 // that a particular edge was traveled during the program's
00062 // instrumentated execution.  GUESS values are educated estimates of
00063 // the count.  Whenever a piece of code is cloned (eg: IPA; also the
00064 // test condition of a WHILE_DO loop is cloned during lowering), the
00065 // code's frequencies are scaled, and EXACT values are converted to
00066 // GUESSes.
00067 //
00068 // Sometimes dead branch elimination and frequency propagation will
00069 // enable GUESSes to be replaced later by EXACT counts, and UNKNOWN
00070 // values to be replaced by EXACT and GUESS values.
00071 //
00072 // Normally, ERROR and UNINIT frequencies should only be encountered
00073 // locally.
00074 //
00075 // Operations ( +, - , * , /, +=, -=, *=, /=, ==, !=, <, >, <=, >= )
00076 // are provided to combine, compare, and display frequencies.  * is
00077 // assumed to be scaling, so EXACT values are replaced by GUESSes.
00078 // Comparison operations do not distinguish between GUESS and EXACT
00079 // values.
00080 //
00081 // ====================================================================
00082 // ====================================================================
00083 
00084 #ifndef fb_freq_INCLUDED
00085 #define fb_freq_INCLUDED
00086 
00087 #include "defs.h"
00088 #ifndef ERRORS_INCLUDED
00089 #include "errors.h"
00090 #endif
00091 
00092 // ====================================================================
00093 // FB_FREQ_TYPE - frequency types
00094 // ====================================================================
00095 
00096 // The FB_FREQ_TYPE integer values are chosen to satisfy two rules:
00097 // (1) When two FB_FREQs are combined, the resulting FB_FREQ has normally
00098 //     FB_FREQ_TYPE equal to the minimum of those of the two FB_FREQ
00099 //     addends; and
00100 // (2) EXACTness and KNOWNness can be ascertained by comparing the
00101 //     FB_FREQ_TYPE to zero.
00102 
00103 enum FB_FREQ_TYPE {
00104   FB_FREQ_TYPE_EXACT   =  1,
00105   FB_FREQ_TYPE_GUESS   =  0,
00106   FB_FREQ_TYPE_UNKNOWN = -1,
00107   FB_FREQ_TYPE_UNINIT  = -2,
00108   FB_FREQ_TYPE_ERROR   = -3
00109 };
00110 
00111 #define FB_FREQ_TYPE_COMBINE( type1, type2 ) \
00112         ( (type1) > (type2) ? (type2) : (type1) )
00113 #define FB_FREQ_TYPE_BETTER( type1, type2 ) ( (type1) > (type2) )
00114 
00115 #define FB_FREQ_TYPE_IS_EXACT( type )        ( (type) >  0 )
00116 #define FB_FREQ_TYPE_IS_GUESS( type )        ( (type) == 0 )
00117 #define FB_FREQ_TYPE_IS_KNOWN( type )        ( (type) >= 0 )
00118 #define FB_FREQ_TYPE_NOT_KNOWN( type )       ( (type) <  0 )
00119 #define FB_FREQ_TYPE_INITIALIZED( type )     ( (type) >= FB_FREQ_TYPE_UNKNOWN )
00120 
00121 #define FB_FREQ_TYPE_IS_VALID( type ) \
00122         ( (type) >= FB_FREQ_TYPE_ERROR && (type) <= FB_FREQ_TYPE_EXACT )
00123 
00124 // ====================================================================
00125 // FB_FREQ - frequency values
00126 // ====================================================================
00127 
00128 // To account for round-off error, x == y  iff  x > y (1 - epsilon)
00129 //                                         and  y > x (1 - epsilon)
00130 
00131 const float FB_FREQ_EPSILON = 0.0001;
00132 
00133 class FB_FREQ {
00134 private:
00135 
00136   FB_FREQ_TYPE  _type;
00137   float         _value;
00138 
00139   // In order to simplify FB_FREQ operations, two internal restrictions
00140   // are imposed:
00141   // (1) If _type >= 0, then _value >= 0.0; and
00142   // (2) If _type <  0, then _value == (float) _type.
00143 
00144   // Private constructor, for binary operations
00145   FB_FREQ( FB_FREQ_TYPE type, float value )
00146     : _type( type ), _value( value ) { }
00147 
00148 public:
00149 
00150   // Constructor methods
00151 
00152   FB_FREQ()
00153     : _type( FB_FREQ_TYPE_UNINIT ),
00154       _value( (float) FB_FREQ_TYPE_UNINIT ) {}
00155 
00156   FB_FREQ( float value, bool exact )
00157     : _type( exact ? FB_FREQ_TYPE_EXACT : FB_FREQ_TYPE_GUESS ),
00158       _value( value )
00159     { Is_True( value >= 0.0, ( "FB_FREQ: negative value %f", value ) ); }
00160 
00161   FB_FREQ( INT64 value )
00162     : _type( FB_FREQ_TYPE_EXACT ),
00163       _value( (float) value )
00164     { Is_True( value >= 0, ( "FB_FREQ: negative value %lld", value ) ); }
00165 
00166   FB_FREQ( FB_FREQ_TYPE type )
00167     : _type( type ),
00168       _value( type >= 0 ? 0.0 : (float) type ) {
00169     Is_True( FB_FREQ_TYPE_IS_VALID( type ),
00170              ( "FB_FREQ: invalid type %d", type ) );
00171   }
00172 
00173   // Member access methods
00174 
00175   float Value() const { return _value; }
00176 
00177   // Boolean tests
00178 
00179   bool Known()         const { return FB_FREQ_TYPE_IS_KNOWN( _type ); }
00180   bool Guess()         const { return FB_FREQ_TYPE_IS_GUESS( _type ); }
00181   bool Exact()         const { return FB_FREQ_TYPE_IS_EXACT( _type ); }
00182   bool Uninitialized() const { return ( _type == FB_FREQ_TYPE_UNINIT ); }
00183   bool Initialized()   const { return FB_FREQ_TYPE_INITIALIZED( _type ); }
00184   bool Error()         const { return ( _type == FB_FREQ_TYPE_ERROR ); }
00185   bool Zero()          const { return ( _value < FB_FREQ_EPSILON &&
00186                                         _value > - FB_FREQ_EPSILON ); }
00187 
00188   bool Better( const FB_FREQ freq ) const {
00189     return FB_FREQ_TYPE_BETTER( _type, freq._type );
00190   }
00191 
00192   // Operators
00193 
00194   FB_FREQ operator+= ( const FB_FREQ freq ) {
00195     _type = FB_FREQ_TYPE_COMBINE( _type, freq._type );
00196     if ( FB_FREQ_TYPE_NOT_KNOWN( _type ) )
00197       _value = (float) _type;
00198     else
00199       _value += freq._value;
00200     return *this;
00201   }
00202 
00203   FB_FREQ operator-= ( const FB_FREQ freq ) {
00204     _type = FB_FREQ_TYPE_COMBINE( _type, freq._type );
00205     if ( FB_FREQ_TYPE_NOT_KNOWN( _type ) )
00206       _value = (float) _type;
00207     else {
00208       _value -= freq._value;
00209       if ( _value < 0 )
00210         if ( - _value < FB_FREQ_EPSILON
00211              || - _value < FB_FREQ_EPSILON * freq._value )
00212           _value = 0;
00213         else {
00214           DevWarn( "FB_FREQ: subtraction of larger from smaller value" );
00215           _type  = FB_FREQ_TYPE_ERROR;
00216           _value = (float) _type;
00217         }
00218     }
00219     return *this;
00220   }
00221 
00222   FB_FREQ operator*= ( const FB_FREQ freq ) {
00223     if ( Zero() && Exact() )
00224       ; // Nothing to do
00225     else if ( freq.Zero() && freq.Exact() ) {
00226       _type  = FB_FREQ_TYPE_EXACT;
00227       _value = 0.0;
00228     } else {
00229       _type = FB_FREQ_TYPE_COMBINE( _type, freq._type );
00230       if ( FB_FREQ_TYPE_NOT_KNOWN( _type ) )
00231         _value = (float) _type;
00232       else
00233         _value *= freq._value;
00234     }
00235     return *this;
00236   }
00237 
00238   // All scale factors are assumed to be guesses
00239   FB_FREQ operator*= ( const float scale ) {
00240     Is_True ( scale >= 0.0, ( "FB_FREQ: negative scale %f", scale ) );
00241     return ( *this *= FB_FREQ( FB_FREQ_TYPE_GUESS, scale ) );
00242   }
00243 
00244   // Division used to determine scale or probability.
00245   // Results other than exact 0s and 1s are assumed to be guesses.
00246   FB_FREQ operator/= ( const FB_FREQ freq ) {
00247     if ( Zero() && Exact() )
00248       ; // Nothing to do
00249     else if ( freq.Zero() ) {
00250       DevWarn("FB_FREQ: division by zero");
00251       _type  = FB_FREQ_TYPE_ERROR;
00252       _value = (float) _type;
00253     } else {
00254       _type = FB_FREQ_TYPE_COMBINE( _type, freq._type );
00255       if ( FB_FREQ_TYPE_NOT_KNOWN( _type ) )
00256         _value = (float) _type;
00257       else {
00258         if ( _value != freq._value )
00259           _type = FB_FREQ_TYPE_COMBINE( _type, FB_FREQ_TYPE_GUESS );
00260         _value /= freq._value;
00261       }
00262     }
00263     return *this;
00264   }
00265 
00266   // All scale factors are assumed to be guesses
00267   FB_FREQ operator/= ( const float scale ) {
00268     Is_True ( scale >= 0.0, ( "FB_FREQ: negative scale %f", scale ) );
00269     return ( *this /= FB_FREQ( FB_FREQ_TYPE_GUESS, scale ) );
00270   }
00271 
00272   // Binary operations
00273 
00274   friend FB_FREQ operator+ ( const FB_FREQ freq1, const FB_FREQ freq2 ) {
00275     FB_FREQ_TYPE type = FB_FREQ_TYPE_COMBINE( freq1._type, freq2._type );
00276     if ( FB_FREQ_TYPE_NOT_KNOWN( type ) )
00277       return FB_FREQ( type );
00278     return FB_FREQ( type, freq1._value + freq2._value );
00279   }
00280 
00281   friend FB_FREQ operator- ( const FB_FREQ freq1, const FB_FREQ freq2 ) {
00282     FB_FREQ_TYPE type = FB_FREQ_TYPE_COMBINE( freq1._type, freq2._type );
00283     if ( FB_FREQ_TYPE_NOT_KNOWN( type ) )
00284       return FB_FREQ( type );
00285     float value = freq1._value - freq2._value;
00286     if ( value >= 0 )
00287       return FB_FREQ( type, value );
00288     if ( - value < FB_FREQ_EPSILON
00289          || - value < freq2._value * FB_FREQ_EPSILON )
00290       return FB_FREQ( type, 0 );
00291     DevWarn( "FB_FREQ: subtraction of larger from smaller value" );
00292     return FB_FREQ( FB_FREQ_TYPE_ERROR );
00293   }
00294 
00295   friend FB_FREQ operator* ( const FB_FREQ freq1, const FB_FREQ freq2 ) {
00296     if ( ( freq1.Zero() && freq1.Exact() ) ||
00297          ( freq2.Zero() && freq2.Exact() ) )
00298       return FB_FREQ( FB_FREQ_TYPE_EXACT, 0.0 );
00299     FB_FREQ_TYPE type = FB_FREQ_TYPE_COMBINE( freq1._type, freq2._type );
00300     if ( FB_FREQ_TYPE_NOT_KNOWN( type ) )
00301       return FB_FREQ( type );
00302     return FB_FREQ( type, freq1._value * freq2._value );
00303   }
00304 
00305   // All scale factors are assumed to be guesses
00306   friend FB_FREQ operator* ( const FB_FREQ freq, const float scale ) {
00307     Is_True ( scale >= 0.0, ( "FB_FREQ: negative scale %f", scale ) );
00308     return ( freq * FB_FREQ( FB_FREQ_TYPE_GUESS, scale ) );
00309   }
00310 
00311   // Division used to determine scale or probability.
00312   // Results other than exact 0s and 1s are assumed to be guesses.
00313   friend FB_FREQ operator/ ( const FB_FREQ freq1, const FB_FREQ freq2 ) {
00314     if ( freq1.Zero() && freq1.Exact() )
00315       return FB_FREQ( FB_FREQ_TYPE_EXACT, 0.0 );
00316     if ( freq2.Zero() ) {
00317       DevWarn("FB_FREQ: division by zero");
00318       return FB_FREQ( FB_FREQ_TYPE_ERROR );
00319     }
00320     FB_FREQ_TYPE type = FB_FREQ_TYPE_COMBINE( freq1._type, freq2._type );
00321     if ( FB_FREQ_TYPE_NOT_KNOWN( type ) )
00322       return FB_FREQ( type );
00323     if ( freq1._value != freq2._value )
00324       type = FB_FREQ_TYPE_COMBINE( type, FB_FREQ_TYPE_GUESS );
00325     float value = freq1._value / freq2._value;
00326     return FB_FREQ( type, value );
00327   }
00328 
00329   // All scale factors are assumed to be guesses
00330   friend FB_FREQ operator/ ( const FB_FREQ freq, float scale ) {
00331     Is_True ( scale >= 0.0, ( "FB_FREQ: negative scale %f", scale ) );
00332     return ( freq / FB_FREQ( FB_FREQ_TYPE_GUESS, scale ) );
00333   }
00334 
00335   friend bool operator== ( const FB_FREQ freq1, const FB_FREQ freq2 ) {
00336     if ( freq1._value > freq2._value )
00337       return ( freq1._value < FB_FREQ_EPSILON
00338                || freq1._value * ( 1 - FB_FREQ_EPSILON ) < freq2._value );
00339     else if ( freq1._value < freq2._value )
00340       return ( freq2._value < FB_FREQ_EPSILON
00341                || freq2._value * ( 1 - FB_FREQ_EPSILON ) < freq1._value );
00342     else return true;
00343   }
00344 
00345   friend bool operator!= ( const FB_FREQ freq1, const FB_FREQ freq2 ) {
00346     if ( freq1._value > freq2._value )
00347       return ( freq1._value >= FB_FREQ_EPSILON
00348                && freq1._value * ( 1 - FB_FREQ_EPSILON ) >= freq2._value );
00349     else if ( freq1._value < freq2._value )
00350       return ( freq2._value >= FB_FREQ_EPSILON
00351                && freq2._value * ( 1 - FB_FREQ_EPSILON ) >= freq1._value );
00352     else return false;
00353   }
00354 
00355   friend bool operator> ( const FB_FREQ freq1, const FB_FREQ freq2 ) {
00356     return ( freq1._value > freq2._value );
00357   }
00358 
00359   friend bool operator< ( const FB_FREQ freq1, const FB_FREQ freq2 ) {
00360     return ( freq1._value < freq2._value );
00361   }
00362 
00363   friend bool operator<= ( const FB_FREQ freq1, const FB_FREQ freq2 ) {
00364     return ( (freq1._value < freq2._value) || (freq1 == freq2) );
00365   }
00366 
00367   // Printing methods
00368 
00369   void Print( FILE *fp ) const {
00370     switch ( _type ) {
00371     case FB_FREQ_TYPE_EXACT:
00372       fprintf( fp, "%g!", _value );
00373       break;
00374     case FB_FREQ_TYPE_GUESS:
00375       fprintf( fp, "%g?", _value );
00376       break;
00377     case FB_FREQ_TYPE_UNKNOWN:
00378       fprintf( fp, "unknown" );
00379       break;
00380     case FB_FREQ_TYPE_UNINIT:
00381       fprintf( fp, "uninitialized" );
00382       break;
00383     case FB_FREQ_TYPE_ERROR:
00384       fprintf( fp, "error" );
00385       break;
00386     default:
00387       Is_True( FALSE, ("FB_FREQ: Unexpected type %d", _type ));
00388       break;
00389     }
00390   }
00391 
00392   INT Sprintf( char *buffer ) const {
00393     INT length = 0;
00394     switch ( _type ) {
00395     case FB_FREQ_TYPE_EXACT:
00396       length = sprintf( buffer, "%g!", _value );
00397       break;
00398     case FB_FREQ_TYPE_GUESS:
00399       length = sprintf( buffer, "%g?", _value );
00400       break;
00401     case FB_FREQ_TYPE_UNKNOWN:
00402       length = sprintf( buffer, "unknown" );
00403       break;
00404     case FB_FREQ_TYPE_UNINIT:
00405       length = sprintf( buffer, "uninitialized" );
00406       break;
00407     case FB_FREQ_TYPE_ERROR:
00408       length = sprintf( buffer, "error" );
00409       break;
00410     default:
00411       Is_True( FALSE, ("FB_FREQ: Unexpected type %d", _type ));
00412       break;
00413     }
00414     return length;
00415   }
00416 };
00417 
00418 
00419 // Some FB_FREQ constants.  For unknown and uninitialized frequencies,
00420 // use these instead of invoking an FB_FREQ constructor.
00421 
00422 const FB_FREQ FB_FREQ_ZERO(    0.0, true /*EXACT*/  );
00423 const FB_FREQ FB_FREQ_UNKNOWN( FB_FREQ_TYPE_UNKNOWN );
00424 const FB_FREQ FB_FREQ_UNINIT(  FB_FREQ_TYPE_UNINIT  );
00425 const FB_FREQ FB_FREQ_ERROR(   FB_FREQ_TYPE_ERROR   );
00426 
00427 // ====================================================================
00428 
00429 #endif //#ifndef fb_freq_INCLUDED

Generated on Thu Dec 18 05:51:53 2008 for Open64 (mfef90, whirl2f, and IR tools) by  doxygen 1.5.7.1