diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp --- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp @@ -6851,8 +6851,8 @@ return new FCmpInst(Pred, LHSI->getOperand(1), RHSC, "", &I); } -/// Optimize fabs(X) compared with zero. -static Instruction *foldFabsWithFcmpZero(FCmpInst &I, InstCombinerImpl &IC) { +/// Optimize fabs(X) compared with zero or infinities. +static Instruction *foldFabsWithFcmp(FCmpInst &I, InstCombinerImpl &IC) { Value *X; if (!match(I.getOperand(0), m_FAbs(m_Value(X)))) return nullptr; @@ -6861,6 +6861,12 @@ if (!match(I.getOperand(1), m_APFloat(C))) return nullptr; + if (C->isPosInfinity() && I.getPredicate() == CmpInst::FCMP_OEQ) + return CallInst::Create( + Intrinsic::getDeclaration(I.getModule(), Intrinsic::is_fpclass, + X->getType()), + {X, ConstantInt::get(Type::getInt32Ty(I.getContext()), fcInf)}); + if (!C->isPosZero()) { if (!C->isSmallestNormalized()) return nullptr; @@ -7104,7 +7110,7 @@ } } - if (Instruction *R = foldFabsWithFcmpZero(I, *this)) + if (Instruction *R = foldFabsWithFcmp(I, *this)) return R; if (match(Op0, m_FNeg(m_Value(X)))) { diff --git a/llvm/test/Transforms/InstCombine/and-fcmp.ll b/llvm/test/Transforms/InstCombine/and-fcmp.ll --- a/llvm/test/Transforms/InstCombine/and-fcmp.ll +++ b/llvm/test/Transforms/InstCombine/and-fcmp.ll @@ -4742,8 +4742,7 @@ ; ueq -> oeq define i1 @clang_builtin_isnormal_inf_check_ueq(half %x) { ; CHECK-LABEL: @clang_builtin_isnormal_inf_check_ueq( -; CHECK-NEXT: [[FABS_X:%.*]] = call half @llvm.fabs.f16(half [[X:%.*]]) -; CHECK-NEXT: [[TMP1:%.*]] = fcmp oeq half [[FABS_X]], 0xH7C00 +; CHECK-NEXT: [[TMP1:%.*]] = call i1 @llvm.is.fpclass.f16(half [[X:%.*]], i32 516) ; CHECK-NEXT: ret i1 [[TMP1]] ; %fabs.x = call half @llvm.fabs.f16(half %x) @@ -4839,11 +4838,8 @@ define i1 @clang_builtin_isnormal_inf_check_oeq(half %x) { ; CHECK-LABEL: @clang_builtin_isnormal_inf_check_oeq( -; CHECK-NEXT: [[FABS_X:%.*]] = call half @llvm.fabs.f16(half [[X:%.*]]) -; CHECK-NEXT: [[ORD:%.*]] = fcmp ord half [[X]], 0xH0000 -; CHECK-NEXT: [[CMP:%.*]] = fcmp oeq half [[FABS_X]], 0xH7C00 -; CHECK-NEXT: [[AND:%.*]] = and i1 [[ORD]], [[CMP]] -; CHECK-NEXT: ret i1 [[AND]] +; CHECK-NEXT: [[CMP:%.*]] = call i1 @llvm.is.fpclass.f16(half [[X:%.*]], i32 516) +; CHECK-NEXT: ret i1 [[CMP]] ; %fabs.x = call half @llvm.fabs.f16(half %x) %ord = fcmp ord half %fabs.x, 0.0 diff --git a/llvm/test/Transforms/InstCombine/create-class-from-logic-fcmp.ll b/llvm/test/Transforms/InstCombine/create-class-from-logic-fcmp.ll --- a/llvm/test/Transforms/InstCombine/create-class-from-logic-fcmp.ll +++ b/llvm/test/Transforms/InstCombine/create-class-from-logic-fcmp.ll @@ -121,8 +121,7 @@ ; Positive test define i1 @oeq_isinf_or_oeq_zero(half %x) { ; CHECK-LABEL: @oeq_isinf_or_oeq_zero( -; CHECK-NEXT: [[FABS:%.*]] = call half @llvm.fabs.f16(half [[X:%.*]]) -; CHECK-NEXT: [[CMPINF:%.*]] = fcmp oeq half [[FABS]], 0xH7C00 +; CHECK-NEXT: [[CMPINF:%.*]] = call i1 @llvm.is.fpclass.f16(half [[X:%.*]], i32 516) ; CHECK-NEXT: [[CMPZERO:%.*]] = fcmp oeq half [[X]], 0xH0000 ; CHECK-NEXT: [[CLASS:%.*]] = or i1 [[CMPZERO]], [[CMPINF]] ; CHECK-NEXT: ret i1 [[CLASS]] @@ -151,8 +150,7 @@ ; Extra fabs. define i1 @oeq_isinf_or_fabs_oeq_zero(half %x) { ; CHECK-LABEL: @oeq_isinf_or_fabs_oeq_zero( -; CHECK-NEXT: [[FABS:%.*]] = call half @llvm.fabs.f16(half [[X:%.*]]) -; CHECK-NEXT: [[CMPINF:%.*]] = fcmp oeq half [[FABS]], 0xH7C00 +; CHECK-NEXT: [[CMPINF:%.*]] = call i1 @llvm.is.fpclass.f16(half [[X:%.*]], i32 516) ; CHECK-NEXT: [[CMPZERO:%.*]] = fcmp oeq half [[X]], 0xH0000 ; CHECK-NEXT: [[CLASS:%.*]] = or i1 [[CMPZERO]], [[CMPINF]] ; CHECK-NEXT: ret i1 [[CLASS]] @@ -616,11 +614,8 @@ define i1 @issubnormal_or_inf(half %x) { ; CHECK-LABEL: @issubnormal_or_inf( -; CHECK-NEXT: [[FABS:%.*]] = call half @llvm.fabs.f16(half [[X:%.*]]) -; CHECK-NEXT: [[CMPINF:%.*]] = fcmp oeq half [[FABS]], 0xH7C00 -; CHECK-NEXT: [[CMP_SMALLEST_NORMAL:%.*]] = fcmp olt half [[FABS]], 0xH0400 -; CHECK-NEXT: [[CLASS:%.*]] = or i1 [[CMP_SMALLEST_NORMAL]], [[CMPINF]] -; CHECK-NEXT: ret i1 [[CLASS]] +; CHECK-NEXT: [[CMPINF:%.*]] = call i1 @llvm.is.fpclass.f16(half [[X:%.*]], i32 756) +; CHECK-NEXT: ret i1 [[CMPINF]] ; %fabs = call half @llvm.fabs.f16(half %x) %cmpinf = fcmp oeq half %fabs, 0xH7C00 @@ -631,11 +626,8 @@ define i1 @olt_smallest_normal_or_inf(half %x) { ; CHECK-LABEL: @olt_smallest_normal_or_inf( -; CHECK-NEXT: [[FABS:%.*]] = call half @llvm.fabs.f16(half [[X:%.*]]) -; CHECK-NEXT: [[CMPINF:%.*]] = fcmp oeq half [[FABS]], 0xH7C00 -; CHECK-NEXT: [[CMP_SMALLEST_NORMAL:%.*]] = fcmp olt half [[X]], 0xH0400 -; CHECK-NEXT: [[CLASS:%.*]] = or i1 [[CMP_SMALLEST_NORMAL]], [[CMPINF]] -; CHECK-NEXT: ret i1 [[CLASS]] +; CHECK-NEXT: [[CMPINF:%.*]] = call i1 @llvm.is.fpclass.f16(half [[X:%.*]], i32 764) +; CHECK-NEXT: ret i1 [[CMPINF]] ; %fabs = call half @llvm.fabs.f16(half %x) %cmpinf = fcmp oeq half %fabs, 0xH7C00 @@ -661,11 +653,8 @@ define i1 @issubnormal_uge_or_inf(half %x) { ; CHECK-LABEL: @issubnormal_uge_or_inf( -; CHECK-NEXT: [[FABS:%.*]] = call half @llvm.fabs.f16(half [[X:%.*]]) -; CHECK-NEXT: [[CMPINF:%.*]] = fcmp oeq half [[FABS]], 0xH7C00 -; CHECK-NEXT: [[CMP_SMALLEST_NORMAL:%.*]] = fcmp uge half [[FABS]], 0xH0400 -; CHECK-NEXT: [[CLASS:%.*]] = or i1 [[CMP_SMALLEST_NORMAL]], [[CMPINF]] -; CHECK-NEXT: ret i1 [[CLASS]] +; CHECK-NEXT: [[CMPINF:%.*]] = call i1 @llvm.is.fpclass.f16(half [[X:%.*]], i32 783) +; CHECK-NEXT: ret i1 [[CMPINF]] ; %fabs = call half @llvm.fabs.f16(half %x) %cmpinf = fcmp oeq half %fabs, 0xH7C00 @@ -678,7 +667,7 @@ define i1 @issubnormal_or_inf_wrong_val(half %x) { ; CHECK-LABEL: @issubnormal_or_inf_wrong_val( ; CHECK-NEXT: [[FABS:%.*]] = call half @llvm.fabs.f16(half [[X:%.*]]) -; CHECK-NEXT: [[CMPINF:%.*]] = fcmp oeq half [[FABS]], 0xH7C00 +; CHECK-NEXT: [[CMPINF:%.*]] = call i1 @llvm.is.fpclass.f16(half [[X]], i32 516) ; CHECK-NEXT: [[CMP_SMALLEST_NORMAL:%.*]] = fcmp olt half [[FABS]], 0xH0401 ; CHECK-NEXT: [[CLASS:%.*]] = or i1 [[CMP_SMALLEST_NORMAL]], [[CMPINF]] ; CHECK-NEXT: ret i1 [[CLASS]] @@ -692,8 +681,7 @@ define i1 @issubnormal_or_inf_neg_smallest_normal(half %x) { ; CHECK-LABEL: @issubnormal_or_inf_neg_smallest_normal( -; CHECK-NEXT: [[FABS:%.*]] = call half @llvm.fabs.f16(half [[X:%.*]]) -; CHECK-NEXT: [[CMPINF:%.*]] = fcmp oeq half [[FABS]], 0xH7C00 +; CHECK-NEXT: [[CMPINF:%.*]] = call i1 @llvm.is.fpclass.f16(half [[X:%.*]], i32 516) ; CHECK-NEXT: ret i1 [[CMPINF]] ; %fabs = call half @llvm.fabs.f16(half %x) @@ -706,7 +694,7 @@ define i1 @fneg_fabs_olt_neg_smallest_normal_or_inf(half %x) { ; CHECK-LABEL: @fneg_fabs_olt_neg_smallest_normal_or_inf( ; CHECK-NEXT: [[FABS:%.*]] = call half @llvm.fabs.f16(half [[X:%.*]]) -; CHECK-NEXT: [[CMPINF:%.*]] = fcmp oeq half [[FABS]], 0xH7C00 +; CHECK-NEXT: [[CMPINF:%.*]] = call i1 @llvm.is.fpclass.f16(half [[X]], i32 516) ; CHECK-NEXT: [[CMP_SMALLEST_NORMAL:%.*]] = fcmp ogt half [[FABS]], 0xH0400 ; CHECK-NEXT: [[CLASS:%.*]] = or i1 [[CMP_SMALLEST_NORMAL]], [[CMPINF]] ; CHECK-NEXT: ret i1 [[CLASS]] @@ -801,9 +789,8 @@ define i1 @is_finite_and_ord(half %x) { ; CHECK-LABEL: @is_finite_and_ord( -; CHECK-NEXT: [[FABS:%.*]] = call half @llvm.fabs.f16(half [[X:%.*]]) -; CHECK-NEXT: [[TMP1:%.*]] = fcmp oeq half [[FABS]], 0xH7C00 -; CHECK-NEXT: ret i1 [[TMP1]] +; CHECK-NEXT: [[AND:%.*]] = call i1 @llvm.is.fpclass.f16(half [[X:%.*]], i32 516) +; CHECK-NEXT: ret i1 [[AND]] ; %fabs = call half @llvm.fabs.f16(half %x) %is.finite = fcmp ueq half %fabs, 0xH7C00 @@ -859,11 +846,8 @@ define i1 @oeq_isinf_or_uno(half %x) { ; CHECK-LABEL: @oeq_isinf_or_uno( -; CHECK-NEXT: [[FABS:%.*]] = call half @llvm.fabs.f16(half [[X:%.*]]) -; CHECK-NEXT: [[CMPINF:%.*]] = fcmp oeq half [[FABS]], 0xH7C00 -; CHECK-NEXT: [[UNO:%.*]] = fcmp uno half [[X]], 0xH0000 -; CHECK-NEXT: [[CLASS:%.*]] = or i1 [[CMPINF]], [[UNO]] -; CHECK-NEXT: ret i1 [[CLASS]] +; CHECK-NEXT: [[CMPINF:%.*]] = call i1 @llvm.is.fpclass.f16(half [[X:%.*]], i32 519) +; CHECK-NEXT: ret i1 [[CMPINF]] ; %fabs = call half @llvm.fabs.f16(half %x) %cmpinf = fcmp oeq half %fabs, 0xH7C00 @@ -874,11 +858,8 @@ define i1 @oeq_isinf_or_ord(half %x) { ; CHECK-LABEL: @oeq_isinf_or_ord( -; CHECK-NEXT: [[FABS:%.*]] = call half @llvm.fabs.f16(half [[X:%.*]]) -; CHECK-NEXT: [[CMPINF:%.*]] = fcmp oeq half [[FABS]], 0xH7C00 -; CHECK-NEXT: [[UNO:%.*]] = fcmp ord half [[X]], 0xH0000 -; CHECK-NEXT: [[CLASS:%.*]] = or i1 [[CMPINF]], [[UNO]] -; CHECK-NEXT: ret i1 [[CLASS]] +; CHECK-NEXT: [[CMPINF:%.*]] = fcmp ord half [[X:%.*]], 0xH0000 +; CHECK-NEXT: ret i1 [[CMPINF]] ; %fabs = call half @llvm.fabs.f16(half %x) %cmpinf = fcmp oeq half %fabs, 0xH7C00 @@ -889,11 +870,7 @@ define i1 @oeq_isinf_and_uno(half %x) { ; CHECK-LABEL: @oeq_isinf_and_uno( -; CHECK-NEXT: [[FABS:%.*]] = call half @llvm.fabs.f16(half [[X:%.*]]) -; CHECK-NEXT: [[CMPINF:%.*]] = fcmp oeq half [[FABS]], 0xH7C00 -; CHECK-NEXT: [[UNO:%.*]] = fcmp uno half [[X]], 0xH0000 -; CHECK-NEXT: [[AND:%.*]] = and i1 [[CMPINF]], [[UNO]] -; CHECK-NEXT: ret i1 [[AND]] +; CHECK-NEXT: ret i1 false ; %fabs = call half @llvm.fabs.f16(half %x) %cmpinf = fcmp oeq half %fabs, 0xH7C00 @@ -904,11 +881,8 @@ define i1 @oeq_isinf_and_ord(half %x) { ; CHECK-LABEL: @oeq_isinf_and_ord( -; CHECK-NEXT: [[FABS:%.*]] = call half @llvm.fabs.f16(half [[X:%.*]]) -; CHECK-NEXT: [[CMPINF:%.*]] = fcmp oeq half [[FABS]], 0xH7C00 -; CHECK-NEXT: [[UNO:%.*]] = fcmp ord half [[X]], 0xH0000 -; CHECK-NEXT: [[AND:%.*]] = and i1 [[CMPINF]], [[UNO]] -; CHECK-NEXT: ret i1 [[AND]] +; CHECK-NEXT: [[CMPINF:%.*]] = call i1 @llvm.is.fpclass.f16(half [[X:%.*]], i32 516) +; CHECK-NEXT: ret i1 [[CMPINF]] ; %fabs = call half @llvm.fabs.f16(half %x) %cmpinf = fcmp oeq half %fabs, 0xH7C00 @@ -1015,11 +989,8 @@ ; -> normal | inf define i1 @isnormalinf_or_inf(half %x) #0 { ; CHECK-LABEL: @isnormalinf_or_inf( -; CHECK-NEXT: [[FABS:%.*]] = call half @llvm.fabs.f16(half [[X:%.*]]) -; CHECK-NEXT: [[IS_NORMAL_INF:%.*]] = fcmp oge half [[FABS]], 0xH0400 -; CHECK-NEXT: [[IS_INF:%.*]] = fcmp oeq half [[FABS]], 0xH7C00 -; CHECK-NEXT: [[OR:%.*]] = or i1 [[IS_NORMAL_INF]], [[IS_INF]] -; CHECK-NEXT: ret i1 [[OR]] +; CHECK-NEXT: [[IS_INF:%.*]] = call i1 @llvm.is.fpclass.f16(half [[X:%.*]], i32 780) +; CHECK-NEXT: ret i1 [[IS_INF]] ; %fabs = call half @llvm.fabs.f16(half %x) %is.normal.inf = fcmp oge half %fabs, 0xH0400 @@ -1031,11 +1002,8 @@ ; -> pinf | pnormal define i1 @posisnormalinf_or_posinf(half %x) #0 { ; CHECK-LABEL: @posisnormalinf_or_posinf( -; CHECK-NEXT: [[FABS:%.*]] = call half @llvm.fabs.f16(half [[X:%.*]]) -; CHECK-NEXT: [[IS_POS_NORMAL_INF:%.*]] = fcmp oge half [[X]], 0xH0400 -; CHECK-NEXT: [[IS_INF:%.*]] = fcmp oeq half [[FABS]], 0xH7C00 -; CHECK-NEXT: [[OR:%.*]] = or i1 [[IS_POS_NORMAL_INF]], [[IS_INF]] -; CHECK-NEXT: ret i1 [[OR]] +; CHECK-NEXT: [[IS_INF:%.*]] = call i1 @llvm.is.fpclass.f16(half [[X:%.*]], i32 772) +; CHECK-NEXT: ret i1 [[IS_INF]] ; %fabs = call half @llvm.fabs.f16(half %x) %is.pos.normal.inf = fcmp oge half %x, 0xH0400 @@ -1063,11 +1031,8 @@ ; -> pinf|ninf define i1 @isnormalinf_and_inf(half %x) #0 { ; CHECK-LABEL: @isnormalinf_and_inf( -; CHECK-NEXT: [[FABS:%.*]] = call half @llvm.fabs.f16(half [[X:%.*]]) -; CHECK-NEXT: [[IS_NORMAL_INF:%.*]] = fcmp oge half [[FABS]], 0xH0400 -; CHECK-NEXT: [[IS_INF:%.*]] = fcmp oeq half [[FABS]], 0xH7C00 -; CHECK-NEXT: [[AND:%.*]] = and i1 [[IS_NORMAL_INF]], [[IS_INF]] -; CHECK-NEXT: ret i1 [[AND]] +; CHECK-NEXT: [[IS_INF:%.*]] = call i1 @llvm.is.fpclass.f16(half [[X:%.*]], i32 516) +; CHECK-NEXT: ret i1 [[IS_INF]] ; %fabs = call half @llvm.fabs.f16(half %x) %is.normal.inf = fcmp oge half %fabs, 0xH0400 @@ -1079,11 +1044,8 @@ ; -> pinf define i1 @posisnormalinf_and_posinf(half %x) #0 { ; CHECK-LABEL: @posisnormalinf_and_posinf( -; CHECK-NEXT: [[FABS:%.*]] = call half @llvm.fabs.f16(half [[X:%.*]]) -; CHECK-NEXT: [[IS_POS_NORMAL_INF:%.*]] = fcmp oge half [[X]], 0xH0400 -; CHECK-NEXT: [[IS_INF:%.*]] = fcmp oeq half [[FABS]], 0xH7C00 -; CHECK-NEXT: [[AND:%.*]] = and i1 [[IS_POS_NORMAL_INF]], [[IS_INF]] -; CHECK-NEXT: ret i1 [[AND]] +; CHECK-NEXT: [[IS_INF:%.*]] = call i1 @llvm.is.fpclass.f16(half [[X:%.*]], i32 512) +; CHECK-NEXT: ret i1 [[IS_INF]] ; %fabs = call half @llvm.fabs.f16(half %x) %is.pos.normal.inf = fcmp oge half %x, 0xH0400 @@ -1195,11 +1157,8 @@ ; -> ~pnormal define i1 @not_negisnormalinf_or_inf(half %x) #0 { ; CHECK-LABEL: @not_negisnormalinf_or_inf( -; CHECK-NEXT: [[FABS:%.*]] = call half @llvm.fabs.f16(half [[X:%.*]]) -; CHECK-NEXT: [[NOT_IS_NEG_NORMAL_INF:%.*]] = fcmp ult half [[X]], 0xH0400 -; CHECK-NEXT: [[IS_INF:%.*]] = fcmp oeq half [[FABS]], 0xH7C00 -; CHECK-NEXT: [[OR:%.*]] = or i1 [[NOT_IS_NEG_NORMAL_INF]], [[IS_INF]] -; CHECK-NEXT: ret i1 [[OR]] +; CHECK-NEXT: [[IS_INF:%.*]] = call i1 @llvm.is.fpclass.f16(half [[X:%.*]], i32 767) +; CHECK-NEXT: ret i1 [[IS_INF]] ; %fabs = call half @llvm.fabs.f16(half %x) %not.is.neg.normal.inf = fcmp ult half %x, 0xH0400