[llvm-commits] [polly] r148814 - /polly/trunk/lib/CodeGeneration.cpp

Tobias Grosser grosser at fim.uni-passau.de
Tue Jan 24 08:42:32 PST 2012


Author: grosser
Date: Tue Jan 24 10:42:32 2012
New Revision: 148814

URL: http://llvm.org/viewvc/llvm-project?rev=148814&view=rev
Log:
CodeGen: Separate declaration and definition of ClastStmtCodeGen

Modified:
    polly/trunk/lib/CodeGeneration.cpp

Modified: polly/trunk/lib/CodeGeneration.cpp
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/CodeGeneration.cpp?rev=148814&r1=148813&r2=148814&view=diff
==============================================================================
--- polly/trunk/lib/CodeGeneration.cpp (original)
+++ polly/trunk/lib/CodeGeneration.cpp Tue Jan 24 10:42:32 2012
@@ -925,185 +925,42 @@
 
 public:
 
-  const std::vector<std::string> &getParallelLoops() {
-    return parallelLoops;
-  }
+  const std::vector<std::string> &getParallelLoops();
 
   protected:
-  void codegen(const clast_assignment *a) {
-    (*clastVars)[a->LHS] = ExpGen.codegen(a->RHS,
-      TD->getIntPtrType(Builder.getContext()));
-  }
+  void codegen(const clast_assignment *a);
 
   void codegen(const clast_assignment *a, ScopStmt *Statement,
                unsigned Dimension, int vectorDim,
-               std::vector<ValueMapT> *VectorVMap = 0) {
-    Value *RHS = ExpGen.codegen(a->RHS,
-      TD->getIntPtrType(Builder.getContext()));
-
-    assert(!a->LHS && "Statement assignments do not have left hand side");
-    const PHINode *PN;
-    PN = Statement->getInductionVariableForDimension(Dimension);
-    const Value *V = PN;
-
-    if (VectorVMap)
-      (*VectorVMap)[vectorDim][V] = RHS;
-
-    ValueMap[V] = RHS;
-  }
+               std::vector<ValueMapT> *VectorVMap = 0);
 
   void codegenSubstitutions(const clast_stmt *Assignment,
                             ScopStmt *Statement, int vectorDim = 0,
-                            std::vector<ValueMapT> *VectorVMap = 0) {
-    int Dimension = 0;
-
-    while (Assignment) {
-      assert(CLAST_STMT_IS_A(Assignment, stmt_ass)
-             && "Substitions are expected to be assignments");
-      codegen((const clast_assignment *)Assignment, Statement, Dimension,
-              vectorDim, VectorVMap);
-      Assignment = Assignment->next;
-      Dimension++;
-    }
-  }
+                            std::vector<ValueMapT> *VectorVMap = 0);
 
   void codegen(const clast_user_stmt *u, std::vector<Value*> *IVS = NULL,
-               const char *iterator = NULL, isl_set *scatteringDomain = 0) {
-    ScopStmt *Statement = (ScopStmt *)u->statement->usr;
-    BasicBlock *BB = Statement->getBasicBlock();
-
-    if (u->substitutions)
-      codegenSubstitutions(u->substitutions, Statement);
-
-    int vectorDimensions = IVS ? IVS->size() : 1;
-
-    VectorValueMapT VectorValueMap(vectorDimensions);
-
-    if (IVS) {
-      assert (u->substitutions && "Substitutions expected!");
-      int i = 0;
-      for (std::vector<Value*>::iterator II = IVS->begin(), IE = IVS->end();
-           II != IE; ++II) {
-        (*clastVars)[iterator] = *II;
-        codegenSubstitutions(u->substitutions, Statement, i, &VectorValueMap);
-        i++;
-      }
-    }
+               const char *iterator = NULL, isl_set *scatteringDomain = 0);
 
-    BlockGenerator Generator(Builder, ValueMap, VectorValueMap, *Statement,
-                             scatteringDomain);
-    Generator.copyBB(BB, DT);
-  }
-
-  void codegen(const clast_block *b) {
-    if (b->body)
-      codegen(b->body);
-  }
+  void codegen(const clast_block *b);
 
   /// @brief Create a classical sequential loop.
   void codegenForSequential(const clast_for *f, Value *LowerBound = 0,
-                                                Value *UpperBound = 0) {
-    APInt Stride;
-    PHINode *IV;
-    Value *IncrementedIV;
-    BasicBlock *AfterBB, *HeaderBB, *LastBodyBB;
-    Type *IntPtrTy;
-
-    Stride = APInt_from_MPZ(f->stride);
-    IntPtrTy = TD->getIntPtrType(Builder.getContext());
-
-    // The value of lowerbound and upperbound will be supplied, if this
-    // function is called while generating OpenMP code. Otherwise get
-    // the values.
-    assert(!!LowerBound == !!UpperBound && "Either give both bounds or none");
-
-    if (LowerBound == 0) {
-        LowerBound = ExpGen.codegen(f->LB, IntPtrTy);
-        UpperBound = ExpGen.codegen(f->UB, IntPtrTy);
-    }
-
-    createLoop(&Builder, LowerBound, UpperBound, Stride, IV, AfterBB,
-               IncrementedIV, DT);
-
-    // Add loop iv to symbols.
-    (*clastVars)[f->iterator] = IV;
-
-    if (f->body)
-      codegen(f->body);
-
-    // Loop is finished, so remove its iv from the live symbols.
-    clastVars->erase(f->iterator);
-
-    HeaderBB = *pred_begin(AfterBB);
-    LastBodyBB = Builder.GetInsertBlock();
-    Builder.CreateBr(HeaderBB);
-    IV->addIncoming(IncrementedIV, LastBodyBB);
-    Builder.SetInsertPoint(AfterBB);
-  }
+                                                Value *UpperBound = 0);
 
   /// @brief Add a new definition of an openmp subfunction.
-  Function *addOpenMPSubfunction(Module *M) {
-    Function *F = Builder.GetInsertBlock()->getParent();
-    std::vector<Type*> Arguments(1, Builder.getInt8PtrTy());
-    FunctionType *FT = FunctionType::get(Builder.getVoidTy(), Arguments, false);
-    Function *FN = Function::Create(FT, Function::InternalLinkage,
-                                    F->getName() + ".omp_subfn", M);
-    // Do not run any polly pass on the new function.
-    SD->markFunctionAsInvalid(FN);
-
-    Function::arg_iterator AI = FN->arg_begin();
-    AI->setName("omp.userContext");
-
-    return FN;
-  }
+  Function *addOpenMPSubfunction(Module *M);
 
   /// @brief Add values to the OpenMP structure.
   ///
   /// Create the subfunction structure and add the values from the list.
   Value *addValuesToOpenMPStruct(SetVector<Value*> OMPDataVals,
-                                 Function *SubFunction) {
-    std::vector<Type*> structMembers;
-
-    // Create the structure.
-    for (unsigned i = 0; i < OMPDataVals.size(); i++)
-      structMembers.push_back(OMPDataVals[i]->getType());
-
-    StructType *structTy = StructType::get(Builder.getContext(),
-                                           structMembers);
-    // Store the values into the structure.
-    Value *structData = Builder.CreateAlloca(structTy, 0, "omp.userContext");
-    for (unsigned i = 0; i < OMPDataVals.size(); i++) {
-      Value *storeAddr = Builder.CreateStructGEP(structData, i);
-      Builder.CreateStore(OMPDataVals[i], storeAddr);
-    }
-
-    return structData;
-  }
+                                 Function *SubFunction);
 
   /// @brief Create OpenMP structure values.
   ///
   /// Create a list of values that has to be stored into the subfuncition
   /// structure.
-  SetVector<Value*> createOpenMPStructValues() {
-    SetVector<Value*> OMPDataVals;
-
-    // Push the clast variables available in the clastVars.
-    for (CharMapT::iterator I = clastVars->begin(), E = clastVars->end();
-         I != E; I++)
-     OMPDataVals.insert(I->second);
-
-    // Push the base addresses of memory references.
-    for (Scop::iterator SI = S->begin(), SE = S->end(); SI != SE; ++SI) {
-      ScopStmt *Stmt = *SI;
-      for (SmallVector<MemoryAccess*, 8>::iterator I = Stmt->memacc_begin(),
-           E = Stmt->memacc_end(); I != E; ++I) {
-        Value *BaseAddr = const_cast<Value*>((*I)->getBaseAddr());
-        OMPDataVals.insert((BaseAddr));
-      }
-    }
-
-    return OMPDataVals;
-  }
+  SetVector<Value*> createOpenMPStructValues();
 
   /// @brief Extract the values from the subfunction parameter.
   ///
@@ -1111,371 +968,574 @@
   /// variables to point to the new values.
   void extractValuesFromOpenMPStruct(CharMapT *clastVarsOMP,
                                      SetVector<Value*> OMPDataVals,
-                                     Value *userContext) {
-    // Extract the clast variables.
-    unsigned i = 0;
-    for (CharMapT::iterator I = clastVars->begin(), E = clastVars->end();
-         I != E; I++) {
-      Value *loadAddr = Builder.CreateStructGEP(userContext, i);
-      (*clastVarsOMP)[I->first] = Builder.CreateLoad(loadAddr);
-      i++;
-    }
-
-    // Extract the base addresses of memory references.
-    for (unsigned j = i; j < OMPDataVals.size(); j++) {
-      Value *loadAddr = Builder.CreateStructGEP(userContext, j);
-      Value *baseAddr = OMPDataVals[j];
-      ValueMap[baseAddr] = Builder.CreateLoad(loadAddr);
-    }
-
-  }
+                                     Value *userContext);
 
   /// @brief Add body to the subfunction.
   void addOpenMPSubfunctionBody(Function *FN, const clast_for *f,
                                 Value *structData,
-                                SetVector<Value*> OMPDataVals) {
-    Module *M = Builder.GetInsertBlock()->getParent()->getParent();
-    LLVMContext &Context = FN->getContext();
-    IntegerType *intPtrTy = TD->getIntPtrType(Context);
-
-    // Store the previous basic block.
-    BasicBlock *PrevBB = Builder.GetInsertBlock();
-
-    // Create basic blocks.
-    BasicBlock *HeaderBB = BasicBlock::Create(Context, "omp.setup", FN);
-    BasicBlock *ExitBB = BasicBlock::Create(Context, "omp.exit", FN);
-    BasicBlock *checkNextBB = BasicBlock::Create(Context, "omp.checkNext", FN);
-    BasicBlock *loadIVBoundsBB = BasicBlock::Create(Context, "omp.loadIVBounds",
-                                                    FN);
-
-    DT->addNewBlock(HeaderBB, PrevBB);
-    DT->addNewBlock(ExitBB, HeaderBB);
-    DT->addNewBlock(checkNextBB, HeaderBB);
-    DT->addNewBlock(loadIVBoundsBB, HeaderBB);
-
-    // Fill up basic block HeaderBB.
-    Builder.SetInsertPoint(HeaderBB);
-    Value *lowerBoundPtr = Builder.CreateAlloca(intPtrTy, 0,
-                                                "omp.lowerBoundPtr");
-    Value *upperBoundPtr = Builder.CreateAlloca(intPtrTy, 0,
-                                                "omp.upperBoundPtr");
-    Value *userContext = Builder.CreateBitCast(FN->arg_begin(),
-                                               structData->getType(),
-                                               "omp.userContext");
-
-    CharMapT clastVarsOMP;
-    extractValuesFromOpenMPStruct(&clastVarsOMP, OMPDataVals, userContext);
-
-    Builder.CreateBr(checkNextBB);
-
-    // Add code to check if another set of iterations will be executed.
-    Builder.SetInsertPoint(checkNextBB);
-    Function *runtimeNextFunction = M->getFunction("GOMP_loop_runtime_next");
-    Value *ret1 = Builder.CreateCall2(runtimeNextFunction,
-                                      lowerBoundPtr, upperBoundPtr);
-    Value *hasNextSchedule = Builder.CreateTrunc(ret1, Builder.getInt1Ty(),
-                                                 "omp.hasNextScheduleBlock");
-    Builder.CreateCondBr(hasNextSchedule, loadIVBoundsBB, ExitBB);
-
-    // Add code to to load the iv bounds for this set of iterations.
-    Builder.SetInsertPoint(loadIVBoundsBB);
-    Value *lowerBound = Builder.CreateLoad(lowerBoundPtr, "omp.lowerBound");
-    Value *upperBound = Builder.CreateLoad(upperBoundPtr, "omp.upperBound");
-
-    // Subtract one as the upper bound provided by openmp is a < comparison
-    // whereas the codegenForSequential function creates a <= comparison.
-    upperBound = Builder.CreateSub(upperBound, ConstantInt::get(intPtrTy, 1),
-                                   "omp.upperBoundAdjusted");
-
-    // Use clastVarsOMP during code generation of the OpenMP subfunction.
-    CharMapT *oldClastVars = clastVars;
-    clastVars = &clastVarsOMP;
-    ExpGen.setIVS(&clastVarsOMP);
-
-    codegenForSequential(f, lowerBound, upperBound);
-
-    // Restore the old clastVars.
-    clastVars = oldClastVars;
-    ExpGen.setIVS(oldClastVars);
-
-    Builder.CreateBr(checkNextBB);
-
-    // Add code to terminate this openmp subfunction.
-    Builder.SetInsertPoint(ExitBB);
-    Function *endnowaitFunction = M->getFunction("GOMP_loop_end_nowait");
-    Builder.CreateCall(endnowaitFunction);
-    Builder.CreateRetVoid();
-
-    // Restore the builder back to previous basic block.
-    Builder.SetInsertPoint(PrevBB);
-  }
+                                SetVector<Value*> OMPDataVals);
 
   /// @brief Create an OpenMP parallel for loop.
   ///
   /// This loop reflects a loop as if it would have been created by an OpenMP
   /// statement.
-  void codegenForOpenMP(const clast_for *f) {
-    Module *M = Builder.GetInsertBlock()->getParent()->getParent();
-    IntegerType *intPtrTy = TD->getIntPtrType(Builder.getContext());
+  void codegenForOpenMP(const clast_for *f);
 
-    Function *SubFunction = addOpenMPSubfunction(M);
-    SetVector<Value*> OMPDataVals = createOpenMPStructValues();
-    Value *structData = addValuesToOpenMPStruct(OMPDataVals, SubFunction);
-
-    addOpenMPSubfunctionBody(SubFunction, f, structData, OMPDataVals);
-
-    // Create call for GOMP_parallel_loop_runtime_start.
-    Value *subfunctionParam = Builder.CreateBitCast(structData,
-                                                    Builder.getInt8PtrTy(),
-                                                    "omp_data");
-
-    Value *numberOfThreads = Builder.getInt32(0);
-    Value *lowerBound = ExpGen.codegen(f->LB, intPtrTy);
-    Value *upperBound = ExpGen.codegen(f->UB, intPtrTy);
-
-    // Add one as the upper bound provided by openmp is a < comparison
-    // whereas the codegenForSequential function creates a <= comparison.
-    upperBound = Builder.CreateAdd(upperBound, ConstantInt::get(intPtrTy, 1));
-    APInt APStride = APInt_from_MPZ(f->stride);
-    Value *stride = ConstantInt::get(intPtrTy,
-                                     APStride.zext(intPtrTy->getBitWidth()));
-
-    SmallVector<Value *, 6> Arguments;
-    Arguments.push_back(SubFunction);
-    Arguments.push_back(subfunctionParam);
-    Arguments.push_back(numberOfThreads);
-    Arguments.push_back(lowerBound);
-    Arguments.push_back(upperBound);
-    Arguments.push_back(stride);
-
-    Function *parallelStartFunction =
-      M->getFunction("GOMP_parallel_loop_runtime_start");
-    Builder.CreateCall(parallelStartFunction, Arguments);
-
-    // Create call to the subfunction.
-    Builder.CreateCall(SubFunction, subfunctionParam);
-
-    // Create call for GOMP_parallel_end.
-    Function *FN = M->getFunction("GOMP_parallel_end");
-    Builder.CreateCall(FN);
-  }
-
-  bool isInnermostLoop(const clast_for *f) {
-    const clast_stmt *stmt = f->body;
-
-    while (stmt) {
-      if (!CLAST_STMT_IS_A(stmt, stmt_user))
-        return false;
+  bool isInnermostLoop(const clast_for *f);
 
-      stmt = stmt->next;
-    }
+  /// @brief Get the number of loop iterations for this loop.
+  /// @param f The clast for loop to check.
+  int getNumberOfIterations(const clast_for *f);
 
-    return true;
+  /// @brief Create vector instructions for this loop.
+  void codegenForVector(const clast_for *f);
+
+  void codegen(const clast_for *f);
+
+  Value *codegen(const clast_equation *eq);
+
+  void codegen(const clast_guard *g);
+
+  void codegen(const clast_stmt *stmt);
+
+  void addParameters(const CloogNames *names);
+
+  public:
+  void codegen(const clast_root *r);
+
+  ClastStmtCodeGen(Scop *scop, ScalarEvolution &se, DominatorTree *dt,
+                   ScopDetection *sd, Dependences *dp, TargetData *td,
+                   IRBuilder<> &B);
+};
+}
+
+const std::vector<std::string> &ClastStmtCodeGen::getParallelLoops() {
+  return parallelLoops;
+}
+
+void ClastStmtCodeGen::codegen(const clast_assignment *a) {
+  Value *V= ExpGen.codegen(a->RHS, TD->getIntPtrType(Builder.getContext()));
+  (*clastVars)[a->LHS] = V;
+}
+
+void ClastStmtCodeGen::codegen(const clast_assignment *a, ScopStmt *Statement,
+                               unsigned Dimension, int vectorDim,
+                               std::vector<ValueMapT> *VectorVMap) {
+  Value *RHS = ExpGen.codegen(a->RHS,
+                              TD->getIntPtrType(Builder.getContext()));
+
+  assert(!a->LHS && "Statement assignments do not have left hand side");
+  const PHINode *PN;
+  PN = Statement->getInductionVariableForDimension(Dimension);
+  const Value *V = PN;
+
+  if (VectorVMap)
+    (*VectorVMap)[vectorDim][V] = RHS;
+
+  ValueMap[V] = RHS;
+}
+
+void ClastStmtCodeGen::codegenSubstitutions(const clast_stmt *Assignment,
+                                             ScopStmt *Statement, int vectorDim,
+  std::vector<ValueMapT> *VectorVMap) {
+  int Dimension = 0;
+
+  while (Assignment) {
+    assert(CLAST_STMT_IS_A(Assignment, stmt_ass)
+           && "Substitions are expected to be assignments");
+    codegen((const clast_assignment *)Assignment, Statement, Dimension,
+            vectorDim, VectorVMap);
+    Assignment = Assignment->next;
+    Dimension++;
   }
+}
 
-  /// @brief Get the number of loop iterations for this loop.
-  /// @param f The clast for loop to check.
-  int getNumberOfIterations(const clast_for *f) {
-    isl_set *loopDomain = isl_set_copy(isl_set_from_cloog_domain(f->domain));
-    isl_set *tmp = isl_set_copy(loopDomain);
-
-    // Calculate a map similar to the identity map, but with the last input
-    // and output dimension not related.
-    //  [i0, i1, i2, i3] -> [i0, i1, i2, o0]
-    isl_space *Space = isl_set_get_space(loopDomain);
-    Space = isl_space_drop_outputs(Space,
-                                   isl_set_dim(loopDomain, isl_dim_set) - 2, 1);
-    Space = isl_space_map_from_set(Space);
-    isl_map *identity = isl_map_identity(Space);
-    identity = isl_map_add_dims(identity, isl_dim_in, 1);
-    identity = isl_map_add_dims(identity, isl_dim_out, 1);
-
-    isl_map *map = isl_map_from_domain_and_range(tmp, loopDomain);
-    map = isl_map_intersect(map, identity);
-
-    isl_map *lexmax = isl_map_lexmax(isl_map_copy(map));
-    isl_map *lexmin = isl_map_lexmin(map);
-    isl_map *sub = isl_map_sum(lexmax, isl_map_neg(lexmin));
-
-    isl_set *elements = isl_map_range(sub);
-
-    if (!isl_set_is_singleton(elements)) {
-      isl_set_free(elements);
-      return -1;
-    }
+void ClastStmtCodeGen::codegen(const clast_user_stmt *u,
+                               std::vector<Value*> *IVS , const char *iterator,
+                               isl_set *scatteringDomain) {
+  ScopStmt *Statement = (ScopStmt *)u->statement->usr;
+  BasicBlock *BB = Statement->getBasicBlock();
+
+  if (u->substitutions)
+    codegenSubstitutions(u->substitutions, Statement);
 
-    isl_point *p = isl_set_sample_point(elements);
+  int vectorDimensions = IVS ? IVS->size() : 1;
 
-    isl_int v;
-    isl_int_init(v);
-    isl_point_get_coordinate(p, isl_dim_set, isl_set_n_dim(loopDomain) - 1, &v);
-    int numberIterations = isl_int_get_si(v);
-    isl_int_clear(v);
-    isl_point_free(p);
+  VectorValueMapT VectorValueMap(vectorDimensions);
 
-    return (numberIterations) / isl_int_get_si(f->stride) + 1;
+  if (IVS) {
+    assert (u->substitutions && "Substitutions expected!");
+    int i = 0;
+    for (std::vector<Value*>::iterator II = IVS->begin(), IE = IVS->end();
+         II != IE; ++II) {
+      (*clastVars)[iterator] = *II;
+      codegenSubstitutions(u->substitutions, Statement, i, &VectorValueMap);
+      i++;
+    }
   }
 
-  /// @brief Create vector instructions for this loop.
-  void codegenForVector(const clast_for *f) {
-    DEBUG(dbgs() << "Vectorizing loop '" << f->iterator << "'\n";);
-    int vectorWidth = getNumberOfIterations(f);
+  BlockGenerator Generator(Builder, ValueMap, VectorValueMap, *Statement,
+                           scatteringDomain);
+  Generator.copyBB(BB, DT);
+}
+
+void ClastStmtCodeGen::codegen(const clast_block *b) {
+  if (b->body)
+    codegen(b->body);
+}
 
-    Value *LB = ExpGen.codegen(f->LB,
-      TD->getIntPtrType(Builder.getContext()));
+void ClastStmtCodeGen::codegenForSequential(const clast_for *f,
+                                            Value *LowerBound,
+                                            Value *UpperBound) {
+  APInt Stride;
+  PHINode *IV;
+  Value *IncrementedIV;
+  BasicBlock *AfterBB, *HeaderBB, *LastBodyBB;
+  Type *IntPtrTy;
+
+  Stride = APInt_from_MPZ(f->stride);
+  IntPtrTy = TD->getIntPtrType(Builder.getContext());
+
+  // The value of lowerbound and upperbound will be supplied, if this
+  // function is called while generating OpenMP code. Otherwise get
+  // the values.
+  assert(!!LowerBound == !!UpperBound && "Either give both bounds or none");
+
+  if (LowerBound == 0) {
+    LowerBound = ExpGen.codegen(f->LB, IntPtrTy);
+    UpperBound = ExpGen.codegen(f->UB, IntPtrTy);
+  }
+
+  createLoop(&Builder, LowerBound, UpperBound, Stride, IV, AfterBB,
+             IncrementedIV, DT);
+
+  // Add loop iv to symbols.
+  (*clastVars)[f->iterator] = IV;
+
+  if (f->body)
+    codegen(f->body);
+
+  // Loop is finished, so remove its iv from the live symbols.
+  clastVars->erase(f->iterator);
+
+  HeaderBB = *pred_begin(AfterBB);
+  LastBodyBB = Builder.GetInsertBlock();
+  Builder.CreateBr(HeaderBB);
+  IV->addIncoming(IncrementedIV, LastBodyBB);
+  Builder.SetInsertPoint(AfterBB);
+}
 
-    APInt Stride = APInt_from_MPZ(f->stride);
-    IntegerType *LoopIVType = dyn_cast<IntegerType>(LB->getType());
-    Stride =  Stride.zext(LoopIVType->getBitWidth());
-    Value *StrideValue = ConstantInt::get(LoopIVType, Stride);
+Function *ClastStmtCodeGen::addOpenMPSubfunction(Module *M) {
+  Function *F = Builder.GetInsertBlock()->getParent();
+  std::vector<Type*> Arguments(1, Builder.getInt8PtrTy());
+  FunctionType *FT = FunctionType::get(Builder.getVoidTy(), Arguments, false);
+  Function *FN = Function::Create(FT, Function::InternalLinkage,
+                                  F->getName() + ".omp_subfn", M);
+  // Do not run any polly pass on the new function.
+  SD->markFunctionAsInvalid(FN);
 
-    std::vector<Value*> IVS(vectorWidth);
-    IVS[0] = LB;
+  Function::arg_iterator AI = FN->arg_begin();
+  AI->setName("omp.userContext");
 
-    for (int i = 1; i < vectorWidth; i++)
-      IVS[i] = Builder.CreateAdd(IVS[i-1], StrideValue, "p_vector_iv");
+  return FN;
+}
 
-    isl_set *scatteringDomain =
-      isl_set_copy(isl_set_from_cloog_domain(f->domain));
+Value *ClastStmtCodeGen::addValuesToOpenMPStruct(SetVector<Value*> OMPDataVals,
+                                                 Function *SubFunction) {
+  std::vector<Type*> structMembers;
+
+  // Create the structure.
+  for (unsigned i = 0; i < OMPDataVals.size(); i++)
+    structMembers.push_back(OMPDataVals[i]->getType());
+
+  StructType *structTy = StructType::get(Builder.getContext(),
+                                         structMembers);
+  // Store the values into the structure.
+  Value *structData = Builder.CreateAlloca(structTy, 0, "omp.userContext");
+  for (unsigned i = 0; i < OMPDataVals.size(); i++) {
+    Value *storeAddr = Builder.CreateStructGEP(structData, i);
+    Builder.CreateStore(OMPDataVals[i], storeAddr);
+  }
 
-    // Add loop iv to symbols.
-    (*clastVars)[f->iterator] = LB;
+  return structData;
+}
 
-    const clast_stmt *stmt = f->body;
+SetVector<Value*> ClastStmtCodeGen::createOpenMPStructValues() {
+  SetVector<Value*> OMPDataVals;
 
-    while (stmt) {
-      codegen((const clast_user_stmt *)stmt, &IVS, f->iterator,
-              scatteringDomain);
-      stmt = stmt->next;
-    }
+  // Push the clast variables available in the clastVars.
+  for (CharMapT::iterator I = clastVars->begin(), E = clastVars->end();
+       I != E; I++)
+    OMPDataVals.insert(I->second);
 
-    // Loop is finished, so remove its iv from the live symbols.
-    isl_set_free(scatteringDomain);
-    clastVars->erase(f->iterator);
-  }
-
-  void codegen(const clast_for *f) {
-    if (Vector && isInnermostLoop(f) && DP->isParallelFor(f)
-        && (-1 != getNumberOfIterations(f))
-        && (getNumberOfIterations(f) <= 16)) {
-      codegenForVector(f);
-    } else if (OpenMP && !parallelCodeGeneration && DP->isParallelFor(f)) {
-      parallelCodeGeneration = true;
-      parallelLoops.push_back(f->iterator);
-      codegenForOpenMP(f);
-      parallelCodeGeneration = false;
-    } else
-      codegenForSequential(f);
-  }
-
-  Value *codegen(const clast_equation *eq) {
-    Value *LHS = ExpGen.codegen(eq->LHS,
-      TD->getIntPtrType(Builder.getContext()));
-    Value *RHS = ExpGen.codegen(eq->RHS,
-      TD->getIntPtrType(Builder.getContext()));
-    CmpInst::Predicate P;
-
-    if (eq->sign == 0)
-      P = ICmpInst::ICMP_EQ;
-    else if (eq->sign > 0)
-      P = ICmpInst::ICMP_SGE;
-    else
-      P = ICmpInst::ICMP_SLE;
-
-    return Builder.CreateICmp(P, LHS, RHS);
-  }
-
-  void codegen(const clast_guard *g) {
-    Function *F = Builder.GetInsertBlock()->getParent();
-    LLVMContext &Context = F->getContext();
-    BasicBlock *ThenBB = BasicBlock::Create(Context, "polly.then", F);
-    BasicBlock *MergeBB = BasicBlock::Create(Context, "polly.merge", F);
-    DT->addNewBlock(ThenBB, Builder.GetInsertBlock());
-    DT->addNewBlock(MergeBB, Builder.GetInsertBlock());
-
-    Value *Predicate = codegen(&(g->eq[0]));
-
-    for (int i = 1; i < g->n; ++i) {
-      Value *TmpPredicate = codegen(&(g->eq[i]));
-      Predicate = Builder.CreateAnd(Predicate, TmpPredicate);
+  // Push the base addresses of memory references.
+  for (Scop::iterator SI = S->begin(), SE = S->end(); SI != SE; ++SI) {
+    ScopStmt *Stmt = *SI;
+    for (SmallVector<MemoryAccess*, 8>::iterator I = Stmt->memacc_begin(),
+         E = Stmt->memacc_end(); I != E; ++I) {
+      Value *BaseAddr = const_cast<Value*>((*I)->getBaseAddr());
+      OMPDataVals.insert((BaseAddr));
     }
+  }
+
+  return OMPDataVals;
+}
 
-    Builder.CreateCondBr(Predicate, ThenBB, MergeBB);
-    Builder.SetInsertPoint(ThenBB);
+void ClastStmtCodeGen::extractValuesFromOpenMPStruct(CharMapT *clastVarsOMP,
+  SetVector<Value*> OMPDataVals, Value *userContext) {
+  // Extract the clast variables.
+  unsigned i = 0;
+  for (CharMapT::iterator I = clastVars->begin(), E = clastVars->end();
+       I != E; I++) {
+    Value *loadAddr = Builder.CreateStructGEP(userContext, i);
+    (*clastVarsOMP)[I->first] = Builder.CreateLoad(loadAddr);
+    i++;
+  }
+
+  // Extract the base addresses of memory references.
+  for (unsigned j = i; j < OMPDataVals.size(); j++) {
+    Value *loadAddr = Builder.CreateStructGEP(userContext, j);
+    Value *baseAddr = OMPDataVals[j];
+    ValueMap[baseAddr] = Builder.CreateLoad(loadAddr);
+  }
+}
 
-    codegen(g->then);
+void ClastStmtCodeGen::addOpenMPSubfunctionBody(Function *FN,
+                                                const clast_for *f,
+                                                Value *structData,
+                                                SetVector<Value*> OMPDataVals) {
+  Module *M = Builder.GetInsertBlock()->getParent()->getParent();
+  LLVMContext &Context = FN->getContext();
+  IntegerType *intPtrTy = TD->getIntPtrType(Context);
+
+  // Store the previous basic block.
+  BasicBlock *PrevBB = Builder.GetInsertBlock();
+
+  // Create basic blocks.
+  BasicBlock *HeaderBB = BasicBlock::Create(Context, "omp.setup", FN);
+  BasicBlock *ExitBB = BasicBlock::Create(Context, "omp.exit", FN);
+  BasicBlock *checkNextBB = BasicBlock::Create(Context, "omp.checkNext", FN);
+  BasicBlock *loadIVBoundsBB = BasicBlock::Create(Context, "omp.loadIVBounds",
+                                                  FN);
+
+  DT->addNewBlock(HeaderBB, PrevBB);
+  DT->addNewBlock(ExitBB, HeaderBB);
+  DT->addNewBlock(checkNextBB, HeaderBB);
+  DT->addNewBlock(loadIVBoundsBB, HeaderBB);
+
+  // Fill up basic block HeaderBB.
+  Builder.SetInsertPoint(HeaderBB);
+  Value *lowerBoundPtr = Builder.CreateAlloca(intPtrTy, 0,
+                                              "omp.lowerBoundPtr");
+  Value *upperBoundPtr = Builder.CreateAlloca(intPtrTy, 0,
+                                              "omp.upperBoundPtr");
+  Value *userContext = Builder.CreateBitCast(FN->arg_begin(),
+                                             structData->getType(),
+                                             "omp.userContext");
+
+  CharMapT clastVarsOMP;
+  extractValuesFromOpenMPStruct(&clastVarsOMP, OMPDataVals, userContext);
+
+  Builder.CreateBr(checkNextBB);
+
+  // Add code to check if another set of iterations will be executed.
+  Builder.SetInsertPoint(checkNextBB);
+  Function *runtimeNextFunction = M->getFunction("GOMP_loop_runtime_next");
+  Value *ret1 = Builder.CreateCall2(runtimeNextFunction,
+                                    lowerBoundPtr, upperBoundPtr);
+  Value *hasNextSchedule = Builder.CreateTrunc(ret1, Builder.getInt1Ty(),
+                                               "omp.hasNextScheduleBlock");
+  Builder.CreateCondBr(hasNextSchedule, loadIVBoundsBB, ExitBB);
+
+  // Add code to to load the iv bounds for this set of iterations.
+  Builder.SetInsertPoint(loadIVBoundsBB);
+  Value *lowerBound = Builder.CreateLoad(lowerBoundPtr, "omp.lowerBound");
+  Value *upperBound = Builder.CreateLoad(upperBoundPtr, "omp.upperBound");
+
+  // Subtract one as the upper bound provided by openmp is a < comparison
+  // whereas the codegenForSequential function creates a <= comparison.
+  upperBound = Builder.CreateSub(upperBound, ConstantInt::get(intPtrTy, 1),
+                                 "omp.upperBoundAdjusted");
+
+  // Use clastVarsOMP during code generation of the OpenMP subfunction.
+  CharMapT *oldClastVars = clastVars;
+  clastVars = &clastVarsOMP;
+  ExpGen.setIVS(&clastVarsOMP);
+
+  codegenForSequential(f, lowerBound, upperBound);
+
+  // Restore the old clastVars.
+  clastVars = oldClastVars;
+  ExpGen.setIVS(oldClastVars);
+
+  Builder.CreateBr(checkNextBB);
+
+  // Add code to terminate this openmp subfunction.
+  Builder.SetInsertPoint(ExitBB);
+  Function *endnowaitFunction = M->getFunction("GOMP_loop_end_nowait");
+  Builder.CreateCall(endnowaitFunction);
+  Builder.CreateRetVoid();
+
+  // Restore the builder back to previous basic block.
+  Builder.SetInsertPoint(PrevBB);
+}
+
+void ClastStmtCodeGen::codegenForOpenMP(const clast_for *f) {
+  Module *M = Builder.GetInsertBlock()->getParent()->getParent();
+  IntegerType *intPtrTy = TD->getIntPtrType(Builder.getContext());
+
+  Function *SubFunction = addOpenMPSubfunction(M);
+  SetVector<Value*> OMPDataVals = createOpenMPStructValues();
+  Value *structData = addValuesToOpenMPStruct(OMPDataVals, SubFunction);
+
+  addOpenMPSubfunctionBody(SubFunction, f, structData, OMPDataVals);
+
+  // Create call for GOMP_parallel_loop_runtime_start.
+  Value *subfunctionParam = Builder.CreateBitCast(structData,
+                                                  Builder.getInt8PtrTy(),
+                                                  "omp_data");
+
+  Value *numberOfThreads = Builder.getInt32(0);
+  Value *lowerBound = ExpGen.codegen(f->LB, intPtrTy);
+  Value *upperBound = ExpGen.codegen(f->UB, intPtrTy);
+
+  // Add one as the upper bound provided by openmp is a < comparison
+  // whereas the codegenForSequential function creates a <= comparison.
+  upperBound = Builder.CreateAdd(upperBound, ConstantInt::get(intPtrTy, 1));
+  APInt APStride = APInt_from_MPZ(f->stride);
+  Value *stride = ConstantInt::get(intPtrTy,
+                                   APStride.zext(intPtrTy->getBitWidth()));
+
+  SmallVector<Value *, 6> Arguments;
+  Arguments.push_back(SubFunction);
+  Arguments.push_back(subfunctionParam);
+  Arguments.push_back(numberOfThreads);
+  Arguments.push_back(lowerBound);
+  Arguments.push_back(upperBound);
+  Arguments.push_back(stride);
+
+  Function *parallelStartFunction =
+    M->getFunction("GOMP_parallel_loop_runtime_start");
+  Builder.CreateCall(parallelStartFunction, Arguments);
+
+  // Create call to the subfunction.
+  Builder.CreateCall(SubFunction, subfunctionParam);
+
+  // Create call for GOMP_parallel_end.
+  Function *FN = M->getFunction("GOMP_parallel_end");
+  Builder.CreateCall(FN);
+}
 
-    Builder.CreateBr(MergeBB);
-    Builder.SetInsertPoint(MergeBB);
+bool ClastStmtCodeGen::isInnermostLoop(const clast_for *f) {
+  const clast_stmt *stmt = f->body;
+
+  while (stmt) {
+    if (!CLAST_STMT_IS_A(stmt, stmt_user))
+      return false;
+
+    stmt = stmt->next;
   }
 
-  void codegen(const clast_stmt *stmt) {
-    if	    (CLAST_STMT_IS_A(stmt, stmt_root))
-      assert(false && "No second root statement expected");
-    else if (CLAST_STMT_IS_A(stmt, stmt_ass))
-      codegen((const clast_assignment *)stmt);
-    else if (CLAST_STMT_IS_A(stmt, stmt_user))
-      codegen((const clast_user_stmt *)stmt);
-    else if (CLAST_STMT_IS_A(stmt, stmt_block))
-      codegen((const clast_block *)stmt);
-    else if (CLAST_STMT_IS_A(stmt, stmt_for))
-      codegen((const clast_for *)stmt);
-    else if (CLAST_STMT_IS_A(stmt, stmt_guard))
-      codegen((const clast_guard *)stmt);
-
-    if (stmt->next)
-      codegen(stmt->next);
-  }
-
-  void addParameters(const CloogNames *names) {
-    SCEVExpander Rewriter(SE, "polly");
-
-    // Create an instruction that specifies the location where the parameters
-    // are expanded.
-    CastInst::CreateIntegerCast(ConstantInt::getTrue(Builder.getContext()),
-                                  Builder.getInt16Ty(), false, "insertInst",
-                                  Builder.GetInsertBlock());
+  return true;
+}
 
-    int i = 0;
-    for (Scop::param_iterator PI = S->param_begin(), PE = S->param_end();
-         PI != PE; ++PI) {
-      assert(i < names->nb_parameters && "Not enough parameter names");
-
-      const SCEV *Param = *PI;
-      Type *Ty = Param->getType();
-
-      Instruction *insertLocation = --(Builder.GetInsertBlock()->end());
-      Value *V = Rewriter.expandCodeFor(Param, Ty, insertLocation);
-      (*clastVars)[names->parameters[i]] = V;
+int ClastStmtCodeGen::getNumberOfIterations(const clast_for *f) {
+  isl_set *loopDomain = isl_set_copy(isl_set_from_cloog_domain(f->domain));
+  isl_set *tmp = isl_set_copy(loopDomain);
+
+  // Calculate a map similar to the identity map, but with the last input
+  // and output dimension not related.
+  //  [i0, i1, i2, i3] -> [i0, i1, i2, o0]
+  isl_space *Space = isl_set_get_space(loopDomain);
+  Space = isl_space_drop_outputs(Space,
+                                 isl_set_dim(loopDomain, isl_dim_set) - 2, 1);
+  Space = isl_space_map_from_set(Space);
+  isl_map *identity = isl_map_identity(Space);
+  identity = isl_map_add_dims(identity, isl_dim_in, 1);
+  identity = isl_map_add_dims(identity, isl_dim_out, 1);
+
+  isl_map *map = isl_map_from_domain_and_range(tmp, loopDomain);
+  map = isl_map_intersect(map, identity);
+
+  isl_map *lexmax = isl_map_lexmax(isl_map_copy(map));
+  isl_map *lexmin = isl_map_lexmin(map);
+  isl_map *sub = isl_map_sum(lexmax, isl_map_neg(lexmin));
+
+  isl_set *elements = isl_map_range(sub);
+
+  if (!isl_set_is_singleton(elements)) {
+    isl_set_free(elements);
+    return -1;
+  }
+
+  isl_point *p = isl_set_sample_point(elements);
+
+  isl_int v;
+  isl_int_init(v);
+  isl_point_get_coordinate(p, isl_dim_set, isl_set_n_dim(loopDomain) - 1, &v);
+  int numberIterations = isl_int_get_si(v);
+  isl_int_clear(v);
+  isl_point_free(p);
 
-      ++i;
-    }
+  return (numberIterations) / isl_int_get_si(f->stride) + 1;
+}
+
+void ClastStmtCodeGen::codegenForVector(const clast_for *f) {
+  DEBUG(dbgs() << "Vectorizing loop '" << f->iterator << "'\n";);
+  int vectorWidth = getNumberOfIterations(f);
+
+  Value *LB = ExpGen.codegen(f->LB,
+                             TD->getIntPtrType(Builder.getContext()));
+
+  APInt Stride = APInt_from_MPZ(f->stride);
+  IntegerType *LoopIVType = dyn_cast<IntegerType>(LB->getType());
+  Stride =  Stride.zext(LoopIVType->getBitWidth());
+  Value *StrideValue = ConstantInt::get(LoopIVType, Stride);
+
+  std::vector<Value*> IVS(vectorWidth);
+  IVS[0] = LB;
+
+  for (int i = 1; i < vectorWidth; i++)
+    IVS[i] = Builder.CreateAdd(IVS[i-1], StrideValue, "p_vector_iv");
+
+  isl_set *scatteringDomain =
+    isl_set_copy(isl_set_from_cloog_domain(f->domain));
+
+  // Add loop iv to symbols.
+  (*clastVars)[f->iterator] = LB;
+
+  const clast_stmt *stmt = f->body;
+
+  while (stmt) {
+    codegen((const clast_user_stmt *)stmt, &IVS, f->iterator,
+            scatteringDomain);
+    stmt = stmt->next;
   }
 
-  public:
-  void codegen(const clast_root *r) {
-    clastVars = new CharMapT();
-    addParameters(r->names);
-    ExpGen.setIVS(clastVars);
+  // Loop is finished, so remove its iv from the live symbols.
+  isl_set_free(scatteringDomain);
+  clastVars->erase(f->iterator);
+}
 
+void ClastStmtCodeGen::codegen(const clast_for *f) {
+  if (Vector && isInnermostLoop(f) && DP->isParallelFor(f)
+      && (-1 != getNumberOfIterations(f))
+      && (getNumberOfIterations(f) <= 16)) {
+    codegenForVector(f);
+  } else if (OpenMP && !parallelCodeGeneration && DP->isParallelFor(f)) {
+    parallelCodeGeneration = true;
+    parallelLoops.push_back(f->iterator);
+    codegenForOpenMP(f);
     parallelCodeGeneration = false;
+  } else
+    codegenForSequential(f);
+}
+
+Value *ClastStmtCodeGen::codegen(const clast_equation *eq) {
+  Value *LHS = ExpGen.codegen(eq->LHS,
+                              TD->getIntPtrType(Builder.getContext()));
+  Value *RHS = ExpGen.codegen(eq->RHS,
+                              TD->getIntPtrType(Builder.getContext()));
+  CmpInst::Predicate P;
+
+  if (eq->sign == 0)
+    P = ICmpInst::ICMP_EQ;
+  else if (eq->sign > 0)
+    P = ICmpInst::ICMP_SGE;
+  else
+    P = ICmpInst::ICMP_SLE;
+
+  return Builder.CreateICmp(P, LHS, RHS);
+}
 
-    const clast_stmt *stmt = (const clast_stmt*) r;
-    if (stmt->next)
-      codegen(stmt->next);
+void ClastStmtCodeGen::codegen(const clast_guard *g) {
+  Function *F = Builder.GetInsertBlock()->getParent();
+  LLVMContext &Context = F->getContext();
+  BasicBlock *ThenBB = BasicBlock::Create(Context, "polly.then", F);
+  BasicBlock *MergeBB = BasicBlock::Create(Context, "polly.merge", F);
+  DT->addNewBlock(ThenBB, Builder.GetInsertBlock());
+  DT->addNewBlock(MergeBB, Builder.GetInsertBlock());
 
-    delete clastVars;
+  Value *Predicate = codegen(&(g->eq[0]));
+
+  for (int i = 1; i < g->n; ++i) {
+    Value *TmpPredicate = codegen(&(g->eq[i]));
+    Predicate = Builder.CreateAnd(Predicate, TmpPredicate);
   }
 
-  ClastStmtCodeGen(Scop *scop, ScalarEvolution &se, DominatorTree *dt,
-                   ScopDetection *sd, Dependences *dp, TargetData *td,
-                   IRBuilder<> &B) :
-    S(scop), SE(se), DT(dt), SD(sd), DP(dp), TD(td), Builder(B),
-    ExpGen(Builder, NULL) {}
+  Builder.CreateCondBr(Predicate, ThenBB, MergeBB);
+  Builder.SetInsertPoint(ThenBB);
 
-};
+  codegen(g->then);
+
+  Builder.CreateBr(MergeBB);
+  Builder.SetInsertPoint(MergeBB);
 }
 
+void ClastStmtCodeGen::codegen(const clast_stmt *stmt) {
+  if	    (CLAST_STMT_IS_A(stmt, stmt_root))
+    assert(false && "No second root statement expected");
+  else if (CLAST_STMT_IS_A(stmt, stmt_ass))
+    codegen((const clast_assignment *)stmt);
+  else if (CLAST_STMT_IS_A(stmt, stmt_user))
+    codegen((const clast_user_stmt *)stmt);
+  else if (CLAST_STMT_IS_A(stmt, stmt_block))
+    codegen((const clast_block *)stmt);
+  else if (CLAST_STMT_IS_A(stmt, stmt_for))
+    codegen((const clast_for *)stmt);
+  else if (CLAST_STMT_IS_A(stmt, stmt_guard))
+    codegen((const clast_guard *)stmt);
+
+  if (stmt->next)
+    codegen(stmt->next);
+}
+
+void ClastStmtCodeGen::addParameters(const CloogNames *names) {
+  SCEVExpander Rewriter(SE, "polly");
+
+  // Create an instruction that specifies the location where the parameters
+  // are expanded.
+  CastInst::CreateIntegerCast(ConstantInt::getTrue(Builder.getContext()),
+                              Builder.getInt16Ty(), false, "insertInst",
+                              Builder.GetInsertBlock());
+
+  int i = 0;
+  for (Scop::param_iterator PI = S->param_begin(), PE = S->param_end();
+       PI != PE; ++PI) {
+    assert(i < names->nb_parameters && "Not enough parameter names");
+
+    const SCEV *Param = *PI;
+    Type *Ty = Param->getType();
+
+    Instruction *insertLocation = --(Builder.GetInsertBlock()->end());
+    Value *V = Rewriter.expandCodeFor(Param, Ty, insertLocation);
+    (*clastVars)[names->parameters[i]] = V;
+
+    ++i;
+  }
+}
+
+void ClastStmtCodeGen::codegen(const clast_root *r) {
+  clastVars = new CharMapT();
+  addParameters(r->names);
+  ExpGen.setIVS(clastVars);
+
+  parallelCodeGeneration = false;
+
+  const clast_stmt *stmt = (const clast_stmt*) r;
+  if (stmt->next)
+    codegen(stmt->next);
+
+  delete clastVars;
+}
+
+ClastStmtCodeGen::ClastStmtCodeGen(Scop *scop, ScalarEvolution &se,
+                                   DominatorTree *dt, ScopDetection *sd,
+                                   Dependences *dp, TargetData *td,
+                                  IRBuilder<> &B) :
+    S(scop), SE(se), DT(dt), SD(sd), DP(dp), TD(td), Builder(B),
+    ExpGen(Builder, NULL) {}
+
 namespace {
 class CodeGeneration : public ScopPass {
   Region *region;





More information about the llvm-commits mailing list