Index: include/polly/Support/ScopHelper.h =================================================================== --- include/polly/Support/ScopHelper.h +++ include/polly/Support/ScopHelper.h @@ -391,10 +391,12 @@ /// @param LI The loop info. /// @param SE The scalar evolution analysis. /// @param DT The dominator tree of the function. +/// @param RequiredILS The invariant load set. /// /// @return True if @p LInst can be hoisted in @p R. bool isHoistableLoad(llvm::LoadInst *LInst, llvm::Region &R, llvm::LoopInfo &LI, - llvm::ScalarEvolution &SE, const llvm::DominatorTree &DT); + llvm::ScalarEvolution &SE, const llvm::DominatorTree &DT, + InvariantLoadsSetTy &RequiredILS); /// Return true iff @p V is an intrinsic that we ignore during code /// generation. Index: lib/Analysis/ScopDetection.cpp =================================================================== --- lib/Analysis/ScopDetection.cpp +++ lib/Analysis/ScopDetection.cpp @@ -484,7 +484,7 @@ if (Context.RequiredILS.count(Load)) continue; - if (!isHoistableLoad(Load, CurRegion, LI, SE, DT)) + if (!isHoistableLoad(Load, CurRegion, LI, SE, DT, Context.RequiredILS)) return false; for (auto NonAffineRegion : Context.NonAffineSubRegionSet) { @@ -938,7 +938,7 @@ auto *V = dyn_cast(Unknown->getValue()); if (auto *Load = dyn_cast(V)) { if (Context.CurRegion.contains(Load) && - isHoistableLoad(Load, CurRegion, LI, SE, DT)) + isHoistableLoad(Load, CurRegion, LI, SE, DT, Context.RequiredILS)) Context.RequiredILS.insert(Load); continue; } @@ -1143,23 +1143,39 @@ if (!AS.isMustAlias()) { if (PollyUseRuntimeAliasChecks) { bool CanBuildRunTimeCheck = true; + + InvariantLoadsSetTy variantLS, invariantLS; // The run-time alias check places code that involves the base pointer at // the beginning of the SCoP. This breaks if the base pointer is defined // inside the scop. Hence, we can only create a run-time check if we are // sure the base pointer is not an instruction defined inside the scop. // However, we can ignore loads that will be hoisted. - for (const auto &Ptr : AS) { - Instruction *Inst = dyn_cast(Ptr.getValue()); - if (Inst && Context.CurRegion.contains(Inst)) { - auto *Load = dyn_cast(Inst); - if (Load && isHoistableLoad(Load, Context.CurRegion, LI, SE, DT)) { - Context.RequiredILS.insert(Load); - continue; + + while (1) { + unsigned int variantSize = variantLS.size(), + invariantSize = invariantLS.size(); + + for (const auto &Ptr : AS) { + Instruction *Inst = dyn_cast(Ptr.getValue()); + if (Inst && Context.CurRegion.contains(Inst)) { + auto *Load = dyn_cast(Inst); + if (Load && (invariantLS.count(Load) || variantLS.count(Load))) + continue; + if (Load && isHoistableLoad(Load, Context.CurRegion, LI, SE, DT, + invariantLS)) { + Context.RequiredILS.insert(Load); + invariantLS.insert(Load); + break; + } else { + CanBuildRunTimeCheck = false; + variantLS.insert(Load); + } } + } - CanBuildRunTimeCheck = false; + if (invariantSize == invariantLS.size() && + variantSize == variantLS.size()) break; - } } if (CanBuildRunTimeCheck) Index: lib/Support/ScopHelper.cpp =================================================================== --- lib/Support/ScopHelper.cpp +++ lib/Support/ScopHelper.cpp @@ -442,9 +442,19 @@ } bool polly::isHoistableLoad(LoadInst *LInst, Region &R, LoopInfo &LI, - ScalarEvolution &SE, const DominatorTree &DT) { + ScalarEvolution &SE, const DominatorTree &DT, + InvariantLoadsSetTy &RequiredILS) { Loop *L = LI.getLoopFor(LInst->getParent()); auto *Ptr = LInst->getPointerOperand(); + + if (auto *gepInst = dyn_cast(Ptr)) { + if (auto *decidingLoad = dyn_cast(gepInst->getPointerOperand())) { + for (auto i : RequiredILS) + if (i == decidingLoad) + return true; + } + } + const SCEV *PtrSCEV = SE.getSCEVAtScope(Ptr, L); while (L && R.contains(L)) { if (!SE.isLoopInvariant(PtrSCEV, L))