Index: include/polly/Support/ScopHelper.h =================================================================== --- include/polly/Support/ScopHelper.h +++ include/polly/Support/ScopHelper.h @@ -19,6 +19,7 @@ #include "llvm/IR/Instructions.h" #include "llvm/IR/IntrinsicInst.h" #include "llvm/IR/ValueHandle.h" +#include "isl/space.h" #include #include @@ -433,5 +434,20 @@ std::tuple, std::vector> getIndexExpressionsFromGEP(llvm::GetElementPtrInst *GEP, llvm::ScalarEvolution &SE); + +/// @brief Check whether two spaces are compatible to each other. +/// +/// Two spaces are 'compatible' when binary operations like union, intersect can +/// be used on them. The spaces must be of same type (param, set, or map) and +/// domain/range/set tuple must be equal. In contrast to isl_space_is_equal, the +/// parameter tuple does not need to be equal as (most) isl operations align +/// them before execution. +/// +/// @param Space1 isl_space to compare with Space2 +/// @param Space2 isl_space to compare with Space1 +/// +/// @return True iff the the two spaces are compatible. +bool isl_space_is_compatible(__isl_keep isl_space *Space1, + __isl_keep isl_space *Space2); } // namespace polly #endif Index: lib/Analysis/ScopInfo.cpp =================================================================== --- lib/Analysis/ScopInfo.cpp +++ lib/Analysis/ScopInfo.cpp @@ -962,7 +962,43 @@ return isStrideX(Schedule, 1); } -void MemoryAccess::setNewAccessRelation(isl_map *NewAccess) { +void MemoryAccess::setNewAccessRelation(__isl_take isl_map *NewAccess) { + assert(NewAccess); + +#ifndef NDEBUG + // Check domain space compatibility. + auto *NewSpace = isl_map_get_space(NewAccess); + auto *NewDomainSpace = isl_space_domain(isl_space_copy(NewSpace)); + auto *OriginalDomainSpace = getStatement()->getDomainSpace(); + assert(isl_space_is_compatible(OriginalDomainSpace, NewDomainSpace)); + isl_space_free(NewDomainSpace); + isl_space_free(OriginalDomainSpace); + + // Check whether there is an access for every statement instance. + auto *StmtDomain = getStatement()->getDomain(); + StmtDomain = isl_set_intersect_params( + StmtDomain, getStatement()->getParent()->getContext()); + auto *NewDomain = isl_map_domain(isl_map_copy(NewAccess)); + assert(isl_set_is_subset(StmtDomain, NewDomain) && + "Partial accesses not supported"); + isl_set_free(NewDomain); + isl_set_free(StmtDomain); + + // Check whether access dimensions correspond to number of dimensions of the + // accesses array. + auto *NewAccessSpace = isl_space_range(NewSpace); + assert(isl_space_has_tuple_id(NewAccessSpace, isl_dim_set) && + "Must specify the array that is accessed"); + auto *NewArrayId = isl_space_get_tuple_id(NewAccessSpace, isl_dim_set); + auto *SAI = static_cast(isl_id_get_user(NewArrayId)); + assert(SAI && "Must set a ScopArrayInfo"); + auto Dims = SAI->getNumberOfDimensions(); + assert(isl_space_dim(NewAccessSpace, isl_dim_set) == Dims && + "Access dims must match array dims"); + isl_space_free(NewAccessSpace); + isl_id_free(NewArrayId); +#endif + isl_map_free(NewAccessRelation); NewAccessRelation = NewAccess; } Index: lib/Support/ScopHelper.cpp =================================================================== --- lib/Support/ScopHelper.cpp +++ lib/Support/ScopHelper.cpp @@ -539,3 +539,16 @@ return std::make_tuple(Subscripts, Sizes); } + +bool polly::isl_space_is_compatible(__isl_keep isl_space *Space1, + __isl_keep isl_space *Space2) { + if (isl_space_is_map(Space1) && isl_space_is_map(Space2)) + return isl_space_tuple_is_equal(Space1, isl_dim_in, Space2, isl_dim_in) && + isl_space_tuple_is_equal(Space1, isl_dim_out, Space2, isl_dim_out); + if (isl_space_is_set(Space1) && isl_space_is_set(Space2)) + return isl_space_tuple_is_equal(Space1, isl_dim_set, Space2, isl_dim_set); + if (isl_space_is_params(Space1) && isl_space_is_params(Space2)) + return true; + + return false; +}