Index: include/llvm/Analysis/Loads.h =================================================================== --- include/llvm/Analysis/Loads.h +++ include/llvm/Analysis/Loads.h @@ -85,7 +85,8 @@ BasicBlock::iterator &ScanFrom, unsigned MaxInstsToScan = DefMaxInstsToScan, AliasAnalysis *AA = nullptr, - bool *IsLoadCSE = nullptr); + bool *IsLoadCSE = nullptr, + unsigned *NumScanedInst = nullptr); } Index: lib/Analysis/Loads.cpp =================================================================== --- lib/Analysis/Loads.cpp +++ lib/Analysis/Loads.cpp @@ -312,7 +312,8 @@ BasicBlock *ScanBB, BasicBlock::iterator &ScanFrom, unsigned MaxInstsToScan, - AliasAnalysis *AA, bool *IsLoadCSE) { + AliasAnalysis *AA, bool *IsLoadCSE, + unsigned *NumScanedInst) { if (MaxInstsToScan == 0) MaxInstsToScan = ~0U; @@ -344,6 +345,9 @@ // Restore ScanFrom to expected value in case next test succeeds ScanFrom++; + if (NumScanedInst) + ++(*NumScanedInst); + // Don't scan huge blocks. if (MaxInstsToScan-- == 0) return nullptr; Index: lib/Transforms/Scalar/JumpThreading.cpp =================================================================== --- lib/Transforms/Scalar/JumpThreading.cpp +++ lib/Transforms/Scalar/JumpThreading.cpp @@ -999,10 +999,25 @@ // Scan the predecessor to see if the value is available in the pred. BBIt = PredBB->end(); - Value *PredAvailable = FindAvailableLoadedValue(LI, PredBB, BBIt, - DefMaxInstsToScan, - nullptr, - &IsLoadCSE); + unsigned NumScanedInst = 0; + Value *PredAvailable = + FindAvailableLoadedValue(LI, PredBB, BBIt, DefMaxInstsToScan, nullptr, + &IsLoadCSE, &NumScanedInst); + + // If PredBB has a single predecessor, continue scanning through the single + // precessor. + BasicBlock *CurPredBB = PredBB; + BasicBlock *SinglePredPredBB = PredBB->getSinglePredecessor(); + while (!PredAvailable && BBIt == CurPredBB->begin() && SinglePredPredBB && + NumScanedInst < DefMaxInstsToScan) { + BBIt = SinglePredPredBB->end(); + PredAvailable = FindAvailableLoadedValue( + LI, SinglePredPredBB, BBIt, (DefMaxInstsToScan - NumScanedInst), + nullptr, &IsLoadCSE, &NumScanedInst); + CurPredBB = SinglePredPredBB; + SinglePredPredBB = SinglePredPredBB->getSinglePredecessor(); + } + if (!PredAvailable) { OneUnavailablePred = PredBB; continue; Index: test/Transforms/JumpThreading/thread-loads.ll =================================================================== --- test/Transforms/JumpThreading/thread-loads.ll +++ test/Transforms/JumpThreading/thread-loads.ll @@ -302,6 +302,44 @@ ret void } +define i32 @fn_SinglePred(i1 %c2,i64* %P) { +; CHECK-LABEL: @fn_SinglePred +; CHECK-LABEL: entry: +; CHECK: %[[L1:.*]] = load i64, i64* %P +; CHECK: br i1 %c, label %cond3, label %cond1 +; CHECK-LABEL: cond2: +; CHECK-NOT: load +; CHECK: %l2 = phi i64 [ %[[L1]], %cond1 ] +; CHECK-LABEL: cond3: +; CHECK: call void @fn2(i64 %l1) +; CHECK: call void @fn3(i64 %l1) + +entry: + %l1 = load i64, i64* %P + %c = icmp eq i64 %l1, 0 + br i1 %c, label %cond2, label %cond1 + +cond1: + br i1 %c2, label %cond2, label %end + +cond2: + %l2 = load i64, i64* %P + call void @fn2(i64 %l2) + %c3 = icmp eq i64 %l2, 0 + br i1 %c3, label %cond3, label %end + +cond3: + call void @fn3(i64 %l2) + br label %end + +end: + ret i32 0 +} + +declare void @fn2(i64) +declare void @fn3(i64) + + !0 = !{!3, !3, i64 0} !1 = !{!"omnipotent char", !2} !2 = !{!"Simple C/C++ TBAA"}