[polly] r277263 - Extend the jscop interface to allow the user to declare new arrays and to reference these arrays from access expressions

Roman Gareev via llvm-commits llvm-commits at lists.llvm.org
Sat Jul 30 02:25:52 PDT 2016


Author: romangareev
Date: Sat Jul 30 04:25:51 2016
New Revision: 277263

URL: http://llvm.org/viewvc/llvm-project?rev=277263&view=rev
Log:
Extend the jscop interface to allow the user to declare new arrays and to reference these arrays from access expressions

Extend the jscop interface to allow the user to export arrays. It is required
that already existing arrays of the list of arrays correspond to arrays
of the SCoP. Each array that is appended to the list will be newly created.
Furthermore, we allow the user to modify access expressions to reference
any array in case it has the same element type.

Reviewed-by: Tobias Grosser <tobias at grosser.es>

Differential Revision: https://reviews.llvm.org/D22828

Added:
    polly/trunk/test/Isl/CodeGen/MemAccess/create_arrays.ll
    polly/trunk/test/Isl/CodeGen/MemAccess/create_arrays___%bb9---%bb26.jscop
    polly/trunk/test/Isl/CodeGen/MemAccess/create_arrays___%bb9---%bb26.jscop.transformed
Modified:
    polly/trunk/include/polly/CodeGen/IslNodeBuilder.h
    polly/trunk/include/polly/ScopInfo.h
    polly/trunk/lib/Analysis/ScopInfo.cpp
    polly/trunk/lib/CodeGen/BlockGenerators.cpp
    polly/trunk/lib/CodeGen/CodeGeneration.cpp
    polly/trunk/lib/CodeGen/IslNodeBuilder.cpp
    polly/trunk/lib/CodeGen/PPCGCodeGeneration.cpp
    polly/trunk/lib/Exchange/JSONExporter.cpp

Modified: polly/trunk/include/polly/CodeGen/IslNodeBuilder.h
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/include/polly/CodeGen/IslNodeBuilder.h?rev=277263&r1=277262&r2=277263&view=diff
==============================================================================
--- polly/trunk/include/polly/CodeGen/IslNodeBuilder.h (original)
+++ polly/trunk/include/polly/CodeGen/IslNodeBuilder.h Sat Jul 30 04:25:51 2016
@@ -55,6 +55,9 @@ public:
   void addParameters(__isl_take isl_set *Context);
   void create(__isl_take isl_ast_node *Node);
 
+  /// @brief Allocate memory for all new arrays created by Polly.
+  void allocateNewArrays();
+
   /// @brief Preload all memory loads that are invariant.
   bool preloadInvariantLoads();
 

Modified: polly/trunk/include/polly/ScopInfo.h
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/include/polly/ScopInfo.h?rev=277263&r1=277262&r2=277263&view=diff
==============================================================================
--- polly/trunk/include/polly/ScopInfo.h (original)
+++ polly/trunk/include/polly/ScopInfo.h Sat Jul 30 04:25:51 2016
@@ -231,9 +231,10 @@ public:
   /// @param Kind           The kind of the array object.
   /// @param DL             The data layout of the module.
   /// @param S              The scop this array object belongs to.
+  /// @param BaseName       The optional name of this memory reference.
   ScopArrayInfo(Value *BasePtr, Type *ElementType, isl_ctx *IslCtx,
                 ArrayRef<const SCEV *> DimensionSizes, enum MemoryKind Kind,
-                const DataLayout &DL, Scop *S);
+                const DataLayout &DL, Scop *S, const char *BaseName = nullptr);
 
   ///  @brief Update the element type of the ScopArrayInfo object.
   ///
@@ -1398,9 +1399,14 @@ private:
   /// @brief The affinator used to translate SCEVs to isl expressions.
   SCEVAffinator Affinator;
 
-  typedef MapVector<std::pair<AssertingVH<const Value>, int>,
-                    std::unique_ptr<ScopArrayInfo>>
+  typedef std::map<std::pair<AssertingVH<const Value>, int>,
+                   std::unique_ptr<ScopArrayInfo>>
       ArrayInfoMapTy;
+
+  typedef StringMap<std::unique_ptr<ScopArrayInfo>> ArrayNameMapTy;
+
+  typedef SetVector<ScopArrayInfo *> ArrayInfoSetTy;
+
   /// @brief A map to remember ScopArrayInfo objects for all base pointers.
   ///
   /// As PHI nodes may have two array info objects associated, we add a flag
@@ -1408,6 +1414,14 @@ private:
   /// and the normal one.
   ArrayInfoMapTy ScopArrayInfoMap;
 
+  /// @brief A map to remember ScopArrayInfo objects for all names of memory
+  ///        references.
+  ArrayNameMapTy ScopArrayNameMap;
+
+  /// @brief A set to remember ScopArrayInfo objects.
+  /// @see Scop::ScopArrayInfoMap
+  ArrayInfoSetTy ScopArrayInfoSet;
+
   /// @brief The assumptions under which this scop was built.
   ///
   /// When constructing a scop sometimes the exact representation of a statement
@@ -1855,21 +1869,21 @@ public:
   /// could be executed.
   bool isEmpty() const { return Stmts.empty(); }
 
-  typedef ArrayInfoMapTy::iterator array_iterator;
-  typedef ArrayInfoMapTy::const_iterator const_array_iterator;
-  typedef iterator_range<ArrayInfoMapTy::iterator> array_range;
-  typedef iterator_range<ArrayInfoMapTy::const_iterator> const_array_range;
+  typedef ArrayInfoSetTy::iterator array_iterator;
+  typedef ArrayInfoSetTy::const_iterator const_array_iterator;
+  typedef iterator_range<ArrayInfoSetTy::iterator> array_range;
+  typedef iterator_range<ArrayInfoSetTy::const_iterator> const_array_range;
 
-  inline array_iterator array_begin() { return ScopArrayInfoMap.begin(); }
+  inline array_iterator array_begin() { return ScopArrayInfoSet.begin(); }
 
-  inline array_iterator array_end() { return ScopArrayInfoMap.end(); }
+  inline array_iterator array_end() { return ScopArrayInfoSet.end(); }
 
   inline const_array_iterator array_begin() const {
-    return ScopArrayInfoMap.begin();
+    return ScopArrayInfoSet.begin();
   }
 
   inline const_array_iterator array_end() const {
-    return ScopArrayInfoMap.end();
+    return ScopArrayInfoSet.end();
   }
 
   inline array_range arrays() {
@@ -2148,10 +2162,21 @@ public:
   ///
   /// @param ElementType The type of the elements stored in this array.
   /// @param Kind        The kind of the array info object.
+  /// @param BaseName    The optional name of this memory reference.
   const ScopArrayInfo *getOrCreateScopArrayInfo(Value *BasePtr,
                                                 Type *ElementType,
                                                 ArrayRef<const SCEV *> Sizes,
-                                                ScopArrayInfo::MemoryKind Kind);
+                                                ScopArrayInfo::MemoryKind Kind,
+                                                const char *BaseName = nullptr);
+
+  /// @brief Create an array and return the corresponding ScopArrayInfo object.
+  ///
+  /// @param ElementType The type of the elements stored in this array.
+  /// @param BaseName    The name of this memory reference.
+  /// @param Sizes       The sizes of dimensions.
+  const ScopArrayInfo *createScopArrayInfo(Type *ElementType,
+                                           const std::string &BaseName,
+                                           const std::vector<unsigned> &Sizes);
 
   /// @brief Return the cached ScopArrayInfo object for @p BasePtr.
   ///
@@ -2165,7 +2190,11 @@ public:
   /// @param BasePtr The base pointer of the ScopArrayInfo object to invalidate.
   /// @param Kind    The Kind of the ScopArrayInfo object.
   void invalidateScopArrayInfo(Value *BasePtr, ScopArrayInfo::MemoryKind Kind) {
-    ScopArrayInfoMap.erase(std::make_pair(BasePtr, Kind));
+    auto It = ScopArrayInfoMap.find(std::make_pair(BasePtr, Kind));
+    if (It == ScopArrayInfoMap.end())
+      return;
+    ScopArrayInfoSet.remove(It->second.get());
+    ScopArrayInfoMap.erase(It);
   }
 
   void setContext(isl_set *NewContext);
@@ -2275,6 +2304,10 @@ public:
   ///   >0 for other loops in the SCoP
   ///   -1 if @p L is nullptr or there is no outermost loop in the SCoP
   int getRelativeLoopDepth(const Loop *L) const;
+
+  /// @brief Find the ScopArrayInfo associated with an isl Id
+  ///        that has name @p Name.
+  ScopArrayInfo *getArrayInfoByName(const std::string BaseName);
 };
 
 /// @brief Print Scop scop to raw_ostream O.

Modified: polly/trunk/lib/Analysis/ScopInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/Analysis/ScopInfo.cpp?rev=277263&r1=277262&r2=277263&view=diff
==============================================================================
--- polly/trunk/lib/Analysis/ScopInfo.cpp (original)
+++ polly/trunk/lib/Analysis/ScopInfo.cpp Sat Jul 30 04:25:51 2016
@@ -169,13 +169,21 @@ static const ScopArrayInfo *identifyBase
 
 ScopArrayInfo::ScopArrayInfo(Value *BasePtr, Type *ElementType, isl_ctx *Ctx,
                              ArrayRef<const SCEV *> Sizes, enum MemoryKind Kind,
-                             const DataLayout &DL, Scop *S)
+                             const DataLayout &DL, Scop *S,
+                             const char *BaseName)
     : BasePtr(BasePtr), ElementType(ElementType), Kind(Kind), DL(DL), S(*S) {
   std::string BasePtrName =
-      getIslCompatibleName("MemRef_", BasePtr, Kind == MK_PHI ? "__phi" : "");
+      BaseName ? BaseName : getIslCompatibleName("MemRef_", BasePtr,
+                                                 Kind == MK_PHI ? "__phi" : "");
   Id = isl_id_alloc(Ctx, BasePtrName.c_str(), this);
 
   updateSizes(Sizes);
+
+  if (!BasePtr) {
+    BasePtrOriginSAI = nullptr;
+    return;
+  }
+
   BasePtrOriginSAI = identifyBasePtrOriginSAI(S, BasePtr);
   if (BasePtrOriginSAI)
     const_cast<ScopArrayInfo *>(BasePtrOriginSAI)->addDerivedSAI(this);
@@ -3133,7 +3141,9 @@ Scop::~Scop() {
   // Explicitly release all Scop objects and the underlying isl objects before
   // we relase the isl context.
   Stmts.clear();
+  ScopArrayInfoSet.clear();
   ScopArrayInfoMap.clear();
+  ScopArrayNameMap.clear();
   AccFuncMap.clear();
 }
 
@@ -3476,15 +3486,19 @@ void Scop::hoistInvariantLoads() {
   isl_union_map_free(Writes);
 }
 
-const ScopArrayInfo *
-Scop::getOrCreateScopArrayInfo(Value *BasePtr, Type *ElementType,
-                               ArrayRef<const SCEV *> Sizes,
-                               ScopArrayInfo::MemoryKind Kind) {
-  auto &SAI = ScopArrayInfoMap[std::make_pair(BasePtr, Kind)];
+const ScopArrayInfo *Scop::getOrCreateScopArrayInfo(
+    Value *BasePtr, Type *ElementType, ArrayRef<const SCEV *> Sizes,
+    ScopArrayInfo::MemoryKind Kind, const char *BaseName) {
+  assert((BasePtr || BaseName) &&
+         "BasePtr and BaseName can not be nullptr at the same time.");
+  assert(!(BasePtr && BaseName) && "BaseName is redundant.");
+  auto &SAI = BasePtr ? ScopArrayInfoMap[std::make_pair(BasePtr, Kind)]
+                      : ScopArrayNameMap[BaseName];
   if (!SAI) {
     auto &DL = getFunction().getParent()->getDataLayout();
     SAI.reset(new ScopArrayInfo(BasePtr, ElementType, getIslCtx(), Sizes, Kind,
-                                DL, this));
+                                DL, this, BaseName));
+    ScopArrayInfoSet.insert(SAI.get());
   } else {
     SAI->updateElementType(ElementType);
     // In case of mismatching array sizes, we bail out by setting the run-time
@@ -3495,6 +3509,21 @@ Scop::getOrCreateScopArrayInfo(Value *Ba
   return SAI.get();
 }
 
+const ScopArrayInfo *
+Scop::createScopArrayInfo(Type *ElementType, const std::string &BaseName,
+                          const std::vector<unsigned> &Sizes) {
+  auto *DimSizeType = Type::getInt64Ty(getSE()->getContext());
+  std::vector<const SCEV *> SCEVSizes;
+
+  for (auto size : Sizes)
+    SCEVSizes.push_back(getSE()->getConstant(DimSizeType, size, false));
+
+  auto *SAI =
+      getOrCreateScopArrayInfo(nullptr, ElementType, SCEVSizes,
+                               ScopArrayInfo::MK_Array, BaseName.c_str());
+  return SAI;
+}
+
 const ScopArrayInfo *Scop::getScopArrayInfo(Value *BasePtr,
                                             ScopArrayInfo::MemoryKind Kind) {
   auto *SAI = ScopArrayInfoMap[std::make_pair(BasePtr, Kind)].get();
@@ -3781,14 +3810,14 @@ void Scop::printArrayInfo(raw_ostream &O
   OS << "Arrays {\n";
 
   for (auto &Array : arrays())
-    Array.second->print(OS);
+    Array->print(OS);
 
   OS.indent(4) << "}\n";
 
   OS.indent(4) << "Arrays (Bounds as pw_affs) {\n";
 
   for (auto &Array : arrays())
-    Array.second->print(OS, /* SizeAsPwAff */ true);
+    Array->print(OS, /* SizeAsPwAff */ true);
 
   OS.indent(4) << "}\n";
 }
@@ -4187,6 +4216,14 @@ int Scop::getRelativeLoopDepth(const Loo
   return L->getLoopDepth() - OuterLoop->getLoopDepth();
 }
 
+ScopArrayInfo *Scop::getArrayInfoByName(const std::string BaseName) {
+  for (auto &SAI : arrays()) {
+    if (SAI->getName() == BaseName)
+      return SAI;
+  }
+  return nullptr;
+}
+
 //===----------------------------------------------------------------------===//
 void ScopInfoRegionPass::getAnalysisUsage(AnalysisUsage &AU) const {
   AU.addRequired<LoopInfoWrapperPass>();

Modified: polly/trunk/lib/CodeGen/BlockGenerators.cpp
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/CodeGen/BlockGenerators.cpp?rev=277263&r1=277262&r2=277263&view=diff
==============================================================================
--- polly/trunk/lib/CodeGen/BlockGenerators.cpp (original)
+++ polly/trunk/lib/CodeGen/BlockGenerators.cpp Sat Jul 30 04:25:51 2016
@@ -485,8 +485,7 @@ void BlockGenerator::createScalarInitial
 
   Builder.SetInsertPoint(StartBB->getTerminator());
 
-  for (auto &Pair : S.arrays()) {
-    auto &Array = Pair.second;
+  for (auto &Array : S.arrays()) {
     if (Array->getNumberOfDimensions() != 0)
       continue;
     if (Array->isPHIKind()) {
@@ -576,8 +575,7 @@ void BlockGenerator::createScalarFinaliz
 }
 
 void BlockGenerator::findOutsideUsers(Scop &S) {
-  for (auto &Pair : S.arrays()) {
-    auto &Array = Pair.second;
+  for (auto &Array : S.arrays()) {
 
     if (Array->getNumberOfDimensions() != 0)
       continue;
@@ -613,8 +611,7 @@ void BlockGenerator::createExitPHINodeMe
 
   Builder.SetInsertPoint(OptExitBB->getTerminator());
 
-  for (auto &Pair : S.arrays()) {
-    auto &SAI = Pair.second;
+  for (auto &SAI : S.arrays()) {
     auto *Val = SAI->getBasePtr();
 
     // Only Value-like scalars need a merge PHI. Exit block PHIs receive either

Modified: polly/trunk/lib/CodeGen/CodeGeneration.cpp
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/CodeGen/CodeGeneration.cpp?rev=277263&r1=277262&r2=277263&view=diff
==============================================================================
--- polly/trunk/lib/CodeGen/CodeGeneration.cpp (original)
+++ polly/trunk/lib/CodeGen/CodeGeneration.cpp Sat Jul 30 04:25:51 2016
@@ -189,6 +189,7 @@ public:
 
       isl_ast_node_free(AstRoot);
     } else {
+      NodeBuilder.allocateNewArrays();
 
       NodeBuilder.addParameters(S.getContext());
 

Modified: polly/trunk/lib/CodeGen/IslNodeBuilder.cpp
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/CodeGen/IslNodeBuilder.cpp?rev=277263&r1=277262&r2=277263&view=diff
==============================================================================
--- polly/trunk/lib/CodeGen/IslNodeBuilder.cpp (original)
+++ polly/trunk/lib/CodeGen/IslNodeBuilder.cpp Sat Jul 30 04:25:51 2016
@@ -1157,6 +1157,32 @@ bool IslNodeBuilder::preloadInvariantEqu
   return true;
 }
 
+void IslNodeBuilder::allocateNewArrays() {
+  for (auto &SAI : S.arrays()) {
+    if (SAI->getBasePtr())
+      continue;
+
+    Type *NewArrayType = nullptr;
+    for (unsigned i = SAI->getNumberOfDimensions() - 1; i >= 1; i--) {
+      auto *DimSize = SAI->getDimensionSize(i);
+      unsigned UnsignedDimSize = static_cast<const SCEVConstant *>(DimSize)
+                                     ->getAPInt()
+                                     .getLimitedValue();
+
+      if (!NewArrayType)
+        NewArrayType = SAI->getElementType();
+
+      NewArrayType = ArrayType::get(NewArrayType, UnsignedDimSize);
+    }
+
+    auto InstIt =
+        Builder.GetInsertBlock()->getParent()->getEntryBlock().getTerminator();
+    Value *CreatedArray =
+        new AllocaInst(NewArrayType, SAI->getName(), &*InstIt);
+    SAI->setBasePtr(CreatedArray);
+  }
+}
+
 bool IslNodeBuilder::preloadInvariantLoads() {
 
   auto &InvariantEquivClasses = S.getInvariantAccesses();

Modified: polly/trunk/lib/CodeGen/PPCGCodeGeneration.cpp
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/CodeGen/PPCGCodeGeneration.cpp?rev=277263&r1=277262&r2=277263&view=diff
==============================================================================
--- polly/trunk/lib/CodeGen/PPCGCodeGeneration.cpp (original)
+++ polly/trunk/lib/CodeGen/PPCGCodeGeneration.cpp Sat Jul 30 04:25:51 2016
@@ -794,7 +794,7 @@ SetVector<Value *> GPUNodeBuilder::getRe
     findValues(Expr, SE, SubtreeValues);
 
   for (auto &SAI : S.arrays())
-    SubtreeValues.remove(SAI.second->getBasePtr());
+    SubtreeValues.remove(SAI->getBasePtr());
 
   isl_space *Space = S.getParamSpace();
   for (long i = 0; i < isl_space_dim(Space, isl_dim_param); i++) {
@@ -1379,7 +1379,7 @@ public:
     }
 
     for (auto &Array : S->arrays()) {
-      auto Id = Array.second->getBasePtrId();
+      auto Id = Array->getBasePtrId();
       Names = isl_id_to_ast_expr_set(Names, Id, isl_ast_expr_copy(Zero));
     }
 
@@ -1550,9 +1550,7 @@ public:
   /// @param PPCGProg The program to compute the arrays for.
   void createArrays(gpu_prog *PPCGProg) {
     int i = 0;
-    for (auto &Element : S->arrays()) {
-      ScopArrayInfo *Array = Element.second.get();
-
+    for (auto &Array : S->arrays()) {
       std::string TypeName;
       raw_string_ostream OS(TypeName);
 
@@ -1595,8 +1593,7 @@ public:
   isl_union_map *getArrayIdentity() {
     isl_union_map *Maps = isl_union_map_empty(S->getParamSpace());
 
-    for (auto &Item : S->arrays()) {
-      ScopArrayInfo *Array = Item.second.get();
+    for (auto &Array : S->arrays()) {
       isl_space *Space = Array->getSpace();
       Space = isl_space_map_from_set(Space);
       isl_map *Identity = isl_map_identity(Space);

Modified: polly/trunk/lib/Exchange/JSONExporter.cpp
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/Exchange/JSONExporter.cpp?rev=277263&r1=277262&r2=277263&view=diff
==============================================================================
--- polly/trunk/lib/Exchange/JSONExporter.cpp (original)
+++ polly/trunk/lib/Exchange/JSONExporter.cpp Sat Jul 30 04:25:51 2016
@@ -23,6 +23,7 @@
 #include "llvm/Support/FileSystem.h"
 #include "llvm/Support/MemoryBuffer.h"
 #include "llvm/Support/ToolOutputFile.h"
+#include "llvm/Support/raw_ostream.h"
 #include "isl/constraint.h"
 #include "isl/map.h"
 #include "isl/printer.h"
@@ -96,6 +97,14 @@ struct JSONImporter : public ScopPass {
   /// @returns True if the import succeeded, otherwise False.
   bool importSchedule(Scop &S, Json::Value &JScop, const Dependences &D);
 
+  /// Import new arrays from JScop.
+  ///
+  /// @param S The scop to update.
+  /// @param JScop The JScop file describing new arrays.
+  ///
+  /// @returns True if the import succeeded, otherwise False.
+  bool importArrays(Scop &S, Json::Value &JScop);
+
   /// Import new memory accesses from JScop.
   ///
   /// @param S The scop to update.
@@ -127,6 +136,35 @@ std::string JSONExporter::getFileName(Sc
 
 void JSONExporter::printScop(raw_ostream &OS, Scop &S) const { S.print(OS); }
 
+/// Export all arrays from the Scop.
+///
+/// @param S The Scop containing the arrays.
+///
+/// @returns Json::Value containing the arrays.
+Json::Value exportArrays(const Scop &S) {
+  Json::Value Arrays;
+  std::string Buffer;
+  llvm::raw_string_ostream RawStringOstream(Buffer);
+
+  for (auto &SAI : S.arrays()) {
+    if (!SAI->isArrayKind())
+      continue;
+
+    Json::Value Array;
+    Array["name"] = SAI->getName();
+    for (unsigned i = 1; i < SAI->getNumberOfDimensions(); i++) {
+      SAI->getDimensionSize(i)->print(RawStringOstream);
+      Array["sizes"].append(RawStringOstream.str());
+      Buffer.clear();
+    }
+    SAI->getElementType()->print(RawStringOstream);
+    Array["type"] = RawStringOstream.str();
+    Buffer.clear();
+    Arrays.append(Array);
+  }
+  return Arrays;
+}
+
 Json::Value JSONExporter::getJSON(Scop &S) const {
   Json::Value root;
   unsigned LineBegin, LineEnd;
@@ -142,6 +180,9 @@ Json::Value JSONExporter::getJSON(Scop &
   root["context"] = S.getContextStr();
   if (LineBegin != (unsigned)-1)
     root["location"] = Location;
+
+  root["arrays"] = exportArrays(S);
+
   root["statements"];
 
   for (ScopStmt &Stmt : S) {
@@ -305,8 +346,28 @@ bool JSONImporter::importAccesses(Scop &
         return false;
       }
 
-      isl_id *OutId = isl_map_get_tuple_id(CurrentAccessMap, isl_dim_out);
-      NewAccessMap = isl_map_set_tuple_id(NewAccessMap, isl_dim_out, OutId);
+      isl_id *NewOutId;
+
+      if (MA->isArrayKind()) {
+        NewOutId = isl_map_get_tuple_id(NewAccessMap, isl_dim_out);
+        auto *SAI = S.getArrayInfoByName(isl_id_get_name(NewOutId));
+        isl_id *OutId = isl_map_get_tuple_id(CurrentAccessMap, isl_dim_out);
+        auto *OutSAI = ScopArrayInfo::getFromId(OutId);
+        if (!SAI || SAI->getElementType() != OutSAI->getElementType()) {
+          errs() << "JScop file contains access function with undeclared "
+                    "ScopArrayInfo\n";
+          isl_map_free(CurrentAccessMap);
+          isl_map_free(NewAccessMap);
+          isl_id_free(NewOutId);
+          return false;
+        }
+        isl_id_free(NewOutId);
+        NewOutId = SAI->getBasePtrId();
+      } else {
+        NewOutId = isl_map_get_tuple_id(CurrentAccessMap, isl_dim_out);
+      }
+
+      NewAccessMap = isl_map_set_tuple_id(NewAccessMap, isl_dim_out, NewOutId);
 
       if (MA->isArrayKind()) {
         // We keep the old alignment, thus we cannot allow accesses to memory
@@ -354,17 +415,19 @@ bool JSONImporter::importAccesses(Scop &
       isl_id *Id = isl_map_get_tuple_id(CurrentAccessMap, isl_dim_in);
       NewAccessMap = isl_map_set_tuple_id(NewAccessMap, isl_dim_in, Id);
 
-      if (!isl_map_has_equal_space(CurrentAccessMap, NewAccessMap)) {
+      auto NewAccessDomain = isl_map_domain(isl_map_copy(NewAccessMap));
+      auto CurrentAccessDomain = isl_map_domain(isl_map_copy(CurrentAccessMap));
+
+      if (!isl_set_has_equal_space(NewAccessDomain, CurrentAccessDomain)) {
         errs() << "JScop file contains access function with incompatible "
                << "dimensions\n";
         isl_map_free(CurrentAccessMap);
         isl_map_free(NewAccessMap);
+        isl_set_free(NewAccessDomain);
+        isl_set_free(CurrentAccessDomain);
         return false;
       }
 
-      auto NewAccessDomain = isl_map_domain(isl_map_copy(NewAccessMap));
-      auto CurrentAccessDomain = isl_map_domain(isl_map_copy(CurrentAccessMap));
-
       NewAccessDomain =
           isl_set_intersect_params(NewAccessDomain, S.getContext());
       CurrentAccessDomain =
@@ -400,6 +463,95 @@ bool JSONImporter::importAccesses(Scop &
   return true;
 }
 
+/// @brief Check whether @p SAI and @p Array represent the same array.
+bool areArraysEqual(ScopArrayInfo *SAI, Json::Value Array) {
+  std::string Buffer;
+  llvm::raw_string_ostream RawStringOstream(Buffer);
+
+  if (SAI->getName() != Array["name"].asCString())
+    return false;
+
+  if (SAI->getNumberOfDimensions() != Array["sizes"].size() + 1)
+    return false;
+
+  for (unsigned i = 0; i < Array["sizes"].size(); i++) {
+    SAI->getDimensionSize(i + 1)->print(RawStringOstream);
+    if (RawStringOstream.str() != Array["sizes"][i].asCString())
+      return false;
+    Buffer.clear();
+  }
+
+  SAI->getElementType()->print(RawStringOstream);
+  if (RawStringOstream.str() != Array["type"].asCString())
+    return false;
+
+  return true;
+}
+
+/// @brief Get the accepted primitive type from its textual representation
+///        @p TypeTextRepresentation.
+///
+/// @param TypeTextRepresentation The textual representation of the type.
+/// @return The pointer to the primitive type, if this type is accepted
+///         or nullptr otherwise.
+Type *parseTextType(const std::string &TypeTextRepresentation,
+                    LLVMContext &LLVMContext) {
+  std::map<std::string, Type *> MapStrToType = {
+      {"void", Type::getVoidTy(LLVMContext)},
+      {"half", Type::getHalfTy(LLVMContext)},
+      {"float", Type::getFloatTy(LLVMContext)},
+      {"double", Type::getDoubleTy(LLVMContext)},
+      {"x86_fp80", Type::getX86_FP80Ty(LLVMContext)},
+      {"fp128", Type::getFP128Ty(LLVMContext)},
+      {"ppc_fp128", Type::getPPC_FP128Ty(LLVMContext)},
+      {"i1", Type::getInt1Ty(LLVMContext)},
+      {"i8", Type::getInt8Ty(LLVMContext)},
+      {"i16", Type::getInt16Ty(LLVMContext)},
+      {"i32", Type::getInt32Ty(LLVMContext)},
+      {"i64", Type::getInt64Ty(LLVMContext)},
+      {"i128", Type::getInt128Ty(LLVMContext)}};
+
+  auto It = MapStrToType.find(TypeTextRepresentation);
+  if (It != MapStrToType.end())
+    return It->second;
+
+  errs() << "Textual representation can not be parsed: "
+         << TypeTextRepresentation << "\n";
+  return nullptr;
+}
+
+bool JSONImporter::importArrays(Scop &S, Json::Value &JScop) {
+  Json::Value Arrays = JScop["arrays"];
+
+  if (Arrays.size() == 0)
+    return true;
+
+  unsigned ArrayIdx = 0;
+  for (auto &SAI : S.arrays()) {
+    if (!SAI->isArrayKind())
+      continue;
+    if (ArrayIdx + 1 > Arrays.size())
+      return false;
+    if (!areArraysEqual(SAI, Arrays[ArrayIdx]))
+      return false;
+    ArrayIdx++;
+  }
+
+  for (; ArrayIdx < Arrays.size(); ArrayIdx++) {
+    auto *ElementType = parseTextType(Arrays[ArrayIdx]["type"].asCString(),
+                                      S.getSE()->getContext());
+    if (!ElementType)
+      return false;
+    std::vector<unsigned> DimSizes;
+    for (unsigned i = 0; i < Arrays[ArrayIdx]["sizes"].size(); i++)
+      DimSizes.push_back(std::stoi(Arrays[ArrayIdx]["sizes"][i].asCString()));
+    S.createScopArrayInfo(ElementType, Arrays[ArrayIdx]["name"].asCString(),
+                          DimSizes);
+  }
+
+  return true;
+}
+
 bool JSONImporter::runOnScop(Scop &S) {
   const Dependences &D =
       getAnalysis<DependenceInfo>().getDependences(Dependences::AL_Statement);
@@ -438,6 +590,11 @@ bool JSONImporter::runOnScop(Scop &S) {
 
   if (!Success)
     return false;
+
+  Success = importArrays(S, jscop);
+
+  if (!Success)
+    return false;
 
   Success = importAccesses(S, jscop, DL);
 

Added: polly/trunk/test/Isl/CodeGen/MemAccess/create_arrays.ll
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/test/Isl/CodeGen/MemAccess/create_arrays.ll?rev=277263&view=auto
==============================================================================
--- polly/trunk/test/Isl/CodeGen/MemAccess/create_arrays.ll (added)
+++ polly/trunk/test/Isl/CodeGen/MemAccess/create_arrays.ll Sat Jul 30 04:25:51 2016
@@ -0,0 +1,76 @@
+; RUN: opt %loadPolly -polly-scops -analyze -polly-import-jscop-dir=%S -polly-import-jscop -polly-import-jscop-postfix=transformed < %s 2>&1 | FileCheck %s
+; RUN: opt %loadPolly -polly-import-jscop-dir=%S -polly-import-jscop -polly-import-jscop-postfix=transformed -polly-codegen -S < %s 2>&1 | FileCheck %s --check-prefix=CODEGEN
+;
+;  for (i = 0; i < _PB_NI; i++)
+;    for (j = 0; j < _PB_NJ; j++)
+;      for (k = 0; k < _PB_NK; ++k)
+;        B[i][j] = beta * A[i][k];
+;
+;
+; CHECK:    Arrays {
+; CHECK:        double MemRef_B[*][1024]; // Element size 8
+; CHECK:        double MemRef_beta; // Element size 8
+; CHECK:        double MemRef_A[*][1056]; // Element size 8
+; CHECK:        double D[*][270336]; // Element size 8
+; CHECK:        double E[*][270336][200000]; // Element size 8
+; CHECK:        i64 F[*][270336]; // Element size 8
+;
+; CHECK:New access function '{ Stmt_bb12[i0, i1, i2] -> E[i2, i0] }'detected in JSCOP file
+;
+;define internal void @create_arrays(i32 %arg, i32 %arg1, i32 %arg2, double %arg3, double %beta, [1056 x double]* %A, [1024 x double]* %B, [1056 x double]* %arg7) #0 {
+;bb:
+;  %beta.s2a = alloca double
+;  %D = alloca [270336 x double]
+;  %E = alloca [270336 x [200000 x double]]
+;  %F = alloca [270336 x i64]
+;  br label %bb8
+;
+; CODEGEN:  %polly.access.cast.E = bitcast [270336 x [200000 x double]]* %E to double*
+; CODEGEN:  %polly.access.mul.E = mul nsw i64 %polly.indvar33, 270336
+; CODEGEN:  %polly.access.add.E = add nsw i64 %polly.access.mul.E, %polly.indvar
+;
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-unknown"
+
+; Function Attrs: nounwind uwtable
+define internal void @create_arrays(i32 %arg, i32 %arg1, i32 %arg2, double %arg3, double %beta, [1056 x double]* %A, [1024 x double]* %B, [1056 x double]* %arg7) #0 {
+bb:
+  br label %bb8
+
+bb8:                                              ; preds = %bb
+  br label %bb9
+
+bb9:                                              ; preds = %bb23, %bb8
+  %tmp = phi i64 [ 0, %bb8 ], [ %tmp24, %bb23 ]
+  br label %bb10
+
+bb10:                                             ; preds = %bb20, %bb9
+  %tmp11 = phi i64 [ 0, %bb9 ], [ %tmp21, %bb20 ]
+  br label %bb12
+
+bb12:                                             ; preds = %bb12, %bb10
+  %tmp13 = phi i64 [ 0, %bb10 ], [ %tmp18, %bb12 ]
+  %tmp14 = getelementptr inbounds [1024 x double], [1024 x double]* %B, i64 %tmp, i64 %tmp13
+  %tmp15 = load double, double* %tmp14, align 8
+  %tmp16 = fmul double %tmp15, %beta
+  %tmp17 = getelementptr inbounds [1056 x double], [1056 x double]* %A, i64 %tmp, i64 %tmp11
+  store double %tmp16, double* %tmp17, align 8
+  %tmp18 = add nuw nsw i64 %tmp13, 1
+  %tmp19 = icmp ne i64 %tmp18, 1024
+  br i1 %tmp19, label %bb12, label %bb20
+
+bb20:                                             ; preds = %bb12
+  %tmp21 = add nuw nsw i64 %tmp11, 1
+  %tmp22 = icmp ne i64 %tmp21, 1056
+  br i1 %tmp22, label %bb10, label %bb23
+
+bb23:                                             ; preds = %bb20
+  %tmp24 = add nuw nsw i64 %tmp, 1
+  %tmp25 = icmp ne i64 %tmp24, 1056
+  br i1 %tmp25, label %bb9, label %bb26
+
+bb26:                                             ; preds = %bb23
+  ret void
+}
+
+attributes #0 = { nounwind uwtable "target-cpu"="x86-64" "target-features"="+aes,+avx,+cmov,+cx16,+fxsr,+mmx,+pclmul,+popcnt,+sse,+sse2,+sse3,+sse4.1,+sse4.2,+ssse3,+x87,+xsave,+xsaveopt" }

Added: polly/trunk/test/Isl/CodeGen/MemAccess/create_arrays___%bb9---%bb26.jscop
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/test/Isl/CodeGen/MemAccess/create_arrays___%25bb9---%25bb26.jscop?rev=277263&view=auto
==============================================================================
--- polly/trunk/test/Isl/CodeGen/MemAccess/create_arrays___%bb9---%bb26.jscop (added)
+++ polly/trunk/test/Isl/CodeGen/MemAccess/create_arrays___%bb9---%bb26.jscop Sat Jul 30 04:25:51 2016
@@ -0,0 +1,37 @@
+{
+   "arrays" : [
+     {
+         "name" : "MemRef_B",
+         "sizes" : [ "1024" ],
+         "type" : "double"
+      },
+      {
+         "name" : "MemRef_A",
+         "sizes" : [ "1056" ],
+         "type" : "double"
+      }
+   ],
+   "context" : "{  :  }",
+   "name" : "%bb9---%bb26",
+   "statements" : [
+      {
+         "accesses" : [
+            {
+               "kind" : "read",
+               "relation" : "{ Stmt_bb12[i0, i1, i2] -> MemRef_B[i0, i2] }"
+            },
+            {
+               "kind" : "read",
+               "relation" : "{ Stmt_bb12[i0, i1, i2] -> MemRef_beta[] }"
+            },
+            {
+               "kind" : "write",
+               "relation" : "{ Stmt_bb12[i0, i1, i2] -> MemRef_A[i0, i1] }"
+            }
+         ],
+         "domain" : "{ Stmt_bb12[i0, i1, i2] : 0 <= i0 <= 1055 and 0 <= i1 <= 1055 and 0 <= i2 <= 1023 }",
+         "name" : "Stmt_bb12",
+         "schedule" : "{ Stmt_bb12[i0, i1, i2] -> [i0, i1, i2] }"
+      }
+   ]
+}

Added: polly/trunk/test/Isl/CodeGen/MemAccess/create_arrays___%bb9---%bb26.jscop.transformed
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/test/Isl/CodeGen/MemAccess/create_arrays___%25bb9---%25bb26.jscop.transformed?rev=277263&view=auto
==============================================================================
--- polly/trunk/test/Isl/CodeGen/MemAccess/create_arrays___%bb9---%bb26.jscop.transformed (added)
+++ polly/trunk/test/Isl/CodeGen/MemAccess/create_arrays___%bb9---%bb26.jscop.transformed Sat Jul 30 04:25:51 2016
@@ -0,0 +1,52 @@
+{
+   "arrays" : [
+       {
+         "name" : "MemRef_B",
+         "sizes" : [ "1024" ],
+         "type" : "double"
+      },
+      {
+         "name" : "MemRef_A",
+         "sizes" : [ "1056" ],
+         "type" : "double"
+      },
+      {
+         "name" : "D",
+         "sizes" : [ "270336" ],
+         "type" : "double"
+      },
+      {
+         "name" : "E",
+         "sizes" : [ "270336", "200000" ],
+         "type" : "double"
+      },
+      {
+         "name" : "F",
+         "sizes" : [ "270336" ],
+         "type" : "i64"
+      }
+   ],
+   "context" : "{  :  }",
+   "name" : "%bb9---%bb26",
+   "statements" : [
+      {
+         "accesses" : [
+            {
+               "kind" : "read",
+               "relation" : "{ Stmt_bb12[i0, i1, i2] -> E[i2, i0] }"
+            },
+            {
+               "kind" : "read",
+               "relation" : "{ Stmt_bb12[i0, i1, i2] -> MemRef_beta[] }"
+            },
+            {
+               "kind" : "write",
+               "relation" : "{ Stmt_bb12[i0, i1, i2] -> MemRef_A[i0, i1] }"
+            }
+         ],
+         "domain" : "{ Stmt_bb12[i0, i1, i2] : 0 <= i0 <= 1055 and 0 <= i1 <= 1055 and 0 <= i2 <= 1023 }",
+         "name" : "Stmt_bb12",
+         "schedule" : "{ Stmt_bb12[i0, i1, i2] -> [i0, i1, i2] }"
+      }
+   ]
+}




More information about the llvm-commits mailing list