OpenADFortTk (basic)
src/lib/support/OAMaps.cxx
Go to the documentation of this file.
00001 #include "OpenAnalysis/CSFIActivity/ManagerDUGStandard.hpp"
00002 #include "OpenAnalysis/ReachDefs/ReachDefsStandard.hpp"
00003 
00004 #include "Open64IRInterface/Open64IRInterface.hpp"
00005 #include "OpenAnalysis/ICFG/ManagerICFG.hpp"
00006 
00007 #include "OAMaps.h"
00008 #include "WhirlParentize.h"
00009 #include "XAIFStrings.h"
00010 
00011 namespace fortTkSupport {
00012 
00013   OA::OA_ptr<OA::CFG::CFGInterface>
00014   CreateCFG(PU_Info* pu, 
00015             OA::OA_ptr<OA::CFG::EachCFGInterface> cfgeach,
00016             OA::OA_ptr<Open64IRInterface> irIF);
00017 
00018   static void
00019   MassageOACallGraphIntoXAIFCallGraph(OA::OA_ptr<OA::CallGraph::CallGraph> cg);
00020 
00021   static void
00022   AddControlFlowEndTags(PU_Info* pu, 
00023                         WhirlParentMap* wnParentMap, 
00024                         OA::OA_ptr<Open64IRInterface> irIF);
00025 
00026 
00027   static void
00028   MassageOACFGIntoXAIFCFG(OA::OA_ptr<OA::CFG::CFG> cfg,
00029                           OA::OA_ptr<Open64IRInterface> irIF);
00030 
00031 
00032   std::set<ST*> IntraOAInfo::ourActiveGlobalSTPSet;
00033   bool IntraOAInfo::ourDoNotFilterFlag=false; 
00034 
00035   IntraOAInfo::IntraOAInfo(PU_Info* pu, InterOAInfoMap* inter) { 
00036     OA::ProcHandle proc((OA::irhandle_t)pu);
00037     OA::OA_ptr<Open64IRInterface> irIF = inter->getIRInterface();
00038     OA::OA_ptr<OA::CFG::CFGInterface> cfg = inter->getCFGEach()->getCFGResults(proc);
00039     OA::OA_ptr<OA::SideEffect::InterSideEffectStandard> interSideEffect = inter->getInterSideEffect();
00040     FORTTK_MSG(2, "progress: retrieve intra alias from inter alias information");
00041     OA::OA_ptr<OA::Alias::Interface> intraAlias;
00042     intraAlias=inter->getInterAlias()->getAliasResults(proc);
00043     setAlias(intraAlias);
00044     FORTTK_MSG(2, "progress: reach defs: performAnalysis");
00045     OA::OA_ptr<OA::ReachDefsOverwrite::ManagerReachDefsOverwriteStandard> rdoman;
00046     rdoman = new OA::ReachDefsOverwrite::ManagerReachDefsOverwriteStandard(irIF);
00047     OA::OA_ptr<OA::ReachDefsOverwrite::ReachDefsOverwriteStandard> rdos 
00048       = rdoman->performAnalysis(proc, cfg, intraAlias, interSideEffect,OA::DataFlow::ITERATIVE);
00049     setReachDefsOverwrite(rdos);
00050     OA::OA_ptr<OA::ReachDefs::ReachDefsStandard> rds=rdos.convert<OA::ReachDefs::ReachDefsStandard>();
00051     FORTTK_MSG(2, "progress: uddu: performAnalysis");
00052     OA::OA_ptr<OA::UDDUChains::ManagerUDDUChainsStandard> udman;
00053     udman = new OA::UDDUChains::ManagerUDDUChainsStandard(irIF);
00054     OA::OA_ptr<OA::UDDUChains::UDDUChainsStandard> udduchains 
00055       = udman->performAnalysis(proc, intraAlias, rds, interSideEffect);
00056     // udduchains->dump(std::cout, irIF); 
00057     setUDDUChains(udduchains);
00058     FORTTK_MSG(2, "progress: alias to xaif: performAnalysis");
00059     OA::OA_ptr<OA::XAIF::ManagerAliasMapXAIF> aliasmanXAIF;
00060     aliasmanXAIF = new OA::XAIF::ManagerAliasMapXAIF(irIF);
00061     OA::OA_ptr<OA::XAIF::AliasMapXAIF> aliasXAIF = 
00062       aliasmanXAIF->performAnalysis(proc, intraAlias);
00063     setAliasXAIF(aliasXAIF);
00064     FORTTK_MSG(2, "progress: ud to xaif : performAnalysis");
00065     OA::OA_ptr<OA::XAIF::ManagerUDDUChainsXAIF> udmanXAIF;
00066     udmanXAIF = new OA::XAIF::ManagerUDDUChainsXAIF(irIF);
00067     OA::OA_ptr<OA::XAIF::UDDUChainsXAIF> udduchainsXAIF 
00068     = udmanXAIF->performAnalysis(cfg, udduchains,IntraOAInfo::getDoNotFilterFlag());
00069     //udduchainsXAIF->dump(std::cout, irIF);
00070     setUDDUChainsXAIF(udduchainsXAIF);
00071     FORTTK_MSG(2, "progress: overwrite to xaif : performAnalysis");
00072     OA::OA_ptr<OA::XAIF::ManagerReachDefsOverwriteXAIF> rdomanXAIF;
00073     rdomanXAIF = new OA::XAIF::ManagerReachDefsOverwriteXAIF(irIF);
00074     OA::OA_ptr<OA::XAIF::ReachDefsOverwriteXAIF> rdoXAIF
00075       = rdomanXAIF->performAnalysis(cfg, getReachDefsOverwrite());
00076     //rdoXAIF->dump(std::cout, irIF);
00077     setReachDefsOverwriteXAIF(rdoXAIF);
00078   };
00079 
00080   void IntraOAInfo::setDoNotFilterFlag() { 
00081     ourDoNotFilterFlag=true;
00082   }
00083   
00084   bool IntraOAInfo::getDoNotFilterFlag() { 
00085     return ourDoNotFilterFlag;
00086   }
00087 
00088   void
00089   InterOAInfoMap::init(PU_Info* pu_forest, OA::OA_ptr<Open64IRInterface> irIF,
00090                        bool activeWithVariedOnly) {
00091     assert(pu_forest);
00092     setIRInterface(irIF);
00093     OA::OA_ptr<Open64IRProcIterator> procIt;
00094     procIt = new Open64IRProcIterator(pu_forest);
00095     // Create CFGs [FIXME: and perform MemRefExprKludge]
00096     // first Create CFG 'manager' (compute CFG on demand)
00097     OA::OA_ptr<OA::CFG::ManagerCFGStandard> cfgman;
00098     cfgman = new OA::CFG::ManagerCFGStandard(getIRInterface());
00099     OA::OA_ptr<OA::CFG::EachCFGInterface> cfgeach;
00100     cfgeach = new OA::CFG::EachCFGStandard(cfgman);
00101     FORTTK_MSG(1, "progress: CreateCFG");
00102     for ( ; procIt->isValid(); ++(*procIt)) { 
00103       PU_Info* pu = (PU_Info*)procIt->current().hval();
00104       OA::OA_ptr<OA::CFG::CFGInterface> cfg = CreateCFG(pu, cfgeach, getIRInterface());
00105     }
00106     setCFGEach(cfgeach);
00107     // Inter Alias 
00108     procIt->reset();
00109     FORTTK_MSG(1, "progress: inter alias: performAnalysis");
00110     OA::OA_ptr<OA::Alias::ManagerFIAliasAliasMap> interaliasmapman;
00111     interaliasmapman = new OA::Alias::ManagerFIAliasAliasMap(getIRInterface());
00112     OA::OA_ptr<OA::Alias::InterAliasMap> interAlias;
00113     interAlias = interaliasmapman->performAnalysis(procIt);
00114     setInterAlias(interAlias);
00115     // Create call graph
00116     FORTTK_MSG(1, "progress: call graph: performAnalysis");
00117     // Create call graph (massage OA version into XAIF version below)
00118     procIt->reset();
00119     OA::OA_ptr<OA::CallGraph::ManagerCallGraphStandard> cgraphman;
00120     cgraphman = new OA::CallGraph::ManagerCallGraphStandard(getIRInterface());
00121     OA::OA_ptr<OA::CallGraph::CallGraph> cgraph = 
00122       cgraphman->performAnalysis(procIt,interAlias);
00123     if (0) { cgraph->dump(std::cout, getIRInterface()); }
00124     setCallGraph(cgraph);
00125     // -------------------------------------------------------
00126     // Compute interprocedural analysis info
00127     // -------------------------------------------------------
00128     FORTTK_MSG(1, "progress: parameter bindings: performAnalysis");
00129     // ParamBindings
00130     OA::OA_ptr<OA::DataFlow::ManagerParamBindings> parambindman;
00131     parambindman = new OA::DataFlow::ManagerParamBindings(getIRInterface());
00132     OA::OA_ptr<OA::DataFlow::ParamBindings> parambind
00133       = parambindman->performAnalysis(cgraph);
00134     setParamBind(parambind);
00135     //   // JU: begin debugging stuff
00136     //   procIt->reset();
00137     //   for ( ; procIt->isValid(); ++(*procIt)) { 
00138     //     OA::OA_ptr<OA::SymHandleIterator> symHandleI=parambind->getFormalIterator(procIt->current());
00139     //     symHandleI->reset();
00140     //     ST* st = ST_ptr(PU_Info_proc_sym((PU_Info*)procIt->current().hval()));
00141     //     const char* nm = ST_name(st);
00142     //     if (!symHandleI->isValid())
00143     //       std::cout << "Note: after performAnalysis: empty symHandleI for " << nm << std::endl;
00144     //     else { 
00145     //       for ( ; symHandleI->isValid(); ++(*symHandleI)) { 
00146     //  ST* st1 = (ST*)(symHandleI->current().hval());
00147     //  const char* nm1 = ST_name(st1);
00148     //  std::cout << "Note: after performAnalysis: symHandleI for " 
00149     //            << nm 
00150     //            << " contains " 
00151     //            << nm1 
00152     //            <<  std::endl;
00153     //       }
00154     //     }
00155     //   }
00156     //   // JU: end debugging stuff
00157     // Side Effect
00158     FORTTK_MSG(1, "progress: side effect: performAnalysis");
00159     OA::OA_ptr<OA::SideEffect::ManagerSideEffectStandard> sideeffectman;
00160     sideeffectman = new OA::SideEffect::ManagerSideEffectStandard(getIRInterface());
00161     // Inter Side Effect
00162     FORTTK_MSG(1, "progress: inter side effect: performAnalysis");
00163     OA::OA_ptr<OA::SideEffect::ManagerInterSideEffectStandard> interSEman;
00164     interSEman = new OA::SideEffect::ManagerInterSideEffectStandard(getIRInterface());
00165     OA::OA_ptr<OA::SideEffect::InterSideEffectStandard> interSE;
00166     interSE = interSEman->performAnalysis(cgraph, parambind, interAlias, sideeffectman, OA::DataFlow::ITERATIVE);
00167     setInterSideEffect(interSE);
00168     // ICFG
00169     FORTTK_MSG(1, "progress: icfg standard: performAnalysis");
00170     OA::OA_ptr<OA::ICFG::ManagerICFGStandard> icfgman;
00171     icfgman = new OA::ICFG::ManagerICFGStandard(getIRInterface());
00172     OA::OA_ptr<OA::ICFG::ICFG> icfg 
00173       = icfgman->performAnalysis(procIt,cfgeach,cgraph);
00174     // Def-Use Graph
00175     FORTTK_MSG(1, "progress: DUG standard: building Def-Use graph");
00176     OA::OA_ptr<OA::DUG::ManagerDUGStandard> dugman;
00177     dugman = new OA::DUG::ManagerDUGStandard(getIRInterface(), getIRInterface());
00178     OA::OA_ptr<OA::DUG::DUGStandard> dug
00179       = dugman->performAnalysis(procIt, parambind, cgraph);
00180     dugman->transitiveClosureDepMatrix(cgraph);
00181     // #define DEBUG_DUAA_LAST 1
00182 #ifdef DEBUG_DUAA_LAST
00183     dug->dumpdot(cout, getIRInterface());
00184 #endif
00185     // Def-Use Activity Analysis
00186     FORTTK_MSG(1, "progress: Def-Use activity: performAnalysis");
00187     OA::OA_ptr<OA::Activity::ManagerDUActive> duactiveman;
00188     duactiveman = new OA::Activity::ManagerDUActive(getIRInterface(), dug);
00189     OA::OA_ptr<OA::Activity::InterActiveFortran> duactive;
00190     duactive = duactiveman->performAnalysis(parambind, activeWithVariedOnly);
00191 #ifdef DEBUG_DUAA
00192     duactive->dump(cout, getIRInterface());
00193 #endif
00194     setInterActiveFortran(duactive);
00195     //   // this is only for context sensitive analysis
00196     //     OAAnalInfo::collectGlobalSymbolActivityInfo(active,
00197     //                                          interAlias,
00198     //                                          getIRInterface(),
00199     //                                          pu_forest);
00200     // -------------------------------------------------------
00201     // For each PU, compute intraprocedural analysis info
00202     // -------------------------------------------------------
00203     FORTTK_MSG(1, "progress: intraprocedural analysis");
00204     procIt->reset();
00205     for ( ; procIt->isValid(); ++(*procIt)) { 
00206       PU_Info* pu = (PU_Info*)procIt->current().hval();
00207       ST* st = ST_ptr(PU_Info_proc_sym(pu));
00208       const char* nm = ST_name(st);
00209       FORTTK_MSG(1, "progress: analyzing compile unit " << nm );
00210       IntraOAInfo* info = new IntraOAInfo(pu, this);
00211       Insert(pu, info);
00212     }
00213     // -------------------------------------------------------
00214     // Post-analysis
00215     // -------------------------------------------------------
00216     // massage the Call Graph into something that XAIF can use
00217     FORTTK_MSG(1, "progress: call graph: massage for XAIF");
00218     MassageOACallGraphIntoXAIFCallGraph(cgraph);
00219     // fix up the CFGs
00220     procIt->reset();
00221     for ( ; procIt->isValid(); ++(*procIt)) { 
00222       PU_Info* pu = (PU_Info*)procIt->current().hval();
00223       OA::ProcHandle proc((OA::irhandle_t)pu);
00224       OA::OA_ptr<OA::CFG::CFGInterface> cfgIF = cfgeach->getCFGResults(proc);
00225       OA::OA_ptr<OA::CFG::CFG> cfg = cfgIF.convert<OA::CFG::CFG>();
00226       MassageOACFGIntoXAIFCFG(cfg,getIRInterface());
00227     }
00228   }
00229 
00230 
00231   OA::OA_ptr<OA::CFG::CFGInterface>
00232   CreateCFG(PU_Info* pu, OA::OA_ptr<OA::CFG::EachCFGInterface> cfgeach,
00233             OA::OA_ptr<Open64IRInterface> irIF)
00234   {
00235     OA::ProcHandle proc((OA::irhandle_t)pu);
00236 
00237     // FIXME: This should probably be a global puinfo->parentmmap map
00238     WN *wn_pu = PU_Info_tree_ptr(pu);
00239     WhirlParentMap wnParentMap(wn_pu);
00240 
00241     // -------------------------------------------------------
00242     // CFG
00243     // -------------------------------------------------------  
00244     AddControlFlowEndTags(pu, &wnParentMap, irIF);
00245   
00246     OA::OA_ptr<OA::CFG::CFGInterface> cfgIF = cfgeach->getCFGResults(proc);
00247     OA::OA_ptr<OA::CFG::CFG> cfg = cfgIF.convert<OA::CFG::CFG>();
00248     if (0) { cfg->dump(std::cout, irIF); }
00249         // cfg->dump(std::cout, irIF); 
00250     return cfg;
00251   }
00252 
00253   // MassageOACallGraphIntoXAIFCallGraph: Process CallGraph to eliminate
00254   // synthetic edges.
00255   //   - eliminate special Open64 functions and inlinable intrinsics
00256   //   - need to figure out what to do with non-inlinable intrinsics
00257   //  
00258   static void
00259   MassageOACallGraphIntoXAIFCallGraph(OA::OA_ptr<OA::CallGraph::CallGraph> cg) {
00260     using namespace OA::CallGraph;
00261     DGraphNodeList toRemove; 
00262     OA::OA_ptr<OA::DGraph::NodesIteratorInterface> it = cg->getNodesIterator();
00263     for( ; it->isValid(); ++(*it)) {
00264       OA::OA_ptr<OA::DGraph::NodeInterface> dn = it->current();
00265       OA::OA_ptr<Node> n = dn.convert<Node>();
00266       if (n->getProc().hval() == 0) {
00267         FORTTK_DIAGIF_DEV(2) {
00268           ST* st = (ST*)n->getProcSym().hval();
00269           std::cout << "* Removing '" << ST_name(st) << "' from CallGraph\n";
00270         }
00271         toRemove.push_back(n);
00272       }
00273     }
00274     for (DGraphNodeList::iterator it = toRemove.begin(); it != toRemove.end(); ++it) {
00275       OA::OA_ptr<OA::DGraph::NodeInterface> n = (*it);
00276       cg->removeNode(n);
00277     }
00278     toRemove.clear();
00279   }
00280 
00281 
00282   // ***************************************************************************
00283 
00284   // AddControlFlowEndTags: Add control flow end tags
00285   // FIXME: assumes fully structured control flow???
00286   static void
00287   AddControlFlowEndTags(PU_Info* pu, WhirlParentMap* wnParentMap, 
00288                         OA::OA_ptr<Open64IRInterface> irIF) {
00289     // FIXME: we should be skipping most expression sub trees like
00290     // interface to NewOA.
00291     WN* wn = PU_Info_tree_ptr(pu);
00292     WN_TREE_CONTAINER<PRE_ORDER> wtree(wn);
00293     WN_TREE_CONTAINER<PRE_ORDER>::iterator it;
00294     for (it = wtree.begin(); it != wtree.end(); ++it) {
00295       WN* curWN = it.Wn();
00296       OPERATOR opr = WN_operator(curWN);
00297       const char* vty = GetCFGControlFlowVertexType(curWN);
00298       if (!vty) { continue; }
00299       // Find structured (and some unstructured) control flow and insert
00300       // placehoder statement.
00301       if (vty == XAIFStrings.elem_BBForLoop() || 
00302           vty == XAIFStrings.elem_BBPostLoop() ||
00303           vty == XAIFStrings.elem_BBPreLoop()) {
00304         // do (...)
00305         //   ...
00306         // * EndLoop
00307         // enddo
00308         WN* loopBodyWN = NULL;
00309         if (opr == OPR_DO_LOOP) { 
00310           loopBodyWN = WN_do_body(curWN); 
00311         } else {
00312           loopBodyWN = WN_while_body(curWN);
00313         }
00314         WN* newWN = WN_CreateComment((char*)XAIFStrings.elem_BBEndLoop());
00315         WN_INSERT_BlockLast(loopBodyWN, newWN);
00316         // the new WN must be added to the context map.
00317         irIF->setContext((OA::irhandle_t)newWN, (OA::irhandle_t)pu);
00318       }
00319       else if (vty == XAIFStrings.elem_BBBranch()) {
00320         WN* ipWN = NULL;
00321         if (opr == OPR_SWITCH) {
00322           //   switch(...) [unstructured]
00323           //     casegoto L2
00324           //     casegoto L3
00325           //   end
00326           //   L2 ... L3 ...
00327           //   L1 (branch-around-label: beginning of code after switch)
00328           // * EndBranch
00329           INT32 lbl = WN_last_label(curWN);
00330           for (WN* x = WN_next(curWN); x; x = WN_next(x)) {
00331             if (WN_operator(x) == OPR_LABEL && WN_label_number(x) == lbl) {
00332               ipWN = x;
00333               break;
00334             }
00335           }
00336         } 
00337         else {
00338           //   if (...) { ... }  OR   if (...) goto77 [unstructured]
00339           //   else { ... }         * EndBranch      
00340           //   endif                                
00341           // * EndBranch
00342           ipWN = curWN;
00343         }
00344         if (ipWN) {
00345           WN* blkWN = wnParentMap->FindBlock(ipWN);
00346           WN* newWN = WN_CreateComment((char*)XAIFStrings.elem_BBEndBranch());
00347           // 'newWN' after 'ipWN' which is either the parent of the last label block 
00348           // or the parent of the branch. 
00349           WN_INSERT_BlockAfter(blkWN, ipWN, newWN); 
00350           // the new WN must be added to the context map.
00351           irIF->setContext((OA::irhandle_t)newWN, (OA::irhandle_t)pu);
00352         }
00353       }
00354     }
00355   }
00356 
00357 
00358   // MassageOACFGIntoXAIFCFG: Convert an OpenAnalysis CFG into a valid
00359   // XAIF CFG.  
00360   // 
00361   // 1. OpenAnalysis creates basic blocks with labels at the beginning
00362   // and branches at the end.  E.g. for TWOWAY_CONDITIONAL and
00363   // MULTIWAY_CONDITIONAL statements OpenAnalysis may generate BBs such
00364   // as:
00365   //
00366   // Code:                   | BBs:
00367   //   x = 5                 |          x = 5
00368   //   if (x .eq. 5) then    |          if (x .eq. 5)
00369   //     x = 6               |       _______/\_________
00370   //   else                  |      /                  \   
00371   //     x = 7               |  x = 6                  x = 7
00372   //   ...                   |      \-------  ---------/   
00373   //                         |              \/
00374   //                         |            ......
00375   // 
00376   // While OA creates correct BBs, in order to create valid XAIF, the
00377   // first BB must be split so that the if condition can be placed
00378   // within xaif:If.  We create a new BB here so that the translation
00379   // into XAIF is easy:
00380   // 
00381   //   <xaif:BasicBlock>
00382   //     <xaif:Assignment...
00383   //     </xaif:Asignment>
00384   //   </xaif:BasicBlock>
00385   // 
00386   //   <xaif:Branch>
00387   //     <xaif:Condition...
00388   //     </xaif:Condition>
00389   //   </xaif:If>
00390   // 
00391   // 2. OpenAnalysis places the initialization and update nodes of
00392   // OPR_DO_LOOPs in the appropriate BB: they are virtually (but not
00393   // really) spliced out of the OPR_DO_LOOPs.  For example an
00394   // OPR_DO_LOOP node with initialization, condition, update, and a
00395   // block of statements may become:
00396   //
00397   //                   ....
00398   //                   DO_LOOP initialization
00399   //                              |
00400   //                              v
00401   //                      DO_LOOP condition <--------------|
00402   //                      _______/\________                |
00403   //                     /                 \               |
00404   //                    |            DO_LOOP statements    |
00405   //                    |            DO_LOOP update     ---| 
00406   //                    v
00407   //                  .....
00408   //
00409   // Because XAIF can preserve and exploit high level control strucures
00410   // such as OPR_DO_LOOP, we want to *remove* the initialization and
00411   // update statement so they can be placed in the special xaif:ForLoop
00412   // construct.  xaif2whirl also depends on this transformation.
00413   //
00414   // [When xaif2whirl deletes the translation interval for the first BB
00415   // above (for subsequent replacement), it actually deletes the whole
00416   // OPR_DO_LOOP node!  Testing for special conditions doesn't help much
00417   // because when WHIRL is created from the new XAIF, we do not know how to
00418   // replace the deleted loop initialization node.]
00419   //
00420   // 3. Split basic blocks with EndLoop and EndBranch tags.  EndLoop and
00421   // EndBranch are taged statements inserted into WHIRL so that
00422   // corresponding CFG nodes will identify structured loops and
00423   // branches.  Since EndLoops and EndBranches must be mpty BBs we must
00424   // split any would in them into BasicBlocks.
00425   // 
00426   static void
00427   MassageOACFGIntoXAIFCFG(OA::OA_ptr<OA::CFG::CFG> cfg,
00428                           OA::OA_ptr<Open64IRInterface> irIF) {
00429     typedef std::list< pair<CFGNodeList::iterator, WN*> > MySplitList;
00430     //DGraphNodeList workList;  
00431     CFGNodeList workList;  
00432     MySplitList toSplit; // nodes to split
00433     OA::OA_ptr<OA::DGraph::NodesIteratorInterface> nodeItTmp; 
00434     // -------------------------------------------------------
00435     // 1. Find BBs with conditionals and split them
00436     // -------------------------------------------------------
00437     // a. Collect all BBs with more that one stmt into 'workList'
00438     nodeItTmp = cfg->getNodesIterator();
00439     for ( ; nodeItTmp->isValid(); ++(*nodeItTmp)) {
00440       OA::OA_ptr<OA::DGraph::NodeInterface> dn = nodeItTmp->current();
00441       OA::OA_ptr<OA::CFG::NodeInterface> n = dn.convert<OA::CFG::NodeInterface>();
00442       if ( (n->size() > 1) ) { 
00443         workList.push_back(n);
00444       }
00445     }
00446     // b. Iterate over 'workList' nodes.  For each node examine the
00447     // statements.  If a conditional is found at the end of the BB,
00448     // split it.  A block will only need to be split at most once.
00449     for (CFGNodeList::iterator wnodeIt = workList.begin(); 
00450          wnodeIt != workList.end(); ++wnodeIt) {
00451       OA::OA_ptr<OA::CFG::NodeInterface> n = (*wnodeIt);
00452       OA::OA_ptr<OA::CFG::NodeStatementsIteratorInterface> stmtItPtr
00453         = n->getNodeStatementsIterator();
00454       for (; stmtItPtr->isValid(); ++(*stmtItPtr)) {
00455         OA::StmtHandle stmt = stmtItPtr->current();
00456         OA::CFG::IRStmtType ty = irIF->getCFGStmtType(stmt);
00457         if (ty == OA::CFG::STRUCT_TWOWAY_CONDITIONAL
00458             || ty == OA::CFG::USTRUCT_TWOWAY_CONDITIONAL_T
00459             || ty == OA::CFG::USTRUCT_TWOWAY_CONDITIONAL_F
00460             || ty == OA::CFG::STRUCT_MULTIWAY_CONDITIONAL
00461             || ty == OA::CFG::USTRUCT_MULTIWAY_CONDITIONAL) {
00462           toSplit.push_back(make_pair(wnodeIt, (WN*)stmt.hval()));
00463           break;
00464         }
00465       }
00466     }
00467     // c. Split blocks
00468     for (MySplitList::iterator it = toSplit.begin(); it != toSplit.end(); ++it) {
00469       CFGNodeList::iterator wnodeIt = (*it).first;
00470       OA::OA_ptr<OA::CFG::NodeInterface> ntmp = *wnodeIt;
00471       OA::OA_ptr<OA::CFG::Node> n = ntmp.convert<OA::CFG::Node>();
00472       WN* startWN = (*it).second;
00473       OA::StmtHandle stmt((OA::irhandle_t)startWN);
00474       OA::OA_ptr<OA::CFG::Node> newblock = cfg->splitBlock(n, stmt);
00475       cfg->connect(n, newblock, OA::CFG::FALLTHROUGH_EDGE);
00476     }
00477     toSplit.clear();
00478     // d. clear 'workList'
00479     workList.clear();
00480     // -------------------------------------------------------
00481     // 2. Recover OPR_DO_LOOPs
00482     // -------------------------------------------------------
00483     // This process can create empty basic blocks
00484     CFGNodeList toRemove; // basic blocks made empty (slated for removal)
00485     nodeItTmp = cfg->getNodesIterator();
00486     for ( ; nodeItTmp->isValid(); ++(*nodeItTmp)) {
00487       OA::OA_ptr<OA::DGraph::NodeInterface> dn = nodeItTmp->current();
00488       OA::OA_ptr<OA::CFG::Node> n = dn.convert<OA::CFG::Node>();
00489       // Use CFG nodes representing the OPR_DO_LOOP condition to find
00490       // initialization and update information.  With this info, remove
00491       // the 'copied' initialization and update statements from whatever BB they
00492       // may be in because the  original ones are loop node children anyway. 
00493       // New basic blocks are not created.
00494       // FIXME: use a better classification method 
00495       if (GetCFGVertexType(cfg, n) == XAIFStrings.elem_BBForLoop()) {
00496         assert(n->size() == 1);
00497         OA::OA_ptr<OA::CFG::NodeStatementsIteratorInterface> stmtItPtr = n->getNodeStatementsIterator();
00498         OA::StmtHandle loopStmt = stmtItPtr->current();
00499         WN* loopWN = (WN *)loopStmt.hval();
00500         WN* initWN = WN_start(loopWN);
00501         WN* updateWN = WN_step(loopWN);
00502         // FIXME: this is a terrible way of doing this, because we 
00503         // should only have to iterate over a subgraph but at least this 
00504         // ensures  correctness
00505         OA::OA_ptr<OA::DGraph::NodesIteratorInterface> nodeIt1Ptr = cfg->getNodesIterator();
00506         for (; nodeIt1Ptr->isValid(); ++(*nodeIt1Ptr)) {
00507           OA::OA_ptr<OA::DGraph::NodeInterface> dn1 = nodeIt1Ptr->current();
00508           OA::OA_ptr<OA::CFG::Node> n1 = dn1.convert<OA::CFG::Node>();
00509           OA::OA_ptr<OA::CFG::NodeStatementsIteratorInterface> stmtIt1Ptr = n1->getNodeStatementsIterator();
00510           for (; stmtIt1Ptr->isValid(); ++(*stmtIt1Ptr)) {
00511             OA::StmtHandle st = stmtIt1Ptr->current();
00512             WN* wn = (WN*)st.hval();
00513             if ((wn == initWN) || (wn == updateWN)) {
00514               n1->erase(OA::StmtHandle((OA::irhandle_t)wn));
00515               if (n1->size() == 0 && wn == updateWN) {
00516                 toRemove.push_back(n1); // ONLY erase update 
00517               }                         // [EndLoop] --> [update] --backedge-->
00518               break;
00519             }
00520           }
00521         }
00522       }
00523     }
00524     // Remove basic blocks 
00525     for (CFGNodeList::iterator it = toRemove.begin(); 
00526          it != toRemove.end(); ++it) {
00527       OA::OA_ptr<OA::CFG::NodeInterface> n = *it;
00528       // Find predecessor node.  If more than one, we cannot do it 
00529       if (n->num_incoming() > 1) {
00530         continue;
00531       } 
00532       OA::OA_ptr<OA::DGraph::NodeInterface> predI = n->getSourceNodesIterator()->current();
00533       OA::OA_ptr<OA::CFG::Node> pred = predI.convert<OA::CFG::Node>();
00534       // All outgoing edges of 'n' become outgoing edges of 'pred'
00535       OA::OA_ptr<OA::DGraph::EdgesIteratorInterface> outEdgeItPtr = n->getOutgoingEdgesIterator();
00536       for ( ; outEdgeItPtr->isValid(); ++(*outEdgeItPtr)) {
00537         OA::OA_ptr<OA::DGraph::EdgeInterface> de = outEdgeItPtr->current();
00538         OA::OA_ptr<OA::CFG::Edge> e = de.convert<OA::CFG::Edge>();
00539         OA::OA_ptr<OA::DGraph::NodeInterface> dsnk = e->getSink();
00540         OA::OA_ptr<OA::CFG::Node> snk = dsnk.convert<OA::CFG::Node>();
00541         cfg->connect(pred, snk, e->getType());
00542       }
00543       cfg->removeNode(n); // removes all outgoing and incoming edges
00544     }
00545     toRemove.clear();
00546     // -------------------------------------------------------
00547     // 3. Split basic blocks with EndLoop and EndBranch tags
00548     // -------------------------------------------------------
00549     // Notes:
00550     //  - EndBranch statments will be the first or second statment
00551     //   (switches) of a basic block; EndLoop at the end.
00552     //  - Some blocks will have to be split more than once, requiring an
00553     //    iterative algoritihm. E.g.
00554     //      EndBr
00555     //      Assignment
00556     //      EndLoop
00557     // uses 'workList'
00558     // uses 'toSplit'
00559     std::list<CFGNodeList::iterator> toRem;
00560     // a. Collect all BBs with more that one stmt into 'workList'
00561     nodeItTmp = cfg->getNodesIterator();
00562     for ( ; nodeItTmp->isValid(); ++(*nodeItTmp)) {
00563       OA::OA_ptr<OA::DGraph::NodeInterface> dn = nodeItTmp->current();
00564       OA::OA_ptr<OA::CFG::Node> n = dn.convert<OA::CFG::Node>(); 
00565       if ( (n->size() > 1) ) { 
00566         workList.push_back(n);
00567       }
00568     }
00569     // b. Iterate until 'workList' is empty (fixed-point is reached).  
00570     // Each node in the worklist is guaranteed to have more than one stmt.
00571     while (!workList.empty()) {
00572       for (CFGNodeList::iterator wnodeIt = workList.begin(); 
00573            wnodeIt != workList.end(); ++wnodeIt) {
00574         OA::OA_ptr<OA::CFG::NodeInterface> ntmp = *wnodeIt;
00575         OA::OA_ptr<OA::CFG::Node> n = ntmp.convert<OA::CFG::Node>();
00576         // 1. Find split-point for this node.  If there is none, remove it
00577         // from 'workList'
00578       restart_loop:
00579         WN* bbSplitPointWN = NULL; // start of new basic block
00580         unsigned int stmtcount = 1;
00581         OA::OA_ptr<OA::CFG::NodeStatementsIteratorInterface> stmtIt = n->getNodeStatementsIterator();
00582         for (; stmtIt->isValid(); ++(*stmtIt), ++stmtcount) {
00583           OA::StmtHandle st = stmtIt->current();
00584           WN* wn = (WN*)st.hval();
00585           const char* vty = GetCFGControlFlowVertexType(wn);
00586           if (vty == XAIFStrings.elem_BBEndBranch()) {
00587             // If EndBranch is not the first stmt, move it to the
00588             // beginning and restart the loop
00589             if (stmtcount > 1) {
00590               n->erase(OA::StmtHandle((OA::irhandle_t)wn));
00591               n->add_front(OA::StmtHandle((OA::irhandle_t)wn));
00592               goto restart_loop;
00593             }
00594             ++(*stmtIt); // advance iterator to find start of new basic block
00595             assert(stmtIt->isValid());
00596             bbSplitPointWN = (WN*)stmtIt->current().hval();
00597             break;
00598           }
00599           else if (vty == XAIFStrings.elem_BBEndLoop()) {
00600             bbSplitPointWN = wn;
00601             break;
00602           }
00603         }
00604         if (bbSplitPointWN) {
00605           toSplit.push_back(make_pair(wnodeIt, bbSplitPointWN));
00606         } else {
00607           toRem.push_back(wnodeIt);
00608         }
00609       }
00610       // 2. Split basic blocks
00611       for (MySplitList::iterator it = toSplit.begin(); 
00612            it != toSplit.end(); ++it) {
00613         CFGNodeList::iterator wnodeIt = (*it).first;
00614         OA::OA_ptr<OA::CFG::NodeInterface> ntmp = *wnodeIt;
00615         OA::OA_ptr<OA::CFG::Node> n = 
00616           ntmp.convert<OA::CFG::Node>();
00617         WN* startWN = (*it).second;
00618         OA::StmtHandle stmt((OA::irhandle_t)startWN);
00619         OA::OA_ptr<OA::CFG::Node> newblock = cfg->splitBlock(n, stmt);
00620         cfg->connect(n, newblock, OA::CFG::FALLTHROUGH_EDGE);
00621         // Remove BBs with less than 1 stmt; add others
00622         if (newblock->size() > 1) {
00623           workList.push_back(newblock);
00624         }
00625         if ( !(n->size() > 1) ) {
00626           toRem.push_back(wnodeIt);
00627         }
00628       }
00629       toSplit.clear();
00630       // 3. Remove nodes from 'workList'
00631       for (std::list<CFGNodeList::iterator>::iterator it = toRem.begin(); 
00632            it != toRem.end(); ++it) {
00633         workList.erase(*it); // *it is type CFGNodeList::iterator
00634       }
00635       toRem.clear();
00636     }
00637   }
00638 
00639   // ***************************************************************************
00640 
00641   class CollectModVars_ST_TAB {
00642   public:
00643     CollectModVars_ST_TAB(std::map<std::string, ST*>* modSymNmMap_,
00644                           std::set<ST*>* modSymDup_)
00645       : modSymNmMap(modSymNmMap_), modSymDup(modSymDup_)
00646     { } 
00647 
00648     // A function object applied to every entry of a ST_TAB
00649     void operator()(UINT32 idx, ST* st) const 
00650     { 
00651       // If 'st' is from a module or a module variable...
00652       if (ST_is_in_module(st)) {
00653         // If 'st' is actually a module variable
00654         if (!ST_is_external(st)) {
00655           modSymNmMap->insert(make_pair(std::string(ST_name(st)), st));
00656         } 
00657         else {
00658           modSymDup->insert(st);
00659         }
00660       }
00661     }
00662   
00663   private:
00664     std::map<std::string, ST*>* modSymNmMap; // map of bona-fide modules symbols
00665     std::set<ST*>* modSymDup;                // 'duplicated' module symbols
00666   };
00667 
00668   // ***************************************************************************
00669 
00670   // GetCFGVertexType: A CFG vertex is either an Entry, Exit,
00671   // BasicBlock, or a special structured control flow vertex (e.g., Branch,
00672   // ForLoop, PreLoop, PostLoop).  The string returned is from
00673   // 'XAIFStrings' which means users can compare on pointer value
00674   // (instead of using strcmp()).
00675   //
00676   // Vertices are classified by the statements contained within.  Since
00677   // the classifications are mutually exclusive, a vertex should not
00678   // contain two statements that correspond to structured control flow.
00679   //
00680   // FIXME: we know that loop and if BBs should only have one node in
00681   // them. because of MassageOA...
00682   const char*
00683   GetCFGVertexType(OA::OA_ptr<OA::CFG::CFGInterface> cfg, 
00684                    OA::OA_ptr<OA::CFG::NodeInterface> n)
00685   {
00686     using namespace OA::CFG;
00687 
00688     // We know these are cheap so they can be recomputed each time we are called
00689     OA::OA_ptr<NodeInterface> entry = cfg->getEntry();
00690     OA::OA_ptr<NodeInterface> exit = cfg->getExit();
00691   
00692     if (n == entry) {
00693       return XAIFStrings.elem_BBEntry();
00694     } else if (n == exit) { 
00695       return XAIFStrings.elem_BBExit();
00696     }
00697   
00698     // FIXME: we do not need to iterate over all statements since
00699     // control flow statements contructs will be in their own xaif:BB.
00700     OA::OA_ptr<OA::CFG::NodeStatementsIteratorInterface> stmtIt
00701       = n->getNodeStatementsIterator();
00702     for (; stmtIt->isValid(); ++(*stmtIt)) {
00703       OA::StmtHandle st = stmtIt->current();
00704       WN* wstmt = (WN*)st.hval();
00705       const char* vty = GetCFGControlFlowVertexType(wstmt);
00706       if (vty) { 
00707         return vty; 
00708       }
00709     }
00710   
00711     return XAIFStrings.elem_BB(); // default, non-structured type
00712   }
00713 
00714 
00715   // GetCFGControlFlowVertexType: If the WHIRL statement corresponds to a
00716   // CFG *control flow* vertex, return that type.  Otherwise return NULL.
00717   // Returns strings from XAIFStrings.
00718   const char*
00719   GetCFGControlFlowVertexType(WN* wstmt)
00720   {
00721     OPERATOR opr = WN_operator(wstmt);
00722     switch (opr) {
00723     
00724       // In OA, loop nodes represent the *condition* (not the body).
00725       // For a DO_LOOP, it additionally represents the initialization
00726       // and update statements.
00727     case OPR_DO_LOOP: 
00728       return XAIFStrings.elem_BBForLoop();
00729     case OPR_DO_WHILE: 
00730       return XAIFStrings.elem_BBPostLoop();
00731     case OPR_WHILE_DO:
00732       return XAIFStrings.elem_BBPreLoop();
00733 
00734       // In OA, IF nodes represent the *condition* (not the body)
00735     case OPR_IF:
00736     case OPR_TRUEBR:   // unstructured
00737     case OPR_FALSEBR:  // unstructured
00738       return XAIFStrings.elem_BBBranch();
00739     case OPR_SWITCH:   // unstructured
00740     case OPR_COMPGOTO: // unstructured
00741       return XAIFStrings.elem_BBBranch();
00742     
00743       // Currently we use special comments to denote EndBranch and EndLoop
00744     case OPR_COMMENT: 
00745       {
00746         static const char* endbr = XAIFStrings.elem_BBEndBranch();
00747         static const char* endlp = XAIFStrings.elem_BBEndLoop();
00748         const char* com = Index_To_Str(WN_GetComment(wstmt));
00749         if (strcmp(com, endbr) == 0) {
00750           return endbr;
00751         } else if (strcmp(com, endlp) == 0) {
00752           return endlp;
00753         }
00754         // fall through
00755       }
00756     
00757     default: 
00758       break; // fall through
00759     }
00760   
00761     return NULL;
00762   }
00763 
00764 //   void 
00765 //   OAAnalInfo::collectGlobalSymbolActivityInfo(OA::OA_ptr<OA::Activity::InterActiveFortran> active,
00766 //                                            OA::OA_ptr<OA::Alias::InterAliasMap> interAlias,
00767 //                                            OA::OA_ptr<Open64IRInterface> irIF,
00768 //                                            PU_Info* pu_forest) {
00769 //     // Collect module variables
00770 //     std::map<std::string, ST*> modSymNmMap; // map of bona-fide modules symbols
00771 //     std::set<ST*> modSymDup;                // 'duplicated' module symbols
00772 //     CollectModVars_ST_TAB collectModVars(&modSymNmMap, &modSymDup);
00773 //     For_all(St_Table, GLOBAL_SYMTAB, collectModVars);
00774 //     // For each 'duplicated' module variable that is active, make sure
00775 //     // the true module variable is activated.
00776 //     std::map<std::string, ST*>::iterator it = modSymNmMap.begin();
00777 //     // iterate through all global (module) variables
00778 //     for ( ; it != modSymNmMap.end(); ++it) {
00779 //       bool isActive=false;
00780 //       ST* st_p = (*it).second;
00781 
00782 //       // debug begin -----
00783 //       char* symbolName = ST_name(st_p);
00784 //       std::cout << "JU: OAAnalInfo::collectGlobalSymbolActivityInfo: for symbol name: " << symbolName << std::endl; 
00785 //       // debug end ----
00786 
00787 //       // make an memory reference expression from the given symbol
00788 //       OA::SymHandle sym = OA::SymHandle((OA::irhandle_t)st_p) ; 
00789 //       OA::OA_ptr<OA::MemRefExpr> symMRE = irIF->convertSymToMemRefExpr(sym);
00790 //       // iterate through all PUs
00791 //       OA::OA_ptr<Open64IRProcIterator> procIt;
00792 //       procIt = new Open64IRProcIterator(pu_forest);
00793 //       for ( ; procIt->isValid() && !isActive; ++(*procIt)) { 
00794 
00795 //      // debug begin -----
00796 //      ST* procST_p = ST_ptr(PU_Info_proc_sym((PU_Info*)procIt->current().hval()));
00797 //      const char* procName = ST_name(procST_p);
00798 //      std::cout << "JU: OAAnalInfo::collectGlobalSymbolActivityInfo: looking in: " << procName << " : "; 
00799 //      // debug end -----
00800         
00801 //      OA::OA_ptr<OA::LocIterator> symMRElocs_I = 
00802 //        interAlias->getAliasResults(procIt->current())->getMayLocs(*symMRE,procIt->current());
00803 //      // we now have the locations that may alias the symbol and  need to compare these 
00804 //      // against the locations determined to be active by the activity analysis. 
00805 //      for ( ; symMRElocs_I->isValid() && !isActive; (*symMRElocs_I)++ ) {
00806 //        OA::OA_ptr<OA::LocIterator> activeLoc_I = active->getActiveLocsIterator(procIt->current());
00807 //        for ( ; activeLoc_I->isValid() && !isActive; (*activeLoc_I)++ ) {
00808 //          if (activeLoc_I->current()->mayOverlap(*(symMRElocs_I->current()))) {
00809 //            ourActiveGlobalSTPSet.insert(st_p);
00810 //            isActive=true;
00811 //            std::cout << " active "; 
00812 //          }
00813 //        }
00814 //      }
00815 //      std::cout << std::endl; 
00816 //       }
00817 //     }
00818 //   }
00819 
00820   bool 
00821   IntraOAInfo::isGlobalSymbolActive(ST* anST_p) {
00822     return (ourActiveGlobalSTPSet.find(anST_p)!=ourActiveGlobalSTPSet.end());
00823   } 
00824 
00825 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines