diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp index 56eb3f99b39d2..39872e022f42e 100644 --- a/llvm/lib/Analysis/ValueTracking.cpp +++ b/llvm/lib/Analysis/ValueTracking.cpp @@ -2697,11 +2697,6 @@ static bool isNonZeroSub(const APInt &DemandedElts, unsigned Depth, if (matchOpWithOpEqZero(X, Y)) return true; - // TODO: Move this case into isKnownNonEqual(). - if (auto *C = dyn_cast(X)) - if (C->isNullValue() && isKnownNonZero(Y, DemandedElts, Q, Depth)) - return true; - return ::isKnownNonEqual(X, Y, DemandedElts, Depth, Q); } @@ -3537,25 +3532,17 @@ static bool isNonEqualPHIs(const PHINode *PN1, const PHINode *PN2, return false; SmallPtrSet VisitedBBs; - bool UsedFullRecursion = false; for (const BasicBlock *IncomBB : PN1->blocks()) { if (!VisitedBBs.insert(IncomBB).second) continue; // Don't reprocess blocks that we have dealt with already. const Value *IV1 = PN1->getIncomingValueForBlock(IncomBB); const Value *IV2 = PN2->getIncomingValueForBlock(IncomBB); - const APInt *C1, *C2; - if (match(IV1, m_APInt(C1)) && match(IV2, m_APInt(C2)) && *C1 != *C2) - continue; - - // Only one pair of phi operands is allowed for full recursion. - if (UsedFullRecursion) - return false; - + const unsigned PhiRecursionLimit = + std::max(Depth + 1, MaxAnalysisRecursionDepth - 2); SimplifyQuery RecQ = Q.getWithoutCondContext(); RecQ.CxtI = IncomBB->getTerminator(); - if (!isKnownNonEqual(IV1, IV2, DemandedElts, Depth + 1, RecQ)) + if (!isKnownNonEqual(IV1, IV2, DemandedElts, PhiRecursionLimit, RecQ)) return false; - UsedFullRecursion = true; } return true; } @@ -3642,6 +3629,12 @@ static bool isKnownNonEqual(const Value *V1, const Value *V2, // We can't look through casts yet. return false; + if (isa(V2)) + std::swap(V1, V2); + if (auto *C = dyn_cast(V1)) + if (C->isNullValue() && isKnownNonZero(V2, DemandedElts, Q, Depth)) + return true; + if (Depth >= MaxAnalysisRecursionDepth) return false; diff --git a/llvm/test/Analysis/ValueTracking/known-non-equal.ll b/llvm/test/Analysis/ValueTracking/known-non-equal.ll index d67f1b5662147..c669613afbabf 100644 --- a/llvm/test/Analysis/ValueTracking/known-non-equal.ll +++ b/llvm/test/Analysis/ValueTracking/known-non-equal.ll @@ -316,6 +316,82 @@ exit: ret i1 %cmp } +define i1 @known_non_equal_phis2(i8 %p, i8 %n) { +; CHECK-LABEL: @known_non_equal_phis2( +; CHECK-NEXT: entry: +; CHECK-NEXT: br label [[LOOP:%.*]] +; CHECK: loop: +; CHECK-NEXT: [[A:%.*]] = phi i8 [ 0, [[ENTRY:%.*]] ], [ [[NEXT:%.*]], [[LOOP]] ] +; CHECK-NEXT: [[NEXT]] = add 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 true +; +entry: + %known.nonzero = add nuw i8 %p, 1 + br label %loop +loop: + %A = phi i8 [ 0, %entry ], [ %next, %loop ] + %B = phi i8 [ %known.nonzero, %entry ], [ %A, %loop ] + %next = add nsw i8 %A, 2 + %cmp1 = icmp eq i8 %A, %n + br i1 %cmp1, label %exit, label %loop +exit: + %cmp = icmp ne i8 %A, %B + ret i1 %cmp +} + +define i1 @phi_max_recursion_limit(i1 %cond, i32 %switch.cond) { +; CHECK-LABEL: @phi_max_recursion_limit( +; CHECK-NEXT: entry: +; CHECK-NEXT: br label [[BB0:%.*]] +; CHECK: bb0: +; CHECK-NEXT: [[PHIA_0:%.*]] = phi i32 [ [[PHIA_1:%.*]], [[BB1:%.*]] ], [ 0, [[ENTRY:%.*]] ] +; CHECK-NEXT: [[PHIB_0:%.*]] = phi i32 [ [[PHIB_1:%.*]], [[BB1]] ], [ 0, [[ENTRY]] ] +; CHECK-NEXT: br i1 [[COND:%.*]], label [[SWITCH_BLOCK:%.*]], label [[EXIT:%.*]] +; CHECK: switch.block: +; CHECK-NEXT: switch i32 [[SWITCH_COND:%.*]], label [[BB1]] [ +; CHECK-NEXT: i32 0, label [[EPILOGUE:%.*]] +; CHECK-NEXT: i32 1, label [[EPILOGUE]] +; CHECK-NEXT: ] +; CHECK: bb1: +; CHECK-NEXT: [[PHIA_1]] = phi i32 [ [[PHIA_0]], [[SWITCH_BLOCK]] ], [ 0, [[EPILOGUE]] ] +; CHECK-NEXT: [[PHIB_1]] = phi i32 [ [[PHIB_0]], [[SWITCH_BLOCK]] ], [ 0, [[EPILOGUE]] ] +; CHECK-NEXT: br label [[BB0]] +; CHECK: epilogue: +; CHECK-NEXT: br label [[BB1]] +; CHECK: exit: +; CHECK-NEXT: [[RET:%.*]] = icmp eq i32 [[PHIA_0]], [[PHIB_0]] +; CHECK-NEXT: ret i1 [[RET]] +; +entry: + br label %bb0 + +bb0: + %phiA.0 = phi i32 [ %phiA.1, %bb1 ], [ 0, %entry ] + %phiB.0 = phi i32 [ %phiB.1, %bb1 ], [ 0, %entry ] + br i1 %cond, label %switch.block, label %exit + +switch.block: + switch i32 %switch.cond, label %bb1 [ + i32 0, label %epilogue + i32 1, label %epilogue + ] + +bb1: + %phiA.1 = phi i32 [ %phiA.0, %switch.block ], [ 0, %epilogue ] + %phiB.1 = phi i32 [ %phiB.0, %switch.block ], [ 0, %epilogue ] + br label %bb0 + +epilogue: + br label %bb1 + +exit: + %ret = icmp eq i32 %phiA.0, %phiB.0 + ret i1 %ret +} + define i1 @known_non_equal_phis_fail(i8 %p, ptr %pq, i8 %n, i8 %r) { ; CHECK-LABEL: @known_non_equal_phis_fail( ; CHECK-NEXT: entry: