[llvm] 2e2740b - [ValueTracking] Handle increasing mul recurrence in isKnownNonZero()
Jingu Kang via llvm-commits
llvm-commits at lists.llvm.org
Tue Mar 23 16:06:46 PDT 2021
Author: Jingu Kang
Date: 2021-03-23T23:04:41Z
New Revision: 2e2740b859cfe28cc8410df043a37f81def677a3
URL: https://github.com/llvm/llvm-project/commit/2e2740b859cfe28cc8410df043a37f81def677a3
DIFF: https://github.com/llvm/llvm-project/commit/2e2740b859cfe28cc8410df043a37f81def677a3.diff
LOG: [ValueTracking] Handle increasing mul recurrence in isKnownNonZero()
Differential Revision: https://reviews.llvm.org/D99069
Added:
Modified:
llvm/lib/Analysis/ValueTracking.cpp
llvm/test/Analysis/ValueTracking/monotonic-phi.ll
Removed:
################################################################################
diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index c0f41c7caa3e9..798450056d12e 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -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;
diff --git a/llvm/test/Analysis/ValueTracking/monotonic-phi.ll b/llvm/test/Analysis/ValueTracking/monotonic-phi.ll
index 0af4addf97e8d..d0c8f403ed95f 100644
--- a/llvm/test/Analysis/ValueTracking/monotonic-phi.ll
+++ b/llvm/test/Analysis/ValueTracking/monotonic-phi.ll
@@ -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
+}
More information about the llvm-commits
mailing list