dataflow.cpp

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2005, 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.cpp
00012  * OVERVIEW:   Implementation of the DataFlow class
00013  *============================================================================*/
00014 
00015 /*
00016  * $Revision: 1.65 $    // 1.43.2.24
00017  * 15 Mar 05 - Mike: Separated from cfg.cpp
00018  */
00019 
00020 #include <sstream>
00021 
00022 #include "dataflow.h"
00023 #include "cfg.h"
00024 #include "proc.h"
00025 #include "exp.h"
00026 #include "boomerang.h"
00027 #include "visitor.h"
00028 #include "log.h"
00029 #include "frontend.h"
00030 
00031 extern char debug_buffer[];      // For prints functions
00032 
00033 
00034 /*
00035  * Dominator frontier code largely as per Appel 2002 ("Modern Compiler Implementation in Java")
00036  */
00037 
00038 void DataFlow::DFS(int p, int n) {
00039     if (dfnum[n] == 0) {
00040         dfnum[n] = N; vertex[N] = n; parent[n] = p;
00041         N++;
00042         // For each successor w of n
00043         PBB bb = BBs[n];
00044         std::vector<PBB>& outEdges = bb->getOutEdges();
00045         std::vector<PBB>::iterator oo;
00046         for (oo = outEdges.begin(); oo != outEdges.end(); oo++) {
00047             DFS(n, indices[*oo]);
00048         }
00049     }
00050 }
00051 
00052 // Essentially Algorithm 19.9 of Appel's "modern compiler implementation in Java" 2nd ed 2002
00053 void DataFlow::dominators(Cfg* cfg) {
00054     PBB r = cfg->getEntryBB();
00055     unsigned numBB = cfg->getNumBBs();
00056     BBs.resize(numBB, (PBB)-1);
00057     N = 0; BBs[0] = r;
00058     indices.clear();            // In case restart decompilation due to switch statements
00059     indices[r] = 0;
00060     // Initialise to "none"
00061     dfnum.resize(numBB, 0);
00062     semi.resize(numBB, -1);
00063     ancestor.resize(numBB, -1);
00064     idom.resize(numBB, -1);
00065     samedom.resize(numBB, -1);
00066     vertex.resize(numBB, -1);
00067     parent.resize(numBB, -1);
00068     best.resize(numBB, -1);
00069     bucket.resize(numBB);
00070     DF.resize(numBB);
00071     // Set up the BBs and indices vectors. Do this here because sometimes a BB can be unreachable (so relying on
00072     // in-edges doesn't work)
00073     std::list<PBB>::iterator ii;
00074     int idx = 1;
00075     for (ii = cfg->begin(); ii != cfg->end(); ii++) {
00076         PBB bb = *ii;
00077         if (bb != r) {     // Entry BB r already done
00078             indices[bb] = idx;
00079             BBs[idx++] = bb;
00080         }
00081     }
00082     DFS(-1, 0);
00083     int i;
00084     for (i=N-1; i >= 1; i--) {
00085         int n = vertex[i]; int p = parent[n]; int s = p;
00086         /* These lines calculate the semi-dominator of n, based on the Semidominator Theorem */
00087         // for each predecessor v of n
00088         PBB bb = BBs[n];
00089         std::vector<PBB>& inEdges = bb->getInEdges();
00090         std::vector<PBB>::iterator it;
00091         for (it = inEdges.begin(); it != inEdges.end(); it++) {
00092             if (indices.find(*it) == indices.end()) {
00093                 std::cerr << "BB not in indices: "; (*it)->print(std::cerr);
00094                 assert(false);
00095             }
00096             int v = indices[*it];
00097             int sdash;
00098             if (dfnum[v] <= dfnum[n])
00099                 sdash = v;
00100             else sdash = semi[ancestorWithLowestSemi(v)];
00101             if (dfnum[sdash] < dfnum[s])
00102                 s = sdash;
00103         }
00104         semi[n] = s;
00105         /* Calculation of n's dominator is deferred until the path from s to n has been linked into the forest */
00106         bucket[s].insert(n);
00107         Link(p, n);
00108         // for each v in bucket[p]
00109         std::set<int>::iterator jj;
00110         for (jj=bucket[p].begin(); jj != bucket[p].end(); jj++) {
00111             int v = *jj;
00112             /* Now that the path from p to v has been linked into the spanning forest, these lines calculate the
00113                 dominator of v, based on the first clause of the Dominator Theorem, or else defer the calculation until
00114                 y's dominator is known. */
00115             int y = ancestorWithLowestSemi(v);
00116             if (semi[y] == semi[v])
00117                 idom[v] = p;                // Success!
00118             else samedom[v] = y;            // Defer
00119         }
00120         bucket[p].clear();
00121     }
00122     for (i=1; i < N-1; i++) {
00123         /* Now all the deferred dominator calculations, based on the second clause of the Dominator Theorem, are
00124             performed. */
00125         int n = vertex[i];
00126         if (samedom[n] != -1) {
00127             idom[n] = idom[samedom[n]];     // Deferred success!
00128         }
00129     }
00130     computeDF(0);                           // Finally, compute the dominance frontiers
00131 }
00132 
00133 // Basically algorithm 19.10b of Appel 2002 (uses path compression for O(log N) amortised time per operation
00134 // (overall O(N log N))
00135 int DataFlow::ancestorWithLowestSemi(int v) {
00136     int a = ancestor[v];
00137     if (ancestor[a] != -1) {
00138         int b = ancestorWithLowestSemi(a);
00139         ancestor[v] = ancestor[a];
00140         if (dfnum[semi[b]] < dfnum[semi[best[v]]])
00141             best[v] = b;
00142     }
00143     return best[v];
00144 }
00145 
00146 void DataFlow::Link(int p, int n) {
00147     ancestor[n] = p; best[n] = n;
00148 }
00149 
00150 // Return true if n dominates w
00151 bool DataFlow::doesDominate(int n, int w) {
00152     while (idom[w] != -1) {
00153         if (idom[w] == n)
00154             return true;
00155         w = idom[w];     // Move up the dominator tree
00156     }
00157     return false;
00158 }
00159 
00160 void DataFlow::computeDF(int n) {
00161     std::set<int> S;
00162     /* THis loop computes DF_local[n] */
00163     // for each node y in succ(n)
00164     PBB bb = BBs[n];
00165     std::vector<PBB>& outEdges = bb->getOutEdges();
00166     std::vector<PBB>::iterator it;
00167     for (it = outEdges.begin(); it != outEdges.end(); it++) {
00168         int y = indices[*it];
00169         if (idom[y] != n)
00170             S.insert(y);
00171     }
00172     // for each child c of n in the dominator tree
00173     // Note: this is a linear search!
00174     int sz = idom.size();               // ? Was ancestor.size()
00175     for (int c = 0; c < sz; ++c) {
00176         if (idom[c] != n) continue;
00177         computeDF(c);
00178         /* This loop computes DF_up[c] */
00179         // for each element w of DF[c]
00180         std::set<int>& s = DF[c];
00181         std::set<int>::iterator ww;
00182         for (ww = s.begin(); ww != s.end(); ww++) {
00183             int w = *ww;
00184             // if n does not dominate w, or if n = w
00185             if (n == w || !doesDominate(n, w)) {
00186                 S.insert(w);
00187             }
00188         }
00189     }
00190     DF[n] = S;
00191 }   // end computeDF
00192 
00193 
00194 bool DataFlow::canRename(Exp* e, UserProc* proc) {
00195     if (e->isSubscript()) e = ((RefExp*)e)->getSubExp1();   // Look inside refs
00196     if (e->isRegOf()) return true;      // Always rename registers
00197     if (e->isTemp()) return true;       // Always rename temps (always want to propagate away)
00198     if (e->isFlags()) return true;      // Always rename flags
00199     if (e->isMainFlag()) return true;   // Always rename individual flags like %CF
00200     if (e->isLocal()) return true;      // Rename hard locals in the post fromSSA pass
00201     if (!e->isMemOf()) return false;    // Can't rename %pc or other junk
00202     // I used to check here if there was a symbol for the memory expression, and if so allow it to be renamed. However,
00203     // even named locals and parameters could have their addresses escape the local function, so we need another test
00204     // anyway. So locals and parameters should not be renamed (and hence propagated) until escape analysis is done (and
00205     // hence renaleLocalsAndParams is set)
00206     // Besides,  before we have types and references, it is not easy to find a type for the location, so we can't tell
00207     // if e.g. m[esp{-}+12] is evnp or a separate local.
00208     // It certainly needs to have the local/parameter pattern
00209     if (!proc->isLocalOrParamPattern(e)) return false;
00210     // e is a local or parameter; allow it to be propagated iff we've done escape analysis and the address has not
00211     return renameLocalsAndParams && !proc->isAddressEscapedVar(e);  // escaped
00212 }
00213 
00214 // For debugging
00215 void DataFlow::dumpA_phi() {
00216     std::map<Exp*, std::set<int>, lessExpStar>::iterator zz;
00217     std::cerr << "A_phi:\n";
00218     for (zz = A_phi.begin(); zz != A_phi.end(); ++zz) {
00219         std::cerr << zz->first << " -> ";
00220         std::set<int>& si = zz->second;
00221         std::set<int>::iterator qq;
00222         for (qq = si.begin(); qq != si.end(); ++qq)
00223             std::cerr << *qq << ", ";
00224         std::cerr << "\n";
00225     }
00226     std::cerr << "end A_phi\n";
00227 }
00228 
00229 
00230 bool DataFlow::placePhiFunctions(UserProc* proc) {
00231     // First free some memory no longer needed
00232     dfnum.resize(0);
00233     semi.resize(0);
00234     ancestor.resize(0);
00235     samedom.resize(0);
00236     vertex.resize(0);
00237     parent.resize(0);
00238     best.resize(0);
00239     bucket.resize(0);
00240     defsites.clear();           // Clear defsites map,
00241     defallsites.clear();
00242     A_orig.clear();             // and A_orig,
00243     defStmts.clear();           // and the map from variable to defining Stmt 
00244 
00245     bool change = false;
00246 
00247     // Set the sizes of needed vectors
00248     unsigned numBB = indices.size();
00249     Cfg* cfg = proc->getCFG();
00250     assert(numBB == cfg->getNumBBs());
00251     A_orig.resize(numBB);
00252 
00253     // We need to create A_orig[n] for all n, the array of sets of locations defined at BB n
00254     // Recreate each call because propagation and other changes make old data invalid
00255     unsigned n;
00256     for (n=0; n < numBB; n++) {
00257         BasicBlock::rtlit rit; StatementList::iterator sit;
00258         PBB bb = BBs[n];
00259         for (Statement* s = bb->getFirstStmt(rit, sit); s; s = bb->getNextStmt(rit, sit)) {
00260             LocationSet ls;
00261             LocationSet::iterator it;
00262             s->getDefinitions(ls);
00263             if (s->isCall() && ((CallStatement*)s)->isChildless())      // If this is a childless call
00264                 defallsites.insert(n);                                  // then this block defines every variable
00265             for (it = ls.begin(); it != ls.end(); it++) {
00266                 if (canRename(*it, proc)) {
00267                     A_orig[n].insert((*it)->clone());
00268                     defStmts[*it] = s;
00269                 }
00270             }
00271         }
00272     }
00273 
00274     // For each node n
00275     for (n=0; n < numBB; n++) {
00276         // For each variable a in A_orig[n]
00277         std::set<Exp*, lessExpStar>& s = A_orig[n];
00278         std::set<Exp*, lessExpStar>::iterator aa;
00279         for (aa = s.begin(); aa != s.end(); aa++) {
00280             Exp* a = *aa;
00281             defsites[a].insert(n);
00282         }
00283     }
00284 
00285     // For each variable a (in defsites, i.e. defined anywhere)
00286     std::map<Exp*, std::set<int>, lessExpStar>::iterator mm;
00287     for (mm = defsites.begin(); mm != defsites.end(); mm++) {
00288         Exp* a = (*mm).first;               // *mm is pair<Exp*, set<int>>
00289 
00290         // Special processing for define-alls
00291         // for each n in defallsites
00292         std::set<int>::iterator da;
00293         for (da = defallsites.begin(); da != defallsites.end(); ++da)
00294             defsites[a].insert(*da);
00295 
00296         // W <- defsites[a];
00297         std::set<int> W = defsites[a];      // set copy
00298         // While W not empty
00299         while (W.size()) {
00300             // Remove some node n from W
00301             int n = *W.begin();             // Copy first element
00302             W.erase(W.begin());             // Remove first element
00303             // for each y in DF[n]
00304             std::set<int>::iterator yy;
00305             std::set<int>& DFn = DF[n];
00306             for (yy = DFn.begin(); yy != DFn.end(); yy++) {
00307                 int y = *yy;
00308                 // if y not element of A_phi[a]
00309                 std::set<int>& s = A_phi[a];
00310                 if (s.find(y) == s.end()) {
00311                     // Insert trivial phi function for a at top of block y: a := phi()
00312                     change = true;
00313                     Statement* as = new PhiAssign(a->clone());
00314                     PBB Ybb = BBs[y];
00315                     Ybb->prependStmt(as, proc);
00316                     // A_phi[a] <- A_phi[a] U {y}
00317                     s.insert(y);
00318                     // if a !elementof A_orig[y]
00319                     if (A_orig[y].find(a) == A_orig[y].end()) {
00320                         // W <- W U {y}
00321                         W.insert(y);
00322                     }
00323                 }
00324             }
00325         }
00326     }
00327     return change;
00328 }       // end placePhiFunctions
00329 
00330 
00331 
00332 static Exp* defineAll = new Terminal(opDefineAll);      // An expression representing <all>
00333 
00334 // There is an entry in stacks[defineAll] that represents the latest definition from a define-all source. It is needed
00335 // for variables that don't have a definition as yet (i.e. stacks[x].empty() is true). As soon as a real definition to
00336 // x appears, stacks[defineAll] does not apply for variable x. This is needed to get correct operation of the use
00337 // collectors in calls.
00338 
00339 // Care with the Stacks object (a map from expression to stack); using Stacks[q].empty() can needlessly insert an empty
00340 // stack
00341 #define STACKS_EMPTY(q) (Stacks.find(q) == Stacks.end() || Stacks[q].empty())
00342 
00343 // Subscript dataflow variables
00344 static int progress = 0;
00345 bool DataFlow::renameBlockVars(UserProc* proc, int n, bool clearStacks /* = false */ ) {
00346     if (++progress > 200) {
00347         std::cerr << 'r' << std::flush;
00348         progress = 0;
00349     }
00350     bool changed = false;
00351 
00352     // Need to clear the Stacks of old, renamed locations like m[esp-4] (these will be deleted, and will cause compare
00353     // failures in the Stacks, so it can't be correctly ordered and hence balanced etc, and will lead to segfaults)
00354     if (clearStacks) Stacks.clear();
00355 
00356     // For each statement S in block n
00357     BasicBlock::rtlit rit; StatementList::iterator sit;
00358     PBB bb = BBs[n];
00359     Statement* S;
00360     for (S = bb->getFirstStmt(rit, sit); S; S = bb->getNextStmt(rit, sit)) {
00361         // if S is not a phi function (per Appel)
00362         /* if (!S->isPhi()) */ {
00363             // For each use of some variable x in S (not just assignments)
00364             LocationSet locs;
00365             if (S->isPhi()) {
00366                 PhiAssign* pa = (PhiAssign*)S;
00367                 Exp* phiLeft = pa->getLeft();
00368                 if (phiLeft->isMemOf() || phiLeft->isRegOf())
00369                     phiLeft->getSubExp1()->addUsedLocs(locs);
00370                 // A phi statement may use a location defined in a childless call, in which case its use collector
00371                 // needs updating
00372                 PhiAssign::iterator pp;
00373                 for (pp = pa->begin(); pp != pa->end(); ++pp) {
00374                     Statement* def = pp->def;
00375                     if (def && def->isCall())
00376                         ((CallStatement*)def)->useBeforeDefine(phiLeft->clone());
00377                 }
00378             }
00379             else {              // Not a phi assignment
00380                 S->addUsedLocs(locs);
00381             }
00382             LocationSet::iterator xx;
00383             for (xx = locs.begin(); xx != locs.end(); xx++) {
00384                 Exp* x = *xx;
00385                 // Don't rename memOfs that are not renamable according to the current policy
00386                 if (!canRename(x, proc)) continue;
00387                 Statement* def = NULL;
00388                 if (x->isSubscript()) {                 // Already subscripted?
00389                     // No renaming required, but redo the usage analysis, in case this is a new return, and also because
00390                     // we may have just removed all call livenesses
00391                     // Update use information in calls, and in the proc (for parameters)
00392                     Exp* base = ((RefExp*)x)->getSubExp1();
00393                     def = ((RefExp*)x)->getDef();
00394                     if (def && def->isCall()) {
00395                         // Calls have UseCollectors for locations that are used before definition at the call
00396                         ((CallStatement*)def)->useBeforeDefine(base->clone());
00397                         continue;
00398                     }
00399                     // Update use collector in the proc (for parameters)
00400                     if (def == NULL)
00401                         proc->useBeforeDefine(base->clone());
00402                     continue;                           // Don't re-rename the renamed variable
00403                 }
00404                 // Else x is not subscripted yet
00405                 if (STACKS_EMPTY(x)) {
00406                     if (!Stacks[defineAll].empty())
00407                         def = Stacks[defineAll].top();
00408                     else {
00409                         // If the both stacks are empty, use a NULL definition. This will be changed into a pointer
00410                         // to an implicit definition at the start of type analysis, but not until all the m[...]
00411                         // have stopped changing their expressions (complicates implicit assignments considerably).
00412                         def = NULL;
00413                         // Update the collector at the start of the UserProc
00414                         proc->useBeforeDefine(x->clone());
00415                     }
00416                 }
00417                 else
00418                     def = Stacks[x].top();
00419                 if (def && def->isCall())
00420                     // Calls have UseCollectors for locations that are used before definition at the call
00421                     ((CallStatement*)def)->useBeforeDefine(x->clone());
00422                 // Replace the use of x with x{def} in S
00423                 changed = true;
00424                 if (S->isPhi()) {
00425                     Exp* phiLeft = ((PhiAssign*)S)->getLeft();
00426                     phiLeft->setSubExp1(phiLeft->getSubExp1()->expSubscriptVar(x, def /*, this*/));
00427                 } else {
00428                     S->subscriptVar(x, def /*, this */);
00429                 }
00430             }
00431         }
00432 
00433         // MVE: Check for Call and Return Statements; these have DefCollector objects that need to be updated
00434         // Do before the below, so CallStatements have not yet processed their defines
00435         if (S->isCall() || S->isReturn()) {
00436             DefCollector* col;
00437             if (S->isCall())
00438                 col = ((CallStatement*)S)->getDefCollector();
00439             else
00440                 col = ((ReturnStatement*)S)->getCollector();
00441             col->updateDefs(Stacks, proc);
00442         }
00443 
00444         // For each definition of some variable a in S
00445         LocationSet defs;
00446         S->getDefinitions(defs);
00447         LocationSet::iterator dd;
00448         for (dd = defs.begin(); dd != defs.end(); dd++) {
00449             Exp* a = *dd;
00450             // Don't consider a if it cannot be renamed
00451             bool suitable = canRename(a, proc);
00452             if (suitable) {
00453                 // Push i onto Stacks[a]
00454                 // Note: we clone a because otherwise it could be an expression that gets deleted through various
00455                 // modifications. This is necessary because we do several passes of this algorithm to sort out the
00456                 // memory expressions
00457                 Stacks[a->clone()].push(S);
00458                 // Replace definition of a with definition of a_i in S (we don't do this)
00459             }
00460             // FIXME: MVE: do we need this awful hack?
00461             if (a->getOper() == opLocal) {
00462                 Exp *a1 = S->getProc()->expFromSymbol(((Const*)a->getSubExp1())->getStr());
00463                 assert(a1);
00464                 a = a1;
00465                 // Stacks already has a definition for a (as just the bare local)
00466                 if (suitable) {
00467                     Stacks[a->clone()].push(S);
00468                 }
00469             }
00470         }
00471         // Special processing for define-alls (presently, only childless calls).
00472 // But note that only everythings at the current memory level are defined!
00473         if (S->isCall() && ((CallStatement*)S)->isChildless() && !Boomerang::get()->assumeABI) {
00474             // S is a childless call (and we're not assuming ABI compliance)
00475             Stacks[defineAll];                                      // Ensure that there is an entry for defineAll
00476             std::map<Exp*, std::stack<Statement*>, lessExpStar>::iterator dd;
00477             for (dd = Stacks.begin(); dd != Stacks.end(); ++dd) {
00478 // if (dd->first->isMemDepth(memDepth))
00479                     dd->second.push(S);                             // Add a definition for all vars
00480             }
00481         }
00482     }
00483 
00484     // For each successor Y of block n
00485     std::vector<PBB>& outEdges = bb->getOutEdges();
00486     unsigned numSucc = outEdges.size();
00487     for (unsigned succ = 0; succ < numSucc; succ++) {
00488         PBB Ybb = outEdges[succ];
00489         // Suppose n is the jth predecessor of Y
00490         int j = Ybb->whichPred(bb);
00491         // For each phi-function in Y
00492         Statement* S;
00493         for (S = Ybb->getFirstStmt(rit, sit); S; S = Ybb->getNextStmt(rit, sit)) {
00494             PhiAssign* pa = dynamic_cast<PhiAssign*>(S);
00495             // if S is not a phi function, then quit the loop (no more phi's)
00496             // Wrong: do not quit the loop: there's an optimisation that turns a PhiAssign into an ordinary Assign.
00497             // So continue, not break.
00498             if (!pa) continue;
00499             // Suppose the jth operand of the phi is a
00500             // For now, just get the LHS
00501             Exp* a = pa->getLeft();
00502             // Only consider variables that can be renamed
00503             if (!canRename(a, proc)) continue;
00504             Statement* def;
00505             if (STACKS_EMPTY(a))
00506                 def = NULL;             // No reaching definition
00507             else
00508                 def = Stacks[a].top();
00509             // "Replace jth operand with a_i"
00510             pa->putAt(j, def, a);
00511         }
00512     }
00513 
00514     // For each child X of n
00515     // Note: linear search!
00516     unsigned numBB = proc->getCFG()->getNumBBs();
00517     for (unsigned X=0; X < numBB; X++) {
00518         if (idom[X] == n)
00519             renameBlockVars(proc, X);
00520     }
00521 
00522     // For each statement S in block n
00523     // NOTE: Because of the need to pop childless calls from the Stacks, it is important in my algorithm to process the
00524     // statments in the BB *backwards*. (It is not important in Appel's algorithm, since he always pushes a definition
00525     // for every variable defined on the Stacks).
00526     BasicBlock::rtlrit rrit; StatementList::reverse_iterator srit;
00527     for (S = bb->getLastStmt(rrit, srit); S; S = bb->getPrevStmt(rrit, srit)) {
00528         // For each definition of some variable a in S
00529         LocationSet defs;
00530         S->getDefinitions(defs);
00531         LocationSet::iterator dd;
00532         for (dd = defs.begin(); dd != defs.end(); dd++) {
00533             if (canRename(*dd, proc)) {
00534                 // if ((*dd)->getMemDepth() == memDepth)
00535                 std::map<Exp*, std::stack<Statement*>, lessExpStar>::iterator ss = Stacks.find(*dd);
00536                 if (ss == Stacks.end()) {
00537                     std::cerr << "Tried to pop " << *dd << " from Stacks; does not exist\n";
00538                     assert(0);
00539                 }
00540                     ss->second.pop();
00541             }
00542         }
00543         // Pop all defs due to childless calls
00544         if (S->isCall() && ((CallStatement*)S)->isChildless()) {
00545             std::map<Exp*, std::stack<Statement*>, lessExpStar>::iterator sss;
00546             for (sss = Stacks.begin(); sss != Stacks.end(); ++sss) {
00547                 if (!sss->second.empty() && sss->second.top() == S) {
00548                     sss->second.pop();
00549                 }
00550             }
00551         }
00552     }
00553     return changed;
00554 }
00555 
00556 void DataFlow::dumpStacks() {
00557     std::cerr << "Stacks: " << Stacks.size() << " entries\n";
00558     std::map<Exp*, std::stack<Statement*>, lessExpStar>::iterator zz;
00559     for (zz = Stacks.begin(); zz != Stacks.end(); zz++) {
00560         std::cerr << "Var " << zz->first << " [ ";
00561         std::stack<Statement*>tt = zz->second;               // Copy the stack!
00562         while (!tt.empty()) {
00563             std::cerr << tt.top()->getNumber() << " "; tt.pop();
00564         }
00565         std::cerr << "]\n";
00566     }
00567 }
00568 
00569 void DataFlow::dumpDefsites() {
00570     std::map<Exp*, std::set<int>, lessExpStar>::iterator dd;
00571     for (dd = defsites.begin(); dd != defsites.end(); ++dd) {
00572         std::cerr << dd->first;
00573         std::set<int>::iterator ii;
00574         std::set<int>& si = dd->second;
00575         for (ii = si.begin(); ii != si.end(); ++ii)
00576             std::cerr << " " << *ii;
00577         std::cerr << "\n";
00578     }
00579 }
00580 
00581 void DataFlow::dumpA_orig() {
00582     int n = A_orig.size();
00583     for (int i=0; i < n; ++i) {
00584         std::cerr << i;
00585         std::set<Exp*, lessExpStar>::iterator ee;
00586         std::set<Exp*, lessExpStar>& se = A_orig[i];
00587         for (ee = se.begin(); ee != se.end(); ++ee)
00588             std::cerr << " " << *ee;
00589         std::cerr << "\n";
00590     }
00591 }
00592 
00593 void DefCollector::updateDefs(std::map<Exp*, std::stack<Statement*>, lessExpStar>& Stacks, UserProc* proc) {
00594     std::map<Exp*, std::stack<Statement*>, lessExpStar>::iterator it;
00595     for (it = Stacks.begin(); it != Stacks.end(); it++) {
00596         if (it->second.size() == 0)
00597             continue;                   // This variable's definition doesn't reach here
00598         // Create an assignment of the form loc := loc{def}
00599         RefExp* re = new RefExp(it->first->clone(), it->second.top());
00600         Assign* as = new Assign(it->first->clone(), re);
00601         as->setProc(proc);              // Simplify sometimes needs this
00602         insert(as);
00603     }
00604     initialised = true;
00605 }
00606 
00607 // Find the definition for e that reaches this Collector. If none reaches here, return NULL
00608 Exp* DefCollector::findDefFor(Exp* e) {
00609     iterator it;
00610     for (it = defs.begin(); it != defs.end(); ++it) {
00611         Exp* lhs = (*it)->getLeft();
00612         if (*lhs == *e)
00613             return (*it)->getRight();
00614     }
00615     return NULL;                    // Not explicitly defined here
00616 }
00617 
00618 void UseCollector::print(std::ostream& os, bool html) {
00619     LocationSet::iterator it;
00620     bool first = true;
00621     for (it=locs.begin(); it != locs.end(); ++it) {
00622         if (first)
00623             first = false;
00624         else
00625             os << ",  ";
00626         (*it)->print(os, html);
00627     }
00628 }
00629 
00630 #define DEFCOL_COLS 120
00631 void DefCollector::print(std::ostream& os, bool html) {
00632     iterator it;
00633     unsigned col = 36;
00634     bool first = true;
00635     for (it=defs.begin(); it != defs.end(); ++it) {
00636         std::ostringstream ost;
00637         (*it)->getLeft()->print(ost, html);
00638         ost << "=";
00639         (*it)->getRight()->print(ost, html);
00640         unsigned len = ost.str().length();
00641         if (first)
00642             first = false;
00643         else if (col+4+len >= DEFCOL_COLS) {        // 4 for a comma and three spaces
00644             if (col != DEFCOL_COLS-1) os << ",";    // Comma at end of line
00645             os << "\n                ";
00646             col = 16;
00647         } else {
00648             os << ",   ";
00649             col += 4;
00650         }
00651         os << ost.str().c_str();
00652         col += len;
00653     }
00654 }
00655 
00656 char* UseCollector::prints() {
00657     std::ostringstream ost;
00658     print(ost);
00659     strncpy(debug_buffer, ost.str().c_str(), DEBUG_BUFSIZE-1);
00660     debug_buffer[DEBUG_BUFSIZE-1] = '\0';
00661     return debug_buffer;
00662 }
00663 
00664 char* DefCollector::prints() {
00665     std::ostringstream ost;
00666     print(ost);
00667     strncpy(debug_buffer, ost.str().c_str(), DEBUG_BUFSIZE-1);
00668     debug_buffer[DEBUG_BUFSIZE-1] = '\0';
00669     return debug_buffer;
00670 }
00671 
00672 void UseCollector::dump() {
00673     std::ostringstream ost;
00674     print(ost);
00675     std::cerr << ost.str();
00676 }
00677 
00678 void DefCollector::dump() {
00679     std::ostringstream ost;
00680     print(ost);
00681     std::cerr << ost.str();
00682 }
00683 
00684 void UseCollector::makeCloneOf(UseCollector& other) {
00685     initialised = other.initialised;
00686     locs.clear();
00687     for (iterator it = other.begin(); it != other.end(); ++it)
00688         locs.insert((*it)->clone());
00689 }
00690 
00691 void DefCollector::makeCloneOf(DefCollector& other) {
00692     initialised = other.initialised;
00693     defs.clear();
00694     for (iterator it = other.begin(); it != other.end(); ++it)
00695         defs.insert((Assign*)(*it)->clone());
00696 }
00697 
00698 void DefCollector::searchReplaceAll(Exp* from, Exp* to, bool& change) {
00699     iterator it;
00700     for (it=defs.begin(); it != defs.end(); ++it)
00701         (*it)->searchAndReplace(from, to);
00702 }
00703 
00704 // Called from CallStatement::fromSSAform. The UserProc is needed for the symbol map
00705 void UseCollector::fromSSAform(UserProc* proc, Statement* def) {
00706     LocationSet removes, inserts;
00707     iterator it;
00708     ExpSsaXformer esx(proc);
00709     for (it = locs.begin(); it != locs.end(); ++it) {
00710         RefExp* ref = new RefExp(*it, def);         // Wrap it in a def
00711         Exp* ret = ref->accept(&esx);
00712         // If there is no change, ret will equal *it again (i.e. fromSSAform just removed the subscript)
00713         if (ret != *it) {                           // Pointer comparison
00714             // There was a change; we want to replace *it with ret
00715             removes.insert(*it);
00716             inserts.insert(ret);
00717         }
00718     }
00719     for (it = removes.begin(); it != removes.end(); ++it)
00720         locs.remove(*it);
00721     for (it = inserts.begin(); it != inserts.end(); ++it)
00722         locs.insert(*it);
00723 }
00724 
00725 bool UseCollector::operator==(UseCollector& other) {
00726     if (other.initialised != initialised) return false;
00727     iterator it1, it2;
00728     if (other.locs.size() != locs.size()) return false;
00729     for (it1 = locs.begin(), it2 = other.locs.begin(); it1 != locs.end(); ++it1, ++it2)
00730         if (!(**it1 == **it2)) return false;
00731     return true;
00732 }
00733 
00734 void DefCollector::insert(Assign* a) {
00735     Exp* l = a->getLeft();
00736     if (existsOnLeft(l)) return;
00737     defs.insert(a);
00738 }
00739 
00740 void DataFlow::convertImplicits(Cfg* cfg) {
00741     // Convert statements in A_phi from m[...]{-} to m[...]{0}
00742     std::map<Exp*, std::set<int>, lessExpStar> A_phi_copy = A_phi;          // Object copy
00743     std::map<Exp*, std::set<int>, lessExpStar>::iterator it;
00744     ImplicitConverter ic(cfg);
00745     A_phi.clear();
00746     for (it = A_phi_copy.begin(); it != A_phi_copy.end(); ++it) {
00747         Exp* e = it->first->clone();
00748         e = e->accept(&ic);
00749         A_phi[e] = it->second;                  // Copy the set (doesn't have to be deep)
00750     }
00751 
00752     std::map<Exp*, std::set<int>, lessExpStar > defsites_copy = defsites;   // Object copy
00753     std::map<Exp*, std::set<int>, lessExpStar >::iterator dd;
00754     defsites.clear();
00755     for (dd = A_phi_copy.begin(); dd != A_phi_copy.end(); ++dd) {
00756         Exp* e = dd->first->clone();
00757         e = e->accept(&ic);
00758         defsites[e] = dd->second;               // Copy the set (doesn't have to be deep)
00759     }
00760 
00761     std::vector<std::set<Exp*, lessExpStar> > A_orig_copy;
00762     std::vector<std::set<Exp*, lessExpStar> >::iterator oo;
00763     A_orig.clear();
00764     for (oo = A_orig_copy.begin(); oo != A_orig_copy.end(); ++oo) {
00765         std::set<Exp*, lessExpStar>& se = *oo;
00766         std::set<Exp*, lessExpStar> se_new;
00767         std::set<Exp*, lessExpStar>::iterator ee;
00768         for (ee = se.begin(); ee != se.end(); ++ee) {
00769             Exp* e = (*ee)->clone();
00770             e = e->accept(&ic);
00771             se_new.insert(e);
00772         }
00773         A_orig.insert(A_orig.end(), se_new);    // Copy the set (doesn't have to be a deep copy)
00774     }
00775 }
00776 
00777 
00778 // Helper function for UserProc::propagateStatements()
00779 // Works on basic block n; call from UserProc with n=0 (entry BB)
00780 // If an SSA location is in usedByDomPhi it means it is used in a phi that dominates its assignment
00781 // However, it could turn out that the phi is dead, in which case we don't want to keep the associated entries in
00782 // usedByDomPhi. So we maintain the map defdByPhi which maps locations defined at a phi to the phi statements. Every
00783 // time we see a use of a location in defdByPhi, we remove that map entry. At the end of the procedure we therefore have
00784 // only dead phi statements in the map, so we can delete the associated entries in defdByPhi and also remove the dead
00785 // phi statements.
00786 // We add to the set usedByDomPhi0 whenever we see a location referenced by a phi parameter. When we see a definition
00787 // for such a location, we remove it from the usedByDomPhi0 set (to save memory) and add it to the usedByDomPhi set.
00788 // For locations defined before they are used in a phi parameter, there will be no entry in usedByDomPhi, so we ignore
00789 // it. Remember that each location is defined only once, so that's the time to decide if it is dominated by a phi use or
00790 // not.
00791 void DataFlow::findLiveAtDomPhi(int n, LocationSet& usedByDomPhi, LocationSet& usedByDomPhi0,
00792             std::map<Exp*, PhiAssign*, lessExpStar>& defdByPhi) {
00793     // For each statement this BB
00794     BasicBlock::rtlit rit; StatementList::iterator sit;
00795     PBB bb = BBs[n];
00796     Statement* S;
00797     for (S = bb->getFirstStmt(rit, sit); S; S = bb->getNextStmt(rit, sit)) {
00798         if (S->isPhi()) {
00799             // For each phi parameter, insert an entry into usedByDomPhi0
00800             PhiAssign* pa = (PhiAssign*)S;
00801             PhiAssign::iterator it;
00802             for (it = pa->begin(); it != pa->end(); ++it) {
00803                 if (it->e) {
00804                     RefExp* re = new RefExp(it->e, it->def);
00805                     usedByDomPhi0.insert(re);
00806                 }
00807             }
00808             // Insert an entry into the defdByPhi map
00809             RefExp* wrappedLhs = new RefExp(pa->getLeft(), pa);
00810             defdByPhi[wrappedLhs] = pa;
00811             // Fall through to the below, because phi uses are also legitimate uses
00812         }
00813         LocationSet ls;
00814         S->addUsedLocs(ls);
00815         // Consider uses of this statement
00816         LocationSet::iterator it;
00817         for (it = ls.begin(); it != ls.end(); ++it) {
00818             // Remove this entry from the map, since it is not unused
00819             defdByPhi.erase(*it);
00820         }
00821         // Now process any definitions
00822         ls.clear();
00823         S->getDefinitions(ls);
00824         for (it = ls.begin(); it != ls.end(); ++it) {
00825             RefExp* wrappedDef = new RefExp(*it, S);
00826             // If this definition is in the usedByDomPhi0 set, then it is in fact dominated by a phi use, so move it to
00827             // the final usedByDomPhi set
00828             if (usedByDomPhi0.find(wrappedDef) != usedByDomPhi0.end()) {
00829                 usedByDomPhi0.remove(wrappedDef);
00830                 usedByDomPhi.insert(wrappedDef);
00831             }
00832         }
00833     }
00834 
00835     // Visit each child in the dominator graph
00836     // Note: this is a linear search!
00837     // Note also that usedByDomPhi0 may have some irrelevant entries, but this will do no harm, and attempting to erase
00838     // the irrelevant ones would probably cost more than leaving them alone
00839     int sz = idom.size();
00840     for (int c = 0; c < sz; ++c) {
00841         if (idom[c] != n) continue;
00842         // Recurse to the child
00843         findLiveAtDomPhi(c, usedByDomPhi, usedByDomPhi0, defdByPhi);
00844     }
00845 }
00846 
00847 #if USE_DOMINANCE_NUMS
00848 void DataFlow::setDominanceNums(int n, int& currNum) {
00849     BasicBlock::rtlit rit; StatementList::iterator sit;
00850     PBB bb = BBs[n];
00851     Statement* S;
00852     for (S = bb->getFirstStmt(rit, sit); S; S = bb->getNextStmt(rit, sit))
00853         S->setDomNumber(currNum++);
00854     int sz = idom.size();
00855     for (int c = 0; c < sz; ++c) {
00856         if (idom[c] != n) continue;
00857         // Recurse to the child
00858         setDominanceNums(c, currNum);
00859     }
00860 }
00861 #endif
00862 

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