Index: include/llvm/Transforms/Scalar/JumpThreading.h =================================================================== --- include/llvm/Transforms/Scalar/JumpThreading.h +++ include/llvm/Transforms/Scalar/JumpThreading.h @@ -62,11 +62,14 @@ std::unique_ptr BFI; std::unique_ptr BPI; bool HasProfileData = false; + #ifdef NDEBUG - SmallPtrSet LoopHeaders; + DenseMap> LoopHeaders; #else - SmallSet, 16> LoopHeaders; + DenseMap, SmallPtrSet> + LoopHeaders; #endif + DenseSet> RecursionSet; unsigned BBDupThreshold; Index: lib/Transforms/Scalar/JumpThreading.cpp =================================================================== --- lib/Transforms/Scalar/JumpThreading.cpp +++ lib/Transforms/Scalar/JumpThreading.cpp @@ -326,7 +326,7 @@ FindFunctionBackedges(F, Edges); for (const auto &Edge : Edges) - LoopHeaders.insert(Edge.second); + LoopHeaders[Edge.second].insert(Edge.first); } /// getKnownConstant - Helper method to determine if we can thread over a @@ -699,8 +699,10 @@ if (!TI->isExceptional() && TI->getNumSuccessors() == 1 && SinglePred != BB && !hasAddressTakenAndUsed(BB)) { // If SinglePred was a loop header, BB becomes one. - if (LoopHeaders.erase(SinglePred)) - LoopHeaders.insert(BB); + if (LoopHeaders.count(SinglePred)) { + LoopHeaders[BB] = LoopHeaders[SinglePred]; + LoopHeaders.erase(SinglePred); + } LVI->eraseBlock(SinglePred); MergeBasicBlockIntoOnlyPred(BB); @@ -1051,7 +1053,8 @@ } // Split them out to their own block. - UnavailablePred = SplitBlockPreds(LoadBB, PredsToSplit, "thread-pre-split"); + if (!(UnavailablePred = SplitBlockPreds(LoadBB, PredsToSplit, "thread-pre-split"))) + return false; } // If the value isn't available in all predecessors, then there will be @@ -1606,6 +1609,19 @@ BasicBlock *JumpThreadingPass::SplitBlockPreds(BasicBlock *BB, ArrayRef Preds, const char *Suffix) { + bool HasBackedge = false; + bool HasNonBackedge = false; + if (LoopHeaders.count(BB)) { + for (auto PredBB : Preds) { + if (LoopHeaders[BB].count(PredBB)) + HasBackedge = true; + else + HasNonBackedge = true; + if (HasNonBackedge && HasBackedge) + return nullptr; + } + } + // Collect the frequencies of all predecessors of BB, which will be used to // update the edge weight on BB->SuccBB. BlockFrequency PredBBFreq(0); Index: test/Transforms/JumpThreading/thread-loads.ll =================================================================== --- test/Transforms/JumpThreading/thread-loads.ll +++ test/Transforms/JumpThreading/thread-loads.ll @@ -377,6 +377,47 @@ ret i32 0 } +; This tests jump threading do not turn a proper loop structures into an +; irreducible loop by SimplifyPartiallyRedundantLoad(). Note this test contain +; unswithch opportunity in %while.cond2, so we want to keep %while.cond2 as a +; loop header. +; CHECK-LABEL: @fn_keep_loop +; CHECK-NOT: while.cond2thread-pre-split +define i32 @fn_keep_loop(i1 %c0, i1 %c1, i64* %ptr0, i64* %ptr1) { +entry: + br i1 %c0, label %while.cond, label %sw.epilog + +while.cond: ; preds = %land.rhs, %entry + %magicptr = load i64, i64* %ptr1, align 8 + %c = icmp eq i64 %magicptr, 0 + br i1 %c, label %while.cond2, label %land.rhs + +land.rhs: ; preds = %while.cond + %arrayidx = getelementptr inbounds i64, i64* %ptr0, i64 1 + %l2 = load i64, i64* %arrayidx, align 4 + %tobool1 = icmp eq i64 %l2, 0 + br i1 %tobool1, label %while.cond2, label %while.cond + +while.cond2: + %l3 = load i64, i64* %ptr1, align 8 + br i1 %c1, label %if.then, label %if.end + +if.then: + call void @fn3(i64 %l3) + br label %if.end + +if.end: + %c2 = icmp eq i64 %l3, 0 + br i1 %c2, label %sw.epilog, label %while.body4 + +while.body4: ; preds = %while.cond2 + call void @fn2(i64 %l3) + br label %while.cond2 + +sw.epilog: ; preds = %while.cond2, %entry + ret i32 undef +} + declare void @fn2(i64) declare void @fn3(i64)