Skip to content

Commit

Permalink
[ScopInfo] Introduce ScopStmt::getSurroundingLoop(). NFC.
Browse files Browse the repository at this point in the history
Introduce ScopStmt::getSurroundingLoop() to replace getFirstNonBoxedLoopFor.

getSurroundingLoop() returns the precomputed surrounding/first non-boxed
loop. Except in ScopDetection, the list of boxed loops is only used to
get the surrounding loop. getFirstNonBoxedLoopFor also requires LoopInfo
at every use which is not necessarily available everywhere where we may
want to use it.

Differential Revision: https://reviews.llvm.org/D30985

llvm-svn: 297899
  • Loading branch information
Meinersbur committed Mar 15, 2017
1 parent 17ce8a2 commit 5545407
Show file tree
Hide file tree
Showing 6 changed files with 104 additions and 97 deletions.
24 changes: 12 additions & 12 deletions polly/include/polly/ScopBuilder.h
Expand Up @@ -61,48 +61,48 @@ class ScopBuilder {
/// Load/Store instruction.
///
/// @param Inst The Load/Store instruction that access the memory
/// @param L The parent loop of the instruction
/// @param Stmt The parent statement of the instruction
///
/// @returns True if the access could be built, False otherwise.
bool buildAccessMultiDimFixed(MemAccInst Inst, Loop *L);
bool buildAccessMultiDimFixed(MemAccInst Inst, ScopStmt *Stmt);

/// Try to build a multi-dimensional parameteric sized MemoryAccess.
/// from the Load/Store instruction.
///
/// @param Inst The Load/Store instruction that access the memory
/// @param L The parent loop of the instruction
/// @param Stmt The parent statement of the instruction
///
/// @returns True if the access could be built, False otherwise.
bool buildAccessMultiDimParam(MemAccInst Inst, Loop *L);
bool buildAccessMultiDimParam(MemAccInst Inst, ScopStmt *Stmt);

/// Try to build a MemoryAccess for a memory intrinsic.
///
/// @param Inst The instruction that access the memory
/// @param L The parent loop of the instruction
/// @param Stmt The parent statement of the instruction
///
/// @returns True if the access could be built, False otherwise.
bool buildAccessMemIntrinsic(MemAccInst Inst, Loop *L);
bool buildAccessMemIntrinsic(MemAccInst Inst, ScopStmt *Stmt);

/// Try to build a MemoryAccess for a call instruction.
///
/// @param Inst The call instruction that access the memory
/// @param L The parent loop of the instruction
/// @param Stmt The parent statement of the instruction
///
/// @returns True if the access could be built, False otherwise.
bool buildAccessCallInst(MemAccInst Inst, Loop *L);
bool buildAccessCallInst(MemAccInst Inst, ScopStmt *Stmt);

/// Build a single-dimensional parametric sized MemoryAccess
/// from the Load/Store instruction.
///
/// @param Inst The Load/Store instruction that access the memory
/// @param L The parent loop of the instruction
void buildAccessSingleDim(MemAccInst Inst, Loop *L);
/// @param Stmt The parent statement of the instruction
void buildAccessSingleDim(MemAccInst Inst, ScopStmt *Stmt);

/// Build an instance of MemoryAccess from the Load/Store instruction.
///
/// @param Inst The Load/Store instruction that access the memory
/// @param L The parent loop of the instruction
void buildMemoryAccess(MemAccInst Inst, Loop *L);
/// @param Stmt The parent statement of the instruction
void buildMemoryAccess(MemAccInst Inst, ScopStmt *Stmt);

/// Analyze and extract the cross-BB scalar dependences (or, dataflow
/// dependencies) of an instruction.
Expand Down
45 changes: 39 additions & 6 deletions polly/include/polly/ScopInfo.h
Expand Up @@ -1112,10 +1112,10 @@ class ScopStmt {
const ScopStmt &operator=(const ScopStmt &) = delete;

/// Create the ScopStmt from a BasicBlock.
ScopStmt(Scop &parent, BasicBlock &bb);
ScopStmt(Scop &parent, BasicBlock &bb, Loop *SurroundingLoop);

/// Create an overapproximating ScopStmt for the region @p R.
ScopStmt(Scop &parent, Region &R);
ScopStmt(Scop &parent, Region &R, Loop *SurroundingLoop);

/// Create a copy statement.
///
Expand Down Expand Up @@ -1216,6 +1216,9 @@ class ScopStmt {

std::string BaseName;

/// The closest loop that contains this statement.
Loop *SurroundingLoop;

/// Build the statement.
//@{
void buildDomain();
Expand Down Expand Up @@ -1311,6 +1314,34 @@ class ScopStmt {
/// statements, return its entry block.
BasicBlock *getEntryBlock() const;

/// Return whether @p L is boxed within this statement.
bool contains(const Loop *L) const {
// Block statements never contain loops.
if (isBlockStmt())
return false;

return getRegion()->contains(L);
}

/// Return the closest innermost loop that contains this statement, but is not
/// contained in it.
///
/// For block statement, this is just the loop that contains the block. Region
/// statements can contain boxed loops, so getting the loop of one of the
/// region's BBs might return such an inner loop. For instance, the region's
/// entry could be a header of a loop, but the region might extend to BBs
/// after the loop exit. Similarly, the region might only contain parts of the
/// loop body and still include the loop header.
///
/// Most of the time the surrounding loop is the top element of #NestLoops,
/// except when it is empty. In that case it return the loop that the whole
/// SCoP is contained in. That can be nullptr if there is no such loop.
Loop *getSurroundingLoop() const {
assert(!isCopyStmt() &&
"No surrounding loop for artificially created statements");
return SurroundingLoop;
}

/// Return true if this statement does not contain any accesses.
bool isEmpty() const { return MemAccs.empty(); }

Expand Down Expand Up @@ -1881,16 +1912,18 @@ class Scop {
/// vector
/// and map.
///
/// @param BB The basic block we build the statement for.
void addScopStmt(BasicBlock *BB);
/// @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);

/// Create a new SCoP statement for @p R.
///
/// A new statement for @p R will be created and added to the statement vector
/// and map.
///
/// @param R The region we build the statement for.
void addScopStmt(Region *R);
/// @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);

/// Update access dimensionalities.
///
Expand Down
19 changes: 0 additions & 19 deletions polly/include/polly/Support/ScopHelper.h
Expand Up @@ -426,24 +426,5 @@ llvm::BasicBlock *getUseBlock(llvm::Use &U);
std::tuple<std::vector<const llvm::SCEV *>, std::vector<int>>
getIndexExpressionsFromGEP(llvm::GetElementPtrInst *GEP,
llvm::ScalarEvolution &SE);

// If the loop is nonaffine/boxed, return the first non-boxed surrounding loop
// for Polly. If the loop is affine, return the loop itself.
//
// @param L Pointer to the Loop object to analyze.
// @param LI Reference to the LoopInfo.
// @param Boxed Loops Set of Boxed Loops we get from the SCoP.
llvm::Loop *getFirstNonBoxedLoopFor(llvm::Loop *L, llvm::LoopInfo &LI,
const BoxedLoopsSetTy &BoxedLoops);

// If the Basic Block belongs to a loop that is nonaffine/boxed, return the
// first non-boxed surrounding loop for Polly. If the loop is affine, return
// the loop itself.
//
// @param BB Pointer to the Basic Block to analyze.
// @param LI Reference to the LoopInfo.
// @param Boxed Loops Set of Boxed Loops we get from the SCoP.
llvm::Loop *getFirstNonBoxedLoopFor(llvm::BasicBlock *BB, llvm::LoopInfo &LI,
const BoxedLoopsSetTy &BoxedLoops);
} // namespace polly
#endif
64 changes: 39 additions & 25 deletions polly/lib/Analysis/ScopBuilder.cpp
Expand Up @@ -112,11 +112,12 @@ void ScopBuilder::buildEscapingDependences(Instruction *Inst) {
}
}

bool ScopBuilder::buildAccessMultiDimFixed(MemAccInst Inst, Loop *L) {
bool ScopBuilder::buildAccessMultiDimFixed(MemAccInst Inst, ScopStmt *Stmt) {
Value *Val = Inst.getValueOperand();
Type *ElementType = Val->getType();
Value *Address = Inst.getPointerOperand();
const SCEV *AccessFunction = SE.getSCEVAtScope(Address, L);
const SCEV *AccessFunction =
SE.getSCEVAtScope(Address, LI.getLoopFor(Inst->getParent()));
const SCEVUnknown *BasePointer =
dyn_cast<SCEVUnknown>(SE.getPointerBase(AccessFunction));
enum MemoryAccess::AccessType AccType =
Expand Down Expand Up @@ -158,7 +159,7 @@ bool ScopBuilder::buildAccessMultiDimFixed(MemAccInst Inst, Loop *L) {

const InvariantLoadsSetTy &ScopRIL = scop->getRequiredInvariantLoads();

Loop *SurroundingLoop = getFirstNonBoxedLoopFor(L, LI, scop->getBoxedLoops());
Loop *SurroundingLoop = Stmt->getSurroundingLoop();
for (auto *Subscript : Subscripts) {
InvariantLoadsSetTy AccessILS;
if (!isAffineExpr(&scop->getRegion(), SurroundingLoop, Subscript, SE,
Expand All @@ -184,7 +185,7 @@ bool ScopBuilder::buildAccessMultiDimFixed(MemAccInst Inst, Loop *L) {
return true;
}

bool ScopBuilder::buildAccessMultiDimParam(MemAccInst Inst, Loop *L) {
bool ScopBuilder::buildAccessMultiDimParam(MemAccInst Inst, ScopStmt *Stmt) {
if (!PollyDelinearize)
return false;

Expand All @@ -195,7 +196,8 @@ bool ScopBuilder::buildAccessMultiDimParam(MemAccInst Inst, Loop *L) {
enum MemoryAccess::AccessType AccType =
isa<LoadInst>(Inst) ? MemoryAccess::READ : MemoryAccess::MUST_WRITE;

const SCEV *AccessFunction = SE.getSCEVAtScope(Address, L);
const SCEV *AccessFunction =
SE.getSCEVAtScope(Address, LI.getLoopFor(Inst->getParent()));
const SCEVUnknown *BasePointer =
dyn_cast<SCEVUnknown>(SE.getPointerBase(AccessFunction));

Expand Down Expand Up @@ -227,20 +229,21 @@ bool ScopBuilder::buildAccessMultiDimParam(MemAccInst Inst, Loop *L) {
return true;
}

bool ScopBuilder::buildAccessMemIntrinsic(MemAccInst Inst, Loop *L) {
bool ScopBuilder::buildAccessMemIntrinsic(MemAccInst Inst, ScopStmt *Stmt) {
auto *MemIntr = dyn_cast_or_null<MemIntrinsic>(Inst);

if (MemIntr == nullptr)
return false;

auto *L = LI.getLoopFor(Inst->getParent());
auto *LengthVal = SE.getSCEVAtScope(MemIntr->getLength(), L);
assert(LengthVal);

// Check if the length val is actually affine or if we overapproximate it
InvariantLoadsSetTy AccessILS;
const InvariantLoadsSetTy &ScopRIL = scop->getRequiredInvariantLoads();

Loop *SurroundingLoop = getFirstNonBoxedLoopFor(L, LI, scop->getBoxedLoops());
Loop *SurroundingLoop = Stmt->getSurroundingLoop();
bool LengthIsAffine = isAffineExpr(&scop->getRegion(), SurroundingLoop,
LengthVal, SE, &AccessILS);
for (LoadInst *LInst : AccessILS)
Expand Down Expand Up @@ -295,7 +298,7 @@ bool ScopBuilder::buildAccessMemIntrinsic(MemAccInst Inst, Loop *L) {
return true;
}

bool ScopBuilder::buildAccessCallInst(MemAccInst Inst, Loop *L) {
bool ScopBuilder::buildAccessCallInst(MemAccInst Inst, ScopStmt *Stmt) {
auto *CI = dyn_cast_or_null<CallInst>(Inst);

if (CI == nullptr)
Expand Down Expand Up @@ -324,6 +327,7 @@ bool ScopBuilder::buildAccessCallInst(MemAccInst Inst, Loop *L) {
// Fall through
case FMRB_OnlyAccessesArgumentPointees:
auto AccType = ReadOnly ? MemoryAccess::READ : MemoryAccess::MAY_WRITE;
Loop *L = LI.getLoopFor(Inst->getParent());
for (const auto &Arg : CI->arg_operands()) {
if (!Arg->getType()->isPointerTy())
continue;
Expand All @@ -342,14 +346,15 @@ bool ScopBuilder::buildAccessCallInst(MemAccInst Inst, Loop *L) {
return true;
}

void ScopBuilder::buildAccessSingleDim(MemAccInst Inst, Loop *L) {
void ScopBuilder::buildAccessSingleDim(MemAccInst Inst, ScopStmt *Stmt) {
Value *Address = Inst.getPointerOperand();
Value *Val = Inst.getValueOperand();
Type *ElementType = Val->getType();
enum MemoryAccess::AccessType AccType =
isa<LoadInst>(Inst) ? MemoryAccess::READ : MemoryAccess::MUST_WRITE;

const SCEV *AccessFunction = SE.getSCEVAtScope(Address, L);
const SCEV *AccessFunction =
SE.getSCEVAtScope(Address, LI.getLoopFor(Inst->getParent()));
const SCEVUnknown *BasePointer =
dyn_cast<SCEVUnknown>(SE.getPointerBase(AccessFunction));

Expand All @@ -359,15 +364,16 @@ void ScopBuilder::buildAccessSingleDim(MemAccInst Inst, Loop *L) {
// Check if the access depends on a loop contained in a non-affine subregion.
bool isVariantInNonAffineLoop = false;
SetVector<const Loop *> Loops;
auto &BoxedLoops = scop->getBoxedLoops();
findLoops(AccessFunction, Loops);
for (const Loop *L : Loops)
if (BoxedLoops.count(L))
if (Stmt->contains(L)) {
isVariantInNonAffineLoop = true;
break;
}

InvariantLoadsSetTy AccessILS;

Loop *SurroundingLoop = getFirstNonBoxedLoopFor(L, LI, BoxedLoops);
Loop *SurroundingLoop = Stmt->getSurroundingLoop();
bool IsAffine = !isVariantInNonAffineLoop &&
isAffineExpr(&scop->getRegion(), SurroundingLoop,
AccessFunction, SE, &AccessILS);
Expand All @@ -384,21 +390,21 @@ void ScopBuilder::buildAccessSingleDim(MemAccInst Inst, Loop *L) {
{AccessFunction}, {nullptr}, Val);
}

void ScopBuilder::buildMemoryAccess(MemAccInst Inst, Loop *L) {
void ScopBuilder::buildMemoryAccess(MemAccInst Inst, ScopStmt *Stmt) {

if (buildAccessMemIntrinsic(Inst, L))
if (buildAccessMemIntrinsic(Inst, Stmt))
return;

if (buildAccessCallInst(Inst, L))
if (buildAccessCallInst(Inst, Stmt))
return;

if (buildAccessMultiDimFixed(Inst, L))
if (buildAccessMultiDimFixed(Inst, Stmt))
return;

if (buildAccessMultiDimParam(Inst, L))
if (buildAccessMultiDimParam(Inst, Stmt))
return;

buildAccessSingleDim(Inst, L);
buildAccessSingleDim(Inst, Stmt);
}

void ScopBuilder::buildAccessFunctions(Region &SR) {
Expand All @@ -419,15 +425,21 @@ void ScopBuilder::buildAccessFunctions(Region &SR) {
void ScopBuilder::buildStmts(Region &SR) {

if (scop->isNonAffineSubRegion(&SR)) {
scop->addScopStmt(&SR);
Loop *SurroundingLoop = LI.getLoopFor(SR.getEntry());
auto &BoxedLoops = scop->getBoxedLoops();
while (BoxedLoops.count(SurroundingLoop))
SurroundingLoop = SurroundingLoop->getParentLoop();
scop->addScopStmt(&SR, SurroundingLoop);
return;
}

for (auto I = SR.element_begin(), E = SR.element_end(); I != E; ++I)
if (I->isSubRegion())
buildStmts(*I->getNodeAs<Region>());
else
scop->addScopStmt(I->getNodeAs<BasicBlock>());
else {
Loop *SurroundingLoop = LI.getLoopFor(I->getNodeAs<BasicBlock>());
scop->addScopStmt(I->getNodeAs<BasicBlock>(), SurroundingLoop);
}
}

void ScopBuilder::buildAccessFunctions(BasicBlock &BB,
Expand All @@ -438,7 +450,7 @@ void ScopBuilder::buildAccessFunctions(BasicBlock &BB,
if (isErrorBlock(BB, scop->getRegion(), LI, DT) && !IsExitBlock)
return;

Loop *L = LI.getLoopFor(&BB);
ScopStmt *Stmt = scop->getStmtFor(&BB);

for (Instruction &Inst : BB) {
PHINode *PHI = dyn_cast<PHINode>(&Inst);
Expand All @@ -449,8 +461,10 @@ void ScopBuilder::buildAccessFunctions(BasicBlock &BB,
if (!PHI && IsExitBlock)
break;

if (auto MemInst = MemAccInst::dyn_cast(Inst))
buildMemoryAccess(MemInst, L);
if (auto MemInst = MemAccInst::dyn_cast(Inst)) {
assert(Stmt && "Cannot build access function in non-existing statement");
buildMemoryAccess(MemInst, Stmt);
}

if (isIgnoredIntrinsic(&Inst))
continue;
Expand Down

0 comments on commit 5545407

Please sign in to comment.