From ae8f280427851c9b99fd4436daa4c6eead54f7e5 Mon Sep 17 00:00:00 2001 From: Yingwei Zheng Date: Wed, 7 Feb 2024 20:23:44 +0800 Subject: [PATCH 1/3] [InstCombine] Add pre-commit tests. NFC. --- .../InstCombine/canonicalize-fcmp-inf.ll | 200 ++++++++++++++++++ 1 file changed, 200 insertions(+) create mode 100644 llvm/test/Transforms/InstCombine/canonicalize-fcmp-inf.ll diff --git a/llvm/test/Transforms/InstCombine/canonicalize-fcmp-inf.ll b/llvm/test/Transforms/InstCombine/canonicalize-fcmp-inf.ll new file mode 100644 index 0000000000000..e9157f59c9ec3 --- /dev/null +++ b/llvm/test/Transforms/InstCombine/canonicalize-fcmp-inf.ll @@ -0,0 +1,200 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 +; RUN: opt < %s -passes=instcombine -S | FileCheck %s + +define i1 @olt_pinf(half %x) { +; CHECK-LABEL: define i1 @olt_pinf( +; CHECK-SAME: half [[X:%.*]]) { +; CHECK-NEXT: [[CMP:%.*]] = fcmp olt half [[X]], 0xH7C00 +; CHECK-NEXT: ret i1 [[CMP]] +; + %cmp = fcmp olt half %x, 0xH7c00 + ret i1 %cmp +} + +define i1 @ole_pinf(half %x) { +; CHECK-LABEL: define i1 @ole_pinf( +; CHECK-SAME: half [[X:%.*]]) { +; CHECK-NEXT: [[CMP:%.*]] = fcmp ole half [[X]], 0xH7C00 +; CHECK-NEXT: ret i1 [[CMP]] +; + %cmp = fcmp ole half %x, 0xH7c00 + ret i1 %cmp +} + +define i1 @ogt_pinf(half %x) { +; CHECK-LABEL: define i1 @ogt_pinf( +; CHECK-SAME: half [[X:%.*]]) { +; CHECK-NEXT: ret i1 false +; + %cmp = fcmp ogt half %x, 0xH7c00 + ret i1 %cmp +} + +define i1 @oge_pinf(half %x) { +; CHECK-LABEL: define i1 @oge_pinf( +; CHECK-SAME: half [[X:%.*]]) { +; CHECK-NEXT: [[CMP:%.*]] = fcmp oge half [[X]], 0xH7C00 +; CHECK-NEXT: ret i1 [[CMP]] +; + %cmp = fcmp oge half %x, 0xH7c00 + ret i1 %cmp +} + +define i1 @ult_pinf(half %x) { +; CHECK-LABEL: define i1 @ult_pinf( +; CHECK-SAME: half [[X:%.*]]) { +; CHECK-NEXT: [[CMP:%.*]] = fcmp ult half [[X]], 0xH7C00 +; CHECK-NEXT: ret i1 [[CMP]] +; + %cmp = fcmp ult half %x, 0xH7c00 + ret i1 %cmp +} + +define i1 @ule_pinf(half %x) { +; CHECK-LABEL: define i1 @ule_pinf( +; CHECK-SAME: half [[X:%.*]]) { +; CHECK-NEXT: ret i1 true +; + %cmp = fcmp ule half %x, 0xH7c00 + ret i1 %cmp +} + +define i1 @ugt_pinf(half %x) { +; CHECK-LABEL: define i1 @ugt_pinf( +; CHECK-SAME: half [[X:%.*]]) { +; CHECK-NEXT: [[CMP:%.*]] = fcmp ugt half [[X]], 0xH7C00 +; CHECK-NEXT: ret i1 [[CMP]] +; + %cmp = fcmp ugt half %x, 0xH7c00 + ret i1 %cmp +} + +define i1 @uge_pinf(half %x) { +; CHECK-LABEL: define i1 @uge_pinf( +; CHECK-SAME: half [[X:%.*]]) { +; CHECK-NEXT: [[CMP:%.*]] = fcmp uge half [[X]], 0xH7C00 +; CHECK-NEXT: ret i1 [[CMP]] +; + %cmp = fcmp uge half %x, 0xH7c00 + ret i1 %cmp +} + +define i1 @olt_ninf(half %x) { +; CHECK-LABEL: define i1 @olt_ninf( +; CHECK-SAME: half [[X:%.*]]) { +; CHECK-NEXT: ret i1 false +; + %cmp = fcmp olt half %x, 0xHfc00 + ret i1 %cmp +} + +define i1 @ole_ninf(half %x) { +; CHECK-LABEL: define i1 @ole_ninf( +; CHECK-SAME: half [[X:%.*]]) { +; CHECK-NEXT: [[CMP:%.*]] = fcmp ole half [[X]], 0xHFC00 +; CHECK-NEXT: ret i1 [[CMP]] +; + %cmp = fcmp ole half %x, 0xHfc00 + ret i1 %cmp +} + +define i1 @ogt_ninf(half %x) { +; CHECK-LABEL: define i1 @ogt_ninf( +; CHECK-SAME: half [[X:%.*]]) { +; CHECK-NEXT: [[CMP:%.*]] = fcmp ogt half [[X]], 0xHFC00 +; CHECK-NEXT: ret i1 [[CMP]] +; + %cmp = fcmp ogt half %x, 0xHfc00 + ret i1 %cmp +} + +define i1 @oge_ninf(half %x) { +; CHECK-LABEL: define i1 @oge_ninf( +; CHECK-SAME: half [[X:%.*]]) { +; CHECK-NEXT: [[CMP:%.*]] = fcmp oge half [[X]], 0xHFC00 +; CHECK-NEXT: ret i1 [[CMP]] +; + %cmp = fcmp oge half %x, 0xHfc00 + ret i1 %cmp +} + +define i1 @ult_ninf(half %x) { +; CHECK-LABEL: define i1 @ult_ninf( +; CHECK-SAME: half [[X:%.*]]) { +; CHECK-NEXT: [[CMP:%.*]] = fcmp ult half [[X]], 0xHFC00 +; CHECK-NEXT: ret i1 [[CMP]] +; + %cmp = fcmp ult half %x, 0xHfc00 + ret i1 %cmp +} + +define i1 @ule_ninf(half %x) { +; CHECK-LABEL: define i1 @ule_ninf( +; CHECK-SAME: half [[X:%.*]]) { +; CHECK-NEXT: [[CMP:%.*]] = fcmp ule half [[X]], 0xHFC00 +; CHECK-NEXT: ret i1 [[CMP]] +; + %cmp = fcmp ule half %x, 0xHfc00 + ret i1 %cmp +} + +define i1 @ugt_ninf(half %x) { +; CHECK-LABEL: define i1 @ugt_ninf( +; CHECK-SAME: half [[X:%.*]]) { +; CHECK-NEXT: [[CMP:%.*]] = fcmp ugt half [[X]], 0xHFC00 +; CHECK-NEXT: ret i1 [[CMP]] +; + %cmp = fcmp ugt half %x, 0xHfc00 + ret i1 %cmp +} + +define i1 @uge_ninf(half %x) { +; CHECK-LABEL: define i1 @uge_ninf( +; CHECK-SAME: half [[X:%.*]]) { +; CHECK-NEXT: ret i1 true +; + %cmp = fcmp uge half %x, 0xHfc00 + ret i1 %cmp +} + +define i1 @olt_pinf_fmf(half %x) { +; CHECK-LABEL: define i1 @olt_pinf_fmf( +; CHECK-SAME: half [[X:%.*]]) { +; CHECK-NEXT: [[CMP:%.*]] = fcmp nsz olt half [[X]], 0xH7C00 +; CHECK-NEXT: ret i1 [[CMP]] +; + %cmp = fcmp nsz olt half %x, 0xH7c00 + ret i1 %cmp +} + +define i1 @oge_pinf_fmf(half %x) { +; CHECK-LABEL: define i1 @oge_pinf_fmf( +; CHECK-SAME: half [[X:%.*]]) { +; CHECK-NEXT: [[CMP:%.*]] = fcmp nnan oge half [[X]], 0xH7C00 +; CHECK-NEXT: ret i1 [[CMP]] +; + %cmp = fcmp nnan oge half %x, 0xH7c00 + ret i1 %cmp +} + +; Negative tests + +define i1 @ord_pinf(half %x) { +; CHECK-LABEL: define i1 @ord_pinf( +; CHECK-SAME: half [[X:%.*]]) { +; CHECK-NEXT: [[CMP:%.*]] = fcmp ord half [[X]], 0xH0000 +; CHECK-NEXT: ret i1 [[CMP]] +; + %cmp = fcmp ord half %x, 0xH7c00 + ret i1 %cmp +} + +define i1 @olt_one(half %x) { +; CHECK-LABEL: define i1 @olt_one( +; CHECK-SAME: half [[X:%.*]]) { +; CHECK-NEXT: [[CMP:%.*]] = fcmp olt half [[X]], 0xH3C00 +; CHECK-NEXT: ret i1 [[CMP]] +; + %cmp = fcmp olt half %x, 1.0 + ret i1 %cmp +} From 18ab29f8afca96106e9b685a7387a1bc5aef0725 Mon Sep 17 00:00:00 2001 From: Yingwei Zheng Date: Wed, 7 Feb 2024 20:24:45 +0800 Subject: [PATCH 2/3] [InstCombine] Canonicalize fcmp with inf --- .../InstCombine/InstCombineCompares.cpp | 43 ++++++++++++++++++- llvm/test/Transforms/InstCombine/and-fcmp.ll | 40 ++++++++--------- .../InstCombine/canonicalize-fcmp-inf.ll | 28 ++++++------ .../create-class-from-logic-fcmp.ll | 4 +- .../InstCombine/fold-select-fmul-if-zero.ll | 4 +- 5 files changed, 80 insertions(+), 39 deletions(-) diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp index 380cb3504209d..85960660e6ab0 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp @@ -7751,6 +7751,48 @@ Instruction *InstCombinerImpl::visitFCmpInst(FCmpInst &I) { if (match(Op1, m_AnyZeroFP()) && !match(Op1, m_PosZeroFP())) return replaceOperand(I, 1, ConstantFP::getZero(OpType)); + // Canonicalize: + // fcmp olt X, +inf -> fcmp one X, +inf + // fcmp ole X, +inf -> fcmp ord X, 0 + // fcmp ogt X, +inf -> false + // fcmp oge X, +inf -> fcmp oeq X, +inf + // fcmp ult X, +inf -> fcmp une X, +inf + // fcmp ule X, +inf -> true + // fcmp ugt X, +inf -> fcmp uno X, 0 + // fcmp uge X, +inf -> fcmp ueq X, +inf + // fcmp olt X, -inf -> false + // fcmp ole X, -inf -> fcmp oeq X, -inf + // fcmp ogt X, -inf -> fcmp one X, -inf + // fcmp oge X, -inf -> fcmp ord X, 0 + // fcmp ult X, -inf -> fcmp uno X, 0 + // fcmp ule X, -inf -> fcmp ueq X, -inf + // fcmp ugt X, -inf -> fcmp une X, -inf + // fcmp uge X, -inf -> true + const APFloat *C; + if (match(Op1, m_APFloat(C)) && C->isInfinity()) { + switch (C->isNegative() ? FCmpInst::getSwappedPredicate(Pred) : Pred) { + default: + break; + case FCmpInst::FCMP_OGT: + case FCmpInst::FCMP_ULE: + llvm_unreachable("Should be simplified by InstSimplify"); + case FCmpInst::FCMP_OLT: + return new FCmpInst(FCmpInst::FCMP_ONE, Op0, Op1, "", &I); + case FCmpInst::FCMP_OLE: + return new FCmpInst(FCmpInst::FCMP_ORD, Op0, ConstantFP::getZero(OpType), + "", &I); + case FCmpInst::FCMP_OGE: + return new FCmpInst(FCmpInst::FCMP_OEQ, Op0, Op1, "", &I); + case FCmpInst::FCMP_ULT: + return new FCmpInst(FCmpInst::FCMP_UNE, Op0, Op1, "", &I); + case FCmpInst::FCMP_UGT: + return new FCmpInst(FCmpInst::FCMP_UNO, Op0, ConstantFP::getZero(OpType), + "", &I); + case FCmpInst::FCMP_UGE: + return new FCmpInst(FCmpInst::FCMP_UEQ, Op0, Op1, "", &I); + } + } + // Ignore signbit of bitcasted int when comparing equality to FP 0.0: // fcmp oeq/une (bitcast X), 0.0 --> (and X, SignMaskC) ==/!= 0 if (match(Op1, m_PosZeroFP()) && @@ -7864,7 +7906,6 @@ Instruction *InstCombinerImpl::visitFCmpInst(FCmpInst &I) { // TODO: Simplify if the copysign constant is 0.0 or NaN. // TODO: Handle non-zero compare constants. // TODO: Handle other predicates. - const APFloat *C; if (match(Op0, m_OneUse(m_Intrinsic(m_APFloat(C), m_Value(X)))) && match(Op1, m_AnyZeroFP()) && !C->isZero() && !C->isNaN()) { diff --git a/llvm/test/Transforms/InstCombine/and-fcmp.ll b/llvm/test/Transforms/InstCombine/and-fcmp.ll index 42e3f34d126d6..f1ae2e74ac2e4 100644 --- a/llvm/test/Transforms/InstCombine/and-fcmp.ll +++ b/llvm/test/Transforms/InstCombine/and-fcmp.ll @@ -4614,7 +4614,7 @@ define i1 @intersect_fmf_4(double %a, double %b) { define i1 @clang_builtin_isnormal_inf_check(half %x) { ; CHECK-LABEL: @clang_builtin_isnormal_inf_check( ; CHECK-NEXT: [[FABS_X:%.*]] = call half @llvm.fabs.f16(half [[X:%.*]]) -; CHECK-NEXT: [[AND:%.*]] = fcmp oge half [[FABS_X]], 0xH7C00 +; CHECK-NEXT: [[AND:%.*]] = fcmp oeq half [[FABS_X]], 0xH7C00 ; CHECK-NEXT: ret i1 [[AND]] ; %fabs.x = call half @llvm.fabs.f16(half %x) @@ -4627,7 +4627,7 @@ define i1 @clang_builtin_isnormal_inf_check(half %x) { define <2 x i1> @clang_builtin_isnormal_inf_check_vector(<2 x half> %x) { ; CHECK-LABEL: @clang_builtin_isnormal_inf_check_vector( ; CHECK-NEXT: [[FABS_X:%.*]] = call <2 x half> @llvm.fabs.v2f16(<2 x half> [[X:%.*]]) -; CHECK-NEXT: [[AND:%.*]] = fcmp oge <2 x half> [[FABS_X]], +; CHECK-NEXT: [[AND:%.*]] = fcmp oeq <2 x half> [[FABS_X]], ; CHECK-NEXT: ret <2 x i1> [[AND]] ; %fabs.x = call <2 x half> @llvm.fabs.v2f16(<2 x half> %x) @@ -4640,7 +4640,7 @@ define <2 x i1> @clang_builtin_isnormal_inf_check_vector(<2 x half> %x) { define i1 @clang_builtin_isnormal_inf_check_commute(half %x) { ; CHECK-LABEL: @clang_builtin_isnormal_inf_check_commute( ; CHECK-NEXT: [[FABS_X:%.*]] = call half @llvm.fabs.f16(half [[X:%.*]]) -; CHECK-NEXT: [[AND:%.*]] = fcmp oge half [[FABS_X]], 0xH7C00 +; CHECK-NEXT: [[AND:%.*]] = fcmp oeq half [[FABS_X]], 0xH7C00 ; CHECK-NEXT: ret i1 [[AND]] ; %fabs.x = call half @llvm.fabs.f16(half %x) @@ -4653,7 +4653,7 @@ define i1 @clang_builtin_isnormal_inf_check_commute(half %x) { define i1 @clang_builtin_isnormal_inf_check_commute_nsz_rhs(half %x) { ; CHECK-LABEL: @clang_builtin_isnormal_inf_check_commute_nsz_rhs( ; CHECK-NEXT: [[FABS_X:%.*]] = call half @llvm.fabs.f16(half [[X:%.*]]) -; CHECK-NEXT: [[AND:%.*]] = fcmp oge half [[FABS_X]], 0xH7C00 +; CHECK-NEXT: [[AND:%.*]] = fcmp oeq half [[FABS_X]], 0xH7C00 ; CHECK-NEXT: ret i1 [[AND]] ; %fabs.x = call half @llvm.fabs.f16(half %x) @@ -4666,7 +4666,7 @@ define i1 @clang_builtin_isnormal_inf_check_commute_nsz_rhs(half %x) { define i1 @clang_builtin_isnormal_inf_check_commute_nsz_lhs(half %x) { ; CHECK-LABEL: @clang_builtin_isnormal_inf_check_commute_nsz_lhs( ; CHECK-NEXT: [[FABS_X:%.*]] = call half @llvm.fabs.f16(half [[X:%.*]]) -; CHECK-NEXT: [[AND:%.*]] = fcmp oge half [[FABS_X]], 0xH7C00 +; CHECK-NEXT: [[AND:%.*]] = fcmp oeq half [[FABS_X]], 0xH7C00 ; CHECK-NEXT: ret i1 [[AND]] ; %fabs.x = call half @llvm.fabs.f16(half %x) @@ -4690,7 +4690,7 @@ define i1 @clang_builtin_isnormal_inf_check_commute_nofabs_ueq(half %x) { define i1 @clang_builtin_isnormal_inf_check_commute_nsz(half %x) { ; CHECK-LABEL: @clang_builtin_isnormal_inf_check_commute_nsz( ; CHECK-NEXT: [[FABS_X:%.*]] = call half @llvm.fabs.f16(half [[X:%.*]]) -; CHECK-NEXT: [[AND:%.*]] = fcmp nsz oge half [[FABS_X]], 0xH7C00 +; CHECK-NEXT: [[AND:%.*]] = fcmp nsz oeq half [[FABS_X]], 0xH7C00 ; CHECK-NEXT: ret i1 [[AND]] ; %fabs.x = call half @llvm.fabs.f16(half %x) @@ -4716,7 +4716,7 @@ define i1 @clang_builtin_isnormal_inf_check_ugt(half %x) { define i1 @clang_builtin_isnormal_inf_check_ult(half %x) { ; CHECK-LABEL: @clang_builtin_isnormal_inf_check_ult( ; CHECK-NEXT: [[FABS_X:%.*]] = call half @llvm.fabs.f16(half [[X:%.*]]) -; CHECK-NEXT: [[AND:%.*]] = fcmp olt half [[FABS_X]], 0xH7C00 +; CHECK-NEXT: [[AND:%.*]] = fcmp one half [[FABS_X]], 0xH7C00 ; CHECK-NEXT: ret i1 [[AND]] ; %fabs.x = call half @llvm.fabs.f16(half %x) @@ -4820,8 +4820,8 @@ define i1 @clang_builtin_isnormal_inf_check_olt(half %x) { define i1 @clang_builtin_isnormal_inf_check_ole(half %x) { ; CHECK-LABEL: @clang_builtin_isnormal_inf_check_ole( -; CHECK-NEXT: [[AND:%.*]] = fcmp ord half [[X:%.*]], 0xH0000 -; CHECK-NEXT: ret i1 [[AND]] +; CHECK-NEXT: [[CMP:%.*]] = fcmp ord half [[X:%.*]], 0xH0000 +; CHECK-NEXT: ret i1 [[CMP]] ; %fabs.x = call half @llvm.fabs.f16(half %x) %ord = fcmp ord half %fabs.x, 0.0 @@ -4846,7 +4846,7 @@ define i1 @clang_builtin_isnormal_inf_check_oeq(half %x) { define i1 @clang_builtin_isnormal_inf_check_unnececcary_fabs(half %x) { ; CHECK-LABEL: @clang_builtin_isnormal_inf_check_unnececcary_fabs( ; CHECK-NEXT: [[FABS_X:%.*]] = call half @llvm.fabs.f16(half [[X:%.*]]) -; CHECK-NEXT: [[AND:%.*]] = fcmp oge half [[FABS_X]], 0xH7C00 +; CHECK-NEXT: [[AND:%.*]] = fcmp oeq half [[FABS_X]], 0xH7C00 ; CHECK-NEXT: ret i1 [[AND]] ; %fabs.x = call half @llvm.fabs.f16(half %x) @@ -4871,7 +4871,7 @@ define i1 @clang_builtin_isnormal_inf_check_not_ord(half %x) { define i1 @clang_builtin_isnormal_inf_check_missing_fabs(half %x) { ; CHECK-LABEL: @clang_builtin_isnormal_inf_check_missing_fabs( -; CHECK-NEXT: [[AND:%.*]] = fcmp oge half [[X:%.*]], 0xH7C00 +; CHECK-NEXT: [[AND:%.*]] = fcmp oeq half [[X:%.*]], 0xH7C00 ; CHECK-NEXT: ret i1 [[AND]] ; %fabs.x = call half @llvm.fabs.f16(half %x) @@ -4912,7 +4912,7 @@ define i1 @clang_builtin_isnormal_inf_check_not_inf(half %x) { define i1 @clang_builtin_isnormal_inf_check_nsz_lhs(half %x) { ; CHECK-LABEL: @clang_builtin_isnormal_inf_check_nsz_lhs( ; CHECK-NEXT: [[FABS_X:%.*]] = call half @llvm.fabs.f16(half [[X:%.*]]) -; CHECK-NEXT: [[AND:%.*]] = fcmp oge half [[FABS_X]], 0xH7C00 +; CHECK-NEXT: [[AND:%.*]] = fcmp oeq half [[FABS_X]], 0xH7C00 ; CHECK-NEXT: ret i1 [[AND]] ; %fabs.x = call half @llvm.fabs.f16(half %x) @@ -4925,7 +4925,7 @@ define i1 @clang_builtin_isnormal_inf_check_nsz_lhs(half %x) { define i1 @clang_builtin_isnormal_inf_check_nsz_rhs(half %x) { ; CHECK-LABEL: @clang_builtin_isnormal_inf_check_nsz_rhs( ; CHECK-NEXT: [[FABS_X:%.*]] = call half @llvm.fabs.f16(half [[X:%.*]]) -; CHECK-NEXT: [[AND:%.*]] = fcmp oge half [[FABS_X]], 0xH7C00 +; CHECK-NEXT: [[AND:%.*]] = fcmp oeq half [[FABS_X]], 0xH7C00 ; CHECK-NEXT: ret i1 [[AND]] ; %fabs.x = call half @llvm.fabs.f16(half %x) @@ -4938,7 +4938,7 @@ define i1 @clang_builtin_isnormal_inf_check_nsz_rhs(half %x) { define i1 @clang_builtin_isnormal_inf_check_nsz(half %x) { ; CHECK-LABEL: @clang_builtin_isnormal_inf_check_nsz( ; CHECK-NEXT: [[FABS_X:%.*]] = call half @llvm.fabs.f16(half [[X:%.*]]) -; CHECK-NEXT: [[AND:%.*]] = fcmp nsz oge half [[FABS_X]], 0xH7C00 +; CHECK-NEXT: [[AND:%.*]] = fcmp nsz oeq half [[FABS_X]], 0xH7C00 ; CHECK-NEXT: ret i1 [[AND]] ; %fabs.x = call half @llvm.fabs.f16(half %x) @@ -4950,7 +4950,7 @@ define i1 @clang_builtin_isnormal_inf_check_nsz(half %x) { define i1 @clang_builtin_isnormal_inf_check_fneg(half %x) { ; CHECK-LABEL: @clang_builtin_isnormal_inf_check_fneg( -; CHECK-NEXT: [[AND:%.*]] = fcmp oge half [[X:%.*]], 0xH7C00 +; CHECK-NEXT: [[AND:%.*]] = fcmp oeq half [[X:%.*]], 0xH7C00 ; CHECK-NEXT: ret i1 [[AND]] ; %fneg.x = fneg half %x @@ -4963,7 +4963,7 @@ define i1 @clang_builtin_isnormal_inf_check_fneg(half %x) { define i1 @clang_builtin_isnormal_inf_check_copysign(half %x, half %y) { ; CHECK-LABEL: @clang_builtin_isnormal_inf_check_copysign( ; CHECK-NEXT: [[COPYSIGN_X:%.*]] = call half @llvm.copysign.f16(half [[X:%.*]], half [[Y:%.*]]) -; CHECK-NEXT: [[AND:%.*]] = fcmp oge half [[COPYSIGN_X]], 0xH7C00 +; CHECK-NEXT: [[AND:%.*]] = fcmp oeq half [[COPYSIGN_X]], 0xH7C00 ; CHECK-NEXT: ret i1 [[AND]] ; %copysign.x = call half @llvm.copysign.f16(half %x, half %y) @@ -4976,7 +4976,7 @@ define i1 @clang_builtin_isnormal_inf_check_copysign(half %x, half %y) { define i1 @isnormal_logical_select_0(half %x) { ; CHECK-LABEL: @isnormal_logical_select_0( ; CHECK-NEXT: [[FABS_X:%.*]] = call half @llvm.fabs.f16(half [[X:%.*]]) -; CHECK-NEXT: [[AND:%.*]] = fcmp oge half [[FABS_X]], 0xH7C00 +; CHECK-NEXT: [[AND:%.*]] = fcmp oeq half [[FABS_X]], 0xH7C00 ; CHECK-NEXT: ret i1 [[AND]] ; %fabs.x = call half @llvm.fabs.f16(half %x) @@ -4989,7 +4989,7 @@ define i1 @isnormal_logical_select_0(half %x) { define i1 @isnormal_logical_select_1(half %x) { ; CHECK-LABEL: @isnormal_logical_select_1( ; CHECK-NEXT: [[FABS_X:%.*]] = call half @llvm.fabs.f16(half [[X:%.*]]) -; CHECK-NEXT: [[AND:%.*]] = fcmp oge half [[FABS_X]], 0xH7C00 +; CHECK-NEXT: [[AND:%.*]] = fcmp oeq half [[FABS_X]], 0xH7C00 ; CHECK-NEXT: ret i1 [[AND]] ; %fabs.x = call half @llvm.fabs.f16(half %x) @@ -5002,7 +5002,7 @@ define i1 @isnormal_logical_select_1(half %x) { define i1 @isnormal_logical_select_0_fmf0(half %x) { ; CHECK-LABEL: @isnormal_logical_select_0_fmf0( ; CHECK-NEXT: [[FABS_X:%.*]] = call half @llvm.fabs.f16(half [[X:%.*]]) -; CHECK-NEXT: [[AND:%.*]] = fcmp reassoc nsz arcp oge half [[FABS_X]], 0xH7C00 +; CHECK-NEXT: [[AND:%.*]] = fcmp reassoc nsz arcp oeq half [[FABS_X]], 0xH7C00 ; CHECK-NEXT: ret i1 [[AND]] ; %fabs.x = call half @llvm.fabs.f16(half %x) @@ -5015,7 +5015,7 @@ define i1 @isnormal_logical_select_0_fmf0(half %x) { define i1 @isnormal_logical_select_0_fmf1(half %x) { ; CHECK-LABEL: @isnormal_logical_select_0_fmf1( ; CHECK-NEXT: [[FABS_X:%.*]] = call half @llvm.fabs.f16(half [[X:%.*]]) -; CHECK-NEXT: [[AND:%.*]] = fcmp oge half [[FABS_X]], 0xH7C00 +; CHECK-NEXT: [[AND:%.*]] = fcmp oeq half [[FABS_X]], 0xH7C00 ; CHECK-NEXT: ret i1 [[AND]] ; %fabs.x = call half @llvm.fabs.f16(half %x) diff --git a/llvm/test/Transforms/InstCombine/canonicalize-fcmp-inf.ll b/llvm/test/Transforms/InstCombine/canonicalize-fcmp-inf.ll index e9157f59c9ec3..2fd397a9be36c 100644 --- a/llvm/test/Transforms/InstCombine/canonicalize-fcmp-inf.ll +++ b/llvm/test/Transforms/InstCombine/canonicalize-fcmp-inf.ll @@ -4,7 +4,7 @@ define i1 @olt_pinf(half %x) { ; CHECK-LABEL: define i1 @olt_pinf( ; CHECK-SAME: half [[X:%.*]]) { -; CHECK-NEXT: [[CMP:%.*]] = fcmp olt half [[X]], 0xH7C00 +; CHECK-NEXT: [[CMP:%.*]] = fcmp one half [[X]], 0xH7C00 ; CHECK-NEXT: ret i1 [[CMP]] ; %cmp = fcmp olt half %x, 0xH7c00 @@ -14,7 +14,7 @@ define i1 @olt_pinf(half %x) { define i1 @ole_pinf(half %x) { ; CHECK-LABEL: define i1 @ole_pinf( ; CHECK-SAME: half [[X:%.*]]) { -; CHECK-NEXT: [[CMP:%.*]] = fcmp ole half [[X]], 0xH7C00 +; CHECK-NEXT: [[CMP:%.*]] = fcmp ord half [[X]], 0xH0000 ; CHECK-NEXT: ret i1 [[CMP]] ; %cmp = fcmp ole half %x, 0xH7c00 @@ -33,7 +33,7 @@ define i1 @ogt_pinf(half %x) { define i1 @oge_pinf(half %x) { ; CHECK-LABEL: define i1 @oge_pinf( ; CHECK-SAME: half [[X:%.*]]) { -; CHECK-NEXT: [[CMP:%.*]] = fcmp oge half [[X]], 0xH7C00 +; CHECK-NEXT: [[CMP:%.*]] = fcmp oeq half [[X]], 0xH7C00 ; CHECK-NEXT: ret i1 [[CMP]] ; %cmp = fcmp oge half %x, 0xH7c00 @@ -43,7 +43,7 @@ define i1 @oge_pinf(half %x) { define i1 @ult_pinf(half %x) { ; CHECK-LABEL: define i1 @ult_pinf( ; CHECK-SAME: half [[X:%.*]]) { -; CHECK-NEXT: [[CMP:%.*]] = fcmp ult half [[X]], 0xH7C00 +; CHECK-NEXT: [[CMP:%.*]] = fcmp une half [[X]], 0xH7C00 ; CHECK-NEXT: ret i1 [[CMP]] ; %cmp = fcmp ult half %x, 0xH7c00 @@ -62,7 +62,7 @@ define i1 @ule_pinf(half %x) { define i1 @ugt_pinf(half %x) { ; CHECK-LABEL: define i1 @ugt_pinf( ; CHECK-SAME: half [[X:%.*]]) { -; CHECK-NEXT: [[CMP:%.*]] = fcmp ugt half [[X]], 0xH7C00 +; CHECK-NEXT: [[CMP:%.*]] = fcmp uno half [[X]], 0xH0000 ; CHECK-NEXT: ret i1 [[CMP]] ; %cmp = fcmp ugt half %x, 0xH7c00 @@ -72,7 +72,7 @@ define i1 @ugt_pinf(half %x) { define i1 @uge_pinf(half %x) { ; CHECK-LABEL: define i1 @uge_pinf( ; CHECK-SAME: half [[X:%.*]]) { -; CHECK-NEXT: [[CMP:%.*]] = fcmp uge half [[X]], 0xH7C00 +; CHECK-NEXT: [[CMP:%.*]] = fcmp ueq half [[X]], 0xH7C00 ; CHECK-NEXT: ret i1 [[CMP]] ; %cmp = fcmp uge half %x, 0xH7c00 @@ -91,7 +91,7 @@ define i1 @olt_ninf(half %x) { define i1 @ole_ninf(half %x) { ; CHECK-LABEL: define i1 @ole_ninf( ; CHECK-SAME: half [[X:%.*]]) { -; CHECK-NEXT: [[CMP:%.*]] = fcmp ole half [[X]], 0xHFC00 +; CHECK-NEXT: [[CMP:%.*]] = fcmp oeq half [[X]], 0xHFC00 ; CHECK-NEXT: ret i1 [[CMP]] ; %cmp = fcmp ole half %x, 0xHfc00 @@ -101,7 +101,7 @@ define i1 @ole_ninf(half %x) { define i1 @ogt_ninf(half %x) { ; CHECK-LABEL: define i1 @ogt_ninf( ; CHECK-SAME: half [[X:%.*]]) { -; CHECK-NEXT: [[CMP:%.*]] = fcmp ogt half [[X]], 0xHFC00 +; CHECK-NEXT: [[CMP:%.*]] = fcmp one half [[X]], 0xHFC00 ; CHECK-NEXT: ret i1 [[CMP]] ; %cmp = fcmp ogt half %x, 0xHfc00 @@ -111,7 +111,7 @@ define i1 @ogt_ninf(half %x) { define i1 @oge_ninf(half %x) { ; CHECK-LABEL: define i1 @oge_ninf( ; CHECK-SAME: half [[X:%.*]]) { -; CHECK-NEXT: [[CMP:%.*]] = fcmp oge half [[X]], 0xHFC00 +; CHECK-NEXT: [[CMP:%.*]] = fcmp ord half [[X]], 0xH0000 ; CHECK-NEXT: ret i1 [[CMP]] ; %cmp = fcmp oge half %x, 0xHfc00 @@ -121,7 +121,7 @@ define i1 @oge_ninf(half %x) { define i1 @ult_ninf(half %x) { ; CHECK-LABEL: define i1 @ult_ninf( ; CHECK-SAME: half [[X:%.*]]) { -; CHECK-NEXT: [[CMP:%.*]] = fcmp ult half [[X]], 0xHFC00 +; CHECK-NEXT: [[CMP:%.*]] = fcmp uno half [[X]], 0xH0000 ; CHECK-NEXT: ret i1 [[CMP]] ; %cmp = fcmp ult half %x, 0xHfc00 @@ -131,7 +131,7 @@ define i1 @ult_ninf(half %x) { define i1 @ule_ninf(half %x) { ; CHECK-LABEL: define i1 @ule_ninf( ; CHECK-SAME: half [[X:%.*]]) { -; CHECK-NEXT: [[CMP:%.*]] = fcmp ule half [[X]], 0xHFC00 +; CHECK-NEXT: [[CMP:%.*]] = fcmp ueq half [[X]], 0xHFC00 ; CHECK-NEXT: ret i1 [[CMP]] ; %cmp = fcmp ule half %x, 0xHfc00 @@ -141,7 +141,7 @@ define i1 @ule_ninf(half %x) { define i1 @ugt_ninf(half %x) { ; CHECK-LABEL: define i1 @ugt_ninf( ; CHECK-SAME: half [[X:%.*]]) { -; CHECK-NEXT: [[CMP:%.*]] = fcmp ugt half [[X]], 0xHFC00 +; CHECK-NEXT: [[CMP:%.*]] = fcmp une half [[X]], 0xHFC00 ; CHECK-NEXT: ret i1 [[CMP]] ; %cmp = fcmp ugt half %x, 0xHfc00 @@ -160,7 +160,7 @@ define i1 @uge_ninf(half %x) { define i1 @olt_pinf_fmf(half %x) { ; CHECK-LABEL: define i1 @olt_pinf_fmf( ; CHECK-SAME: half [[X:%.*]]) { -; CHECK-NEXT: [[CMP:%.*]] = fcmp nsz olt half [[X]], 0xH7C00 +; CHECK-NEXT: [[CMP:%.*]] = fcmp nsz one half [[X]], 0xH7C00 ; CHECK-NEXT: ret i1 [[CMP]] ; %cmp = fcmp nsz olt half %x, 0xH7c00 @@ -170,7 +170,7 @@ define i1 @olt_pinf_fmf(half %x) { define i1 @oge_pinf_fmf(half %x) { ; CHECK-LABEL: define i1 @oge_pinf_fmf( ; CHECK-SAME: half [[X:%.*]]) { -; CHECK-NEXT: [[CMP:%.*]] = fcmp nnan oge half [[X]], 0xH7C00 +; CHECK-NEXT: [[CMP:%.*]] = fcmp nnan oeq half [[X]], 0xH7C00 ; CHECK-NEXT: ret i1 [[CMP]] ; %cmp = fcmp nnan oge half %x, 0xH7c00 diff --git a/llvm/test/Transforms/InstCombine/create-class-from-logic-fcmp.ll b/llvm/test/Transforms/InstCombine/create-class-from-logic-fcmp.ll index ea056de3f8ee7..24dac97672f71 100644 --- a/llvm/test/Transforms/InstCombine/create-class-from-logic-fcmp.ll +++ b/llvm/test/Transforms/InstCombine/create-class-from-logic-fcmp.ll @@ -1343,7 +1343,7 @@ define i1 @oge_eq_inf_or_uno(half %x) #0 { define i1 @ult_fabs_eq_inf_and_ord(half %x) #0 { ; CHECK-LABEL: @ult_fabs_eq_inf_and_ord( ; CHECK-NEXT: [[FABS:%.*]] = call half @llvm.fabs.f16(half [[X:%.*]]) -; CHECK-NEXT: [[AND:%.*]] = fcmp olt half [[FABS]], 0xH7C00 +; CHECK-NEXT: [[AND:%.*]] = fcmp one half [[FABS]], 0xH7C00 ; CHECK-NEXT: ret i1 [[AND]] ; %fabs = call half @llvm.fabs.f16(half %x) @@ -1355,7 +1355,7 @@ define i1 @ult_fabs_eq_inf_and_ord(half %x) #0 { define i1 @ult_eq_inf_and_ord(half %x) #0 { ; CHECK-LABEL: @ult_eq_inf_and_ord( -; CHECK-NEXT: [[AND:%.*]] = fcmp olt half [[X:%.*]], 0xH7C00 +; CHECK-NEXT: [[AND:%.*]] = fcmp one half [[X:%.*]], 0xH7C00 ; CHECK-NEXT: ret i1 [[AND]] ; %ult.fabs.inf = fcmp ult half %x, 0xH7C00 diff --git a/llvm/test/Transforms/InstCombine/fold-select-fmul-if-zero.ll b/llvm/test/Transforms/InstCombine/fold-select-fmul-if-zero.ll index 607b12b03b2a1..a7adcd1ac61e7 100644 --- a/llvm/test/Transforms/InstCombine/fold-select-fmul-if-zero.ll +++ b/llvm/test/Transforms/InstCombine/fold-select-fmul-if-zero.ll @@ -659,7 +659,7 @@ define float @fmul_by_var_if_0_oeq_zero_f32_fmul_known_never_nan_inf_neg(float % define float @fmul_by_var_if_0_oeq_zero_f32_assume_finite_fmul_nsz(float %x, float %y) { ; CHECK-LABEL: @fmul_by_var_if_0_oeq_zero_f32_assume_finite_fmul_nsz( ; CHECK-NEXT: [[FABS_Y:%.*]] = call float @llvm.fabs.f32(float [[Y:%.*]]) -; CHECK-NEXT: [[IS_FINITE:%.*]] = fcmp olt float [[FABS_Y]], 0x7FF0000000000000 +; CHECK-NEXT: [[IS_FINITE:%.*]] = fcmp one float [[FABS_Y]], 0x7FF0000000000000 ; CHECK-NEXT: call void @llvm.assume(i1 [[IS_FINITE]]) ; CHECK-NEXT: ret float [[X:%.*]] ; @@ -676,7 +676,7 @@ define float @fmul_by_var_if_0_oeq_zero_f32_assume_finite_fmul_nsz(float %x, flo define float @fmul_by_var_if_not_one_0_zero_f32_assume_finite_fmul_nsz(float %x, float %y) { ; CHECK-LABEL: @fmul_by_var_if_not_one_0_zero_f32_assume_finite_fmul_nsz( ; CHECK-NEXT: [[FABS_Y:%.*]] = call float @llvm.fabs.f32(float [[Y:%.*]]) -; CHECK-NEXT: [[IS_FINITE:%.*]] = fcmp olt float [[FABS_Y]], 0x7FF0000000000000 +; CHECK-NEXT: [[IS_FINITE:%.*]] = fcmp one float [[FABS_Y]], 0x7FF0000000000000 ; CHECK-NEXT: call void @llvm.assume(i1 [[IS_FINITE]]) ; CHECK-NEXT: ret float [[X:%.*]] ; From 05db34737b48b9d7de76d44a8d7ee8f69e14bddd Mon Sep 17 00:00:00 2001 From: Yingwei Zheng Date: Wed, 7 Feb 2024 22:51:00 +0800 Subject: [PATCH 3/3] fixup! [InstCombine] Canonicalize fcmp with inf Address review feedbacks. --- .../InstCombine/InstCombineCompares.cpp | 6 +- .../InstCombine/canonicalize-fcmp-inf.ll | 86 +++++++++++++++++++ 2 files changed, 90 insertions(+), 2 deletions(-) diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp index 85960660e6ab0..ec5e211a634cd 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp @@ -7771,8 +7771,10 @@ Instruction *InstCombinerImpl::visitFCmpInst(FCmpInst &I) { const APFloat *C; if (match(Op1, m_APFloat(C)) && C->isInfinity()) { switch (C->isNegative() ? FCmpInst::getSwappedPredicate(Pred) : Pred) { - default: - break; + case FCmpInst::FCMP_ORD: + case FCmpInst::FCMP_UNO: + case FCmpInst::FCMP_TRUE: + case FCmpInst::FCMP_FALSE: case FCmpInst::FCMP_OGT: case FCmpInst::FCMP_ULE: llvm_unreachable("Should be simplified by InstSimplify"); diff --git a/llvm/test/Transforms/InstCombine/canonicalize-fcmp-inf.ll b/llvm/test/Transforms/InstCombine/canonicalize-fcmp-inf.ll index 2fd397a9be36c..297dc647e7c67 100644 --- a/llvm/test/Transforms/InstCombine/canonicalize-fcmp-inf.ll +++ b/llvm/test/Transforms/InstCombine/canonicalize-fcmp-inf.ll @@ -177,6 +177,26 @@ define i1 @oge_pinf_fmf(half %x) { ret i1 %cmp } +define <2 x i1> @olt_pinf_vec(<2 x half> %x) { +; CHECK-LABEL: define <2 x i1> @olt_pinf_vec( +; CHECK-SAME: <2 x half> [[X:%.*]]) { +; CHECK-NEXT: [[CMP:%.*]] = fcmp one <2 x half> [[X]], +; CHECK-NEXT: ret <2 x i1> [[CMP]] +; + %cmp = fcmp olt <2 x half> %x, + ret <2 x i1> %cmp +} + +define <2 x i1> @oge_ninf_vec(<2 x half> %x) { +; CHECK-LABEL: define <2 x i1> @oge_ninf_vec( +; CHECK-SAME: <2 x half> [[X:%.*]]) { +; CHECK-NEXT: [[CMP:%.*]] = fcmp ord <2 x half> [[X]], zeroinitializer +; CHECK-NEXT: ret <2 x i1> [[CMP]] +; + %cmp = fcmp oge <2 x half> %x, + ret <2 x i1> %cmp +} + ; Negative tests define i1 @ord_pinf(half %x) { @@ -189,6 +209,72 @@ define i1 @ord_pinf(half %x) { ret i1 %cmp } +define i1 @uno_pinf(half %x) { +; CHECK-LABEL: define i1 @uno_pinf( +; CHECK-SAME: half [[X:%.*]]) { +; CHECK-NEXT: [[CMP:%.*]] = fcmp uno half [[X]], 0xH0000 +; CHECK-NEXT: ret i1 [[CMP]] +; + %cmp = fcmp uno half %x, 0xH7c00 + ret i1 %cmp +} + +define i1 @true_pinf(half %x) { +; CHECK-LABEL: define i1 @true_pinf( +; CHECK-SAME: half [[X:%.*]]) { +; CHECK-NEXT: ret i1 true +; + %cmp = fcmp true half %x, 0xH7c00 + ret i1 %cmp +} + +define i1 @false_pinf(half %x) { +; CHECK-LABEL: define i1 @false_pinf( +; CHECK-SAME: half [[X:%.*]]) { +; CHECK-NEXT: ret i1 false +; + %cmp = fcmp false half %x, 0xH7c00 + ret i1 %cmp +} + +define i1 @ord_ninf(half %x) { +; CHECK-LABEL: define i1 @ord_ninf( +; CHECK-SAME: half [[X:%.*]]) { +; CHECK-NEXT: [[CMP:%.*]] = fcmp ord half [[X]], 0xH0000 +; CHECK-NEXT: ret i1 [[CMP]] +; + %cmp = fcmp ord half %x, 0xHfc00 + ret i1 %cmp +} + +define i1 @uno_ninf(half %x) { +; CHECK-LABEL: define i1 @uno_ninf( +; CHECK-SAME: half [[X:%.*]]) { +; CHECK-NEXT: [[CMP:%.*]] = fcmp uno half [[X]], 0xH0000 +; CHECK-NEXT: ret i1 [[CMP]] +; + %cmp = fcmp uno half %x, 0xHfc00 + ret i1 %cmp +} + +define i1 @true_ninf(half %x) { +; CHECK-LABEL: define i1 @true_ninf( +; CHECK-SAME: half [[X:%.*]]) { +; CHECK-NEXT: ret i1 true +; + %cmp = fcmp true half %x, 0xHfc00 + ret i1 %cmp +} + +define i1 @false_ninf(half %x) { +; CHECK-LABEL: define i1 @false_ninf( +; CHECK-SAME: half [[X:%.*]]) { +; CHECK-NEXT: ret i1 false +; + %cmp = fcmp false half %x, 0xHfc00 + ret i1 %cmp +} + define i1 @olt_one(half %x) { ; CHECK-LABEL: define i1 @olt_one( ; CHECK-SAME: half [[X:%.*]]) {