summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--polly/include/polly/ScopInfo.h1
-rw-r--r--polly/lib/Analysis/ScopInfo.cpp36
-rw-r--r--polly/test/Isl/CodeGen/invariant_cannot_handle_void.ll6
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"
OpenPOWER on IntegriCloud