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  

memoryaccess.cc

Go to the documentation of this file.
00001 // $Id: memoryaccess.cc,v 1.28 2003/08/07 23:14:22 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 "memoryaccess.h"
00040 // #include <limits>
00041 
00042 /* #include "mergepoints.h" */
00043 
00044 // ------------------------------------------------------------
00045 // memoryAccess
00046 // ------------------------------------------------------------
00047 
00048 bool memoryAccess::Verbose = false;
00049 unsigned int memoryAccess::def_count = 0;
00050 unsigned int memoryAccess::use_count = 0;
00051 unsigned int memoryAccess::merge_use_count = 0;
00052 
00053 memoryAccess::memoryAccess(Location * where, memoryBlock * owner)
00054   : _where(where),
00055     _is_weak(false),
00056     _multiplicity(Unallocated),
00057     _search_for_def(true),
00058     _active(true),
00059     _owner(owner)
00060 {}
00061 
00062 void memoryAccess::stats()
00063 {
00064   cout << "  memoryDef : " << def_count << " objects x " 
00065        << sizeof(memoryDef) << " bytes = " << def_count * sizeof(memoryDef) 
00066        << " bytes. " << endl;
00067 
00068   cout << "  memoryUse : " << use_count << " objects x " 
00069        << sizeof(memoryUse) << " bytes = " << use_count * sizeof(memoryUse) 
00070        << " bytes. " << endl;
00071   cout << "  memoryuse_list : " << sizeof(memoryuse_list) << " bytes" << endl;
00072   cout << "  memoryblock_set : " << sizeof(memoryblock_set) << " bytes" << endl;
00073 }
00074 
00075 // ------------------------------------------------------------
00076 // memoryDef
00077 // ------------------------------------------------------------
00078 
00079 memoryDef::memoryDef(Location * where, memoryBlock * owner)
00080   : memoryAccess(where, owner),
00081     // _uses(),
00082     _points_to(),
00083     // _previous(),
00084     _value(0),
00085     _self_assign_use(0)
00086 {
00087   memoryAccess::def_count++;
00088 }
00089 
00090 // --- Destructor
00091 
00092 memoryDef::~memoryDef()
00093 {
00094   memoryAccess::def_count--;
00095 } 
00096 
00097 // --- Add a whole bunch of points-to edges
00098 
00099 void memoryDef::add_pointers(const memoryblock_set & mbs)
00100 {
00101   _points_to.insert(mbs.begin(), mbs.end());
00102 }
00103 
00104 void memoryDef::clear_points_to()
00105 {
00106   _points_to.clear();
00107 }
00108 
00109 // --- Output
00110 
00111 void memoryDef::print(ostream & o) const
00112 {
00113   o << "    Def at " << * where() << endl;
00114 
00115   /*
00116   for (memoryuse_list_cp p = _uses.begin();
00117        p != _uses.end();
00118        ++p)
00119     {
00120       o << "  ";
00121       (*p)->print(o);
00122     }
00123   */
00124 }
00125 
00126 // ------------------------------------------------------------
00127 // orderedDefs
00128 // ------------------------------------------------------------
00129 
00130 // --- Find the memoryDef for a given program location
00131 
00132 memoryDef * orderedDefs::find_def(Location * where)
00133 {
00134   memorydef_location_map_cp q = _quick_lookup.find(where);
00135 
00136   if (q != _quick_lookup.end())
00137     return (*q).second;
00138   else
00139     return 0;
00140 }
00141 
00142 // --- Find the nearest strictly dominating memoryDef
00143 
00144 memoryDef * orderedDefs::find_strictly_dominating_def(Location * where)
00145 {
00146   /*
00147   Pred_defs_strictly_dominates comparator(where);
00148   memorydef_list_cp p = find_if(_defs.begin(), _defs.end(), comparator);
00149 
00150   if (p == _defs.end())
00151     return 0;
00152   else
00153     return *p;
00154   */
00155 
00156   bool dominates = false;
00157   memoryDef * dominator = 0;
00158   Location * current = 0;
00159 
00160   int looking_for_subtree = where->subtree_id();
00161   unsigned int looking_for_min = where->tree_min();
00162   unsigned int looking_for_max = where->tree_max();
00163 
00164   // -- Regular case: search the list for a dominator
00165 
00166   memorydef_list_cp end = _defs.end();
00167   memorydef_list_cp p = _defs.begin();
00168 
00169   while (p != end) {
00170     const memorydef_key & key = (*p);
00171 
00172     current = key.location;
00173 
00174     if (current != where) {
00175 
00176       // dominates = Location::strictly_dominates(current, where);
00177 
00178       if (current->subtree_id() == looking_for_subtree) {
00179 
00180         unsigned int dom_min = current->tree_min();
00181         unsigned int dom_max = current->tree_max();
00182 
00183         if ((dom_min < looking_for_min) && (looking_for_max <= dom_max)) {
00184           dominator = key.def;
00185           break;
00186         }
00187       }
00188     }
00189 
00190     ++p;
00191   }
00192 
00193   return dominator;
00194 }
00195 
00196 // --- Find the nearest dominating memoryDef
00197 
00198 memoryDef * orderedDefs::find_dominating_def(Location * where)
00199 {
00200   /*
00201   Pred_defs_dominates comparator(where);
00202   memorydef_list_cp p = find_if(_defs.begin(), _defs.end(), comparator);
00203 
00204   if (p == _defs.end())
00205     return 0;
00206   else
00207     return *p;
00208   */
00209 
00210   bool dominates = false;
00211   memoryDef * dominator = 0;
00212   Location * current = 0;
00213 
00214   int looking_for_subtree = where->subtree_id();
00215   unsigned int looking_for_min = where->tree_min();
00216   unsigned int looking_for_max = where->tree_max();
00217 
00218   // if (looking_for_max == 0) looking_for_max = numeric_limits<unsigned int>::max();
00219 
00220   // -- Regular case: search the list for a dominator
00221 
00222   memorydef_list_cp end = _defs.end();
00223   memorydef_list_cp p = _defs.begin();
00224 
00225   while (p != end) {
00226     const memorydef_key & key = (*p);
00227 
00228     current = key.location;
00229 
00230     if (current == where) {
00231       dominator = key.def;
00232       break;
00233     }
00234 
00235     // dominates = Location::strictly_dominates(current, where);
00236 
00237     if (current->subtree_id() == looking_for_subtree) {
00238 
00239       unsigned int dom_min = current->tree_min();
00240       unsigned int dom_max = current->tree_max();
00241       
00242       // if (dom_max == 0) dom_max = numeric_limits<unsigned int>::max();
00243 
00244       if ((dom_min < looking_for_min) && (looking_for_max <= dom_max)) {
00245         dominator = key.def;
00246         break;
00247       }
00248     }
00249 
00250     ++p;
00251   }
00252 
00253   return dominator;
00254 }
00255 
00256 // --- Add a new memoryDef in the proper place, and return a pointer
00257 // to it. If there is already an entry for the given path, just return
00258 // that one.
00259 
00260 memoryDef * orderedDefs::make_def_at(Location * where, memoryBlock * owner, bool & is_new)
00261 {
00262   // --- First, see if it already exists
00263 
00264   is_new = false;
00265 
00266   memorydef_location_map_p q = _quick_lookup.find(where);
00267 
00268   if (q != _quick_lookup.end())
00269     return (*q).second;
00270 
00271   // --- Not there, so figure out where it should be
00272 
00273   if (memoryAccess::Verbose)
00274     cout << "make_def_at: dominator for " << * where << endl;
00275  
00276   //  Pred_defs_dominates comparator(where);
00277 
00278   bool dominates = false;
00279   memoryDef * dominator = 0;
00280   Location * current = 0;
00281 
00282   int looking_for_subtree = where->subtree_id();
00283   unsigned int looking_for_min = where->tree_min();
00284   unsigned int looking_for_max = where->tree_max();
00285 
00286   // if (looking_for_max == 0) looking_for_max = numeric_limits<unsigned int>::max();
00287 
00288   // -- Regular case: search the list for a dominator
00289 
00290   memorydef_list_p end = _defs.end();
00291   memorydef_list_p p = _defs.begin();
00292 
00293   while (p != end) {
00294     const memorydef_key & key = (*p);
00295 
00296     current = key.location;
00297 
00305     // dominates = Location::strictly_dominates(current, where);
00306 
00307     if (current->subtree_id() == looking_for_subtree) {
00308 
00309       unsigned int dom_min = current->tree_min();
00310       unsigned int dom_max = current->tree_max();
00311       
00312       // if (dom_max == 0) dom_max = numeric_limits<unsigned int>::max();
00313  
00314       if ((dom_min < looking_for_min) && (looking_for_max <= dom_max)) {
00315         dominator = key.def;
00316         break;
00317       }
00318     }
00319 
00320     ++p;
00321   }
00322 
00323   /*
00324   p = _defs.begin();
00325   while ((p != _defs.end()) &&  ! Location::dominates((*p)->where(), where)) {
00326 
00327     if (memoryAccess::Verbose)
00328       cout << "  NOT dominated by " << * (*p)->where() << endl;
00329 
00330     ++p;
00331   }
00332   */
00333   
00334   if (memoryAccess::Verbose)
00335     if (p != _defs.end())
00336       cout << "  dominated by " << * current << endl;
00337 
00338   // p = find_if(_defs.begin(), _defs.end(), comparator);
00339 
00340   // --- Add an entry with the proper path
00341 
00342   memoryDef * new_def = new memoryDef(where, owner);
00343 
00344   memorydef_key new_entry(new_def);
00345   _defs.insert(p, new_entry);
00346 
00347   _quick_lookup[where] = new_def;
00348     
00349   is_new = true;
00350 
00351   // --- Return a reference to the new element
00352 
00353   return new_def;
00354 }
00355 
00356 // --- Prune out unnecessary defs
00357 
00358 void orderedDefs::prune(orderedUses & Uses)
00359 {
00360   memorydef_list_p p = _defs.begin();
00361   memorydef_list_p to_remove;
00362 
00363   while (p != _defs.end()) {
00364     memoryDef * cur = (*p).def;
00365 
00366     to_remove = p;
00367     ++p;
00368 
00369     // --- Look for unused merges
00370 
00371     /*
00372     if (cur->uses().empty()
00373         // TBD: && mergePoints::is_merge_point(cur->where())
00374         )
00375       {
00376         _defs.erase(to_remove);
00377         Uses.prune(cur->where());
00378         // delete cur;
00379       }
00380     */
00381   }
00382 }
00383 
00384 // --- Output
00385 
00386 void orderedDefs::print(ostream & o) const
00387 {
00388   for (memorydef_list_cp p = _defs.begin();
00389        p != _defs.end();
00390        ++p)
00391     (*p).def->print(o);
00392 }
00393 
00394 // --- Clear
00395 
00396 void orderedDefs::clear()
00397 {
00398   for (memorydef_list_cp p = _defs.begin();
00399        p != _defs.end();
00400        ++p)
00401     delete (*p).def;
00402 
00403   _defs.clear();
00404 }
00405 
00406 // --- Stats
00407 
00408 void orderedDefs::stats(int & total_defs, int & merge_defs, int & weak_defs)
00409 {
00410   total_defs = 0;
00411   merge_defs = 0;
00412   weak_defs = 0;
00413 
00414   for (memorydef_list_p p = _defs.begin();
00415        p != _defs.end();
00416        ++p)
00417     {
00418       memoryDef * def = (*p).def;
00419 
00420       total_defs++;
00421 
00422       if (def->where()->kind() == Location::BasicBlock)
00423         merge_defs++;
00424 
00425       if (def->is_weak())
00426         weak_defs++;
00427     }
00428 }
00429 
00430 // ------------------------------------------------------------
00431 // memoryUse
00432 // ------------------------------------------------------------
00433 
00434 memoryUse::memoryUse(Location * where, memoryBlock * owner)
00435   : memoryAccess(where, owner),
00436     _reaching_def(0)
00437 {
00438   memoryAccess::use_count++;
00439 }
00440 
00441 // --- Destructor
00442 
00443 memoryUse::~memoryUse()
00444 {
00445   memoryAccess::use_count--;
00446 }
00447 
00448 void memoryUse::reaching_def(memoryDef * def)
00449 {
00450   if (memoryAccess::Verbose) {
00451     cout << "-> Use at " << * where();
00452 
00453     if (def)
00454       cout << " setting reaching def to " << * def->where();
00455     else
00456       cout << " no reaching def, ";
00457 
00458     if (_reaching_def)
00459       cout << " was " << * _reaching_def->where() << endl;
00460     else
00461       cout << " no previous reaching def" << endl;
00462   }
00463 
00464   _reaching_def = def;
00465 }
00466 
00467 // --- Output
00468 
00469 void memoryUse::print(ostream & o) const
00470 {
00471   o << "    Use at " << * where() << endl;
00472   o << "  ";
00473   if (_reaching_def)
00474     _reaching_def->print(o);
00475   else
00476     o << " (no reaching def)" << endl;
00477 }
00478 
00479 // ------------------------------------------------------------
00480 // orderedUses
00481 // ------------------------------------------------------------
00482 
00483 // --- Find an existing use for the given location (doesn't work for
00484 // merge/phi functions because it assumes that there is only one). If
00485 // it can't be found, return null.
00486 
00487 memoryUse * orderedUses::find_use(Location * where) const
00488 {
00489   if (where) {
00490     memoryuse_map_cp p = _uses.find(where);
00491     if (p != _uses.end())
00492       return (*p).second;
00493   }
00494 
00495   return 0;
00496 }
00497 
00498 // -- Find uses at (works for phi functions)
00499 
00500 void orderedUses::find_uses_at(Location * where, memoryuse_set & uses)
00501 {
00502   memoryUse * use;
00503 
00504   // -- Regular use
00505 
00506   use = find_use(where);
00507   if (use) {
00508     uses.insert(use);
00509     return;
00510   }
00511 
00512   // -- Merge use
00513 
00514   if (where->kind() == Location::BasicBlock) {
00515 
00516     basicblockLocation * bb = (basicblockLocation *) where;
00517 
00518     merge_use_map_p found = _merge_uses.find(bb);
00519     if (found != _merge_uses.end()) {
00520 
00521       pred_use_map & pum = (*found).second;
00522       
00523       for (pred_use_map_p p = pum.begin();
00524            p != pum.end();
00525            ++p)
00526         {
00527           uses.insert((*p).second);
00528         }
00529     }
00530   }
00531 }
00532 
00533 // --- Add a new use for the given location, or return the existing
00534 // one.
00535 
00536 memoryUse * orderedUses::make_use_at(Location * where, memoryBlock * owner)
00537 {
00538   // --- First, see if it already exists
00539 
00540   memoryUse * res = find_use(where);
00541   if ( ! res ) {
00542     res = new memoryUse(where, owner);
00543     _uses.insert(memoryuse_map_pair(where, res));
00544   }
00545 
00546   return res;
00547 }
00548 
00549 // --- Add a new set of uses for a particular merge point: one use
00550 // for each control-flow predecessor.
00551 
00552 const pred_use_map & orderedUses::make_merge_uses_at(basicblockLocation * where, memoryBlock * owner)
00553 {
00554   // --- Check to see if there is already a set of uses.
00555 
00556   merge_use_map_p found = _merge_uses.find(where);
00557   if (found == _merge_uses.end()) {
00558 
00559     // --- Not found, create one for each control-flow predecessor
00560 
00561     _merge_uses[where] = pred_use_map();
00562     found = _merge_uses.find(where);
00563     pred_use_map & new_uses = (*found).second;
00564 
00565     // --- Populate the predecessor map. Each use is paired with the
00566     // basicblock predecessor that it represents.
00567 
00568     basicblock_list & preds = where->block()->preds();
00569     for (basicblock_list_p p = preds.begin();
00570          p != preds.end();
00571          ++p) {
00572       memoryUse * use = new memoryUse(where, owner);
00573       new_uses[*p] = use;
00574     }
00575   }
00576 
00577   return (*found).second;
00578 }
00579 
00580 // --- Update the def-use chains (only performed once at the end of
00581 // analysis by the memoryModel).
00582 
00583 void orderedUses::update_def_use_chains()
00584 {
00585   memoryUse * use;
00586   memoryDef * def;
00587 
00588   for (memoryuse_map_p p = _uses.begin();
00589        p != _uses.end();
00590        ++p)
00591     {
00592       use = (*p).second;
00593       def = use->reaching_def();
00594       /*
00595       if (def)
00596         def->uses().push_back(use);
00597       */
00598     }
00599 
00600   for (merge_use_map_cp q = _merge_uses.begin();
00601        q != _merge_uses.end();
00602        ++q)
00603     {
00604       const pred_use_map & pred_uses = (*q).second;
00605 
00606       for (pred_use_map_cp w = pred_uses.begin();
00607            w != pred_uses.end();
00608            ++w)
00609         {
00610           use = (*w).second;
00611           def = use->reaching_def();
00612           /*
00613           if (def)
00614             def->uses().push_back(use);
00615           */
00616         }
00617     }
00618 }
00619 
00620 void orderedUses::def_uses(memoryDef * def,
00621                            memoryuse_list & uses)
00622 {
00623   for (memoryuse_map_p p = _uses.begin();
00624        p != _uses.end();
00625        ++p)
00626     {
00627       memoryUse * use = (*p).second;
00628       memoryDef * rdef = use->reaching_def();
00629       if (rdef == def)
00630         uses.push_back(use);
00631     }
00632 
00633   for (merge_use_map_cp q = _merge_uses.begin();
00634        q != _merge_uses.end();
00635        ++q)
00636     {
00637       const pred_use_map & pred_uses = (*q).second;
00638 
00639       for (pred_use_map_cp w = pred_uses.begin();
00640            w != pred_uses.end();
00641            ++w)
00642         {
00643           memoryUse * use = (*w).second;
00644           memoryDef * rdef = use->reaching_def();
00645           if (rdef == def)
00646             uses.push_back(use);
00647         }
00648     }
00649 }
00650 
00651 // --- Prune uses for a particular location
00652 
00653 void orderedUses::prune(Location * where)
00654 {
00655   // Find the use at this particular location
00656 
00657   memoryuse_map_p p = _uses.find(where);
00658 
00659   if (p != _uses.end()) {
00660 
00661     // Remove any references to it, and then delete it.
00662 
00663     memoryUse * use = (*p).second;
00664     memoryDef * def = use->reaching_def();
00665     if (def) {
00666 
00667       // Remove it from the uses list in the reaching definition
00668 
00669       memoryuse_list uses;
00670       /*
00671       def->owner()->def_uses(def, uses);
00672       memoryuse_list_p rem = find(uses.begin(), uses.end(), use);
00673       if (rem == uses.end()) {
00674         cout << "BAD BAD situation ";
00675         // def->owner()->print_def_use(cout);
00676         cout << endl;
00677       }
00678       else
00679         uses.erase(rem);
00680       */
00681     }
00682 
00683     // Delete the actual object
00684     
00685     delete use;
00686 
00687     // Remove the use pointers from the orderedUses list
00688 
00689     _uses.erase(p);
00690   }
00691 }
00692 
00693 // --- Output
00694 
00695 void orderedUses::print(ostream & o) const
00696 {
00697   for (memoryuse_map_cp p = _uses.begin();
00698        p != _uses.end();
00699        ++p)
00700     (*p).second->print(o);
00701 
00702   for (merge_use_map_cp q = _merge_uses.begin();
00703        q != _merge_uses.end();
00704        ++q)
00705     {
00706       const pred_use_map & pred_uses = (*q).second;
00707 
00708       for (pred_use_map_cp w = pred_uses.begin();
00709            w != pred_uses.end();
00710            ++w)
00711         (*w).second->print(o);
00712     }
00713 }
00714 
00715 // --- Clear
00716 
00717 void orderedUses::clear()
00718 {
00719   for (memoryuse_map_cp p = _uses.begin();
00720        p != _uses.end();
00721        ++p)
00722     delete (*p).second;
00723 
00724   for (merge_use_map_cp q = _merge_uses.begin();
00725        q != _merge_uses.end();
00726        ++q)
00727     {
00728       const pred_use_map & pred_uses = (*q).second;
00729 
00730       for (pred_use_map_cp w = pred_uses.begin();
00731            w != pred_uses.end();
00732            ++w)
00733         delete (*w).second;
00734     }
00735 
00736   _uses.clear();
00737   _merge_uses.clear();
00738 }
00739 
00740 // -- Stats
00741 
00742 void orderedUses::stats(int & total_uses, int & merge_uses)
00743 {
00744   merge_uses = _merge_uses.size();
00745   total_uses = _uses.size() + merge_uses;
00746 }
00747 
00748 // ----------------------------------------------------------------------
00749 //  Assignments
00750 // ----------------------------------------------------------------------
00751 
00752 memoryAssignment * assignmentSet::assignment_at(Location * where,
00753                                                 memoryBlock * block,
00754                                                 bool create)
00755 {
00756   assignment_key key(where, block);
00757 
00758   // -- See if it's already there
00759 
00760   assignment_map_p p = _assignments.find(key);
00761   if (p != _assignments.end())
00762     return (*p).second;
00763 
00764   // -- It's not there, should we create a new one?
00765 
00766   if (create) {
00767     memoryAssignment * result = new memoryAssignment(where);
00768     _assignments[key] = result;
00769     return result;
00770   }
00771 
00772   return 0;
00773 }

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