[polly] 58e4e71 - [Polly] Introduce caching for the isErrorBlock function. NFC.
Michael Kruse via llvm-commits
llvm-commits at lists.llvm.org
Wed Aug 18 12:06:03 PDT 2021
Author: Michael Kruse
Date: 2021-08-18T14:05:50-05:00
New Revision: 58e4e71fc8aca712b5662d0654d86ef2ce7fc160
URL: https://github.com/llvm/llvm-project/commit/58e4e71fc8aca712b5662d0654d86ef2ce7fc160
DIFF: https://github.com/llvm/llvm-project/commit/58e4e71fc8aca712b5662d0654d86ef2ce7fc160.diff
LOG: [Polly] Introduce caching for the isErrorBlock function. NFC.
Compilation of the file insn-attrtab.c of the SPEC CPU 2017 502.gcc_r
benchmark takes excessive time (> 30min) with Polly enabled. Most time
is spent in the isErrorBlock function querying the DominatorTree.
The isErrorBlock is invoked redundantly over the course of ScopDetection
and ScopBuilder. This patch introduces a caching mechanism for its
result.
Instead of a free function, isErrorBlock is moved to ScopDetection where
its cache map resides. This also means that many functions directly or
indirectly calling isErrorBlock are not "const" anymore. The
DetectionContextMap was marked as "mutable", but IMHO it never should
have been since it stores the detection result.
502.gcc_r only takes excessive time with the new pass manager. The
reason seeams to be that it invalidates the ScopDetection analysis more
often than the legacy pass manager, for unknown reasons.
Added:
Modified:
polly/include/polly/ScopDetection.h
polly/include/polly/Support/SCEVValidator.h
polly/include/polly/Support/ScopHelper.h
polly/lib/Analysis/ScopBuilder.cpp
polly/lib/Analysis/ScopDetection.cpp
polly/lib/Analysis/ScopGraphPrinter.cpp
polly/lib/Support/SCEVValidator.cpp
polly/lib/Support/ScopHelper.cpp
Removed:
################################################################################
diff --git a/polly/include/polly/ScopDetection.h b/polly/include/polly/ScopDetection.h
index df9e275c59c24..e1195c92b96ef 100644
--- a/polly/include/polly/ScopDetection.h
+++ b/polly/include/polly/ScopDetection.h
@@ -214,7 +214,11 @@ class ScopDetection {
/// Map to remember detection contexts for all regions.
using DetectionContextMapTy =
DenseMap<BBPair, std::unique_ptr<DetectionContext>>;
- mutable DetectionContextMapTy DetectionContextMap;
+ DetectionContextMapTy DetectionContextMap;
+
+ /// Cache for the isErrorBlock function.
+ DenseMap<std::tuple<const BasicBlock *, const Region *>, bool>
+ ErrorBlockCache;
/// Remove cached results for @p R.
void removeCachedResults(const Region &R);
@@ -305,7 +309,7 @@ class ScopDetection {
/// @param Context The context of scop detection.
///
/// @return True if all blocks in R are valid, false otherwise.
- bool allBlocksValid(DetectionContext &Context) const;
+ bool allBlocksValid(DetectionContext &Context);
/// Check if a region has sufficient compute instructions.
///
@@ -347,7 +351,7 @@ class ScopDetection {
/// @param Context The context of scop detection.
///
/// @return True if R is a Scop, false otherwise.
- bool isValidRegion(DetectionContext &Context) const;
+ bool isValidRegion(DetectionContext &Context);
/// Check if an intrinsic call can be part of a Scop.
///
@@ -420,7 +424,7 @@ class ScopDetection {
/// @param Context The context of scop detection.
///
/// @return True if the instruction is valid, false otherwise.
- bool isValidInstruction(Instruction &Inst, DetectionContext &Context) const;
+ bool isValidInstruction(Instruction &Inst, DetectionContext &Context);
/// Check if the switch @p SI with condition @p Condition is valid.
///
@@ -444,7 +448,7 @@ class ScopDetection {
///
/// @return True if the branch @p BI is valid.
bool isValidBranch(BasicBlock &BB, BranchInst *BI, Value *Condition,
- bool IsLoopBranch, DetectionContext &Context) const;
+ bool IsLoopBranch, DetectionContext &Context);
/// Check if the SCEV @p S is affine in the current @p Context.
///
@@ -472,7 +476,7 @@ class ScopDetection {
///
/// @return True if the BB contains only valid control flow.
bool isValidCFG(BasicBlock &BB, bool IsLoopBranch, bool AllowUnreachable,
- DetectionContext &Context) const;
+ DetectionContext &Context);
/// Is a loop valid with respect to a given region.
///
@@ -480,7 +484,7 @@ class ScopDetection {
/// @param Context The context of scop detection.
///
/// @return True if the loop is valid in the region.
- bool isValidLoop(Loop *L, DetectionContext &Context) const;
+ bool isValidLoop(Loop *L, DetectionContext &Context);
/// Count the number of loops and the maximal loop depth in @p L.
///
@@ -505,7 +509,7 @@ class ScopDetection {
/// @param Context The context of scop detection.
///
/// @return True if ISL can compute the trip count of the loop.
- bool canUseISLTripCount(Loop *L, DetectionContext &Context) const;
+ bool canUseISLTripCount(Loop *L, DetectionContext &Context);
/// Print the locations of all detected scops.
void printLocations(Function &F);
@@ -550,7 +554,7 @@ class ScopDetection {
/// referenced by a Scop that is still to be processed.
///
/// @return Return true if R is the maximum Region in a Scop, false otherwise.
- bool isMaxRegionInScop(const Region &R, bool Verify = true) const;
+ bool isMaxRegionInScop(const Region &R, bool Verify = true);
/// Return the detection context for @p R, nullptr if @p R was invalid.
DetectionContext *getDetectionContext(const Region *R) const;
@@ -596,12 +600,12 @@ class ScopDetection {
/// Verify if all valid Regions in this Function are still valid
/// after some transformations.
- void verifyAnalysis() const;
+ void verifyAnalysis();
/// Verify if R is still a valid part of Scop after some transformations.
///
/// @param R The Region to verify.
- void verifyRegion(const Region &R) const;
+ void verifyRegion(const Region &R);
/// Count the number of loops and the maximal loop depth in @p R.
///
@@ -615,6 +619,24 @@ class ScopDetection {
countBeneficialLoops(Region *R, ScalarEvolution &SE, LoopInfo &LI,
unsigned MinProfitableTrips);
+ /// Check if the block is a error block.
+ ///
+ /// A error block is currently any block that fulfills at least one of
+ /// the following conditions:
+ ///
+ /// - It is terminated by an unreachable instruction
+ /// - It contains a call to a non-pure function that is not immediately
+ /// dominated by a loop header and that does not dominate the region exit.
+ /// This is a heuristic to pick only error blocks that are conditionally
+ /// executed and can be assumed to be not executed at all without the
+ /// domains being available.
+ ///
+ /// @param BB The block to check.
+ /// @param R The analyzed region.
+ ///
+ /// @return True if the block is a error block, false otherwise.
+ bool isErrorBlock(llvm::BasicBlock &BB, const llvm::Region &R);
+
private:
/// OptimizationRemarkEmitter object used to emit diagnostic remarks
OptimizationRemarkEmitter &ORE;
@@ -652,8 +674,7 @@ struct ScopDetectionWrapperPass : public FunctionPass {
void print(raw_ostream &OS, const Module *) const override;
//@}
- ScopDetection &getSD() { return *Result; }
- const ScopDetection &getSD() const { return *Result; }
+ ScopDetection &getSD() const { return *Result; }
};
} // namespace polly
diff --git a/polly/include/polly/Support/SCEVValidator.h b/polly/include/polly/Support/SCEVValidator.h
index a341dc08c4b6b..cf97655e50bd2 100644
--- a/polly/include/polly/Support/SCEVValidator.h
+++ b/polly/include/polly/Support/SCEVValidator.h
@@ -18,6 +18,7 @@ class SCEVConstant;
} // namespace llvm
namespace polly {
+class ScopDetection;
/// Check if a call is side-effect free and has only constant arguments.
///
@@ -94,17 +95,14 @@ extractConstantFactor(const llvm::SCEV *M, llvm::ScalarEvolution &SE);
/// conditions that seemed non-affine before are now in fact affine.
const llvm::SCEV *tryForwardThroughPHI(const llvm::SCEV *Expr, llvm::Region &R,
llvm::ScalarEvolution &SE,
- llvm::LoopInfo &LI,
- const llvm::DominatorTree &DT);
+ ScopDetection *SD);
/// Return a unique non-error block incoming value for @p PHI if available.
///
/// @param R The region to run our code on.
-/// @param LI The loopinfo tree
-/// @param DT The dominator tree
+/// @param SD The ScopDetection
llvm::Value *getUniqueNonErrorValue(llvm::PHINode *PHI, llvm::Region *R,
- llvm::LoopInfo &LI,
- const llvm::DominatorTree &DT);
+ ScopDetection *SD);
} // namespace polly
#endif
diff --git a/polly/include/polly/Support/ScopHelper.h b/polly/include/polly/Support/ScopHelper.h
index b1c605549c610..1219b7a97d44f 100644
--- a/polly/include/polly/Support/ScopHelper.h
+++ b/polly/include/polly/Support/ScopHelper.h
@@ -413,27 +413,6 @@ llvm::Value *expandCodeFor(Scop &S, llvm::ScalarEvolution &SE,
llvm::Instruction *IP, ValueMapT *VMap,
llvm::BasicBlock *RTCBB);
-/// Check if the block is a error block.
-///
-/// A error block is currently any block that fulfills at least one of
-/// the following conditions:
-///
-/// - It is terminated by an unreachable instruction
-/// - It contains a call to a non-pure function that is not immediately
-/// dominated by a loop header and that does not dominate the region exit.
-/// This is a heuristic to pick only error blocks that are conditionally
-/// executed and can be assumed to be not executed at all without the domains
-/// being available.
-///
-/// @param BB The block to check.
-/// @param R The analyzed region.
-/// @param LI The loop info analysis.
-/// @param DT The dominator tree of the function.
-///
-/// @return True if the block is a error block, false otherwise.
-bool isErrorBlock(llvm::BasicBlock &BB, const llvm::Region &R,
- llvm::LoopInfo &LI, const llvm::DominatorTree &DT);
-
/// Return the condition for the terminator @p TI.
///
/// For unconditional branches the "i1 true" condition will be returned.
diff --git a/polly/lib/Analysis/ScopBuilder.cpp b/polly/lib/Analysis/ScopBuilder.cpp
index 17907749ad71b..cb15f59939b63 100644
--- a/polly/lib/Analysis/ScopBuilder.cpp
+++ b/polly/lib/Analysis/ScopBuilder.cpp
@@ -180,12 +180,12 @@ getRegionNodeSuccessor(RegionNode *RN, Instruction *TI, unsigned idx) {
return TI->getSuccessor(idx);
}
-static bool containsErrorBlock(RegionNode *RN, const Region &R, LoopInfo &LI,
- const DominatorTree &DT) {
+static bool containsErrorBlock(RegionNode *RN, const Region &R,
+ ScopDetection *SD) {
if (!RN->isSubRegion())
- return isErrorBlock(*RN->getNodeAs<BasicBlock>(), R, LI, DT);
+ return SD->isErrorBlock(*RN->getNodeAs<BasicBlock>(), R);
for (BasicBlock *BB : RN->getNodeAs<Region>()->blocks())
- if (isErrorBlock(*BB, R, LI, DT))
+ if (SD->isErrorBlock(*BB, R))
return true;
return false;
}
@@ -448,7 +448,7 @@ bool ScopBuilder::buildConditionSets(
.release();
} else if (auto *PHI = dyn_cast<PHINode>(Condition)) {
auto *Unique = dyn_cast<ConstantInt>(
- getUniqueNonErrorValue(PHI, &scop->getRegion(), LI, DT));
+ getUniqueNonErrorValue(PHI, &scop->getRegion(), &SD));
if (Unique->isZero())
ConsequenceCondSet = isl_set_empty(isl_set_get_space(Domain));
@@ -497,8 +497,8 @@ bool ScopBuilder::buildConditionSets(
const SCEV *LeftOperand = SE.getSCEVAtScope(ICond->getOperand(0), L),
*RightOperand = SE.getSCEVAtScope(ICond->getOperand(1), L);
- LeftOperand = tryForwardThroughPHI(LeftOperand, R, SE, LI, DT);
- RightOperand = tryForwardThroughPHI(RightOperand, R, SE, LI, DT);
+ LeftOperand = tryForwardThroughPHI(LeftOperand, R, SE, &SD);
+ RightOperand = tryForwardThroughPHI(RightOperand, R, SE, &SD);
switch (ICond->getPredicate()) {
case ICmpInst::ICMP_ULT:
@@ -844,7 +844,7 @@ bool ScopBuilder::buildDomains(
scop->setDomain(EntryBB, Domain);
if (IsOnlyNonAffineRegion)
- return !containsErrorBlock(R->getNode(), *R, LI, DT);
+ return !containsErrorBlock(R->getNode(), *R, &SD);
if (!buildDomainsWithBranchConstraints(R, InvalidDomainMap))
return false;
@@ -897,7 +897,7 @@ bool ScopBuilder::buildDomainsWithBranchConstraints(
}
}
- if (containsErrorBlock(RN, scop->getRegion(), LI, DT))
+ if (containsErrorBlock(RN, scop->getRegion(), &SD))
scop->notifyErrorBlock();
;
@@ -1013,7 +1013,7 @@ bool ScopBuilder::propagateInvalidStmtDomains(
}
}
- bool ContainsErrorBlock = containsErrorBlock(RN, scop->getRegion(), LI, DT);
+ bool ContainsErrorBlock = containsErrorBlock(RN, scop->getRegion(), &SD);
BasicBlock *BB = getRegionNodeBasicBlock(RN);
isl::set &Domain = scop->getOrInitEmptyDomain(BB);
assert(!Domain.is_null() && "Cannot propagate a nullptr");
@@ -2257,7 +2257,7 @@ void ScopBuilder::buildAccessFunctions(ScopStmt *Stmt, BasicBlock &BB,
// We do not build access functions for error blocks, as they may contain
// instructions we can not model.
- if (isErrorBlock(BB, scop->getRegion(), LI, DT))
+ if (SD.isErrorBlock(BB, scop->getRegion()))
return;
auto BuildAccessesForInst = [this, Stmt,
@@ -3673,7 +3673,7 @@ void ScopBuilder::buildScop(Region &R, AssumptionCache &AC) {
// created somewhere.
const InvariantLoadsSetTy &RIL = scop->getRequiredInvariantLoads();
for (BasicBlock *BB : scop->getRegion().blocks()) {
- if (isErrorBlock(*BB, scop->getRegion(), LI, DT))
+ if (SD.isErrorBlock(*BB, scop->getRegion()))
continue;
for (Instruction &Inst : *BB) {
diff --git a/polly/lib/Analysis/ScopDetection.cpp b/polly/lib/Analysis/ScopDetection.cpp
index 65694b78f90ca..1b4f3c92e0d36 100644
--- a/polly/lib/Analysis/ScopDetection.cpp
+++ b/polly/lib/Analysis/ScopDetection.cpp
@@ -226,6 +226,11 @@ static cl::opt<bool, true> XPollyInvariantLoadHoisting(
cl::location(PollyInvariantLoadHoisting), cl::Hidden, cl::ZeroOrMore,
cl::init(false), cl::cat(PollyCategory));
+static cl::opt<bool> PollyAllowErrorBlocks(
+ "polly-allow-error-blocks",
+ cl::desc("Allow to speculate on the execution of 'error blocks'."),
+ cl::Hidden, cl::init(true), cl::ZeroOrMore, cl::cat(PollyCategory));
+
/// The minimal trip count under which loops are considered unprofitable.
static const unsigned MIN_LOOP_TRIP_COUNT = 8;
@@ -410,7 +415,7 @@ inline bool ScopDetection::invalid(DetectionContext &Context, bool Assert,
return false;
}
-bool ScopDetection::isMaxRegionInScop(const Region &R, bool Verify) const {
+bool ScopDetection::isMaxRegionInScop(const Region &R, bool Verify) {
if (!ValidRegions.count(&R))
return false;
@@ -570,7 +575,7 @@ bool ScopDetection::isValidSwitch(BasicBlock &BB, SwitchInst *SI,
bool ScopDetection::isValidBranch(BasicBlock &BB, BranchInst *BI,
Value *Condition, bool IsLoopBranch,
- DetectionContext &Context) const {
+ DetectionContext &Context) {
// Constant integer conditions are always affine.
if (isa<ConstantInt>(Condition))
return true;
@@ -587,7 +592,7 @@ bool ScopDetection::isValidBranch(BasicBlock &BB, BranchInst *BI,
if (auto PHI = dyn_cast<PHINode>(Condition)) {
auto *Unique = dyn_cast_or_null<ConstantInt>(
- getUniqueNonErrorValue(PHI, &Context.CurRegion, LI, DT));
+ getUniqueNonErrorValue(PHI, &Context.CurRegion, this));
if (Unique && (Unique->isZero() || Unique->isOne()))
return true;
}
@@ -617,8 +622,8 @@ bool ScopDetection::isValidBranch(BasicBlock &BB, BranchInst *BI,
const SCEV *LHS = SE.getSCEVAtScope(ICmp->getOperand(0), L);
const SCEV *RHS = SE.getSCEVAtScope(ICmp->getOperand(1), L);
- LHS = tryForwardThroughPHI(LHS, Context.CurRegion, SE, LI, DT);
- RHS = tryForwardThroughPHI(RHS, Context.CurRegion, SE, LI, DT);
+ LHS = tryForwardThroughPHI(LHS, Context.CurRegion, SE, this);
+ RHS = tryForwardThroughPHI(RHS, Context.CurRegion, SE, this);
// If unsigned operations are not allowed try to approximate the region.
if (ICmp->isUnsigned() && !PollyAllowUnsignedOperations)
@@ -650,7 +655,7 @@ bool ScopDetection::isValidBranch(BasicBlock &BB, BranchInst *BI,
bool ScopDetection::isValidCFG(BasicBlock &BB, bool IsLoopBranch,
bool AllowUnreachable,
- DetectionContext &Context) const {
+ DetectionContext &Context) {
Region &CurRegion = Context.CurRegion;
Instruction *TI = BB.getTerminator();
@@ -1210,14 +1215,14 @@ bool ScopDetection::isValidMemoryAccess(MemAccInst Inst,
}
bool ScopDetection::isValidInstruction(Instruction &Inst,
- DetectionContext &Context) const {
+ DetectionContext &Context) {
for (auto &Op : Inst.operands()) {
auto *OpInst = dyn_cast<Instruction>(&Op);
if (!OpInst)
continue;
- if (isErrorBlock(*OpInst->getParent(), Context.CurRegion, LI, DT)) {
+ if (isErrorBlock(*OpInst->getParent(), Context.CurRegion)) {
auto *PHI = dyn_cast<PHINode>(OpInst);
if (PHI) {
for (User *U : PHI->users()) {
@@ -1275,8 +1280,7 @@ static bool hasExitingBlocks(Loop *L) {
return !ExitingBlocks.empty();
}
-bool ScopDetection::canUseISLTripCount(Loop *L,
- DetectionContext &Context) const {
+bool ScopDetection::canUseISLTripCount(Loop *L, DetectionContext &Context) {
// Ensure the loop has valid exiting blocks as well as latches, otherwise we
// need to overapproximate it as a boxed loop.
SmallVector<BasicBlock *, 4> LoopControlBlocks;
@@ -1291,7 +1295,7 @@ bool ScopDetection::canUseISLTripCount(Loop *L,
return true;
}
-bool ScopDetection::isValidLoop(Loop *L, DetectionContext &Context) const {
+bool ScopDetection::isValidLoop(Loop *L, DetectionContext &Context) {
// Loops that contain part but not all of the blocks of a region cannot be
// handled by the schedule generation. Such loop constructs can happen
// because a region can contain BBs that have no path to the exit block
@@ -1405,6 +1409,70 @@ ScopDetection::countBeneficialLoops(Region *R, ScalarEvolution &SE,
return {LoopNum, MaxLoopDepth};
}
+static bool isErrorBlockImpl(BasicBlock &BB, const Region &R, LoopInfo &LI,
+ const DominatorTree &DT) {
+ if (isa<UnreachableInst>(BB.getTerminator()))
+ return true;
+
+ if (LI.isLoopHeader(&BB))
+ return false;
+
+ // Basic blocks that are always executed are not considered error blocks,
+ // as their execution can not be a rare event.
+ bool DominatesAllPredecessors = true;
+ if (R.isTopLevelRegion()) {
+ for (BasicBlock &I : *R.getEntry()->getParent()) {
+ if (isa<ReturnInst>(I.getTerminator()) && !DT.dominates(&BB, &I)) {
+ DominatesAllPredecessors = false;
+ break;
+ }
+ }
+ } else {
+ for (auto Pred : predecessors(R.getExit())) {
+ if (R.contains(Pred) && !DT.dominates(&BB, Pred)) {
+ DominatesAllPredecessors = false;
+ break;
+ }
+ }
+ }
+
+ if (DominatesAllPredecessors)
+ return false;
+
+ for (Instruction &Inst : BB)
+ if (CallInst *CI = dyn_cast<CallInst>(&Inst)) {
+ if (isDebugCall(CI))
+ continue;
+
+ if (isIgnoredIntrinsic(CI))
+ continue;
+
+ // memset, memcpy and memmove are modeled intrinsics.
+ if (isa<MemSetInst>(CI) || isa<MemTransferInst>(CI))
+ continue;
+
+ if (!CI->doesNotAccessMemory())
+ return true;
+ if (CI->doesNotReturn())
+ return true;
+ }
+
+ return false;
+}
+
+bool ScopDetection::isErrorBlock(llvm::BasicBlock &BB, const llvm::Region &R) {
+ if (!PollyAllowErrorBlocks)
+ return false;
+
+ auto It = ErrorBlockCache.insert({{&BB, &R}, false});
+ if (!It.second)
+ return It.first->getSecond();
+
+ bool Result = isErrorBlockImpl(BB, R, LI, DT);
+ It.first->second = Result;
+ return Result;
+}
+
Region *ScopDetection::expandRegion(Region &R) {
// Initial no valid region was found (greater than R)
std::unique_ptr<Region> LastValidRegion;
@@ -1542,7 +1610,7 @@ void ScopDetection::findScops(Region &R) {
}
}
-bool ScopDetection::allBlocksValid(DetectionContext &Context) const {
+bool ScopDetection::allBlocksValid(DetectionContext &Context) {
Region &CurRegion = Context.CurRegion;
for (const BasicBlock *BB : CurRegion.blocks()) {
@@ -1563,7 +1631,7 @@ bool ScopDetection::allBlocksValid(DetectionContext &Context) const {
}
for (BasicBlock *BB : CurRegion.blocks()) {
- bool IsErrorBlock = isErrorBlock(*BB, CurRegion, LI, DT);
+ bool IsErrorBlock = isErrorBlock(*BB, CurRegion);
// Also check exception blocks (and possibly register them as non-affine
// regions). Even though exception blocks are not modeled, we use them
@@ -1657,7 +1725,7 @@ bool ScopDetection::isProfitableRegion(DetectionContext &Context) const {
return invalid<ReportUnprofitable>(Context, /*Assert=*/true, &CurRegion);
}
-bool ScopDetection::isValidRegion(DetectionContext &Context) const {
+bool ScopDetection::isValidRegion(DetectionContext &Context) {
Region &CurRegion = Context.CurRegion;
LLVM_DEBUG(dbgs() << "Checking region: " << CurRegion.getNameStr() << "\n\t");
@@ -1857,14 +1925,14 @@ const RejectLog *ScopDetection::lookupRejectionLog(const Region *R) const {
return DC ? &DC->Log : nullptr;
}
-void ScopDetection::verifyRegion(const Region &R) const {
+void ScopDetection::verifyRegion(const Region &R) {
assert(isMaxRegionInScop(R) && "Expect R is a valid region.");
DetectionContext Context(const_cast<Region &>(R), AA, true /*verifying*/);
isValidRegion(Context);
}
-void ScopDetection::verifyAnalysis() const {
+void ScopDetection::verifyAnalysis() {
if (!VerifyScops)
return;
diff --git a/polly/lib/Analysis/ScopGraphPrinter.cpp b/polly/lib/Analysis/ScopGraphPrinter.cpp
index 21fc7e3408d30..1092d5aa4a461 100644
--- a/polly/lib/Analysis/ScopGraphPrinter.cpp
+++ b/polly/lib/Analysis/ScopGraphPrinter.cpp
@@ -135,7 +135,7 @@ struct DOTGraphTraits<ScopDetectionWrapperPass *>
// Print the cluster of the subregions. This groups the single basic blocks
// and adds a
diff erent background color for each group.
- static void printRegionCluster(const ScopDetection *SD, const Region *R,
+ static void printRegionCluster(ScopDetection *SD, const Region *R,
raw_ostream &O, unsigned depth = 0) {
O.indent(2 * depth) << "subgraph cluster_" << static_cast<const void *>(R)
<< " {\n";
diff --git a/polly/lib/Support/SCEVValidator.cpp b/polly/lib/Support/SCEVValidator.cpp
index 0e0ec73585713..f6b601ae317da 100644
--- a/polly/lib/Support/SCEVValidator.cpp
+++ b/polly/lib/Support/SCEVValidator.cpp
@@ -777,8 +777,7 @@ extractConstantFactor(const SCEV *S, ScalarEvolution &SE) {
}
const SCEV *tryForwardThroughPHI(const SCEV *Expr, Region &R,
- ScalarEvolution &SE, LoopInfo &LI,
- const DominatorTree &DT) {
+ ScalarEvolution &SE, ScopDetection *SD) {
if (auto *Unknown = dyn_cast<SCEVUnknown>(Expr)) {
Value *V = Unknown->getValue();
auto *PHI = dyn_cast<PHINode>(V);
@@ -789,7 +788,7 @@ const SCEV *tryForwardThroughPHI(const SCEV *Expr, Region &R,
for (unsigned i = 0; i < PHI->getNumIncomingValues(); i++) {
BasicBlock *Incoming = PHI->getIncomingBlock(i);
- if (isErrorBlock(*Incoming, R, LI, DT) && R.contains(Incoming))
+ if (SD->isErrorBlock(*Incoming, R) && R.contains(Incoming))
continue;
if (Final)
return Expr;
@@ -802,12 +801,11 @@ const SCEV *tryForwardThroughPHI(const SCEV *Expr, Region &R,
return Expr;
}
-Value *getUniqueNonErrorValue(PHINode *PHI, Region *R, LoopInfo &LI,
- const DominatorTree &DT) {
+Value *getUniqueNonErrorValue(PHINode *PHI, Region *R, ScopDetection *SD) {
Value *V = nullptr;
for (unsigned i = 0; i < PHI->getNumIncomingValues(); i++) {
BasicBlock *BB = PHI->getIncomingBlock(i);
- if (!isErrorBlock(*BB, *R, LI, DT)) {
+ if (!SD->isErrorBlock(*BB, *R)) {
if (V)
return nullptr;
V = PHI->getIncomingValue(i);
diff --git a/polly/lib/Support/ScopHelper.cpp b/polly/lib/Support/ScopHelper.cpp
index 5d29fe8b7a223..922107833d4bc 100644
--- a/polly/lib/Support/ScopHelper.cpp
+++ b/polly/lib/Support/ScopHelper.cpp
@@ -27,11 +27,6 @@ using namespace polly;
#define DEBUG_TYPE "polly-scop-helper"
-static cl::opt<bool> PollyAllowErrorBlocks(
- "polly-allow-error-blocks",
- cl::desc("Allow to speculate on the execution of 'error blocks'."),
- cl::Hidden, cl::init(true), cl::ZeroOrMore, cl::cat(PollyCategory));
-
static cl::list<std::string> DebugFunctions(
"polly-debug-func",
cl::desc("Allow calls to the specified functions in SCoPs even if their "
@@ -413,60 +408,6 @@ Value *polly::expandCodeFor(Scop &S, ScalarEvolution &SE, const DataLayout &DL,
return Expander.expandCodeFor(E, Ty, IP);
}
-bool polly::isErrorBlock(BasicBlock &BB, const Region &R, LoopInfo &LI,
- const DominatorTree &DT) {
- if (!PollyAllowErrorBlocks)
- return false;
-
- if (isa<UnreachableInst>(BB.getTerminator()))
- return true;
-
- if (LI.isLoopHeader(&BB))
- return false;
-
- // Basic blocks that are always executed are not considered error blocks,
- // as their execution can not be a rare event.
- bool DominatesAllPredecessors = true;
- if (R.isTopLevelRegion()) {
- for (BasicBlock &I : *R.getEntry()->getParent()) {
- if (isa<ReturnInst>(I.getTerminator()) && !DT.dominates(&BB, &I)) {
- DominatesAllPredecessors = false;
- break;
- }
- }
- } else {
- for (auto Pred : predecessors(R.getExit())) {
- if (R.contains(Pred) && !DT.dominates(&BB, Pred)) {
- DominatesAllPredecessors = false;
- break;
- }
- }
- }
-
- if (DominatesAllPredecessors)
- return false;
-
- for (Instruction &Inst : BB)
- if (CallInst *CI = dyn_cast<CallInst>(&Inst)) {
- if (isDebugCall(CI))
- continue;
-
- if (isIgnoredIntrinsic(CI))
- continue;
-
- // memset, memcpy and memmove are modeled intrinsics.
- if (isa<MemSetInst>(CI) || isa<MemTransferInst>(CI))
- continue;
-
- if (!CI->doesNotAccessMemory())
- return true;
- if (CI->doesNotReturn())
- return true;
- }
-
- return false;
-}
-
Value *polly::getConditionFromTerminator(Instruction *TI) {
if (BranchInst *BR = dyn_cast<BranchInst>(TI)) {
if (BR->isUnconditional())
More information about the llvm-commits
mailing list