From c96c1d8c87982f2341dba5fb31ee90ae41b31f4c Mon Sep 17 00:00:00 2001 From: Tobias Grosser Date: Thu, 27 Apr 2017 20:08:16 +0000 Subject: [PATCH] [ScopInfo] Consider only write-free dereferencable loads as invariant When we introduced in r297375 support for hoisting loads that are known to be dereferencable without any conditional guard, we forgot to keep the check to verify that no other write into the very same location exists. This change ensures now that dereferencable loads are allowed to access everything, but can only be hoisted in case no conflicting write exists. This resolves llvm.org/PR32778 Reported-by: Huihui Zhang llvm-svn: 301582 --- polly/lib/Analysis/ScopInfo.cpp | 29 +++++++++++++++++------------ polly/test/Isl/CodeGen/reduction_2.ll | 15 ++++++--------- 2 files changed, 23 insertions(+), 21 deletions(-) diff --git a/polly/lib/Analysis/ScopInfo.cpp b/polly/lib/Analysis/ScopInfo.cpp index cfc2297..b6a09a9 100644 --- a/polly/lib/Analysis/ScopInfo.cpp +++ b/polly/lib/Analysis/ScopInfo.cpp @@ -3737,16 +3737,6 @@ __isl_give isl_set *Scop::getNonHoistableCtx(MemoryAccess *Access, if (hasNonHoistableBasePtrInScop(Access, Writes)) return nullptr; - auto &DL = getFunction().getParent()->getDataLayout(); - if (isSafeToLoadUnconditionally(LI->getPointerOperand(), LI->getAlignment(), - DL)) - return isl_set_empty(getParamSpace()); - - // Skip accesses in non-affine subregions as they might not be executed - // under the same condition as the entry of the non-affine subregion. - if (BB != LI->getParent()) - return nullptr; - isl_map *AccessRelation = Access->getAccessRelation(); assert(!isl_map_is_empty(AccessRelation)); @@ -3757,10 +3747,25 @@ __isl_give isl_set *Scop::getNonHoistableCtx(MemoryAccess *Access, } AccessRelation = isl_map_intersect_domain(AccessRelation, Stmt.getDomain()); - isl_set *AccessRange = isl_map_range(AccessRelation); + isl_set *SafeToLoad; + + auto &DL = getFunction().getParent()->getDataLayout(); + if (isSafeToLoadUnconditionally(LI->getPointerOperand(), LI->getAlignment(), + DL)) { + SafeToLoad = + isl_set_universe(isl_space_range(isl_map_get_space(AccessRelation))); + isl_map_free(AccessRelation); + } else if (BB != LI->getParent()) { + // Skip accesses in non-affine subregions as they might not be executed + // under the same condition as the entry of the non-affine subregion. + isl_map_free(AccessRelation); + return nullptr; + } else { + SafeToLoad = isl_map_range(AccessRelation); + } isl_union_map *Written = isl_union_map_intersect_range( - isl_union_map_copy(Writes), isl_union_set_from_set(AccessRange)); + isl_union_map_copy(Writes), isl_union_set_from_set(SafeToLoad)); auto *WrittenCtx = isl_union_map_params(Written); bool IsWritten = !isl_set_is_empty(WrittenCtx); diff --git a/polly/test/Isl/CodeGen/reduction_2.ll b/polly/test/Isl/CodeGen/reduction_2.ll index 886d7a7..13cd32e 100644 --- a/polly/test/Isl/CodeGen/reduction_2.ll +++ b/polly/test/Isl/CodeGen/reduction_2.ll @@ -89,13 +89,10 @@ if.end: ; preds = %if.then, %for.end declare void @llvm.memset.p0i8.i64(i8* nocapture, i8, i64, i32, i1) nounwind -; At some point this was a negative test, where we optimistically assumed RED[0] -; in the conditional after the loop is invariant and expanded the SCoP from -; the loop to include the conditional. However, during SCoP generation we -; realized that RED[0] is in fact not invariant and bailed. +; This is a negative test. We can prove that RED[0] in the conditional after +; the loop is dereferencable and consequently expand the SCoP from the +; loop to include the conditional. However, during SCoP generation we realize +; that, while RED[0] is invariant, it is written to as part of the same scop +; and can consequently not be hoisted. Hence, we invalidate the scop. ; -; Today, LLVM can derive that the load is indeed invariant and Polly uses this -; information to unconditionally invariant load hoist RED[0]. -; -; CHECK: for (int c0 = 0; c0 <= 1018; c0 += 1) -; CHECK-NEXT: Stmt_for_body(c0); +; CHECK-NOT: for (int c0 = 0; c0 <= 1018; c0 += 1) -- 2.7.4