Index: polly/trunk/include/polly/CodeGen/IslNodeBuilder.h =================================================================== --- polly/trunk/include/polly/CodeGen/IslNodeBuilder.h +++ polly/trunk/include/polly/CodeGen/IslNodeBuilder.h @@ -55,6 +55,9 @@ 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(); Index: polly/trunk/include/polly/ScopInfo.h =================================================================== --- polly/trunk/include/polly/ScopInfo.h +++ polly/trunk/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. /// @@ -1398,9 +1399,14 @@ /// @brief The affinator used to translate SCEVs to isl expressions. SCEVAffinator Affinator; - typedef MapVector, int>, - std::unique_ptr> + typedef std::map, int>, + std::unique_ptr> ArrayInfoMapTy; + + typedef StringMap> ArrayNameMapTy; + + typedef SetVector 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 @@ /// 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 @@ /// could be executed. bool isEmpty() const { return Stmts.empty(); } - typedef ArrayInfoMapTy::iterator array_iterator; - typedef ArrayInfoMapTy::const_iterator const_array_iterator; - typedef iterator_range array_range; - typedef iterator_range const_array_range; + typedef ArrayInfoSetTy::iterator array_iterator; + typedef ArrayInfoSetTy::const_iterator const_array_iterator; + typedef iterator_range array_range; + typedef iterator_range 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 @@ /// /// @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. /// @@ -2165,7 +2190,11 @@ /// @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 @@ /// >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: polly/trunk/lib/Analysis/ScopInfo.cpp =================================================================== --- polly/trunk/lib/Analysis/ScopInfo.cpp +++ polly/trunk/lib/Analysis/ScopInfo.cpp @@ -169,13 +169,21 @@ 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); + + if (!BasePtr) { + BasePtrOriginSAI = nullptr; + return; + } + BasePtrOriginSAI = identifyBasePtrOriginSAI(S, BasePtr); if (BasePtrOriginSAI) const_cast(BasePtrOriginSAI)->addDerivedSAI(this); @@ -3133,7 +3141,9 @@ // 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 @@ isl_union_map_free(Writes); } -const ScopArrayInfo * -Scop::getOrCreateScopArrayInfo(Value *BasePtr, Type *ElementType, - ArrayRef Sizes, - ScopArrayInfo::MemoryKind Kind) { - auto &SAI = ScopArrayInfoMap[std::make_pair(BasePtr, Kind)]; +const ScopArrayInfo *Scop::getOrCreateScopArrayInfo( + Value *BasePtr, Type *ElementType, ArrayRef 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 @@ return SAI.get(); } +const ScopArrayInfo * +Scop::createScopArrayInfo(Type *ElementType, const std::string &BaseName, + const std::vector &Sizes) { + auto *DimSizeType = Type::getInt64Ty(getSE()->getContext()); + std::vector 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 @@ 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 @@ 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(); Index: polly/trunk/lib/CodeGen/BlockGenerators.cpp =================================================================== --- polly/trunk/lib/CodeGen/BlockGenerators.cpp +++ polly/trunk/lib/CodeGen/BlockGenerators.cpp @@ -485,8 +485,7 @@ 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::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 @@ 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 Index: polly/trunk/lib/CodeGen/CodeGeneration.cpp =================================================================== --- polly/trunk/lib/CodeGen/CodeGeneration.cpp +++ polly/trunk/lib/CodeGen/CodeGeneration.cpp @@ -189,6 +189,7 @@ isl_ast_node_free(AstRoot); } else { + NodeBuilder.allocateNewArrays(); NodeBuilder.addParameters(S.getContext()); Index: polly/trunk/lib/CodeGen/IslNodeBuilder.cpp =================================================================== --- polly/trunk/lib/CodeGen/IslNodeBuilder.cpp +++ polly/trunk/lib/CodeGen/IslNodeBuilder.cpp @@ -1157,6 +1157,32 @@ 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(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(); Index: polly/trunk/lib/CodeGen/PPCGCodeGeneration.cpp =================================================================== --- polly/trunk/lib/CodeGen/PPCGCodeGeneration.cpp +++ polly/trunk/lib/CodeGen/PPCGCodeGeneration.cpp @@ -794,7 +794,7 @@ 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 @@ } 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 @@ /// @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 @@ 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); Index: polly/trunk/lib/Exchange/JSONExporter.cpp =================================================================== --- polly/trunk/lib/Exchange/JSONExporter.cpp +++ polly/trunk/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->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 @@ 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,95 @@ 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->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 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 +591,11 @@ if (!Success) return false; + Success = importArrays(S, jscop); + + if (!Success) + return false; + Success = importAccesses(S, jscop, DL); if (!Success) Index: polly/trunk/test/Isl/CodeGen/MemAccess/create_arrays.ll =================================================================== --- polly/trunk/test/Isl/CodeGen/MemAccess/create_arrays.ll +++ polly/trunk/test/Isl/CodeGen/MemAccess/create_arrays.ll @@ -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" } Index: polly/trunk/test/Isl/CodeGen/MemAccess/create_arrays___%bb9---%bb26.jscop =================================================================== --- polly/trunk/test/Isl/CodeGen/MemAccess/create_arrays___%bb9---%bb26.jscop +++ polly/trunk/test/Isl/CodeGen/MemAccess/create_arrays___%bb9---%bb26.jscop @@ -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] }" + } + ] +} Index: polly/trunk/test/Isl/CodeGen/MemAccess/create_arrays___%bb9---%bb26.jscop.transformed =================================================================== --- polly/trunk/test/Isl/CodeGen/MemAccess/create_arrays___%bb9---%bb26.jscop.transformed +++ polly/trunk/test/Isl/CodeGen/MemAccess/create_arrays___%bb9---%bb26.jscop.transformed @@ -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] }" + } + ] +}