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

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


Author: grosser
Date: Tue Jan 24 10:42:21 2012
New Revision: 148811

URL: http://llvm.org/viewvc/llvm-project?rev=148811&view=rev
Log:
CodeGen: Separate declaration and definitions of BlockGenerator

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=148811&r1=148810&r2=148811&view=diff
==============================================================================
--- polly/trunk/lib/CodeGeneration.cpp (original)
+++ polly/trunk/lib/CodeGeneration.cpp Tue Jan 24 10:42:21 2012
@@ -152,83 +152,21 @@
   ValueMapT &VMap;
   VectorValueMapT &ValueMaps;
   Scop &S;
-  ScopStmt &statement;
-  isl_set *scatteringDomain;
+  ScopStmt &Statement;
+  isl_set *ScatteringDomain;
 
 public:
   BlockGenerator(IRBuilder<> &B, ValueMapT &vmap, VectorValueMapT &vmaps,
-                 ScopStmt &Stmt, isl_set *domain)
-    : Builder(B), VMap(vmap), ValueMaps(vmaps), S(*Stmt.getParent()),
-    statement(Stmt), scatteringDomain(domain) {}
-
-  const Region &getRegion() {
-    return S.getRegion();
-  }
-
-  Value *makeVectorOperand(Value *operand, int vectorWidth) {
-    if (operand->getType()->isVectorTy())
-      return operand;
+                 ScopStmt &Stmt, __isl_keep isl_set *domain);
 
-    VectorType *vectorType = VectorType::get(operand->getType(), vectorWidth);
-    Value *vector = UndefValue::get(vectorType);
-    vector = Builder.CreateInsertElement(vector, operand, Builder.getInt32(0));
+  const Region &getRegion();
 
-    std::vector<Constant*> splat;
-
-    for (int i = 0; i < vectorWidth; i++)
-      splat.push_back (Builder.getInt32(0));
-
-    Constant *splatVector = ConstantVector::get(splat);
-
-    return Builder.CreateShuffleVector(vector, vector, splatVector);
-  }
+  Value *makeVectorOperand(Value *operand, int vectorWidth);
 
   Value *getOperand(const Value *oldOperand, ValueMapT &BBMap,
-                    ValueMapT *VectorMap = 0) {
-    const Instruction *OpInst = dyn_cast<Instruction>(oldOperand);
-
-    if (!OpInst)
-      return const_cast<Value*>(oldOperand);
-
-    if (VectorMap && VectorMap->count(oldOperand))
-      return (*VectorMap)[oldOperand];
+                    ValueMapT *VectorMap = 0);
 
-    // IVS and Parameters.
-    if (VMap.count(oldOperand)) {
-      Value *NewOperand = VMap[oldOperand];
-
-      // Insert a cast if types are different
-      if (oldOperand->getType()->getScalarSizeInBits()
-          < NewOperand->getType()->getScalarSizeInBits())
-        NewOperand = Builder.CreateTruncOrBitCast(NewOperand,
-                                                   oldOperand->getType());
-
-      return NewOperand;
-    }
-
-    // Instructions calculated in the current BB.
-    if (BBMap.count(oldOperand)) {
-      return BBMap[oldOperand];
-    }
-
-    // Ignore instructions that are referencing ops in the old BB. These
-    // instructions are unused. They where replace by new ones during
-    // createIndependentBlocks().
-    if (getRegion().contains(OpInst->getParent()))
-      return NULL;
-
-    return const_cast<Value*>(oldOperand);
-  }
-
-  Type *getVectorPtrTy(const Value *V, int vectorWidth) {
-    PointerType *pointerType = dyn_cast<PointerType>(V->getType());
-    assert(pointerType && "PointerType expected");
-
-    Type *scalarType = pointerType->getElementType();
-    VectorType *vectorType = VectorType::get(scalarType, vectorWidth);
-
-    return PointerType::getUnqual(vectorType);
-  }
+  Type *getVectorPtrTy(const Value *V, int vectorWidth);
 
   /// @brief Load a vector from a set of adjacent scalars
   ///
@@ -239,19 +177,7 @@
   /// %vec_full = load <4 x double>* %vector_ptr
   ///
   Value *generateStrideOneLoad(const LoadInst *load, ValueMapT &BBMap,
-                               int size) {
-    const Value *pointer = load->getPointerOperand();
-    Type *vectorPtrType = getVectorPtrTy(pointer, size);
-    Value *newPointer = getOperand(pointer, BBMap);
-    Value *VectorPtr = Builder.CreateBitCast(newPointer, vectorPtrType,
-                                             "vector_ptr");
-    LoadInst *VecLoad = Builder.CreateLoad(VectorPtr,
-                                           load->getName() + "_p_vec_full");
-    if (!Aligned)
-      VecLoad->setAlignment(8);
-
-    return VecLoad;
-  }
+                               int size);
 
   /// @brief Load a vector initialized from a single scalar in memory
   ///
@@ -264,31 +190,7 @@
   ///       double> %splat_one, <4 x i32> zeroinitializer
   ///
   Value *generateStrideZeroLoad(const LoadInst *load, ValueMapT &BBMap,
-                                int size) {
-    const Value *pointer = load->getPointerOperand();
-    Type *vectorPtrType = getVectorPtrTy(pointer, 1);
-    Value *newPointer = getOperand(pointer, BBMap);
-    Value *vectorPtr = Builder.CreateBitCast(newPointer, vectorPtrType,
-                                             load->getName() + "_p_vec_p");
-    LoadInst *scalarLoad= Builder.CreateLoad(vectorPtr,
-                                             load->getName() + "_p_splat_one");
-
-    if (!Aligned)
-      scalarLoad->setAlignment(8);
-
-    std::vector<Constant*> splat;
-
-    for (int i = 0; i < size; i++)
-      splat.push_back (Builder.getInt32(0));
-
-    Constant *splatVector = ConstantVector::get(splat);
-
-    Value *vectorLoad = Builder.CreateShuffleVector(scalarLoad, scalarLoad,
-                                                    splatVector,
-                                                    load->getName()
-                                                    + "_p_splat");
-    return vectorLoad;
-  }
+                                int size);
 
   /// @Load a vector from scalars distributed in memory
   ///
@@ -302,369 +204,539 @@
   /// %vec_2 = insertelement <2 x double> %vec_1, double %scalar_1, i32 1
   ///
   Value *generateUnknownStrideLoad(const LoadInst *load,
-                                   VectorValueMapT &scalarMaps,
-                                   int size) {
-    const Value *pointer = load->getPointerOperand();
-    VectorType *vectorType = VectorType::get(
-      dyn_cast<PointerType>(pointer->getType())->getElementType(), size);
-
-    Value *vector = UndefValue::get(vectorType);
-
-    for (int i = 0; i < size; i++) {
-      Value *newPointer = getOperand(pointer, scalarMaps[i]);
-      Value *scalarLoad = Builder.CreateLoad(newPointer,
-                                             load->getName() + "_p_scalar_");
-      vector = Builder.CreateInsertElement(vector, scalarLoad,
-                                           Builder.getInt32(i),
-                                           load->getName() + "_p_vec_");
-    }
-
-    return vector;
-  }
+                                   VectorValueMapT &scalarMaps, int size);
 
   static Value* islAffToValue(__isl_take isl_aff *Aff,
-                              IslPwAffUserInfo *UserInfo) {
-    assert(isl_aff_is_cst(Aff) && "Only constant access functions supported");
-
-    IRBuilder<> *Builder = UserInfo->Builder;
-
-    isl_int OffsetIsl;
-    mpz_t OffsetMPZ;
-
-    isl_int_init(OffsetIsl);
-    mpz_init(OffsetMPZ);
-    isl_aff_get_constant(Aff, &OffsetIsl);
-    isl_int_get_gmp(OffsetIsl, OffsetMPZ);
-
-    Value *OffsetValue = NULL;
-    APInt Offset = APInt_from_MPZ(OffsetMPZ);
-    OffsetValue = ConstantInt::get(Builder->getContext(), Offset);
-
-    mpz_clear(OffsetMPZ);
-    isl_int_clear(OffsetIsl);
-    isl_aff_free(Aff);
-
-    return OffsetValue;
-  }
+                              IslPwAffUserInfo *UserInfo);
 
   static int mergeIslAffValues(__isl_take isl_set *Set,
-                               __isl_take isl_aff *Aff, void *User) {
-    IslPwAffUserInfo *UserInfo = (IslPwAffUserInfo *)User;
+                               __isl_take isl_aff *Aff, void *User);
 
-    assert((UserInfo->Result == NULL) && "Result is already set."
-           "Currently only single isl_aff is supported");
-    assert(isl_set_plain_is_universe(Set)
-           && "Code generation failed because the set is not universe");
-
-    UserInfo->Result = islAffToValue(Aff, UserInfo);
-
-    isl_set_free(Set);
-    return 0;
-  }
-
-  Value* islPwAffToValue(__isl_take isl_pw_aff *PwAff, Value *BaseAddress) {
-    IslPwAffUserInfo UserInfo;
-    UserInfo.BaseAddress = BaseAddress;
-    UserInfo.Result = NULL;
-    UserInfo.Builder = &Builder;
-    isl_pw_aff_foreach_piece(PwAff, mergeIslAffValues, &UserInfo);
-    assert(UserInfo.Result && "Code generation for isl_pw_aff failed");
-
-    isl_pw_aff_free(PwAff);
-    return UserInfo.Result;
-  }
+  Value* islPwAffToValue(__isl_take isl_pw_aff *PwAff, Value *BaseAddress);
 
   /// @brief Get the memory access offset to be added to the base address
   std::vector <Value*> getMemoryAccessIndex(__isl_keep isl_map *AccessRelation,
-                                            Value *BaseAddress) {
-    assert((isl_map_dim(AccessRelation, isl_dim_out) == 1)
-           && "Only single dimensional access functions supported");
-
-    isl_pw_aff *PwAff = isl_map_dim_max(isl_map_copy(AccessRelation), 0);
-    Value *OffsetValue = islPwAffToValue(PwAff, BaseAddress);
-
-    PointerType *BaseAddressType = dyn_cast<PointerType>(
-                                   BaseAddress->getType());
-    Type *ArrayTy = BaseAddressType->getElementType();
-    Type *ArrayElementType = dyn_cast<ArrayType>(ArrayTy)->getElementType();
-    OffsetValue = Builder.CreateSExtOrBitCast(OffsetValue, ArrayElementType);
-
-    std::vector<Value*> IndexArray;
-    Value *NullValue = Constant::getNullValue(ArrayElementType);
-    IndexArray.push_back(NullValue);
-    IndexArray.push_back(OffsetValue);
-    return IndexArray;
-  }
+                                            Value *BaseAddress);
 
   /// @brief Get the new operand address according to the changed access in
   ///        JSCOP file.
   Value *getNewAccessOperand(__isl_keep isl_map *NewAccessRelation,
                              Value *BaseAddress, const Value *OldOperand,
-                             ValueMapT &BBMap) {
-    std::vector<Value*> IndexArray = getMemoryAccessIndex(NewAccessRelation,
-                                                          BaseAddress);
-    Value *NewOperand = Builder.CreateGEP(BaseAddress, IndexArray,
-                                          "p_newarrayidx_");
-    return NewOperand;
-  }
+                             ValueMapT &BBMap);
 
   /// @brief Generate the operand address
   Value *generateLocationAccessed(const Instruction *Inst,
-                                  const Value *Pointer, ValueMapT &BBMap ) {
-    MemoryAccess &Access = statement.getAccessFor(Inst);
-    isl_map *CurrentAccessRelation = Access.getAccessRelation();
-    isl_map *NewAccessRelation = Access.getNewAccessRelation();
-
-    assert(isl_map_has_equal_space(CurrentAccessRelation, NewAccessRelation)
-           && "Current and new access function use different spaces");
+                                  const Value *Pointer, ValueMapT &BBMap );
 
-    Value *NewPointer;
-
-    if (!NewAccessRelation) {
-      NewPointer = getOperand(Pointer, BBMap);
-    } else {
-      Value *BaseAddress = const_cast<Value*>(Access.getBaseAddr());
-      NewPointer = getNewAccessOperand(NewAccessRelation, BaseAddress, Pointer,
-                                       BBMap);
-    }
-
-    isl_map_free(CurrentAccessRelation);
-    isl_map_free(NewAccessRelation);
-    return NewPointer;
-  }
-
-  Value *generateScalarLoad(const LoadInst *load, ValueMapT &BBMap) {
-    const Value *pointer = load->getPointerOperand();
-    const Instruction *Inst = dyn_cast<Instruction>(load);
-    Value *newPointer = generateLocationAccessed(Inst, pointer, BBMap);
-    Value *scalarLoad = Builder.CreateLoad(newPointer,
-                                           load->getName() + "_p_scalar_");
-    return scalarLoad;
-  }
+  Value *generateScalarLoad(const LoadInst *load, ValueMapT &BBMap);
 
   /// @brief Load a value (or several values as a vector) from memory.
   void generateLoad(const LoadInst *load, ValueMapT &vectorMap,
-                    VectorValueMapT &scalarMaps, int vectorWidth) {
-    if (scalarMaps.size() == 1) {
-      scalarMaps[0][load] = generateScalarLoad(load, scalarMaps[0]);
-      return;
-    }
+                    VectorValueMapT &scalarMaps, int vectorWidth);
 
-    Value *newLoad;
+  void copyUnaryInst(const UnaryInstruction *Inst, ValueMapT &BBMap,
+                     ValueMapT &VectorMap, int VectorDimension,
+                     int VectorWidth);
 
-    MemoryAccess &Access = statement.getAccessFor(load);
+  void copyBinInst(const BinaryOperator *Inst, ValueMapT &BBMap,
+                   ValueMapT &vectorMap, int vectorDimension, int vectorWidth);
+
+  void copyVectorStore(const StoreInst *store, ValueMapT &BBMap,
+                       ValueMapT &vectorMap, VectorValueMapT &scalarMaps,
+                       int vectorDimension, int vectorWidth);
 
-    assert(scatteringDomain && "No scattering domain available");
+  void copyInstScalar(const Instruction *Inst, ValueMapT &BBMap);
 
-    if (Access.isStrideZero(isl_set_copy(scatteringDomain)))
-      newLoad = generateStrideZeroLoad(load, scalarMaps[0], vectorWidth);
-    else if (Access.isStrideOne(isl_set_copy(scatteringDomain)))
-      newLoad = generateStrideOneLoad(load, scalarMaps[0], vectorWidth);
-    else
-      newLoad = generateUnknownStrideLoad(load, scalarMaps, vectorWidth);
+  bool hasVectorOperands(const Instruction *Inst, ValueMapT &VectorMap);
+
+  int getVectorSize();
 
-    vectorMap[load] = newLoad;
+  bool isVectorBlock();
+
+  void copyInstruction(const Instruction *Inst, ValueMapT &BBMap,
+                       ValueMapT &vectorMap, VectorValueMapT &scalarMaps,
+                       int vectorDimension, int vectorWidth);
+
+  // Insert a copy of a basic block in the newly generated code.
+  //
+  // @param Builder The builder used to insert the code. It also specifies
+  //                where to insert the code.
+  // @param BB      The basic block to copy
+  // @param VMap    A map returning for any old value its new equivalent. This
+  //                is used to update the operands of the statements.
+  //                For new statements a relation old->new is inserted in this
+  //                map.
+  void copyBB(BasicBlock *BB, DominatorTree *DT);
+};
+
+BlockGenerator::BlockGenerator(IRBuilder<> &B, ValueMapT &vmap,
+                               VectorValueMapT &vmaps, ScopStmt &Stmt,
+                               __isl_keep isl_set *domain)
+    : Builder(B), VMap(vmap), ValueMaps(vmaps), S(*Stmt.getParent()),
+      Statement(Stmt), ScatteringDomain(domain) {}
+
+const Region &BlockGenerator::getRegion() {
+  return S.getRegion();
+}
+
+Value *BlockGenerator::makeVectorOperand(Value *Operand, int VectorWidth) {
+  if (Operand->getType()->isVectorTy())
+    return Operand;
+
+  VectorType *VectorType = VectorType::get(Operand->getType(), VectorWidth);
+  Value *Vector = UndefValue::get(VectorType);
+  Vector = Builder.CreateInsertElement(Vector, Operand, Builder.getInt32(0));
+
+  std::vector<Constant*> Splat;
+
+  for (int i = 0; i < VectorWidth; i++)
+    Splat.push_back (Builder.getInt32(0));
+
+  Constant *SplatVector = ConstantVector::get(Splat);
+
+  return Builder.CreateShuffleVector(Vector, Vector, SplatVector);
+}
+
+Value *BlockGenerator::getOperand(const Value *OldOperand, ValueMapT &BBMap,
+                                  ValueMapT *VectorMap) {
+  const Instruction *OpInst = dyn_cast<Instruction>(OldOperand);
+
+  if (!OpInst)
+    return const_cast<Value*>(OldOperand);
+
+  if (VectorMap && VectorMap->count(OldOperand))
+    return (*VectorMap)[OldOperand];
+
+  // IVS and Parameters.
+  if (VMap.count(OldOperand)) {
+    Value *NewOperand = VMap[OldOperand];
+
+    // Insert a cast if types are different
+    if (OldOperand->getType()->getScalarSizeInBits()
+        < NewOperand->getType()->getScalarSizeInBits())
+      NewOperand = Builder.CreateTruncOrBitCast(NewOperand,
+                                                OldOperand->getType());
+
+    return NewOperand;
   }
 
-  void copyUnaryInst(const UnaryInstruction *Inst, ValueMapT &BBMap,
-                     ValueMapT &VectorMap, int VectorDimension,
-                     int VectorWidth) {
-    Value *NewOperand = getOperand(Inst->getOperand(0), BBMap, &VectorMap);
-    NewOperand = makeVectorOperand(NewOperand, VectorWidth);
-
-    if (const CastInst *Cast = dyn_cast<CastInst>(Inst)) {
-      VectorType *DestType = VectorType::get(Inst->getType(), VectorWidth);
-      VectorMap[Inst] = Builder.CreateCast(Cast->getOpcode(), NewOperand,
-                                           DestType);
-    } else
-      llvm_unreachable("Can not generate vector code for instruction");
-    return;
+  // Instructions calculated in the current BB.
+  if (BBMap.count(OldOperand)) {
+    return BBMap[OldOperand];
   }
 
-  void copyBinInst(const BinaryOperator *Inst, ValueMapT &BBMap,
-                   ValueMapT &vectorMap, int vectorDimension, int vectorWidth) {
-    Value *opZero = Inst->getOperand(0);
-    Value *opOne = Inst->getOperand(1);
-
-    Value *newOpZero, *newOpOne;
-    newOpZero = getOperand(opZero, BBMap, &vectorMap);
-    newOpOne = getOperand(opOne, BBMap, &vectorMap);
-
-    newOpZero = makeVectorOperand(newOpZero, vectorWidth);
-    newOpOne = makeVectorOperand(newOpOne, vectorWidth);
-
-    Value *newInst = Builder.CreateBinOp(Inst->getOpcode(), newOpZero,
-                                         newOpOne,
-                                         Inst->getName() + "p_vec");
-    vectorMap[Inst] = newInst;
+  // Ignore instructions that are referencing ops in the old BB. These
+  // instructions are unused. They where replace by new ones during
+  // createIndependentBlocks().
+  if (getRegion().contains(OpInst->getParent()))
+    return NULL;
 
-    return;
+  return const_cast<Value*>(OldOperand);
+}
+
+Type *BlockGenerator::getVectorPtrTy(const Value *Val, int VectorWidth) {
+  PointerType *PointerTy = dyn_cast<PointerType>(Val->getType());
+  assert(PointerTy && "PointerType expected");
+
+  Type *ScalarType = PointerTy->getElementType();
+  VectorType *VectorType = VectorType::get(ScalarType, VectorWidth);
+
+  return PointerType::getUnqual(VectorType);
+}
+
+Value *BlockGenerator::generateStrideOneLoad(const LoadInst *Load,
+                                             ValueMapT &BBMap, int Size) {
+  const Value *Pointer = Load->getPointerOperand();
+  Type *VectorPtrType = getVectorPtrTy(Pointer, Size);
+  Value *NewPointer = getOperand(Pointer, BBMap);
+  Value *VectorPtr = Builder.CreateBitCast(NewPointer, VectorPtrType,
+                                           "vector_ptr");
+  LoadInst *VecLoad = Builder.CreateLoad(VectorPtr,
+                                         Load->getName() + "_p_vec_full");
+  if (!Aligned)
+    VecLoad->setAlignment(8);
+
+  return VecLoad;
+}
+
+Value *BlockGenerator::generateStrideZeroLoad(const LoadInst *Load,
+                                              ValueMapT &BBMap, int Size) {
+  const Value *Pointer = Load->getPointerOperand();
+  Type *VectorPtrType = getVectorPtrTy(Pointer, 1);
+  Value *NewPointer = getOperand(Pointer, BBMap);
+  Value *VectorPtr = Builder.CreateBitCast(NewPointer, VectorPtrType,
+                                           Load->getName() + "_p_vec_p");
+  LoadInst *ScalarLoad= Builder.CreateLoad(VectorPtr,
+                                           Load->getName() + "_p_splat_one");
+
+  if (!Aligned)
+    ScalarLoad->setAlignment(8);
+
+  std::vector<Constant*> Splat;
+
+  for (int i = 0; i < Size; i++)
+    Splat.push_back (Builder.getInt32(0));
+
+  Constant *SplatVector = ConstantVector::get(Splat);
+
+  Value *VectorLoad = Builder.CreateShuffleVector(ScalarLoad, ScalarLoad,
+                                                  SplatVector,
+                                                  Load->getName()
+                                                  + "_p_splat");
+  return VectorLoad;
+}
+
+Value *BlockGenerator::generateUnknownStrideLoad(const LoadInst *Load,
+                                                 VectorValueMapT &ScalarMaps,
+                                                 int Size) {
+  const Value *Pointer = Load->getPointerOperand();
+  VectorType *VectorType = VectorType::get(
+    dyn_cast<PointerType>(Pointer->getType())->getElementType(), Size);
+
+  Value *Vector = UndefValue::get(VectorType);
+
+  for (int i = 0; i < Size; i++) {
+    Value *NewPointer = getOperand(Pointer, ScalarMaps[i]);
+    Value *ScalarLoad = Builder.CreateLoad(NewPointer,
+                                           Load->getName() + "_p_scalar_");
+    Vector = Builder.CreateInsertElement(Vector, ScalarLoad,
+                                         Builder.getInt32(i),
+                                         Load->getName() + "_p_vec_");
   }
 
-  void copyVectorStore(const StoreInst *store, ValueMapT &BBMap,
-                       ValueMapT &vectorMap, VectorValueMapT &scalarMaps,
-                       int vectorDimension, int vectorWidth) {
-    // In vector mode we only generate a store for the first dimension.
-    if (vectorDimension > 0)
-      return;
+  return Vector;
+}
 
-    MemoryAccess &Access = statement.getAccessFor(store);
+Value *BlockGenerator::islAffToValue(__isl_take isl_aff *Aff,
+                                     IslPwAffUserInfo *UserInfo) {
+  assert(isl_aff_is_cst(Aff) && "Only constant access functions supported");
 
-    assert(scatteringDomain && "No scattering domain available");
+  IRBuilder<> *Builder = UserInfo->Builder;
 
-    const Value *pointer = store->getPointerOperand();
-    Value *vector = getOperand(store->getValueOperand(), BBMap, &vectorMap);
+  isl_int OffsetIsl;
+  mpz_t OffsetMPZ;
 
-    if (Access.isStrideOne(isl_set_copy(scatteringDomain))) {
-      Type *vectorPtrType = getVectorPtrTy(pointer, vectorWidth);
-      Value *newPointer = getOperand(pointer, BBMap, &vectorMap);
+  isl_int_init(OffsetIsl);
+  mpz_init(OffsetMPZ);
+  isl_aff_get_constant(Aff, &OffsetIsl);
+  isl_int_get_gmp(OffsetIsl, OffsetMPZ);
 
-      Value *VectorPtr = Builder.CreateBitCast(newPointer, vectorPtrType,
-                                               "vector_ptr");
-      StoreInst *Store = Builder.CreateStore(vector, VectorPtr);
+  Value *OffsetValue = NULL;
+  APInt Offset = APInt_from_MPZ(OffsetMPZ);
+  OffsetValue = ConstantInt::get(Builder->getContext(), Offset);
 
-      if (!Aligned)
-        Store->setAlignment(8);
-    } else {
-      for (unsigned i = 0; i < scalarMaps.size(); i++) {
-        Value *scalar = Builder.CreateExtractElement(vector,
-                                                     Builder.getInt32(i));
-        Value *newPointer = getOperand(pointer, scalarMaps[i]);
-        Builder.CreateStore(scalar, newPointer);
-      }
-    }
+  mpz_clear(OffsetMPZ);
+  isl_int_clear(OffsetIsl);
+  isl_aff_free(Aff);
+
+  return OffsetValue;
+}
+
+int BlockGenerator::mergeIslAffValues(__isl_take isl_set *Set,
+                                      __isl_take isl_aff *Aff, void *User) {
+  IslPwAffUserInfo *UserInfo = (IslPwAffUserInfo *)User;
+
+  assert((UserInfo->Result == NULL) && "Result is already set."
+         "Currently only single isl_aff is supported");
+  assert(isl_set_plain_is_universe(Set)
+         && "Code generation failed because the set is not universe");
+
+  UserInfo->Result = islAffToValue(Aff, UserInfo);
+
+  isl_set_free(Set);
+  return 0;
+}
+
+Value *BlockGenerator::islPwAffToValue(__isl_take isl_pw_aff *PwAff,
+                                       Value *BaseAddress) {
+  IslPwAffUserInfo UserInfo;
+  UserInfo.BaseAddress = BaseAddress;
+  UserInfo.Result = NULL;
+  UserInfo.Builder = &Builder;
+  isl_pw_aff_foreach_piece(PwAff, mergeIslAffValues, &UserInfo);
+  assert(UserInfo.Result && "Code generation for isl_pw_aff failed");
+
+  isl_pw_aff_free(PwAff);
+  return UserInfo.Result;
+}
 
+std::vector <Value*> BlockGenerator::getMemoryAccessIndex(
+  __isl_keep isl_map *AccessRelation, Value *BaseAddress) {
+  assert((isl_map_dim(AccessRelation, isl_dim_out) == 1)
+         && "Only single dimensional access functions supported");
+
+  isl_pw_aff *PwAff = isl_map_dim_max(isl_map_copy(AccessRelation), 0);
+  Value *OffsetValue = islPwAffToValue(PwAff, BaseAddress);
+
+  PointerType *BaseAddressType = dyn_cast<PointerType>(
+    BaseAddress->getType());
+  Type *ArrayTy = BaseAddressType->getElementType();
+  Type *ArrayElementType = dyn_cast<ArrayType>(ArrayTy)->getElementType();
+  OffsetValue = Builder.CreateSExtOrBitCast(OffsetValue, ArrayElementType);
+
+  std::vector<Value*> IndexArray;
+  Value *NullValue = Constant::getNullValue(ArrayElementType);
+  IndexArray.push_back(NullValue);
+  IndexArray.push_back(OffsetValue);
+  return IndexArray;
+}
+
+Value *BlockGenerator::getNewAccessOperand(
+  __isl_keep isl_map *NewAccessRelation, Value *BaseAddress, const Value
+  *OldOperand, ValueMapT &BBMap) {
+  std::vector<Value*> IndexArray = getMemoryAccessIndex(NewAccessRelation,
+                                                        BaseAddress);
+  Value *NewOperand = Builder.CreateGEP(BaseAddress, IndexArray,
+                                        "p_newarrayidx_");
+  return NewOperand;
+}
+
+Value *BlockGenerator::generateLocationAccessed(const Instruction *Inst,
+                                                const Value *Pointer,
+                                                ValueMapT &BBMap ) {
+  MemoryAccess &Access = Statement.getAccessFor(Inst);
+  isl_map *CurrentAccessRelation = Access.getAccessRelation();
+  isl_map *NewAccessRelation = Access.getNewAccessRelation();
+
+  assert(isl_map_has_equal_space(CurrentAccessRelation, NewAccessRelation)
+         && "Current and new access function use different spaces");
+
+  Value *NewPointer;
+
+  if (!NewAccessRelation) {
+    NewPointer = getOperand(Pointer, BBMap);
+  } else {
+    Value *BaseAddress = const_cast<Value*>(Access.getBaseAddr());
+    NewPointer = getNewAccessOperand(NewAccessRelation, BaseAddress, Pointer,
+                                     BBMap);
+  }
+
+  isl_map_free(CurrentAccessRelation);
+  isl_map_free(NewAccessRelation);
+  return NewPointer;
+}
+
+Value *BlockGenerator::generateScalarLoad(const LoadInst *Load,
+                                          ValueMapT &BBMap) {
+  const Value *Pointer = Load->getPointerOperand();
+  const Instruction *Inst = dyn_cast<Instruction>(Load);
+  Value *NewPointer = generateLocationAccessed(Inst, Pointer, BBMap);
+  Value *ScalarLoad = Builder.CreateLoad(NewPointer,
+                                         Load->getName() + "_p_scalar_");
+  return ScalarLoad;
+}
+
+void BlockGenerator::generateLoad(const LoadInst *Load, ValueMapT &VectorMap,
+                                  VectorValueMapT &ScalarMaps,
+                                  int VectorWidth) {
+  if (ScalarMaps.size() == 1) {
+    ScalarMaps[0][Load] = generateScalarLoad(Load, ScalarMaps[0]);
     return;
   }
 
-  void copyInstScalar(const Instruction *Inst, ValueMapT &BBMap) {
-    Instruction *NewInst = Inst->clone();
+  Value *NewLoad;
 
-    // Replace old operands with the new ones.
-    for (Instruction::const_op_iterator OI = Inst->op_begin(),
-         OE = Inst->op_end(); OI != OE; ++OI) {
-      Value *OldOperand = *OI;
-      Value *NewOperand = getOperand(OldOperand, BBMap);
-
-      if (!NewOperand) {
-        assert(!isa<StoreInst>(NewInst)
-               && "Store instructions are always needed!");
-        delete NewInst;
-        return;
-      }
+  MemoryAccess &Access = Statement.getAccessFor(Load);
 
-      NewInst->replaceUsesOfWith(OldOperand, NewOperand);
-    }
+  assert(ScatteringDomain && "No scattering domain available");
 
-    Builder.Insert(NewInst);
-    BBMap[Inst] = NewInst;
+  if (Access.isStrideZero(isl_set_copy(ScatteringDomain)))
+    NewLoad = generateStrideZeroLoad(Load, ScalarMaps[0], VectorWidth);
+  else if (Access.isStrideOne(isl_set_copy(ScatteringDomain)))
+    NewLoad = generateStrideOneLoad(Load, ScalarMaps[0], VectorWidth);
+  else
+    NewLoad = generateUnknownStrideLoad(Load, ScalarMaps, VectorWidth);
 
-    if (!NewInst->getType()->isVoidTy())
-      NewInst->setName("p_" + Inst->getName());
-  }
+  VectorMap[Load] = NewLoad;
+}
 
-  bool hasVectorOperands(const Instruction *Inst, ValueMapT &VectorMap) {
-    for (Instruction::const_op_iterator OI = Inst->op_begin(),
-         OE = Inst->op_end(); OI != OE; ++OI)
-      if (VectorMap.count(*OI))
-        return true;
-    return false;
-  }
+void BlockGenerator::copyUnaryInst(const UnaryInstruction *Inst,
+                                   ValueMapT &BBMap, ValueMapT &VectorMap,
+                                   int VectorDimension, int VectorWidth) {
+  Value *NewOperand = getOperand(Inst->getOperand(0), BBMap, &VectorMap);
+  NewOperand = makeVectorOperand(NewOperand, VectorWidth);
+
+  assert(isa<CastInst>(Inst) && "Can not generate vector code for instruction");
+
+  const CastInst *Cast = dyn_cast<CastInst>(Inst);
+  VectorType *DestType = VectorType::get(Inst->getType(), VectorWidth);
+  VectorMap[Inst] = Builder.CreateCast(Cast->getOpcode(), NewOperand, DestType);
+}
 
-  int getVectorSize() {
-    return ValueMaps.size();
-  }
+void BlockGenerator::copyBinInst(const BinaryOperator *Inst, ValueMapT &BBMap,
+                                 ValueMapT &VectorMap, int VectorDimension,
+                                 int VectorWidth) {
+  Value *OpZero = Inst->getOperand(0);
+  Value *OpOne = Inst->getOperand(1);
+
+  Value *NewOpZero, *NewOpOne;
+  NewOpZero = getOperand(OpZero, BBMap, &VectorMap);
+  NewOpOne = getOperand(OpOne, BBMap, &VectorMap);
+
+  NewOpZero = makeVectorOperand(NewOpZero, VectorWidth);
+  NewOpOne = makeVectorOperand(NewOpOne, VectorWidth);
+
+  Value *NewInst = Builder.CreateBinOp(Inst->getOpcode(), NewOpZero,
+                                       NewOpOne,
+                                       Inst->getName() + "p_vec");
+  VectorMap[Inst] = NewInst;
+}
 
-  bool isVectorBlock() {
-    return getVectorSize() > 1;
-  }
+void BlockGenerator::copyVectorStore(const StoreInst *Store, ValueMapT &BBMap,
+                                     ValueMapT &VectorMap,
+                                     VectorValueMapT &ScalarMaps,
+                                     int VectorDimension, int VectorWidth) {
+  // In vector mode we only generate a store for the first dimension.
+  if (VectorDimension > 0)
+    return;
 
-  void copyInstruction(const Instruction *Inst, ValueMapT &BBMap,
-                       ValueMapT &vectorMap, VectorValueMapT &scalarMaps,
-                       int vectorDimension, int vectorWidth) {
-    // Terminator instructions control the control flow. They are explicitally
-    // expressed in the clast and do not need to be copied.
-    if (Inst->isTerminator())
-      return;
+  MemoryAccess &Access = Statement.getAccessFor(Store);
+
+  assert(ScatteringDomain && "No scattering domain available");
+
+  const Value *Pointer = Store->getPointerOperand();
+  Value *Vector = getOperand(Store->getValueOperand(), BBMap, &VectorMap);
+
+  if (Access.isStrideOne(isl_set_copy(ScatteringDomain))) {
+    Type *VectorPtrType = getVectorPtrTy(Pointer, VectorWidth);
+    Value *NewPointer = getOperand(Pointer, BBMap, &VectorMap);
 
-    if (isVectorBlock()) {
-      // If this instruction is already in the vectorMap, a vector instruction
-      // was already issued, that calculates the values of all dimensions. No
-      // need to create any more instructions.
-      if (vectorMap.count(Inst))
-        return;
+    Value *VectorPtr = Builder.CreateBitCast(NewPointer, VectorPtrType,
+                                             "vector_ptr");
+    StoreInst *Store = Builder.CreateStore(Vector, VectorPtr);
+
+    if (!Aligned)
+      Store->setAlignment(8);
+  } else {
+    for (unsigned i = 0; i < ScalarMaps.size(); i++) {
+      Value *Scalar = Builder.CreateExtractElement(Vector,
+                                                   Builder.getInt32(i));
+      Value *NewPointer = getOperand(Pointer, ScalarMaps[i]);
+      Builder.CreateStore(Scalar, NewPointer);
     }
+  }
+}
+
+void BlockGenerator::copyInstScalar(const Instruction *Inst, ValueMapT &BBMap) {
+  Instruction *NewInst = Inst->clone();
 
-    if (const LoadInst *load = dyn_cast<LoadInst>(Inst)) {
-      generateLoad(load, vectorMap, scalarMaps, vectorWidth);
+  // Replace old operands with the new ones.
+  for (Instruction::const_op_iterator OI = Inst->op_begin(),
+       OE = Inst->op_end(); OI != OE; ++OI) {
+    Value *OldOperand = *OI;
+    Value *NewOperand = getOperand(OldOperand, BBMap);
+
+    if (!NewOperand) {
+      assert(!isa<StoreInst>(NewInst)
+             && "Store instructions are always needed!");
+      delete NewInst;
       return;
     }
 
-    if (isVectorBlock() && hasVectorOperands(Inst, vectorMap)) {
-      if (const UnaryInstruction *UnaryInst = dyn_cast<UnaryInstruction>(Inst))
-        copyUnaryInst(UnaryInst, BBMap, vectorMap, vectorDimension,
-                      vectorWidth);
-      else if
-        (const BinaryOperator *binaryInst = dyn_cast<BinaryOperator>(Inst))
-        copyBinInst(binaryInst, BBMap, vectorMap, vectorDimension, vectorWidth);
-      else if (const StoreInst *store = dyn_cast<StoreInst>(Inst))
-        copyVectorStore(store, BBMap, vectorMap, scalarMaps, vectorDimension,
-                          vectorWidth);
-      else
-        llvm_unreachable("Cannot issue vector code for this instruction");
+    NewInst->replaceUsesOfWith(OldOperand, NewOperand);
+  }
 
+  Builder.Insert(NewInst);
+  BBMap[Inst] = NewInst;
+
+  if (!NewInst->getType()->isVoidTy())
+    NewInst->setName("p_" + Inst->getName());
+}
+
+bool BlockGenerator::hasVectorOperands(const Instruction *Inst,
+                                       ValueMapT &VectorMap) {
+  for (Instruction::const_op_iterator OI = Inst->op_begin(),
+       OE = Inst->op_end(); OI != OE; ++OI)
+    if (VectorMap.count(*OI))
+      return true;
+  return false;
+}
+
+int BlockGenerator::getVectorSize() {
+  return ValueMaps.size();
+}
+
+bool BlockGenerator::isVectorBlock() {
+  return getVectorSize() > 1;
+}
+
+void BlockGenerator::copyInstruction(const Instruction *Inst, ValueMapT &BBMap,
+                                     ValueMapT &VectorMap,
+                                     VectorValueMapT &ScalarMaps,
+                                     int VectorDimension, int VectorWidth) {
+  // Terminator instructions control the control flow. They are explicitally
+  // expressed in the clast and do not need to be copied.
+  if (Inst->isTerminator())
+    return;
+
+  if (isVectorBlock()) {
+    // If this instruction is already in the vectorMap, a vector instruction
+    // was already issued, that calculates the values of all dimensions. No
+    // need to create any more instructions.
+    if (VectorMap.count(Inst))
       return;
-    }
+  }
 
-    copyInstScalar(Inst, BBMap);
+  if (const LoadInst *Load = dyn_cast<LoadInst>(Inst)) {
+    generateLoad(Load, VectorMap, ScalarMaps, VectorWidth);
+    return;
   }
-  // Insert a copy of a basic block in the newly generated code.
-  //
-  // @param Builder The builder used to insert the code. It also specifies
-  //                where to insert the code.
-  // @param BB      The basic block to copy
-  // @param VMap    A map returning for any old value its new equivalent. This
-  //                is used to update the operands of the statements.
-  //                For new statements a relation old->new is inserted in this
-  //                map.
-  void copyBB(BasicBlock *BB, DominatorTree *DT) {
-    Function *F = Builder.GetInsertBlock()->getParent();
-    LLVMContext &Context = F->getContext();
-    BasicBlock *CopyBB = BasicBlock::Create(Context,
-                                            "polly." + BB->getName() + ".stmt",
-                                            F);
-    Builder.CreateBr(CopyBB);
-    DT->addNewBlock(CopyBB, Builder.GetInsertBlock());
-    Builder.SetInsertPoint(CopyBB);
-
-    // Create two maps that store the mapping from the original instructions of
-    // the old basic block to their copies in the new basic block. Those maps
-    // are basic block local.
-    //
-    // As vector code generation is supported there is one map for scalar values
-    // and one for vector values.
-    //
-    // In case we just do scalar code generation, the vectorMap is not used and
-    // the scalarMap has just one dimension, which contains the mapping.
-    //
-    // In case vector code generation is done, an instruction may either appear
-    // in the vector map once (as it is calculating >vectorwidth< values at a
-    // time. Or (if the values are calculated using scalar operations), it
-    // appears once in every dimension of the scalarMap.
-    VectorValueMapT scalarBlockMap(getVectorSize());
-    ValueMapT vectorBlockMap;
-
-    for (BasicBlock::const_iterator II = BB->begin(), IE = BB->end();
-         II != IE; ++II)
-      for (int i = 0; i < getVectorSize(); i++) {
-        if (isVectorBlock())
-          VMap = ValueMaps[i];
 
-        copyInstruction(II, scalarBlockMap[i], vectorBlockMap,
-                        scalarBlockMap, i, getVectorSize());
-      }
+  if (isVectorBlock() && hasVectorOperands(Inst, VectorMap)) {
+    if (const UnaryInstruction *UnaryInst = dyn_cast<UnaryInstruction>(Inst))
+      copyUnaryInst(UnaryInst, BBMap, VectorMap, VectorDimension, VectorWidth);
+    else if
+      (const BinaryOperator *BinaryInst = dyn_cast<BinaryOperator>(Inst))
+        copyBinInst(BinaryInst, BBMap, VectorMap, VectorDimension, VectorWidth);
+    else if (const StoreInst *Store = dyn_cast<StoreInst>(Inst))
+      copyVectorStore(Store, BBMap, VectorMap, ScalarMaps, VectorDimension,
+                      VectorWidth);
+    else
+      llvm_unreachable("Cannot issue vector code for this instruction");
+
+    return;
   }
-};
+
+  copyInstScalar(Inst, BBMap);
+}
+
+void BlockGenerator::copyBB(BasicBlock *BB, DominatorTree *DT) {
+  Function *F = Builder.GetInsertBlock()->getParent();
+  LLVMContext &Context = F->getContext();
+  BasicBlock *CopyBB = BasicBlock::Create(Context,
+                                          "polly." + BB->getName() + ".stmt",
+                                          F);
+  Builder.CreateBr(CopyBB);
+  DT->addNewBlock(CopyBB, Builder.GetInsertBlock());
+  Builder.SetInsertPoint(CopyBB);
+
+  // Create two maps that store the mapping from the original instructions of
+  // the old basic block to their copies in the new basic block. Those maps
+  // are basic block local.
+  //
+  // As vector code generation is supported there is one map for scalar values
+  // and one for vector values.
+  //
+  // In case we just do scalar code generation, the vectorMap is not used and
+  // the scalarMap has just one dimension, which contains the mapping.
+  //
+  // In case vector code generation is done, an instruction may either appear
+  // in the vector map once (as it is calculating >vectorwidth< values at a
+  // time. Or (if the values are calculated using scalar operations), it
+  // appears once in every dimension of the scalarMap.
+  VectorValueMapT ScalarBlockMap(getVectorSize());
+  ValueMapT VectorBlockMap;
+
+  for (BasicBlock::const_iterator II = BB->begin(), IE = BB->end();
+       II != IE; ++II)
+    for (int i = 0; i < getVectorSize(); i++) {
+      if (isVectorBlock())
+        VMap = ValueMaps[i];
+
+      copyInstruction(II, ScalarBlockMap[i], VectorBlockMap,
+                      ScalarBlockMap, i, getVectorSize());
+    }
+}
 
 /// Class to generate LLVM-IR that calculates the value of a clast_expr.
 class ClastExpCodeGen {





More information about the llvm-commits mailing list