|
OpenADFortTk (basic)
|
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 }