Index: include/polly/ScopInfo.h =================================================================== --- include/polly/ScopInfo.h +++ include/polly/ScopInfo.h @@ -231,9 +231,10 @@ /// @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 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. /// @@ -2148,10 +2149,21 @@ /// /// @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 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 &Sizes); /// @brief Return the cached ScopArrayInfo object for @p BasePtr. /// @@ -2275,6 +2287,10 @@ /// >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. Index: lib/Analysis/ScopInfo.cpp =================================================================== --- lib/Analysis/ScopInfo.cpp +++ lib/Analysis/ScopInfo.cpp @@ -169,10 +169,12 @@ ScopArrayInfo::ScopArrayInfo(Value *BasePtr, Type *ElementType, isl_ctx *Ctx, ArrayRef 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); @@ -3476,15 +3478,14 @@ isl_union_map_free(Writes); } -const ScopArrayInfo * -Scop::getOrCreateScopArrayInfo(Value *BasePtr, Type *ElementType, - ArrayRef Sizes, - ScopArrayInfo::MemoryKind Kind) { +const ScopArrayInfo *Scop::getOrCreateScopArrayInfo( + Value *BasePtr, Type *ElementType, ArrayRef Sizes, + ScopArrayInfo::MemoryKind Kind, const char *BaseName) { auto &SAI = ScopArrayInfoMap[std::make_pair(BasePtr, Kind)]; if (!SAI) { auto &DL = getFunction().getParent()->getDataLayout(); SAI.reset(new ScopArrayInfo(BasePtr, ElementType, getIslCtx(), Sizes, Kind, - DL, this)); + DL, this, BaseName)); } else { SAI->updateElementType(ElementType); // In case of mismatching array sizes, we bail out by setting the run-time @@ -3495,6 +3496,29 @@ return SAI.get(); } +const ScopArrayInfo * +Scop::createScopArrayInfo(Type *ElementType, const std::string &BaseName, + const std::vector &Sizes) { + auto *DimSizeType = Type::getInt64Ty(getSE()->getContext()); + Type *ArrayType = nullptr; + std::vector SCEVSizes; + + for (unsigned i = 0; i < Sizes.size(); i++) { + SCEVSizes.push_back(getSE()->getConstant(DimSizeType, Sizes.at(i), false)); + if (!ArrayType) + ArrayType = ArrayType::get(ElementType, Sizes.at(Sizes.size() - i - 1)); + else + ArrayType = ArrayType::get(ArrayType, Sizes.at(Sizes.size() - i - 1)); + } + + auto InstIt = getEnteringBlock()->getTerminator(); + Value *CreatedArray = new AllocaInst(ArrayType, BaseName, &*InstIt); + auto *SAI = + getOrCreateScopArrayInfo(CreatedArray, 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(); @@ -4187,6 +4211,13 @@ return L->getLoopDepth() - OuterLoop->getLoopDepth(); } +ScopArrayInfo *Scop::getArrayInfoByName(const std::string BaseName) { + for (auto &SAI : arrays()) + if (SAI.second->getName() == BaseName) + return SAI.second.get(); + return nullptr; +} + //===----------------------------------------------------------------------===// void ScopInfoRegionPass::getAnalysisUsage(AnalysisUsage &AU) const { AU.addRequired(); Index: lib/Exchange/JSONExporter.cpp =================================================================== --- lib/Exchange/JSONExporter.cpp +++ lib/Exchange/JSONExporter.cpp @@ -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 @@ /// @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 @@ 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.second->isArrayKind()) + continue; + + Json::Value Array; + Array["name"] = SAI.second->getName(); + for (unsigned i = 1; i < SAI.second->getNumberOfDimensions(); i++) { + SAI.second->getDimensionSize(i)->print(RawStringOstream); + Array["sizes"].append(RawStringOstream.str()); + Buffer.clear(); + } + SAI.second->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 @@ 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 @@ 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 @@ 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,98 @@ 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 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.second->isArrayKind()) + continue; + + if (ArrayIdx + 1 > Arrays.size()) + return false; + + if (!areArraysEqual(SAI.second.get(), 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 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().getDependences(Dependences::AL_Statement); @@ -439,6 +594,11 @@ if (!Success) return false; + Success = importArrays(S, jscop); + + if (!Success) + return false; + Success = importAccesses(S, jscop, DL); if (!Success) Index: test/Isl/CodeGen/MemAccess/create_arrays.ll =================================================================== --- /dev/null +++ test/Isl/CodeGen/MemAccess/create_arrays.ll @@ -0,0 +1,87 @@ +; 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 +; +; /* C := alpha*A*B + beta*C */ +; for (i = 0; i < _PB_NI; i++) +; for (j = 0; j < _PB_NJ; j++) +; { +; C[i][j] *= beta; +; for (k = 0; k < _PB_NK; ++k) +; C[i][j] += alpha * A[i][k] * B[k][j]; +; } +; +; CHECK: Arrays { +; CHECK: double MemRef_arg5[*][1056]; // Element size 8 +; CHECK: double MemRef_arg4; // Element size 8 +; CHECK: double MemRef_arg6[*][1024]; // Element size 8 +; CHECK: double MemRef_arg3; // Element size 8 +; CHECK: double MemRef_arg7[*][1056]; // Element size 8 +; CHECK: double MemRef_8[*][270336]; // Element size 8 +; CHECK: double MemRef_9[*][270336][200000]; // Element size 8 +; CHECK: i64 MemRef_10[*][270336]; // Element size 8 +; +; CHECK:New access function '{ Stmt_bb14[i0, i1, i2] -> MemRef_9[i1, i2] }'detected in JSCOP file +; +; CODEGEN:define internal void @create_arrays(i32 %arg, i32 %arg1, i32 %arg2, double %arg3, double %arg4, [1056 x double]* %arg5, [1024 x double]* %arg6, [1056 x double]* %arg7) #0 { +; CODEGEN:bb: +; CODEGEN: %arg3.s2a = alloca double +; CODEGEN: %arg4.s2a = alloca double +; CODEGEN: %MemRef_8 = alloca [270336 x double] +; CODEGEN: %MemRef_9 = alloca [270336 x [200000 x double]] +; CODEGEN: %MemRef_10 = alloca [270336 x i64] +; +; CODEGEN: %polly.access.cast.MemRef_9 = bitcast [270336 x [200000 x double]]* %MemRef_9 to double* +; CODEGEN: %30 = mul nsw i64 96, %polly.indvar89 +; CODEGEN: %31 = mul nsw i64 8, %polly.indvar101 +; CODEGEN: %32 = add nsw i64 %30, %31 +; CODEGEN: %33 = add nsw i64 %32, %polly.indvar119 +; +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-unknown" + +define internal void @create_arrays(i32 %arg, i32 %arg1, i32 %arg2, double %arg3, double %arg4, [1056 x double]* %arg5, [1024 x double]* %arg6, [1056 x double]* %arg7) #0 { +bb: + br label %bb8 + +bb8: ; preds = %bb29, %bb + %tmp = phi i64 [ 0, %bb ], [ %tmp30, %bb29 ] + br label %bb9 + +bb9: ; preds = %bb26, %bb8 + %tmp10 = phi i64 [ 0, %bb8 ], [ %tmp27, %bb26 ] + %tmp11 = getelementptr inbounds [1056 x double], [1056 x double]* %arg5, i64 %tmp, i64 %tmp10 + %tmp12 = load double, double* %tmp11, align 8 + %tmp13 = fmul double %tmp12, %arg4 + store double %tmp13, double* %tmp11, align 8 + br label %bb14 + +bb14: ; preds = %bb14, %bb9 + %tmp15 = phi i64 [ 0, %bb9 ], [ %tmp24, %bb14 ] + %tmp16 = getelementptr inbounds [1024 x double], [1024 x double]* %arg6, i64 %tmp, i64 %tmp15 + %tmp17 = load double, double* %tmp16, align 8 + %tmp18 = fmul double %tmp17, %arg3 + %tmp19 = getelementptr inbounds [1056 x double], [1056 x double]* %arg7, i64 %tmp15, i64 %tmp10 + %tmp20 = load double, double* %tmp19, align 8 + %tmp21 = fmul double %tmp18, %tmp20 + %tmp22 = load double, double* %tmp11, align 8 + %tmp23 = fadd double %tmp22, %tmp21 + store double %tmp23, double* %tmp11, align 8 + %tmp24 = add nuw nsw i64 %tmp15, 1 + %tmp25 = icmp ne i64 %tmp24, 1024 + br i1 %tmp25, label %bb14, label %bb26 + +bb26: ; preds = %bb14 + %tmp27 = add nuw nsw i64 %tmp10, 1 + %tmp28 = icmp ne i64 %tmp27, 1056 + br i1 %tmp28, label %bb9, label %bb29 + +bb29: ; preds = %bb26 + %tmp30 = add nuw nsw i64 %tmp, 1 + %tmp31 = icmp ne i64 %tmp30, 1056 + br i1 %tmp31, label %bb8, label %bb32 + +bb32: ; preds = %bb29 + 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" } Index: test/Isl/CodeGen/MemAccess/create_arrays___%bb8---%bb32.jscop =================================================================== --- /dev/null +++ test/Isl/CodeGen/MemAccess/create_arrays___%bb8---%bb32.jscop @@ -0,0 +1,69 @@ +{ + "arrays" : [ + { + "name" : "MemRef_arg5", + "sizes" : [ "1056" ], + "type" : "double" + }, + { + "name" : "MemRef_arg6", + "sizes" : [ "1024" ], + "type" : "double" + }, + { + "name" : "MemRef_arg7", + "sizes" : [ "1056" ], + "type" : "double" + } + ], + "context" : "{ : }", + "name" : "%bb8---%bb32", + "statements" : [ + { + "accesses" : [ + { + "kind" : "read", + "relation" : "{ Stmt_bb9[i0, i1] -> MemRef_arg5[i0, i1] }" + }, + { + "kind" : "read", + "relation" : "{ Stmt_bb9[i0, i1] -> MemRef_arg4[] }" + }, + { + "kind" : "write", + "relation" : "{ Stmt_bb9[i0, i1] -> MemRef_arg5[i0, i1] }" + } + ], + "domain" : "{ Stmt_bb9[i0, i1] : 0 <= i0 <= 1055 and 0 <= i1 <= 1055 }", + "name" : "Stmt_bb9", + "schedule" : "{ Stmt_bb9[i0, i1] -> [0, o1, o2, i0 - 32o1, i1 - 32o2, 0, 0, 0, 0, 0, 0, 0, 0] : -31 + i0 <= 32o1 <= i0 and -31 + i1 <= 32o2 <= i1 }" + }, + { + "accesses" : [ + { + "kind" : "read", + "relation" : "{ Stmt_bb14[i0, i1, i2] -> MemRef_arg6[i0, i2] }" + }, + { + "kind" : "read", + "relation" : "{ Stmt_bb14[i0, i1, i2] -> MemRef_arg3[] }" + }, + { + "kind" : "read", + "relation" : "{ Stmt_bb14[i0, i1, i2] -> MemRef_arg7[i2, i1] }" + }, + { + "kind" : "read", + "relation" : "{ Stmt_bb14[i0, i1, i2] -> MemRef_arg5[i0, i1] }" + }, + { + "kind" : "write", + "relation" : "{ Stmt_bb14[i0, i1, i2] -> MemRef_arg5[i0, i1] }" + } + ], + "domain" : "{ Stmt_bb14[i0, i1, i2] : 0 <= i0 <= 1055 and 0 <= i1 <= 1055 and 0 <= i2 <= 1023 }", + "name" : "Stmt_bb14", + "schedule" : "{ Stmt_bb14[i0, i1, i2] -> [1, o1, o2, o3, o4, o5, i2 - 256o2, 0, 0, 0, i0 - 16o1 - 4o4, i1 - 96o3 - 8o5, 0] : -15 + i0 <= 16o1 <= i0 and -255 + i2 <= 256o2 <= i2 and -95 + i1 <= 96o3 <= i1 and -3 + i0 - 16o1 <= 4o4 <= i0 - 16o1 and -7 + i1 - 96o3 <= 8o5 <= i1 - 96o3 }" + } + ] +} Index: test/Isl/CodeGen/MemAccess/create_arrays___%bb8---%bb32.jscop.transformed =================================================================== --- /dev/null +++ test/Isl/CodeGen/MemAccess/create_arrays___%bb8---%bb32.jscop.transformed @@ -0,0 +1,84 @@ +{ + "arrays" : [ + { + "name" : "MemRef_arg5", + "sizes" : [ "1056" ], + "type" : "double" + }, + { + "name" : "MemRef_arg6", + "sizes" : [ "1024" ], + "type" : "double" + }, + { + "name" : "MemRef_arg7", + "sizes" : [ "1056" ], + "type" : "double" + }, + { + "name" : "MemRef_8", + "sizes" : [ "270336" ], + "type" : "double" + }, + { + "name" : "MemRef_9", + "sizes" : [ "270336", "200000" ], + "type" : "double" + }, + { + "name" : "MemRef_10", + "sizes" : [ "270336" ], + "type" : "i64" + } + ], + "context" : "{ : }", + "name" : "%bb8---%bb32", + "statements" : [ + { + "accesses" : [ + { + "kind" : "read", + "relation" : "{ Stmt_bb9[i0, i1] -> MemRef_arg5[i0, i1] }" + }, + { + "kind" : "read", + "relation" : "{ Stmt_bb9[i0, i1] -> MemRef_arg4[] }" + }, + { + "kind" : "write", + "relation" : "{ Stmt_bb9[i0, i1] -> MemRef_arg5[i0, i1] }" + } + ], + "domain" : "{ Stmt_bb9[i0, i1] : 0 <= i0 <= 1055 and 0 <= i1 <= 1055 }", + "name" : "Stmt_bb9", + "schedule" : "{ Stmt_bb9[i0, i1] -> [0, o1, o2, i0 - 32o1, i1 - 32o2, 0, 0, 0, 0, 0, 0, 0, 0] : -31 + i0 <= 32o1 <= i0 and -31 + i1 <= 32o2 <= i1 }" + }, + { + "accesses" : [ + { + "kind" : "read", + "relation" : "{ Stmt_bb14[i0, i1, i2] -> MemRef_arg6[i0, i2] }" + }, + { + "kind" : "read", + "relation" : "{ Stmt_bb14[i0, i1, i2] -> MemRef_arg3[] }" + }, + { + "kind" : "read", + "relation" : "{ Stmt_bb14[i0, i1, i2] -> MemRef_9[i1, i2] }" + }, + { + "kind" : "read", + "relation" : "{ Stmt_bb14[i0, i1, i2] -> MemRef_arg5[i0, i1] }" + }, + { + "kind" : "write", + "relation" : "{ Stmt_bb14[i0, i1, i2] -> MemRef_arg5[i0, i1] }" + } + ], + "domain" : "{ Stmt_bb14[i0, i1, i2] : 0 <= i0 <= 1055 and 0 <= i1 <= 1055 and 0 <= i2 <= 1023 }", + "name" : "Stmt_bb14", + "schedule" : "{ Stmt_bb14[i0, i1, i2] -> [1, o1, o2, o3, o4, o5, i2 - 256o2, 0, 0, 0, i0 - 16o1 - 4o4, i1 - 96o3 - 8o5, 0] : -15 + i0 <= 16o1 <= i0 and -255 + i2 <= 256o2 <= i2 and -95 + i1 <= 96o3 <= i1 and -3 + i0 - 16o1 <= 4o4 <= i0 - 16o1 and -7 + i1 - 96o3 <= 8o5 <= i1 - 96o3 }" + } + ] +}