[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.

GitOrigin-RevId: 58e4e71fc8aca712b5662d0654d86ef2ce7fc160
diff --git a/include/polly/ScopDetection.h b/include/polly/ScopDetection.h
index df9e275..e1195c9 100644
--- a/include/polly/ScopDetection.h
+++ b/include/polly/ScopDetection.h
@@ -214,7 +214,11 @@
   /// 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 @@
   /// @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 @@
   /// @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 @@
   /// @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 @@
   ///
   /// @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 @@
   ///
   /// @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 @@
   /// @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 @@
   /// @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 @@
   ///               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 @@
 
   /// 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 @@
   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 @@
   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/include/polly/Support/SCEVValidator.h b/include/polly/Support/SCEVValidator.h
index a341dc0..cf97655 100644
--- a/include/polly/Support/SCEVValidator.h
+++ b/include/polly/Support/SCEVValidator.h
@@ -18,6 +18,7 @@
 } // namespace llvm
 
 namespace polly {
+class ScopDetection;
 
 /// Check if a call is side-effect free and has only constant arguments.
 ///
@@ -94,17 +95,14 @@
 /// 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/include/polly/Support/ScopHelper.h b/include/polly/Support/ScopHelper.h
index b1c6055..1219b7a 100644
--- a/include/polly/Support/ScopHelper.h
+++ b/include/polly/Support/ScopHelper.h
@@ -413,27 +413,6 @@
                            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/lib/Analysis/ScopBuilder.cpp b/lib/Analysis/ScopBuilder.cpp
index 1790774..cb15f59 100644
--- a/lib/Analysis/ScopBuilder.cpp
+++ b/lib/Analysis/ScopBuilder.cpp
@@ -180,12 +180,12 @@
   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 @@
                              .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 @@
     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 @@
   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 @@
       }
     }
 
-    if (containsErrorBlock(RN, scop->getRegion(), LI, DT))
+    if (containsErrorBlock(RN, scop->getRegion(), &SD))
       scop->notifyErrorBlock();
     ;
 
@@ -1013,7 +1013,7 @@
       }
     }
 
-    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 @@
 
   // 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 @@
   // 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/lib/Analysis/ScopDetection.cpp b/lib/Analysis/ScopDetection.cpp
index 65694b7..1b4f3c9 100644
--- a/lib/Analysis/ScopDetection.cpp
+++ b/lib/Analysis/ScopDetection.cpp
@@ -226,6 +226,11 @@
     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 @@
   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::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 @@
 
   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 @@
   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::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::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 @@
   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 @@
   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 @@
   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 @@
   }
 }
 
-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 @@
   }
 
   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 @@
   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 @@
   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/lib/Analysis/ScopGraphPrinter.cpp b/lib/Analysis/ScopGraphPrinter.cpp
index 21fc7e3..1092d5a 100644
--- a/lib/Analysis/ScopGraphPrinter.cpp
+++ b/lib/Analysis/ScopGraphPrinter.cpp
@@ -135,7 +135,7 @@
 
   // Print the cluster of the subregions. This groups the single basic blocks
   // and adds a different 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/lib/Support/SCEVValidator.cpp b/lib/Support/SCEVValidator.cpp
index 0e0ec73..f6b601a 100644
--- a/lib/Support/SCEVValidator.cpp
+++ b/lib/Support/SCEVValidator.cpp
@@ -777,8 +777,7 @@
 }
 
 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 @@
 
     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 @@
   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/lib/Support/ScopHelper.cpp b/lib/Support/ScopHelper.cpp
index 5d29fe8..9221078 100644
--- a/lib/Support/ScopHelper.cpp
+++ b/lib/Support/ScopHelper.cpp
@@ -27,11 +27,6 @@
 
 #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 @@
   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())