Fix for PR 2323, infinite loop in tail dup.
authorDale Johannesen <dalej@apple.com>
Tue, 13 May 2008 20:06:43 +0000 (20:06 +0000)
committerDale Johannesen <dalej@apple.com>
Tue, 13 May 2008 20:06:43 +0000 (20:06 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@51063 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Transforms/Scalar/TailDuplication.cpp
test/Transforms/TailDup/2008-05-13-InfiniteLoop.ll [new file with mode: 0644]

index 40da808f671d4252da4235e70e0052add6736ceb..c8493b6a5ffdcb4c3e6c57bba594df6a1d8ccf4d 100644 (file)
@@ -32,6 +32,7 @@
 #include "llvm/Support/Compiler.h"
 #include "llvm/Support/Debug.h"
 #include "llvm/ADT/Statistic.h"
+#include "llvm/ADT/SmallPtrSet.h"
 #include <map>
 using namespace llvm;
 
@@ -51,6 +52,7 @@ namespace {
   private:
     inline bool shouldEliminateUnconditionalBranch(TerminatorInst *TI);
     inline void eliminateUnconditionalBranch(BranchInst *BI);
+    SmallPtrSet<BasicBlock*, 4> CycleDetector;
   };
 }
 
@@ -61,17 +63,21 @@ static RegisterPass<TailDup> X("tailduplicate", "Tail Duplication");
 FunctionPass *llvm::createTailDuplicationPass() { return new TailDup(); }
 
 /// runOnFunction - Top level algorithm - Loop over each unconditional branch in
-/// the function, eliminating it if it looks attractive enough.
-///
+/// the function, eliminating it if it looks attractive enough.  CycleDetector
+/// prevents infinite loops by checking that we aren't redirecting a branch to
+/// a place it already pointed to earlier; see PR 2323.
 bool TailDup::runOnFunction(Function &F) {
   bool Changed = false;
-  for (Function::iterator I = F.begin(), E = F.end(); I != E; )
+  CycleDetector.clear();
+  for (Function::iterator I = F.begin(), E = F.end(); I != E; ) {
     if (shouldEliminateUnconditionalBranch(I->getTerminator())) {
       eliminateUnconditionalBranch(cast<BranchInst>(I->getTerminator()));
       Changed = true;
     } else {
       ++I;
+      CycleDetector.clear();
     }
+  }
   return Changed;
 }
 
@@ -140,7 +146,7 @@ bool TailDup::shouldEliminateUnconditionalBranch(TerminatorInst *TI) {
       if (TooMany-- == 0) return false;
   }
   
-  // Finally, if this unconditional branch is a fall-through, be careful about
+  // If this unconditional branch is a fall-through, be careful about
   // tail duplicating it.  In particular, we don't want to taildup it if the
   // original block will still be there after taildup is completed: doing so
   // would eliminate the fall-through, requiring unconditional branches.
@@ -170,6 +176,11 @@ bool TailDup::shouldEliminateUnconditionalBranch(TerminatorInst *TI) {
     }
   }
 
+  // Finally, check that we haven't redirected to this target block earlier;
+  // there are cases where we loop forever if we don't check this (PR 2323).
+  if (!CycleDetector.insert(Dest))
+    return false;
+
   return true;
 }
 
diff --git a/test/Transforms/TailDup/2008-05-13-InfiniteLoop.ll b/test/Transforms/TailDup/2008-05-13-InfiniteLoop.ll
new file mode 100644 (file)
index 0000000..a67e8cd
--- /dev/null
@@ -0,0 +1,26 @@
+; RUN: llvm-as < %s | opt -tailduplicate | llc
+; PR2323
+
+define i32 @func_27(i32 %p_28) nounwind  {
+entry:
+  %tmp125 = trunc i32 %p_28 to i8   ; <i8> [#uses=1]
+  %tmp5.i = icmp eq i8 %tmp125, 0   ; <i1> [#uses=1]
+  br i1 %tmp5.i, label %bb8.i, label %bb.i
+
+bb.i:   ; preds = %entry
+  br label %bb39.i
+
+bb8.i:    ; preds = %entry
+  br label %bb11.i
+
+bb11.i:   ; preds = %bb39.i, %bb8.i
+  %tmp126 = trunc i32 %p_28 to i8   ; <i8> [#uses=1]
+  br label %bb39.i
+
+bb39.i:   ; preds = %bb11.i, %bb.i
+  %tmp127 = trunc i32 %p_28 to i8   ; <i8> [#uses=1]
+  br label %bb11.i
+
+func_29.exit:   ; No predecessors!
+  ret i32 undef
+}