From f12890bc5a0f2db5e0c02cc790ae81c6126e411e Mon Sep 17 00:00:00 2001 From: Michael Kruse Date: Wed, 30 Aug 2017 10:11:06 +0000 Subject: [PATCH] [ScopBuilder] Introduce metadata for splitting scop statement. This patch allows annotating of metadata in ir instruction (with "polly_split_after"), which specifies where to split a particular scop statement. Contributed-by: Nandini Singhal Differential Revision: https://reviews.llvm.org/D36402 git-svn-id: https://llvm.org/svn/llvm-project/polly/trunk@312107 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/polly/ScopBuilder.h | 4 +- include/polly/ScopInfo.h | 5 +- lib/Analysis/ScopBuilder.cpp | 22 ++++++- lib/Analysis/ScopInfo.cpp | 13 ++-- .../CodeGen/stmt_split_no_dependence.ll} | 28 ++++---- test/ScopInfo/stmt_split_exit_of_region_stmt.ll | 71 ++++++++++++++++++++ .../{statement.ll => stmt_split_no_dependence.ll} | 32 +++++++-- test/ScopInfo/stmt_split_on_synthesizable.ll | 56 ++++++++++++++++ test/ScopInfo/stmt_split_phi_in_beginning_bb.ll | 57 ++++++++++++++++ test/ScopInfo/stmt_split_phi_in_stmt.ll | 75 ++++++++++++++++++++++ test/ScopInfo/stmt_split_within_loop.ll | 60 +++++++++++++++++ 11 files changed, 392 insertions(+), 31 deletions(-) copy test/{ScopInfo/statement.ll => Isl/CodeGen/stmt_split_no_dependence.ll} (53%) create mode 100644 test/ScopInfo/stmt_split_exit_of_region_stmt.ll rename test/ScopInfo/{statement.ll => stmt_split_no_dependence.ll} (53%) create mode 100644 test/ScopInfo/stmt_split_on_synthesizable.ll create mode 100644 test/ScopInfo/stmt_split_phi_in_beginning_bb.ll create mode 100644 test/ScopInfo/stmt_split_phi_in_stmt.ll create mode 100644 test/ScopInfo/stmt_split_within_loop.ll diff --git a/include/polly/ScopBuilder.h b/include/polly/ScopBuilder.h index a890d925..74d3b7a9 100644 --- a/include/polly/ScopBuilder.h +++ b/include/polly/ScopBuilder.h @@ -229,8 +229,8 @@ class ScopBuilder { /// access any memory and thus have no effect. void buildStmts(Region &SR); - /// Build the access functions for the basic block @p BB in or represented by - /// @p Stmt. + /// Build the access functions for the statement @p Stmt in or represented by + /// @p BB. /// /// @param Stmt Statement to add MemoryAccesses to. /// @param BB A basic block in @p R. diff --git a/include/polly/ScopInfo.h b/include/polly/ScopInfo.h index f7079a27..3556379d 100644 --- a/include/polly/ScopInfo.h +++ b/include/polly/ScopInfo.h @@ -1192,7 +1192,7 @@ class ScopStmt { public: /// Create the ScopStmt from a BasicBlock. ScopStmt(Scop &parent, BasicBlock &bb, Loop *SurroundingLoop, - std::vector Instructions); + std::vector Instructions, int Count); /// Create an overapproximating ScopStmt for the region @p R. ScopStmt(Scop &parent, Region &R, Loop *SurroundingLoop); @@ -2203,8 +2203,9 @@ private: /// @param BB The basic block we build the statement for. /// @param SurroundingLoop The loop the created statement is contained in. /// @param Instructions The instructions in the statement. + /// @param Count The index of the created statement in @p BB. void addScopStmt(BasicBlock *BB, Loop *SurroundingLoop, - std::vector Instructions); + std::vector Instructions, int Count); /// Create a new SCoP statement for @p R. /// diff --git a/lib/Analysis/ScopBuilder.cpp b/lib/Analysis/ScopBuilder.cpp index 3355546d..8016870a 100644 --- a/lib/Analysis/ScopBuilder.cpp +++ b/lib/Analysis/ScopBuilder.cpp @@ -658,16 +658,24 @@ void ScopBuilder::buildStmts(Region &SR) { if (I->isSubRegion()) buildStmts(*I->getNodeAs()); else { + int Count = 0; std::vector Instructions; for (Instruction &Inst : *I->getNodeAs()) { Loop *L = LI.getLoopFor(Inst.getParent()); if (!isa(&Inst) && !isIgnoredIntrinsic(&Inst) && !canSynthesize(&Inst, *scop, &SE, L)) Instructions.push_back(&Inst); + if (Inst.getMetadata("polly_split_after")) { + Loop *SurroundingLoop = LI.getLoopFor(I->getNodeAs()); + scop->addScopStmt(I->getNodeAs(), SurroundingLoop, + Instructions, Count); + Count++; + Instructions.clear(); + } } Loop *SurroundingLoop = LI.getLoopFor(I->getNodeAs()); scop->addScopStmt(I->getNodeAs(), SurroundingLoop, - Instructions); + Instructions, Count); } } @@ -684,7 +692,19 @@ void ScopBuilder::buildAccessFunctions(ScopStmt *Stmt, BasicBlock &BB, if (isErrorBlock(BB, scop->getRegion(), LI, DT) && !IsExitBlock) return; + int Count = 0; + bool Split = false; for (Instruction &Inst : BB) { + if (Split) { + Split = false; + Count++; + } + if (Inst.getMetadata("polly_split_after")) + Split = true; + + if (Stmt && Stmt->isBlockStmt() && Stmt != scop->getStmtListFor(&BB)[Count]) + continue; + PHINode *PHI = dyn_cast(&Inst); if (PHI) buildPHIAccesses(Stmt, PHI, NonAffineSubRegion, IsExitBlock); diff --git a/lib/Analysis/ScopInfo.cpp b/lib/Analysis/ScopInfo.cpp index 55eef18a..24ab38bb 100644 --- a/lib/Analysis/ScopInfo.cpp +++ b/lib/Analysis/ScopInfo.cpp @@ -1764,11 +1764,14 @@ ScopStmt::ScopStmt(Scop &parent, Region &R, Loop *SurroundingLoop) } ScopStmt::ScopStmt(Scop &parent, BasicBlock &bb, Loop *SurroundingLoop, - std::vector Instructions) + std::vector Instructions, int Count) : Parent(parent), InvalidDomain(nullptr), Domain(nullptr), BB(&bb), Build(nullptr), SurroundingLoop(SurroundingLoop), Instructions(Instructions) { - BaseName = getIslCompatibleName("Stmt", &bb, parent.getNextStmtIdx(), "", + std::string S = ""; + if (Count != 0) + S += std::to_string(Count); + BaseName = getIslCompatibleName("Stmt", &bb, parent.getNextStmtIdx(), S, UseInstructionNames); } @@ -4880,9 +4883,9 @@ static isl::multi_union_pw_aff mapToDimension(isl::union_set USet, int N) { } void Scop::addScopStmt(BasicBlock *BB, Loop *SurroundingLoop, - std::vector Instructions) { + std::vector Instructions, int Count) { assert(BB && "Unexpected nullptr!"); - Stmts.emplace_back(*this, *BB, SurroundingLoop, Instructions); + Stmts.emplace_back(*this, *BB, SurroundingLoop, Instructions, Count); auto *Stmt = &Stmts.back(); StmtMap[BB].push_back(Stmt); for (Instruction *Inst : Instructions) { @@ -5049,8 +5052,6 @@ ArrayRef Scop::getStmtListFor(BasicBlock *BB) const { auto StmtMapIt = StmtMap.find(BB); if (StmtMapIt == StmtMap.end()) return {}; - assert(StmtMapIt->second.size() == 1 && - "Each statement corresponds to exactly one BB."); return StmtMapIt->second; } diff --git a/test/ScopInfo/statement.ll b/test/Isl/CodeGen/stmt_split_no_dependence.ll similarity index 53% copy from test/ScopInfo/statement.ll copy to test/Isl/CodeGen/stmt_split_no_dependence.ll index d9a17a89..539c4067 100644 --- a/test/ScopInfo/statement.ll +++ b/test/Isl/CodeGen/stmt_split_no_dependence.ll @@ -1,5 +1,8 @@ -; RUN: opt %loadPolly -polly-scops -analyze -polly-print-instructions < %s | FileCheck %s - +; RUN: opt %loadPolly -polly-codegen -S < %s | FileCheck %s +; +; CHECK: store i32 %8, i32* %scevgep, align 4, !alias.scope !1, !noalias !3 +; CHECK: store i32 %9, i32* %scevgep4, align 4, !alias.scope !4, !noalias !5 +; ; void func(int *A, int *B){ ; for (int i = 0; i < 1024; i+=1) { ; Stmt: @@ -7,38 +10,35 @@ ; B[i] = i; ; } ; } - -; CHECK: Instructions { -; CHECK-NEXT: store i32 %i.0, i32* %arrayidx, align 4 -; CHECK-NEXT: store i32 %i.0, i32* %arrayidx2, align 4 -; CHECK-NEXT: } - +; ; Function Attrs: noinline nounwind uwtable define void @func(i32* %A, i32* %B) #0 { entry: br label %for.cond -for.cond: ; preds = %for.inc, %entry +for.cond: ; preds = %for.inc, %entry %i.0 = phi i32 [ 0, %entry ], [ %add, %for.inc ] %cmp = icmp slt i32 %i.0, 1024 br i1 %cmp, label %for.body, label %for.end -for.body: ; preds = %for.cond +for.body: ; preds = %for.cond br label %Stmt -Stmt: ; preds = %for.body +Stmt: ; preds = %for.body %idxprom = sext i32 %i.0 to i64 %arrayidx = getelementptr inbounds i32, i32* %A, i64 %idxprom - store i32 %i.0, i32* %arrayidx, align 4 + store i32 %i.0, i32* %arrayidx, align 4, !polly_split_after !0 %idxprom1 = sext i32 %i.0 to i64 %arrayidx2 = getelementptr inbounds i32, i32* %B, i64 %idxprom1 store i32 %i.0, i32* %arrayidx2, align 4 br label %for.inc -for.inc: ; preds = %Stmt +for.inc: ; preds = %Stmt %add = add nsw i32 %i.0, 1 br label %for.cond -for.end: ; preds = %for.cond +for.end: ; preds = %for.cond ret void } + +!0 = !{!"polly_split_after"} diff --git a/test/ScopInfo/stmt_split_exit_of_region_stmt.ll b/test/ScopInfo/stmt_split_exit_of_region_stmt.ll new file mode 100644 index 00000000..2f64ab72 --- /dev/null +++ b/test/ScopInfo/stmt_split_exit_of_region_stmt.ll @@ -0,0 +1,71 @@ +; RUN: opt %loadPolly -polly-scops -analyze -polly-print-instructions < %s | FileCheck %s +; +; CHECK: Statements { +; CHECK-NEXT: Stmt_Region__TO__Stmt +; CHECK-NEXT: Domain := +; CHECK-NEXT: { Stmt_Region__TO__Stmt[i0] : 0 <= i0 <= 1023 }; +; CHECK-NEXT: Schedule := +; CHECK-NEXT: { Stmt_Region__TO__Stmt[i0] -> [i0, 0] }; +; CHECK-NEXT: MayWriteAccess := [Reduction Type: NONE] [Scalar: 0] +; CHECK-NEXT: { Stmt_Region__TO__Stmt[i0] -> MemRef_C[0] }; +; CHECK-NEXT: Stmt_Stmt +; CHECK-NEXT: Domain := +; CHECK-NEXT: { Stmt_Stmt[i0] : 0 <= i0 <= 1023 }; +; CHECK-NEXT: Schedule := +; CHECK-NEXT: { Stmt_Stmt[i0] -> [i0, 1] }; +; CHECK-NEXT: MustWriteAccess := [Reduction Type: NONE] [Scalar: 0] +; CHECK-NEXT: { Stmt_Stmt[i0] -> MemRef_A[i0] }; +; CHECK-NEXT: Instructions { +; CHECK-NEXT: store i32 %i.0, i32* %arrayidx, align 4, !polly_split_after !0 +; CHECK-NEXT: } +; CHECK-NEXT: Stmt_Stmt1 +; CHECK-NEXT: Domain := +; CHECK-NEXT: { Stmt_Stmt1[i0] : 0 <= i0 <= 1023 }; +; CHECK-NEXT: Schedule := +; CHECK-NEXT: { Stmt_Stmt1[i0] -> [i0, 2] }; +; CHECK-NEXT: MustWriteAccess := [Reduction Type: NONE] [Scalar: 0] +; CHECK-NEXT: { Stmt_Stmt1[i0] -> MemRef_B[i0] }; +; CHECK-NEXT: Instructions { +; CHECK-NEXT: store i32 %i.0, i32* %arrayidx2, align 4 +; CHECK-NEXT: } +; CHECK-NEXT: } +; +; Function Attrs: noinline nounwind uwtable +define void @func(i32* %A, i32* %B, double* %C) { +entry: + br label %for.cond + +for.cond: ; preds = %for.inc, %entry + %i.0 = phi i32 [ 0, %entry ], [ %add, %for.inc ] + %cmp = icmp slt i32 %i.0, 1024 + br i1 %cmp, label %for.body, label %for.end + +for.body: ; preds = %for.cond + br label %Region + +Region: ; preds = %for.body + %cond = fcmp oeq double 2.100000e+01, 2.100000e+01 + br i1 %cond, label %Region_true, label %Stmt + +Region_true: ; preds = %Region + store double 0.000000e+00, double* %C + br label %Stmt + +Stmt: ; preds = %Region_true, %Region + %idxprom = sext i32 %i.0 to i64 + %arrayidx = getelementptr inbounds i32, i32* %A, i64 %idxprom + store i32 %i.0, i32* %arrayidx, align 4, !polly_split_after !0 + %idxprom1 = sext i32 %i.0 to i64 + %arrayidx2 = getelementptr inbounds i32, i32* %B, i64 %idxprom1 + store i32 %i.0, i32* %arrayidx2, align 4 + br label %for.inc + +for.inc: ; preds = %Stmt + %add = add nsw i32 %i.0, 1 + br label %for.cond + +for.end: ; preds = %for.cond + ret void +} + +!0 = !{!"polly_split_after"} diff --git a/test/ScopInfo/statement.ll b/test/ScopInfo/stmt_split_no_dependence.ll similarity index 53% rename from test/ScopInfo/statement.ll rename to test/ScopInfo/stmt_split_no_dependence.ll index d9a17a89..e11f7fb5 100644 --- a/test/ScopInfo/statement.ll +++ b/test/ScopInfo/stmt_split_no_dependence.ll @@ -7,12 +7,30 @@ ; B[i] = i; ; } ; } - -; CHECK: Instructions { -; CHECK-NEXT: store i32 %i.0, i32* %arrayidx, align 4 -; CHECK-NEXT: store i32 %i.0, i32* %arrayidx2, align 4 +; +; CHECK: Statements { +; CHECK-NEXT: Stmt_Stmt +; CHECK-NEXT: Domain := +; CHECK-NEXT: { Stmt_Stmt[i0] : 0 <= i0 <= 1023 }; +; CHECK-NEXT: Schedule := +; CHECK-NEXT: { Stmt_Stmt[i0] -> [i0, 0] }; +; CHECK-NEXT: MustWriteAccess := [Reduction Type: NONE] [Scalar: 0] +; CHECK-NEXT: { Stmt_Stmt[i0] -> MemRef_A[i0] }; +; CHECK-NEXT: Instructions { +; CHECK-NEXT: store i32 %i.0, i32* %arrayidx, align 4, !polly_split_after !0 +; CHECK-NEXT: } +; CHECK-NEXT: Stmt_Stmt1 +; CHECK-NEXT: Domain := +; CHECK-NEXT: { Stmt_Stmt1[i0] : 0 <= i0 <= 1023 }; +; CHECK-NEXT: Schedule := +; CHECK-NEXT: { Stmt_Stmt1[i0] -> [i0, 1] }; +; CHECK-NEXT: MustWriteAccess := [Reduction Type: NONE] [Scalar: 0] +; CHECK-NEXT: { Stmt_Stmt1[i0] -> MemRef_B[i0] }; +; CHECK-NEXT: Instructions { +; CHECK-NEXT: store i32 %i.0, i32* %arrayidx2, align 4 +; CHECK-NEXT: } ; CHECK-NEXT: } - +; ; Function Attrs: noinline nounwind uwtable define void @func(i32* %A, i32* %B) #0 { entry: @@ -29,7 +47,7 @@ for.body: ; preds = %for.cond Stmt: ; preds = %for.body %idxprom = sext i32 %i.0 to i64 %arrayidx = getelementptr inbounds i32, i32* %A, i64 %idxprom - store i32 %i.0, i32* %arrayidx, align 4 + store i32 %i.0, i32* %arrayidx, align 4, !polly_split_after !0 %idxprom1 = sext i32 %i.0 to i64 %arrayidx2 = getelementptr inbounds i32, i32* %B, i64 %idxprom1 store i32 %i.0, i32* %arrayidx2, align 4 @@ -42,3 +60,5 @@ for.inc: ; preds = %Stmt for.end: ; preds = %for.cond ret void } + +!0 = !{!"polly_split_after"} diff --git a/test/ScopInfo/stmt_split_on_synthesizable.ll b/test/ScopInfo/stmt_split_on_synthesizable.ll new file mode 100644 index 00000000..0ae49d88 --- /dev/null +++ b/test/ScopInfo/stmt_split_on_synthesizable.ll @@ -0,0 +1,56 @@ +; RUN: opt %loadPolly -polly-scops -analyze -polly-print-instructions < %s | FileCheck %s +; +; CHECK: Statements { +; CHECK-NEXT: Stmt_Stmt +; CHECK-NEXT: Domain := +; CHECK-NEXT: { Stmt_Stmt[i0] : 0 <= i0 <= 1023 }; +; CHECK-NEXT: Schedule := +; CHECK-NEXT: { Stmt_Stmt[i0] -> [i0, 0] }; +; CHECK-NEXT: MustWriteAccess := [Reduction Type: NONE] [Scalar: 0] +; CHECK-NEXT: { Stmt_Stmt[i0] -> MemRef_A[i0] }; +; CHECK-NEXT: Instructions { +; CHECK-NEXT: store i32 %i.0, i32* %arrayidx, align 4 +; CHECK-NEXT: } +; CHECK-NEXT: Stmt_Stmt1 +; CHECK-NEXT: Domain := +; CHECK-NEXT: { Stmt_Stmt1[i0] : 0 <= i0 <= 1023 }; +; CHECK-NEXT: Schedule := +; CHECK-NEXT: { Stmt_Stmt1[i0] -> [i0, 1] }; +; CHECK-NEXT: MustWriteAccess := [Reduction Type: NONE] [Scalar: 0] +; CHECK-NEXT: { Stmt_Stmt1[i0] -> MemRef_B[i0] }; +; CHECK-NEXT: Instructions { +; CHECK-NEXT: store i32 %i.0, i32* %arrayidx2, align 4 +; CHECK-NEXT: } +; CHECK-NEXT: } +; +; Function Attrs: noinline nounwind uwtable +define void @func(i32* %A, i32* %B, double* %C) #0 { +entry: + br label %for.cond + +for.cond: ; preds = %for.inc, %entry + %i.0 = phi i32 [ 0, %entry ], [ %add, %for.inc ] + %cmp = icmp slt i32 %i.0, 1024 + br i1 %cmp, label %for.body, label %for.end + +for.body: ; preds = %for.cond + br label %Stmt + +Stmt: + %idxprom = sext i32 %i.0 to i64 + %arrayidx = getelementptr inbounds i32, i32* %A, i64 %idxprom + store i32 %i.0, i32* %arrayidx, align 4 + %idxprom1 = sext i32 %i.0 to i64, !polly_split_after !0 + %arrayidx2 = getelementptr inbounds i32, i32* %B, i64 %idxprom1 + store i32 %i.0, i32* %arrayidx2, align 4 + br label %for.inc + +for.inc: ; preds = %Stmt + %add = add nsw i32 %i.0, 1 + br label %for.cond + +for.end: ; preds = %for.cond + ret void +} + +!0 = !{!"polly_split_after"} diff --git a/test/ScopInfo/stmt_split_phi_in_beginning_bb.ll b/test/ScopInfo/stmt_split_phi_in_beginning_bb.ll new file mode 100644 index 00000000..1e3c1801 --- /dev/null +++ b/test/ScopInfo/stmt_split_phi_in_beginning_bb.ll @@ -0,0 +1,57 @@ +; RUN: opt %loadPolly -polly-scops -analyze -polly-print-instructions < %s | FileCheck %s +; +; CHECK: Statements { +; CHECK-NEXT: Stmt_Stmt +; CHECK-NEXT: Domain := +; CHECK-NEXT: { Stmt_Stmt[i0] : 0 <= i0 <= 1023 }; +; CHECK-NEXT: Schedule := +; CHECK-NEXT: { Stmt_Stmt[i0] -> [i0, 0] }; +; CHECK-NEXT: MustWriteAccess := [Reduction Type: NONE] [Scalar: 0] +; CHECK-NEXT: { Stmt_Stmt[i0] -> MemRef_A[i0] }; +; CHECK-NEXT: Instructions { +; CHECK-NEXT: store i32 %phi, i32* %arrayidx, align 4, !polly_split_after !0 +; CHECK-NEXT: } +; CHECK-NEXT: Stmt_Stmt1 +; CHECK-NEXT: Domain := +; CHECK-NEXT: { Stmt_Stmt1[i0] : 0 <= i0 <= 1023 }; +; CHECK-NEXT: Schedule := +; CHECK-NEXT: { Stmt_Stmt1[i0] -> [i0, 1] }; +; CHECK-NEXT: MustWriteAccess := [Reduction Type: NONE] [Scalar: 0] +; CHECK-NEXT: { Stmt_Stmt1[i0] -> MemRef_B[i0] }; +; CHECK-NEXT: Instructions { +; CHECK-NEXT: store i32 %i.0, i32* %arrayidx2, align 4 +; CHECK-NEXT: } +; CHECK-NEXT: } +; +; Function Attrs: noinline nounwind uwtable +define void @func(i32* %A, i32* %B) #0 { +entry: + br label %for.cond + +for.cond: ; preds = %for.inc, %entry + %i.0 = phi i32 [ 0, %entry ], [ %add, %for.inc ] + %cmp = icmp slt i32 %i.0, 1024 + br i1 %cmp, label %for.body, label %for.end + +for.body: ; preds = %for.cond + br label %Stmt + +Stmt: + %phi = phi i32 [0, %for.body] + %idxprom = sext i32 %i.0 to i64 + %arrayidx = getelementptr inbounds i32, i32* %A, i64 %idxprom + store i32 %phi, i32* %arrayidx, align 4, !polly_split_after !0 + %idxprom1 = sext i32 %i.0 to i64 + %arrayidx2 = getelementptr inbounds i32, i32* %B, i64 %idxprom1 + store i32 %i.0, i32* %arrayidx2, align 4 + br label %for.inc + +for.inc: ; preds = %Stmt + %add = add nsw i32 %i.0, 1 + br label %for.cond + +for.end: ; preds = %for.cond + ret void +} + +!0 = !{!"polly_split_after"} diff --git a/test/ScopInfo/stmt_split_phi_in_stmt.ll b/test/ScopInfo/stmt_split_phi_in_stmt.ll new file mode 100644 index 00000000..44faf846 --- /dev/null +++ b/test/ScopInfo/stmt_split_phi_in_stmt.ll @@ -0,0 +1,75 @@ +; RUN: opt %loadPolly -polly-scops -analyze -polly-print-instructions < %s | FileCheck %s +; +; CHECK: Statements { +; CHECK-NEXT: Stmt_Stmt +; CHECK-NEXT: Domain := +; CHECK-NEXT: { Stmt_Stmt[i0] : 0 <= i0 <= 1023 }; +; CHECK-NEXT: Schedule := +; CHECK-NEXT: { Stmt_Stmt[i0] -> [i0, 0] }; +; CHECK-NEXT: MustWriteAccess := [Reduction Type: NONE] [Scalar: 0] +; CHECK-NEXT: { Stmt_Stmt[i0] -> MemRef_A[i0] }; +; CHECK-NEXT: Instructions { +; CHECK-NEXT: store i32 %i.0, i32* %arrayidx, align 4, !polly_split_after !0 +; CHECK-NEXT: } +; CHECK-NEXT: Stmt_Stmt1 +; CHECK-NEXT: Domain := +; CHECK-NEXT: { Stmt_Stmt1[i0] : 0 <= i0 <= 1023 }; +; CHECK-NEXT: Schedule := +; CHECK-NEXT: { Stmt_Stmt1[i0] -> [i0, 1] }; +; CHECK-NEXT: MustWriteAccess := [Reduction Type: NONE] [Scalar: 0] +; CHECK-NEXT: { Stmt_Stmt1[i0] -> MemRef_B[i0] }; +; CHECK-NEXT: MustWriteAccess := [Reduction Type: NONE] [Scalar: 1] +; CHECK-NEXT: { Stmt_Stmt1[i0] -> MemRef_phi__phi[] }; +; CHECK-NEXT: Instructions { +; CHECK-NEXT: %d = fadd double 2.100000e+01, 2.100000e+01 +; CHECK-NEXT: store i32 %i.0, i32* %arrayidx2, align 4 +; CHECK-NEXT: } +; CHECK-NEXT: Stmt_for_inc +; CHECK-NEXT: Domain := +; CHECK-NEXT: { Stmt_for_inc[i0] : 0 <= i0 <= 1023 }; +; CHECK-NEXT: Schedule := +; CHECK-NEXT: { Stmt_for_inc[i0] -> [i0, 2] }; +; CHECK-NEXT: ReadAccess := [Reduction Type: NONE] [Scalar: 1] +; CHECK-NEXT: { Stmt_for_inc[i0] -> MemRef_phi__phi[] }; +; CHECK-NEXT: MustWriteAccess := [Reduction Type: NONE] [Scalar: 0] +; CHECK-NEXT: { Stmt_for_inc[i0] -> MemRef_C[0] }; +; CHECK-NEXT: Instructions { +; CHECK-NEXT: %phi = phi double [ %d, %Stmt ] +; CHECK-NEXT: store double %phi, double* %C +; CHECK-NEXT: } +; CHECK-NEXT: } +; +; Function Attrs: noinline nounwind uwtable +define void @func(i32* %A, i32* %B, double* %C) #0 { +entry: + br label %for.cond + +for.cond: ; preds = %for.inc, %entry + %i.0 = phi i32 [ 0, %entry ], [ %add, %for.inc ] + %cmp = icmp slt i32 %i.0, 1024 + br i1 %cmp, label %for.body, label %for.end + +for.body: ; preds = %for.cond + br label %Stmt + +Stmt: + %idxprom = sext i32 %i.0 to i64 + %arrayidx = getelementptr inbounds i32, i32* %A, i64 %idxprom + store i32 %i.0, i32* %arrayidx, align 4, !polly_split_after !0 + %idxprom1 = sext i32 %i.0 to i64 + %d = fadd double 21.0, 21.0 + %arrayidx2 = getelementptr inbounds i32, i32* %B, i64 %idxprom1 + store i32 %i.0, i32* %arrayidx2, align 4 + br label %for.inc + +for.inc: ; preds = %Stmt + %phi = phi double [%d, %Stmt] + store double %phi, double* %C + %add = add nsw i32 %i.0, 1 + br label %for.cond + +for.end: ; preds = %for.cond + ret void +} + +!0 = !{!"polly_split_after"} diff --git a/test/ScopInfo/stmt_split_within_loop.ll b/test/ScopInfo/stmt_split_within_loop.ll new file mode 100644 index 00000000..a5837718 --- /dev/null +++ b/test/ScopInfo/stmt_split_within_loop.ll @@ -0,0 +1,60 @@ +; RUN: opt %loadPolly -polly-scops -analyze -polly-print-instructions < %s | FileCheck %s +; +; CHECK: Statements { +; CHECK-NEXT: Stmt_Stmt +; CHECK-NEXT: Domain := +; CHECK-NEXT: { Stmt_Stmt[i0, i1] : 0 <= i0 <= 1023 and 0 <= i1 <= 512 }; +; CHECK-NEXT: Schedule := +; CHECK-NEXT: { Stmt_Stmt[i0, i1] -> [i0, i1, 0] }; +; CHECK-NEXT: MustWriteAccess := [Reduction Type: NONE] [Scalar: 0] +; CHECK-NEXT: { Stmt_Stmt[i0, i1] -> MemRef_A[i0] }; +; CHECK-NEXT: Instructions { +; CHECK-NEXT: store i32 %i.0, i32* %arrayidx, align 4, !polly_split_after !0 +; CHECK-NEXT: } +; CHECK-NEXT: Stmt_Stmt1 +; CHECK-NEXT: Domain := +; CHECK-NEXT: { Stmt_Stmt1[i0, i1] : 0 <= i0 <= 1023 and 0 <= i1 <= 512 }; +; CHECK-NEXT: Schedule := +; CHECK-NEXT: { Stmt_Stmt1[i0, i1] -> [i0, i1, 1] }; +; CHECK-NEXT: MustWriteAccess := [Reduction Type: NONE] [Scalar: 0] +; CHECK-NEXT: { Stmt_Stmt1[i0, i1] -> MemRef_B[i0] }; +; CHECK-NEXT: Instructions { +; CHECK-NEXT: store i32 %i.0, i32* %arrayidx2, align 4 +; CHECK-NEXT: %cond = icmp slt i32 %j, 512 +; CHECK-NEXT: } +; CHECK-NEXT: } +; +; Function Attrs: noinline nounwind uwtable +define void @func(i32* %A, i32* %B, double* %C) #0 { +entry: + br label %for.cond + +for.cond: ; preds = %for.inc, %entry + %i.0 = phi i32 [ 0, %entry ], [ %add, %for.inc ] + %cmp = icmp slt i32 %i.0, 1024 + br i1 %cmp, label %for.body, label %for.end + +for.body: ; preds = %for.cond + br label %Stmt + +Stmt: + %j = phi i32 [ 0, %for.body ], [ %inc, %Stmt ] + %idxprom = sext i32 %i.0 to i64 + %arrayidx = getelementptr inbounds i32, i32* %A, i64 %idxprom + store i32 %i.0, i32* %arrayidx, align 4, !polly_split_after !0 + %idxprom1 = sext i32 %i.0 to i64 + %arrayidx2 = getelementptr inbounds i32, i32* %B, i64 %idxprom1 + store i32 %i.0, i32* %arrayidx2, align 4 + %inc = add nsw i32 %j, 1 + %cond = icmp slt i32 %j, 512 + br i1 %cond, label %Stmt, label %for.inc + +for.inc: ; preds = %Stmt + %add = add nsw i32 %i.0, 1 + br label %for.cond + +for.end: ; preds = %for.cond + ret void +} + +!0 = !{!"polly_split_after"} -- 2.11.4.GIT