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  

ssa.cc

Go to the documentation of this file.
00001 // $Id: ssa.cc,v 1.8 2003/08/07 23:14:21 pnav Exp $
00002 // ----------------------------------------------------------------------
00003 //
00004 //  C-Breeze
00005 //  C Compiler Framework
00006 // 
00007 //  Copyright (c) 2000 University of Texas at Austin
00008 // 
00009 //  Samuel Z. Guyer
00010 //  Daniel A. Jimenez
00011 //  Calvin Lin
00012 // 
00013 //  Permission is hereby granted, free of charge, to any person
00014 //  obtaining a copy of this software and associated documentation
00015 //  files (the "Software"), to deal in the Software without
00016 //  restriction, including without limitation the rights to use, copy,
00017 //  modify, merge, publish, distribute, sublicense, and/or sell copies
00018 //  of the Software, and to permit persons to whom the Software is
00019 //  furnished to do so, subject to the following conditions:
00020 //  
00021 //  The above copyright notice and this permission notice shall be
00022 //  included in all copies or substantial portions of the Software.
00023 //  
00024 //  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
00025 //  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00026 //  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
00027 //  NONINFRINGEMENT.  IN NO EVENT SHALL THE UNIVERSITY OF TEXAS AT
00028 //  AUSTIN BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
00029 //  IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
00030 //  OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
00031 //  THE SOFTWARE.
00032 //
00033 //  We acknowledge the C-to-C Translator from MIT Laboratory for
00034 //  Computer Science for inspiring parts of the C-Breeze design.
00035 //
00036 // ----------------------------------------------------------------------
00037 
00038 #include "c_breeze.h"
00039 #include "ssa.h"
00040 
00041 SSA::SSA(procNode * proc, bool forward, bool do_renaming)
00042   : _proc(proc),
00043     _root(0),
00044     _cfg(),
00045     DF(proc)
00046 {
00047   // --- Store the CFG as a list of basicblockNodes
00048 
00049   stmt_list & sts = proc->body()->stmts();
00050 
00051   for (stmt_list_p p = sts.begin();
00052        p != sts.end();
00053        ++p)
00054     {
00055       stmtNode * s = *p;
00056       assert(s->typ() == Block);
00057       _cfg.push_back( (basicblockNode *) s);
00058     }
00059 
00060   _root = _cfg.front();
00061 
00062   // --- Initialize ssa_info structures
00063 
00064   for (basicblock_list_p p = _cfg.begin();
00065        p != _cfg.end();
00066        ++p)
00067     {
00068       basicblockNode * cur = (*p);
00069       cur->info(new ssa_info());
00070     }
00071 
00072   // --- Place phi functions
00073 
00074   place_phi_functions();
00075 
00076   // --- Renaming the variables is optional
00077 
00078   if (do_renaming)
00079     rename();
00080 
00081   // --- Remove all the ssa_info structures
00082 
00083   for (basicblock_list_p p = _cfg.begin();
00084        p != _cfg.end();
00085        ++p)
00086     {
00087       basicblockNode * curblock = (*p);
00088       if (curblock->info())
00089         delete curblock->info();
00090       
00091       curblock->info(0);
00092     }
00093 }
00094 
00095 typedef map<declNode *, basicblock_bitset> assignment_map;
00096 typedef assignment_map::iterator assignment_map_p;
00097 
00098 // --- A walker to gather assignment statements
00099 
00100 class Assignment_walker : public Walker
00101 {
00102 private:
00103 
00104   int basicblock;
00105   assignment_map & _a_map;
00106 
00107 public:
00108 
00109   Assignment_walker(assignment_map & a_map, int basicblock_num)
00110     : Walker(Preorder, Subtree),
00111       basicblock(basicblock_num),
00112       _a_map(a_map)
00113   {}
00114 
00115   void at_binary(binaryNode * the_binary, Order ord);
00116 };
00117 
00118 void Assignment_walker::at_binary(binaryNode * the_binary, Order ord)
00119 {
00120   if (the_binary->op()->is_assignment())
00121     if (the_binary->left()->typ() == Id) {
00122       idNode * id = (idNode *) the_binary->left();
00123       declNode * de = id->decl();
00124       if (SSA::need_ssa (de)) { 
00125         if (_a_map.find(de) == _a_map.end())
00126           _a_map[de] = basicblock_bitset();
00127 
00128         _a_map[de].set(basicblock);
00129         // cout << "Def " << id->name() << " at block " << basicblock << endl;
00130       }      
00131     }
00132 }
00133 
00134 // ------------------------------------------------------------
00135 // Place the phi functions
00136 // ------------------------------------------------------------
00137 
00138 void SSA::place_phi_functions()
00139 {
00140   int IterCount = 0;
00141   assignment_map a_map;
00142   basicblock_vec df_vec;
00143 
00144   // --- First collect all the variables that are def'ed. Keep them as
00145   // a list of basic blocks that modify each variable.
00146 
00147   df_vec.resize(_cfg.size(), (basicblockNode *) 0);
00148 
00149   for (basicblock_list_p p = _cfg.begin();
00150        p != _cfg.end();
00151        ++p)
00152     {
00153       basicblockNode * X = (*p);
00154       Assignment_walker aw(a_map, X->dfn());
00155       X->walk(aw);
00156 
00157       df_vec[X->dfn()] = X;
00158     }
00159 
00160   int num_nodes = df_vec.size();
00161 
00162   // --- Clear the renaming stack
00163 
00164   Stack.clear();
00165   Changes.clear();
00166 
00167   basicblock_list W;
00168 
00169   // --- Main loop: for each def'ed variable
00170 
00171   for (assignment_map_p p = a_map.begin();
00172        p != a_map.end();
00173        ++p)
00174     {
00175       declNode * d = (*p).first;
00176       basicblock_bitset & defs = (*p).second;
00177 
00178       // --- Increment the iteration count
00179 
00180       IterCount++;
00181 
00182       // cout << "At variable " << d->name() << endl;
00183 
00184       // --- Initialize the list of basic blocks to visit
00185 
00186       for (int i = 0; i < num_nodes; i++)
00187         if (defs.test(i)) {
00188           basicblockNode * X = df_vec[i];
00189           Work(X) = IterCount;
00190           W.push_back(X);
00191         }
00192 
00193       // --- Also, build the stacks for renaming
00194 
00195       Stack[d] = int_list();
00196       
00197       // --- Start the count at 1 for formal parameters and static variables
00198       // because of the implicit assignment
00199       
00200       if (d->decl_location() == declNode::FORMAL
00201           || d->storage_class() == declNode::STATIC )
00202         Counter[d] = 1;
00203       else Counter[d] = 0;
00204 
00205       // --- Process the work list until empty
00206 
00207       while ( ! W.empty() ) {
00208 
00209         // --- Choose and remove a node X from the work list
00210 
00211         basicblockNode * X = W.front();
00212         W.pop_front();
00213 
00214         // --- For each Y in the dominance frontier of X
00215 
00216         basicblock_list & DFX = DF[X];
00217         for (basicblock_list_p dfp = DFX.begin();
00218              dfp != DFX.end();
00219              ++dfp)
00220           {
00221             basicblockNode * Y = (* dfp);
00222 
00223             // --- If it hasn't been processed yet, add the phi function
00224 
00225             if (HasAlready(Y) < IterCount) {
00226               place_one_phi(d, Y);
00227               HasAlready(Y) = IterCount;
00228 
00229               // --- If it hasn't been on the work list yet, add it
00230 
00231               if (Work(Y) < IterCount) {
00232                 Work(Y) = IterCount;
00233                 W.push_back(Y);
00234               }
00235             }
00236           }
00237       }
00238     }
00239 }
00240 
00241 void SSA::place_one_phi(declNode * d, basicblockNode * block)
00242 {
00243   // cout << "Place a phi " << d->name() << " at " << block->dfn() << endl;
00244 
00245   // --- Build the call to "__phi"
00246 
00247   idNode * phi = new idNode("__phi");
00248 
00249   callNode * call = new callNode(phi, 0);
00250 
00251   // --- One input for each control-flow predecessor
00252 
00253   int sz = block->preds().size();
00254   for (int i = 0; i < sz; i++) {
00255     idNode * v2 = new idNode(d->name().c_str());
00256     v2->decl(d);
00257     typeNode * t = d->no_tdef_type();
00258     if (t)
00259       v2->type((typeNode *) ref_clone_changer::clone(t, false));
00260 
00261     call->args().push_back(v2);
00262   }
00263 
00264   // --- Build the assignment statement
00265 
00266   idNode * v3 = new idNode(d->name().c_str());
00267   v3->decl(d);
00268   typeNode * t = d->no_tdef_type();
00269   if (t)
00270     v3->type((typeNode *) ref_clone_changer::clone(t, false));
00271 
00272   binaryNode * a = new binaryNode('=', v3, call);
00273 
00274   exprstmtNode * e = new exprstmtNode(a);
00275 
00276   // --- Push it to the front of the basic block, but first skip any
00277   // labels.
00278 
00279   stmt_list_p p = block->stmts().begin();
00280   stmtNode * s;
00281 
00282   do {
00283     s = (*p);
00284     p++;
00285   } while ((s->typ() != Label) &&
00286            (p != block->stmts().end()));
00287 
00288   block->stmts().insert(p, e);
00289 }
00290 
00291 int SSA::which_pred(basicblockNode * node, basicblockNode * pred)
00292 {
00293   basicblock_list & bbl = node->preds();
00294   int which = 0;
00295 
00296   for (basicblock_list_p p = bbl.begin();
00297        p != bbl.end();
00298        ++p)
00299     if (pred == (*p))
00300       return which;
00301     else
00302       which++;
00303 
00304   return -1;
00305 }
00306 
00307 // ------------------------------------------------------------
00308 // Rename the variables
00309 // ------------------------------------------------------------
00310 
00311 void SSA::rename()
00312 {
00313   // --- Call the recursive name changer
00314 
00315   search(_root);
00316 
00317   rename_all_variables();
00318 }
00319 
00320 
00321 void SSA::record_index(idNode * the_id)
00322 {
00323   declNode * de = the_id->decl();
00324   if (Stack.find(de) != Stack.end())
00325     if ( ! Stack[de].empty() ) {
00326       int index = Stack[de].front();
00327       Changes.push_back(var_change(the_id, index));
00328     }
00329 }
00330 
00331 class renumber_walker : public Walker
00332 {
00333 public:
00334 
00335   static void renum(Node * n, SSA * ssa)
00336   {
00337     renumber_walker rnw(ssa);
00338 
00339     n->walk(rnw);
00340   }
00341 
00342 private:
00343 
00344   SSA * ssa;
00345 
00346   renumber_walker(SSA * the_ssa)
00347     : Walker(Preorder, Subtree),
00348       ssa(the_ssa)
00349   {}
00350 
00351   void at_id(idNode * the_id, Order ord)
00352   {
00353     // --- Set the subscript to TOP(S(V)) by mapping the normal
00354     // declaration to the new sub-declaration that has the appropriate
00355     // index.
00356 
00357     ssa->record_index(the_id);
00358   }
00359 };
00360 
00361 // --- Useful predicates
00362 
00363 binaryNode * SSA::assignment(stmtNode * s)
00364 {
00365   if (s->typ() == Expr) {
00366     exprNode * e = ((exprstmtNode *) s)->expr();
00367     if (e && (e->typ() == Binary)) {
00368       binaryNode * the_binary = (binaryNode *) e;
00369       if (the_binary->op()->is_assignment())
00370         return the_binary;
00371     }
00372   }
00373 
00374   return 0;
00375 }
00376 
00377 idNode * SSA::lhs(stmtNode * s)
00378 {
00379   binaryNode * b = assignment(s);
00380 
00381   if (b && (b->left()->typ() == Id)) {
00382     idNode* id = (idNode*) b->left();
00383     if (need_ssa (id->decl()))
00384       return (idNode *) b->left();
00385   }  
00386   return 0;
00387 }
00388 
00389 callNode * SSA::phi(stmtNode * s)
00390 {
00391   binaryNode * b = assignment(s);
00392 
00393   if (b && (b->right()->typ() == Call)) {
00394     callNode * c = (callNode *) b->right();
00395     if (c->name()->typ() == Id) {
00396       idNode * id = (idNode *) c->name();
00397       if (id->name() == string("__phi"))
00398         return c;
00399     }
00400   }
00401 
00402   return 0;
00403 }
00404 
00405 // --- ssa is applied only on local variables and not on structs and unions
00406 
00407 bool SSA::need_ssa (declNode* decl) {
00408   declNode::Decl_location loc = decl->decl_location();
00409     
00410   if ( (loc == declNode::FORMAL || loc == declNode::BLOCK)
00411        && decl->storage_class() != declNode::TYPEDEF) {
00412     typeNode* t = decl->no_tdef_type();
00413 
00414     return (t && (t->typ() != Struct) && (t->typ() != Union));    
00415   }
00416   return false;  
00417 }
00418   
00419 // --- Renaming main function
00420 
00421 void SSA::search(basicblockNode * X)
00422 {
00423   // --- For each statement
00424 
00425   for (stmt_list_p p = X->stmts().begin();
00426        p != X->stmts().end();
00427        ++p)
00428     {
00429       stmtNode * s = *p;
00430       binaryNode * A = assignment(s);
00431       callNode * Phi = phi(s);
00432 
00433       // --- If the statement is an ordinary expr statement
00434 
00435       if ((s->typ() == Expr) && ! Phi) {
00436 
00437         if ( A && A->left()->typ() == Id ) {
00438 
00439           // -- For assignments, renumber only the right-hand side
00440 
00441           renumber_walker::renum(A->right(), this);
00442         }
00443         else {
00444 
00445           // -- For all others, renumber everything
00446 
00447           renumber_walker::renum(s, this);
00448         }
00449       }
00450 
00451       // --- Handle the conditional and return:
00452 
00453       if (s->typ() == If || s->typ() == Return)
00454         renumber_walker::renum(s, this);
00455 
00456       // --- Handle the left-hand side
00457 
00458       idNode * LHS = lhs(s);
00459 
00460       if (LHS) {
00461         declNode * de = LHS->decl();
00462         int i = Counter[de];
00463         Stack[de].push_front(i);
00464         record_index(LHS);
00465         Counter[de] = i + 1;
00466       }
00467     }
00468 
00469   // --- For each successor
00470 
00471   basicblock_list & bbl = X->succs();
00472 
00473   for (basicblock_list_p p = bbl.begin();
00474        p != bbl.end();
00475        ++p)
00476     {
00477       basicblockNode * Y = *p;
00478       int j = which_pred(Y, X);
00479       // cout << "Node " << X->dfn() << " is the " << j << " predecessor of " << Y->dfn() << endl;
00480 
00481       // --- For each Phi node in the sucessor
00482 
00483       for (stmt_list_p p = Y->stmts().begin();
00484            p != Y->stmts().end();
00485            ++p)
00486         {
00487           callNode * Phi = phi(*p);
00488           if (Phi) {
00489 
00490             // --- Set replace the jth operand with Vk, k = TOP(S(V))
00491             
00492             int i = 0;
00493             for (expr_list_p ap = Phi->args().begin();
00494                  ap != Phi->args().end();
00495                  ++ap, ++i)
00496               if (i == j) {
00497                 idNode * nid = (idNode *) (*ap);
00498                 declNode * de = nid->decl();
00499 
00500                 if ( ! Stack[de].empty()) {
00501                   record_index(nid);
00502                   // cout << "Set subscript on " << nid->name() << " = " << Stack[de].front() << endl;
00503                 }
00504                 break;
00505               }
00506           }
00507         }
00508     }
00509 
00510   // --- For each child (in the dominator tree)
00511 
00512   for (basicblock_list_p p = X->children().begin();
00513        p != X->children().end();
00514        ++p)
00515     search(*p);
00516 
00517   // --- For each assignment
00518 
00519   for (stmt_list_p p = X->stmts().begin();
00520        p != X->stmts().end();
00521        ++p)
00522     {
00523       stmtNode * s = *p;
00524       idNode * LHS = lhs(s);
00525       if (LHS) {
00526         declNode * de = LHS->decl();
00527         Stack[de].pop_front();
00528       }
00529     }
00530 }
00531 
00532 string SSA::name_with_index(string & name, int index)
00533 {
00534   // --- ostringstream is broken.
00535   // ostringstream ost;
00536   // ost << name << "@" << index;
00537   // ost.close();
00538   // return ost.str();
00539 
00540   char buf[256];
00541   sprintf(buf, "%s@%d", name.c_str(), index);
00542   return string(buf);
00543 }
00544 
00545 void SSA::rename_all_variables()
00546 {
00547   decl_decl_map NewDeclarations;
00548 
00549   // --- First create all the sub-declarations
00550 
00551   for (counter_map_p p = Counter.begin();
00552        p != Counter.end();
00553        ++p)
00554     {
00555       declNode * de = (*p).first;
00556       int max = (*p).second;
00557 
00558       NewDeclarations[de] = decl_vector(max);
00559 
00560       // SZG: Experiment -- only rename versions 1 and up. Leave the
00561       // regular variable as version 0. This ought to fix the problem
00562       // with formal parameters.
00563 
00564       for (int i = 1; i < max; ++i) {
00565 
00566         // --- Create new sub-declaration
00567 
00568         declNode * sde = new subdeclNode( de, i );
00569         sde->decl_location(declNode::BLOCK);
00570 
00571         // --- Store it in the vector
00572 
00573         NewDeclarations[de][i] = sde;
00574 
00575         // --- Add it to the top-level declarations
00576 
00577         _proc->body()->decls().push_back(sde);
00578       }
00579     }
00580 
00581   // --- Fix the variables that need indices (and corresponding new
00582   // declarations).
00583 
00584   for (var_changes_p p = Changes.begin();
00585        p != Changes.end();
00586        ++p)
00587     {
00588       idNode * id = (*p).first;
00589       int index = (*p).second;
00590       declNode * de = id->decl();
00591 
00592       // --- Replace it's declaration with a properly numbered
00593       // subdeclaration.
00594 
00595       if (index > 0) {
00596         subdeclNode * new_decl = (subdeclNode*) NewDeclarations[de][index];
00597 
00598         id->decl(new_decl);
00599         id->name(new_decl->name_with_index());
00600       }
00601     }
00602 }
00603 
00604 // ------------------------------------------------------------
00605 // Public access functions
00606 // ------------------------------------------------------------
00607 
00608 // Add a phi function to the given block for the given
00609 // variable. Return false if a phi function is already there.
00610 
00611 bool SSA::add_phi_function(declNode * d, basicblockNode * block)
00612 {
00613   // --- Make sure it doesn't already exist
00614 
00615   for (stmt_list_p p = block->stmts().begin();
00616        p != block->stmts().end();
00617        ++p)
00618     {
00619       callNode * Phi = phi(*p);
00620       idNode * id = lhs(*p);
00621 
00622       if (Phi && id && (id->decl() == d))
00623         return false;
00624     }
00625 
00626   place_one_phi(d, block);
00627 
00628   return true;
00629 }
00630 

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