diff --git a/llvm/lib/Transforms/Scalar/JumpThreading.cpp b/llvm/lib/Transforms/Scalar/JumpThreading.cpp --- a/llvm/lib/Transforms/Scalar/JumpThreading.cpp +++ b/llvm/lib/Transforms/Scalar/JumpThreading.cpp @@ -2125,6 +2125,18 @@ if (PredBB->getSinglePredecessor()) return false; + // Don't thread through PredBB if it contains a successor edge to itself, in + // which case we would infinite loop. Suppose we are threading an edge from + // PredPredBB through PredBB and BB to SuccBB with PredBB containing a + // successor edge to itself. If we allowed jump threading in this case, we + // could duplicate PredBB and BB as, say, PredBB.thread and BB.thread. Since + // PredBB.thread has a successor edge to PredBB, we would immediately come up + // with another jump threading opportunity from PredBB.thread through PredBB + // and BB to SuccBB. This jump threading would repeatedly occur. That is, we + // would keep peeling one iteration from PredBB. + if (llvm::is_contained(successors(PredBB), PredBB)) + return false; + // Don't thread across a loop header. if (LoopHeaders.count(PredBB)) return false; diff --git a/llvm/test/Transforms/JumpThreading/PR44611-across-header-hang.ll b/llvm/test/Transforms/JumpThreading/PR44611-across-header-hang.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Transforms/JumpThreading/PR44611-across-header-hang.ll @@ -0,0 +1,22 @@ +; RUN: opt -S < %s -jump-threading -jump-threading-across-loop-headers | FileCheck %s + +; CHECK-LABEL: @foo +; Just check that we don't hang on this test. + +define void @foo(i32 %a) { +bb_entry: + br label %bb_header + +bb_header: + %b = phi i32 [ %c, %bb_header ], [ 0, %bb_body1 ], [ 2, %bb_body2 ], [ 0, %bb_entry ] + %c = add nuw nsw i32 %b, 1 + %d = icmp ult i32 %c, 6 + br i1 %d, label %bb_header, label %bb_body1 + +bb_body1: + %e = icmp eq i32 %a, 0 + br i1 %e, label %bb_body2, label %bb_header + +bb_body2: + br label %bb_header +}