Index: include/polly/ScopInfo.h =================================================================== --- include/polly/ScopInfo.h +++ include/polly/ScopInfo.h @@ -1113,7 +1113,8 @@ const ScopStmt &operator=(const ScopStmt &) = delete; /// Create the ScopStmt from a BasicBlock. - ScopStmt(Scop &parent, BasicBlock &bb, Loop *SurroundingLoop); + ScopStmt(Scop &parent, BasicBlock &bb, Loop *SurroundingLoop, + std::vector BBToInst); /// Create an overapproximating ScopStmt for the region @p R. ScopStmt(Scop &parent, Region &R, Loop *SurroundingLoop); @@ -1220,6 +1221,9 @@ /// The closest loop that contains this statement. Loop *SurroundingLoop; + /// Vector for Instructions in a Basic Block. + std::vector BBToInst; + /// Build the statement. //@{ void buildDomain(); @@ -1475,6 +1479,7 @@ /// /// @param OS The output stream the ScopStmt is printed to. void print(raw_ostream &OS) const; + void printInstructions(raw_ostream &OS) const; /// Print the ScopStmt to stderr. void dump() const; @@ -1925,7 +1930,8 @@ /// /// @param BB The basic block we build the statement for. /// @param SurroundingLoop The loop the created statement is contained in. - void addScopStmt(BasicBlock *BB, Loop *SurroundingLoop); + void addScopStmt(BasicBlock *BB, Loop *SurroundingLoop, + std::vector BBToInst); /// Create a new SCoP statement for @p R. /// Index: lib/Analysis/ScopBuilder.cpp =================================================================== --- lib/Analysis/ScopBuilder.cpp +++ lib/Analysis/ScopBuilder.cpp @@ -424,6 +424,8 @@ void ScopBuilder::buildStmts(Region &SR) { + std::vector BBToInst; + if (scop->isNonAffineSubRegion(&SR)) { Loop *SurroundingLoop = LI.getLoopFor(SR.getEntry()); auto &BoxedLoops = scop->getBoxedLoops(); @@ -437,8 +439,10 @@ if (I->isSubRegion()) buildStmts(*I->getNodeAs()); else { + for (Instruction &Inst : *I->getNodeAs()) + BBToInst.push_back(&Inst); Loop *SurroundingLoop = LI.getLoopFor(I->getNodeAs()); - scop->addScopStmt(I->getNodeAs(), SurroundingLoop); + scop->addScopStmt(I->getNodeAs(), SurroundingLoop, BBToInst); } } Index: lib/Analysis/ScopInfo.cpp =================================================================== --- lib/Analysis/ScopInfo.cpp +++ lib/Analysis/ScopInfo.cpp @@ -1580,9 +1580,11 @@ BaseName = getIslCompatibleName("Stmt_", R.getNameStr(), ""); } -ScopStmt::ScopStmt(Scop &parent, BasicBlock &bb, Loop *SurroundingLoop) +ScopStmt::ScopStmt(Scop &parent, BasicBlock &bb, Loop *SurroundingLoop, + std::vector BBToInst) : Parent(parent), InvalidDomain(nullptr), Domain(nullptr), BB(&bb), - R(nullptr), Build(nullptr), SurroundingLoop(SurroundingLoop) { + R(nullptr), Build(nullptr), SurroundingLoop(SurroundingLoop), + BBToInst(BBToInst) { BaseName = getIslCompatibleName("Stmt_", &bb, ""); } @@ -1795,6 +1797,15 @@ isl_set_free(InvalidDomain); } +void ScopStmt::printInstructions(raw_ostream &OS) const { + OS << "Instructions {\n"; + + for (Instruction *Inst : BBToInst) + OS.indent(4) << *Inst << "\n"; + + OS.indent(4) << "}\n"; +} + void ScopStmt::print(raw_ostream &OS) const { OS << "\t" << getBaseName() << "\n"; OS.indent(12) << "Domain :=\n"; @@ -1813,6 +1824,8 @@ for (MemoryAccess *Access : MemAccs) Access->print(OS); + + printInstructions(OS.indent(12)); } void ScopStmt::dump() const { print(dbgs()); } @@ -4441,9 +4454,10 @@ return isl_multi_union_pw_aff_from_union_pw_multi_aff(Data.Res); } -void Scop::addScopStmt(BasicBlock *BB, Loop *SurroundingLoop) { +void Scop::addScopStmt(BasicBlock *BB, Loop *SurroundingLoop, + std::vector BBToInst) { assert(BB && "Unexpected nullptr!"); - Stmts.emplace_back(*this, *BB, SurroundingLoop); + Stmts.emplace_back(*this, *BB, SurroundingLoop, BBToInst); auto *Stmt = &Stmts.back(); StmtMap[BB] = Stmt; } Index: test/ScopInfo/statement.ll =================================================================== --- /dev/null +++ test/ScopInfo/statement.ll @@ -0,0 +1,53 @@ +; RUN: opt %loadPolly -polly-scops -analyze < %s | FileCheck %s + +; void func(int *A, int *B){ +; for (int i = 0; i < 1024; i+=1) { +; Stmt: +; A[i] = i; +; B[i] = i; +; } +; } + +; CHECK: Instructions { +; CHECK-NEXT: %i.0 = phi i32 [ 0, %entry ], [ %add, %for.inc ] +; CHECK-NEXT: %cmp = icmp slt i32 %i.0, 1024 +; CHECK-NEXT: br i1 %cmp, label %for.body, label %for.end +; CHECK-NEXT: br label %Stmt +; CHECK-NEXT: %idxprom = sext i32 %i.0 to i64 +; CHECK-NEXT: %arrayidx = getelementptr inbounds i32, i32* %A, i64 %idxprom +; CHECK-NEXT: store i32 %i.0, i32* %arrayidx, align 4 +; CHECK-NEXT: %idxprom1 = sext i32 %i.0 to i64 +; CHECK-NEXT: %arrayidx2 = getelementptr inbounds i32, i32* %B, i64 %idxprom1 +; CHECK-NEXT: store i32 %i.0, i32* %arrayidx2, align 4 +; CHECK-NEXT: br label %for.inc +; 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: ; 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 + %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 +}