diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp index c48068afc0481..d924a26a7cf5c 100644 --- a/llvm/lib/Analysis/ValueTracking.cpp +++ b/llvm/lib/Analysis/ValueTracking.cpp @@ -4882,9 +4882,19 @@ llvm::fcmpImpliesClass(CmpInst::Predicate Pred, const Function &F, Value *LHS, } static void computeKnownFPClassFromCond(const Value *V, Value *Cond, - bool CondIsTrue, + unsigned Depth, bool CondIsTrue, const Instruction *CxtI, KnownFPClass &KnownFromContext) { + Value *A, *B; + if (Depth < MaxAnalysisRecursionDepth && + (CondIsTrue ? match(Cond, m_LogicalAnd(m_Value(A), m_Value(B))) + : match(Cond, m_LogicalOr(m_Value(A), m_Value(B))))) { + computeKnownFPClassFromCond(V, A, Depth + 1, CondIsTrue, CxtI, + KnownFromContext); + computeKnownFPClassFromCond(V, B, Depth + 1, CondIsTrue, CxtI, + KnownFromContext); + return; + } CmpInst::Predicate Pred; Value *LHS; uint64_t ClassVal = 0; @@ -4925,13 +4935,13 @@ static KnownFPClass computeKnownFPClassFromContext(const Value *V, BasicBlockEdge Edge0(BI->getParent(), BI->getSuccessor(0)); if (Q.DT->dominates(Edge0, Q.CxtI->getParent())) - computeKnownFPClassFromCond(V, Cond, /*CondIsTrue=*/true, Q.CxtI, - KnownFromContext); + computeKnownFPClassFromCond(V, Cond, /*Depth=*/0, /*CondIsTrue=*/true, + Q.CxtI, KnownFromContext); BasicBlockEdge Edge1(BI->getParent(), BI->getSuccessor(1)); if (Q.DT->dominates(Edge1, Q.CxtI->getParent())) - computeKnownFPClassFromCond(V, Cond, /*CondIsTrue=*/false, Q.CxtI, - KnownFromContext); + computeKnownFPClassFromCond(V, Cond, /*Depth=*/0, /*CondIsTrue=*/false, + Q.CxtI, KnownFromContext); } } @@ -4953,8 +4963,8 @@ static KnownFPClass computeKnownFPClassFromContext(const Value *V, if (!isValidAssumeForContext(I, Q.CxtI, Q.DT)) continue; - computeKnownFPClassFromCond(V, I->getArgOperand(0), /*CondIsTrue=*/true, - Q.CxtI, KnownFromContext); + computeKnownFPClassFromCond(V, I->getArgOperand(0), /*Depth=*/0, + /*CondIsTrue=*/true, Q.CxtI, KnownFromContext); } return KnownFromContext; @@ -10090,7 +10100,7 @@ void llvm::findValuesAffectedByCondition( if (HasRHSC && match(A, m_Intrinsic(m_Value(X)))) AddAffected(X); - } else if (match(Cond, m_FCmp(Pred, m_Value(A), m_Value(B)))) { + } else if (match(V, m_FCmp(Pred, m_Value(A), m_Value(B)))) { AddCmpOperands(A, B); // fcmp fneg(x), y diff --git a/llvm/test/Transforms/InstCombine/fpclass-from-dom-cond.ll b/llvm/test/Transforms/InstCombine/fpclass-from-dom-cond.ll index d6706d76056ee..141b44cbbb7a1 100644 --- a/llvm/test/Transforms/InstCombine/fpclass-from-dom-cond.ll +++ b/llvm/test/Transforms/InstCombine/fpclass-from-dom-cond.ll @@ -46,6 +46,31 @@ if.end: ret i1 %cmp.i } +define i1 @test2_or(double %x, i1 %cond) { +; CHECK-LABEL: define i1 @test2_or( +; CHECK-SAME: double [[X:%.*]], i1 [[COND:%.*]]) { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[CMP:%.*]] = fcmp olt double [[X]], 0x3EB0C6F7A0000000 +; CHECK-NEXT: [[OR:%.*]] = or i1 [[CMP]], [[COND]] +; CHECK-NEXT: br i1 [[OR]], label [[IF_THEN:%.*]], label [[IF_END:%.*]] +; CHECK: if.then: +; CHECK-NEXT: ret i1 false +; CHECK: if.end: +; CHECK-NEXT: ret i1 false +; +entry: + %cmp = fcmp olt double %x, 0x3EB0C6F7A0000000 + %or = or i1 %cmp, %cond + br i1 %or, label %if.then, label %if.end + +if.then: + ret i1 false + +if.end: + %cmp.i = fcmp oeq double %x, 0.000000e+00 + ret i1 %cmp.i +} + define i1 @test3(float %x) { ; CHECK-LABEL: define i1 @test3( ; CHECK-SAME: float [[X:%.*]]) { @@ -240,7 +265,6 @@ if.else: ret i1 false } -; TODO: handle and/or conditions define i1 @test11_and(float %x, i1 %cond2) { ; CHECK-LABEL: define i1 @test11_and( ; CHECK-SAME: float [[X:%.*]], i1 [[COND2:%.*]]) { @@ -248,8 +272,7 @@ define i1 @test11_and(float %x, i1 %cond2) { ; CHECK-NEXT: [[AND:%.*]] = and i1 [[COND]], [[COND2]] ; CHECK-NEXT: br i1 [[AND]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] ; CHECK: if.then: -; CHECK-NEXT: [[RET1:%.*]] = fcmp oeq float [[X]], 0x7FF0000000000000 -; CHECK-NEXT: ret i1 [[RET1]] +; CHECK-NEXT: ret i1 false ; CHECK: if.else: ; CHECK-NEXT: ret i1 false ; @@ -264,7 +287,6 @@ if.else: ret i1 false } -; TODO: handle and/or conditions define i1 @test12_or(float %x, i1 %cond2) { ; CHECK-LABEL: define i1 @test12_or( ; CHECK-SAME: float [[X:%.*]], i1 [[COND2:%.*]]) { @@ -275,7 +297,7 @@ define i1 @test12_or(float %x, i1 %cond2) { ; CHECK: if.then: ; CHECK-NEXT: ret i1 false ; CHECK: if.else: -; CHECK-NEXT: [[RET:%.*]] = call i1 @llvm.is.fpclass.f32(float [[X]], i32 783) +; CHECK-NEXT: [[RET:%.*]] = call i1 @llvm.is.fpclass.f32(float [[X]], i32 780) ; CHECK-NEXT: ret i1 [[RET]] ; entry: