Open64 (mfef90, whirl2f, and IR tools)  TAG: version-openad; SVN changeset: 916
fb_cfg.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 // fb_cfg.h and fb_cfg.cxx implement a control flow graph for edge
00044 // frequency data.  The CFG can be displayed (using daVinci), and can
00045 // propagate known frequencies to compute unknown values.
00046 // The CFG _MUST_ contain no critical edges.
00047 //
00048 // ====================================================================
00049 // ====================================================================
00050 
00051 #ifndef fb_cfg_INCLUDED
00052 #define fb_cfg_INCLUDED
00053 
00054 #include "mempool_allocator.h"
00055 
00056 #include <vector>
00057 #include <deque>
00058 
00059 #ifndef _USE_STL_EXT
00060 #include <map>
00061 #else
00062 #include <hash_map>
00063 #endif
00064 
00065 using namespace std;
00066 
00067 #include "fb_whirl.h"
00068 
00069 // ====================================================================
00070 // FB_NODEX     -- Nodes are numbered from 0 upwards
00071 // ====================================================================
00072 
00073 typedef INT32 FB_NODEX;
00074 #define FB_NODEX_UNINIT   (-1)
00075 #define FB_NODEX_VALID(nx) ((nx) >= 0)
00076 
00077 // ====================================================================
00078 // FB_CFG Nodes
00079 // ====================================================================
00080 
00081 // Since FB_CFG contains no critical edges, if pred preceeds succ, then
00082 // either pred.one_edge_succs or succ.one_edge_preds (or both) are true
00083 
00084 struct FB_NODE {
00085 
00086   vector<FB_NODEX> preds; // Predecessors
00087   vector<FB_NODEX> succs; // Successors
00088 
00089   bool one_edge_preds;    // true iff every pred has no other succs
00090   bool one_edge_succs;    // true iff every succ has no other preds
00091 
00092   INT undelayed_succs;    // Used by daVinci
00093 
00094   // Source of node frequency data
00095   FB_EDGE_TYPE        node_type;
00096   WN                 *source;
00097 
00098   // Frequency data.  If in_out_same is true, then we may assume that
00099   // freq_total_in and freq_total_out are equal.
00100   bool                in_out_same;
00101   FB_FREQ             freq_total_in;
00102   FB_FREQ             freq_total_out;
00103 
00104   INT                 unknown_in;
00105   INT                 unknown_out;
00106   INT                 unexact_in;
00107   INT                 unexact_out;
00108 
00109   FB_NODE() :
00110     one_edge_preds( true ),
00111     one_edge_succs( true ),
00112     undelayed_succs( 0),
00113     node_type( FB_EDGE_UNINIT ),
00114     source( NULL ),
00115     in_out_same( true ),
00116     freq_total_in( FB_FREQ_UNKNOWN ),
00117     freq_total_out( FB_FREQ_UNKNOWN ),
00118     unknown_in( 1 ),
00119     unknown_out( 1 ),
00120     unexact_in( 1 ),
00121     unexact_out( 1 ) {}
00122 
00123   FB_NODE( FB_EDGE_TYPE type, WN *src, bool same,
00124            FB_FREQ freq_in, FB_FREQ freq_out ) :
00125     one_edge_preds( true ),
00126     one_edge_succs( true ),
00127     undelayed_succs( 0 ),
00128     node_type( type ),
00129     source( src ),
00130     in_out_same( same ),
00131     freq_total_in( freq_in ),
00132     freq_total_out( freq_out ),
00133     unknown_in(  freq_in.Known()  ? 0 : 1 ),
00134     unknown_out( freq_out.Known() ? 0 : 1 ),
00135     unexact_in(  freq_in.Exact()  ? 0 : 1 ),
00136     unexact_out( freq_out.Exact() ? 0 : 1 ) {}
00137 
00138   void Print( FILE *fp, FB_NODEX nx ) const {
00139     INT t;
00140     char buffer[FB_EDGE_TYPE_NAME_LENGTH];
00141     FB_EDGE_TYPE_sprintf( buffer, node_type );
00142     fprintf( fp, "node %d: node_type %s, source 0x%p, in_out_same %c,\n",
00143              nx, buffer, source, ( in_out_same ? 'Y' : 'N' ) );
00144     fprintf( fp, "  one_edge_preds %c, one_edge_succs %c,"
00145              " undelayed_succs %d,\n", ( one_edge_preds ? 'Y' : 'N' ),
00146              ( one_edge_succs ? 'Y' : 'N' ), undelayed_succs );
00147     fprintf( fp, "  unknown_in  %d, unexact_in  %d, freq_total_in  ",
00148              unknown_in,  unexact_in );
00149     freq_total_in.Print( fp );
00150     fprintf( fp, ", preds [" );
00151     for ( t = 0; t < preds.size(); t++ )
00152       fprintf( fp, " %d", preds[t] );
00153     fprintf( fp, " ],\n");
00154     fprintf( fp, "  unknown_out %d, unexact_out %d, freq_total_out ",
00155              unknown_out, unexact_out );
00156     freq_total_out.Print( fp );
00157     fprintf( fp, ", succs [" );
00158     for ( t = 0; t < succs.size(); t++ )
00159       fprintf( fp, " %d", succs[t] );
00160     fprintf( fp, " ]\n");
00161   }
00162 };
00163 
00164 struct FB_EDGE_DELAYED {  // Destination is a label instead of a node
00165   FB_NODEX      source;
00166   LABEL_IDX     destination;
00167 
00168   FB_EDGE_DELAYED( FB_NODEX src, LABEL_IDX dst ) {
00169     source = src;
00170     destination = dst;
00171   }
00172 };
00173 
00174 // ====================================================================
00175 
00176 class FB_CFG_MEM {
00177 protected:
00178   MEM_POOL _m;
00179 
00180   FB_CFG_MEM() {
00181     MEM_POOL_Initialize( &_m, "FB_CFG_MEM", true );
00182     MEM_POOL_Push( &_m );
00183   }
00184   ~FB_CFG_MEM() {
00185     MEM_POOL_Pop( &_m );
00186     MEM_POOL_Delete(&_m );
00187   }
00188 };
00189 
00190 class FB_CFG : public FB_CFG_MEM {
00191 private:
00192 
00193   bool _trace;        // Get_Trace(TP_FEEDBACK, TP_FEEDBACK_CFG)
00194   bool _trace_draw;   // Get_Trace(TP_FEEDBACK, TP_FEEDBACK_CFG_DRAW)
00195   bool _trace_before; // Get_Trace(TP_FEEDBACK, TP_FEEDBACK_CFG_BEFORE)
00196   bool _trace_prop;   // Get_Trace(TP_FEEDBACK, TP_FEEDBACK_CFG_PROP)
00197 
00198   // vectors containing all nodes, indexed by FB_NODEX
00199   vector< FB_NODE, mempool_allocator<FB_NODE> > _nodes;
00200 
00201   // The following data elements are needed only during the construction of
00202   // the feedback control flow graph, to maintain state as the WHIRL code is
00203   // processed.
00204   //   _lblx_to_nx    maps label indicies to node indicies; assumes label
00205   //                  numbers are unique within a program unit
00206   //   _delayed_edges lists edges that will need to be added to the graph
00207   //                  after all nodes are in place
00208   //   _curr_nx       is the node currently being visited; if no node is
00209   //                  current, then nx == FB_NODEX_UNINIT
00210 
00211 
00212 // Solaris CC workaround
00213 // to replace hash_map with map
00214 #ifndef _USE_STL_EXT
00215   struct LABEL_IDX_ss_compare {
00216       bool operator() (LABEL_IDX idx1, LABEL_IDX idx2)
00217       {
00218           return idx1 < idx2;
00219       }
00220   } ;
00221 
00222   map< LABEL_IDX, FB_NODEX, LABEL_IDX_ss_compare,  
00223     mempool_allocator< pair<const LABEL_IDX,FB_NODEX> > > _lblx_to_nx;
00224 
00225 #else
00226   hash_map< LABEL_IDX, FB_NODEX, hash<LABEL_IDX>, equal_to<LABEL_IDX>,
00227     mempool_allocator< pair<const LABEL_IDX,FB_NODEX> > > _lblx_to_nx;
00228 
00229 #endif
00230   
00231   deque< FB_EDGE_DELAYED, mempool_allocator<FB_EDGE_DELAYED> > _delayed_edges;
00232 
00233   FB_NODEX     _curr_nx;
00234 
00235 private:
00236 
00237   // The following functions access the FB_CFG data representation
00238 
00239   FB_NODEX New_node();
00240   FB_NODEX New_node( FB_EDGE_TYPE node_type, WN *source, FB_FREQ freq_total_in,
00241                      FB_FREQ freq_total_out, bool in_out_same = false );
00242   FB_NODEX New_node( FB_EDGE_TYPE node_type, WN *source,
00243                      FB_FREQ freq_total_in ) {
00244     return New_node( node_type, source, freq_total_in, freq_total_in, true );
00245   }
00246 
00247   void Add_label( LABEL_IDX labelx, FB_NODEX nx ) { _lblx_to_nx[labelx] = nx; }
00248 
00249   void Add_edge(FB_NODEX nx_src, FB_NODEX nx_dst, bool delayed = false );
00250   void Add_delayed_edge( FB_NODEX nx_src, WN *wn );
00251   void Complete_delayed_edges();
00252 
00253   FB_NODEX Curr() const { return _curr_nx; }
00254   void     Set_curr( FB_NODEX nx ) { _curr_nx = nx; }
00255   FB_NODEX Get_curr(); // Creates a new _curr if there isn't one already
00256 
00257   // The following functions are invoked during the construction of the cfg
00258 
00259   void Walk_WN_expression( WN *wn );
00260   void Walk_WN_test_expression( WN *wn, FB_NODEX true_nx, FB_NODEX false_nx );
00261   void Walk_WN_statement( WN *wn );
00262 
00263   void Freq_propagate_node_in( FB_NODEX nx );
00264   void Freq_propagate_node_out( FB_NODEX nx );
00265   void Freq_propagate();
00266 
00267   char *Node_label( FB_NODEX nx ) const;
00268 
00269 public:
00270 
00271   FB_CFG() :
00272     _trace(        Get_Trace( TP_FEEDBACK, TP_FEEDBACK_CFG ) ),
00273     _trace_draw(   Get_Trace( TP_FEEDBACK, TP_FEEDBACK_CFG_DRAW ) ),
00274     _trace_before( Get_Trace( TP_FEEDBACK, TP_FEEDBACK_CFG_BEFORE ) ),
00275     _trace_prop(   Get_Trace( TP_FEEDBACK, TP_FEEDBACK_CFG_PROP ) ),
00276     _nodes( mempool_allocator<FB_NODE>(&_m) ),
00277 
00278 // Solaris CC workaround
00279 // this is the construction of <map> instead of <hash_map>
00280 
00281 #ifndef _USE_STL_EXT
00282     _lblx_to_nx(),
00283 
00284 #else
00285     _lblx_to_nx( 100, hash<LABEL_IDX>(), equal_to<LABEL_IDX>(),
00286                  mempool_allocator< pair<LABEL_IDX,FB_NODEX> >(&_m) ),
00287 
00288 #endif
00289 
00290     _delayed_edges( mempool_allocator<FB_EDGE_DELAYED>(&_m) ),
00291     _curr_nx( FB_NODEX_UNINIT ) {}
00292 
00293   ~FB_CFG() {}
00294 
00295   void Construct_from_whirl( WN *wn_root, const char *caller );
00296   void Guess_unknowns( WN *wn_root, const char *caller );
00297   FB_VERIFY_STATUS Verify_frequencies() const;
00298   void Patch_whirl_frequencies() const;
00299 
00300   void Print( FILE *fp ) const;
00301   void Print_node( FILE *fp, FB_NODEX nx ) const;
00302   void Print_edge( FILE *fp, FB_NODEX src_nx, FB_NODEX dst_nx ) const;
00303   void Draw() const;
00304 };
00305 
00306 void dV_view_fb_cfg(const FB_CFG& cfg, WN *root_wn, const char *caller);
00307 
00308 #endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines