Index: polly/trunk/include/polly/ScopInfo.h =================================================================== --- polly/trunk/include/polly/ScopInfo.h +++ polly/trunk/include/polly/ScopInfo.h @@ -922,17 +922,30 @@ using InvariantAccessesTy = SmallVector; /// @brief Type for equivalent invariant accesses and their domain context. -/// -/// The first element is the SCEV for the pointer/location that identifies this -/// equivalence class. The second is a list of memory accesses to that location -/// that are now treated as invariant and hoisted during code generation. The -/// third element is the execution context under which the invariant memory -/// location is accessed, hence the union of all domain contexts for the memory -/// accesses in the list. The last element describes the type of the invariant -/// access in order to differentiate between different typed invariant loads of -/// the same location. -using InvariantEquivClassTy = - std::tuple; +struct InvariantEquivClassTy { + + /// The pointer that identifies this equivalence class + const SCEV *IdentifyingPointer; + + /// Memory accesses now treated invariant + /// + /// These memory accesses access the pointer location that identifies + /// this equivalence class. They are treated as invariant and hoisted during + /// code generation. + MemoryAccessList InvariantAccesses; + + /// The execution context under which the memory location is accessed + /// + /// It is the union of the execution domains of the memory accesses in the + /// InvariantAccesses list. + isl_set *ExecutionContext; + + /// The type of the invariant access + /// + /// It is used to differentiate between differently typed invariant loads from + /// the same location. + Type *Type; +}; /// @brief Type for invariant accesses equivalence classes. using InvariantEquivClassesTy = SmallVector; Index: polly/trunk/lib/Analysis/ScopInfo.cpp =================================================================== --- polly/trunk/lib/Analysis/ScopInfo.cpp +++ polly/trunk/lib/Analysis/ScopInfo.cpp @@ -1943,8 +1943,8 @@ } ClassRep = LInst; - InvariantEquivClasses.emplace_back(PointerSCEV, MemoryAccessList(), nullptr, - Ty); + InvariantEquivClasses.emplace_back( + InvariantEquivClassTy{PointerSCEV, MemoryAccessList(), nullptr, Ty}); } } @@ -3128,7 +3128,7 @@ } for (const auto &IAClass : InvariantEquivClasses) - isl_set_free(std::get<2>(IAClass)); + isl_set_free(IAClass.ExecutionContext); // Explicitly release all Scop objects and the underlying isl objects before // we relase the isl context. @@ -3210,10 +3210,10 @@ Type *Ty = LInst->getType(); const SCEV *PointerSCEV = SE->getSCEV(LInst->getPointerOperand()); for (auto &IAClass : InvariantEquivClasses) { - if (PointerSCEV != std::get<0>(IAClass) || Ty != std::get<3>(IAClass)) + if (PointerSCEV != IAClass.IdentifyingPointer || Ty != IAClass.Type) continue; - auto &MAs = std::get<1>(IAClass); + auto &MAs = IAClass.InvariantAccesses; for (auto *MA : MAs) if (MA->getAccessInstruction() == Val) return &IAClass; @@ -3331,7 +3331,7 @@ bool Consolidated = false; for (auto &IAClass : InvariantEquivClasses) { - if (PointerSCEV != std::get<0>(IAClass) || Ty != std::get<3>(IAClass)) + if (PointerSCEV != IAClass.IdentifyingPointer || Ty != IAClass.Type) continue; // If the pointer and the type is equal check if the access function wrt. @@ -3339,7 +3339,7 @@ // parameter values and these can be different for distinct part of the // SCoP. If this happens we cannot consolidate the loads but need to // create a new invariant load equivalence class. - auto &MAs = std::get<1>(IAClass); + auto &MAs = IAClass.InvariantAccesses; if (!MAs.empty()) { auto *LastMA = MAs.front(); @@ -3359,7 +3359,7 @@ Consolidated = true; // Unify the execution context of the class and this statement. - isl_set *&IAClassDomainCtx = std::get<2>(IAClass); + isl_set *&IAClassDomainCtx = IAClass.ExecutionContext; if (IAClassDomainCtx) IAClassDomainCtx = isl_set_coalesce(isl_set_union(IAClassDomainCtx, MACtx)); @@ -3373,8 +3373,8 @@ // If we did not consolidate MA, thus did not find an equivalence class // for it, we create a new one. - InvariantEquivClasses.emplace_back(PointerSCEV, MemoryAccessList{MA}, MACtx, - Ty); + InvariantEquivClasses.emplace_back( + InvariantEquivClassTy{PointerSCEV, MemoryAccessList{MA}, MACtx, Ty}); } isl_set_free(DomainCtx); @@ -3799,12 +3799,13 @@ OS.indent(4) << "Max Loop Depth: " << getMaxLoopDepth() << "\n"; OS.indent(4) << "Invariant Accesses: {\n"; for (const auto &IAClass : InvariantEquivClasses) { - const auto &MAs = std::get<1>(IAClass); + const auto &MAs = IAClass.InvariantAccesses; if (MAs.empty()) { - OS.indent(12) << "Class Pointer: " << *std::get<0>(IAClass) << "\n"; + OS.indent(12) << "Class Pointer: " << *IAClass.IdentifyingPointer << "\n"; } else { MAs.front()->print(OS); - OS.indent(12) << "Execution Context: " << std::get<2>(IAClass) << "\n"; + OS.indent(12) << "Execution Context: " << IAClass.ExecutionContext + << "\n"; } } OS.indent(4) << "}\n"; Index: polly/trunk/lib/CodeGen/IslNodeBuilder.cpp =================================================================== --- polly/trunk/lib/CodeGen/IslNodeBuilder.cpp +++ polly/trunk/lib/CodeGen/IslNodeBuilder.cpp @@ -893,7 +893,7 @@ // Check if this invariant access class is empty, hence if we never // actually added a loads instruction to it. In that case it has no // (meaningful) users and we should not try to code generate it. - if (std::get<1>(*IAClass).empty()) + if (IAClass->InvariantAccesses.empty()) V = UndefValue::get(ParamSCEV->getType()); if (!preloadInvariantEquivClass(*IAClass)) { @@ -1064,7 +1064,7 @@ // element with the unified execution context. However, we have to map all // elements of the class to the one preloaded load as they are referenced // during the code generation and therefor need to be mapped. - const MemoryAccessList &MAs = std::get<1>(IAClass); + const MemoryAccessList &MAs = IAClass.InvariantAccesses; if (MAs.empty()) return true; @@ -1079,12 +1079,12 @@ // Check for recurrsion which can be caused by additional constraints, e.g., // non-finitie loop contraints. In such a case we have to bail out and insert // a "false" runtime check that will cause the original code to be executed. - auto PtrId = std::make_pair(std::get<0>(IAClass), std::get<3>(IAClass)); + auto PtrId = std::make_pair(IAClass.IdentifyingPointer, IAClass.Type); if (!PreloadedPtrs.insert(PtrId).second) return false; // The exectution context of the IAClass. - isl_set *&ExecutionCtx = std::get<2>(IAClass); + isl_set *&ExecutionCtx = IAClass.ExecutionContext; // If the base pointer of this class is dependent on another one we have to // make sure it was preloaded already. @@ -1095,7 +1095,7 @@ // After we preloaded the BaseIAClass we adjusted the BaseExecutionCtx and // we need to refine the ExecutionCtx. - isl_set *BaseExecutionCtx = isl_set_copy(std::get<2>(*BaseIAClass)); + isl_set *BaseExecutionCtx = isl_set_copy(BaseIAClass->ExecutionContext); ExecutionCtx = isl_set_intersect(ExecutionCtx, BaseExecutionCtx); }