[llvm-commits] [parallel] CVS: llvm/lib/Transforms/Parallel/ParallelSeqExtractor.cpp

Misha Brukman brukman at cs.uiuc.edu
Fri May 7 16:39:01 PDT 2004


Changes in directory llvm/lib/Transforms/Parallel:

ParallelSeqExtractor.cpp added (r1.1.2.1)

---
Log message:

Extract parallel sequences into separate functions (aggregating arguments) so
that we can spawn off those functions as threads. Note: this does not properly
take care of cases where code is shared among parallel regions/sequences.


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

Index: llvm/lib/Transforms/Parallel/ParallelSeqExtractor.cpp
diff -c /dev/null llvm/lib/Transforms/Parallel/ParallelSeqExtractor.cpp:1.1.2.1
*** /dev/null	Fri May  7 16:39:13 2004
--- llvm/lib/Transforms/Parallel/ParallelSeqExtractor.cpp	Fri May  7 16:39:02 2004
***************
*** 0 ****
--- 1,148 ----
+ //===- PSeqExtractor.cpp - Pull parallel seqs into new functions ----------===//
+ // 
+ //                     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 implements the interface to tear out parallel seqs into a new
+ // function, replacing it with a call to the new function.
+ //
+ //===----------------------------------------------------------------------===//
+ 
+ #include "llvm/Instructions.h"
+ #include "llvm/Module.h"
+ #include "llvm/BasicBlock.h"
+ #include "llvm/Analysis/Dominators.h"
+ #include "llvm/Analysis/ParallelInfo.h"
+ #include "llvm/Transforms/Utils/FunctionUtils.h"
+ #include "llvm/Support/CFG.h"
+ #include "Support/Debug.h"
+ #include <vector>
+ using namespace llvm;
+ 
+ namespace {
+ 
+   /// PSeqExtractor - 
+   ///
+   /// FIXME: This should be a Pass, but Passes currently cannot require
+   /// FunctionPasses.
+   ///
+   struct PSeqExtractor : public FunctionPass {
+   public:
+     PSeqExtractor() {}
+ 
+     virtual void getAnalysisUsage(AnalysisUsage &AU) const {
+       AU.addRequired<DominatorSet>();
+       AU.addRequired<ParallelInfo>();
+     }
+     
+     bool runOnFunction(Function &F);
+   private:
+     bool containsThreadCall(BasicBlock *BB);
+   };
+ 
+   // FIXME: need to specify threshold level.. ie, up to 2 nested pseqs become
+   // new functions, then everything else sequential
+   RegisterOpt<PSeqExtractor>
+   X("pseq-extract", "Extract parallel seqs into new functions");
+ 
+ } // End anonymous namespace
+ 
+ static bool contains(std::vector<BasicBlock*> &haystack,
+                      BasicBlock *needle) {
+   return std::find(haystack.begin(), haystack.end(), needle) != haystack.end();
+ }
+ 
+ static void intersect(std::vector<BasicBlock*> &a,
+                       std::vector<BasicBlock*> &b,
+                       std::vector<BasicBlock*> &intersection) {
+   for (unsigned i = 0, e = a.size(); i != e; ++i)
+     for (unsigned j = 0, f = b.size(); j != f; ++j)
+       if (a[i] == b[j])
+         intersection.push_back(a[i]);
+ }
+ 
+ static BasicBlock* clone(BasicBlock *BB) {
+   BasicBlock *newBB = new BasicBlock(BB->getName(), BB->getParent());
+   for (BasicBlock::iterator i = BB->begin(), e = BB->end(); i != e; ++i)
+     newBB->getInstList().push_back(i->clone());
+   return newBB;
+ }
+ 
+ /// runOnFunction - 
+ ///
+ bool PSeqExtractor::runOnFunction(Function &F) {
+   bool Changed = false;
+   DEBUG(std::cerr << "Running on: " << F.getName() << "\n");
+   ParallelInfo &PI = getAnalysis<ParallelInfo>();
+   DominatorSet &DS = getAnalysis<DominatorSet>();
+ 
+ #if 0
+   // If there is shared code in the ParallelRegions, make copies
+   // 1. find intersecting code region
+   for (ParallelInfo::iterator i = PI.begin(), e = PI.end(); i != e; ++i) {
+     ParallelSeq *PS = *i;
+     ParallelRegion* PR[2];
+     unsigned i=0, e=0;
+     for (ParallelSeq::riterator r = PS->rbegin(), re = PS->rend(); 
+          r!=re; ++r, ++i) PR[i] = *r;
+     std::vector<BasicBlock*> Blocks0(PR[0]->begin(), PR[0]->end());
+     std::vector<BasicBlock*> Blocks1(PR[1]->begin(), PR[1]->end());
+     std::vector<BasicBlock*> Intersection;
+     intersect(Blocks0, Blocks1, Intersection);
+ 
+     // 2. for each basic block in shared code:
+     //      clone block
+     //      all incoming/outgoing edges to/from region0 stay,
+     //      all incoming/outgoing edges to/from region1 redirected to/from clone
+     for (i = 0, e = Intersection.size(); i != e; ++i) {
+       BasicBlock *I = Intersection[i];
+       BasicBlock *newBB = clone(I);
+       for (pred_iterator p = pred_begin(I), pe = pred_end(I); p != pe; ++p) {
+         BasicBlock *pred = *p;
+         if (contains(Blocks1, pred))
+           pred->getTerminator()->replaceUsesOfWith(I, newBB);
+       }
+       for (succ_iterator s = succ_begin(newBB), se = succ_end(newBB); s != se;
+            ++s) {
+         BasicBlock *succ = *s;
+         if (contains(Blocks1, succ)) {
+           BasicBlock *newSucc = clone(succ);
+           newBB->getTerminator()->replaceUsesOfWith(succ, newSucc);
+         }
+       }
+     }
+   }
+ #endif
+ 
+   // extract each code region to a new function
+   for (ParallelInfo::iterator i = PI.begin(), e = PI.end(); i != e; ++i) {
+     ParallelSeq *PS = *i;
+     for (ParallelSeq::riterator r = PS->rbegin(), re = PS->rend(); r!=re; ++r) {
+       Changed = true;
+       ParallelRegion *PR = *r;
+       std::vector<BasicBlock*> RegionBlocks(PR->begin(), PR->end());
+       if (RegionBlocks.empty()) continue;
+       if (containsThreadCall(RegionBlocks[0])) continue;
+       ExtractCodeRegion(DS, RegionBlocks, true /* aggregate args */);
+       for (std::vector<BasicBlock*>::iterator BBr = RegionBlocks.begin(),
+              BBre = RegionBlocks.end(); BBr != BBre; ++BBr)
+         PR->removeBasicBlock(*BBr);
+     }
+   }
+ 
+   return Changed;
+ }
+ 
+ bool PSeqExtractor::containsThreadCall(BasicBlock *BB) {
+   static const std::string llvmThreadFn("__llvm_thread_start");
+   for (BasicBlock::iterator i = BB->begin(), e = BB->end(); i != e; ++i)
+     if (CallInst *CI = dyn_cast<CallInst>(i))
+       if (CI->getCalledFunction()->getName() == llvmThreadFn)
+         return true;
+ 
+   return false;
+ }





More information about the llvm-commits mailing list