Index: include/polly/ScopInfo.h =================================================================== --- include/polly/ScopInfo.h +++ include/polly/ScopInfo.h @@ -1833,6 +1833,21 @@ /// void hoistInvariantLoads(); + /// Unify indirect arrays with base pointers from the same equivalence class. + /// + /// In case the IR we read reloads base pointers multiple times, we will have + /// modeled accesses relative these base pointers as different arrays. This + /// model is obviously incorrect and will cause us to miss data dependences. + /// As we verify the correctness of our model, for example as part of the + /// run-time alias check, this will not result in the incorrect execution of + /// scops, but rather the fallback to the unoptimized code version. + /// + /// After having computed equivalence classes for invariant loads, we can + /// canonicalize memory accesses to a single pointer in the equivalence class. + /// For this we choose for each equivalence class the first pointer in this + /// equivalence class. + void unifyIndirectArrays(); + /// Add invariant loads listed in @p InvMAs with the domain of @p Stmt. void addInvariantLoads(ScopStmt &Stmt, InvariantAccessesTy &InvMAs); Index: lib/Analysis/ScopInfo.cpp =================================================================== --- lib/Analysis/ScopInfo.cpp +++ lib/Analysis/ScopInfo.cpp @@ -1086,8 +1086,8 @@ 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"); - assert(!SAI->getBasePtrOriginSAI() && - "Indirect array not supported by codegen"); + //assert(!SAI->getBasePtrOriginSAI() && + // "Indirect array not supported by codegen"); auto Dims = SAI->getNumberOfDimensions(); assert(isl_space_dim(NewAccessSpace, isl_dim_set) == Dims && "Access dims must match array dims"); @@ -3288,6 +3288,7 @@ return; hoistInvariantLoads(); + unifyIndirectArrays(); verifyInvariantLoads(); simplifySCoP(true); @@ -3688,6 +3689,52 @@ isl_union_map_free(Writes); } +void Scop::unifyIndirectArrays() { + if (!PollyInvariantLoadHoisting) + return; + + for (InvariantEquivClassTy &EqClass : InvariantEquivClasses) { + int i = 0; + MemoryAccess *CanonicalAccess; + ScopArrayInfo *CanonicalSAI = nullptr; + for (MemoryAccess *InvAccess : EqClass.InvariantAccesses) { + i++; + if (i == 1) { + CanonicalAccess = InvAccess; + + for (ScopArrayInfo *SAI : arrays()) + if (SAI->getBasePtr() == CanonicalAccess->getAccessInstruction()) { + CanonicalSAI = SAI; + break; + } + if (!CanonicalSAI) + break; + + continue; + } + + ScopArrayInfo *OldSAI = nullptr; + for (ScopArrayInfo *SAI : arrays()) + if (SAI->getBasePtr() == InvAccess->getAccessInstruction()) { + OldSAI = SAI; + break; + } + + if (!OldSAI) + continue; + + for (ScopStmt &Stmt : *this) + for (MemoryAccess *Access : Stmt) + if (Access->getScopArrayInfo() == OldSAI) { + isl_id *Id = CanonicalSAI->getBasePtrId(); + isl_map *Map = Access->getAccessRelation(); + Map = isl_map_set_tuple_id(Map, isl_dim_out, Id); + Access->setNewAccessRelation(Map); + } + } + } +} + const ScopArrayInfo *Scop::getOrCreateScopArrayInfo( Value *BasePtr, Type *ElementType, ArrayRef Sizes, ScopArrayInfo::MemoryKind Kind, const char *BaseName) {