dataflow.h

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2005-2006, Mike Van Emmerik
00003  *
00004  * See the file "LICENSE.TERMS" for information on usage and
00005  * redistribution of this file, and for a DISCLAIMER OF ALL
00006  * WARRANTIES.
00007  *
00008  */
00009 
00010 /*==============================================================================
00011  * FILE:       dataflow.h
00012  * OVERVIEW:   Interface for SSA based data flow analysis
00013  *============================================================================*/
00014 
00015 /*
00016  * $Revision: 1.47 $    // 1.39.2.19
00017  *
00018  * 15 Mar 05 - Mike: Separated from cfg.h
00019  */
00020 
00021 #ifndef _DATAFLOW_H_
00022 #define _DATAFLOW_H_
00023 
00024 #include <vector>
00025 #include <map>
00026 #include <set>
00027 #include <stack>
00028 
00029 #include "exphelp.h"        // For lessExpStar, etc
00030 #include "managed.h"        // For LocationSet
00031 #include "boomerang.h"      // For USE_DOMINANCE_NUMS etc
00032 
00033 class Cfg;
00034 class BasicBlock;
00035 class Exp;
00036 class RefExp;
00037 class Statement;
00038 class UserProc;
00039 class PhiAssign;
00040 class Type;
00041 
00042 typedef BasicBlock* PBB;
00043 
00044 class DataFlow {
00045     /******************** Dominance Frontier Data *******************/
00046 
00047         /* These first two are not from Appel; they map PBBs to indices */
00048         std::vector<PBB> BBs;               // Pointers to BBs from indices
00049         std::map<PBB, int> indices;         // Indices from pointers to BBs
00050         /*
00051          * Calculating the dominance frontier
00052          */
00053         // If there is a path from a to b in the cfg, then a is an ancestor of b
00054         // if dfnum[a] < denum[b]
00055         std::vector<int> dfnum;             // Number set in depth first search
00056         std::vector<int> semi;              // Semi dominators
00057         std::vector<int> ancestor;          // Defines the forest that becomes the spanning tree
00058         std::vector<int> idom;              // Immediate dominator
00059         std::vector<int> samedom;           // ? To do with deferring
00060         std::vector<int> vertex;            // ?
00061         std::vector<int> parent;            // Parent in the dominator tree?
00062         std::vector<int> best;              // Improves ancestorWithLowestSemi
00063         std::vector<std::set<int> > bucket; // Deferred calculation?
00064         int         N;                      // Current node number in algorithm
00065         std::vector<std::set<int> > DF;     // The dominance frontiers
00066 
00067         /*
00068          * Inserting phi-functions
00069          */
00070         // Array of sets of locations defined in BB n
00071         std::vector<std::set<Exp*, lessExpStar> > A_orig;
00072         // Map from expression to set of block numbers
00073         std::map<Exp*, std::set<int>, lessExpStar > defsites;
00074         // Set of block numbers defining all variables
00075         std::set<int> defallsites;
00076         // Array of sets of BBs needing phis
00077         std::map<Exp*, std::set<int>, lessExpStar> A_phi;
00078         // A Boomerang requirement: Statements defining particular subscripted locations
00079         std::map<Exp*, Statement*, lessExpStar> defStmts;
00080 
00081         /*
00082          * Renaming variables
00083          */
00084         // The stack which remembers the last definition of an expression.
00085         // A map from expression (Exp*) to a stack of (pointers to) Statements
00086         std::map<Exp*, std::stack<Statement*>, lessExpStar> Stacks;
00087 
00088         // Initially false, meaning that locals and parameters are not renamed and hence not propagated.
00089         // When true, locals and parameters can be renamed if their address does not escape the local procedure.
00090         // See Mike's thesis for details.
00091         bool        renameLocalsAndParams;
00092 
00093 public:
00094                     DataFlow() : renameLocalsAndParams(false) {}        // Constructor
00095         /*
00096          * Dominance frontier and SSA code
00097          */
00098         void        DFS(int p, int n);
00099         void        dominators(Cfg* cfg);
00100         int         ancestorWithLowestSemi(int v);
00101         void        Link(int p, int n);
00102         void        computeDF(int n);
00103         // Place phi functions. Return true if any change
00104         bool        placePhiFunctions(UserProc* proc);
00105         // Rename variables in basicblock n. Return true if any change made
00106         bool        renameBlockVars(UserProc* proc, int n, bool clearStacks = false);
00107         bool        doesDominate(int n, int w);
00108         void        setRenameLocalsParams(bool b) {renameLocalsAndParams = b;}
00109         bool        canRenameLocalsParams() {return renameLocalsAndParams;}
00110         bool        canRename(Exp* e, UserProc* proc);
00111         void        convertImplicits(Cfg* cfg);
00112         // Find the locations used by a live, dominating phi-function. Also removes dead phi-funcions
00113         void        findLiveAtDomPhi(int n, LocationSet& usedByDomPhi, LocationSet& usedByDomPhi0,
00114                         std::map<Exp*, PhiAssign*, lessExpStar>& defdByPhi);
00115 #if     USE_DOMINANCE_NUMS
00116         void        setDominanceNums(int n, int& currNum);      // Set the dominance statement number
00117 #endif
00118         void        clearA_phi() {A_phi.clear();}
00119 
00120         // For testing:
00121         int         pbbToNode(PBB bb) {return indices[bb];}
00122         std::set<int>& getDF(int node) {return DF[node];}
00123         PBB         nodeToBB(int node) {return BBs[node];} 
00124         int         getIdom(int node) {return idom[node];}
00125         int         getSemi(int node) {return semi[node];}
00126         std::set<int>& getA_phi(Exp* e) {return A_phi[e];}
00127 
00128         // For debugging:
00129         void        dumpStacks();
00130         void        dumpDefsites();
00131         void        dumpA_orig();
00132         void        dumpA_phi();
00133 
00134 };
00135 
00136 /*  *   *   *   *   *   *\
00137 *                        *
00138 *   C o l l e c t o r s  *
00139 *                        *
00140 \*  *   *   *   *   *   */
00141 
00142 /**
00143  * DefCollector class. This class collects all definitions that reach the statement that contains this collector.
00144  */
00145 class DefCollector {
00146         /*
00147          * True if initialised. When not initialised, callees should not subscript parameters inserted into the
00148          * associated CallStatement
00149          */
00150         bool        initialised;
00151         /**
00152          * The set of definitions.
00153          */
00154         AssignSet   defs;
00155 public:
00156         /**
00157          * Constructor
00158          */
00159                     DefCollector() : initialised(false) {}
00160 
00161         /**
00162          * makeCloneOf(): clone the given Collector into this one
00163          */
00164         void        makeCloneOf(DefCollector& other);
00165 
00166         /*
00167          * Return true if initialised
00168          */
00169         bool        isInitialised() {return initialised;}
00170 
00171         /*
00172          * Clear the location set
00173          */
00174         void        clear() {defs.clear(); initialised = false;}
00175 
00176         /*
00177          * Insert a new member (make sure none exists yet)
00178          */
00179         void        insert(Assign* a);
00180         /*
00181          * Print the collected locations to stream os
00182          */
00183         void        print(std::ostream& os, bool html = false);
00184 
00185         /*
00186          * Print to string or stdout (for debugging)
00187          */
00188         char*       prints();
00189         void        dump();
00190 Assign* dumpAddrOfFourth();
00191 
00192         /*
00193          * begin() and end() so we can iterate through the locations
00194          */
00195         typedef AssignSet::iterator iterator;
00196         iterator    begin() {return defs.begin();}
00197         iterator    end()    {return defs.end();}
00198         bool        existsOnLeft(Exp* e) {return defs.definesLoc(e);}
00199 
00200         /*
00201          * Update the definitions with the current set of reaching definitions
00202          * proc is the enclosing procedure
00203          */
00204         void        updateDefs(std::map<Exp*, std::stack<Statement*>, lessExpStar>& Stacks, UserProc* proc);
00205 
00206         /**
00207          * Find the definition for a location. If not found, return NULL
00208          */
00209         Exp*        findDefFor(Exp* e);
00210 
00211         /**
00212          * Search and replace all occurrences
00213          */
00214         void        searchReplaceAll(Exp* from, Exp* to, bool& change);
00215 };      // class DefCollector
00216 
00217 /**
00218  * UseCollector class. This class collects all uses (live variables) that will be defined by the statement that 
00219  * contains this collector (or the UserProc that contains it).
00220  * Typically the entries are not subscripted, like parameters or locations on the LHS of assignments
00221  */
00222 class UseCollector {
00223         /*
00224          * True if initialised. When not initialised, callees should not subscript parameters inserted into the
00225          * associated CallStatement
00226          */
00227         bool        initialised;
00228         /**
00229          * The set of locations. Use lessExpStar to compare properly
00230          */
00231         LocationSet locs;
00232 public:
00233         /**
00234          * Constructor
00235          */
00236                     UseCollector() : initialised(false) {}
00237 
00238         /**
00239          * makeCloneOf(): clone the given Collector into this one
00240          */
00241         void        makeCloneOf(UseCollector& other);
00242 
00243         /*
00244          * Return true if initialised
00245          */
00246         bool        isInitialised() {return initialised;}
00247 
00248         /*
00249          * Clear the location set
00250          */
00251         void        clear() {locs.clear(); initialised = false;}
00252 
00253         /*
00254          * Insert a new member
00255          */
00256         void        insert(Exp* e) {locs.insert(e);}
00257         /*
00258          * Print the collected locations to stream os
00259          */
00260         void        print(std::ostream& os, bool html = false);
00261 
00262         /*
00263          * Print to string or stderr (for debugging)
00264          */
00265         char*       prints();
00266         void        dump();
00267 
00268         /*
00269          * begin() and end() so we can iterate through the locations
00270          */
00271         typedef LocationSet::iterator iterator;
00272         iterator    begin() {return locs.begin();}
00273         iterator    end()    {return locs.end();}
00274         bool        exists(Exp* e)  {return locs.exists(e);}    // True if e is in the collection
00275         LocationSet& getLocSet() {return locs;}
00276 public:
00277         /*
00278          * Add a new use from Statement u
00279          */
00280         void        updateLocs(Statement* u);
00281         void        remove(Exp* loc) {                          // Remove the given location
00282                         locs.remove(loc);
00283                     }
00284         void        remove(iterator it) {                       // Remove the current location
00285                         locs.remove(it);
00286                     }
00287         void        fromSSAform(UserProc* proc, Statement* def);    // Translate out of SSA form
00288         bool        operator==(UseCollector& other);
00289 };      // class UseCollector
00290 
00291 
00292 #endif  // _DATAFLOW_H_
00293 

Generated on Tue Sep 19 21:18:15 2006 for Boomerang by  doxygen 1.4.6