[llvm-commits] [parallel] CVS: llvm/lib/Analysis/ParallelInfo.cpp

Misha Brukman brukman at cs.uiuc.edu
Sun Feb 8 00:42:04 PST 2004


Changes in directory llvm/lib/Analysis:

ParallelInfo.cpp added (r1.1.2.1)

---
Log message:

Implementation of the parallel region/sequence analysis.


---
Diffs of the changes:  (+195 -0)

Index: llvm/lib/Analysis/ParallelInfo.cpp
diff -c /dev/null llvm/lib/Analysis/ParallelInfo.cpp:1.1.2.1
*** /dev/null	Sun Feb  8 00:41:39 2004
--- llvm/lib/Analysis/ParallelInfo.cpp	Sun Feb  8 00:41:29 2004
***************
*** 0 ****
--- 1,195 ----
+ //===- ParallelInfo.cpp - Parallel Sequence Calculator --------------------===//
+ // 
+ //                     The LLVM Compiler Infrastructure
+ //
+ // This file was developed by the LLVM research group and is distributed under
+ // the University of Illinois Open Source License. See LICENSE.TXT for details.
+ // 
+ //===----------------------------------------------------------------------===//
+ //
+ // This file defines the ParallelInfo class that is used to identify parallel
+ // code blocks and code sequences within the CFG. It should make transformations
+ // and parallel code generation easier.
+ //
+ //===----------------------------------------------------------------------===//
+ 
+ #include "llvm/iOther.h"
+ #include "llvm/iTerminators.h"
+ #include "llvm/Analysis/ParallelInfo.h"
+ #include "llvm/Analysis/Dominators.h"
+ #include "llvm/Support/CFG.h"
+ #include "Support/Debug.h"
+ #include "Support/DepthFirstIterator.h"
+ #include "Support/StringExtras.h"
+ #include <algorithm>
+ #include <vector>
+ 
+ namespace llvm {
+ 
+ static RegisterAnalysis<ParallelInfo>
+ X("paraseq", "Parallel Sequence Construction", true);
+ 
+ //===----------------------------------------------------------------------===//
+ // ParallelRegion implementation
+ //
+ 
+ bool ParallelRegion::contains(const BasicBlock *BB) {
+   return std::find(Blocks.begin(), Blocks.end(), BB) != Blocks.end();
+ }
+ 
+ void ParallelRegion::removeBasicBlock(BasicBlock *BB) {
+   iterator BBe = Blocks.end();
+   iterator BBi = std::find(Blocks.begin(), BBe, BB);
+   assert(BBi != BBe && "Attempting to delete block not in region!");
+   Blocks.erase(BBi);
+ }
+ 
+ void ParallelRegion::print(std::ostream &os) {
+   for (const_iterator i = const_begin(), e = const_end(); i != e; ++i) {
+     os << (*i)->getName() << " ";
+   }
+ }
+ 
+ ParallelRegion* ParallelRegion::discoverRegion(BasicBlock *pbrBlock,
+                                                BasicBlock *begin,
+                                                BasicBlock *end) {
+   ParallelRegion *PR = new ParallelRegion();
+   
+   // accumulate all the basic blocks in the subtree following to the first
+   // join worklist algorithm. assumption: no shared code between parallel
+   // regions.
+   std::vector<BasicBlock*> Worklist;
+   DEBUG(std::cerr << "begin: " << begin->getName() << "\n");
+   Worklist.push_back(begin);
+ 
+   while (!Worklist.empty()) {
+     BasicBlock *BB = Worklist.back();
+     DEBUG(std::cerr << "processing: " << BB->getName() << "\n");
+     Worklist.pop_back();
+     PR->addBasicBlock(BB);
+ 
+     TerminatorInst *TI = BB->getTerminator();
+     // Add all successors to the worklist
+     if (BranchInst *BI = dyn_cast<BranchInst>(TI)) {
+       for (unsigned i = 0, e = BI->getNumSuccessors(); i != e; ++i) {
+         BasicBlock *succ = BI->getSuccessor(i);
+         DEBUG(std::cerr << "successor: " << succ->getName() << "\n");
+         if (succ != pbrBlock && succ != end && !PR->contains(succ) &&
+             std::find(Worklist.begin(), Worklist.end(), succ) == Worklist.end())
+           Worklist.push_back(succ);
+       }
+     } else if (SwitchInst *SI = dyn_cast<SwitchInst>(TI)) {
+       assert(0 && "switch not handled within parallel region");
+     } else if (ReturnInst *RI = dyn_cast<ReturnInst>(TI)) {
+       assert(0 && "return not handled within parallel region");
+     } else if (ParaBrInst *PB = dyn_cast<ParaBrInst>(TI)) {
+       assert(0 && "pbr not handled within parallel region");
+     } else {
+       assert(0 && "<unknown terminator> not handled within parallel region");
+     }
+   } 
+ 
+   return PR;
+ }
+ 
+ 
+ //===----------------------------------------------------------------------===//
+ // ParallelSeq implementation
+ //
+ 
+ /// contains - Return true of the specified basic block is in this loop
+ ///
+ bool ParallelSeq::contains(const BasicBlock *BB) const {
+   for (region_iterator i = region_begin(), e = region_end(); i != e; ++i)
+     if ((*i)->contains(BB))
+       return true;
+   return false;
+ }
+ 
+ void ParallelSeq::print(std::ostream &os, unsigned Depth) const {
+   unsigned region = 0;
+   if (SeqHeader)
+     os << "header: " << SeqHeader->getName() << "\n";
+   for (region_iterator i = region_begin(), e = region_end(); i != e;
+        ++i, ++region)
+   {
+     os << utostr(region) << " ";
+     (*i)->print(os);
+     os << "\n";
+   }
+ }
+ 
+ void ParallelSeq::dump() const {
+   print(std::cerr);
+ }
+ 
+ 
+ //===----------------------------------------------------------------------===//
+ // ParallelInfo implementation
+ //
+ 
+ bool ParallelInfo::runOnFunction(Function &) {
+   Calculate(getAnalysis<DominatorSet>());
+   return false;
+ }
+ 
+ void ParallelInfo::Calculate(const DominatorSet &DS) {
+   BasicBlock *RootNode = DS.getRoot();
+ 
+   for (df_iterator<BasicBlock*> NI = df_begin(RootNode),
+ 	 NE = df_end(RootNode); NI != NE; ++NI)
+     if (ParallelSeq *PS = ConsiderParallelSeq(*NI, DS))
+       TopLevelSeqs.push_back(PS);
+ }
+ 
+ ParallelSeq*
+ ParallelInfo::ConsiderParallelSeq(BasicBlock *BB, const DominatorSet &DS) {
+   // if this block has a pbr
+   bool bbHasPbr = false;
+   ParaBrInst *PBr = 0;
+   for (BasicBlock::iterator i = BB->begin(), e = BB->end(); i != e; ++i) {
+     if ((PBr = dyn_cast<ParaBrInst>(i))) {
+       bbHasPbr = true;
+       break;
+     }
+   }
+ 
+   if (!bbHasPbr) return 0;
+ 
+   // process each successor tree separately into regions, and combine them
+   // into a parallel sequence
+ 
+   // The last instruction of the pbr BasicBlock is the pbr that spawned the
+   // regionStart, so find the join instruction correlated to it and hence the
+   // end basic block for the region.
+   Value::use_iterator join = PBr->use_begin();
+   CallInst *call = dyn_cast<CallInst>(*join);
+   // FIXME: make sure the call is to "llvm.join" intrinsic
+   assert(call && "Value returned by pbr used in something not a call to join!");
+   BasicBlock *end = call->getParent();
+ 
+   ParallelRegion *PR0 =
+     ParallelRegion::discoverRegion(PBr->getParent(), PBr->getSuccessor(0), end);
+   DEBUG(std::cerr << "PR0: "; PR0->print(std::cerr); std::cerr << "\n";);
+   ParallelRegion *PR1 =
+     ParallelRegion::discoverRegion(PBr->getParent(), PBr->getSuccessor(1), end);
+   DEBUG(std::cerr << "PR1: "; PR1->print(std::cerr); std::cerr << "\n";);
+ 
+   // construct a parallel sequence
+   ParallelSeq *PS = new ParallelSeq(PR0, PR1);
+ 
+   return PS;
+ }
+   
+ 
+ void ParallelInfo::getAnalysisUsage(AnalysisUsage &AU) const {
+   AU.setPreservesAll();
+   AU.addRequired<DominatorSet>();
+ }
+ 
+ void ParallelInfo::print(std::ostream &OS) const {
+   for (unsigned i = 0; i < TopLevelSeqs.size(); ++i)
+     TopLevelSeqs[i]->print(OS);
+ }
+ 
+ } // End llvm namespace





More information about the llvm-commits mailing list