1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-10-18 18:42:46 +02:00

[ValueTracking] Handle increasing mul recurrence in isKnownNonZero()

Differential Revision: https://reviews.llvm.org/D99069
This commit is contained in:
Jingu Kang 2021-03-22 10:12:39 +00:00
parent 3b0888e5fb
commit af9f082c95
2 changed files with 214 additions and 15 deletions

View File

@ -2450,21 +2450,19 @@ bool isKnownNonZero(const Value *V, const APInt &DemandedElts, unsigned Depth,
else if (const PHINode *PN = dyn_cast<PHINode>(V)) {
// Try and detect a recurrence that monotonically increases from a
// starting value, as these are common as induction variables.
if (PN->getNumIncomingValues() == 2) {
Value *Start = PN->getIncomingValue(0);
Value *Induction = PN->getIncomingValue(1);
if (isa<ConstantInt>(Induction) && !isa<ConstantInt>(Start))
std::swap(Start, Induction);
if (ConstantInt *C = dyn_cast<ConstantInt>(Start)) {
if (!C->isZero() && !C->isNegative()) {
ConstantInt *X;
if (Q.IIQ.UseInstrInfo &&
(match(Induction, m_NSWAdd(m_Specific(PN), m_ConstantInt(X))) ||
match(Induction, m_NUWAdd(m_Specific(PN), m_ConstantInt(X)))) &&
!X->isNegative())
return true;
}
}
BinaryOperator *BO = nullptr;
Value *Start = nullptr, *Step = nullptr;
const APInt *StartC, *StepC;
if (Q.IIQ.UseInstrInfo && matchSimpleRecurrence(PN, BO, Start, Step) &&
match(Start, m_APInt(StartC)) && match(Step, m_APInt(StepC))) {
if (BO->getOpcode() == Instruction::Add &&
(BO->hasNoUnsignedWrap() || BO->hasNoSignedWrap()) &&
StartC->isStrictlyPositive() && !StepC->isNegative())
return true;
if (BO->getOpcode() == Instruction::Mul &&
(BO->hasNoUnsignedWrap() || BO->hasNoSignedWrap()) &&
!StartC->isNullValue() && StepC->isStrictlyPositive())
return true;
}
// Check if all incoming values are non-zero using recursion.
Query RecQ = Q;

View File

@ -77,3 +77,204 @@ exit:
%cmp = icmp eq i8 %add, 0
ret i1 %cmp
}
define i1 @test4(i8 %p, i8* %pq, i8 %n, i8 %r) {
; CHECK-LABEL: @test4(
; CHECK-NEXT: entry:
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
; CHECK-NEXT: [[A:%.*]] = phi i8 [ 0, [[ENTRY:%.*]] ], [ [[NEXT:%.*]], [[LOOP]] ]
; CHECK-NEXT: [[NEXT]] = add nuw i8 [[A]], 1
; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i8 [[A]], [[N:%.*]]
; CHECK-NEXT: br i1 [[CMP1]], label [[EXIT:%.*]], label [[LOOP]]
; CHECK: exit:
; CHECK-NEXT: [[ADD:%.*]] = or i8 [[A]], [[R:%.*]]
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[ADD]], 0
; CHECK-NEXT: ret i1 [[CMP]]
;
entry:
br label %loop
loop:
%A = phi i8 [ 0, %entry ], [ %next, %loop ]
%next = add nuw i8 %A, 1
%cmp1 = icmp eq i8 %A, %n
br i1 %cmp1, label %exit, label %loop
exit:
%add = or i8 %A, %r
%cmp = icmp eq i8 %add, 0
ret i1 %cmp
}
define i1 @test5(i8 %p, i8* %pq, i8 %n, i8 %r) {
; CHECK-LABEL: @test5(
; CHECK-NEXT: entry:
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
; CHECK-NEXT: [[A:%.*]] = phi i8 [ -2, [[ENTRY:%.*]] ], [ [[NEXT:%.*]], [[LOOP]] ]
; CHECK-NEXT: [[NEXT]] = add nuw i8 [[A]], 1
; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i8 [[A]], [[N:%.*]]
; CHECK-NEXT: br i1 [[CMP1]], label [[EXIT:%.*]], label [[LOOP]]
; CHECK: exit:
; CHECK-NEXT: [[ADD:%.*]] = or i8 [[A]], [[R:%.*]]
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[ADD]], 0
; CHECK-NEXT: ret i1 [[CMP]]
;
entry:
br label %loop
loop:
%A = phi i8 [ -2, %entry ], [ %next, %loop ]
%next = add nuw i8 %A, 1
%cmp1 = icmp eq i8 %A, %n
br i1 %cmp1, label %exit, label %loop
exit:
%add = or i8 %A, %r
%cmp = icmp eq i8 %add, 0
ret i1 %cmp
}
define i1 @test6(i8 %p, i8* %pq, i8 %n, i8 %r) {
; CHECK-LABEL: @test6(
; CHECK-NEXT: entry:
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
; CHECK-NEXT: [[A:%.*]] = phi i8 [ 2, [[ENTRY:%.*]] ], [ [[NEXT:%.*]], [[LOOP]] ]
; CHECK-NEXT: [[NEXT]] = mul nsw i8 [[A]], 2
; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i8 [[A]], [[N:%.*]]
; CHECK-NEXT: br i1 [[CMP1]], label [[EXIT:%.*]], label [[LOOP]]
; CHECK: exit:
; CHECK-NEXT: ret i1 false
;
entry:
br label %loop
loop:
%A = phi i8 [ 2, %entry ], [ %next, %loop ]
%next = mul nsw i8 %A, 2
%cmp1 = icmp eq i8 %A, %n
br i1 %cmp1, label %exit, label %loop
exit:
%cmp = icmp eq i8 %A, 0
ret i1 %cmp
}
define i1 @test7(i8 %p, i8* %pq, i8 %n, i8 %r) {
; CHECK-LABEL: @test7(
; CHECK-NEXT: entry:
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
; CHECK-NEXT: [[A:%.*]] = phi i8 [ 2, [[ENTRY:%.*]] ], [ [[NEXT:%.*]], [[LOOP]] ]
; CHECK-NEXT: [[NEXT]] = mul i8 [[A]], 2
; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i8 [[A]], [[N:%.*]]
; CHECK-NEXT: br i1 [[CMP1]], label [[EXIT:%.*]], label [[LOOP]]
; CHECK: exit:
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[A]], 0
; CHECK-NEXT: ret i1 [[CMP]]
;
entry:
br label %loop
loop:
%A = phi i8 [ 2, %entry ], [ %next, %loop ]
%next = mul i8 %A, 2
%cmp1 = icmp eq i8 %A, %n
br i1 %cmp1, label %exit, label %loop
exit:
%cmp = icmp eq i8 %A, 0
ret i1 %cmp
}
define i1 @test8(i8 %p, i8* %pq, i8 %n, i8 %r) {
; CHECK-LABEL: @test8(
; CHECK-NEXT: entry:
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
; CHECK-NEXT: [[A:%.*]] = phi i8 [ 2, [[ENTRY:%.*]] ], [ [[NEXT:%.*]], [[LOOP]] ]
; CHECK-NEXT: [[NEXT]] = mul nuw i8 [[A]], 2
; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i8 [[A]], [[N:%.*]]
; CHECK-NEXT: br i1 [[CMP1]], label [[EXIT:%.*]], label [[LOOP]]
; CHECK: exit:
; CHECK-NEXT: ret i1 false
;
entry:
br label %loop
loop:
%A = phi i8 [ 2, %entry ], [ %next, %loop ]
%next = mul nuw i8 %A, 2
%cmp1 = icmp eq i8 %A, %n
br i1 %cmp1, label %exit, label %loop
exit:
%cmp = icmp eq i8 %A, 0
ret i1 %cmp
}
define i1 @test9(i8 %p, i8* %pq, i8 %n, i8 %r) {
; CHECK-LABEL: @test9(
; CHECK-NEXT: entry:
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
; CHECK-NEXT: [[A:%.*]] = phi i8 [ 0, [[ENTRY:%.*]] ], [ [[NEXT:%.*]], [[LOOP]] ]
; CHECK-NEXT: [[NEXT]] = mul nuw i8 [[A]], 2
; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i8 [[A]], [[N:%.*]]
; CHECK-NEXT: br i1 [[CMP1]], label [[EXIT:%.*]], label [[LOOP]]
; CHECK: exit:
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[A]], 0
; CHECK-NEXT: ret i1 [[CMP]]
;
entry:
br label %loop
loop:
%A = phi i8 [ 0, %entry ], [ %next, %loop ]
%next = mul nuw i8 %A, 2
%cmp1 = icmp eq i8 %A, %n
br i1 %cmp1, label %exit, label %loop
exit:
%cmp = icmp eq i8 %A, 0
ret i1 %cmp
}
define i1 @test10(i8 %p, i8* %pq, i8 %n, i8 %r) {
; CHECK-LABEL: @test10(
; CHECK-NEXT: entry:
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
; CHECK-NEXT: [[A:%.*]] = phi i8 [ 2, [[ENTRY:%.*]] ], [ [[NEXT:%.*]], [[LOOP]] ]
; CHECK-NEXT: [[NEXT]] = mul nuw i8 [[A]], -2
; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i8 [[A]], [[N:%.*]]
; CHECK-NEXT: br i1 [[CMP1]], label [[EXIT:%.*]], label [[LOOP]]
; CHECK: exit:
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[A]], 0
; CHECK-NEXT: ret i1 [[CMP]]
;
entry:
br label %loop
loop:
%A = phi i8 [ 2, %entry ], [ %next, %loop ]
%next = mul nuw i8 %A, -2
%cmp1 = icmp eq i8 %A, %n
br i1 %cmp1, label %exit, label %loop
exit:
%cmp = icmp eq i8 %A, 0
ret i1 %cmp
}
define i1 @test11(i8 %p, i8* %pq, i8 %n, i8 %r) {
; CHECK-LABEL: @test11(
; CHECK-NEXT: entry:
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
; CHECK-NEXT: [[A:%.*]] = phi i8 [ -2, [[ENTRY:%.*]] ], [ [[NEXT:%.*]], [[LOOP]] ]
; CHECK-NEXT: [[NEXT]] = mul nuw i8 [[A]], 2
; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i8 [[A]], [[N:%.*]]
; CHECK-NEXT: br i1 [[CMP1]], label [[EXIT:%.*]], label [[LOOP]]
; CHECK: exit:
; CHECK-NEXT: ret i1 false
;
entry:
br label %loop
loop:
%A = phi i8 [ -2, %entry ], [ %next, %loop ]
%next = mul nuw i8 %A, 2
%cmp1 = icmp eq i8 %A, %n
br i1 %cmp1, label %exit, label %loop
exit:
%cmp = icmp eq i8 %A, 0
ret i1 %cmp
}