diff options
-rw-r--r-- | polly/include/polly/ScopInfo.h | 1 | ||||
-rw-r--r-- | polly/lib/Analysis/ScopInfo.cpp | 36 | ||||
-rw-r--r-- | polly/test/Isl/CodeGen/invariant_cannot_handle_void.ll | 6 |
3 files changed, 38 insertions, 5 deletions
diff --git a/polly/include/polly/ScopInfo.h b/polly/include/polly/ScopInfo.h index 9f372388f7f..975bc020b17 100644 --- a/polly/include/polly/ScopInfo.h +++ b/polly/include/polly/ScopInfo.h @@ -72,6 +72,7 @@ enum AssumptionKind { ALIASING, INBOUNDS, WRAPPING, + ALIGNMENT, ERRORBLOCK, INFINITELOOP, INVARIANTLOAD, diff --git a/polly/lib/Analysis/ScopInfo.cpp b/polly/lib/Analysis/ScopInfo.cpp index 43e14bdc0b0..ec90ccb6962 100644 --- a/polly/lib/Analysis/ScopInfo.cpp +++ b/polly/lib/Analysis/ScopInfo.cpp @@ -601,6 +601,32 @@ __isl_give isl_map *MemoryAccess::foldAccess(__isl_take isl_map *AccessRelation, return AccessRelation; } +/// @brief Check if @p Expr is divisible by @p Size. +static bool isDivisible(const SCEV *Expr, unsigned Size, ScalarEvolution &SE) { + + // Only one factor needs to be divisible. + if (auto *MulExpr = dyn_cast<SCEVMulExpr>(Expr)) { + for (auto *FactorExpr : MulExpr->operands()) + if (isDivisible(FactorExpr, Size, SE)) + return true; + return false; + } + + // For other n-ary expressions (Add, AddRec, Max,...) all operands need + // to be divisble. + if (auto *NAryExpr = dyn_cast<SCEVNAryExpr>(Expr)) { + for (auto *OpExpr : NAryExpr->operands()) + if (!isDivisible(OpExpr, Size, SE)) + return false; + return true; + } + + auto *SizeSCEV = SE.getConstant(Expr->getType(), Size); + auto *UDivSCEV = SE.getUDivExpr(Expr, SizeSCEV); + auto *MulSCEV = SE.getMulExpr(UDivSCEV, SizeSCEV); + return MulSCEV == Expr; +} + void MemoryAccess::buildAccessRelation(const ScopArrayInfo *SAI) { assert(!AccessRelation && "AccessReltation already built"); @@ -620,6 +646,7 @@ void MemoryAccess::buildAccessRelation(const ScopArrayInfo *SAI) { return; } + Scop &S = *getStatement()->getParent(); isl_space *Space = isl_space_alloc(Ctx, 0, Statement->getNumIterators(), 0); AccessRelation = isl_map_universe(Space); @@ -634,9 +661,14 @@ void MemoryAccess::buildAccessRelation(const ScopArrayInfo *SAI) { // LLVM-IR as something like A[i * elementsize]. This hides the fact that // two subsequent values of 'i' index two values that are stored next to // each other in memory. By this division we make this characteristic - // obvious again. + // obvious again. However, if the index is not divisible by the element + // size we will bail out. isl_val *v = isl_val_int_from_si(Ctx, getElemSizeInBytes()); Affine = isl_pw_aff_scale_down_val(Affine, v); + + if (!isDivisible(Subscripts[0], getElemSizeInBytes(), *S.getSE())) + S.addAssumption(ALIGNMENT, isl_set_empty(S.getParamSpace()), + AccessInstruction->getDebugLoc()); } isl_map *SubscriptMap = isl_map_from_pw_aff(Affine); @@ -2941,6 +2973,8 @@ static std::string toString(AssumptionKind Kind) { return "Inbounds"; case WRAPPING: return "No-overflows"; + case ALIGNMENT: + return "Alignment"; case ERRORBLOCK: return "No-error"; case INFINITELOOP: diff --git a/polly/test/Isl/CodeGen/invariant_cannot_handle_void.ll b/polly/test/Isl/CodeGen/invariant_cannot_handle_void.ll index 5497b31d26d..65480d7a4ad 100644 --- a/polly/test/Isl/CodeGen/invariant_cannot_handle_void.ll +++ b/polly/test/Isl/CodeGen/invariant_cannot_handle_void.ll @@ -1,11 +1,9 @@ ; RUN: opt %loadPolly -S -polly-codegen %s | FileCheck %s ; ; The offset of the %tmp1 load wrt. to %buff (62 bytes) is not divisible -; by the type size (i32 = 4 bytes), thus the access function build for -; %tmp1 is empty. As a result the code generation crashed when hoisting -; %tmp1. This test verifies we do not crash anymore. +; by the type size (i32 = 4 bytes), thus we will bail out. ; -; CHECK: polly.start +; CHECK-NOT: polly.start ; target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" |