[polly] r230329 - Allow non-affine control flow -- SCoP Modeling
Johannes Doerfert
doerfert at cs.uni-saarland.de
Tue Feb 24 04:00:51 PST 2015
Author: jdoerfert
Date: Tue Feb 24 06:00:50 2015
New Revision: 230329
URL: http://llvm.org/viewvc/llvm-project?rev=230329&view=rev
Log:
Allow non-affine control flow -- SCoP Modeling
This allows us to model non-affine regions in the SCoP representation.
SCoP statements can now describe either basic blocks or non-affine
regions. In the latter case all accesses in the region are accumulated
for the statement and write accesses, except in the entry, have to be
marked as may-write.
Differential Revision: http://reviews.llvm.org/D7846
Added:
polly/trunk/test/ScopInfo/NonAffine/non_affine_conditional_nested.ll
polly/trunk/test/ScopInfo/NonAffine/non_affine_float_compare.ll
Modified:
polly/trunk/include/polly/ScopInfo.h
polly/trunk/include/polly/TempScopInfo.h
polly/trunk/lib/Analysis/ScopInfo.cpp
polly/trunk/lib/Analysis/TempScopInfo.cpp
Modified: polly/trunk/include/polly/ScopInfo.h
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/include/polly/ScopInfo.h?rev=230329&r1=230328&r2=230329&view=diff
==============================================================================
--- polly/trunk/include/polly/ScopInfo.h (original)
+++ polly/trunk/include/polly/ScopInfo.h Tue Feb 24 06:00:50 2015
@@ -429,9 +429,21 @@ class ScopStmt {
//@}
- /// The BasicBlock represented by this statement.
+ /// @brief A SCoP statement represents either a basic block (affine/precise
+ /// case) or a whole region (non-affine case). Only one of the
+ /// following two members will therefore be set and indicate which
+ /// kind of statement this is.
+ ///
+ ///{
+
+ /// @brief The BasicBlock represented by this statement (in the affine case).
BasicBlock *BB;
+ /// @brief The region represented by this statement (in the non-affine case).
+ Region *R;
+
+ ///}
+
/// @brief The isl AST build for the new generated AST.
isl_ast_build *Build;
@@ -449,7 +461,17 @@ class ScopStmt {
TempScop &tempScop);
__isl_give isl_set *buildDomain(TempScop &tempScop, const Region &CurRegion);
void buildScattering(SmallVectorImpl<unsigned> &Scatter);
- void buildAccesses(TempScop &tempScop);
+
+ /// @brief Create the accesses for instructions in @p Block.
+ ///
+ /// @param tempScop The template SCoP.
+ /// @param Block The basic block for which accesses should be
+ /// created.
+ /// @param isApproximated Flag to indicate blocks that might not be executed,
+ /// hence for which write accesses need to be modelt as
+ /// may-write accesses.
+ void buildAccesses(TempScop &tempScop, BasicBlock *Block,
+ bool isApproximated = false);
/// @brief Detect and mark reductions in the ScopStmt
void checkForReductions();
@@ -489,14 +511,19 @@ class ScopStmt {
/// or non-optimal run-time checks.
void deriveAssumptionsFromGEP(GetElementPtrInst *Inst);
- /// @brief Scan the scop and derive assumptions about parameter values.
- void deriveAssumptions();
+ /// @brief Scan @p Block and derive assumptions about parameter values.
+ void deriveAssumptions(BasicBlock *Block);
/// Create the ScopStmt from a BasicBlock.
ScopStmt(Scop &parent, TempScop &tempScop, const Region &CurRegion,
BasicBlock &bb, SmallVectorImpl<Loop *> &NestLoops,
SmallVectorImpl<unsigned> &Scatter);
+ /// Create an overapproximating ScopStmt for the region @p R.
+ ScopStmt(Scop &parent, TempScop &tempScop, const Region &CurRegion, Region &R,
+ SmallVectorImpl<Loop *> &NestLoops,
+ SmallVectorImpl<unsigned> &Scatter);
+
friend class Scop;
public:
@@ -532,11 +559,24 @@ public:
/// @brief Get an isl string representing this scattering.
std::string getScatteringStr() const;
- /// @brief Get the BasicBlock represented by this ScopStmt.
+ /// @brief Get the BasicBlock represented by this ScopStmt (if any).
///
- /// @return The BasicBlock represented by this ScopStmt.
+ /// @return The BasicBlock represented by this ScopStmt, or null if the
+ /// statement represents a region.
BasicBlock *getBasicBlock() const { return BB; }
+ /// @brief Return true if this statement represents a single basic block.
+ bool isBlockStmt() const { return BB != nullptr; }
+
+ /// @brief Get the region represented by this ScopStmt (if any).
+ ///
+ /// @return The region represented by this ScopStmt, or null if the statement
+ /// represents a basic block.
+ Region *getRegion() const { return R; }
+
+ /// @brief Return true if this statement represents a whole region.
+ bool isRegionStmt() const { return R != nullptr; }
+
const MemoryAccess &getAccessFor(const Instruction *Inst) const {
MemoryAccess *A = lookupAccessFor(Inst);
assert(A && "Cannot get memory access because it does not exist!");
@@ -549,7 +589,12 @@ public:
return at == InstructionToAccess.end() ? NULL : at->second;
}
- void setBasicBlock(BasicBlock *Block) { BB = Block; }
+ void setBasicBlock(BasicBlock *Block) {
+ // TODO: Handle the case where the statement is a region statement, thus
+ // the entry block was split and needs to be changed in the region R.
+ assert(BB && "Cannot set a block for a region statement");
+ BB = Block;
+ }
typedef MemoryAccessVec::iterator iterator;
typedef MemoryAccessVec::const_iterator const_iterator;
@@ -697,7 +742,8 @@ private:
/// Create the static control part with a region, max loop depth of this
/// region and parameters used in this region.
- Scop(TempScop &TempScop, LoopInfo &LI, ScalarEvolution &SE, isl_ctx *ctx);
+ Scop(TempScop &TempScop, LoopInfo &LI, ScalarEvolution &SE, ScopDetection &SD,
+ isl_ctx *ctx);
/// @brief Check if a basic block is trivial.
///
@@ -719,12 +765,28 @@ private:
/// @brief Simplify the assumed context.
void simplifyAssumedContext();
+ /// @brief Create a new SCoP statement for either @p BB or @p R.
+ ///
+ /// Either @p BB or @p R should be non-null. A new statement for the non-null
+ /// argument will be created and added to the statement vector and map.
+ ///
+ /// @param BB The basic block we build the statement for (or null)
+ /// @param R The region we build the statement for (or null).
+ /// @param tempScop The temp SCoP we use as model.
+ /// @param CurRegion The SCoP region.
+ /// @param NestLoops A vector of all surrounding loops.
+ /// @param Scatter The position of the new statement as scattering.
+ void addScopStmt(BasicBlock *BB, Region *R, TempScop &tempScop,
+ const Region &CurRegion, SmallVectorImpl<Loop *> &NestLoops,
+ SmallVectorImpl<unsigned> &Scatter);
+
/// Build the Scop and Statement with precalculated scop information.
void buildScop(TempScop &TempScop, const Region &CurRegion,
// Loops in Scop containing CurRegion
SmallVectorImpl<Loop *> &NestLoops,
// The scattering numbers
- SmallVectorImpl<unsigned> &Scatter, LoopInfo &LI);
+ SmallVectorImpl<unsigned> &Scatter, LoopInfo &LI,
+ ScopDetection &SD);
/// @name Helper function for printing the Scop.
///
Modified: polly/trunk/include/polly/TempScopInfo.h
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/include/polly/TempScopInfo.h?rev=230329&r1=230328&r2=230329&view=diff
==============================================================================
--- polly/trunk/include/polly/TempScopInfo.h (original)
+++ polly/trunk/include/polly/TempScopInfo.h Tue Feb 24 06:00:50 2015
@@ -80,6 +80,8 @@ public:
bool isWrite() const { return Type == MUST_WRITE; }
+ void setMayWrite() { Type = MAY_WRITE; }
+
bool isMayWrite() const { return Type == MAY_WRITE; }
bool isScalar() const { return Subscripts.size() == 0; }
@@ -136,7 +138,7 @@ class TempScop {
const BBCondMapType &BBConds;
// Access function of bbs.
- const AccFuncMapType &AccFuncMap;
+ AccFuncMapType &AccFuncMap;
friend class TempScopInfo;
@@ -169,8 +171,8 @@ public:
///
/// @return All access functions in BB
///
- const AccFuncSetType *getAccessFunctions(const BasicBlock *BB) const {
- AccFuncMapType::const_iterator at = AccFuncMap.find(BB);
+ AccFuncSetType *getAccessFunctions(const BasicBlock *BB) {
+ AccFuncMapType::iterator at = AccFuncMap.find(BB);
return at != AccFuncMap.end() ? &(at->second) : 0;
}
//@}
@@ -239,10 +241,9 @@ class TempScopInfo : public FunctionPass
/// @brief Build condition constrains to BBs in a valid Scop.
///
- /// @param BB The BasicBlock to build condition constrains
- /// @param RegionEntry The entry block of the Smallest Region that containing
- /// BB
- void buildCondition(BasicBlock *BB, BasicBlock *RegionEntry);
+ /// @param BB The BasicBlock to build condition constrains
+ /// @param R The region for the current TempScop.
+ void buildCondition(BasicBlock *BB, Region &R);
// Build the affine function of the given condition
void buildAffineCondition(Value &V, bool inverted, Comparison **Comp) const;
Modified: polly/trunk/lib/Analysis/ScopInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/Analysis/ScopInfo.cpp?rev=230329&r1=230328&r2=230329&view=diff
==============================================================================
--- polly/trunk/lib/Analysis/ScopInfo.cpp (original)
+++ polly/trunk/lib/Analysis/ScopInfo.cpp Tue Feb 24 06:00:50 2015
@@ -797,15 +797,23 @@ void ScopStmt::buildScattering(SmallVect
Scattering = isl_map_align_params(Scattering, Parent.getParamSpace());
}
-void ScopStmt::buildAccesses(TempScop &tempScop) {
- for (const auto &AccessPair : *tempScop.getAccessFunctions(BB)) {
- const IRAccess &Access = AccessPair.first;
+void ScopStmt::buildAccesses(TempScop &tempScop, BasicBlock *Block,
+ bool isApproximated) {
+ AccFuncSetType *AFS = tempScop.getAccessFunctions(Block);
+ if (!AFS)
+ return;
+
+ for (auto &AccessPair : *AFS) {
+ IRAccess &Access = AccessPair.first;
Instruction *AccessInst = AccessPair.second;
Type *AccessType = getAccessInstType(AccessInst)->getPointerTo();
const ScopArrayInfo *SAI = getParent()->getOrCreateScopArrayInfo(
Access.getBase(), AccessType, Access.Sizes);
+ if (isApproximated && Access.isWrite())
+ Access.setMayWrite();
+
MemAccs.push_back(new MemoryAccess(Access, AccessInst, this, SAI));
// We do not track locations for scalar memory accesses at the moment.
@@ -894,7 +902,7 @@ __isl_give isl_set *ScopStmt::addConditi
const Region &CurRegion) {
const Region *TopRegion = tempScop.getMaxRegion().getParent(),
*CurrentRegion = &CurRegion;
- const BasicBlock *BranchingBB = BB;
+ const BasicBlock *BranchingBB = BB ? BB : R->getEntry();
do {
if (BranchingBB != CurrentRegion->getEntry()) {
@@ -978,16 +986,39 @@ void ScopStmt::deriveAssumptionsFromGEP(
isl_local_space_free(LSpace);
}
-void ScopStmt::deriveAssumptions() {
- for (Instruction &Inst : *BB)
+void ScopStmt::deriveAssumptions(BasicBlock *Block) {
+ for (Instruction &Inst : *Block)
if (auto *GEP = dyn_cast<GetElementPtrInst>(&Inst))
deriveAssumptionsFromGEP(GEP);
}
ScopStmt::ScopStmt(Scop &parent, TempScop &tempScop, const Region &CurRegion,
+ Region &R, SmallVectorImpl<Loop *> &Nest,
+ SmallVectorImpl<unsigned> &Scatter)
+ : Parent(parent), BB(nullptr), R(&R), Build(nullptr),
+ NestLoops(Nest.size()) {
+ // Setup the induction variables.
+ for (unsigned i = 0, e = Nest.size(); i < e; ++i)
+ NestLoops[i] = Nest[i];
+
+ BaseName = getIslCompatibleName("Stmt_(", R.getNameStr(), ")");
+
+ Domain = buildDomain(tempScop, CurRegion);
+ buildScattering(Scatter);
+
+ BasicBlock *EntryBB = R.getEntry();
+ for (BasicBlock *Block : R.blocks()) {
+ buildAccesses(tempScop, Block, Block != EntryBB);
+ deriveAssumptions(Block);
+ }
+ checkForReductions();
+}
+
+ScopStmt::ScopStmt(Scop &parent, TempScop &tempScop, const Region &CurRegion,
BasicBlock &bb, SmallVectorImpl<Loop *> &Nest,
SmallVectorImpl<unsigned> &Scatter)
- : Parent(parent), BB(&bb), Build(nullptr), NestLoops(Nest.size()) {
+ : Parent(parent), BB(&bb), R(nullptr), Build(nullptr),
+ NestLoops(Nest.size()) {
// Setup the induction variables.
for (unsigned i = 0, e = Nest.size(); i < e; ++i)
NestLoops[i] = Nest[i];
@@ -996,20 +1027,23 @@ ScopStmt::ScopStmt(Scop &parent, TempSco
Domain = buildDomain(tempScop, CurRegion);
buildScattering(Scatter);
- buildAccesses(tempScop);
+ buildAccesses(tempScop, BB);
+ deriveAssumptions(BB);
checkForReductions();
- deriveAssumptions();
}
/// @brief Collect loads which might form a reduction chain with @p StoreMA
///
-/// Check if the stored value for @p StoreMA is a binary operator with one or
-/// two loads as operands. If the binary operand is commutative & associative,
+/// Check if the stored value for @p StoreMA is a binary operator with one
+/// or
+/// two loads as operands. If the binary operand is commutative &
+/// associative,
/// used only once (by @p StoreMA) and its load operands are also used only
/// once, we have found a possible reduction chain. It starts at an operand
/// load and includes the binary operator and @p StoreMA.
///
-/// Note: We allow only one use to ensure the load and binary operator cannot
+/// Note: We allow only one use to ensure the load and binary operator
+/// cannot
/// escape this block or into any other store except @p StoreMA.
void ScopStmt::collectCandiateReductionLoads(
MemoryAccess *StoreMA, SmallVectorImpl<MemoryAccess *> &Loads) {
@@ -1026,7 +1060,8 @@ void ScopStmt::collectCandiateReductionL
if (BinOp->getNumUses() != 1)
return;
- // Skip if the opcode of the binary operator is not commutative/associative
+ // Skip if the opcode of the binary operator is not
+ // commutative/associative
if (!BinOp->isCommutative() || !BinOp->isAssociative())
return;
@@ -1057,11 +1092,16 @@ void ScopStmt::collectCandiateReductionL
/// @brief Check for reductions in this ScopStmt
///
-/// Iterate over all store memory accesses and check for valid binary reduction
-/// like chains. For all candidates we check if they have the same base address
-/// and there are no other accesses which overlap with them. The base address
-/// check rules out impossible reductions candidates early. The overlap check,
-/// together with the "only one user" check in collectCandiateReductionLoads,
+/// Iterate over all store memory accesses and check for valid binary
+/// reduction
+/// like chains. For all candidates we check if they have the same base
+/// address
+/// and there are no other accesses which overlap with them. The base
+/// address
+/// check rules out impossible reductions candidates early. The overlap
+/// check,
+/// together with the "only one user" check in
+/// collectCandiateReductionLoads,
/// guarantees that none of the intermediate results will escape during
/// execution of the loop nest. We basically check here that no other memory
/// access can access the same memory as the potential reduction.
@@ -1069,7 +1109,8 @@ void ScopStmt::checkForReductions() {
SmallVector<MemoryAccess *, 2> Loads;
SmallVector<std::pair<MemoryAccess *, MemoryAccess *>, 4> Candidates;
- // First collect candidate load-store reduction chains by iterating over all
+ // First collect candidate load-store reduction chains by iterating over
+ // all
// stores and collecting possible reduction loads.
for (MemoryAccess *StoreMA : MemAccs) {
if (StoreMA->isRead())
@@ -1282,10 +1323,13 @@ void Scop::simplifyAssumedContext() {
// WARNING: This only holds if the assumptions we have taken do not reduce
// the set of statement instances that are executed. Otherwise we
// may run into a case where the iteration domains suggest that
- // for a certain set of parameter constraints no code is executed,
+ // for a certain set of parameter constraints no code is
+ // executed,
// but in the original program some computation would have been
- // performed. In such a case, modifying the run-time conditions and
- // possibly influencing the run-time check may cause certain scops
+ // performed. In such a case, modifying the run-time conditions
+ // and
+ // possibly influencing the run-time check may cause certain
+ // scops
// to not be executed.
//
// Example:
@@ -1297,7 +1341,8 @@ void Scop::simplifyAssumedContext() {
// A[i+p][j] = 1.0;
//
// we assume that the condition m <= 0 or (m >= 1 and p >= 0) holds as
- // otherwise we would access out of bound data. Now, knowing that code is
+ // otherwise we would access out of bound data. Now, knowing that code
+ // is
// only executed for the case m >= 0, it is sufficient to assume p >= 0.
AssumedContext =
isl_set_gist_params(AssumedContext, isl_union_set_params(getDomains()));
@@ -1374,18 +1419,22 @@ static __isl_give isl_set *getAccessDoma
bool Scop::buildAliasGroups(AliasAnalysis &AA) {
// To create sound alias checks we perform the following steps:
- // o) Use the alias analysis and an alias set tracker to build alias sets
+ // o) Use the alias analysis and an alias set tracker to build alias
+ // sets
// for all memory accesses inside the SCoP.
// o) For each alias set we then map the aliasing pointers back to the
- // memory accesses we know, thus obtain groups of memory accesses which
+ // memory accesses we know, thus obtain groups of memory accesses
+ // which
// might alias.
// o) We divide each group based on the domains of the minimal/maximal
- // accesses. That means two minimal/maximal accesses are only in a group
+ // accesses. That means two minimal/maximal accesses are only in a
+ // group
// if their access domains intersect, otherwise they are in different
// ones.
// o) We split groups such that they contain at most one read only base
// address.
- // o) For each group with more than one base pointer we then compute minimal
+ // o) For each group with more than one base pointer we then compute
+ // minimal
// and maximal accesses to each array in this group.
using AliasGroupTy = SmallVector<MemoryAccess *, 4>;
@@ -1485,7 +1534,8 @@ bool Scop::buildAliasGroups(AliasAnalysi
}
// If we have both read only and non read only base pointers we combine
- // the non read only ones with exactly one read only one at a time into a
+ // the non read only ones with exactly one read only one at a time into
+ // a
// new alias group and clear the old alias group in the end.
for (const auto &ReadOnlyPair : ReadOnlyPairs) {
AliasGroupTy AGNonReadOnly = AG;
@@ -1582,10 +1632,11 @@ void Scop::dropConstantScheduleDims() {
}
Scop::Scop(TempScop &tempScop, LoopInfo &LI, ScalarEvolution &ScalarEvolution,
- isl_ctx *Context)
+ ScopDetection &SD, isl_ctx *Context)
: SE(&ScalarEvolution), R(tempScop.getMaxRegion()), IsOptimized(false),
MaxLoopDepth(getMaxLoopDepthInRegion(tempScop.getMaxRegion(), LI)) {
IslCtx = Context;
+
buildContext();
SmallVector<Loop *, 8> NestLoops;
@@ -1595,7 +1646,7 @@ Scop::Scop(TempScop &tempScop, LoopInfo
// Build the iteration domain, access functions and scattering functions
// traversing the region tree.
- buildScop(tempScop, getRegion(), NestLoops, Scatter, LI);
+ buildScop(tempScop, getRegion(), NestLoops, Scatter, LI, SD);
realignParams();
addParameterBounds();
@@ -1866,9 +1917,39 @@ bool Scop::isTrivialBB(BasicBlock *BB, T
return true;
}
+void Scop::addScopStmt(BasicBlock *BB, Region *R, TempScop &tempScop,
+ const Region &CurRegion,
+ SmallVectorImpl<Loop *> &NestLoops,
+ SmallVectorImpl<unsigned> &Scatter) {
+ ScopStmt *Stmt;
+
+ if (BB) {
+ Stmt = new ScopStmt(*this, tempScop, CurRegion, *BB, NestLoops, Scatter);
+ StmtMap[BB] = Stmt;
+ } else {
+ assert(R && "Either a basic block or a region is needed to "
+ "create a new SCoP stmt.");
+ Stmt = new ScopStmt(*this, tempScop, CurRegion, *R, NestLoops, Scatter);
+ for (BasicBlock *BB : R->blocks())
+ StmtMap[BB] = Stmt;
+ }
+
+ // Insert all statements into the statement map and the statement vector.
+ Stmts.push_back(Stmt);
+
+ // Increasing the Scattering function is OK for the moment, because
+ // we are using a depth first iterator and the program is well structured.
+ ++Scatter[NestLoops.size()];
+}
+
void Scop::buildScop(TempScop &tempScop, const Region &CurRegion,
SmallVectorImpl<Loop *> &NestLoops,
- SmallVectorImpl<unsigned> &Scatter, LoopInfo &LI) {
+ SmallVectorImpl<unsigned> &Scatter, LoopInfo &LI,
+ ScopDetection &SD) {
+ if (SD.isNonAffineSubRegion(&CurRegion, &getRegion()))
+ return addScopStmt(nullptr, const_cast<Region *>(&CurRegion), tempScop,
+ CurRegion, NestLoops, Scatter);
+
Loop *L = castToLoop(CurRegion, LI);
if (L)
@@ -1880,24 +1961,15 @@ void Scop::buildScop(TempScop &tempScop,
for (Region::const_element_iterator I = CurRegion.element_begin(),
E = CurRegion.element_end();
I != E; ++I)
- if (I->isSubRegion())
- buildScop(tempScop, *(I->getNodeAs<Region>()), NestLoops, Scatter, LI);
- else {
+ if (I->isSubRegion()) {
+ buildScop(tempScop, *I->getNodeAs<Region>(), NestLoops, Scatter, LI, SD);
+ } else {
BasicBlock *BB = I->getNodeAs<BasicBlock>();
if (isTrivialBB(BB, tempScop))
continue;
- ScopStmt *Stmt =
- new ScopStmt(*this, tempScop, CurRegion, *BB, NestLoops, Scatter);
-
- // Insert all statements into the statement map and the statement vector.
- StmtMap[BB] = Stmt;
- Stmts.push_back(Stmt);
-
- // Increasing the Scattering function is OK for the moment, because
- // we are using a depth first iterator and the program is well structured.
- ++Scatter[loopDepth];
+ addScopStmt(BB, nullptr, tempScop, CurRegion, NestLoops, Scatter);
}
if (!L)
@@ -1931,6 +2003,7 @@ void ScopInfo::getAnalysisUsage(Analysis
AU.addRequired<LoopInfoWrapperPass>();
AU.addRequired<RegionInfoPass>();
AU.addRequired<ScalarEvolution>();
+ AU.addRequired<ScopDetection>();
AU.addRequired<TempScopInfo>();
AU.addRequired<AliasAnalysis>();
AU.setPreservesAll();
@@ -1939,6 +2012,7 @@ void ScopInfo::getAnalysisUsage(Analysis
bool ScopInfo::runOnRegion(Region *R, RGPassManager &RGM) {
LoopInfo &LI = getAnalysis<LoopInfoWrapperPass>().getLoopInfo();
AliasAnalysis &AA = getAnalysis<AliasAnalysis>();
+ ScopDetection &SD = getAnalysis<ScopDetection>();
ScalarEvolution &SE = getAnalysis<ScalarEvolution>();
TempScop *tempScop = getAnalysis<TempScopInfo>().getTempScop(R);
@@ -1949,7 +2023,7 @@ bool ScopInfo::runOnRegion(Region *R, RG
return false;
}
- scop = new Scop(*tempScop, LI, SE, ctx);
+ scop = new Scop(*tempScop, LI, SE, SD, ctx);
if (!PollyUseRuntimeAliasChecks) {
// Statistics.
@@ -1971,10 +2045,12 @@ bool ScopInfo::runOnRegion(Region *R, RG
DEBUG(dbgs()
<< "\n\nNOTE: Run time checks for " << scop->getNameStr()
- << " could not be created as the number of parameters involved is too "
+ << " could not be created as the number of parameters involved is "
+ "too "
"high. The SCoP will be "
"dismissed.\nUse:\n\t--polly-rtc-max-parameters=X\nto adjust the "
- "maximal number of parameters but be advised that the compile time "
+ "maximal number of parameters but be advised that the compile "
+ "time "
"might increase exponentially.\n\n");
delete scop;
@@ -1993,6 +2069,7 @@ INITIALIZE_AG_DEPENDENCY(AliasAnalysis);
INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass);
INITIALIZE_PASS_DEPENDENCY(RegionInfoPass);
INITIALIZE_PASS_DEPENDENCY(ScalarEvolution);
+INITIALIZE_PASS_DEPENDENCY(ScopDetection);
INITIALIZE_PASS_DEPENDENCY(TempScopInfo);
INITIALIZE_PASS_END(ScopInfo, "polly-scops",
"Polly - Create polyhedral description of Scops", false,
Modified: polly/trunk/lib/Analysis/TempScopInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/Analysis/TempScopInfo.cpp?rev=230329&r1=230328&r2=230329&view=diff
==============================================================================
--- polly/trunk/lib/Analysis/TempScopInfo.cpp (original)
+++ polly/trunk/lib/Analysis/TempScopInfo.cpp Tue Feb 24 06:00:50 2015
@@ -310,15 +310,17 @@ void TempScopInfo::buildAffineCondition(
*Comp = new Comparison(LHS, RHS, Pred);
}
-void TempScopInfo::buildCondition(BasicBlock *BB, BasicBlock *RegionEntry) {
+void TempScopInfo::buildCondition(BasicBlock *BB, Region &R) {
+ BasicBlock *RegionEntry = R.getEntry();
BBCond Cond;
DomTreeNode *BBNode = DT->getNode(BB), *EntryNode = DT->getNode(RegionEntry);
assert(BBNode && EntryNode && "Get null node while building condition!");
- // Walk up the dominance tree until reaching the entry node. Add all
- // conditions on the path to BB except if BB postdominates the block
+ // Walk up the dominance tree until reaching the entry node. Collect all
+ // branching blocks on the path to BB except if BB postdominates the block
// containing the condition.
+ SmallVector<BasicBlock *, 4> DominatorBrBlocks;
while (BBNode != EntryNode) {
BasicBlock *CurBB = BBNode->getBlock();
BBNode = BBNode->getIDom();
@@ -333,6 +335,24 @@ void TempScopInfo::buildCondition(BasicB
if (Br->isUnconditional())
continue;
+ DominatorBrBlocks.push_back(BBNode->getBlock());
+ }
+
+ RegionInfo *RI = R.getRegionInfo();
+ // Iterate in reverse order over the dominating blocks. Until a non-affine
+ // branch was encountered add all conditions collected. If a non-affine branch
+ // was encountered, stop as we overapproximate from here on anyway.
+ for (auto BIt = DominatorBrBlocks.rbegin(), BEnd = DominatorBrBlocks.rend();
+ BIt != BEnd; BIt++) {
+
+ BasicBlock *BBNode = *BIt;
+ BranchInst *Br = dyn_cast<BranchInst>(BBNode->getTerminator());
+ assert(Br && "A Valid Scop should only contain branch instruction");
+ assert(Br->isConditional() && "Assumed a conditional branch");
+
+ if (SD->isNonAffineSubRegion(RI->getRegionFor(BBNode), &R))
+ break;
+
BasicBlock *TrueBB = Br->getSuccessor(0), *FalseBB = Br->getSuccessor(1);
// Is BB on the ELSE side of the branch?
@@ -365,7 +385,7 @@ TempScop *TempScopInfo::buildTempScop(Re
for (const auto &BB : R.blocks()) {
buildAccessFunctions(R, *BB);
- buildCondition(BB, R.getEntry());
+ buildCondition(BB, R);
}
return TScop;
Added: polly/trunk/test/ScopInfo/NonAffine/non_affine_conditional_nested.ll
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/test/ScopInfo/NonAffine/non_affine_conditional_nested.ll?rev=230329&view=auto
==============================================================================
--- polly/trunk/test/ScopInfo/NonAffine/non_affine_conditional_nested.ll (added)
+++ polly/trunk/test/ScopInfo/NonAffine/non_affine_conditional_nested.ll Tue Feb 24 06:00:50 2015
@@ -0,0 +1,72 @@
+; RUN: opt %loadPolly -polly-scops -polly-allow-nonaffine-branches -analyze < %s | FileCheck %s
+;
+; void f(int *A) {
+; for (int i = 0; i < 1024; i++)
+; if (A[i])
+; if (A[i - 1])
+; A[i] = A[i - 2];
+; }
+;
+; CHECK: Region: %bb1---%bb18
+; CHECK: Max Loop Depth: 1
+; CHECK: Statements {
+; CHECK: Stmt_(bb2 => bb16)
+; CHECK: Domain :=
+; CHECK: { Stmt_(bb2 => bb16)[i0] : i0 >= 0 and i0 <= 1023 };
+; CHECK: Scattering :=
+; CHECK: { Stmt_(bb2 => bb16)[i0] -> [i0] };
+; CHECK: ReadAccess := [Reduction Type: NONE] [Scalar: 0]
+; CHECK: { Stmt_(bb2 => bb16)[i0] -> MemRef_A[i0] };
+; CHECK: ReadAccess := [Reduction Type: NONE] [Scalar: 0]
+; CHECK: { Stmt_(bb2 => bb16)[i0] -> MemRef_A[-1 + i0] };
+; CHECK: ReadAccess := [Reduction Type: NONE] [Scalar: 0]
+; CHECK: { Stmt_(bb2 => bb16)[i0] -> MemRef_A[-2 + i0] };
+; CHECK: MayWriteAccess := [Reduction Type: NONE] [Scalar: 0]
+; CHECK: { Stmt_(bb2 => bb16)[i0] -> MemRef_A[i0] };
+; CHECK: }
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+define void @f(i32* %A) {
+bb:
+ br label %bb1
+
+bb1: ; preds = %bb17, %bb
+ %indvars.iv = phi i64 [ %indvars.iv.next, %bb17 ], [ 0, %bb ]
+ %exitcond = icmp ne i64 %indvars.iv, 1024
+ br i1 %exitcond, label %bb2, label %bb18
+
+bb2: ; preds = %bb1
+ %tmp = getelementptr inbounds i32* %A, i64 %indvars.iv
+ %tmp3 = load i32* %tmp, align 4
+ %tmp4 = icmp eq i32 %tmp3, 0
+ br i1 %tmp4, label %bb16, label %bb5
+
+bb5: ; preds = %bb2
+ %tmp6 = add nsw i64 %indvars.iv, -1
+ %tmp7 = getelementptr inbounds i32* %A, i64 %tmp6
+ %tmp8 = load i32* %tmp7, align 4
+ %tmp9 = icmp eq i32 %tmp8, 0
+ br i1 %tmp9, label %bb15, label %bb10
+
+bb10: ; preds = %bb5
+ %tmp11 = add nsw i64 %indvars.iv, -2
+ %tmp12 = getelementptr inbounds i32* %A, i64 %tmp11
+ %tmp13 = load i32* %tmp12, align 4
+ %tmp14 = getelementptr inbounds i32* %A, i64 %indvars.iv
+ store i32 %tmp13, i32* %tmp14, align 4
+ br label %bb15
+
+bb15: ; preds = %bb5, %bb10
+ br label %bb16
+
+bb16: ; preds = %bb2, %bb15
+ br label %bb17
+
+bb17: ; preds = %bb16
+ %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
+ br label %bb1
+
+bb18: ; preds = %bb1
+ ret void
+}
Added: polly/trunk/test/ScopInfo/NonAffine/non_affine_float_compare.ll
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/test/ScopInfo/NonAffine/non_affine_float_compare.ll?rev=230329&view=auto
==============================================================================
--- polly/trunk/test/ScopInfo/NonAffine/non_affine_float_compare.ll (added)
+++ polly/trunk/test/ScopInfo/NonAffine/non_affine_float_compare.ll Tue Feb 24 06:00:50 2015
@@ -0,0 +1,63 @@
+; RUN: opt %loadPolly -polly-scops -polly-allow-nonaffine-branches -analyze < %s | FileCheck %s
+;
+; void f(float *A) {
+; for (int i = 0; i < 1024; i++)
+; if (A[i] == A[i - 1])
+; A[i]++;
+; }
+;
+; CHECK: Function: f
+; CHECK: Region: %bb1---%bb14
+; CHECK: Max Loop Depth: 1
+; CHECK: Statements {
+; CHECK: Stmt_(bb2 => bb12)
+; CHECK: Domain :=
+; CHECK: { Stmt_(bb2 => bb12)[i0] : i0 >= 0 and i0 <= 1023 };
+; CHECK: Scattering :=
+; CHECK: { Stmt_(bb2 => bb12)[i0] -> [i0] };
+; CHECK: ReadAccess := [Reduction Type: NONE] [Scalar: 0]
+; CHECK: { Stmt_(bb2 => bb12)[i0] -> MemRef_A[i0] };
+; CHECK: ReadAccess := [Reduction Type: NONE] [Scalar: 0]
+; CHECK: { Stmt_(bb2 => bb12)[i0] -> MemRef_A[-1 + i0] };
+; CHECK: ReadAccess := [Reduction Type: NONE] [Scalar: 0]
+; CHECK: { Stmt_(bb2 => bb12)[i0] -> MemRef_A[i0] };
+; CHECK: MayWriteAccess := [Reduction Type: NONE] [Scalar: 0]
+; CHECK: { Stmt_(bb2 => bb12)[i0] -> MemRef_A[i0] };
+; CHECK: }
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+define void @f(float* %A) {
+bb:
+ br label %bb1
+
+bb1: ; preds = %bb13, %bb
+ %indvars.iv = phi i64 [ %indvars.iv.next, %bb13 ], [ 0, %bb ]
+ %exitcond = icmp ne i64 %indvars.iv, 1024
+ br i1 %exitcond, label %bb2, label %bb14
+
+bb2: ; preds = %bb1
+ %tmp = getelementptr inbounds float* %A, i64 %indvars.iv
+ %tmp3 = load float* %tmp, align 4
+ %tmp4 = add nsw i64 %indvars.iv, -1
+ %tmp5 = getelementptr inbounds float* %A, i64 %tmp4
+ %tmp6 = load float* %tmp5, align 4
+ %tmp7 = fcmp oeq float %tmp3, %tmp6
+ br i1 %tmp7, label %bb8, label %bb12
+
+bb8: ; preds = %bb2
+ %tmp9 = getelementptr inbounds float* %A, i64 %indvars.iv
+ %tmp10 = load float* %tmp9, align 4
+ %tmp11 = fadd float %tmp10, 1.000000e+00
+ store float %tmp11, float* %tmp9, align 4
+ br label %bb12
+
+bb12: ; preds = %bb8, %bb2
+ br label %bb13
+
+bb13: ; preds = %bb12
+ %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
+ br label %bb1
+
+bb14: ; preds = %bb1
+ ret void
+}
More information about the llvm-commits
mailing list