Polaris: DDgraph.h Source File

DDgraph.h

Go to the documentation of this file.
00001 #ifndef _DD_GRAPH_H
00002 #define _DD_GRAPH_H
00003 ///
00004 ///
00005 ///
00006 /// \class DDgraph 
00007 /// \brief a semantic interface to the Data Dependence Graph.
00008 /// \defgroup Polaris
00009 /// \ingroup Polaris
00010 ///  Base
00011 /// \see DDgraph.h
00012 /// \see DDgraph.h
00013 ///
00014 /// \endcode
00015 /// \section Overview Overview
00016 /// The DDgraph provides the user with information about the data
00017 /// dependences contained in a program.
00018 ///
00019 /// \endcode
00020 /// \section Description Description
00021 /// The DDgraph provides the user with information about the data
00022 /// dependences contained in a program.
00023 ///
00024 /// \endcode
00025 /// \section Caveats Caveats
00026 /// A paragraph describing unusual features of the class.
00027 /// This paragraph may be omitted.
00028 ///
00029 #define _DDG_TEST
00030 ///
00031 #ifdef  _DDG_TEST
00032 class DDgraphTester;
00033 #endif
00034 
00035 #ifdef POLARIS_GNU_PRAGMAS
00036 #pragma interface
00037 #endif
00038 
00039 #include <assert.h>
00040 
00041 #include "Symbol/Symbol.h"
00042 #include "Statement/Statement.h"
00043 #include "StmtList.h"
00044 #include "Collection/List.h"
00045 #include "Collection/RefList.h"
00046 #include "Collection/Iterator.h"
00047 #include "Collection/Mutator.h"
00048 #include "Expression/Expression.h"
00049 #include "Expression/ArrayRefExpr.h"
00050 #include "Expression/IDExpr.h"
00051 #include "macros.h"
00052 
00053 #include "ArcSpec.h"
00054 
00055 
00056 class Program;
00057 class DDgraph;
00058 class DDiterator;
00059 
00060 typedef signed char Binary_flag;
00061 ///< Used for flags with on/off as its values
00062 
00063 
00064 enum DDtests_Seq {
00065     ///< Specify the sequence of the dd-tests to be used
00066     ///< Currently the sequence is fixed, and the only option uesr might
00067     ///< choose is what tests are included and omitted in this fixed sequence
00068     _None,
00069     _GCD_Only,      ///< Constant_test included here
00070     _Banerjee_Only,
00071     _Omega_Only,
00072     _GCD_Banerjee,
00073     _Banerjee_Omega,
00074     _GCD_Omega,
00075     _All
00076 };
00077 
00078 
00079 enum DDI_INIT_TYPE {
00080     ///< DDiterator object is initialized
00081     ///< tells how 'from/to'-statement of
00082     _STMTS,                     
00083     _EXPR
00084 };
00085 
00086 enum In_Out_refs {
00087     ///< Used only in DDiterator
00088     _IN_REFS,                   
00089     _OUT_REFS
00090 };
00091 
00092 enum First_Last {
00093     ///< Used in compute_dvf_n_arc()
00094     _FIRST,                     
00095     _LAST
00096 };
00097 
00098 ///< An ElementDV object corresponds to a direction whose value is one of
00099 ///< <,>,=,<=,=>,<>,* and a delimiter '000'.  List<ElementDV> is a drection
00100 ///< vector and is included in a DVfield object.  Through ElementDV, we can
00101 ///< do elemental operations querying/updating one direction element of a
00102 ///< direction vector. For more general operations for a direction vector
00103 ///< such as expanding/shrinking/ a DV itself by adding/deleting its
00104 ///< elements, we may use the member functions provided in a DVfield object.
00105 
00106 class ElementDV : public Listable {
00107  private:
00108     DIREC_TYPE      _direction;
00109     DDIST_TYPE      _min_distance;      ///< lower bound on distance
00110     DDIST_TYPE      _max_distance;      ///< upper bound on distance
00111     Boolean         _distance_valid;        ///< distance valid bit
00112 
00113 
00114  public:
00115     inline       ElementDV(DIREC_TYPE direc);
00116 
00117     inline       ElementDV(const ElementDV & other);
00118 
00119     inline       ElementDV(DIREC_TYPE direc, DDIST_TYPE const_distance);
00120 
00121     inline       ElementDV(DIREC_TYPE direc, DDIST_TYPE min, DDIST_TYPE max);
00122 
00123     ~ElementDV();
00124 
00125     inline DIREC_TYPE  direction() const;
00126     inline void        direction(DIREC_TYPE new_direc);
00127     ///< Query or Update a direction
00128 
00129     ///< Query or Update a distance
00130     inline Boolean     is_distance_valid ();    ///< check valid
00131     inline void        make_distance_valid ();  ///< make valid
00132     inline Boolean     is_distance_constant (); ///< check constant distance
00133 
00134     ///< query and update distance components;
00135     inline DDIST_TYPE distance ();
00136     inline void       distance(DDIST_TYPE new_distance);
00137 
00138     inline DDIST_TYPE min_distance ();
00139     inline void       min_distance (DDIST_TYPE new_min_distance);
00140 
00141     inline DDIST_TYPE max_distance ();
00142     inline void       max_distance (DDIST_TYPE new_max_distance);
00143 
00144     virtual Listable *listable_clone() const;
00145     ///< Duplicate copy of this object
00146 
00147     virtual void    print(ostream & o) const;
00148 };
00149 
00150 ///< DVfield is a basic unit of data dependence information between two
00151 ///< expressions and is built by a DDiterator object. The information it
00152 ///< keeps inside it is as follows;
00153 ///< one direction vector for the dependence relation,
00154 ///< dependency decision(assumed/proved),
00155 ///< dependence type(flow/anti/input/output),
00156 ///< pointers to the expressions & statements related to the dependency.
00157 
00158 class DVfield   : public Listable {
00159  private:
00160 #ifdef  _DDG_TEST
00161     friend class          DDgraphTester;
00162 #endif
00163     friend class         DDgraph;
00164 
00165     int             _references;
00166     ///< Number of DDiterators currently pointing to this DVfield.
00167 
00168     Binary_flag     _valid;
00169     ///< If this field is off, this DVfield is no longer valid.
00170     ///< The last iterator which leaves this node will dispose this.
00171 
00172     DEP_DECISION    _dep_decided;
00173     DEP_TYPE        _dep_type;
00174 
00175     const           Expression & _from_expr;
00176     const           Expression & _to_expr;
00177     ///< There is dependency arc from _from_expr to _to_expr
00178 
00179     const           Statement & _from_stmt;
00180     const           Statement & _to_stmt;
00181     ///< _from/to_expr belong to _from/to_stmt, respectively
00182 
00183     Expression      *_label;
00184 
00185     List<ElementDV>_dv;
00186     ///< List of dependence directions
00187 
00188     inline int      references_inc();
00189     inline int      references_dec();
00190     ///< increase/decrease the reference count by one and return 
00191     ///< the new count
00192 
00193     inline void     valid_on();
00194     inline void     valid_off();
00195     ///< make this DVfield valid/invalid
00196 
00197  public:
00198     inline DVfield(DEP_DECISION dep_decided, DEP_TYPE dep_type,
00199                    const Statement & from_stmt, const Expression & from_expr,
00200                    const Statement & to_stmt, const Expression & to_expr);
00201 
00202     inline DVfield(const DVfield & other);
00203 
00204     ~DVfield();
00205 
00206     inline DEP_DECISION dep_decided();
00207     inline void     dep_decided(DEP_DECISION new_ddecided);
00208     ///< Query or update dep_decided/assumed dependency flag in DVfield
00209 
00210     inline DEP_TYPE dep_type();
00211     inline void     dep_type(DEP_TYPE new_dtype);
00212     ///< Query or update dependence type in DVfield
00213 
00214     inline const    Expression & from_expr();
00215     inline const    Expression & to_expr();
00216     inline const    Statement & from_stmt();
00217     inline const    Statement & to_stmt();
00218     ///< Get the information about what expressions and statements
00219     ///< are involoved in this dependency relation
00220 
00221     ///< There are two ways to build a direction vector as follows;
00222     ///< -> adding one element by one element: dv()
00223     ///< -> copying everything from another: dv(List<ElementDV>&)
00224 
00225     inline          List<ElementDV>&dv();
00226     ///< Get a reference of the direction vector.
00227     ///< Using this reference, a new DV can be built or reorganized.
00228     ///< First get this reference, and insert or delete some of elements
00229     ///< of this DV by using the operations provided in class List<>.
00230 
00231     inline void     dv(List<ElementDV>&new_dv);
00232     ///< copy constructor - another way to build a DV.
00233     ///< If the DV is only for this DVfield, we recommend to use
00234     ///< the way described above rather than this copy constructor.
00235 
00236   Expression *label() { return _label; }
00237   void setLabel(Expression *label) { _label = label; }
00238 
00239     virtual Listable *listable_clone() const;
00240     ///< Duplicate copy of this object
00241 
00242     virtual void    print(ostream & o) const ;
00243 
00244 };
00245 
00246 
00247 ///< A list of these ActiveArc objects are directly managed by an DDgraph
00248 ///< object.  This is an uncompacted version of an arc which is embedded 
00249 ///< in a ProgramUint.  Most of the fields in this object are based on the 
00250 ///< arc.  When the first visitor(DDiterator) arrives some arc, the 'active' 
00251 ///< field is made to be turned on and most of the values in the arc are 
00252 ///< copied into the DDgraph creating a new ActiveArc object.  Every operation 
00253 ///< on arc is actually performed on this object through the DDgraph by each 
00254 ///< DDiterator. When all of DDiterators leave this object, the most updated 
00255 ///< data in this will be copied back into the corresponing arc in the 
00256 ///< ProgramUnit. Currently every member and operation is accessed and managed 
00257 ///< by DDgraph only.  
00258 
00259 class ActiveArc : public Listable {
00260  private:
00261 #ifdef  _DDG_TEST
00262     friend class            DDgraphTester;
00263 #endif
00264     friend class         DDgraph;
00265 
00266     int             _references;
00267     ///< Number of DDiterators pointing this active arc
00268     ///< (cf: _references in DVfield object)
00269 
00270     Arc_type       *_this_arc;
00271     Arc_type       *_prev_arc;
00272     Arc_type       *_next_arc;
00273     ///< pointing to the this/previous/next arcs in the compacted form,
00274     ///< respectively.  _this_arc is the current arc whose data is
00275     ///< originally copied into this ActiveArc object.
00276 
00277     const           Expression & _source_expr;
00278     const           Expression & _target_expr;
00279     ///< Dependency is described in terms of two expressions, source and
00280     ///< target.  Dependence direction is from the source to the target.
00281     ///< For instance, if the direction is reverse(_REVERSE),
00282     ///< then that implies the source is dependent on the target.
00283     ///< _source_expr is the current expression which points to the current
00284     ///< arc.
00285 
00286     const           Statement & _source_stmt;
00287     const           Statement & _target_stmt;
00288     ///< _source_stmt has _source_expr and _target_stmt does _target_expr.
00289     ///< _source_stmt is the current statement.
00290 
00291     List<DVfield>*_original_dv_fields;
00292     ///< An exact copy of the original DVfields stored in the arc
00293 
00294     List<DVfield>_working_dv_fields;
00295     ///< Initially, the same copy with the original list,
00296     ///< _original_dv_fields.  Unlike it, the contents of this list are 
00297     ///< changed by DDiterators or users, as time goes by.  When this 
00298     ///< ActiveArc is decativated(destructed), this list is compared with 
00299     ///< the original list.  If they are diffrent, the working list will be 
00300     ///< overwritten onto the corresponding arc in a ProgramUnit.  Especially, 
00301     ///< if their size are also diffrent, the arc will be deallocated and a 
00302     ///< new space will be allocated to accomodate the working list.
00303 
00304   ///< CC 06/15/98
00305   Expression *_label;
00306   ///< denotes the number of references accessed between source and dest.
00307   ///< used for the stack algorithm
00308   ///< CC end
00309 
00310  public:
00311     ///< Initialized with the address of the original arc and its size in
00312     ///< terms of the number of bits, also initializing the other members 
00313     ///< with proper values
00314 
00315     inline ActiveArc(DDgraph & ddg, Arc_type * original_arc,
00316              Arc_type * prev_of_origin, Arc_type * next_of_origin,
00317              const Statement & src_stmt, const Expression & src_expr);
00318 
00319     inline ActiveArc(const ActiveArc & other);
00320 
00321     ~ActiveArc();
00322 
00323     virtual void    print(ostream & o) const;
00324 
00325     virtual Listable *listable_clone() const;
00326     ///< Duplicate copy of this object
00327 
00328   ///< CC 06/15/98
00329   Expression *label() { return _label; }
00330   void setLabel(Expression *label) { _label = label; }
00331   ///< CC end
00332 
00333 
00334 };
00335 
00336 ///< Interface for access to the elements in Data Dependence(DD) graph.
00337 ///< Some of operations are allowed only to DDiterator objects and the
00338 ///< others are allowed to general users, such as adding some dependency
00339 ///< information into DDgraph.  DDgraph can exclusively access all the 
00340 ///< private elements of DVfield and ActiveArc, and the original arcs 
00341 ///< itself(defined as a private member of Expression and DDgraph is 
00342 ///< its friend).
00343 
00344 class DDgraph {
00345  private:
00346 #ifdef  _DDG_TEST
00347     friend class          DDgraphTester;
00348 #endif
00349     friend class         ActiveArc;
00350     friend class         DDiterator;
00351     ///< to use the private member functions
00352 
00353     const int       _ptr_size;  ///< Size of a pointer type in bits
00354 
00355     const int       _tgt_expr_offset;
00356     const int       _label_offset;
00357     const int       _next_arc_offset;
00358     const int       _data_field_offset;
00359     ///< Offsets for three pointers stored in an arc
00360 
00361     StmtList & _stmts;
00362     ///< Statement list of this ProgramUnit
00363 
00364     inline Arc_type *arcs_ptr(const Expression & src_expr);
00365     ///< Return the pointer to the original arc
00366     ///< Return NULL if src_expr.op is not either ID nor Array Reference
00367 
00368     List<ActiveArc>_active_arcs;
00369     ///< Initially, an empty list
00370 
00371     inline void     _clear_arc(Arc_type * arc, int bytes);
00372 
00373     inline Binary_flag is_active(Arc_type * arc);
00374     inline void     activate(Arc_type * arc);
00375     inline void     deactivate(Arc_type * arc);
00376     ///< query/activate/deactivate the arc by accessing the active flag
00377     ///< stored in arc_field where each arc is represented by a consecutive
00378     ///< series of Arc_type variables and 'arc_field' is one of them
00379 
00380     inline Statement *target_stmt(Arc_type * arc) const;
00381     inline Expression *target_expr(Arc_type * arc) const;
00382     inline Expression *label_expr(Arc_type * arc) const;
00383     inline Arc_type *next_arc(Arc_type * arc) const;
00384     inline Arc_type *data_field(Arc_type * arc) const;
00385     ///< Return the pointers to the appropriate type stored in 'arc'
00386 
00387     inline void     store_target_stmt(Arc_type * arc, const Statement & stmt);
00388     inline void     store_target_expr(Arc_type * arc, const Expression & expr);
00389     inline void     store_label_expr(Arc_type * arc, const Expression & expr);
00390     inline void     store_next_arc(Arc_type * arc, Arc_type * next);
00391     ///< Store the pointers to the appropriate type into 'arc'
00392 
00393     Binary_flag  is_new_dvfield(Arc_type * &arc_field, int &position);
00394     DEP_DECISION dep_decision(Arc_type * &arc_field, int &position);
00395     DEP_DIREC    dep_direction(Arc_type * &arc_field, int &position);
00396     DEP_TYPE     dep_type(Arc_type * &arc_field, int &position);
00397     DIREC_TYPE   direction(Arc_type * &arc_field, int &position);
00398     DDIST_TYPE   min_distance(Arc_type * &arc_field, int &position);
00399     DDIST_TYPE   max_distance(Arc_type * &arc_field, int &position);
00400 
00401     ///< 'arc_field' is one Arc_type variable which contains the part of the
00402     ///< information of DV fields such as dependence decision, dependence
00403     ///< direction, and so on.  The field to be extracted from 'arc_field'
00404     ///< starts from ('position'-1)th bit.  The value of 'position' will be
00405     ///< changed to the beginning position of the next field after the
00406     ///< current field is extracted and returned.  Since sizeof(Arc_type) 
00407     ///< is currently a byte, 'position' normally ranges from 0 to 7.
00408     ///< The next 'position' is normally 'position' + length(current field),
00409     ///< but if sizeof(Arc_type) < the next 'position', then the next
00410     ///< 'position' become position' + length(current field) -  sizeof(Arc_type) 
00411     ///< and arc_field is moved to the next one by arc_field++.  So, arc_field
00412     ///< and position are always supposed to point to the beginning of the next
00413     ///< field when the function is returned.
00414 
00415     inline DEP_DIREC test_dep_direction(Arc_type * arc_field, int offset);
00416     ///< Unlike the above methods, there is no side effect and 'offset' can
00417     ///< be greater then A_BYTE.  'offset' is counted from the beginning of
00418     ///< 'arc_field'.
00419 
00420     void     mark_new_dvfield(Arc_type * &arc_field, int &position);
00421     void     mark_arc_end(Arc_type * &arc_field, int &position);
00422     void     store_dep_decision(Arc_type * &arc_field, int &position,
00423                                               DEP_DECISION ddeci);
00424     void     store_dep_direction(Arc_type * &arc_field, int &position,
00425                                                  DEP_DIREC ddirec);
00426     void     store_dep_type(Arc_type * &arc_field, int &position,
00427                                                    DEP_TYPE deptype);
00428     void     store_direction(Arc_type * &arc_field, int &position,
00429                                                     DIREC_TYPE direct);
00430     void     store_min_distance(Arc_type * &arc_field, int &position,
00431                                                     DDIST_TYPE min_dist);
00432     void     store_max_distance(Arc_type * &arc_field, int &position,
00433                                                     DDIST_TYPE min_dist);
00434     void     store_const_distance(Arc_type * &arc_field, int &position,
00435                                                     DDIST_TYPE const_dist);
00436 
00437     ///< Store each field data into the Arc_type variable by appending it
00438     ///< at the end of the valid data so far stored.
00439     ///< arc_field must be initially cleared before it is filled with the
00440     ///< fields.
00441 
00442     inline Arc_type _test_1bit_field(Arc_type * arc_field, int offset);
00443 
00444     ///< Test and return dep. direction which is located at the 'offset'th
00445     ///< bit from the beginning of 'arc_field'.  The type of return value 
00446     ///< can be Arc_type or any of its derived type, such as DEP_TYPE.  NO 
00447     ///< Side effect.
00448 
00449     inline void     _skip_this_dvfield(Arc_type * &arc_field, int &position);
00450     ///< When this is called, pair(arc_field, position) must point to the
00451     ///< dependence decision field of the current DV field.  After this
00452     ///< function is performed, they are changed to point to a bit marking 
00453     ///< a beginning of the next DVfield that is 1 bit before the dependence 
00454     ///< decision field of the DVfield. If this DV field was the last in this 
00455     ///< arc, is_new_dvfield() will return FALSE at the new position.
00456 
00457     inline int      _count_this_dvfield(Arc_type * &arc_field, int &position);
00458 
00459     ///< As skipping this DVfield, count the bits and return the final
00460     ///< number.
00461 
00462     void search_active_arcs_for(DVfield * &dvf, ActiveArc * &active_arc,
00463                                 First_Last fl, DEP_DIREC ddirec,
00464                                 const Expression & from_expr,
00465                                 const Expression & to_expr);
00466 
00467     ///< INPUT: ddirec, src_expr, tgt_expr
00468     ///< OUTPUT: dvf, active_arc
00469     ///<
00470     ///< Search ActiveArc list for DVfield & ActiveArc with from_expr &
00471     ///< to_expr with dependence direction as ddirec, and return their 
00472     ///< pointers The first of such a DVfield and an ActiveArc will be 
00473     ///< returned.  IF there is no such DVfield, then dvf will be NULL.
00474     ///< \note The ActiveArc with a pair 'from/to'_expr as its source and
00475     ///< target must already be in _active_arcs.
00476 
00477     void update_links_between(Arc_type * new_this, ActiveArc * active_arc);
00478     ///< Put new_this arc between prev and next arcs of active_arc:w
00479 
00480     void  write_back_arc(ActiveArc * active_arc);
00481     ///< If there has any change in active_arc from the original arc,
00482     ///< write the contents of active_arc back to the orignal arc, with
00483     ///< memeory operation if necessary.
00484     ///< active_arc must have at least one DVfield at the moment.
00485 
00486     void compute_dvf_n_arc(DVfield * &dvf, ActiveArc * &active_arc, 
00487                            First_Last fl,
00488                            const Statement & from_stmt,
00489                            const Expression & from_expr,
00490                            const Statement & to_stmt,
00491                            const Expression & to_expr);
00492     ///< INPUT: from_stmt, from_expr, to_stmt, to_expr, fl
00493     ///< OUTPUT: dvf, active_arc
00494     ///<
00495     ///< Upon the request of DDiterator, DDgraph access the original arc and
00496     ///< check its active field. If it is active, search _active_arcs for
00497     ///< the correspondng active arc and if the active one is found then all 
00498     ///< the DVfields inside it is searched again matching input arguments 
00499     ///< with each of them.  Depending on the value of 'fl', return the
00500     ///< first/last one which satisfy the requirement.  If the original arc 
00501     ///< is inactive, first search it for a matching DVfield, and if it is 
00502     ///< found then create a new ActiveArc object for the arc returning the 
00503     ///< pointer to the DVfield dvf in ActiveArc active_arc.  If all these 
00504     ///< efforts to find the right DVfield are failed, NULL will be returned 
00505     ///< for the value of dvf*.
00506 
00507     DVfield        *prev(DVfield * dvf, ActiveArc * active_arc);
00508     DVfield        *next(DVfield * dvf, ActiveArc * active_arc);
00509 
00510     ///< Return the previous/next object of 'dvf' within the same active
00511     ///< arc.  The previous/next one must have the same pairs of from/to-
00512     ///< statements and from/to-expressions with 'dvf'.  If there is no 
00513     ///< more such a DVfield object, NULL will be returned and simutaneously 
00514     ///< check all the DV fields in the active arc to see all reference 
00515     ///< values are zero(no DDiterator pointing to any DVfields in this arc). 
00516     ///< If they are all zero, then update or not the original arc field 
00517     ///< depending on the status of flags in ActveArc.
00518 
00519     inline void     exit(DVfield * dvf, ActiveArc * active_arc);
00520     ///< When the client(DDiterator) leaves the current active arc, it must
00521     ///< report to DDgraph so that DDgraph can update the corresponding
00522     ///< active arc, esp reference count of the DVfield the client pointed
00523     ///< to last and the reference count of the active arc itself where if 
00524     ///< the latter count is zero, then the active structure will be purged 
00525     ///< and written back to the original arc if there are any change from 
00526     ///< the original copy.  No operation if dvf is NULL.
00527 
00528     void            release(DVfield * dvf, ActiveArc * &active_arc);
00529     inline void     hold(DVfield * dvf);
00530 
00531     ///< Handling chores which must be dealt with when we release/hold
00532     ///< DVfield.  In releasing it, if the dvf is invalid and the only 
00533     ///< one in active_arc, then delete the arc and make active_arc NULL.  
00534     ///< In hold it, increase the reference count of the DVfield.
00535 
00536     inline void     mark_dead(DVfield * dvf);
00537     ///< Invalidate dvf to mark this deleted
00538 
00539     inline Binary_flag is_alive(DVfield * dvf);
00540     ///< Return the validity of dvf
00541 
00542     inline Binary_flag is_shared(DVfield * dvf);
00543     ///< Return true if dvf is shared by more than one DDiterators
00544 
00545     inline DVfield *detach(DVfield * dvf, ActiveArc * active_arc);
00546     ///< Remove 'dvf' from 'active_arc' only
00547 
00548     inline List<DVfield>*dvfield_list(ActiveArc * active_arc);
00549     ///< Return a pointer to working_dv_filed of active_arc
00550 
00551     void initialize_this_active_arc(ActiveArc * aarc, Arc_type * arc);
00552     ///< This is called by only 'aarc' when it is created
00553 
00554  public:
00555     inline DDgraph(StmtList & stmts);
00556 
00557     inline ~DDgraph();
00558 
00559     void   add(List<DVfield>&dv_fields);
00560 
00561     ///< dv_fields is a list of DV fields where each DV field has dependency
00562     ///< information between two expressions.  Instead of directly adding
00563     ///< these to DDgraph, usually turn them into a compact form and embed 
00564     ///< them into the ProgramUint for the future use. But, if one of these 
00565     ///< DVfields would belong to an arc which is currently active, then it 
00566     ///< must be directly added to the corresponding active structure ActiveArc.
00567 }; 
00568 
00569 inline
00570 DDgraph::DDgraph(StmtList & stmts)
00571     : _ptr_size(sizeof(char *) * A_BYTE), 
00572       _tgt_expr_offset(sizeof(char *)), 
00573       _label_offset(sizeof(char *) * 2),
00574       _next_arc_offset(sizeof(char *) * 3), 
00575       _data_field_offset(sizeof(char *) * 4),
00576       _stmts(stmts)
00577 {
00578     assert(sizeof(Arc_type) == 1 && sizeof(Binary_flag) == 1);
00579     ///<       p_assert("sizeof(Arc_type) & sizeof(Binary_flag) must be  equal to 1 byte");
00580 }
00581 
00582 inline
00583 DDgraph::~DDgraph() 
00584 {
00585     ///< nothing to do
00586 }
00587 
00588 ///< A DDiterator object pretends to iterate over each DVfield which
00589 ///< embraces the data dependence information between two expressions
00590 ///< (See above), but it actually contains at any moment all the data
00591 ///< stored in an arc where several DVfields might be included.
00592 ///< When it has ended its iteration over all the DVfields in an arc,
00593 ///< it throws away all the information pertaing to the old arc such as
00594 ///< List<DVfield>, and moves to the next arc(if necessay, the next
00595 ///< Expression and the next Statement too) creating and organizing the
00596 ///< information for the new arc.
00597 
00598 class DDiterator {
00599 
00600     ///< DDiterator is initialized by one of the following options;
00601     ///< (2 Statement lists) -> from-statements vs. to-statements
00602     ///< (2 pairs of a Statement & an Expression) -> dependency for two
00603     ///< expressions where each lives in its partner statement, respectively
00604     ///<
00605     ///< --> A statement list must be RefList and is for randomly selected
00606     ///< statements to update/query their dependency information.
00607 
00608  private:
00609 #ifdef  _DDG_TEST
00610     friend class         DDgraphTester;
00611 #endif
00612     DDI_INIT_TYPE   _init_from;
00613     DDI_INIT_TYPE   _init_to;
00614 
00615     ///< tells how each 'from' and 'to' part of this iterator is
00616     ///< initialized.  The choice is made from three selections, 
00617     ///< namely, a statement list (STMTS), a pair of a statement and 
00618     ///< an expression(EXPR)
00619 
00620     In_Out_refs     _from_refs;
00621     In_Out_refs     _to_refs;
00622     ///< Miscellaneous flags used for _iter_from/to_exprs initialization
00623 
00624     RefList<Statement> * _from_stmts;
00625     RefList<Statement> * _to_stmts;
00626     ///< If this iterator is initialized by STMTS, these keep the
00627     ///< corresponding list of statements
00628 
00629     Iterator<Statement>*_iter_from_stmts;
00630     Iterator<Statement>*_iter_to_stmts;
00631     ///< iterators for the lists of statements above
00632 
00633     Iterator<Expression>*_iter_from_exprs;
00634     Iterator<Expression>*_iter_to_exprs;
00635     ///< Keep in/out_refs() expression lists of the current statements when
00636     ///< this iterator is initialized by STMTS
00637 
00638     const           Statement * _from_stmt;
00639     const           Expression * _from_expr;
00640     const           Statement * _to_stmt;
00641     const           Expression * _to_expr;
00642     ///< If this iterator is initialized by EXPR, these keep the infomation
00643 
00644     DVfield        *_current_dvf;
00645     ///< the current DV field object.
00646     ///< Must be NULL(= 0) when this iterator doen't point to anything, such
00647     ///< as when it arrives the end of the iteration space.
00648 
00649     ActiveArc      *_active_arc;
00650     ///< in which _current_dvf lives
00651 
00652     DDgraph & _ddgraph;
00653     ///< This is the only interface through which a DDiterator can access
00654     ///< DVfields inside a data dependence graph.  DDiterator can read or
00655     ///< call any private members but not modify them directly.
00656     ///< We are supposed to have a unique _ddgraph pointer per ProgramUni.
00657 
00658     void            _next_in_STMTS_n_STMTS();
00659     void            _next_in_STMTS_n_EXPR();
00660     void            _next_in_EXPR_n_STMTS();
00661     void            _prev_in_STMTS_n_STMTS();
00662     void            _prev_in_STMTS_n_EXPR();
00663     void            _prev_in_EXPR_n_STMTS();
00664     ///< Compute previous/next DVfield of the current position in the
00665     ///< iteration space.  This choice of the computation is distingushed 
00666     ///< by the method of the initialization, such as (from == STMTS, 
00667     ///< to == STMTS).
00668 
00669  public:
00670     DDiterator(RefList<Statement> * from_stmts, RefList<Statement> * to_stmts,
00671            DDgraph & ddgraph);
00672     ///< The ownership of both RefLists is transfered to DDiterator.
00673     ///< That means DDiterator will delete these lists later(Note: since
00674     ///< they are RefLists, their elements<each Statement> won't be deleted,
00675     ///< but the lists itself will be dissolved).
00676 
00677     inline DDiterator(const Statement & from_stmt, const Expression & from_expr,
00678                       const Statement & to_stmt, const Expression & to_expr,
00679                       DDgraph & ddgraph);
00680 
00681     DDiterator(RefList<Statement> * from_stmts,
00682                const Statement & to_stmt, const Expression & to_expr,
00683                DDgraph & ddgraph);
00684 
00685     DDiterator(const Statement & from_stmt, const Expression & from_expr,
00686                RefList<Statement> * to_stmts, DDgraph & ddgraph);
00687 
00688     DDiterator(const DDiterator & other);
00689     ///< This method copies the entire state (including current arc)
00690     ///< of the iterator.  If you don't like this, then immediately follow
00691     ///< this constructor with a call to reset()
00692 
00693     inline          ~DDiterator();
00694     ///< Release the current DVfield on exiting
00695 
00696     inline Boolean  valid();
00697     inline Boolean  end();
00698     ///< Used to check if there are more Nodes to iterate on.
00699     ///< If yes, then valid() returns TRUE, else FALSE.
00700     ///< end() is equivalent to NOT valid().
00701 
00702     inline          DVfield & current();
00703     ///< Return a reference to the current DV field of the current arc.
00704     ///< If there is no current, this results in an error.
00705     ///< This is always suppposed to return VALID node, since every invalid
00706     ///< node will be automatically skipped.
00707 
00708   ///< CC 06/15/98
00709   ActiveArc *current_arc() { return _active_arc; }
00710   ///< CC end
00711 
00712     inline Boolean  current_valid();
00713     inline Boolean  current_invalid();
00714 
00715     ///< tells whether or not this node is valid.
00716     ///< Even though DDiterator guarantees to return valid node in response
00717     ///< to current(), there is still chance for the current node to become
00718     ///< invalid by grab() called by the other iterator which shares it.  
00719     ///< Since accessing any members in invalid object causes an error, 
00720     ///< checking for validity of the current might be necessary for safety 
00721     ///< reason.
00722 
00723     inline DVfield *grab();
00724     ///< Grab the current element after deleting or invalidating it from the
00725     ///< list
00726 
00727     inline void     modify(DVfield * other);
00728     ///< Subsititude new_dv_field for the DVfield currently pointed by
00729     ///< iterator
00730 
00731     inline void     del();
00732     ///< Delete the current DVfield.
00733     ///< If this DVfield is only one left in the current arc,
00734     ///< the arc would also be deleted(invalidated or deallocated).
00735 
00736     ///< Move operations: reset, set_to_last, next, prev, ++, --
00737     ///< -> When an iterator leaves one arc for another, the list DVfields
00738     ///< will be overwritten to the old arc in a compacted form subject
00739     ///< to its modification in the arc. no modification, no overwriting.
00740 
00741     void            reset();
00742     void            set_to_last();
00743     ///< Move the current arc position in the iteration space
00744     ///< to the beginning or to the last.
00745     ///< Moving to the last might be useful if you need to iterator
00746     ///< backwards
00747 
00748     ///< void     prev();
00749     void            operator-- ();
00750     ///< Go to the previous valid arc.
00751 
00752     ///< void     next();
00753     void            operator++ ();
00754     ///< Go to the next valid arc.
00755 
00756 };
00757 
00758 
00759 
00760 ///< ///////      inline codes
00761 
00762 
00763 
00764 inline 
00765 ElementDV::ElementDV(DIREC_TYPE direc)
00766 {
00767     _direction = direc;
00768     _distance_valid = False;
00769     _min_distance = INV_DDIST;
00770     _max_distance = INV_DDIST;
00771 }
00772 
00773 inline
00774 ElementDV::ElementDV(DIREC_TYPE direc, DDIST_TYPE const_distance)
00775 {
00776     _direction = direc;
00777     _min_distance = const_distance;
00778     _max_distance = const_distance;
00779     _distance_valid = True;
00780 }
00781 
00782 inline
00783 ElementDV::ElementDV(DIREC_TYPE direc, DDIST_TYPE min, DDIST_TYPE max)
00784 {
00785     _direction = direc;
00786     _min_distance = min;
00787     _max_distance = max;
00788     _distance_valid = True;
00789 }
00790 
00791 inline
00792 ElementDV::ElementDV(const ElementDV & other)
00793 {
00794    _direction    = other._direction;
00795    _min_distance = other._min_distance;
00796    _max_distance = other._max_distance;
00797    _distance_valid   = other._distance_valid;
00798 }
00799 
00800 inline DIREC_TYPE 
00801 ElementDV::direction() const
00802 {
00803     return _direction;
00804 }
00805 
00806 inline void     
00807 ElementDV::direction(DIREC_TYPE new_direc)
00808 {
00809     _direction = new_direc;
00810 }
00811 
00812 inline Boolean
00813 ElementDV::is_distance_valid ()
00814 {
00815   ///<    return(_distance_valid);
00816   return (_min_distance != INV_DDIST && _max_distance != INV_DDIST);
00817 }
00818 
00819 inline void
00820 ElementDV::make_distance_valid ()
00821 {
00822     _distance_valid = True;
00823 }
00824 
00825 inline Boolean
00826 ElementDV::is_distance_constant ()
00827 {
00828     return (_min_distance == _max_distance);
00829 }
00830 
00831 inline DDIST_TYPE
00832 ElementDV::distance ()
00833 {
00834     ///< will not check to see if actually constant
00835     return(_min_distance);
00836 }
00837 
00838 inline void
00839 ElementDV::distance(DDIST_TYPE new_distance)
00840 {
00841     _min_distance = new_distance;
00842     _max_distance = new_distance;
00843     _distance_valid = True;
00844 }
00845 
00846 inline DDIST_TYPE
00847 ElementDV::min_distance ()
00848 {
00849     return(_min_distance);
00850 }
00851 
00852 inline void
00853 ElementDV::min_distance (DDIST_TYPE new_min_distance)
00854 {
00855     _min_distance = new_min_distance;
00856     _distance_valid = True;
00857 }
00858 
00859 inline DDIST_TYPE
00860 ElementDV::max_distance ()
00861 {
00862     return(_max_distance);
00863 }
00864 
00865 inline void
00866 ElementDV::max_distance (DDIST_TYPE new_max_distance)
00867 {
00868     _max_distance = new_max_distance;
00869     _distance_valid = True;
00870 }
00871 
00872 inline          
00873 DVfield::DVfield(DEP_DECISION dep_decided, DEP_TYPE dep_type,
00874                  const Statement & from_stmt, const Expression & from_expr,
00875                  const Statement & to_stmt, const Expression & to_expr)
00876     : _from_expr(from_expr), _to_expr(to_expr),
00877       _from_stmt(from_stmt), _to_stmt(to_stmt), _label(NULL)
00878 {
00879     _dep_decided = dep_decided;
00880     _dep_type = dep_type;
00881     _valid = 1;
00882     _references = 0;
00883 }
00884 
00885 inline
00886 DVfield::DVfield(const DVfield & other)
00887     : _from_expr(other._from_expr), _to_expr(other._to_expr),
00888       _from_stmt(other._from_stmt), _to_stmt(other._to_stmt)
00889 {
00890     _dep_decided = other._dep_decided;
00891     _dep_type = other._dep_type;
00892     _valid = other._valid;
00893     _references = other._references;
00894     if(other._label != NULL) _label = other._label->clone();
00895     else _label = NULL;
00896 }
00897 
00898 inline int      
00899 DVfield::references_inc()
00900 {
00901     return ++_references;
00902 }
00903 
00904 
00905 inline int      
00906 DVfield::references_dec()
00907 {
00908     return --_references;
00909 }
00910 
00911 inline void     
00912 DVfield::valid_on()
00913 {
00914     _valid = 1;
00915 }
00916 
00917 inline void     
00918 DVfield::valid_off()
00919 {
00920     _valid = 0;
00921 }
00922 
00923 inline DEP_DECISION 
00924 DVfield::dep_decided()
00925 {
00926     return _dep_decided;
00927 }
00928 
00929 inline void     
00930 DVfield::dep_decided(DEP_DECISION new_ddecided)
00931 {
00932     _dep_decided = new_ddecided;
00933 }
00934 
00935 inline DEP_TYPE 
00936 DVfield::dep_type()
00937 {
00938     return _dep_type;
00939 }
00940 
00941 inline void     
00942 DVfield::dep_type(DEP_TYPE new_dtype)
00943 {
00944     _dep_type = new_dtype;
00945 }
00946 
00947 inline const Expression & 
00948 DVfield::from_expr()
00949 {
00950     return _from_expr;
00951 }
00952 
00953 inline const Expression & 
00954 DVfield::to_expr()
00955 {
00956     return _to_expr;
00957 }
00958 
00959 inline const Statement & 
00960 DVfield::from_stmt()
00961 {
00962     return _from_stmt;
00963 }
00964 
00965 inline const Statement & 
00966 DVfield::to_stmt()
00967 {
00968     return _to_stmt;
00969 }
00970 
00971 inline List<ElementDV> &
00972 DVfield::dv()
00973 {
00974     return _dv;
00975 }
00976 
00977 inline void     
00978 DVfield::dv(List<ElementDV>&new_dv)
00979 {
00980     Iterator<ElementDV> iter = new_dv;
00981 
00982     for (; iter.valid(); ++iter)
00983         _dv.ins_last(new ElementDV(iter.current()));
00984 }
00985 
00986 
00987 
00988 inline
00989 ActiveArc::ActiveArc(DDgraph & ddg, Arc_type * arc,
00990                      Arc_type * prev, Arc_type * next,
00991                      const Statement & src_stmt, const Expression & src_expr)
00992     : _this_arc(arc), _prev_arc(prev), _next_arc(next),
00993       _source_expr(src_expr), _target_expr(*ddg.target_expr(arc)),
00994       _source_stmt(src_stmt), _target_stmt(*ddg.target_stmt(arc))
00995 {
00996      ddg.initialize_this_active_arc(this, arc);
00997      ///< CC 06/15/98
00998      _label = ddg.label_expr(arc);
00999      ///< CC end
01000 }
01001 
01002 inline
01003 ActiveArc::ActiveArc(const ActiveArc & other)
01004     : _source_expr(other._source_expr), _target_expr(other._target_expr),
01005       _source_stmt(other._source_stmt), _target_stmt(other._target_stmt)
01006 {
01007     _this_arc = other._this_arc;
01008     _prev_arc = other._prev_arc;
01009     _next_arc = other._next_arc;
01010     ///< CC 06/15/98
01011     _label = (other._label != NULL) ? other._label->clone() : NULL;
01012     ///< CC end
01013 }
01014 
01015 
01016 
01017 inline Arc_type *
01018 DDgraph::arcs_ptr(const Expression & src_expr)
01019 {
01020     switch (src_expr.op()) {
01021     case ID_OP:
01022         return ((IDExpr &) src_expr)._arcs;
01023 
01024     case ARRAY_REF_OP:
01025         return ((ArrayRefExpr &) src_expr)._arcs;
01026 
01027     default:
01028         return NULL;            ///< Only ID & ArrayRef Expression concerned
01029     }
01030 }
01031 
01032 inline void     
01033 DDgraph::_clear_arc(Arc_type * arc, int bytes)
01034 {
01035     while (bytes-- > 0)
01036         arc[bytes] = '\0';
01037 }
01038 
01039 inline Binary_flag 
01040 DDgraph::is_active(Arc_type * arc)
01041 {
01042     return (Binary_flag) (*(arc + _data_field_offset) & ARC_ACTIVE);
01043 }
01044 
01045 inline void     
01046 DDgraph::activate(Arc_type * arc)
01047 {
01048     *(arc + _data_field_offset) |= ARC_ACTIVE;
01049 }
01050 
01051 inline void     
01052 DDgraph::deactivate(Arc_type * arc)
01053 {
01054     *(arc + _data_field_offset) &= ~ARC_ACTIVE;
01055 }
01056 
01057 inline Statement *
01058 DDgraph::target_stmt(Arc_type * arc) const
01059 {
01060     return *(Statement **) arc;
01061 }
01062 
01063 inline Expression *
01064 DDgraph::target_expr(Arc_type * arc) const
01065 {
01066     return *(Expression **) (arc + _tgt_expr_offset);
01067 }
01068 
01069 inline Expression *
01070 DDgraph::label_expr(Arc_type * arc) const
01071 {
01072     return *(Expression **) (arc + _label_offset);
01073 }
01074 
01075 inline Arc_type *
01076 DDgraph::next_arc(Arc_type * arc) const
01077 {
01078     return *(Arc_type **) (arc + _next_arc_offset);
01079 }
01080 
01081 inline Arc_type *
01082 DDgraph::data_field(Arc_type * arc) const
01083 {
01084     return arc + _data_field_offset;
01085 }
01086 
01087 inline void     
01088 DDgraph::store_target_stmt(Arc_type * arc, const Statement & stmt)
01089 {
01090     *(Statement **) arc = (Statement *) &stmt;
01091 }
01092 
01093 inline void     
01094 DDgraph::store_target_expr(Arc_type * arc, const Expression & expr)
01095 {
01096     *(Expression **) (arc + _tgt_expr_offset) = (Expression *) &expr;
01097 }
01098 
01099 inline void     
01100 DDgraph::store_label_expr(Arc_type * arc, const Expression & expr)
01101 {
01102     *(Expression **) (arc + _label_offset) = (Expression *) &expr;
01103 }
01104 
01105 inline void     
01106 DDgraph::store_next_arc(Arc_type * arc, Arc_type * next)
01107 {
01108     *(Arc_type **) (arc + _next_arc_offset) = next;
01109 }
01110 
01111 inline DEP_DIREC
01112 DDgraph::test_dep_direction(Arc_type * arc_field, int offset)
01113 {
01114     return (DEP_DIREC) _test_1bit_field(arc_field, offset);
01115 }
01116 
01117 inline Arc_type 
01118 DDgraph::_test_1bit_field(Arc_type * arc_field, int offset)
01119 {
01120     if (offset >= A_BYTE)
01121         return arc_field[offset / A_BYTE] << offset % A_BYTE & ARC_1_BIT;
01122 
01123     return *arc_field << offset & ARC_1_BIT;
01124 }
01125 
01126 inline void     
01127 DDgraph::_skip_this_dvfield(Arc_type * &arc_field, int &position)
01128 {
01129     if ((position += DVF_DIREC) >= A_BYTE) {
01130         position -= A_BYTE;
01131         ++arc_field;
01132     }
01133 
01134     while (_DELIM != direction(arc_field, position)) {
01135         DDIST_TYPE t = min_distance(arc_field, position);
01136         t = max_distance(arc_field, position);
01137         ///< nothing else to do
01138     }
01139 }
01140 
01141 inline int      
01142 DDgraph::_count_this_dvfield(Arc_type * &arc_field, int &position)
01143 {
01144     int             bits = CONST_BITS;
01145 
01146     if ((position += DVF_DIREC) >= A_BYTE) {
01147         position -= A_BYTE;
01148         ++arc_field;
01149     }
01150 
01151     while (_DELIM != direction(arc_field, position)) {
01152         bits += (THREE_BIT + EIGHT_BIT + EIGHT_BIT);
01153         DDIST_TYPE t = min_distance(arc_field, position);
01154         t = max_distance(arc_field, position);
01155     }
01156 
01157     return bits;
01158 }
01159 
01160 
01161 inline void     
01162 DDgraph::exit(DVfield * dvf, ActiveArc * active_arc)
01163 {
01164     release(dvf, active_arc);
01165 
01166     ///< This active_arc isn't empty but check if no more iterators use this
01167 
01168     if (active_arc && !--active_arc->_references) {
01169         ///< no iterator refers to this arc
01170         write_back_arc(active_arc);     
01171     }
01172 }
01173 
01174 inline void
01175 DDgraph::hold(DVfield * dvf)
01176 {
01177     dvf->references_inc();
01178 }
01179 
01180 inline void     
01181 DDgraph::mark_dead(DVfield * dvf)
01182 {
01183     dvf->valid_off();
01184 }
01185 
01186 inline Binary_flag 
01187 DDgraph::is_alive(DVfield * dvf)
01188 {
01189     return dvf->_valid;
01190 }
01191 
01192 inline Binary_flag 
01193 DDgraph::is_shared(DVfield * dvf)
01194 {
01195     return (dvf->_references>1);
01196 }
01197 
01198 inline DVfield *
01199 DDgraph::detach(DVfield * dvf, ActiveArc * active_arc)
01200 {
01201     return active_arc->_working_dv_fields.grab(*dvf);
01202 }
01203 
01204 inline List<DVfield> *
01205 DDgraph::dvfield_list(ActiveArc * active_arc)
01206 {
01207     return &active_arc->_working_dv_fields;
01208 }
01209 
01210 
01211 
01212 inline 
01213 DDiterator::DDiterator(const Statement & from_stmt, 
01214                        const Expression & from_expr,
01215                        const Statement & to_stmt, const Expression & to_expr,
01216                        DDgraph & ddgraph)
01217     : _ddgraph(ddgraph)
01218 {
01219     _from_stmt = &from_stmt;
01220     _to_stmt = &to_stmt;
01221     _from_expr = &from_expr;
01222     _to_expr = &to_expr;
01223     _init_from = _init_to = _EXPR;
01224 
01225     _ddgraph.compute_dvf_n_arc(_current_dvf, _active_arc, _FIRST,
01226                                from_stmt, from_expr, to_stmt, to_expr);
01227 }
01228 
01229 inline          
01230 DDiterator::~DDiterator()
01231 {
01232     if (_current_dvf && _active_arc)
01233     _ddgraph.exit(_current_dvf, _active_arc);
01234 
01235     if (_init_from == _STMTS) {
01236         delete _iter_from_stmts;
01237         delete _iter_from_exprs;
01238     delete _from_stmts;
01239     }
01240 
01241     if (_init_to == _STMTS) {
01242         delete _iter_to_stmts;
01243         delete _iter_to_exprs;
01244     delete _to_stmts;
01245     }
01246 }
01247 
01248 inline Boolean  
01249 DDiterator::valid()
01250 {
01251     return (_current_dvf ? True : False);
01252 }
01253 
01254 inline Boolean  
01255 DDiterator::end()
01256 {
01257     return !valid();
01258 }
01259 
01260 inline DVfield & 
01261 DDiterator::current()
01262 {
01263     p_assert(current_valid(), "Try to access a dead object");
01264 
01265     return *_current_dvf;
01266 }
01267 
01268 inline Boolean  
01269 DDiterator::current_valid()
01270 {
01271     return ((_current_dvf && _ddgraph.is_alive(_current_dvf) ) ? True : False);
01272 }
01273 
01274 inline Boolean  
01275 DDiterator::current_invalid()
01276 {
01277     return !current_valid();
01278 }
01279 
01280 inline DVfield *
01281 DDiterator::grab()
01282 {
01283     p_assert(current_valid(), "Try to grab a dead object");
01284 
01285     _ddgraph.mark_dead(_current_dvf);
01286 
01287     DVfield * dvf = (DVfield *) _current_dvf->listable_clone();
01288 /*
01289     DVfield * dvf = new DVfield(_current_dvf->dep_decided(),
01290                 _current_dvf->dep_type(),
01291                 _current_dvf->from_stmt(),
01292                 _current_dvf->from_expr(),
01293                 _current_dvf->to_stmt(),
01294                 _current_dvf->to_expr());
01295 */
01296     Iterator<ElementDV> iter = _current_dvf->dv();
01297     for (; iter.valid(); ++iter)
01298     dvf->dv().ins_last(new ElementDV(iter.current()));
01299 
01300     return dvf;
01301 }
01302 
01303 
01304 inline void     
01305 DDiterator::del()
01306 {
01307     p_assert(current_valid(), "Try to delete a dead object");
01308 
01309     _ddgraph.mark_dead(_current_dvf);
01310 }
01311 
01312 inline void 
01313 DDiterator::modify(DVfield * other)
01314 {
01315     p_assert(current_valid(), "Try to modify a dead object");
01316 
01317     _ddgraph.mark_dead(_current_dvf);
01318     _ddgraph.dvfield_list(_active_arc)->ins_after(other, _current_dvf);
01319     _ddgraph.release(_current_dvf, _active_arc);
01320     _ddgraph.hold(other);
01321     _current_dvf = other;
01322 }
01323 
01324 
01325 
01326 ///< DVcapsule is for the routine merge_DVs() only 
01327 
01328 struct DVcapsule {
01329     DVfield * dvf;
01330     DVcapsule * next;
01331     Binary_flag alive;
01332 
01333     DVcapsule(DVfield * dvf_ptr) {
01334     dvf = dvf_ptr;
01335     next = 0;
01336     alive = 1;  ///< Initially alive
01337     }
01338 
01339     Binary_flag is_alive() {
01340     return alive;
01341     }
01342 
01343     void mark_dead() {
01344     alive = 0;
01345     }
01346 };
01347 
01348 ///< Perform merge operation on all the DVfields in 'dvfs'.
01349 ///< Ex: (<,>) + (=,>) --> (<=,>) where the values of the other fields
01350 ///< in both the DVfields are the same.
01351 ///< The original list of 'dvfs' will be changed to have the merged list
01352 
01353 void     merge_DVs(List<DVfield> & dvfs);
01354 
01355 ///< _dispose_capsules() recursively deletes all the DVcapsules hanging to the
01356 ///< corresponding Slots
01357 
01358 void _dispose_capsules(DVcapsule *& dvc);
01359 
01360 ///< With (<=, *) and (=, <>), the second is the proper subdirection..
01361 ///< Nonproper subdirection will also be removed; that means the same
01362 ///< directions are to be removed such as (<, >=) & (<, >=).
01363 
01364 void _remove_all_subdirections(DVcapsule ** Slots, int levels);
01365 
01366 ///< Find the parent node, if any, for 'dvc' and some DVcapsule in 'list', and
01367 ///< create the new DVcapsule for that and add the the parent slot, 'Slot'.
01368 ///< Return the pointer to the capsule in 'list' if found.
01369 ///< Return 0 if there is not such a DVcapsule in 'list'.
01370 
01371 DVcapsule * _create_parent(DVcapsule *& Slot,DVcapsule * dvc,DVcapsule * list);
01372 
01373 ///< _is_parent_for() _is_subdirecion() and _is_same() are used
01374 ///< in merge_DVs() only.   The dimension of two DVs must be the same...
01375 ///< otherwise, false will be returned.
01376 
01377 Binary_flag _is_parent_for(Iterator<ElementDV> & citer,
01378                Iterator<ElementDV> & piter); 
01379 
01380 inline Binary_flag _is_same(Iterator<ElementDV> & iter1,
01381                   Iterator<ElementDV> & iter2);
01382 
01383 Binary_flag _is_subdirecion(Iterator<ElementDV> & iter1,
01384                 Iterator<ElementDV> & iter2);
01385 
01386 ///<///////////////////// Implementation 
01387 inline Binary_flag _is_same(Iterator<ElementDV> & iter1,
01388                   Iterator<ElementDV> & iter2)
01389 {
01390     iter1.reset();
01391     iter2.reset();
01392 
01393     for (; iter1.valid() && iter2.valid(); ++iter1, ++iter2)
01394        if (iter1.current().direction() != iter2.current().direction())
01395           return 0;
01396 
01397     if (iter1.end() && iter2.end())
01398        return 1;
01399     else
01400        return 0;
01401 }
01402 
01403 void
01404 ddtests_main(Program&, DDtests_Seq, Binary_flag);
01405 
01406 #endif
 © 1995-2005 University of Illinois, Urbana-Champaign. All rights reserved.  Fri Mar 25 23:05:44 2005