Skip to content

Commit 3fd64cc

Browse files
committed
[ValueTracking] Handle two PHIs in isKnownNonEqual()
loop: %cmp.0 = phi i32 [ 3, %entry ], [ %inc, %loop ] %pos.0 = phi i32 [ 1, %entry ], [ %cmp.0, %loop ] ... %inc = add i32 %cmp.0, 1 br label %loop On above example, %pos.0 uses previous iteration's %cmp.0 with backedge according to PHI's instruction's defintion. If the %inc is not same among iterations, we can say the two PHIs are not same. Differential Revision: https://reviews.llvm.org/D98422
1 parent bbb4191 commit 3fd64cc

File tree

2 files changed

+93
-3
lines changed

2 files changed

+93
-3
lines changed

llvm/lib/Analysis/ValueTracking.cpp

Lines changed: 41 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2548,6 +2548,36 @@ static bool isNonEqualMul(const Value *V1, const Value *V2, unsigned Depth,
25482548
return false;
25492549
}
25502550

2551+
static bool isNonEqualPHIs(const PHINode *PN1, const PHINode *PN2,
2552+
unsigned Depth, const Query &Q) {
2553+
// Check two PHIs are in same block.
2554+
if (PN1->getParent() != PN2->getParent())
2555+
return false;
2556+
2557+
SmallPtrSet<const BasicBlock *, 8> VisitedBBs;
2558+
bool UsedFullRecursion = false;
2559+
for (const BasicBlock *IncomBB : PN1->blocks()) {
2560+
if (!VisitedBBs.insert(IncomBB).second)
2561+
continue; // Don't reprocess blocks that we have dealt with already.
2562+
const Value *IV1 = PN1->getIncomingValueForBlock(IncomBB);
2563+
const Value *IV2 = PN2->getIncomingValueForBlock(IncomBB);
2564+
const APInt *C1, *C2;
2565+
if (match(IV1, m_APInt(C1)) && match(IV2, m_APInt(C2)) && *C1 != *C2)
2566+
continue;
2567+
2568+
// Only one pair of phi operands is allowed for full recursion.
2569+
if (UsedFullRecursion)
2570+
return false;
2571+
2572+
Query RecQ = Q;
2573+
RecQ.CxtI = IncomBB->getTerminator();
2574+
if (!isKnownNonEqual(IV1, IV2, Depth + 1, RecQ))
2575+
return false;
2576+
UsedFullRecursion = true;
2577+
}
2578+
return true;
2579+
}
2580+
25512581
/// Return true if it is known that V1 != V2.
25522582
static bool isKnownNonEqual(const Value *V1, const Value *V2, unsigned Depth,
25532583
const Query &Q) {
@@ -2599,12 +2629,20 @@ static bool isKnownNonEqual(const Value *V1, const Value *V2, unsigned Depth,
25992629
case Instruction::SExt:
26002630
case Instruction::ZExt:
26012631
if (O1->getOperand(0)->getType() == O2->getOperand(0)->getType())
2602-
return isKnownNonEqual(O1->getOperand(0), O2->getOperand(0),
2603-
Depth + 1, Q);
2632+
return isKnownNonEqual(O1->getOperand(0), O2->getOperand(0), Depth + 1,
2633+
Q);
2634+
break;
2635+
case Instruction::PHI:
2636+
const PHINode *PN1 = cast<PHINode>(V1);
2637+
const PHINode *PN2 = cast<PHINode>(V2);
2638+
// FIXME: This is missing a generalization to handle the case where one is
2639+
// a PHI and another one isn't.
2640+
if (isNonEqualPHIs(PN1, PN2, Depth, Q))
2641+
return true;
26042642
break;
26052643
};
26062644
}
2607-
2645+
26082646
if (isAddOfNonZero(V1, V2, Depth, Q) || isAddOfNonZero(V2, V1, Depth, Q))
26092647
return true;
26102648

llvm/test/Analysis/ValueTracking/known-non-equal.ll

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -291,4 +291,56 @@ define i1 @mul_other_may_be_zero_or_one(i16 %x, i16 %y) {
291291
ret i1 %cmp
292292
}
293293

294+
define i1 @known_non_equal_phis(i8 %p, i8* %pq, i8 %n, i8 %r) {
295+
; CHECK-LABEL: @known_non_equal_phis(
296+
; CHECK-NEXT: entry:
297+
; CHECK-NEXT: br label [[LOOP:%.*]]
298+
; CHECK: loop:
299+
; CHECK-NEXT: [[A:%.*]] = phi i8 [ 2, [[ENTRY:%.*]] ], [ [[NEXT:%.*]], [[LOOP]] ]
300+
; CHECK-NEXT: [[NEXT]] = mul nsw i8 [[A]], 2
301+
; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i8 [[A]], [[N:%.*]]
302+
; CHECK-NEXT: br i1 [[CMP1]], label [[EXIT:%.*]], label [[LOOP]]
303+
; CHECK: exit:
304+
; CHECK-NEXT: ret i1 true
305+
;
306+
entry:
307+
br label %loop
308+
loop:
309+
%A = phi i8 [ 2, %entry ], [ %next, %loop ]
310+
%B = phi i8 [ 3, %entry ], [ %A, %loop ]
311+
%next = mul nsw i8 %A, 2
312+
%cmp1 = icmp eq i8 %A, %n
313+
br i1 %cmp1, label %exit, label %loop
314+
exit:
315+
%cmp = icmp ne i8 %A, %B
316+
ret i1 %cmp
317+
}
318+
319+
define i1 @known_non_equal_phis_fail(i8 %p, i8* %pq, i8 %n, i8 %r) {
320+
; CHECK-LABEL: @known_non_equal_phis_fail(
321+
; CHECK-NEXT: entry:
322+
; CHECK-NEXT: br label [[LOOP:%.*]]
323+
; CHECK: loop:
324+
; CHECK-NEXT: [[A:%.*]] = phi i8 [ 2, [[ENTRY:%.*]] ], [ [[NEXT:%.*]], [[LOOP]] ]
325+
; CHECK-NEXT: [[B:%.*]] = phi i8 [ 2, [[ENTRY]] ], [ [[A]], [[LOOP]] ]
326+
; CHECK-NEXT: [[NEXT]] = mul nsw i8 [[A]], 2
327+
; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i8 [[A]], [[N:%.*]]
328+
; CHECK-NEXT: br i1 [[CMP1]], label [[EXIT:%.*]], label [[LOOP]]
329+
; CHECK: exit:
330+
; CHECK-NEXT: [[CMP:%.*]] = icmp ne i8 [[A]], [[B]]
331+
; CHECK-NEXT: ret i1 [[CMP]]
332+
;
333+
entry:
334+
br label %loop
335+
loop:
336+
%A = phi i8 [ 2, %entry ], [ %next, %loop ]
337+
%B = phi i8 [ 2, %entry ], [ %A, %loop ]
338+
%next = mul nsw i8 %A, 2
339+
%cmp1 = icmp eq i8 %A, %n
340+
br i1 %cmp1, label %exit, label %loop
341+
exit:
342+
%cmp = icmp ne i8 %A, %B
343+
ret i1 %cmp
344+
}
345+
294346
!0 = !{ i8 1, i8 5 }

0 commit comments

Comments
 (0)