C-Breeze
C Compiler Infrastructure

[ Project home page]
Main Page   Modules   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages  

reaching.cc

Go to the documentation of this file.
00001 // $Id: reaching.cc,v 1.8 2003/08/11 14:21:32 toktb Exp $
00002 // ----------------------------------------------------------------------
00003 //
00004 //  C-Breeze
00005 //  C Compiler Framework
00006 // 
00007 //  Copyright (c) 2000 University of Texas at Austin
00008 // 
00009 //  Teck Bok Tok
00010 //  Samuel Z. Guyer
00011 //  Daniel A. Jimenez
00012 //  Calvin Lin
00013 // 
00014 //  Permission is hereby granted, free of charge, to any person
00015 //  obtaining a copy of this software and associated documentation
00016 //  files (the "Software"), to deal in the Software without
00017 //  restriction, including without limitation the rights to use, copy,
00018 //  modify, merge, publish, distribute, sublicense, and/or sell copies
00019 //  of the Software, and to permit persons to whom the Software is
00020 //  furnished to do so, subject to the following conditions:
00021 //  
00022 //  The above copyright notice and this permission notice shall be
00023 //  included in all copies or substantial portions of the Software.
00024 //  
00025 //  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
00026 //  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00027 //  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
00028 //  NONINFRINGEMENT.  IN NO EVENT SHALL THE UNIVERSITY OF TEXAS AT
00029 //  AUSTIN BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
00030 //  IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
00031 //  OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
00032 //  THE SOFTWARE.
00033 //
00034 //  We acknowledge the C-to-C Translator from MIT Laboratory for
00035 //  Computer Science for inspiring parts of the C-Breeze design.
00036 //
00037 // ----------------------------------------------------------------------
00038 
00039 #include "c_breeze.h"
00040 #include "bits.h"
00041 #include "reaching.h"
00042 
00045 class reachingDefinitionsWalker::defFlowVal {
00046   friend class reachingGenKillWalker;
00047 private:
00048 
00049   int                        size; // the number of definitions
00050   map <threeAddrNode*, int> *def2num;  // a map from a definition to its
00051                                        // index (bit position)
00052   Bits                      *bits;
00053   threeAddrNode            **definitions; // array mapping a definition's
00054                                           // index (bit position) to itself
00055 
00056 public:
00065   defFlowVal (int n, map<threeAddrNode*,int> *m, threeAddrNode **d)
00066   : size(n), def2num(m), definitions(d), bits(new Bits(n+1)) { to_top (); }
00067 
00068   ~defFlowVal (void) { delete bits; }
00069 
00070   // set this flow value to top (i.e., the empty set)
00071   void to_top (void) { bits->reset_all(); }
00072 
00073   // get a clone of this flow value
00074   defFlowVal * clone (void) const {
00075     defFlowVal *other = new defFlowVal (size, def2num, definitions);
00076     other->bits = bits->clone();
00077     return other;
00078   }
00079 
00080   // returns true iff the two flow values differ
00081   bool diff (defFlowVal *other) const {
00082     if(!other) return true;
00083     for (int i=1; i<=size; i++)
00084       if (other->bits->value(i) != bits->value(i)) 
00085         return true;
00086     return false;
00087   }
00088 
00089   // return true if the definition is in the set, by a pointer to the definition
00090   bool in (threeAddrNode *s) const { return bits->value((*def2num)[s]); }
00091 
00092   // return true if the definition is in the set, by the index of the definition
00093   bool in (int i) const { return bits->value(i); }
00094 
00096   void insert (threeAddrNode *s) { bits->set ((*def2num)[s], true); }
00097 
00099   void insert (int i) { bits->set (i, true); }
00100 
00102   void remove (threeAddrNode *s) { bits->set ((*def2num)[s], false); }
00103 
00105   void remove (int i) { bits->set (i, false); }
00106 
00108   void copy (defFlowVal *other) { if(other) bits->copy (other->bits); }
00109 
00111   void Union (const defFlowVal *v) { if(v) bits->Or (v->bits); }
00112 
00114   void Intersect (const defFlowVal *v) { if(v) bits->And (v->bits); }
00115 
00116   // set this definition to the set difference of itself with the parameter
00117   // (i.e. this - the other)
00118   void Difference (defFlowVal *other) {
00119     if(!other) return;
00120     Bits comp(size+1);
00121     comp.copy (other->bits);
00122     comp.Not ();
00123     bits->And (&comp);
00124   }
00125 
00127   void meet (const defFlowVal *v) { Union(v); }
00128 }; // defFlowVal 
00129 
00130 
00132 
00135 class reachingDefinitionsWalker::reachingGenKillWalker : public Walker {
00136   friend class reachingDefinitionsWalker;
00137 
00138 private:
00139   // reachingGenKillWalker creates the gen/kill sets of all statements and
00140   // blocks in a procedure. To do that, we need to gather all definitions in
00141   // the procedure. Use GetDefsWalker to do that.
00142   class GetDefsWalker : public Walker {
00143   private:
00144 
00145     // passed in
00146 
00147     map<threeAddrNode*, declNode*> * defines;
00148 
00149     // list of ambiguous definitions, passed in
00150 
00151     stmt_list * ambiguous_defs;
00152 
00153   public:
00154     GetDefsWalker (map<threeAddrNode*, declNode*> *d, stmt_list *l) : 
00155       Walker (Preorder, Subtree), ambiguous_defs(l), defines(d) { }
00156 
00157     // for each definition, get what it defines, and check if it is an
00158     // ambiguous definition.
00159     void at_threeAddr (threeAddrNode *stmt, Order) {
00160       bool ambiguous = false;
00161       if(stmt->lhs()) { // found a definition.
00162         operandNode *lhs = stmt->lhs();
00163         if(lhs->star() || ! lhs->fields().empty() || lhs->index())
00164           ambiguous = true;
00165         else {
00166           assert(lhs->var()->typ() == Id);
00167           (*defines)[stmt] = ((idNode*)lhs->var())->decl();
00168         }
00169       }
00170       if(stmt->op() && stmt->op()->id() == Operator::FUNC_CALL)
00171         ambiguous = true;
00172       if(ambiguous)
00173         ambiguous_defs->push_back (stmt);
00174     }
00175   }; // class GetDefsWalker
00176 
00178   // %{ remaining of class reachingGenKillWalker
00179 
00181   map <threeAddrNode *, int> * node2num;
00182 
00184   map <threeAddrNode *, declNode *> * defines;
00185 
00187   map <declNode *, defFlowVal *> *defs;
00188 
00190   stmt_list ambiguous_defs;
00191 
00192   // mapping from bit positions to definitions in the current procedure.
00193   threeAddrNode ***num2node;
00194 
00196   int *n; 
00197 
00198   // the instance of reaching definition class that created and used me.
00199   reachingDefinitionsWalker *_rd;
00200 
00202   defFlowVal * _flowval;
00203 
00205   defFlowVal * _everything;
00206 
00207   // dummy statements
00208   stmt_list & _dummies;
00209 
00210 public:
00211 
00212   // constructor
00213   reachingGenKillWalker (map <threeAddrNode *, int> *n2n,
00214                          map <threeAddrNode *, declNode *> *dfns,
00215                          map <declNode *, defFlowVal *> *dfs,
00216                          threeAddrNode ***num2n,
00217                          int *numdefs,
00218                          reachingDefinitionsWalker *rd,
00219                          stmt_list & dummies) :
00220       Walker (Preorder, Subtree), 
00221       node2num(n2n),
00222       defines(dfns),
00223       defs(dfs),
00224       n(numdefs),
00225       _flowval(NULL),
00226       num2node(num2n),
00227       _rd(rd),
00228       _dummies(dummies) { }
00229 
00230   // destructor
00231   ~reachingGenKillWalker (void) {}
00232 
00238   defFlowVal * new_flowval (void) {
00239     defFlowVal *f = (defFlowVal *) _flowval->clone();
00240     f->to_top();
00241     return f;
00242   }
00243 
00244   void at_proc (procNode *, Order);
00245 
00246   void at_basicblock (basicblockNode *, Order);
00247 
00248   // we just want to populate gen and kill sets at the procedure level; it
00249   // makes no sense at the unit level.
00250   void at_unit (unitNode *, Order) {
00251     cerr << "Don't invoke the reachingGenKillWalker from a unitNode!\n";
00252     exit (1);
00253   }
00254   // %} end of class reachingGenKillWalker
00255 }; // class reachingGenKillWalker 
00256 
00257 
00258 void reachingDefinitionsWalker::reachingGenKillWalker
00259      ::at_proc(procNode *p, Order ord) {
00260   int  i;
00261 
00262   // get the definitions from this procedure
00263 
00264   defines->clear();
00265   GetDefsWalker gdw (defines, & ambiguous_defs);
00266   p->walk (gdw);
00267 
00268   // get a list of all the variables defined
00269 
00270   decl_list vars;
00271   map <threeAddrNode *, declNode *>::iterator r;
00272   for (r=defines->begin(); r!=defines->end(); r++)
00273     vars.push_back ((*r).second);
00274   vars.sort();
00275   vars.unique();
00276 
00277   // n will be the length of the bit vector (minus 1). We need one bit for
00278   // each variable (for arbiguous definitions) and each definition.
00279 
00280   *n = defines->size() + vars.size();
00281 
00282   // num2node will map bit positions to statements.
00283   // bit positions go from 1..n, since 0 might be returned by the map on
00284   // an unrecognized statement
00285 
00286   *num2node = new threeAddrNode *[*n + 1];
00287 
00288   // get an empty flow value we can clone later
00289 
00290   _flowval = new defFlowVal (*n, node2num, *num2node);
00291   _flowval->to_top();
00292 
00293   // map stmtNode's to bit positions
00294   // and vice versa; also, populate defs[]
00295 
00296   // first, unambiguous definitions
00297 
00298   for (i=1, r=defines->begin(); r!=defines->end(); i++,r++) {
00299 
00300     // the bit position of this definition is i
00301 
00302     (*node2num)[(*r).first] = i;
00303 
00304     // the i'th bit position represents this definition
00305 
00306     (*num2node)[i] = (*r).first;
00307 
00308     // for the variable declaration (*p).second, defs[(*r).second] will
00309     // contain all its definitions
00310 
00311     defFlowVal *v = (*defs)[(*r).second];
00312 
00313     // no such flow val?  make one.
00314 
00315     if (v == NULL) {
00316       v = (defFlowVal *) _flowval->clone();
00317       (*defs)[(*r).second] = v;
00318     }
00319     v->insert (i);
00320   }
00321 
00322   // now, ambiguous definitions; we'll make up one for each variable
00323 
00324   _everything = (defFlowVal *) _flowval->clone();
00325   decl_list_p q;
00326   for (q=vars.begin(); q!=vars.end(); q++, i++) {
00327 
00328     // make a new statement that will represent
00329     // "the" ambiguous definition of this variable
00330 
00331     threeAddrNode *dummy = new threeAddrNode (NULL,(operandNode*)NULL);
00332     _dummies.push_back(dummy);
00333 
00334     // set up the mapping between bit positions
00335     // and the stmtNode *
00336 
00337     (*node2num)[dummy] = i;
00338     (*num2node)[i] = dummy;
00339 
00340     // this ``definition'' defines this variable
00341 
00342     (*defines)[dummy] = *q;
00343 
00344     // get the set of definitions for this variable
00345 
00346     defFlowVal *v = (*defs)[*q];
00347 
00348     // this should have been created already
00349 
00350     assert (v);
00351 
00352     // insert this ambiguous definition
00353 
00354     v->insert (i);
00355 
00356     // also insert it into _everything; at the end,
00357     // _everything will be a set, for each variable,
00358     // of "the" ambiguous definition for that variable.
00359 
00360     _everything->insert (i);
00361   }
00362 
00363   // ready to process procedure body.
00364 
00365   // if the first block has a label, we need a preheader to receive gen
00366   // for the parameters and globals
00367 
00368   basicblockNode *b = (basicblockNode *) p->body()->stmts().front();
00369   if (b->stmts().size() && b->stmts().front()->typ() == Label) {
00370     // new Goto to the first block
00371     stmt_list new_stmt;
00372     new_stmt.push_back( new gotoNode((labelNode*) b->stmts().front()) );
00373 
00374     // make an empty preheader for the procedure
00375 
00376     b = new basicblockNode (NULL, & new_stmt);
00377     b->comment() = "preheader to generate parameters and globals";
00378   
00379     // link it to the first block in the procedure
00380   
00381     ((basicblockNode *)(p->body()->stmts().front()))->
00382       preds().push_back (b);
00383     b->succs().push_back ((basicblockNode *) 
00384       p->body()->stmts().front());
00385     p->body()->stmts().push_front (b);
00386   }
00387 
00388   // make gen and kill sets for each statement (a basicblock),
00389   // giving them initially empty gen/kill sets
00390 
00391   stmt_list_p t;
00392   for (t=p->body()->stmts().begin(); t!=p->body()->stmts().end(); t++) {
00393     b = (basicblockNode *) *t;
00394     stmt_list_p r;
00395     for (r=b->stmts().begin(); r!=b->stmts().end(); r++) {
00396       _rd->gen[*r] = (defFlowVal *) _flowval->clone();
00397       _rd->kill[*r] = (defFlowVal *) _flowval->clone();
00398     }
00399   }
00400 
00401   // for every statement that is an ambiguous definition,
00402   // it generates everything
00403 
00404   for (t=ambiguous_defs.begin(); t!=ambiguous_defs.end(); t++) {
00405     defFlowVal *v = _rd->gen[*t];
00406     assert (v);
00407     v->Union (_everything);
00408   }
00409 
00410   // let at_basicblock take care of the rest
00411 } // at_proc
00412 
00413 
00414 void reachingDefinitionsWalker::reachingGenKillWalker
00415      ::at_basicblock(basicblockNode *b, Order ord) {
00416   stmt_list_p r;
00417 
00418   defFlowVal *gen;
00419   defFlowVal *kill;
00420 
00421   // make gen and kill for each statement in the basicblock
00422 
00423   for (r=b->stmts().begin(); r!=b->stmts().end(); r++) {
00424     if((*r)->typ() != ThreeAddr) continue;
00425 
00426     // d is the definition (or just a statement)
00427 
00428     threeAddrNode *d = (threeAddrNode*) *r;
00429 
00430     // gen and kill are new flowvals, initially empty
00431 
00432     gen = _rd->gen[d];
00433     kill = _rd->kill[d];
00434 
00435     // v is the variable defined by definition d.
00436 
00437     declNode *v = (*defines)[d];
00438     if (v == NULL) {
00439 
00440       // nothing to do; d is not a definition,
00441       // or may be ambiguous and thus not
00442       // in defines.
00443 
00444     } else {
00445 
00446       // definition d defines variable v
00447       // all definitions of v are killed
00448 
00449       kill->Union ((*defs)[v]);
00450 
00451       // except for this one!
00452 
00453       kill->remove (d);
00454 
00455       // this definition gens itself
00456 
00457       gen->insert (d);
00458     }
00459   }
00460 
00461   // gen and kill are defined for each statement.
00462   // put them all together for gen and kill
00463   // for this block.
00464 
00465   gen = (defFlowVal *) _flowval->clone();
00466   kill = (defFlowVal *) _flowval->clone();
00467 
00468   // the (pre)header should be seen to generate all ambiguous
00469   // definitions, so that parameters and global variables are 
00470   // seen with definitions reaching into the procedure
00471 
00472   if (b->preds().size() == 0) gen->Union (_everything);
00473 
00474   for (r=b->stmts().begin(); r!=b->stmts().end(); r++) {
00475     stmtNode *d = *r;
00476 
00477     // from Dragon book:
00478     // gen[S] = gen[S_2] U (gen[S_1] - kill[S_2])
00479     // kill[S] = kill[S_2] U (kill[S_1] - gen[S_2])
00480     // we think of the basic block as seen so far
00481     // as S_1, and the current statement (d) as S_2,
00482     // with the resulting current basic block so far
00483     // as S.
00484 
00485     gen->Difference (_rd->kill[d]);
00486     gen->Union (_rd->gen[d]);
00487     kill->Difference (_rd->gen[d]);
00488     kill->Union (_rd->kill[d]);
00489   }
00490   _rd->gen[b] = gen;
00491   _rd->kill[b] = kill;
00492 } // at_basicblock
00493 
00495 
00496 
00497 void reachingDefinitionsWalker::at_proc (procNode *p, Order ord) {
00498   if (ord == Postorder) {
00499     // clean up
00500     delete [] num2node;
00501     num2node = NULL;
00502     for(stmt_list_p d=dummies.begin(); d!=dummies.end(); d++) delete *d;
00503     return;
00504   }
00505   node2num.clear();
00506   defines.clear();
00507   in.clear();
00508   out.clear();
00509   defs.clear();
00510 
00511   // get gen/kill sets for each basic block
00512 
00513   reachingGenKillWalker gcw (&node2num, &defines, &defs, &num2node, &n, this,
00514                              dummies);
00515   p->walk (gcw);
00516   defFlowVal *v = gcw.new_flowval();
00517   blockNode *b = p->body();
00518 
00519   // for each basic block B, initial value of in and out:
00520   // out[B] = gen[B],
00521   // in[B] = empty
00522 
00523   stmt_list_p r;
00524   for (r=b->stmts().begin(); r!=b->stmts().end(); r++) {
00525     basicblockNode *B = (basicblockNode *) *r;
00526     out[B] = (defFlowVal *) gen[B]->clone();
00527     in[B] = (defFlowVal *) v->clone();
00528   }
00529 
00530   defFlowVal *oldout = gcw.new_flowval(); // used in loop below.
00531   bool change = true;
00532   
00533   // there is a lot of copying going on in this loop,
00534   // but we do this because to move pointers around would
00535   // require lots of changing the map and malloc'ing,
00536   // which tends to run out of memory on some pathological
00537   // functions (like perl's eval.c)
00538 
00539   while (change) {
00540     change = false;
00541 
00542     // for each block B do
00543 
00544     for (r=b->stmts().begin(); r!=b->stmts().end(); r++) {
00545       basicblockNode *B = (basicblockNode *) *r;
00546       defFlowVal *inb = in[B];
00547       defFlowVal *outb = out[B];
00548 
00549       // from Dragon book:
00550       // in[B] = U_{q in pred(B)} out[Q]
00551 
00552       inb->to_top();
00553       basicblock_list_p q;
00554       for (q=B->preds().begin(); q!=B->preds().end(); q++)
00555         inb->Union (out[*q]);
00556 
00557       oldout->copy (outb); // remember value
00558 
00559       // out[B] = gen[B] U (in[B] - kill[B])
00560 
00561       // v is a copy of in[B]
00562       v->copy (inb);
00563       v->Difference (kill[B]);
00564       v->Union (gen[B]);
00565       outb->copy (v);
00566       if (oldout->diff(v)) change = true;
00567     }
00568   }
00569   delete v;
00570   delete oldout;
00571   delete gcw._flowval;
00572   // let at_basicblock() compute the values at statement level.
00573 } // at_proc
00574 
00575 
00576 void reachingDefinitionsWalker::at_basicblock (basicblockNode *b,
00577                                                      Order ord) {
00578   stmt_list_p p;
00579   if (ord == Postorder) {
00580     // cleanup
00581     for (p=b->stmts().begin(); p!=b->stmts().end(); p++) {
00582       stmtNode *s = *p;
00583       if (gen[s]) {
00584         delete gen[s];
00585         gen[s] = NULL;
00586       }
00587       if (kill[s]) {
00588         delete kill[s];
00589         kill[s] = NULL;
00590       }
00591     }
00592     if (gen[b]) {
00593       delete gen[b];
00594       gen[b] = NULL;
00595     }
00596     if (kill[b]) {
00597       delete kill[b];
00598       kill[b] = NULL;
00599     }
00600     delete in[b];
00601     delete out[b];
00602     return;
00603   }
00604 
00605   current_in = (defFlowVal *) in[b]->clone();
00606   for (p=b->stmts().begin(); p!=b->stmts().end(); p++) {
00607     make_ud_chains (*p); // make ud chain using current_in
00608 
00609     // the current reaching definitions
00610     // are the current ones union
00611     // the ones generated here minus
00612     // the ones killed here.
00613 
00614     current_in->Difference (kill[*p]);
00615     current_in->Union (gen[*p]);
00616   }
00617   delete current_in;
00618 } // at_basicblock
00619 
00620 
00621 
00622 void reachingDefinitionsWalker::make_ud_chains (stmtNode *s) {
00623   switch(s->typ()) {
00624     case Condition: {
00625       conditiongotoNode *g = (conditiongotoNode*) s;
00626       make_ud_chains(g->left(), NULL, s);
00627       make_ud_chains(g->right(), NULL, s);
00628       break;
00629     }
00630 
00631     case ThreeAddr: {
00632       threeAddrNode *S = (threeAddrNode*) s;
00633       if(S->lhs() && S->lhs()->index())
00634         make_ud_chains(S->lhs()->index(), NULL, s);
00635       make_ud_chains(S->rhs1(), NULL, s);
00636       make_ud_chains(S->rhs2(), NULL, s);
00637       for(operand_list_p a=S->arg_list().begin(); a!=S->arg_list().end(); a++)
00638         make_ud_chains(*a, NULL, s);
00639       break;
00640     }
00641 
00642     case Return: make_ud_chains(((returnNode*)s)->expr(), NULL, s);
00643                  break;
00644 
00645     case Expr: assert(! ((exprstmtNode*)s)->expr()); // no Expr in
00646                break;                                // dismanted code.
00647 
00648     case Label:
00649     case Goto:  break; // nothing to do
00650     default: cout << s->typ() << " " << s->coord() << endl;
00651              assert(false); // unreachable
00652   }
00653 } // make_ud_chains(stmt)
00654 
00655 
00656 void reachingDefinitionsWalker::make_ud_chains (exprNode *e,
00657                                                       exprNode *E,
00658                                                       stmtNode *usesite) {
00659   if (!e) return;
00660   if (!E) E=e;   // if E was not NULL, it is an Operand and e is the id or
00661                  // index inside. In that case we want to make ud-chain on
00662                  // both E and e.
00663   switch (e->typ()) {
00664     case Id: {
00665       idNode *i = (idNode *) e;
00666 
00667       // i_defs is the set of definitions of i
00668 
00669       defFlowVal *i_defs = defs[i->decl()];
00670 
00671       // maybe unknown id, like a function identifier
00672 
00673       if (!i_defs) return;
00674 
00675       bool has_ambiguous = false;
00676       for (int j=1; j<=n; j++)
00677         if (i_defs->in (j) && current_in->in (j)) {
00678           threeAddrNode *t = num2node[j];
00679           assert(t);
00680           if (!t->lhs() && !t->rhs1()) // this is a dummy threeAddrNode created
00681                                        // by reachingGenKillWalker::at_proc();
00682             has_ambiguous = true;
00683           else {
00684             udChain->add(E, num2node[j], usesite);
00685             if(E!=i) udChain->add(i, num2node[j], usesite);
00686           }
00687         }
00688       if (has_ambiguous) {
00689         udChain->add(E, NULL, usesite); // The NULL indicates an ambiguous defn
00690         if(E!=i) udChain->add(E, NULL, usesite);
00691       }
00692       break;
00693     }
00694 
00695     case Operand: {
00696       operandNode *o = (operandNode*) e;
00697       if(o->addr()) break; // not an use.
00698       make_ud_chains(o->var(), o, usesite);
00699       make_ud_chains(o->index(), NULL, usesite);
00700       break;
00701     }
00702 
00703     case Const: break; // nothing to do
00704 
00705     default: assert(false); // unreachable
00706   }
00707 } // make_ud_chains(expr)
00708 

Generated on August 27, 2003
Back to the C-Breeze home page