Open64 (mfef90, whirl2f, and IR tools)  TAG: version-openad; SVN changeset: 916
dep_graph.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 //                      Data Dependence Graph for Arrays
00038 //                     ---------------------------------
00039 //
00040 // Description:
00041 //
00042 //     A data dependence graph. This data structure is used for three different
00043 //     graphs.
00044 //
00045 //     1. LNO has a graph for all array statements in the program unit.
00046 //     There is one graph per program unit but edges only exist between
00047 //     two array loads/stores that share at least one common "good" DO loop.
00048 //     We attach to each edge a DEPV_ARRAY.
00049 //     Each load/store of an array WN is mapped to the vertex in the graph.
00050 //     Each dependence is defined to be the difference between loop iterations,
00051 //      ie, we divide by the step size
00052 //
00053 //      Non-array loads/stores (i.e. LDIDs/STIDs) can be in the graph, as
00054 //     second class citizens, if there is a dependence between an array 
00055 //     load/store and an LDID/STID.  They are second class citizens in the
00056 //      sense that they only appear in the graph if they are dependent on an
00057 //      array load/store, and there is never any edges between two LDIDs/STIDs.
00058 //
00059 //     2. Fission/fusion usess a graph of dependence levels.  The dependences
00060 //     are mapped to statements.
00061 //
00062 //     3. CG uses a dependence graph of DEPs.  This defines edges on 
00063 //     array loads/stores in the same "good" inner DO loop.
00064 // TODO: also should put edges in non-good inner loops.
00065 //     The CG graph also contains must dependences.  A must dependence
00066 //     means that modulo control flow, there is guranteed to be a dependence
00067 //     between all pairs of references satisfying the dependence 
00068 //     distance/direction.  In addition, two references with a must dependence
00069 //     must be the same size.  As opposed to regular dependences, must
00070 //     dependences can also be read-read dependences.
00071 //     other loads.  A boolean flag is set to true on the dependence
00072 //     edge if the dependence edge is a must dependence.
00073 //     Each dependence is defined to be the difference between loop iterations,
00074 //      ie, we divide by the step size
00075 //     As opposed to the DEPV_ARRAY graph, LDIDs/STIDs never appear in the graph.
00076 //
00077 //     For all graphs:
00078 //     An unmapped vertex must be assumed to be dependent on everything.
00079 //     Each edge only contains lexicographically positive dependences.
00080 //
00081 //        
00082 //
00083 //
00084 //
00085 // Exported types and functions:
00086 //
00087 //      enum DEP_GRAPH_TYPE 
00088 //        {DEPV_ARRAY_ARRAY_GRAPH,LEVEL_ARRAY_GRAPH,DEP_ARRAY_GRAPH};
00089 //
00090 //              Which type of graph
00091 //
00092 //      ARRAY_VERTEX16 : public VERTEX16
00093 //
00094 //              A vertex 
00095 //
00096 //          WN *wn
00097 //
00098 //              The WN of the load/store
00099 //
00100 //
00101 //      ARRAY_EDGE16 : public EDGE16
00102 //
00103 //              An edge 
00104 //
00105 //        Union
00106 //          class DEPV_ARRAY *Depv_Array
00107 //          class LEVEL_STRUCT Level_Info
00108 //          Struct {
00109 //            DEP Dep
00110 //            mBOOL Is_Must
00111 //          }
00112 //
00113 //              The dependence
00114 //
00115 //     ARRAY_DIRECTED_GRAPH16 : 
00116 //              public DIRECTED_GRAPH16<ARRAY_VERTEX16, ARRAY_EDGE16>
00117 //
00118 //              The graph
00119 //
00120 //          ARRAY_DIRECTED_GRAPH16(mUINT16 num_v, mUINT16 num_e, WN_MAP map,
00121 //              DEP_GRAPH_TYPE type) 
00122 //
00123 //              Create a graph of type type.  
00124 //              The graph will be attached to the code using map.
00125 //
00126 //          EINDEX16 Add_Edge(VINDEX16 from, VINDEX16 to, DEP dep,
00127 //                              BOOL is_must = FALSE)
00128 //
00129 //              Add a non-must  edge to the graph.  
00130 //              Return 0 if the graph is full.
00131 //
00132 //          VINDEX16 Add_Vertex(WN *wn)
00133 //
00134 //              Add a vertex to the graph.  Return 0 if the graph is full.
00135 //              Use map to map the vertex to this wn.
00136 //
00137 //          UINT8       Level(EINDEX16 edge)
00138 //
00139 //              Return the dependence associated with the edge
00140 //
00141 //          void Set_Level(EINDEX16 edge, UINT8 level) 
00142 //
00143 //          DEP         Dep(EINDEX16 edge)
00144 //
00145 //              Return the dependence associated with the edge
00146 //
00147 //          BOOL        Is_Must(EINDEX16 edge)
00148 //
00149 //              Is the dependence a must dependence
00150 //
00151 //          void        Set_Dep(EINDEX16 edge, DEP dep, BOOL is_must)
00152 //
00153 //          MEM_POOL *Pool()
00154 //
00155 //              Return the pool used for the DEPV_ARRAYS in the graph
00156 //
00157 //          void Print(FILE *fp)
00158 //
00159 //          void Remove_Edge(EINDEX16 e)
00160 //
00161 //              Remove the edge from the graph.  Do not delete the
00162 //              Depv_Array (this is useful for stack-based memory disciplines)
00163 //
00164 //          VINDEX16 Get_Vertex(WN *wn)
00165 //
00166 //              Use the map to find  the index associated with this wn.
00167 //              Returns 0 if this wn has no vertex
00168 //
00169 //          VINDEX16 Get_Vertex()
00170 //
00171 //              Get the first vertex in the graph
00172 //
00173 //          WN *Get_Wn(VINDEX16 v)
00174 //
00175 //              Find the wn associated with this v.
00176 //
00177 //          void Set_Wn(VINDEX16 v, WN* wn) {
00178 //
00179 //              Make wn to be associated with v and update the map
00180 //
00181 //          void Clear_Map_For_Vertex(VINDEX v)
00182 //
00183 //              Remove the wn from the map and reset the wn of the vertex.
00184 //              This method is solely used by wopt when wn node is being
00185 //              transformed into the CODEREP representations.
00186 //              
00187 //          void Clear_Map()
00188 //
00189 //              Remove all mappings in the map and reset wns of all
00190 //              vertex to be NULL. 
00191 //
00192 //          mBOOL Copy_Vertex(VINDEX16 v1, VINDEX16 v2)
00193 //
00194 //              Copy all edges to/from v1 to v2
00195 //              return 0 if the graph is full.
00196 //              This only works on CG's dependence graph.
00197 //
00198 //          void Erase_Graph()
00199 //
00200 //              Remove all edge edges and vertices from the graph
00201 //
00202 // The remaining routines of this class are LNO specific.  No one else
00203 // should use them
00204 //
00205 //          EINDEX16 Add_Edge(VINDEX16 from, VINDEX16 to, DEPV_ARRAY *array)
00206 //
00207 //              Add an edge to the graph.  Return 0 if the graph is full.
00208 //
00209 //          BOOL Add_Edge(WN *ref1, const DOLOOP_STACK *s1,
00210 //                        WN *ref2, const DOLOOP_STACK *s2,
00211 //                        BOOL s1_lex_before_s2,BOOL use_bounds=TRUE)
00212 //
00213 //              Compute the dependences (a DEPV_ARRAY or a DEP) and 
00214 //              add two edges to the graph (from ref1 to ref2 and
00215 //              from ref2 to ref1).  Ref1 and Ref2 are loads/stores/call nodes.
00216 //              s1_lex_before_s2 should be true
00217 //              if s1 appears lexically before s2 in the code.
00218 //              This routine assumes that the vertices for the two
00219 //              references are already in the graph.
00220 //              If this is a DEP graph and not a DEPV_ARRAY graph, the
00221 //              two references must be in the same inner loop
00222 //              Return 0 if the graph is full.
00223 //              If use_bounds is FALSE, don't use bounds information to
00224 //              compute dependences (this is an efficiency vrs accuracy
00225 //              issue)
00226 //
00227 //          BOOL Add_Edge_Stars(WN *ref1, DOLOOP_STACK *s1, WN *ref2, 
00228 //                              DOLOOP_STACK *s2,BOOL s1_lex_before_s2,
00229 //                              BOOL pos_only=FALSE)
00230 //
00231 //              Like Add_Edge above, but rather than actually computing
00232 //              depedences, just make them all stars.  pos_only adds
00233 //              an edge only from ref1 to ref2.
00234 //
00235 //          BOOL Add_Edge_Equals(WN *ref1, DOLOOP_STACK *s1, WN *ref2, 
00236 //                              DOLOOP_STACK *s2)
00237 //
00238 //              Add an all equals edge from ref1 to ref2
00239 //
00240 //          EINDEX16 Add_Edge(VINDEX16 from, VINDEX16 to, UINT8 level)
00241 //
00242 //              Add an edge to the graph.  Return 0 if the graph is full.
00243 //
00244 //          DEPV_ARRAY *Depv_Array(EINDEX16 edge)
00245 //
00246 //          void Set_Depv_Array(EINDEX16 edge, DEPV_ARRAY*)
00247 //
00248 //          INT Build(WN *func_nd,MEM_POOL *pool=0);
00249 //
00250 //              Build the graph for the procedure. Store the DEPV_ARRAYs,
00251 //              if this is a DEPV_ARRAY graph, in pool.
00252 //              (the actual graph is stored in its own pool)
00253 //              Map each l/s node to its vertex in the graph. 
00254 //              Return 0 on error
00255 //
00256 //          INT Build(ARRAY_DIRECTED_GRAPH16 *da_graph)
00257 //
00258 //              Given a DEPV_ARRAY graph, build a DEP graph.  Copy the
00259 //              vertices (although map them to l/s rather than arrays).
00260 //              Throw out all the edges between two vertices not in the
00261 //              same inner loop.  Convert all remaining DEPV_ARRAYs to
00262 //              DEPs. 
00263 //
00264 //          void Delete_Array_Edge(EINDEX16 e)
00265 //
00266 //              Remove the edge from a DEPV_ARRAY graph and delete the array
00267 //
00268 //          INT Add_Deps_To_Copy_Block(WN *orig,WN *copy,
00269 //                                     BOOL keep_internal_edge)
00270 //
00271 //              Given that copy is a copy of the tree rooted at orig.
00272 //              Given that all the dependences for orig are in the graph
00273 //              Add copies of the dependences to the graph for the nodes in
00274 //              copy.  This works on the DEPV_ARRAY graph. By default,
00275 //              keep_internal_edge is set to TRUE which allows copying
00276 //              the edges within the orig. tree. Set it to FALSE would make
00277 //              edges within the orig. tree NOT be copied.
00278 //              Return 0 on error
00279 //
00280 //          INT Unrolled_Dependences_Update(WN** bodies, UINT u, UINT loopno)
00281 //
00282 //              Fix the array dependences after loop unrolling.  
00283 //              Loopno is the number of the loop being unrolled u times.
00284 //              bodies[0..u-1] are identical copies of code  
00285 //              bodies 0 is the original.
00286 //              Return 0 on error
00287 //              
00288 //          void Fission_Dep_Update(WN* in_loop,UINT32 total_loops)
00289 //
00290 //              Fix the array dependences after fission.  
00291 //              in_loop points to the outer loop of the first fissioned loop 
00292 //              (the rest can be found via next pointers). Total_loops gives 
00293 //              the number of loops. 
00294 //
00295 //          INT Fission_Dep_Update(WN* in_loop,UINT32 total_loops, 
00296 //                                      UINT fission_depth)
00297 //              Fix the statement dependence graph after fission.
00298 //              in_loop points to the outer loop of the first fissioned loop 
00299 //              (the rest can be found via next pointers). Total_loops gives 
00300 //              the number of loops.  Fission_depth gives the number of
00301 //              perfectly nested loops being fissioned together
00302 //              Return 0 on error (can only happen for statement graph).
00303 //
00304 //          INT Build_Region(WN* start, WN* end, DOLOOP_STACK *stack,
00305 //                           BOOL rebuild=FALSE, BOOL skip_bad=FALSE)
00306 //
00307 //              Build the dependences WITHIN a region specified by start
00308 //              and end WHIRL nodes. Old edges will be removed 
00309 //              if rebuild==TRUE.
00310 //              If skip_bad do not visit bad loops within this region
00311 //
00312 //
00313 //          void Versioned_Dependences_Update (WN* body_orig, WN* body_new, 
00314 //              UINT loopno, WN_MAP version_map)
00315 //              Fix the array dependence graph after versioning loops for 
00316 //              prefetching.
00317 //              body_orig is the original body (the then part after versioning),
00318 //              body_new is the new body (the then part after versioning),
00319 //              and loopno is the depth of the loop being split.
00320 //
00321 //          void Versioned_Create_Vertices (WN* body_orig, WN* body_new)
00322 //              Given the original and new body of a versioned loop,
00323 //              add vertices in the new body for each node in orig-body that
00324 //              has a vertex.
00325 //
00326 //          void Versioned_Dependences_Update_E (WN *body_orig,
00327 //                                               WN* body_new,
00328 //                                               WN* root_orig,
00329 //                                               WN* root_new,
00330 //                                               UINT loopno, 
00331 //                                               WN_MAP version_map)
00332 //              Given the orig-body and new-body of a versioned loop,
00333 //              add the edges based on the edges in the original dependence 
00334 //              graph.
00335 //
00336 //          void Check_Graph()
00337 //
00338 //              Assertion fails if a few simple checks fail.
00339 //              Only defined if Is_True_On is set.
00340 //
00341 //
00342 
00343 #ifndef dep_graph_INCLUDED
00344 #define dep_graph_INCLUDED "dep_graph.h"
00345 
00346 #ifdef _KEEP_RCS_ID
00347 #endif /* _KEEP_RCS_ID */
00348 
00349 #ifndef cxx_graph_INCLUDED
00350 #include "cxx_graph.h"
00351 #endif
00352 #ifndef graph_template_INCLUDED
00353 #include "graph_template.h"
00354 #endif
00355 #ifndef _defs_INCLUDED
00356 #include "cxx_memory.h"
00357 #endif
00358 
00359 #ifdef LNO
00360 #ifndef dep_INCLUDED
00361 #include "dep.h"
00362 #endif
00363 #ifndef cxx_hash_INCLUDED
00364 #include "cxx_hash.h"
00365 #endif
00366 #endif
00367 
00368 #ifndef LNO
00369 #ifndef dvector_INCLUDED
00370 #include "dvector.h"
00371 #endif
00372 #endif
00373 
00374 /* C interface functions used for reading and writing graphs */
00375 extern "C" {
00376   void *C_Dep_Graph(void);
00377   void Init_Dep_Graph(void *g);
00378   void Dealloc_Dep_Graph(void);
00379   void Depgraph_Write(void *depgraph, struct output_file *fl, WN_MAP off_map);
00380   void *Depgraph_Read(char *cur_addr, char *end_addr, char *wn_base);
00381 
00382   void LNOPreserveMapPair(WN *orig, WN *wn1, WN *wn2);
00383   void LNOPruneMapsUsingParity(void);
00384   void LNOPrintDepGraph(FILE *fp);
00385   VINDEX16 LNOGetVertex(WN *wn);
00386 
00387   BOOL WN_parity_independent(WN *wn1, WN *wn2);
00388 
00389   BOOL LnoDependenceEdge(WN *wn1, WN *wn2, EINDEX16 *distance, DIRECTION *direction, BOOL *is_must, BOOL *status);
00390 }
00391 
00392 enum DEP_GRAPH_TYPE {DEPV_ARRAY_ARRAY_GRAPH,LEVEL_ARRAY_GRAPH,DEP_ARRAY_GRAPH};
00393 
00394 class ARRAY_VERTEX16 : public VERTEX16 {
00395 public:
00396   WN *Wn;
00397   ARRAY_VERTEX16(WN *wn) { Wn = wn;}
00398   friend class ARRAY_DIRECTED_GRAPH16;
00399 };
00400 
00401 #define  HAS_ALL_ZERO           0x0001
00402 #define  HAS_SCALAR_FLOW        0x0002
00403 #define  HAS_SCALAR_ANTI        0x0004
00404 #define  HAS_SCALAR_OUTPUT      0x0008
00405 #define  HAS_ARRAY_FLOW         0x0010
00406 #define  HAS_ARRAY_ANTI         0x0020
00407 #define  HAS_ARRAY_OUTPUT       0x0040
00408 
00409 struct LEVEL_STRUCT {
00410   UINT8 Level;
00411   UINT16 Property;
00412 };
00413 
00414 struct DEP_STRUCT {
00415  DEP Dep;
00416  mBOOL Is_Must;
00417 }; 
00418 
00419 class ARRAY_EDGE16 : public EDGE16 {
00420 public:
00421   friend class ARRAY_DIRECTED_GRAPH16;
00422   union {
00423     class DEPV_ARRAY *Depv_Array;
00424     struct LEVEL_STRUCT Level_Info;
00425     DEP_STRUCT DEP_Struct;
00426   };
00427 };
00428 
00429 #ifdef LNO
00430 class REFERENCE_LIST;
00431 typedef STACK<REFERENCE_LIST *> REF_LIST_STACK;
00432 typedef STACK<VINDEX16 > VINDEX16_STACK;
00433 
00434 class VINDEX16P_LEX_COUNT {
00435 public:
00436   VINDEX16 *_vp;
00437   INT _lex_count;
00438   VINDEX16P_LEX_COUNT(VINDEX16 *vp, INT lex_count) {
00439     _vp = vp;
00440     _lex_count = lex_count;
00441   }
00442 };
00443 
00444 #endif
00445 
00446 class  ARRAY_DIRECTED_GRAPH16 : 
00447         public DIRECTED_GRAPH16<ARRAY_EDGE16,ARRAY_VERTEX16> {
00448   WN_MAP _map;
00449   DEP_GRAPH_TYPE  _type;
00450   MEM_POOL *_pool;
00451 public:
00452   void Print(FILE *fp);
00453   ARRAY_DIRECTED_GRAPH16(mUINT16 num_v, mUINT16 num_e, WN_MAP map, 
00454         DEP_GRAPH_TYPE type) : 
00455         DIRECTED_GRAPH16<ARRAY_EDGE16,ARRAY_VERTEX16>(num_v,num_e) {
00456     _map=map;
00457     _type = type;
00458     _pool = NULL;
00459   }
00460 
00461   MEM_POOL *Pool() { return _pool; }
00462 
00463   void Erase_Graph();
00464 
00465   EINDEX16 Add_Edge(VINDEX16 from, VINDEX16 to, DEP dep, BOOL is_must=FALSE) {
00466     Is_True(_type==DEP_ARRAY_GRAPH,
00467       ("Trying to add a dep edge to a non-dep graph"));
00468     EINDEX16 result = 
00469       DIRECTED_GRAPH16<ARRAY_EDGE16,ARRAY_VERTEX16>::Add_Edge(from,to);
00470     if (result != 0) _e[result].DEP_Struct.Dep = dep;
00471     _e[result].DEP_Struct.Is_Must = is_must;
00472     return result;
00473   }
00474 
00475   DEP Dep(EINDEX16 edge) {
00476     Is_True(_type==DEP_ARRAY_GRAPH,
00477       ("Trying to get a dep edge from a non-dep graph"));
00478     return(_e[edge].DEP_Struct.Dep);
00479   }
00480   BOOL Is_Must(EINDEX16 edge) {
00481     Is_True(_type==DEP_ARRAY_GRAPH,
00482       ("Trying to get a dep edge from a non-dep graph"));
00483     return(_e[edge].DEP_Struct.Is_Must);
00484   }
00485   void Set_Dep(EINDEX16 edge, DEP dep, BOOL is_must=FALSE) {
00486     Is_True(_type==DEP_ARRAY_GRAPH,
00487       ("Trying to set a dep edge in a non-dep graph"));
00488     _e[edge].DEP_Struct.Dep = dep;
00489     _e[edge].DEP_Struct.Is_Must = is_must;
00490   }
00491 
00492   VINDEX16 Add_Vertex(WN *wn) {
00493     VINDEX16 result = 
00494       DIRECTED_GRAPH16<ARRAY_EDGE16,ARRAY_VERTEX16>::Add_Vertex();
00495     if (result != 0) {
00496       _v[result].Wn = wn;
00497       WN_MAP_Set(_map,wn, (void *) (UINT) result);
00498     }
00499     return result;
00500   }
00501 
00502   void Remove_Edge(EINDEX16 e) { 
00503     DIRECTED_GRAPH16<ARRAY_EDGE16,ARRAY_VERTEX16>::Delete_Edge(e);
00504   }
00505 
00506   VINDEX16 Get_Vertex(WN *wn) {
00507     return (VINDEX16) (UINT) (INTPTR) WN_MAP_Get(_map,wn);
00508   }
00509 
00510   VINDEX16 Get_Vertex() {
00511     return DIRECTED_GRAPH16<ARRAY_EDGE16,ARRAY_VERTEX16>::Get_Vertex();
00512   }
00513 
00514   void Delete_Vertex(VINDEX16 v) {
00515     WN_MAP_Set(_map, _v[v].Wn, NULL);
00516     DIRECTED_GRAPH16<ARRAY_EDGE16,ARRAY_VERTEX16>::Delete_Vertex(v);
00517   }
00518 
00519   WN* Get_Wn(VINDEX16 v) {
00520     return _v[v].Wn;
00521   }
00522 
00523   void Set_Wn(VINDEX16 v, WN* wn) {
00524     _v[v].Wn=wn;
00525     WN_MAP_Set(_map, _v[v].Wn, (void*)(UINT)v);
00526   }
00527 
00528   void Delete_Vertex(WN *wn) {
00529     Delete_Vertex(Get_Vertex(wn));
00530   }
00531 
00532   void Clear_Map_For_Vertex(VINDEX16 v) {
00533     WN_MAP_Set(_map, _v[v].Wn, NULL);
00534     _v[v].Wn=NULL;
00535   }
00536 
00537   void Clear_Map() {
00538     VINDEX16 v=Get_Vertex();
00539     while (v!=0) {
00540       Clear_Map_For_Vertex(v);
00541       v=Get_Next_Vertex(v);
00542     }
00543   }
00544 
00545   mBOOL Copy_Vertex(VINDEX16 v1, VINDEX16 v2) {
00546     Is_True(_type==DEP_ARRAY_GRAPH,
00547       ("Copy_Vertex only works on DEP_ARRAY_GRAPH"));
00548     if (v2 != 0) {
00549       EINDEX16 e=Get_Out_Edge(v2);
00550       while (e) {
00551         EINDEX16 e1=Get_Next_Out_Edge(e);
00552         Remove_Edge(e);
00553         e=e1;
00554       }
00555       e=Get_In_Edge(v2);
00556       while (e) {
00557         EINDEX16 e1=Get_Next_In_Edge(e);
00558         Remove_Edge(e);
00559         e=e1;
00560       }
00561       e=Get_Out_Edge(v1);
00562       while (e) {
00563         VINDEX16 to=Get_Sink(e);
00564         if (!Add_Edge(v2,to,_e[e].DEP_Struct.Dep,_e[e].DEP_Struct.Is_Must)) {
00565           return 0;
00566         }
00567         e=Get_Next_Out_Edge(e);
00568       }
00569       e=Get_In_Edge(v1);
00570       while (e) {
00571         VINDEX16 source=Get_Source(e);
00572         if (!Add_Edge(source,v2,_e[e].DEP_Struct.Dep,_e[e].DEP_Struct.Is_Must)) {
00573           return 0;
00574         }
00575         e=Get_Next_In_Edge(e);
00576       }
00577     }
00578     return 1;
00579   }
00580 
00581 
00582   void PreserveMapPair(WN *orig, WN *wn1, WN *wn2)
00583   {
00584     VINDEX16    origV;
00585     Is_True((Get_Vertex(wn1)==0),("Dep_PreserveMapPair(): unexpected map"));
00586     Is_True((Get_Vertex(wn2)==0),("Dep_PreserveMapPair(): unexpected map"));
00587 
00588     if (origV = Get_Vertex(orig))
00589     {
00590       VINDEX16  v1 = Get_Vertex(wn1);
00591       VINDEX16  v2 = Get_Vertex(wn2);
00592 
00593       if (v1 == 0)
00594         v1 = Add_Vertex(wn1);
00595 
00596       if (v2 == 0)
00597         v2 = Add_Vertex(wn2);
00598 
00599       Copy_Vertex(origV, v1);
00600       Copy_Vertex(origV, v2);
00601     }
00602   }
00603 
00604   void PruneMapsUsingParity(void);
00605 
00606 
00607 #ifdef LNO
00608   INT Build(WN *func_nd,MEM_POOL *pool=0);
00609   INT Build(ARRAY_DIRECTED_GRAPH16 *da_graph);
00610   EINDEX16 Add_Edge(VINDEX16 from, VINDEX16 to, DEPV_ARRAY *array) {
00611     Is_True(_type==DEPV_ARRAY_ARRAY_GRAPH,
00612       ("Trying to add a DEPV_ARRAY edge to a non-DEPV_ARRAY graph"));
00613     Is_True(!Get_Edge(from,to),("Duplicate edge in Add_Edge \n"));
00614     Is_True(array,("Null array in Add_Edge"));
00615     if (!array) return (EINDEX16) 0;
00616     EINDEX16 result = 
00617       DIRECTED_GRAPH16<ARRAY_EDGE16,ARRAY_VERTEX16>::Add_Edge(from,to);
00618     if (result != 0) _e[result].Depv_Array = array;
00619     return result;
00620   }
00621   EINDEX16 Add_Edge(VINDEX16 from, VINDEX16 to, UINT8 level) {
00622     Is_True(_type==LEVEL_ARRAY_GRAPH,
00623       ("Trying to add a level edge to a non-level graph"));
00624     EINDEX16 result = 
00625       DIRECTED_GRAPH16<ARRAY_EDGE16,ARRAY_VERTEX16>::Add_Edge(from,to);
00626     if (result != 0) _e[result].Level_Info.Level = level;
00627     return result;
00628   }
00629   BOOL Add_Edge(WN *ref1, const DOLOOP_STACK *s1,
00630                 WN *ref2, const DOLOOP_STACK *s2,
00631                 BOOL s1_lex_before_s2, BOOL use_bounds=TRUE);
00632   BOOL Add_Edge_Stars(WN *ref1, const DOLOOP_STACK *s1,
00633                       WN *ref2, const DOLOOP_STACK *s2,
00634                       BOOL s1_lex_before_s2, BOOL pos_only=FALSE);
00635   BOOL Add_Edge_Equals(WN *ref1, const DOLOOP_STACK *s1,
00636                       WN *ref2, const DOLOOP_STACK *s2);
00637 
00638   DEPV_ARRAY *Depv_Array(EINDEX16 edge) {
00639     Is_True(_type==DEPV_ARRAY_ARRAY_GRAPH,
00640       ("Trying to get a DEPV_ARRAY edge from a non-DEPV_ARRAY graph"));
00641     return(_e[edge].Depv_Array);
00642   }
00643 
00644   void Set_Depv_Array(EINDEX16 edge, DEPV_ARRAY* newdv) {
00645     Is_True(_type==DEPV_ARRAY_ARRAY_GRAPH,
00646       ("Trying to set a DEPV_ARRAY edge in a non-DEPV_ARRAY graph"));
00647     _e[edge].Depv_Array = newdv;
00648   }
00649 
00650   UINT8 Level(EINDEX16 edge) {
00651     Is_True(_type==LEVEL_ARRAY_GRAPH,
00652       ("Trying to get a level edge from a non-level graph"));
00653     return(_e[edge].Level_Info.Level);
00654   }
00655 
00656   void Set_Level(EINDEX16 edge, UINT8 level) {
00657     Is_True(_type==LEVEL_ARRAY_GRAPH,
00658       ("Trying to set a level edge in a non-level graph"));
00659     _e[edge].Level_Info.Level = level;
00660   }
00661 
00662 
00663   void Delete_Array_Edge(EINDEX16 e) { 
00664     Is_True(_type==DEPV_ARRAY_ARRAY_GRAPH,
00665       ("Trying to delete a DEPV_ARRAY edge from a non-DEPV_ARRAY graph"));
00666     Delete_DEPV_ARRAY(_e[e].Depv_Array,_pool);
00667     DIRECTED_GRAPH16<ARRAY_EDGE16,ARRAY_VERTEX16>::Delete_Edge(e);
00668   }
00669 
00670 
00671   void Set_Level_Property(EINDEX16 e, UINT16 property) {
00672     _e[e].Level_Info.Property |= property;
00673   }
00674 
00675   BOOL Get_Level_Property(EINDEX16 e, UINT16 property) {
00676     return ((_e[e].Level_Info.Property & property) != 0);
00677   }
00678 
00679   INT Add_Deps_To_Copy_Block(WN *orig, WN *copy, BOOL keep_internal_edge=TRUE);
00680   INT Unrolled_Dependences_Update(WN** bodies, UINT u, UINT loopno);
00681   void Fission_Dep_Update(WN* in_loop,UINT32 total_loops);   
00682   INT Fission_Dep_Update(WN* in_loop,UINT32 total_loops, UINT fission_depth);
00683   void Fission_Dep_Update_R(WN* wn,WN *in_loop,UINT depth);   
00684   INT Build_Region(WN* start, WN* end,DOLOOP_STACK *stack,BOOL rebuild=FALSE, BOOL skip_bad=FALSE);
00685   BOOL Versioned_Dependences_Update (WN* body_orig, WN* body_new, UINT loopno,
00686     WN_MAP version_map);
00687   void Versioned_Create_Vertices (WN* body_orig, WN* body_new);
00688   BOOL Versioned_Dependences_Update_E (WN *body_orig,
00689                                        WN* body_new,
00690                                        WN* root_orig,
00691                                        WN* root_new,
00692                                        UINT loopno,
00693                                        WN_MAP version_map);
00694 
00695 #ifdef Is_True_On
00696   void Check_Graph();
00697 #endif
00698 #endif /* LNO */
00699 
00700 private:
00701 
00702 #ifdef LNO
00703   void Add_Must();
00704   void Set_Must(EINDEX16 edge) {
00705     _e[edge].DEP_Struct.Is_Must = TRUE;
00706   }
00707   BOOL Is_Must(ACCESS_ARRAY *a1, ACCESS_ARRAY *a2, WN *inner_loop,
00708                                         DEP *dep=NULL);
00709 
00710   INT Find_Region(WN *wn, DOLOOP_STACK *stack);
00711   INT Gather_References(WN *wn, REF_LIST_STACK *writes, 
00712         REF_LIST_STACK *reads, DOLOOP_STACK *stack,
00713         class SCALAR_STACK *scalar_writes, class SCALAR_STACK *scalar_reads,
00714         class CALL_STACK *calls, BOOL skip_bad=FALSE);
00715   INT Add_Deps_To_Copy_Block_V(WN *orig, WN *copy, 
00716                 class HASH_TABLE<VINDEX16,VINDEX16> *hash_table);
00717   INT Add_Deps_To_Copy_Block_E(WN *orig, WN *copy,
00718                 class HASH_TABLE<VINDEX16,VINDEX16> *hash_table,
00719                 BOOL keep_internal_edge=TRUE);
00720   INT Unrolled_Dependences_Update_V(WN** bodies, UINT u, 
00721         class HASH_TABLE<VINDEX16,VINDEX16P_LEX_COUNT *> *hash_table,
00722         VINDEX16_STACK *orig_vertices);
00723   INT Unrolled_Dependences_Update_E(UINT u, 
00724         UINT loopno,class HASH_TABLE<VINDEX16,VINDEX16P_LEX_COUNT*>*hash_table,
00725         VINDEX16_STACK *orig_vertices);
00726   INT Unrolled_Dependences_Update_E(VINDEX16 *sources, VINDEX16 *sinks,
00727         EINDEX16 fedge, EINDEX16 bedge,UINT u, UINT loopno, INT lex_count,
00728         INT sink_lex_count);
00729   void Fission_Dep_Update_V(VINDEX16 v,WN *in_loop, UINT depth);   
00730   INT Copy_Do_Loop_Deps(VINDEX16 *do_loop_vertices, INT num_loops);
00731   INT Fission_Dep_Update_R(WN *in_loop,UINT fission_depth, UINT depth,
00732         BOOL outer_good_do);   
00733 #endif
00734 
00735   /* friends called from C functions for reading and writing graphs */
00736   friend void Depgraph_Write(void *depgraph, struct output_file *fl,
00737                              WN_MAP off_map);
00738   friend void *Depgraph_Read(char *cur_addr, char *end_addr, char *wn_base);
00739 };
00740 
00741 extern ARRAY_DIRECTED_GRAPH16 *Current_Dep_Graph;
00742 extern void LNO_Erase_Dg_From_Here_In(WN* wn, ARRAY_DIRECTED_GRAPH16* dg);
00743 extern void Unmapped_Vertices_Here_Out(WN* wn);
00744 
00745 #ifdef LNO
00746 // A list of references and their associated DOLOOP_STACKs
00747 // For efficiency reasons, the build routines use stacks of 
00748 // REFERENCE_LISTs, one element for each base array.  
00749 // A base array is represented by its ST_Base pointer.  
00750 // We only call the dependence routines on two arrays with the same
00751 // base pointer.  If we can't figure out an element's
00752 // base pointer, we put it on the list of zero base pointers.
00753 // Zero base pointers will be compared to everything.
00754 
00755 
00756 class REFERENCE_NODE: public SLIST_NODE {
00757   DECLARE_SLIST_NODE_CLASS( REFERENCE_NODE);
00758 public:
00759   DOLOOP_STACK *Stack;
00760   WN *Wn;
00761   UINT Statement_Number;
00762 
00763   REFERENCE_NODE(WN *wn, DOLOOP_STACK *stack, UINT statement_number) { 
00764     Wn = wn;
00765     Stack = stack; 
00766     Statement_Number = statement_number;
00767   };
00768   void Print(FILE *fp) {
00769     fprintf(fp,"Wn, Statment_Number = 0x%p %d\n",
00770         Wn,Statement_Number); 
00771   }
00772   ~REFERENCE_NODE(); 
00773 };
00774 
00775 class REFERENCE_LIST: public SLIST {
00776   DECLARE_SLIST_CLASS( REFERENCE_LIST, REFERENCE_NODE )
00777 public:
00778   ST *ST_Base;
00779   WN *Array;
00780   WN *Inner_Loop;
00781   REFERENCE_LIST(ST *st_base, WN *array, WN *inner_loop=0) { 
00782     ST_Base = st_base; 
00783     Array = array;
00784     Inner_Loop = inner_loop;
00785   };
00786   void Print(FILE *fp);
00787   ~REFERENCE_LIST();
00788 };
00789 
00790 
00791 // A stack of SYMBOLs and all the WNs that access that symbol
00792 
00793 // one reference
00794 class SCALAR_REF {
00795 public:
00796   WN *Wn;
00797   UINT Statement_Number;
00798   SCALAR_REF(WN *wn, UINT statement_number) {
00799     Wn = wn;
00800     Statement_Number = statement_number;
00801   }
00802   SCALAR_REF& operator=(const SCALAR_REF& scalar_ref) {
00803     Wn = scalar_ref.Wn;
00804     Statement_Number = scalar_ref.Statement_Number;
00805     return *this;
00806   }
00807 };
00808 
00809 // all the references to a particular SYMBOL
00810 class SCALAR_NODE
00811 {
00812   MEM_POOL *_pool;
00813 public:
00814   SYMBOL _scalar;
00815   STACK <SCALAR_REF> *_scalar_ref_stack;
00816   SCALAR_NODE(MEM_POOL *pool, SYMBOL scalar) { 
00817     typedef STACK<SCALAR_REF> SCALAR_REF_STACK;
00818     _pool = pool;
00819     _scalar_ref_stack = CXX_NEW(SCALAR_REF_STACK(pool),pool);
00820     _scalar = scalar;
00821   }
00822   INT Elements() const { return _scalar_ref_stack->Elements(); };
00823   SCALAR_REF *Bottom_nth(INT i) { return &_scalar_ref_stack->Bottom_nth(i); };
00824   SCALAR_REF *Top_nth(INT i) { return &_scalar_ref_stack->Top_nth(i); };
00825 };
00826 
00827 class SCALAR_STACK
00828 {
00829   STACK <SCALAR_NODE> *_stack;
00830   MEM_POOL *_pool;
00831 public:
00832   SCALAR_STACK(MEM_POOL *pool) { 
00833     typedef STACK<SCALAR_NODE> SNODE_STACK;
00834     typedef STACK<INT> INT_STACK;
00835     _pool = pool;
00836     _stack = CXX_NEW(SNODE_STACK(pool),pool);
00837   }
00838   void Add_Scalar(WN *wn, UINT snumber);
00839   void Add_Scalar(WN *wn_call, SYMBOL* symbol, UINT snumber);
00840   void Print(FILE *fp);
00841   void Clear() { _stack->Clear(); };
00842   INT Elements() const { return _stack->Elements(); };
00843   SCALAR_NODE* Bottom_nth(INT i) { return &_stack->Bottom_nth(i); };
00844   SCALAR_NODE* Top_nth(INT i) { return &_stack->Top_nth(i); };
00845   void Add_Scalar_Node(SCALAR_NODE* sn) {_stack->Push(*sn);};
00846   void Clear_Formal(INT i); 
00847 };
00848 
00849 // describe the calls
00850 class CALL_NODE
00851 {
00852 public:
00853   WN *_call;
00854   UINT _statement_number;
00855   DOLOOP_STACK *_stack;
00856   BOOL _is_concurrent_call;
00857   CALL_NODE(WN *call, UINT statement_number, DOLOOP_STACK *stack,
00858                         BOOL is_concurrent_call) {
00859     _call = call;
00860     _statement_number = statement_number;
00861     _stack = stack;
00862     _is_concurrent_call = is_concurrent_call;
00863   }
00864 };
00865 
00866 class CALL_STACK
00867 {
00868   STACK <CALL_NODE> *_stack;
00869   MEM_POOL *_pool;
00870 public:
00871   CALL_STACK(MEM_POOL *pool) { 
00872     typedef STACK<CALL_NODE> CNODE_STACK;
00873     _pool = pool;
00874     _stack = CXX_NEW(CNODE_STACK(pool),pool);
00875   }
00876   void Clear() { _stack->Clear(); }
00877   INT Elements() const { return _stack->Elements(); };
00878   CALL_NODE *Bottom_nth(INT i) { return &_stack->Bottom_nth(i); };
00879   CALL_NODE *Top_nth(INT i) { return &_stack->Top_nth(i); };
00880   void Push(WN *call, UINT statement_number,DOLOOP_STACK *stack,
00881                 BOOL is_concurrent_call) { 
00882     _stack->Push(CALL_NODE(call,statement_number,stack,is_concurrent_call)); 
00883   };
00884 };
00885 
00886 // describe the calls
00887 
00888 
00889 
00890 class REFERENCE_ITER: public SLIST_ITER {
00891   DECLARE_SLIST_ITER_CLASS( REFERENCE_ITER, REFERENCE_NODE ,REFERENCE_LIST);
00892 public:
00893   ~REFERENCE_ITER() {};
00894 };
00895 
00896 #endif 
00897 
00898 
00899 #endif
00900 
00901 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines