[llvm] [InstCombine] Canonicalize fcmp with inf (PR #80986)
via llvm-commits
llvm-commits at lists.llvm.org
Wed Feb 7 04:42:47 PST 2024
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-llvm-transforms
Author: Yingwei Zheng (dtcxzyw)
<details>
<summary>Changes</summary>
This patch canonicalizes floating-point comparisons with inf:
```
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
```
Alive2: https://alive2.llvm.org/ce/z/FRqqDg
The motivation of this patch is to fix the regression found in https://github.com/dtcxzyw/llvm-opt-benchmark/pull/199#discussion_r1480974120.
---
Full diff: https://github.com/llvm/llvm-project/pull/80986.diff
5 Files Affected:
- (modified) llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp (+42-1)
- (modified) llvm/test/Transforms/InstCombine/and-fcmp.ll (+20-20)
- (added) llvm/test/Transforms/InstCombine/canonicalize-fcmp-inf.ll (+200)
- (modified) llvm/test/Transforms/InstCombine/create-class-from-logic-fcmp.ll (+2-2)
- (modified) llvm/test/Transforms/InstCombine/fold-select-fmul-if-zero.ll (+2-2)
``````````diff
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
index 380cb3504209d3..85960660e6ab06 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<Intrinsic::copysign>(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 42e3f34d126d66..f1ae2e74ac2e4e 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]], <half 0xH7C00, half 0xH7C00>
+; CHECK-NEXT: [[AND:%.*]] = fcmp oeq <2 x half> [[FABS_X]], <half 0xH7C00, half 0xH7C00>
; 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
new file mode 100644
index 00000000000000..2fd397a9be36c2
--- /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 one 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 ord half [[X]], 0xH0000
+; 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 oeq 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 une 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 uno half [[X]], 0xH0000
+; 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 ueq 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 oeq 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 one 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 ord half [[X]], 0xH0000
+; 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 uno half [[X]], 0xH0000
+; 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 ueq 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 une 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 one 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 oeq 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
+}
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 ea056de3f8ee71..24dac97672f71a 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 607b12b03b2a12..a7adcd1ac61e7f 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:%.*]]
;
``````````
</details>
https://github.com/llvm/llvm-project/pull/80986
More information about the llvm-commits
mailing list