Codegen:Do not invalidate dominator tree when bailing out during code generation
authorTobias Grosser <tobias@grosser.es>
Wed, 23 Mar 2016 06:57:51 +0000 (06:57 +0000)
committerTobias Grosser <tobias@grosser.es>
Wed, 23 Mar 2016 06:57:51 +0000 (06:57 +0000)
When codegenerating invariant loads in some rare cases we cannot generate code
and bail out. This change ensures that we maintain a valid dominator tree
in these situations. This fixes llvm.org/PR26736

Contributed-by: Matthias Reisinger <d412vv1n@gmail.com>
llvm-svn: 264142

polly/lib/CodeGen/CodeGeneration.cpp
polly/test/Isl/CodeGen/stack-overflow-in-load-hoisting.ll

index d66ff94..ec10b3e 100644 (file)
@@ -110,6 +110,17 @@ public:
     }
   }
 
+  /// @brief Mark a basic block unreachable.
+  ///
+  /// Marks the basic block @p Block unreachable by equipping it with an
+  /// UnreachableInst.
+  void markBlockUnreachable(BasicBlock &Block, PollyIRBuilder &Builder) {
+    auto *OrigTerminator = Block.getTerminator();
+    Builder.SetInsertPoint(OrigTerminator);
+    Builder.CreateUnreachable();
+    OrigTerminator->eraseFromParent();
+  }
+
   /// @brief Generate LLVM-IR for the SCoP @p S.
   bool runOnScop(Scop &S) override {
     AI = &getAnalysis<IslAstInfo>();
@@ -146,7 +157,7 @@ public:
     // code generating this scop.
     BasicBlock *StartBlock =
         executeScopConditionally(S, this, Builder.getTrue());
-    auto SplitBlock = StartBlock->getSinglePredecessor();
+    auto *SplitBlock = StartBlock->getSinglePredecessor();
 
     // First generate code for the hoisted invariant loads and transitively the
     // parameters they reference. Afterwards, for the remaining parameters that
@@ -156,15 +167,26 @@ public:
     Builder.SetInsertPoint(SplitBlock->getTerminator());
     if (!NodeBuilder.preloadInvariantLoads()) {
 
+      // Patch the introduced branch condition to ensure that we always execute
+      // the original SCoP.
       auto *FalseI1 = Builder.getFalse();
       auto *SplitBBTerm = Builder.GetInsertBlock()->getTerminator();
       SplitBBTerm->setOperand(0, FalseI1);
-      auto *StartBBTerm = StartBlock->getTerminator();
-      Builder.SetInsertPoint(StartBBTerm);
-      Builder.CreateUnreachable();
-      StartBBTerm->eraseFromParent();
-      isl_ast_node_free(AstRoot);
 
+      // Since the other branch is hence ignored we mark it as unreachable and
+      // adjust the dominator tree accordingly.
+      auto *ExitingBlock = StartBlock->getUniqueSuccessor();
+      assert(ExitingBlock);
+      auto *MergeBlock = ExitingBlock->getUniqueSuccessor();
+      assert(MergeBlock);
+      markBlockUnreachable(*StartBlock, Builder);
+      markBlockUnreachable(*ExitingBlock, Builder);
+      auto *ExitingBB = R->getExitingBlock();
+      assert(ExitingBB);
+      DT->changeImmediateDominator(MergeBlock, ExitingBB);
+      DT->eraseNode(ExitingBlock);
+
+      isl_ast_node_free(AstRoot);
     } else {
 
       NodeBuilder.addParameters(S.getContext());
index 9534b72..e43baca 100644 (file)
@@ -1,4 +1,4 @@
-; RUN: opt %loadPolly -polly-codegen -S < %s | FileCheck %s
+; RUN: opt %loadPolly -verify-dom-info -polly-codegen -S < %s | FileCheck %s
 ;
 ; This caused an infinite recursion during invariant load hoisting at some
 ; point. Check it does not and we add a "false" runtime check.