[polly] r248662 - Ensure memory accesses to the same array have identical dimensionality

Tobias Grosser via llvm-commits llvm-commits at lists.llvm.org
Sat Sep 26 01:55:55 PDT 2015


Author: grosser
Date: Sat Sep 26 03:55:54 2015
New Revision: 248662

URL: http://llvm.org/viewvc/llvm-project?rev=248662&view=rev
Log:
Ensure memory accesses to the same array have identical dimensionality

When recovering multi-dimensional memory accesses, it may happen that different
accesses to the same base array are recovered with different dimensionality.
This patch ensures that the dimensionalities are unified by adding zero valued
dimensions to acesses with lower dimensionality. When starting to model
fixed-size arrays as multi-dimensional in 247906, this has not been taken
care of.

Added:
    polly/trunk/test/ScopInfo/multidim_fixedsize_different_dimensionality.ll
Modified:
    polly/trunk/include/polly/ScopInfo.h
    polly/trunk/lib/Analysis/ScopInfo.cpp

Modified: polly/trunk/include/polly/ScopInfo.h
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/include/polly/ScopInfo.h?rev=248662&r1=248661&r2=248662&view=diff
==============================================================================
--- polly/trunk/include/polly/ScopInfo.h (original)
+++ polly/trunk/include/polly/ScopInfo.h Sat Sep 26 03:55:54 2015
@@ -114,6 +114,16 @@ public:
   ScopArrayInfo(Value *BasePtr, Type *ElementType, isl_ctx *IslCtx,
                 ArrayRef<const SCEV *> DimensionSizes, bool IsPHI, Scop *S);
 
+  ///  @brief Update the sizes of the ScopArrayInfo object.
+  ///
+  ///  A ScopArrayInfo object may with certain outer dimensions not being added
+  ///  on the first creation. This function allows to update the sizes of the
+  ///  ScopArrayInfo object by adding additional outer array dimensions.
+  ///
+  ///  @param A vector of array sizes where the rightmost array sizes need to
+  ///         match the innermost array sizes already defined in SAI.
+  void updateSizes(ArrayRef<const SCEV *> Sizes);
+
   /// @brief Destructor to free the isl id of the base pointer.
   ~ScopArrayInfo();
 
@@ -182,6 +192,9 @@ public:
   /// @brief Access the ScopArrayInfo associated with an isl Id.
   static const ScopArrayInfo *getFromId(__isl_take isl_id *Id);
 
+  /// @brief Get the space of this array access.
+  __isl_give isl_space *getSpace() const;
+
 private:
   void addDerivedSAI(ScopArrayInfo *DerivedSAI) {
     DerivedSAIs.insert(DerivedSAI);
@@ -210,6 +223,9 @@ private:
 
   /// @brief Is this PHI node specific storage?
   bool IsPHI;
+
+  /// @brief The scop this SAI object belongs to.
+  Scop &S;
 };
 
 /// @brief Represent memory accesses in statements.
@@ -596,6 +612,16 @@ public:
   /// @brief Align the parameters in the access relation to the scop context
   void realignParams();
 
+  /// @brief Update the dimensionality of the memory access.
+  ///
+  /// During scop construction some memory accesses may not be constructed with
+  /// their full dimensionality, but outer dimensions that may have been omitted
+  /// if they took the value 'zero'. By updating the dimensionality of the
+  /// statement we add additional zero-valued dimensions to match the
+  /// dimensionality of the ScopArrayInfo object that belongs to this memory
+  /// access.
+  void updateDimensionality();
+
   /// @brief Get identifier for the memory access.
   ///
   /// This identifier is unique for all accesses that belong to the same scop
@@ -1131,6 +1157,15 @@ private:
   /// @param R          The region we build the statement for (or null).
   ScopStmt *addScopStmt(BasicBlock *BB, Region *R);
 
+  /// @param Update access dimensionalities.
+  ///
+  /// When detecting memory accesses different accesses to the same array may
+  /// have built with different dimensionality, as outer zero-values dimensions
+  /// may not have been recognized as separate dimensions. This function goes
+  /// again over all memory accesses and updates their dimensionality to match
+  /// the dimensionality of the underlying ScopArrayInfo object.
+  void updateAccessDimensionality();
+
   /// @brief Build Schedule and ScopStmts.
   ///
   /// @param R  The current region traversed.

Modified: polly/trunk/lib/Analysis/ScopInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/Analysis/ScopInfo.cpp?rev=248662&r1=248661&r2=248662&view=diff
==============================================================================
--- polly/trunk/lib/Analysis/ScopInfo.cpp (original)
+++ polly/trunk/lib/Analysis/ScopInfo.cpp Sat Sep 26 03:55:54 2015
@@ -160,24 +160,48 @@ static const ScopArrayInfo *identifyBase
 }
 
 ScopArrayInfo::ScopArrayInfo(Value *BasePtr, Type *ElementType, isl_ctx *Ctx,
-                             ArrayRef<const SCEV *> DimensionSizes, bool IsPHI,
-                             Scop *S)
-    : BasePtr(BasePtr), ElementType(ElementType),
-      DimensionSizes(DimensionSizes.begin(), DimensionSizes.end()),
-      IsPHI(IsPHI) {
+                             ArrayRef<const SCEV *> Sizes, bool IsPHI, Scop *S)
+    : BasePtr(BasePtr), ElementType(ElementType), IsPHI(IsPHI), S(*S) {
   std::string BasePtrName =
       getIslCompatibleName("MemRef_", BasePtr, IsPHI ? "__phi" : "");
   Id = isl_id_alloc(Ctx, BasePtrName.c_str(), this);
-  for (const SCEV *Expr : DimensionSizes) {
-    isl_pw_aff *Size = S->getPwAff(Expr);
-    DimensionSizesPw.push_back(Size);
-  }
 
+  updateSizes(Sizes);
   BasePtrOriginSAI = identifyBasePtrOriginSAI(S, BasePtr);
   if (BasePtrOriginSAI)
     const_cast<ScopArrayInfo *>(BasePtrOriginSAI)->addDerivedSAI(this);
 }
 
+__isl_give isl_space *ScopArrayInfo::getSpace() const {
+  auto Space =
+      isl_space_set_alloc(isl_id_get_ctx(Id), 0, getNumberOfDimensions());
+  Space = isl_space_set_tuple_id(Space, isl_dim_set, isl_id_copy(Id));
+  return Space;
+}
+
+void ScopArrayInfo::updateSizes(ArrayRef<const SCEV *> NewSizes) {
+#ifndef NDEBUG
+  int SharedDims = std::min(NewSizes.size(), DimensionSizes.size());
+  int ExtraDimsNew = NewSizes.size() - SharedDims;
+  int ExtraDimsOld = DimensionSizes.size() - SharedDims;
+  for (int i = 0; i < SharedDims; i++) {
+    assert(NewSizes[i + ExtraDimsNew] == DimensionSizes[i + ExtraDimsOld] &&
+           "Array update with non-matching dimension sizes");
+  }
+#endif
+
+  DimensionSizes.clear();
+  DimensionSizes.insert(DimensionSizes.begin(), NewSizes.begin(),
+                        NewSizes.end());
+  for (isl_pw_aff *Size : DimensionSizesPw)
+    isl_pw_aff_free(Size);
+  DimensionSizesPw.clear();
+  for (const SCEV *Expr : DimensionSizes) {
+    isl_pw_aff *Size = S.getPwAff(Expr);
+    DimensionSizesPw.push_back(Size);
+  }
+}
+
 ScopArrayInfo::~ScopArrayInfo() {
   isl_id_free(Id);
   for (isl_pw_aff *Size : DimensionSizesPw)
@@ -227,6 +251,26 @@ const ScopArrayInfo *ScopArrayInfo::getF
   return SAI;
 }
 
+void MemoryAccess::updateDimensionality() {
+  auto ArraySpace = getScopArrayInfo()->getSpace();
+  auto AccessSpace = isl_space_range(isl_map_get_space(AccessRelation));
+
+  auto DimsArray = isl_space_dim(ArraySpace, isl_dim_set);
+  auto DimsAccess = isl_space_dim(AccessSpace, isl_dim_set);
+  auto DimsMissing = DimsArray - DimsAccess;
+
+  auto Map = isl_map_from_domain_and_range(isl_set_universe(AccessSpace),
+                                           isl_set_universe(ArraySpace));
+
+  for (unsigned i = 0; i < DimsMissing; i++)
+    Map = isl_map_fix_si(Map, isl_dim_out, i, 0);
+
+  for (unsigned i = DimsMissing; i < DimsArray; i++)
+    Map = isl_map_equate(Map, isl_dim_in, i - DimsMissing, isl_dim_out, i);
+
+  AccessRelation = isl_map_apply_range(AccessRelation, Map);
+}
+
 const std::string
 MemoryAccess::getReductionOperatorStr(MemoryAccess::ReductionType RT) {
   switch (RT) {
@@ -2146,6 +2190,7 @@ void Scop::init(LoopInfo &LI, ScopDetect
   Loop *L = getLoopSurroundingRegion(R, LI);
   LoopSchedules[L];
   buildSchedule(&R, LI, SD, LoopSchedules);
+  updateAccessDimensionality();
   Schedule = LoopSchedules[L].first;
 
   realignParams();
@@ -2178,13 +2223,23 @@ Scop::~Scop() {
   }
 }
 
+void Scop::updateAccessDimensionality() {
+  for (auto &Stmt : *this)
+    for (auto &Access : Stmt)
+      Access->updateDimensionality();
+}
+
 const ScopArrayInfo *
 Scop::getOrCreateScopArrayInfo(Value *BasePtr, Type *AccessType,
                                ArrayRef<const SCEV *> Sizes, bool IsPHI) {
   auto &SAI = ScopArrayInfoMap[std::make_pair(BasePtr, IsPHI)];
-  if (!SAI)
+  if (!SAI) {
     SAI.reset(new ScopArrayInfo(BasePtr, AccessType, getIslCtx(), Sizes, IsPHI,
                                 this));
+  } else {
+    if (Sizes.size() > SAI->getNumberOfDimensions())
+      SAI->updateSizes(Sizes);
+  }
   return SAI.get();
 }
 

Added: polly/trunk/test/ScopInfo/multidim_fixedsize_different_dimensionality.ll
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/test/ScopInfo/multidim_fixedsize_different_dimensionality.ll?rev=248662&view=auto
==============================================================================
--- polly/trunk/test/ScopInfo/multidim_fixedsize_different_dimensionality.ll (added)
+++ polly/trunk/test/ScopInfo/multidim_fixedsize_different_dimensionality.ll Sat Sep 26 03:55:54 2015
@@ -0,0 +1,257 @@
+; RUN: opt %loadPolly -polly-scops -analyze < %s | FileCheck %s
+;
+;    #define N 400
+;
+;    void first_higher_dimensional(float A[][N]) {
+;      for (long i = 0; i < N; i++)
+;        for (long j = 0; j < N; j++)
+;          A[i][j] += i + j;
+;
+;      A[0][0] += A[100][100];
+;
+;      for (long i = 0; i < N; i++)
+;        for (long j = 0; j < N; j++)
+;          A[i][j] += i + j;
+;    }
+
+; CHECK: Stmt_bb7
+; CHECK:       Domain :=
+; CHECK:           { Stmt_bb7[i0, i1] : i0 <= 399 and i0 >= 0 and i1 <= 399 and i1 >= 0 };
+; CHECK:       Schedule :=
+; CHECK:           { Stmt_bb7[i0, i1] -> [0, i0, i1] };
+; CHECK:       ReadAccess :=       [Reduction Type: NONE] [Scalar: 0]
+; CHECK:           { Stmt_bb7[i0, i1] -> MemRef_A[i0, i1] };
+; CHECK:       MustWriteAccess :=  [Reduction Type: NONE] [Scalar: 0]
+; CHECK:           { Stmt_bb7[i0, i1] -> MemRef_A[i0, i1] };
+; CHECK: Stmt_bb17
+; CHECK:       Domain :=
+; CHECK:           { Stmt_bb17[] };
+; CHECK:       Schedule :=
+; CHECK:           { Stmt_bb17[] -> [1, 0, 0] };
+; CHECK:       ReadAccess :=       [Reduction Type: NONE] [Scalar: 0]
+; CHECK:           { Stmt_bb17[] -> MemRef_A[100, 100] };
+; CHECK:       ReadAccess :=       [Reduction Type: NONE] [Scalar: 0]
+; CHECK:           { Stmt_bb17[] -> MemRef_A[0, 0] };
+; CHECK:       MustWriteAccess :=  [Reduction Type: NONE] [Scalar: 0]
+; CHECK:           { Stmt_bb17[] -> MemRef_A[0, 0] };
+; CHECK: Stmt_bb26
+; CHECK:       Domain :=
+; CHECK:           { Stmt_bb26[i0, i1] : i0 <= 399 and i0 >= 0 and i1 <= 399 and i1 >= 0 };
+; CHECK:       Schedule :=
+; CHECK:           { Stmt_bb26[i0, i1] -> [2, i0, i1] };
+; CHECK:       ReadAccess :=       [Reduction Type: NONE] [Scalar: 0]
+; CHECK:           { Stmt_bb26[i0, i1] -> MemRef_A[i0, i1] };
+; CHECK:       MustWriteAccess :=  [Reduction Type: NONE] [Scalar: 0]
+; CHECK:           { Stmt_bb26[i0, i1] -> MemRef_A[i0, i1] };
+
+;    void first_lower_dimensional(float A[][N], float B[][N]) {
+;      for (long i = 0; i < N; i++)
+;        for (long j = 0; j < N; j++)
+;          B[i][j] += i + j;
+;
+;      A[0][0] += B[100][100];
+;
+;      for (long i = 0; i < N; i++)
+;        for (long j = 0; j < N; j++)
+;          A[i][j] += i + j;
+;    }
+
+; CHECK: Statements {
+; CHECK:   Stmt_bb7
+; CHECK:         Domain :=
+; CHECK:             { Stmt_bb7[i0, i1] : i0 <= 399 and i0 >= 0 and i1 <= 399 and i1 >= 0 };
+; CHECK:         Schedule :=
+; CHECK:             { Stmt_bb7[i0, i1] -> [0, i0, i1] };
+; CHECK:         ReadAccess :=       [Reduction Type: NONE] [Scalar: 0]
+; CHECK:             { Stmt_bb7[i0, i1]  -> MemRef_B[i0, i1] };
+; CHECK:         MustWriteAccess :=  [Reduction Type: NONE] [Scalar: 0]
+; CHECK:             { Stmt_bb7[i0, i1] -> MemRef_B[i0, i1] };
+; CHECK:   Stmt_bb17
+; CHECK:         Domain :=
+; CHECK:             { Stmt_bb17[] };
+; CHECK:         Schedule :=
+; CHECK:             { Stmt_bb17[] -> [1, 0, 0] };
+; CHECK:         ReadAccess :=       [Reduction Type: NONE] [Scalar: 0]
+; CHECK:             { Stmt_bb17[] -> MemRef_B[100, 100] };
+; CHECK:         ReadAccess :=       [Reduction Type: NONE] [Scalar: 0]
+; CHECK:             { Stmt_bb17[] -> MemRef_A[0, 0] };
+; CHECK:         MustWriteAccess :=  [Reduction Type: NONE] [Scalar: 0]
+; CHECK:             { Stmt_bb17[] -> MemRef_A[0, 0] };
+; CHECK:   Stmt_bb26
+; CHECK:         Domain :=
+; CHECK:             { Stmt_bb26[i0, i1] : i0 <= 399 and i0 >= 0 and i1 <= 399 and i1 >= 0 };
+; CHECK:         Schedule :=
+; CHECK:             { Stmt_bb26[i0, i1] -> [2, i0, i1] };
+; CHECK:         ReadAccess :=       [Reduction Type: NONE] [Scalar: 0]
+; CHECK:             { Stmt_bb26[i0, i1] -> MemRef_A[i0, i1] };
+; CHECK:         MustWriteAccess :=  [Reduction Type: NONE] [Scalar: 0]
+; CHECK:             { Stmt_bb26[i0, i1] -> MemRef_A[i0, i1] };
+
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+define void @first_higher_dimensional([400 x float]* %A) {
+bb:
+  br label %bb4
+
+bb4:                                              ; preds = %bb15, %bb
+  %i.0 = phi i64 [ 0, %bb ], [ %tmp16, %bb15 ]
+  %exitcond3 = icmp ne i64 %i.0, 400
+  br i1 %exitcond3, label %bb5, label %bb17
+
+bb5:                                              ; preds = %bb4
+  br label %bb6
+
+bb6:                                              ; preds = %bb12, %bb5
+  %j.0 = phi i64 [ 0, %bb5 ], [ %tmp13, %bb12 ]
+  %exitcond2 = icmp ne i64 %j.0, 400
+  br i1 %exitcond2, label %bb7, label %bb14
+
+bb7:                                              ; preds = %bb6
+  %tmp = add nuw nsw i64 %i.0, %j.0
+  %tmp8 = sitofp i64 %tmp to float
+  %tmp9 = getelementptr inbounds [400 x float], [400 x float]* %A, i64 %i.0, i64 %j.0
+  %tmp10 = load float, float* %tmp9, align 4
+  %tmp11 = fadd float %tmp10, %tmp8
+  store float %tmp11, float* %tmp9, align 4
+  br label %bb12
+
+bb12:                                             ; preds = %bb7
+  %tmp13 = add nuw nsw i64 %j.0, 1
+  br label %bb6
+
+bb14:                                             ; preds = %bb6
+  br label %bb15
+
+bb15:                                             ; preds = %bb14
+  %tmp16 = add nuw nsw i64 %i.0, 1
+  br label %bb4
+
+bb17:                                             ; preds = %bb4
+  %tmp18 = getelementptr inbounds [400 x float], [400 x float]* %A, i64 100, i64 100
+  %tmp19 = load float, float* %tmp18, align 4
+  %tmp20 = getelementptr inbounds [400 x float], [400 x float]* %A, i64 0, i64 0
+  %tmp21 = load float, float* %tmp20, align 4
+  %tmp22 = fadd float %tmp21, %tmp19
+  store float %tmp22, float* %tmp20, align 4
+  br label %bb23
+
+bb23:                                             ; preds = %bb35, %bb17
+  %i1.0 = phi i64 [ 0, %bb17 ], [ %tmp36, %bb35 ]
+  %exitcond1 = icmp ne i64 %i1.0, 400
+  br i1 %exitcond1, label %bb24, label %bb37
+
+bb24:                                             ; preds = %bb23
+  br label %bb25
+
+bb25:                                             ; preds = %bb32, %bb24
+  %j2.0 = phi i64 [ 0, %bb24 ], [ %tmp33, %bb32 ]
+  %exitcond = icmp ne i64 %j2.0, 400
+  br i1 %exitcond, label %bb26, label %bb34
+
+bb26:                                             ; preds = %bb25
+  %tmp27 = add nuw nsw i64 %i1.0, %j2.0
+  %tmp28 = sitofp i64 %tmp27 to float
+  %tmp29 = getelementptr inbounds [400 x float], [400 x float]* %A, i64 %i1.0, i64 %j2.0
+  %tmp30 = load float, float* %tmp29, align 4
+  %tmp31 = fadd float %tmp30, %tmp28
+  store float %tmp31, float* %tmp29, align 4
+  br label %bb32
+
+bb32:                                             ; preds = %bb26
+  %tmp33 = add nuw nsw i64 %j2.0, 1
+  br label %bb25
+
+bb34:                                             ; preds = %bb25
+  br label %bb35
+
+bb35:                                             ; preds = %bb34
+  %tmp36 = add nuw nsw i64 %i1.0, 1
+  br label %bb23
+
+bb37:                                             ; preds = %bb23
+  ret void
+}
+
+define void @first_lower_dimensional([400 x float]* %A, [400 x float]* %B) {
+bb:
+  br label %bb4
+
+bb4:                                              ; preds = %bb15, %bb
+  %i.0 = phi i64 [ 0, %bb ], [ %tmp16, %bb15 ]
+  %exitcond3 = icmp ne i64 %i.0, 400
+  br i1 %exitcond3, label %bb5, label %bb17
+
+bb5:                                              ; preds = %bb4
+  br label %bb6
+
+bb6:                                              ; preds = %bb12, %bb5
+  %j.0 = phi i64 [ 0, %bb5 ], [ %tmp13, %bb12 ]
+  %exitcond2 = icmp ne i64 %j.0, 400
+  br i1 %exitcond2, label %bb7, label %bb14
+
+bb7:                                              ; preds = %bb6
+  %tmp = add nuw nsw i64 %i.0, %j.0
+  %tmp8 = sitofp i64 %tmp to float
+  %tmp9 = getelementptr inbounds [400 x float], [400 x float]* %B, i64 %i.0, i64 %j.0
+  %tmp10 = load float, float* %tmp9, align 4
+  %tmp11 = fadd float %tmp10, %tmp8
+  store float %tmp11, float* %tmp9, align 4
+  br label %bb12
+
+bb12:                                             ; preds = %bb7
+  %tmp13 = add nuw nsw i64 %j.0, 1
+  br label %bb6
+
+bb14:                                             ; preds = %bb6
+  br label %bb15
+
+bb15:                                             ; preds = %bb14
+  %tmp16 = add nuw nsw i64 %i.0, 1
+  br label %bb4
+
+bb17:                                             ; preds = %bb4
+  %tmp18 = getelementptr inbounds [400 x float], [400 x float]* %B, i64 100, i64 100
+  %tmp19 = load float, float* %tmp18, align 4
+  %tmp20 = getelementptr inbounds [400 x float], [400 x float]* %A, i64 0, i64 0
+  %tmp21 = load float, float* %tmp20, align 4
+  %tmp22 = fadd float %tmp21, %tmp19
+  store float %tmp22, float* %tmp20, align 4
+  br label %bb23
+
+bb23:                                             ; preds = %bb35, %bb17
+  %i1.0 = phi i64 [ 0, %bb17 ], [ %tmp36, %bb35 ]
+  %exitcond1 = icmp ne i64 %i1.0, 400
+  br i1 %exitcond1, label %bb24, label %bb37
+
+bb24:                                             ; preds = %bb23
+  br label %bb25
+
+bb25:                                             ; preds = %bb32, %bb24
+  %j2.0 = phi i64 [ 0, %bb24 ], [ %tmp33, %bb32 ]
+  %exitcond = icmp ne i64 %j2.0, 400
+  br i1 %exitcond, label %bb26, label %bb34
+
+bb26:                                             ; preds = %bb25
+  %tmp27 = add nuw nsw i64 %i1.0, %j2.0
+  %tmp28 = sitofp i64 %tmp27 to float
+  %tmp29 = getelementptr inbounds [400 x float], [400 x float]* %A, i64 %i1.0, i64 %j2.0
+  %tmp30 = load float, float* %tmp29, align 4
+  %tmp31 = fadd float %tmp30, %tmp28
+  store float %tmp31, float* %tmp29, align 4
+  br label %bb32
+
+bb32:                                             ; preds = %bb26
+  %tmp33 = add nuw nsw i64 %j2.0, 1
+  br label %bb25
+
+bb34:                                             ; preds = %bb25
+  br label %bb35
+
+bb35:                                             ; preds = %bb34
+  %tmp36 = add nuw nsw i64 %i1.0, 1
+  br label %bb23
+
+bb37:                                             ; preds = %bb23
+  ret void
+}




More information about the llvm-commits mailing list