[polly] r240955 - Add first support to delinearize A[t%2][i][j]
Tobias Grosser
tobias at grosser.es
Mon Jun 29 07:44:22 PDT 2015
Author: grosser
Date: Mon Jun 29 09:44:22 2015
New Revision: 240955
URL: http://llvm.org/viewvc/llvm-project?rev=240955&view=rev
Log:
Add first support to delinearize A[t%2][i][j]
This is very preliminary support, but it seems to work for the most common case.
When observing more/different test cases, we can work on generalizing this.
Added:
polly/trunk/test/ScopInfo/multidim_srem.ll
Modified:
polly/trunk/lib/Analysis/ScopDetection.cpp
Modified: polly/trunk/lib/Analysis/ScopDetection.cpp
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/Analysis/ScopDetection.cpp?rev=240955&r1=240954&r2=240955&view=diff
==============================================================================
--- polly/trunk/lib/Analysis/ScopDetection.cpp (original)
+++ polly/trunk/lib/Analysis/ScopDetection.cpp Mon Jun 29 09:44:22 2015
@@ -470,10 +470,44 @@ bool ScopDetection::hasAffineMemoryAcces
// First step: collect parametric terms in all array references.
SmallVector<const SCEV *, 4> Terms;
for (const auto &Pair : Context.Accesses[BasePointer]) {
- const SCEVAddRecExpr *AF = dyn_cast<SCEVAddRecExpr>(Pair.second);
-
- if (AF)
+ 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
+ // inside the scop. Such instructions, if allowed at all, are instructions
+ // SCEV can not represent, but Polly is still looking through. As a
+ // result, these instructions can depend on induction variables and are
+ // most likely no array sizes. However, terms that are multiplied with
+ // them are likely candidates for array sizes.
+ if (auto *AF = dyn_cast<SCEVAddExpr>(Pair.second)) {
+ for (auto Op : AF->operands()) {
+ if (auto *AF2 = dyn_cast<SCEVAddRecExpr>(Op))
+ SE->collectParametricTerms(AF2, Terms);
+ if (auto *AF2 = dyn_cast<SCEVMulExpr>(Op)) {
+ SmallVector<const SCEV *, 0> Operands;
+ bool TermsHasInRegionInst = false;
+
+ for (auto *MulOp : AF2->operands()) {
+ if (auto *Const = dyn_cast<SCEVConstant>(MulOp))
+ Operands.push_back(Const);
+ if (auto *Unknown = dyn_cast<SCEVUnknown>(MulOp)) {
+ if (auto *Inst = dyn_cast<Instruction>(Unknown->getValue())) {
+ if (!Context.CurRegion.contains(Inst))
+ Operands.push_back(MulOp);
+ else
+ TermsHasInRegionInst = true;
+
+ } else {
+ Operands.push_back(MulOp);
+ }
+ }
+ }
+ Terms.push_back(SE->getMulExpr(Operands));
+ }
+ }
+ }
}
// Second step: find array shape.
@@ -517,7 +551,7 @@ bool ScopDetection::hasAffineMemoryAcces
MapInsnToMemAcc TempMemoryAccesses;
for (const auto &Pair : Context.Accesses[BasePointer]) {
const Instruction *Insn = Pair.first;
- const SCEVAddRecExpr *AF = dyn_cast<SCEVAddRecExpr>(Pair.second);
+ auto *AF = Pair.second;
bool IsNonAffine = false;
TempMemoryAccesses.insert(std::make_pair(Insn, MemAcc(Insn, Shape)));
MemAcc *Acc = &TempMemoryAccesses.find(Insn)->second;
Added: polly/trunk/test/ScopInfo/multidim_srem.ll
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/test/ScopInfo/multidim_srem.ll?rev=240955&view=auto
==============================================================================
--- polly/trunk/test/ScopInfo/multidim_srem.ll (added)
+++ polly/trunk/test/ScopInfo/multidim_srem.ll Mon Jun 29 09:44:22 2015
@@ -0,0 +1,92 @@
+; RUN: opt %loadPolly -analyze -polly-scops -S < %s | FileCheck %s
+;
+; void foo(long n, float A[][n][n]) {
+; for (long i = 0; i < 200; i++)
+; for (long j = 0; j < n; j++)
+; for (long k = 0; k < n; k++)
+; A[i % 2][j][k] += 10;
+; }
+;
+; CHECK: ReadAccess := [Reduction Type: NONE] [Scalar: 0]
+; CHECK: [n] -> { Stmt_for_body_8[i0, i1, i2] -> MemRef_A[o0, i1, i2] : exists (e0 = floor((-i0 + o0)/2): 2e0 = -i0 + o0 and o0 >= 0 and o0 <= 1) };
+; CHECK: MustWriteAccess := [Reduction Type: NONE] [Scalar: 0]
+; CHECK: [n] -> { Stmt_for_body_8[i0, i1, i2] -> MemRef_A[o0, i1, i2] : exists (e0 = floor((-i0 + o0)/2): 2e0 = -i0 + o0 and o0 >= 0 and o0 <= 1) };
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+
+define void @foo(i64 %n, float* %A) #0 {
+entry:
+ br label %entry.split
+
+entry.split: ; preds = %entry
+ br label %for.cond.1.preheader
+
+for.cond.1.preheader: ; preds = %entry.split, %for.inc.14
+ %i.06 = phi i64 [ 0, %entry.split ], [ %inc15, %for.inc.14 ]
+ %cmp2.3 = icmp sgt i64 %n, 0
+ br i1 %cmp2.3, label %for.cond.5.preheader.lr.ph, label %for.inc.14
+
+for.cond.5.preheader.lr.ph: ; preds = %for.cond.1.preheader
+ br label %for.cond.5.preheader
+
+for.cond.5.preheader: ; preds = %for.cond.5.preheader.lr.ph, %for.inc.11
+ %j.04 = phi i64 [ 0, %for.cond.5.preheader.lr.ph ], [ %inc12, %for.inc.11 ]
+ %cmp6.1 = icmp sgt i64 %n, 0
+ br i1 %cmp6.1, label %for.body.8.lr.ph, label %for.inc.11
+
+for.body.8.lr.ph: ; preds = %for.cond.5.preheader
+ br label %for.body.8
+
+for.body.8: ; preds = %for.body.8.lr.ph, %for.body.8
+ %k.02 = phi i64 [ 0, %for.body.8.lr.ph ], [ %inc, %for.body.8 ]
+ %rem = srem i64 %i.06, 2
+ %0 = mul nuw i64 %n, %n
+ %1 = mul nsw i64 %0, %rem
+ %arrayidx = getelementptr inbounds float, float* %A, i64 %1
+ %2 = mul nsw i64 %j.04, %n
+ %arrayidx9 = getelementptr inbounds float, float* %arrayidx, i64 %2
+ %arrayidx10 = getelementptr inbounds float, float* %arrayidx9, i64 %k.02
+ %3 = load float, float* %arrayidx10, align 4, !tbaa !1
+ %add = fadd float %3, 1.000000e+01
+ store float %add, float* %arrayidx10, align 4, !tbaa !1
+ %inc = add nuw nsw i64 %k.02, 1
+ %exitcond = icmp ne i64 %inc, %n
+ br i1 %exitcond, label %for.body.8, label %for.cond.5.for.inc.11_crit_edge
+
+for.cond.5.for.inc.11_crit_edge: ; preds = %for.body.8
+ br label %for.inc.11
+
+for.inc.11: ; preds = %for.cond.5.for.inc.11_crit_edge, %for.cond.5.preheader
+ %inc12 = add nuw nsw i64 %j.04, 1
+ %exitcond7 = icmp ne i64 %inc12, %n
+ br i1 %exitcond7, label %for.cond.5.preheader, label %for.cond.1.for.inc.14_crit_edge
+
+for.cond.1.for.inc.14_crit_edge: ; preds = %for.inc.11
+ br label %for.inc.14
+
+for.inc.14: ; preds = %for.cond.1.for.inc.14_crit_edge, %for.cond.1.preheader
+ %inc15 = add nuw nsw i64 %i.06, 1
+ %exitcond8 = icmp ne i64 %inc15, 200
+ br i1 %exitcond8, label %for.cond.1.preheader, label %for.end.16
+
+for.end.16: ; preds = %for.inc.14
+ ret void
+}
+
+; Function Attrs: nounwind
+declare void @llvm.lifetime.start(i64, i8* nocapture) #1
+
+; Function Attrs: nounwind
+declare void @llvm.lifetime.end(i64, i8* nocapture) #1
+
+attributes #0 = { nounwind uwtable "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+sse,+sse2" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #1 = { nounwind }
+
+!llvm.ident = !{!0}
+
+!0 = !{!"clang version 3.7.0 (trunk 240923) (llvm/trunk 240924)"}
+!1 = !{!2, !2, i64 0}
+!2 = !{!"float", !3, i64 0}
+!3 = !{!"omnipotent char", !4, i64 0}
+!4 = !{!"Simple C/C++ TBAA"}
More information about the llvm-commits
mailing list