Index: polly/trunk/include/polly/ScopBuilder.h =================================================================== --- polly/trunk/include/polly/ScopBuilder.h +++ polly/trunk/include/polly/ScopBuilder.h @@ -120,6 +120,20 @@ void buildScop(Region &R, AssumptionCache &AC, OptimizationRemarkEmitter &ORE); + /// Create equivalence classes for required invariant accesses. + /// + /// These classes will consolidate multiple required invariant loads from the + /// same address in order to keep the number of dimensions in the SCoP + /// description small. For each such class equivalence class only one + /// representing element, hence one required invariant load, will be chosen + /// and modeled as parameter. The method + /// Scop::getRepresentingInvariantLoadSCEV() will replace each element from an + /// equivalence class with the representing element that is modeled. As a + /// consequence Scop::getIdForParam() will only return an id for the + /// representing element of each equivalence class, thus for each required + /// invariant location. + void buildInvariantEquivalenceClasses(); + /// Try to build a multi-dimensional fixed sized MemoryAccess from the /// Load/Store instruction. /// Index: polly/trunk/include/polly/ScopInfo.h =================================================================== --- polly/trunk/include/polly/ScopInfo.h +++ polly/trunk/include/polly/ScopInfo.h @@ -2031,20 +2031,6 @@ /// Check if the base ptr of @p MA is in the SCoP but not hoistable. bool hasNonHoistableBasePtrInScop(MemoryAccess *MA, isl::union_map Writes); - /// Create equivalence classes for required invariant accesses. - /// - /// These classes will consolidate multiple required invariant loads from the - /// same address in order to keep the number of dimensions in the SCoP - /// description small. For each such class equivalence class only one - /// representing element, hence one required invariant load, will be chosen - /// and modeled as parameter. The method - /// Scop::getRepresentingInvariantLoadSCEV() will replace each element from an - /// equivalence class with the representing element that is modeled. As a - /// consequence Scop::getIdForParam() will only return an id for the - /// representing element of each equivalence class, thus for each required - /// invariant location. - void buildInvariantEquivalenceClasses(); - /// Return the context under which the access cannot be hoisted. /// /// @param Access The access to check. @@ -2386,6 +2372,18 @@ /// Add metadata for @p Access. void addAccessData(MemoryAccess *Access); + /// Add new invariant access equivalence class + void + addInvariantEquivClass(const InvariantEquivClassTy &InvariantEquivClass) { + InvariantEquivClasses.emplace_back(InvariantEquivClass); + } + + /// Add mapping from invariant loads to the representing invariant load of + /// their equivalence class. + void addInvariantLoadMapping(const Value *LoadInst, Value *ClassRep) { + InvEquivClassVMap[LoadInst] = ClassRep; + } + /// Remove the metadata stored for @p Access. void removeAccessData(MemoryAccess *Access); Index: polly/trunk/lib/Analysis/ScopBuilder.cpp =================================================================== --- polly/trunk/lib/Analysis/ScopBuilder.cpp +++ polly/trunk/lib/Analysis/ScopBuilder.cpp @@ -105,6 +105,26 @@ "Store-level granularity")), cl::init(GranularityChoice::ScalarIndependence), cl::cat(PollyCategory)); +void ScopBuilder::buildInvariantEquivalenceClasses() { + DenseMap, LoadInst *> EquivClasses; + + const InvariantLoadsSetTy &RIL = scop->getRequiredInvariantLoads(); + for (LoadInst *LInst : RIL) { + const SCEV *PointerSCEV = SE.getSCEV(LInst->getPointerOperand()); + + Type *Ty = LInst->getType(); + LoadInst *&ClassRep = EquivClasses[std::make_pair(PointerSCEV, Ty)]; + if (ClassRep) { + scop->addInvariantLoadMapping(LInst, ClassRep); + continue; + } + + ClassRep = LInst; + scop->addInvariantEquivClass( + InvariantEquivClassTy{PointerSCEV, MemoryAccessList(), nullptr, Ty}); + } +} + void ScopBuilder::buildPHIAccesses(ScopStmt *PHIStmt, PHINode *PHI, Region *NonAffineSubRegion, bool IsExitBlock) { @@ -1492,7 +1512,7 @@ BP, BP->getType(), false, {AF}, {nullptr}, GlobalRead); } - scop->buildInvariantEquivalenceClasses(); + buildInvariantEquivalenceClasses(); /// A map from basic blocks to their invalid domains. DenseMap InvalidDomainMap; Index: polly/trunk/lib/Analysis/ScopInfo.cpp =================================================================== --- polly/trunk/lib/Analysis/ScopInfo.cpp +++ polly/trunk/lib/Analysis/ScopInfo.cpp @@ -2102,26 +2102,6 @@ Context = Context.intersect(UserContext); } -void Scop::buildInvariantEquivalenceClasses() { - DenseMap, LoadInst *> EquivClasses; - - const InvariantLoadsSetTy &RIL = getRequiredInvariantLoads(); - for (LoadInst *LInst : RIL) { - const SCEV *PointerSCEV = SE->getSCEV(LInst->getPointerOperand()); - - Type *Ty = LInst->getType(); - LoadInst *&ClassRep = EquivClasses[std::make_pair(PointerSCEV, Ty)]; - if (ClassRep) { - InvEquivClassVMap[LInst] = ClassRep; - continue; - } - - ClassRep = LInst; - InvariantEquivClasses.emplace_back( - InvariantEquivClassTy{PointerSCEV, MemoryAccessList(), nullptr, Ty}); - } -} - void Scop::buildContext() { isl::space Space = isl::space::params_alloc(getIslCtx(), 0); Context = isl::set::universe(Space); @@ -3699,7 +3679,7 @@ // If we did not consolidate MA, thus did not find an equivalence class // for it, we create a new one. - InvariantEquivClasses.emplace_back( + addInvariantEquivClass( InvariantEquivClassTy{PointerSCEV, MemoryAccessList{MA}, MACtx, Ty}); } }