00001 /* 00002 * Copyright 2003, 2004, 2005, 2006 PathScale, Inc. All Rights Reserved. 00003 */ 00004 00005 /* 00006 00007 Copyright (C) 2000, 2001 Silicon Graphics, Inc. All Rights Reserved. 00008 00009 This program is free software; you can redistribute it and/or modify it 00010 under the terms of version 2 of the GNU General Public License as 00011 published by the Free Software Foundation. 00012 00013 This program is distributed in the hope that it would be useful, but 00014 WITHOUT ANY WARRANTY; without even the implied warranty of 00015 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 00016 00017 Further, this software is distributed without any warranty that it is 00018 free of the rightful claim of any third person regarding infringement 00019 or the like. Any license provided herein, whether implied or 00020 otherwise, applies only to this software file. Patent licenses, if 00021 any, provided herein do not apply to combinations of this program with 00022 other software, or any other product whatsoever. 00023 00024 You should have received a copy of the GNU General Public License along 00025 with this program; if not, write the Free Software Foundation, Inc., 59 00026 Temple Place - Suite 330, Boston MA 02111-1307, USA. 00027 00028 Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pky, 00029 Mountain View, CA 94043, or: 00030 00031 http://www.sgi.com 00032 00033 For further information regarding this notice, see: 00034 00035 http://oss.sgi.com/projects/GenInfo/NoticeExplan 00036 00037 */ 00038 00039 00040 // ==================================================================== 00041 // ==================================================================== 00042 // 00043 // Module: ipa_solver.h 00044 // $Revision: 1.1.1.1 $ 00045 // $Date: 2005/10/21 19:00:00 $ 00046 // $Author: marcel $ 00047 // $Source: /proj/osprey/CVS/open64/osprey1.0/ipa/main/analyze/ipa_solver.h,v $ 00048 // 00049 // Revision history: 00050 // 19-Sep-95 - Initial version 00051 // 00052 // Description: 00053 // 00054 // This package provides a template interface for solving dataflow 00055 // problems over the call graph. It is derived from the base class 00056 // implementation of ipa_df.cxx. 00057 // 00058 // The associated source file ipa_solver.cxx contains an instantiation 00059 // of these facilities for the purpose of printing a callgraph. See it 00060 // (the routine Trace_Callgraph and the class DF_PRINT) for a complete 00061 // description of how this is intended to be used. The IPA aliasing 00062 // and mod/ref analysis in ipaa.cxx contains a more extensive instance. 00063 // 00064 // ==================================================================== 00065 // ==================================================================== 00066 00067 #ifdef _KEEP_RCS_ID 00068 static char *ipa_solver_rcs_id = "$Source: /proj/osprey/CVS/open64/osprey1.0/ipa/main/analyze/ipa_solver.h,v $ $Revision: 1.1.1.1 $"; 00069 #endif /* _KEEP_RCS_ID */ 00070 00071 #ifndef cxx_ipa_solver_INCLUDED 00072 #define cxx_ipa_solver_INCLUDED 00073 00074 // This header requires prior inclusion of erglob.h, ip_graph.h. 00075 00076 00077 #ifndef cxx_ipa_df_INCLUDED 00078 #include "ipa_df.h" // DF_DIRECTION 00079 #endif 00080 00081 #ifndef ipa_option_INCLUDED 00082 #include "ipa_option.h" 00083 #endif 00084 00085 00086 // ==================================================================== 00087 // 00088 // Utility functions 00089 // 00090 // ==================================================================== 00091 00092 // Reverse the graph for backward data flow problems: 00093 extern void Reverse_Graph ( GRAPH *g ); 00094 00095 // Trace a callgraph via the depth-first iterator in the given 00096 // direction. This routine serves as an example of using the dataflow 00097 // solver facilities in this module. 00098 extern void Trace_Callgraph ( 00099 IPA_CALL_GRAPH &cg, // Callgraph to trace 00100 DF_DIRECTION direction, // Direction to use 00101 const char *msg // Message to add to heading 00102 ); 00103 00104 // ==================================================================== 00105 // ==================================================================== 00106 // 00107 // Define some infrastructure for manipulating the dataflow problem. 00108 // 00109 // ==================================================================== 00110 // ==================================================================== 00111 00112 00113 // ==================================================================== 00114 // 00115 // DFBASE: Dataflow solver base class. 00116 // 00117 // It is expected that every dataflow solver will be a class derived 00118 // from this one, with additional member functions having 00119 // implementations derived from the templates below. 00120 // 00121 // ==================================================================== 00122 00123 class DFBASE 00124 { 00125 protected: 00126 00127 MEM_POOL *_m; // Mempool to use for allocation 00128 IPA_CALL_GRAPH *_cg; // Underlying callgraph 00129 DFN *_iter; // Iterator over the callgraph 00130 NODE_INDEX _entry, _exit; // Entry, exit nodes that connect the entire graph 00131 NODE_INDEX _saved_root; // Original root node of the graph 00132 DF_DIRECTION _dir; // Data flow direction 00133 mBOOL _reversed; // Has the callgraph been reversed? 00134 mBOOL _changed; // Has the solution changed yet this round? 00135 00136 public: 00137 00138 // Constructor: This sets the data fields to the given values, 00139 // connects the callgraph to distinct entry and exit nodes. If 00140 // a NULL iterator is provided, it is left to the solver to provide. 00141 DFBASE ( IPA_CALL_GRAPH &cg, DF_DIRECTION direction, 00142 MEM_POOL *mpool, DFN *iter ); 00143 00144 // Destructor: If necessary, this restores the underlying callgraph 00145 // and frees the iterator memory: 00146 ~DFBASE (); 00147 00148 // ==== Field references ===== 00149 // Don't change these fields after construction: 00150 MEM_POOL *Get_mempool () const { return _m; }; 00151 IPA_CALL_GRAPH *Get_callgraph () const { return _cg; }; 00152 00153 // These fields may change after construction: 00154 DF_DIRECTION Get_direction () const { return _dir; }; 00155 void Set_direction ( DF_DIRECTION d ) { _dir = d; }; 00156 DFN *Get_iter () const { return _iter; }; 00157 void Set_iter ( DFN *d ) { _iter = d; }; 00158 NODE_INDEX Get_entry () const { return _entry; }; 00159 void Set_entry ( NODE_INDEX entry ) { _entry = entry; }; 00160 NODE_INDEX Get_exit () const { return _exit; }; 00161 void Set_exit ( NODE_INDEX exit ) { _exit = exit; }; 00162 NODE_INDEX Get_saved_root () const { return _saved_root; }; 00163 void Set_saved_root ( NODE_INDEX root ) { _saved_root = root; }; 00164 BOOL Get_changed () const { return _changed; }; 00165 void Set_changed () { _changed = TRUE; }; 00166 void Reset_changed () { _changed = FALSE; }; 00167 BOOL Get_reversed () const { return _reversed; }; 00168 00169 // Ensure that the entire graph is connected, with a unique entry 00170 // and a unique exit node: 00171 void Connect_graph ( MEM_POOL *pool ); 00172 00173 // Reverse the graph for backward data flow problems. 00174 void Reverse_graph (); 00175 00176 // Restore graph to its original form, removing the entry and exit 00177 // nodes, and reversing it for backward dataflow problems: 00178 void Restore_graph (); 00179 00180 // Query the underlying callgraph. Note that the meanings of the 00181 // edge ends is inverted if the graph has been reversed: 00182 IPA_NODE* Get_caller ( const IPA_EDGE *edge ) const 00183 { return _reversed ? _cg->Callee(edge) 00184 : _cg->Caller(edge); }; 00185 IPA_NODE* Get_callee ( const IPA_EDGE *edge ) const 00186 { return _reversed ? _cg->Caller(edge) 00187 : _cg->Callee(edge); }; 00188 00189 // Clone a node in the underlying callgraph: 00190 IPA_NODE* Clone ( IPA_NODE *n) 00191 { return ( _cg->Create_Clone(n) ); }; 00192 }; 00193 00194 // ==================================================================== 00195 // ==================================================================== 00196 // 00197 // Define the template functions to be used in setting up a dataflow 00198 // solver. 00199 // 00200 // In each of the following templates, the formal class parameter 00201 // DF_T is the type derived from DFBASE above. IN_T is the type of its 00202 // input annotations, and OUT_T is the type of its output annotations. 00203 // 00204 // ==================================================================== 00205 // ==================================================================== 00206 00207 // ==================================================================== 00208 // 00209 // Initialize_Annotation 00210 // 00211 // Initialize the in/out annotations on the callgraph nodes. 00212 // The 'in' and 'out' formal function parameters are strictly for the 00213 // purpose of establishing their types. 00214 // 00215 // This function is generally called by the solver template, because 00216 // the initialization may depend on having the graph already 00217 // reversed. Therefore, a class with a multi-solver problem (e.g. 00218 // alias analysis does a backward phase followed by a forward phase) 00219 // needs to make sure it can deal with already-initialized data 00220 // structures. 00221 // 00222 // REQUIRES -- the DF_T class must have members: 00223 // void Set_in ( IN_T ** ); -- input annotation array 00224 // IN_T ** Get_in (); 00225 // void Set_out ( OUT_T ** ); -- output annotation array 00226 // OUT_T** Get_out (); 00227 // void Initialize_node ( void * user_data ); 00228 // 00229 // ==================================================================== 00230 00231 template < class DF_T, class IN_T, class OUT_T > 00232 void 00233 Initialize_Annotation ( DF_T *dataflow, IN_T **, OUT_T ** ) 00234 { 00235 INT32 i; 00236 DFN *iter = dataflow->Get_iter(); 00237 GRAPH *graph = dataflow->Get_callgraph()->Graph(); 00238 MEM_POOL *mpool = dataflow->Get_mempool(); 00239 IN_T **in = dataflow->Get_in(); 00240 OUT_T **out = dataflow->Get_out(); 00241 00242 // Create the input annotations for all vertices: 00243 if ( in == NULL ) { 00244 INT32 size_in = sizeof(IN_T*) * GRAPH_vmax(graph); 00245 00246 in = (IN_T**) MEM_POOL_Alloc ( mpool, size_in ); 00247 if ( in == NULL ) { 00248 ErrMsg ( EC_No_Mem, "Initialize_Annotation: input annotations" ); 00249 } else { 00250 bzero ( in, size_in ); 00251 dataflow->Set_in ( in ); 00252 } 00253 } 00254 00255 // Create the output annotations for all vertices: 00256 if ( out == NULL ) { 00257 INT32 size_out = sizeof(OUT_T*) * GRAPH_vmax(graph); 00258 00259 out = (OUT_T**) MEM_POOL_Alloc ( mpool, size_out ); 00260 if ( out == NULL ) { 00261 ErrMsg ( EC_No_Mem, "Initialize_Annotation: output annotations" ); 00262 } else { 00263 bzero ( out, size_out ); 00264 dataflow->Set_out ( out ); 00265 } 00266 } 00267 00268 // Check the allocations and clear the resulting arrays: 00269 00270 for ( i=DFN_first(iter); i< DFN_end(iter); ++i ) { 00271 NODE_INDEX vindex = DFN_v_list_i(iter,i); 00272 00273 if ( vindex == dataflow->Get_entry() ) continue; 00274 dataflow->Initialize_node ( 00275 NODE_user ( &GRAPH_v_i ( graph, vindex ) ) ); 00276 } 00277 } 00278 00279 // ==================================================================== 00280 // 00281 // Iterative_Solver_Core 00282 // 00283 // Do one iteration over the dataflow graph, in the order given by its 00284 // iterator. For each of the callgraph nodes, call the Meet function 00285 // for each of its incoming edges, producing its 'in' annotation, and 00286 // then the Trans function to produce its 'out' annotation. 00287 // 00288 // The parameters passed to Meet are the input sets to the meet (in), 00289 // the predecessor's current data flow set (pred_set), the annotation 00290 // in the callgraph vertex obtained from the local phase, and the edge 00291 // annotation obtained from the local phase (on the first iteration). 00292 // For the subsequent iterations, it reflects the result of the Trans 00293 // operation. 00294 // 00295 // For a call graph, local node annotation corresponds to summary 00296 // information collected for a function or procedure and edge 00297 // annotation refers to summary information collected for a call site. 00298 // The parameters passed to trans are the result of the meet operation 00299 // and the previous out annotation and the variable change which 00300 // is used to determine whether the data flow problem has settled. 00301 // 00302 // REQUIRES -- the DF_T class must have members: 00303 // void Set_in_elmt ( NODE_INDEX i, IN_T * ); 00304 // IN_T *Get_in_elmt ( NODE_INDEX i ); 00305 // void Set_out_elmt ( NODE_INDEX i, OUT_T * ); 00306 // OUT_T *Get_out_elmt ( NODE_INDEX i ); 00307 // IN_T *Meet ( IN_T *, VUSER_T * ); 00308 // OUT_T *Trans ( IN_T *, OUT_T *, VUSER_T * ); 00309 // where: 00310 // IN_T is the type of an input annotation. 00311 // OUT_T is the type of an output annotation. 00312 // VUSER_T is the type of a callgraph vertex user annotation. 00313 // 00314 // ==================================================================== 00315 00316 template < class DF_T > 00317 void 00318 Iterative_Solver_Core ( DF_T *dataflow ) 00319 { 00320 DFN *iter = dataflow->Get_iter(); 00321 IPA_CALL_GRAPH *callgraph = dataflow->Get_callgraph(); 00322 GRAPH *graph = callgraph->Graph(); 00323 NODE_INDEX i; 00324 00325 // Make sure that iter is not empty: 00326 assert ( iter != NULL ); 00327 00328 if ( Get_Trace ( TP_IPA, IPA_TRACE_CG ) ) { 00329 Print_DFN ( TFile, iter ); 00330 } 00331 00332 // for all vertices in depth first ordering, perform meet and trans: 00333 for ( i=DFN_first(iter); i< DFN_end(iter); ++i ) { 00334 INT vindex = DFN_v_list_i(iter,i); 00335 00336 if ( vindex != dataflow->Get_entry() 00337 && vindex != dataflow->Get_exit() ) 00338 { // Avoid the special entry and exit nodes, since they are there 00339 // only to connect the entire graph. 00340 00341 // Compute the meet of incoming edge and existing in. For 00342 // the meet operation, pass the in set, the predecessor's out 00343 // annotation, the current node annotation and current edge 00344 // annotation. 00345 00346 // NOTE: for a call graph and the forward dataflow problem, 00347 // the current node annotation refers to the callee and the 00348 // edge annotation refers to the callsite note, the meet 00349 // operation will delete the old in and return the new in. 00350 00351 dataflow->Set_in_elmt ( 00352 vindex, 00353 dataflow->Meet ( 00354 dataflow->Get_in_elmt ( vindex ), 00355 NODE_user ( &GRAPH_v_i (graph, vindex) ) ) 00356 ); 00357 00358 // Transfer: pass the in set, the out set, and the current 00359 // node annotation (for a call graph, the procedure node). It 00360 // must set the _changed indicator in the class instance to 00361 // indicate whether the dataflow problem has settled. 00362 // 00363 // NOTE: the trans operation will delete the old out and return 00364 // the new out. 00365 00366 dataflow->Set_out_elmt ( 00367 vindex, 00368 dataflow->Trans ( 00369 dataflow->Get_in_elmt ( vindex ), 00370 dataflow->Get_out_elmt ( vindex ), 00371 NODE_user ( &GRAPH_v_i ( graph, vindex ) ) ) 00372 ); 00373 00374 } 00375 } 00376 } 00377 00378 // ==================================================================== 00379 // 00380 // Iterative_Dataflow_Solver 00381 // 00382 // Main driver for an iterative solver. In addition to the DF_T class 00383 // parameter, it requires a GRAPH_ITER parameter which is a function: 00384 // DFN *GRAPH_ITER ( GRAPH *g, MEM_POOL *m ); 00385 // returning a node iterator of type DFN *, e.g. Depth_First_Ordering. 00386 // 00387 // REQUIRES -- the DF_T class must have members: 00388 // void Initialize_annotations (); 00389 // void Solver_core (); 00390 // void Init_IO (); 00391 // void Post_process_IO ( void *vertex_user ); 00392 // 00393 // ==================================================================== 00394 00395 template < class DF_T, class GRAPH_ITER > 00396 void 00397 Iterative_Dataflow_Solver ( 00398 DF_T *dataflow, // The solver class object 00399 GRAPH_ITER get_iter ) // Function to create a callgraph iterator 00400 { 00401 // We'll need a handle on the underlying callgraph: 00402 IPA_CALL_GRAPH *callgraph = dataflow->Get_callgraph(); 00403 GRAPH *graph = callgraph->Graph(); 00404 00405 /* If it's a backward data flow solver, reverse the graph */ 00406 if ( dataflow->Get_direction() == BACKWARD ) { 00407 dataflow->Reverse_graph (); 00408 } 00409 00410 if ( dataflow->Get_iter() == NULL ) { 00411 dataflow->Set_iter ( get_iter ( graph, 00412 dataflow->Get_mempool() ) ); 00413 } 00414 00415 // Initialize callgraph vertex, in, and out annotations: 00416 dataflow->Initialize_annotations (); 00417 00418 dataflow->Set_changed (); 00419 00420 // While the data flow problem has not settled do: 00421 while ( dataflow->Get_changed() ) { 00422 // Reset changed to FALSE. Any step which changes information 00423 // during the iteration (i.e. Meet or Trans) must set it to TRUE. 00424 dataflow->Reset_changed(); 00425 00426 // Call the workhorse dataflow solver: 00427 dataflow->Solver_core (); 00428 } 00429 } 00430 00431 // ==================================================================== 00432 // 00433 // Extract_Solution 00434 // 00435 // Extract the solution data from the solved problem. 00436 // 00437 // REQUIRES -- the DF_T class must have members: 00438 // void Init_IO (); 00439 // void Post_process_IO ( void *vertex_user ); 00440 // 00441 // ==================================================================== 00442 00443 template < class DF_T > 00444 void 00445 Extract_Solution ( DF_T *dataflow ) 00446 { 00447 // We'll need a handle on the underlying callgraph: 00448 IPA_CALL_GRAPH *callgraph = dataflow->Get_callgraph(); 00449 GRAPH *graph = callgraph->Graph(); 00450 00451 // Other temporaries: 00452 INT i; 00453 00454 // Initialize any data structures that are needed by post processing: 00455 dataflow->Init_IO (); 00456 00457 // Do any necessary post processing: 00458 // In the case of constant propagation, the tcons need to be reset. 00459 00460 DFN* iter = dataflow->Get_iter(); 00461 for ( i=DFN_first(iter); i< DFN_end(iter); ++i ) { 00462 NODE_INDEX vindex = DFN_v_list_i(iter,i); 00463 00464 if ( vindex == dataflow->Get_entry() 00465 || vindex == dataflow->Get_exit() ) 00466 { 00467 continue; 00468 } 00469 00470 dataflow->Post_process_IO ( NODE_user(&GRAPH_v_i(graph,vindex)) ); 00471 } 00472 } 00473 00474 #endif /* cxx_ipa_solver_INCLUDED */ 00475
1.5.6