ScopInfo: Allow simple 'AddRec * Parameter' products in delinearization

We also allow such products for cases where 'Parameter' is loaded within the
scop, but where we can dynamically verify that the value of 'Parameter' remains
unchanged during the execution of the scop.

This change relies on Polly's new RequiredILS tracking infrastructure recently
contributed by Johannes.

llvm-svn: 250019
This commit is contained in:
Tobias Grosser 2015-10-12 08:02:30 +00:00
parent 374bce0c22
commit e2c8275346
2 changed files with 74 additions and 5 deletions

@ -495,9 +495,6 @@ bool ScopDetection::hasAffineMemoryAccesses(DetectionContext &Context) const {
// First step: collect parametric terms in all array references.
SmallVector<const SCEV *, 4> Terms;
for (const auto &Pair : Context.Accesses[BasePointer]) {
if (auto *AF = dyn_cast<SCEVAddRecExpr>(Pair.second))
SE->collectParametricTerms(AF, Terms);
// In case the outermost expression is a plain add, we check if any of its
// terms has the form 4 * %inst * %param * %param ..., aka a term that
// contains a product between a parameter and an instruction that is
@ -530,6 +527,8 @@ bool ScopDetection::hasAffineMemoryAccesses(DetectionContext &Context) const {
}
}
}
if (Terms.empty())
SE->collectParametricTerms(Pair.second, Terms);
}
// Second step: find array shape.
@ -539,13 +538,19 @@ bool ScopDetection::hasAffineMemoryAccesses(DetectionContext &Context) const {
if (!AllowNonAffine)
for (const SCEV *DelinearizedSize : Shape->DelinearizedSizes) {
if (auto *Unknown = dyn_cast<SCEVUnknown>(DelinearizedSize)) {
auto *value = dyn_cast<Value>(Unknown->getValue());
if (isa<UndefValue>(value)) {
auto *V = dyn_cast<Value>(Unknown->getValue());
if (isa<UndefValue>(V)) {
invalid<ReportDifferentArrayElementSize>(
Context, /*Assert=*/true,
Context.Accesses[BasePointer].front().first, BaseValue);
return false;
}
if (auto *Load = dyn_cast<LoadInst>(V)) {
if (Context.CurRegion.contains(Load) &&
isHoistableLoad(Load, CurRegion, *LI, *SE))
Context.RequiredILS.insert(Load);
continue;
}
}
if (hasScalarDepsInsideRegion(DelinearizedSize, &CurRegion))
invalid<ReportNonAffineAccess>(

@ -0,0 +1,64 @@
; RUN: opt %loadPolly -polly-scops -analyze < %s | FileCheck %s
;
; void foo(float *A, long *p) {
; for (long i = 0; i < 100; i++)
; for (long j = 0; j < 100; j++)
; A[i * (*p) + j] += i + j;
; }
; CHECK: Invariant Accesses: {
; CHECK-NEXT: ReadAccess := [Reduction Type: NONE] [Scalar: 0]
; CHECK-NEXT: [p] -> { Stmt_bb5[i0, i1] -> MemRef_p[0] };
; CHECK-NEXT: Execution Context: [p] -> { : }
; CHECK-NEXT: }
; CHECK: ReadAccess := [Reduction Type: NONE] [Scalar: 0]
; CHECK: [p] -> { Stmt_bb5[i0, i1] -> MemRef_A[i0, i1] };
; CHECK: MustWriteAccess := [Reduction Type: NONE] [Scalar: 0]
; CHECK: [p] -> { Stmt_bb5[i0, i1] -> MemRef_A[i0, i1] };
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
define void @foo(float* %A, i64* %p) {
bb:
br label %bb2
bb2: ; preds = %bb16, %bb
%i.0 = phi i64 [ 0, %bb ], [ %tmp17, %bb16 ]
%exitcond1 = icmp ne i64 %i.0, 100
br i1 %exitcond1, label %bb3, label %bb18
bb3: ; preds = %bb2
br label %bb4
bb4: ; preds = %bb13, %bb3
%j.0 = phi i64 [ 0, %bb3 ], [ %tmp14, %bb13 ]
%exitcond = icmp ne i64 %j.0, 100
br i1 %exitcond, label %bb5, label %bb15
bb5: ; preds = %bb4
%tmp = add nuw nsw i64 %i.0, %j.0
%tmp6 = sitofp i64 %tmp to float
%pval = load i64, i64* %p, align 8
%tmp8 = mul nsw i64 %i.0, %pval
%tmp9 = add nsw i64 %tmp8, %j.0
%tmp10 = getelementptr inbounds float, float* %A, i64 %tmp9
%tmp11 = load float, float* %tmp10, align 4
%tmp12 = fadd float %tmp11, %tmp6
store float %tmp12, float* %tmp10, align 4
br label %bb13
bb13: ; preds = %bb5
%tmp14 = add nuw nsw i64 %j.0, 1
br label %bb4
bb15: ; preds = %bb4
br label %bb16
bb16: ; preds = %bb15
%tmp17 = add nuw nsw i64 %i.0, 1
br label %bb2
bb18: ; preds = %bb2
ret void
}