mirror of
https://github.com/RPCS3/llvm.git
synced 2025-01-23 19:17:17 +00:00
[LazyValueInfo] Look through Phi nodes when trying to prove a predicate
If asked to prove a predicate about a value produced by a PHI node, LazyValueInfo was unable to do so even if the predicate was known to be true for each input to the PHI. This prevented JumpThreading from eliminating a provably redundant branch. The problematic test case looks something like this: ListNode *p = ...; while (p != null) { if (!p) return; x = g->x; // unrelated p = p->next } The null check at the top of the loop is redundant since the value of 'p' is null checked on entry to the loop and before executing the backedge. This resulted in us a) executing an extra null check per iteration and b) not being able to LICM unrelated loads after the check since we couldn't prove they would execute or that their dereferenceability wasn't effected by the null check on the first iteration. Differential Revision: http://reviews.llvm.org/D12383 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@246465 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
21b967e3e1
commit
9c89f4441e
@ -1274,14 +1274,44 @@ LazyValueInfo::getPredicateAt(unsigned Pred, Value *V, Constant *C,
|
||||
// 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
|
||||
// analysis 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<PHINode>(V))
|
||||
if (PHI->getParent() == BB) {
|
||||
Tristate Baseline = Unknown;
|
||||
for (unsigned i = 0, e = PHI->getNumIncomingValues(); i < e; 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.
|
||||
Baseline = (i == 0) ? Result /* First iteration */
|
||||
: (Baseline == Result ? Baseline : Unknown); /* 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<Instruction>(V) ||
|
||||
cast<Instruction>(V)->getParent() != BB)) {
|
||||
if (!isa<Instruction>(V) ||
|
||||
cast<Instruction>(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
|
||||
// the value of the comparison in this block.
|
||||
|
66
test/Transforms/JumpThreading/phi-known.ll
Normal file
66
test/Transforms/JumpThreading/phi-known.ll
Normal file
@ -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
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user