Index: lib/Analysis/LazyValueInfo.cpp =================================================================== --- lib/Analysis/LazyValueInfo.cpp +++ lib/Analysis/LazyValueInfo.cpp @@ -1270,13 +1270,46 @@ // than re-queried on each call. This would also allow us to merge the // underlying lattice values to get more information if (CxtI) { + BasicBlock *BB = CxtI->getParent(); + + // Function entry or an unreachable block. Bail to avoid confusing + // transforms below. + pred_iterator PI = pred_begin(BB), PE = pred_end(BB); + if (PI == PE) + return Unknown; + + // If V is a PHI node in the same block as the context, we need to ask + // questions about the predicate as applied to the incoming value along + // each edge. This is useful for eliminating cases where the predicate is + // known along all incoming edges. + if (auto *PHI = dyn_cast(V)) + if (PHI->getParent() == BB) { + Tristate Baseline = Unknown; + for (unsigned i = 0; i < PHI->getNumIncomingValues(); i++) { + Value *Incoming = PHI->getIncomingValue(i); + BasicBlock *PredBB = PHI->getIncomingBlock(i); + // Note that PredBB may be BB itself. + Tristate Result = getPredicateOnEdge(Pred, Incoming, C, PredBB, BB, + CxtI); + + // Keep going as long as we've seen a consistent known result for + // all inputs. + auto mergeResults = [](Tristate Baseline, Tristate Result) { + return Baseline == Result ? Baseline : Unknown; + }; + Baseline = (Baseline == Unknown) ? Result /* First iteration */ + : mergeResults(Baseline, Result); /* All others */ + if (Baseline == Unknown) + break; + } + if (Baseline != Unknown) + return Baseline; + } + // For a comparison where the V is outside this block, it's possible // that we've branched on it before. Look to see if the value is known // on all incoming edges. - BasicBlock *BB = CxtI->getParent(); - pred_iterator PI = pred_begin(BB), PE = pred_end(BB); - if (PI != PE && - (!isa(V) || + if ((!isa(V) || cast(V)->getParent() != BB)) { // For predecessor edge, determine if the comparison is true or false // on that edge. If they're all true or all false, we can conclude Index: test/Transforms/JumpThreading/phi-known.ll =================================================================== --- /dev/null +++ test/Transforms/JumpThreading/phi-known.ll @@ -0,0 +1,66 @@ +; RUN: opt -S -jump-threading %s | FileCheck %s + +; Value of predicate known on all inputs (trivial case) +; Note: InstCombine/EarlyCSE would also get this case +define void @test(i8* %p, i8** %addr) { +; CHECK-LABEL: @test +entry: + %cmp0 = icmp eq i8* %p, null + br i1 %cmp0, label %exit, label %loop +loop: +; CHECK-LABEL: loop: +; CHECK-NEXT: phi +; CHECK-NEXT: br label %loop + %p1 = phi i8* [%p, %entry], [%p1, %loop] + %cmp1 = icmp eq i8* %p1, null + br i1 %cmp1, label %exit, label %loop +exit: + ret void +} + +; Value of predicate known on all inputs (non-trivial) +define void @test2(i8* %p) { +; CHECK-LABEL: @test2 +entry: + %cmp0 = icmp eq i8* %p, null + br i1 %cmp0, label %exit, label %loop +loop: + %p1 = phi i8* [%p, %entry], [%p2, %backedge] + %cmp1 = icmp eq i8* %p1, null + br i1 %cmp1, label %exit, label %backedge +backedge: +; CHECK-LABEL: backedge: +; CHECK-NEXT: phi +; CHECK-NEXT: bitcast +; CHECK-NEXT: load +; CHECK-NEXT: cmp +; CHECK-NEXT: br +; CHECK-DAG: label %backedge + %addr = bitcast i8* %p1 to i8** + %p2 = load i8*, i8** %addr + %cmp2 = icmp eq i8* %p2, null + br i1 %cmp2, label %exit, label %loop +exit: + ret void +} + +; If the inputs don't branch the same way, we can't rewrite +; Well, we could unroll this loop exactly twice, but that's +; a different transform. +define void @test_mixed(i8* %p) { +; CHECK-LABEL: @test_mixed +entry: + %cmp0 = icmp eq i8* %p, null + br i1 %cmp0, label %exit, label %loop +loop: +; CHECK-LABEL: loop: +; CHECK-NEXT: phi +; CHECK-NEXT: %cmp1 = icmp +; CHECK-NEXT: br i1 %cmp1 + %p1 = phi i8* [%p, %entry], [%p1, %loop] + %cmp1 = icmp ne i8* %p1, null + br i1 %cmp1, label %exit, label %loop +exit: + ret void +} +