[ScopInfo] Use statement lists for entry blocks of region statements

By using statement lists in the entry blocks of region statements, instruction
level analyses also work on region statements.

We currently only model the entry block of a region statements, as this is
sufficient for most transformations the known-passes currently execute. Modeling
instructions in the presence of control flow (e.g. infinite loops) is left
out to not increase code complexity too much. It can be added when good use
cases are found.

This change set is reapplied, after a memory corruption issue had been fixed.

llvm-svn: 312210
This commit is contained in:
Tobias Grosser 2017-08-31 03:15:56 +00:00
parent d3edc16416
commit bd15d13d4e
6 changed files with 131 additions and 14 deletions

View File

@ -221,6 +221,14 @@ class ScopBuilder {
/// Build the access functions for the subregion @p SR.
void buildAccessFunctions();
/// Should an instruction be modeled in a ScopStmt.
///
/// @param Inst The instruction to check.
/// @param L The loop in which context the instruction is looked at.
///
/// @returns True if the instruction should be modeled.
bool shouldModelInst(Instruction *Inst, Loop *L);
/// Create ScopStmt for all BBs and non-affine subregions of @p SR.
///
/// @param SR A subregion of @p R.

View File

@ -1198,7 +1198,15 @@ public:
std::vector<Instruction *> Instructions, int Count);
/// Create an overapproximating ScopStmt for the region @p R.
ScopStmt(Scop &parent, Region &R, Loop *SurroundingLoop);
///
/// @param EntryBlockInstructions The list of instructions that belong to the
/// entry block of the region statement.
/// Instructions are only tracked for entry
/// blocks for now. We currently do not allow
/// to modify the instructions of blocks later
/// in the region statement.
ScopStmt(Scop &parent, Region &R, Loop *SurroundingLoop,
std::vector<Instruction *> EntryBlockInstructions);
/// Create a copy statement.
///
@ -2196,7 +2204,8 @@ private:
///
/// @param R The region we build the statement for.
/// @param SurroundingLoop The loop the created statement is contained in.
void addScopStmt(Region *R, Loop *SurroundingLoop);
void addScopStmt(Region *R, Loop *SurroundingLoop,
std::vector<Instruction *> EntryBlockInstructions);
/// Update access dimensionalities.
///

View File

@ -659,11 +659,20 @@ void ScopBuilder::buildAccessFunctions() {
}
}
bool ScopBuilder::shouldModelInst(Instruction *Inst, Loop *L) {
return !isa<TerminatorInst>(Inst) && !isIgnoredIntrinsic(Inst) &&
!canSynthesize(Inst, *scop, &SE, L);
}
void ScopBuilder::buildStmts(Region &SR) {
if (scop->isNonAffineSubRegion(&SR)) {
std::vector<Instruction *> Instructions;
Loop *SurroundingLoop =
getFirstNonBoxedLoopFor(SR.getEntry(), LI, scop->getBoxedLoops());
scop->addScopStmt(&SR, SurroundingLoop);
for (Instruction &Inst : *SR.getEntry())
if (shouldModelInst(&Inst, SurroundingLoop))
Instructions.push_back(&Inst);
scop->addScopStmt(&SR, SurroundingLoop, Instructions);
return;
}
@ -675,8 +684,7 @@ void ScopBuilder::buildStmts(Region &SR) {
std::vector<Instruction *> Instructions;
for (Instruction &Inst : *I->getNodeAs<BasicBlock>()) {
Loop *L = LI.getLoopFor(Inst.getParent());
if (!isa<TerminatorInst>(&Inst) && !isIgnoredIntrinsic(&Inst) &&
!canSynthesize(&Inst, *scop, &SE, L))
if (shouldModelInst(&Inst, L))
Instructions.push_back(&Inst);
if (Inst.getMetadata("polly_split_after")) {
Loop *SurroundingLoop = LI.getLoopFor(I->getNodeAs<BasicBlock>());

View File

@ -1676,9 +1676,11 @@ buildConditionSets(Scop &S, BasicBlock *BB, TerminatorInst *TI, Loop *L,
ConditionSets);
}
ScopStmt::ScopStmt(Scop &parent, Region &R, Loop *SurroundingLoop)
ScopStmt::ScopStmt(Scop &parent, Region &R, Loop *SurroundingLoop,
std::vector<Instruction *> EntryBlockInstructions)
: Parent(parent), InvalidDomain(nullptr), Domain(nullptr), R(&R),
Build(nullptr), SurroundingLoop(SurroundingLoop) {
Build(nullptr), SurroundingLoop(SurroundingLoop),
Instructions(EntryBlockInstructions) {
BaseName = getIslCompatibleName(
"Stmt", R.getNameStr(), parent.getNextStmtIdx(), "", UseInstructionNames);
}
@ -1779,7 +1781,7 @@ void ScopStmt::print(raw_ostream &OS, bool PrintInstructions) const {
for (MemoryAccess *Access : MemAccs)
Access->print(OS);
if (PrintInstructions && isBlockStmt())
if (PrintInstructions)
printInstructions(OS.indent(12));
}
@ -3588,16 +3590,21 @@ void Scop::assumeNoOutOfBounds() {
}
void Scop::removeFromStmtMap(ScopStmt &Stmt) {
if (Stmt.isRegionStmt())
for (Instruction *Inst : Stmt.getInstructions())
InstStmtMap.erase(Inst);
if (Stmt.isRegionStmt()) {
for (BasicBlock *BB : Stmt.getRegion()->blocks()) {
StmtMap.erase(BB);
// Skip entry basic block, as its instructions are already deleted as
// part of the statement's instruction list.
if (BB == Stmt.getEntryBlock())
continue;
for (Instruction &Inst : *BB)
InstStmtMap.erase(&Inst);
}
else {
} else {
StmtMap.erase(Stmt.getBasicBlock());
for (Instruction *Inst : Stmt.getInstructions())
InstStmtMap.erase(Inst);
}
}
@ -4681,12 +4688,22 @@ void Scop::addScopStmt(BasicBlock *BB, Loop *SurroundingLoop,
}
}
void Scop::addScopStmt(Region *R, Loop *SurroundingLoop) {
void Scop::addScopStmt(Region *R, Loop *SurroundingLoop,
std::vector<Instruction *> Instructions) {
assert(R && "Unexpected nullptr!");
Stmts.emplace_back(*this, *R, SurroundingLoop);
Stmts.emplace_back(*this, *R, SurroundingLoop, Instructions);
auto *Stmt = &Stmts.back();
for (Instruction *Inst : Instructions) {
assert(!InstStmtMap.count(Inst) &&
"Unexpected statement corresponding to the instruction.");
InstStmtMap[Inst] = Stmt;
}
for (BasicBlock *BB : R->blocks()) {
StmtMap[BB].push_back(Stmt);
if (BB == R->getEntry())
continue;
for (Instruction &Inst : *BB) {
assert(!InstStmtMap.count(&Inst) &&
"Unexpected statement corresponding to the instruction.");

View File

@ -0,0 +1,72 @@
; RUN: opt %loadPolly -polly-scops -analyze -polly-print-instructions \
; RUN: < %s | FileCheck %s
; CHECK: Statements {
; CHECK: Stmt_bb46
; CHECK: Domain :=
; CHECK: [tmp44, tmp9] -> { Stmt_bb46[] : tmp9 = tmp44 };
; CHECK: Schedule :=
; CHECK: [tmp44, tmp9] -> { Stmt_bb46[] -> [0, 0] };
; CHECK: MustWriteAccess := [Reduction Type: NONE] [Scalar: 1]
; CHECK: [tmp44, tmp9] -> { Stmt_bb46[] -> MemRef_tmp47[] };
; CHECK: Instructions {
; CHECK: %tmp47 = or i64 1, %tmp14
; CHECK: }
; CHECK: Stmt_bb48__TO__bb56
; CHECK: Domain :=
; CHECK: [tmp44, tmp9] -> { Stmt_bb48__TO__bb56[i0] : tmp9 = tmp44 and 0 <= i0 < tmp44 };
; CHECK: Schedule :=
; CHECK: [tmp44, tmp9] -> { Stmt_bb48__TO__bb56[i0] -> [1, i0] };
; CHECK: ReadAccess := [Reduction Type: NONE] [Scalar: 0]
; CHECK: [tmp44, tmp9] -> { Stmt_bb48__TO__bb56[i0] -> MemRef_A[i0] };
; CHECK: MustWriteAccess := [Reduction Type: NONE] [Scalar: 0]
; CHECK: [tmp44, tmp9] -> { Stmt_bb48__TO__bb56[i0] -> MemRef_A[i0] };
; CHECK: ReadAccess := [Reduction Type: NONE] [Scalar: 1]
; CHECK: [tmp44, tmp9] -> { Stmt_bb48__TO__bb56[i0] -> MemRef_tmp47[] };
; CHECK: MayWriteAccess := [Reduction Type: NONE] [Scalar: 0]
; CHECK: [tmp44, tmp9] -> { Stmt_bb48__TO__bb56[i0] -> MemRef_A[i0] };
; CHECK: Instructions {
; CHECK: %tmp51 = load i64, i64* %tmp50, align 8
; CHECK: %tmp52 = and i64 %tmp51, %tmp26
; CHECK: %tmp53 = icmp eq i64 %tmp52, %tmp26
; CHECK: store i64 42, i64* %tmp50, align 8
; CHECK: }
; CHECK: }
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
define void @quux(i32 %arg, i32 %arg1, i64* %A, i64 %tmp9, i64 %tmp24, i64 %tmp14, i64 %tmp22, i64 %tmp44) {
bb:
%tmp26 = or i64 %tmp22, %tmp24
br label %bb39
bb39: ; preds = %bb39, %bb38
%tmp45 = icmp eq i64 %tmp44, %tmp9
br i1 %tmp45, label %bb46, label %bb81
bb46: ; preds = %bb39
%tmp47 = or i64 1, %tmp14
br label %bb48
bb48: ; preds = %bb56, %bb46
%tmp49 = phi i64 [ 0, %bb46 ], [ %tmp57, %bb56 ]
%tmp50 = getelementptr inbounds i64, i64* %A, i64 %tmp49
%tmp51 = load i64, i64* %tmp50, align 8
%tmp52 = and i64 %tmp51, %tmp26
%tmp53 = icmp eq i64 %tmp52, %tmp26
store i64 42, i64* %tmp50, align 8
br i1 %tmp53, label %bb54, label %bb56
bb54: ; preds = %bb48
%tmp55 = xor i64 %tmp51, %tmp47
store i64 %tmp55, i64* %tmp50, align 8
br label %bb56
bb56: ; preds = %bb54, %bb48
%tmp57 = add nuw nsw i64 %tmp49, 1
%tmp58 = icmp eq i64 %tmp57, %tmp9
br i1 %tmp58, label %bb81, label %bb48
bb81: ; preds = %bb74, %bb56
ret void
}

View File

@ -8,6 +8,9 @@
; 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: Instructions {
; CHECK-NEXT: %cond = fcmp oeq double 2.100000e+01, 2.100000e+01
; CHECK-NEXT: }
; CHECK-NEXT: Stmt_Stmt
; CHECK-NEXT: Domain :=
; CHECK-NEXT: { Stmt_Stmt[i0] : 0 <= i0 <= 1023 };