diff --git a/llvm/test/Transforms/InstCombine/unordered-compare-and-ordered.ll b/llvm/test/Transforms/InstCombine/unordered-compare-and-ordered.ll new file mode 100644 index 0000000000000..36d7eb9ea70a4 --- /dev/null +++ b/llvm/test/Transforms/InstCombine/unordered-compare-and-ordered.ll @@ -0,0 +1,502 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt -S -passes=instcombine < %s | FileCheck %s + +define i1 @fcmp_ord_and_uno(half %x, half %y) { +; CHECK-LABEL: @fcmp_ord_and_uno( +; CHECK-NEXT: [[ORD:%.*]] = fcmp ord half [[X:%.*]], 0xH0000 +; CHECK-NEXT: [[UNO:%.*]] = fcmp uno half [[X]], [[Y:%.*]] +; CHECK-NEXT: [[AND:%.*]] = and i1 [[ORD]], [[UNO]] +; CHECK-NEXT: ret i1 [[AND]] +; + %ord = fcmp ord half %x, 0.0 + %uno = fcmp uno half %x, %y + %and = and i1 %ord, %uno + ret i1 %and +} + +define i1 @fcmp_ord_and_ueq(half %x, half %y) { +; CHECK-LABEL: @fcmp_ord_and_ueq( +; CHECK-NEXT: [[ORD:%.*]] = fcmp ord half [[X:%.*]], 0xH0000 +; CHECK-NEXT: [[UEQ:%.*]] = fcmp ueq half [[X]], [[Y:%.*]] +; CHECK-NEXT: [[AND:%.*]] = and i1 [[ORD]], [[UEQ]] +; CHECK-NEXT: ret i1 [[AND]] +; + %ord = fcmp ord half %x, 0.0 + %ueq = fcmp ueq half %x, %y + %and = and i1 %ord, %ueq + ret i1 %and +} + +define i1 @fcmp_ord_and_ugt(half %x, half %y) { +; CHECK-LABEL: @fcmp_ord_and_ugt( +; CHECK-NEXT: [[ORD:%.*]] = fcmp ord half [[X:%.*]], 0xH0000 +; CHECK-NEXT: [[UGT:%.*]] = fcmp ugt half [[X]], [[Y:%.*]] +; CHECK-NEXT: [[AND:%.*]] = and i1 [[ORD]], [[UGT]] +; CHECK-NEXT: ret i1 [[AND]] +; + %ord = fcmp ord half %x, 0.0 + %ugt = fcmp ugt half %x, %y + %and = and i1 %ord, %ugt + ret i1 %and +} + +define i1 @fcmp_ord_and_uge(half %x, half %y) { +; CHECK-LABEL: @fcmp_ord_and_uge( +; CHECK-NEXT: [[ORD:%.*]] = fcmp ord half [[X:%.*]], 0xH0000 +; CHECK-NEXT: [[UGE:%.*]] = fcmp uge half [[X]], [[Y:%.*]] +; CHECK-NEXT: [[AND:%.*]] = and i1 [[ORD]], [[UGE]] +; CHECK-NEXT: ret i1 [[AND]] +; + %ord = fcmp ord half %x, 0.0 + %uge = fcmp uge half %x, %y + %and = and i1 %ord, %uge + ret i1 %and +} + +define i1 @fcmp_ord_and_ult(half %x, half %y) { +; CHECK-LABEL: @fcmp_ord_and_ult( +; CHECK-NEXT: [[ORD:%.*]] = fcmp ord half [[X:%.*]], 0xH0000 +; CHECK-NEXT: [[ULT:%.*]] = fcmp ult half [[X]], [[Y:%.*]] +; CHECK-NEXT: [[AND:%.*]] = and i1 [[ORD]], [[ULT]] +; CHECK-NEXT: ret i1 [[AND]] +; + %ord = fcmp ord half %x, 0.0 + %ult = fcmp ult half %x, %y + %and = and i1 %ord, %ult + ret i1 %and +} + +define i1 @fcmp_ord_and_ule(half %x, half %y) { +; CHECK-LABEL: @fcmp_ord_and_ule( +; CHECK-NEXT: [[ORD:%.*]] = fcmp ord half [[X:%.*]], 0xH0000 +; CHECK-NEXT: [[ULE:%.*]] = fcmp ule half [[X]], [[Y:%.*]] +; CHECK-NEXT: [[AND:%.*]] = and i1 [[ORD]], [[ULE]] +; CHECK-NEXT: ret i1 [[AND]] +; + %ord = fcmp ord half %x, 0.0 + %ule = fcmp ule half %x, %y + %and = and i1 %ord, %ule + ret i1 %and +} + +define i1 @fcmp_ord_and_une(half %x, half %y) { +; CHECK-LABEL: @fcmp_ord_and_une( +; CHECK-NEXT: [[ORD:%.*]] = fcmp ord half [[X:%.*]], 0xH0000 +; CHECK-NEXT: [[UNE:%.*]] = fcmp une half [[X]], [[Y:%.*]] +; CHECK-NEXT: [[AND:%.*]] = and i1 [[ORD]], [[UNE]] +; CHECK-NEXT: ret i1 [[AND]] +; + %ord = fcmp ord half %x, 0.0 + %une = fcmp une half %x, %y + %and = and i1 %ord, %une + ret i1 %and +} + +define i1 @fcmp_ord_and_true(half %x, half %y) { +; CHECK-LABEL: @fcmp_ord_and_true( +; CHECK-NEXT: [[UNE:%.*]] = fcmp une half [[X:%.*]], [[Y:%.*]] +; CHECK-NEXT: ret i1 [[UNE]] +; + %ord = fcmp true half %x, 0.0 + %une = fcmp une half %x, %y + %and = and i1 %ord, %une + ret i1 %and +} + +define <2 x i1> @fcmp_ord_and_ueq_vector(<2 x half> %x, <2 x half> %y) { +; CHECK-LABEL: @fcmp_ord_and_ueq_vector( +; CHECK-NEXT: [[ORD:%.*]] = fcmp ord <2 x half> [[X:%.*]], zeroinitializer +; CHECK-NEXT: [[UEQ:%.*]] = fcmp ueq <2 x half> [[X]], [[Y:%.*]] +; CHECK-NEXT: [[AND:%.*]] = and <2 x i1> [[ORD]], [[UEQ]] +; CHECK-NEXT: ret <2 x i1> [[AND]] +; + %ord = fcmp ord <2 x half> %x, zeroinitializer + %ueq = fcmp ueq <2 x half> %x, %y + %and = and <2 x i1> %ord, %ueq + ret <2 x i1> %and +} + +; Negative test +define i1 @fcmp_ord_and_ueq_different_value0(half %x, half %y, half %z) { +; CHECK-LABEL: @fcmp_ord_and_ueq_different_value0( +; CHECK-NEXT: [[ORD:%.*]] = fcmp ord half [[X:%.*]], 0xH0000 +; CHECK-NEXT: [[UEQ:%.*]] = fcmp ueq half [[Z:%.*]], [[Y:%.*]] +; CHECK-NEXT: [[AND:%.*]] = and i1 [[ORD]], [[UEQ]] +; CHECK-NEXT: ret i1 [[AND]] +; + %ord = fcmp ord half %x, 0.0 + %ueq = fcmp ueq half %z, %y + %and = and i1 %ord, %ueq + ret i1 %and +} + +; Negative test +define i1 @fcmp_ord_and_ueq_different_value1(half %x, half %y, half %z) { +; CHECK-LABEL: @fcmp_ord_and_ueq_different_value1( +; CHECK-NEXT: [[ORD:%.*]] = fcmp ord half [[X:%.*]], 0xH0000 +; CHECK-NEXT: [[UEQ:%.*]] = fcmp ueq half [[Y:%.*]], [[Z:%.*]] +; CHECK-NEXT: [[AND:%.*]] = and i1 [[ORD]], [[UEQ]] +; CHECK-NEXT: ret i1 [[AND]] +; + %ord = fcmp ord half %x, 0.0 + %ueq = fcmp ueq half %y, %z + %and = and i1 %ord, %ueq + ret i1 %and +} + +declare half @foo() + +define i1 @fcmp_ord_and_ueq_commute0() { +; CHECK-LABEL: @fcmp_ord_and_ueq_commute0( +; CHECK-NEXT: [[X:%.*]] = call half @foo() +; CHECK-NEXT: [[Y:%.*]] = call half @foo() +; CHECK-NEXT: [[ORD:%.*]] = fcmp ord half [[X]], 0xH0000 +; CHECK-NEXT: [[UEQ:%.*]] = fcmp ueq half [[X]], [[Y]] +; CHECK-NEXT: [[AND:%.*]] = and i1 [[UEQ]], [[ORD]] +; CHECK-NEXT: ret i1 [[AND]] +; + %x = call half @foo() + %y = call half @foo() + %ord = fcmp ord half %x, 0.0 + %ueq = fcmp ueq half %x, %y + %and = and i1 %ueq, %ord + ret i1 %and +} + +define i1 @fcmp_ord_and_ueq_commute1() { +; CHECK-LABEL: @fcmp_ord_and_ueq_commute1( +; CHECK-NEXT: [[X:%.*]] = call half @foo() +; CHECK-NEXT: [[Y:%.*]] = call half @foo() +; CHECK-NEXT: [[ORD:%.*]] = fcmp ord half [[X]], 0xH0000 +; CHECK-NEXT: [[UEQ:%.*]] = fcmp ueq half [[X]], [[Y]] +; CHECK-NEXT: [[AND:%.*]] = and i1 [[ORD]], [[UEQ]] +; CHECK-NEXT: ret i1 [[AND]] +; + %x = call half @foo() + %y = call half @foo() + %ord = fcmp ord half %x, 0.0 + %ueq = fcmp ueq half %x, %y + %and = and i1 %ord, %ueq + ret i1 %and +} + +define i1 @fcmp_oeq_x_x_and_ult(half %x, half %y) { +; CHECK-LABEL: @fcmp_oeq_x_x_and_ult( +; CHECK-NEXT: [[ORD:%.*]] = fcmp ord half [[X:%.*]], 0xH0000 +; CHECK-NEXT: [[ULT:%.*]] = fcmp ult half [[X]], [[Y:%.*]] +; CHECK-NEXT: [[AND:%.*]] = and i1 [[ORD]], [[ULT]] +; CHECK-NEXT: ret i1 [[AND]] +; + %ord = fcmp oeq half %x, %x ; noncanonical ordered + %ult = fcmp ult half %x, %y + %and = and i1 %ord, %ult + ret i1 %and +} + +define i1 @fcmp_ord_and_ueq_preserve_flags(half %x, half %y) { +; CHECK-LABEL: @fcmp_ord_and_ueq_preserve_flags( +; CHECK-NEXT: [[ORD:%.*]] = fcmp nsz ord half [[X:%.*]], 0xH0000 +; CHECK-NEXT: [[UEQ:%.*]] = fcmp nsz ueq half [[X]], [[Y:%.*]] +; CHECK-NEXT: [[AND:%.*]] = and i1 [[ORD]], [[UEQ]] +; CHECK-NEXT: ret i1 [[AND]] +; + %ord = fcmp nsz ord half %x, 0.0 + %ueq = fcmp nsz ueq half %x, %y + %and = and i1 %ord, %ueq + ret i1 %and +} + +define i1 @fcmp_ord_and_ueq_preserve_subset_flags0(half %x, half %y) { +; CHECK-LABEL: @fcmp_ord_and_ueq_preserve_subset_flags0( +; CHECK-NEXT: [[ORD:%.*]] = fcmp nsz ord half [[X:%.*]], 0xH0000 +; CHECK-NEXT: [[UEQ:%.*]] = fcmp ninf nsz ueq half [[X]], [[Y:%.*]] +; CHECK-NEXT: [[AND:%.*]] = and i1 [[ORD]], [[UEQ]] +; CHECK-NEXT: ret i1 [[AND]] +; + %ord = fcmp nsz ord half %x, 0.0 + %ueq = fcmp ninf nsz ueq half %x, %y + %and = and i1 %ord, %ueq + ret i1 %and +} + +define i1 @fcmp_ord_and_ueq_preserve_subset_flags1(half %x, half %y) { +; CHECK-LABEL: @fcmp_ord_and_ueq_preserve_subset_flags1( +; CHECK-NEXT: [[ORD:%.*]] = fcmp ninf nsz ord half [[X:%.*]], 0xH0000 +; CHECK-NEXT: [[UEQ:%.*]] = fcmp nsz ueq half [[X]], [[Y:%.*]] +; CHECK-NEXT: [[AND:%.*]] = and i1 [[ORD]], [[UEQ]] +; CHECK-NEXT: ret i1 [[AND]] +; + %ord = fcmp ninf nsz ord half %x, 0.0 + %ueq = fcmp nsz ueq half %x, %y + %and = and i1 %ord, %ueq + ret i1 %and +} + +define i1 @fcmp_ord_and_ueq_flags_lhs(half %x, half %y) { +; CHECK-LABEL: @fcmp_ord_and_ueq_flags_lhs( +; CHECK-NEXT: [[ORD:%.*]] = fcmp nsz ord half [[X:%.*]], 0xH0000 +; CHECK-NEXT: [[UEQ:%.*]] = fcmp ueq half [[X]], [[Y:%.*]] +; CHECK-NEXT: [[AND:%.*]] = and i1 [[ORD]], [[UEQ]] +; CHECK-NEXT: ret i1 [[AND]] +; + %ord = fcmp nsz ord half %x, 0.0 + %ueq = fcmp ueq half %x, %y + %and = and i1 %ord, %ueq + ret i1 %and +} + +define i1 @fcmp_ord_and_ueq_flags_rhs(half %x, half %y) { +; CHECK-LABEL: @fcmp_ord_and_ueq_flags_rhs( +; CHECK-NEXT: [[ORD:%.*]] = fcmp ord half [[X:%.*]], 0xH0000 +; CHECK-NEXT: [[UEQ:%.*]] = fcmp nsz ueq half [[X]], [[Y:%.*]] +; CHECK-NEXT: [[AND:%.*]] = and i1 [[ORD]], [[UEQ]] +; CHECK-NEXT: ret i1 [[AND]] +; + %ord = fcmp ord half %x, 0.0 + %ueq = fcmp nsz ueq half %x, %y + %and = and i1 %ord, %ueq + ret i1 %and +} + +; Can ignore fabs and fneg +define i1 @fcmp_ord_and_fabs_ueq(half %x, half %y) { +; CHECK-LABEL: @fcmp_ord_and_fabs_ueq( +; CHECK-NEXT: [[FABS_X:%.*]] = call half @llvm.fabs.f16(half [[X:%.*]]) +; CHECK-NEXT: [[ORD:%.*]] = fcmp ord half [[X]], 0xH0000 +; CHECK-NEXT: [[UEQ:%.*]] = fcmp ueq half [[FABS_X]], [[Y:%.*]] +; CHECK-NEXT: [[AND:%.*]] = and i1 [[ORD]], [[UEQ]] +; CHECK-NEXT: ret i1 [[AND]] +; + %fabs.x = call half @llvm.fabs.f16(half %x) + %ord = fcmp ord half %x, 0.0 + %ueq = fcmp ueq half %fabs.x, %y + %and = and i1 %ord, %ueq + ret i1 %and +} + +define i1 @fcmp_ord_fabs_and_ueq(half %x, half %y) { +; CHECK-LABEL: @fcmp_ord_fabs_and_ueq( +; CHECK-NEXT: [[ORD:%.*]] = fcmp ord half [[X:%.*]], 0xH0000 +; CHECK-NEXT: [[UEQ:%.*]] = fcmp ueq half [[X]], [[Y:%.*]] +; CHECK-NEXT: [[AND:%.*]] = and i1 [[ORD]], [[UEQ]] +; CHECK-NEXT: ret i1 [[AND]] +; + %fabs.x = call half @llvm.fabs.f16(half %x) + %ord = fcmp ord half %fabs.x, 0.0 + %ueq = fcmp ueq half %x, %y + %and = and i1 %ord, %ueq + ret i1 %and +} + +define i1 @fcmp_ord_and_fabs_ueq_commute0() { +; CHECK-LABEL: @fcmp_ord_and_fabs_ueq_commute0( +; CHECK-NEXT: [[X:%.*]] = call half @foo() +; CHECK-NEXT: [[Y:%.*]] = call half @foo() +; CHECK-NEXT: [[FABS_X:%.*]] = call half @llvm.fabs.f16(half [[X]]) +; CHECK-NEXT: [[ORD:%.*]] = fcmp ord half [[X]], 0xH0000 +; CHECK-NEXT: [[UEQ:%.*]] = fcmp ueq half [[Y]], [[FABS_X]] +; CHECK-NEXT: [[AND:%.*]] = and i1 [[ORD]], [[UEQ]] +; CHECK-NEXT: ret i1 [[AND]] +; + %x = call half @foo() + %y = call half @foo() + %fabs.x = call half @llvm.fabs.f16(half %x) + %ord = fcmp ord half %x, 0.0 + %ueq = fcmp ueq half %y, %fabs.x + %and = and i1 %ord, %ueq + ret i1 %and +} + +define i1 @fcmp_ord_and_fabs_ueq_commute1() { +; CHECK-LABEL: @fcmp_ord_and_fabs_ueq_commute1( +; CHECK-NEXT: [[X:%.*]] = call half @foo() +; CHECK-NEXT: [[Y:%.*]] = call half @foo() +; CHECK-NEXT: [[FABS_X:%.*]] = call half @llvm.fabs.f16(half [[X]]) +; CHECK-NEXT: [[ORD:%.*]] = fcmp ord half [[X]], 0xH0000 +; CHECK-NEXT: [[UEQ:%.*]] = fcmp ueq half [[Y]], [[FABS_X]] +; CHECK-NEXT: [[AND:%.*]] = and i1 [[UEQ]], [[ORD]] +; CHECK-NEXT: ret i1 [[AND]] +; + %x = call half @foo() + %y = call half @foo() + %fabs.x = call half @llvm.fabs.f16(half %x) + %ord = fcmp ord half %x, 0.0 + %ueq = fcmp ueq half %y, %fabs.x + %and = and i1 %ueq, %ord + ret i1 %and +} + +define <2 x i1> @fcmp_ord_and_fabs_ueq_vector(<2 x half> %x, <2 x half> %y) { +; CHECK-LABEL: @fcmp_ord_and_fabs_ueq_vector( +; CHECK-NEXT: [[FABS_X:%.*]] = call <2 x half> @llvm.fabs.v2f16(<2 x half> [[X:%.*]]) +; CHECK-NEXT: [[ORD:%.*]] = fcmp ord <2 x half> [[X]], zeroinitializer +; CHECK-NEXT: [[UEQ:%.*]] = fcmp ueq <2 x half> [[FABS_X]], [[Y:%.*]] +; CHECK-NEXT: [[AND:%.*]] = and <2 x i1> [[ORD]], [[UEQ]] +; CHECK-NEXT: ret <2 x i1> [[AND]] +; + %fabs.x = call <2 x half> @llvm.fabs.v2f16(<2 x half> %x) + %ord = fcmp ord <2 x half> %x, zeroinitializer + %ueq = fcmp ueq <2 x half> %fabs.x, %y + %and = and <2 x i1> %ord, %ueq + ret <2 x i1> %and +} + +define i1 @fcmp_ord_fabs_and_fabs_ueq(half %x, half %y) { +; CHECK-LABEL: @fcmp_ord_fabs_and_fabs_ueq( +; CHECK-NEXT: [[FABS_X:%.*]] = call half @llvm.fabs.f16(half [[X:%.*]]) +; CHECK-NEXT: [[ORD:%.*]] = fcmp ord half [[X]], 0xH0000 +; CHECK-NEXT: [[UEQ:%.*]] = fcmp ueq half [[FABS_X]], [[Y:%.*]] +; CHECK-NEXT: [[AND:%.*]] = and i1 [[ORD]], [[UEQ]] +; CHECK-NEXT: ret i1 [[AND]] +; + %fabs.x = call half @llvm.fabs.f16(half %x) + %ord = fcmp ord half %fabs.x, 0.0 + %ueq = fcmp ueq half %fabs.x, %y + %and = and i1 %ord, %ueq + ret i1 %and +} + +define i1 @fcmp_ord_and_fneg_ueq(half %x, half %y) { +; CHECK-LABEL: @fcmp_ord_and_fneg_ueq( +; CHECK-NEXT: [[FNEG_X:%.*]] = fneg half [[X:%.*]] +; CHECK-NEXT: [[ORD:%.*]] = fcmp ord half [[X]], 0xH0000 +; CHECK-NEXT: [[UEQ:%.*]] = fcmp ueq half [[FNEG_X]], [[Y:%.*]] +; CHECK-NEXT: [[AND:%.*]] = and i1 [[ORD]], [[UEQ]] +; CHECK-NEXT: ret i1 [[AND]] +; + %fneg.x = fneg half %x + %ord = fcmp ord half %x, 0.0 + %ueq = fcmp ueq half %fneg.x, %y + %and = and i1 %ord, %ueq + ret i1 %and +} + +define i1 @fcmp_ord_fneg_and_ueq(half %x, half %y) { +; CHECK-LABEL: @fcmp_ord_fneg_and_ueq( +; CHECK-NEXT: [[ORD:%.*]] = fcmp ord half [[X:%.*]], 0xH0000 +; CHECK-NEXT: [[UEQ:%.*]] = fcmp ueq half [[X]], [[Y:%.*]] +; CHECK-NEXT: [[AND:%.*]] = and i1 [[ORD]], [[UEQ]] +; CHECK-NEXT: ret i1 [[AND]] +; + %fneg.x = fneg half %x + %ord = fcmp ord half %fneg.x, 0.0 + %ueq = fcmp ueq half %x, %y + %and = and i1 %ord, %ueq + ret i1 %and +} + +define i1 @fcmp_ord_fneg_and_fneg_ueq(half %x, half %y) { +; CHECK-LABEL: @fcmp_ord_fneg_and_fneg_ueq( +; CHECK-NEXT: [[FNEG_X:%.*]] = fneg half [[X:%.*]] +; CHECK-NEXT: [[ORD:%.*]] = fcmp ord half [[X]], 0xH0000 +; CHECK-NEXT: [[UEQ:%.*]] = fcmp ueq half [[FNEG_X]], [[Y:%.*]] +; CHECK-NEXT: [[AND:%.*]] = and i1 [[ORD]], [[UEQ]] +; CHECK-NEXT: ret i1 [[AND]] +; + %fneg.x = fneg half %x + %ord = fcmp ord half %fneg.x, 0.0 + %ueq = fcmp ueq half %fneg.x, %y + %and = and i1 %ord, %ueq + ret i1 %and +} + +define i1 @fcmp_ord_and_fneg_fabs_ueq(half %x, half %y) { +; CHECK-LABEL: @fcmp_ord_and_fneg_fabs_ueq( +; CHECK-NEXT: [[FABS_X:%.*]] = call half @llvm.fabs.f16(half [[X:%.*]]) +; CHECK-NEXT: [[FNEG_FABS_X:%.*]] = fneg half [[FABS_X]] +; CHECK-NEXT: [[ORD:%.*]] = fcmp ord half [[X]], 0xH0000 +; CHECK-NEXT: [[UEQ:%.*]] = fcmp ueq half [[FNEG_FABS_X]], [[Y:%.*]] +; CHECK-NEXT: [[AND:%.*]] = and i1 [[ORD]], [[UEQ]] +; CHECK-NEXT: ret i1 [[AND]] +; + %fabs.x = call half @llvm.fabs.f16(half %x) + %fneg.fabs.x = fneg half %fabs.x + %ord = fcmp ord half %x, 0.0 + %ueq = fcmp ueq half %fneg.fabs.x, %y + %and = and i1 %ord, %ueq + ret i1 %and +} + +define i1 @fcmp_ord_and_copysign_ueq(half %x, half %y, half %z) { +; CHECK-LABEL: @fcmp_ord_and_copysign_ueq( +; CHECK-NEXT: [[COPYSIGN_X_Y:%.*]] = call half @llvm.copysign.f16(half [[X:%.*]], half [[Z:%.*]]) +; CHECK-NEXT: [[ORD:%.*]] = fcmp ord half [[X]], 0xH0000 +; CHECK-NEXT: [[UEQ:%.*]] = fcmp ueq half [[COPYSIGN_X_Y]], [[Y:%.*]] +; CHECK-NEXT: [[AND:%.*]] = and i1 [[ORD]], [[UEQ]] +; CHECK-NEXT: ret i1 [[AND]] +; + %copysign.x.y = call half @llvm.copysign.f16(half %x, half %z) + %ord = fcmp ord half %x, 0.0 + %ueq = fcmp ueq half %copysign.x.y, %y + %and = and i1 %ord, %ueq + ret i1 %and +} + +define i1 @fcmp_copysign_ord_and_ueq(half %x, half %y, half %z) { +; CHECK-LABEL: @fcmp_copysign_ord_and_ueq( +; CHECK-NEXT: [[COPYSIGN_X_Y:%.*]] = call half @llvm.copysign.f16(half [[X:%.*]], half [[Z:%.*]]) +; CHECK-NEXT: [[ORD:%.*]] = fcmp ord half [[COPYSIGN_X_Y]], 0xH0000 +; CHECK-NEXT: [[UEQ:%.*]] = fcmp ueq half [[X]], [[Y:%.*]] +; CHECK-NEXT: [[AND:%.*]] = and i1 [[ORD]], [[UEQ]] +; CHECK-NEXT: ret i1 [[AND]] +; + %copysign.x.y = call half @llvm.copysign.f16(half %x, half %z) + %ord = fcmp ord half %copysign.x.y, 0.0 + %ueq = fcmp ueq half %x, %y + %and = and i1 %ord, %ueq + ret i1 %and +} + +define i1 @fcmp_ord_and_copysign_ueq_commute(half %x, half %y, half %z) { +; CHECK-LABEL: @fcmp_ord_and_copysign_ueq_commute( +; CHECK-NEXT: [[COPYSIGN_X_Y:%.*]] = call half @llvm.copysign.f16(half [[X:%.*]], half [[Z:%.*]]) +; CHECK-NEXT: [[ORD:%.*]] = fcmp ord half [[X]], 0xH0000 +; CHECK-NEXT: [[UEQ:%.*]] = fcmp ueq half [[COPYSIGN_X_Y]], [[Y:%.*]] +; CHECK-NEXT: [[AND:%.*]] = and i1 [[ORD]], [[UEQ]] +; CHECK-NEXT: ret i1 [[AND]] +; + %copysign.x.y = call half @llvm.copysign.f16(half %x, half %z) + %ord = fcmp ord half %x, 0.0 + %ueq = fcmp ueq half %y, %copysign.x.y + %and = and i1 %ord, %ueq + ret i1 %and +} + +define i1 @fcmp_ord_and_copysign_fneg_ueq(half %x, half %y, half %z) { +; CHECK-LABEL: @fcmp_ord_and_copysign_fneg_ueq( +; CHECK-NEXT: [[COPYSIGN_X_Y:%.*]] = call half @llvm.copysign.f16(half [[X:%.*]], half [[Z:%.*]]) +; CHECK-NEXT: [[ORD:%.*]] = fcmp ord half [[X]], 0xH0000 +; CHECK-NEXT: [[UEQ:%.*]] = fcmp ueq half [[COPYSIGN_X_Y]], [[Y:%.*]] +; CHECK-NEXT: [[AND:%.*]] = and i1 [[ORD]], [[UEQ]] +; CHECK-NEXT: ret i1 [[AND]] +; + %x.fneg = fneg half %x + %copysign.x.y = call half @llvm.copysign.f16(half %x.fneg, half %z) + %ord = fcmp ord half %x, 0.0 + %ueq = fcmp ueq half %copysign.x.y, %y + %and = and i1 %ord, %ueq + ret i1 %and +} + +define i1 @fcmp_ord_and_fneg_copysign_ueq(half %x, half %y, half %z) { +; CHECK-LABEL: @fcmp_ord_and_fneg_copysign_ueq( +; CHECK-NEXT: [[COPYSIGN_X_Y:%.*]] = call half @llvm.copysign.f16(half [[X:%.*]], half [[Z:%.*]]) +; CHECK-NEXT: [[FNEG_COPYSIGN:%.*]] = fneg half [[COPYSIGN_X_Y]] +; CHECK-NEXT: [[ORD:%.*]] = fcmp ord half [[X]], 0xH0000 +; CHECK-NEXT: [[UEQ:%.*]] = fcmp ueq half [[FNEG_COPYSIGN]], [[Y:%.*]] +; CHECK-NEXT: [[AND:%.*]] = and i1 [[ORD]], [[UEQ]] +; CHECK-NEXT: ret i1 [[AND]] +; + %copysign.x.y = call half @llvm.copysign.f16(half %x, half %z) + %fneg.copysign = fneg half %copysign.x.y + %ord = fcmp ord half %x, 0.0 + %ueq = fcmp ueq half %fneg.copysign, %y + %and = and i1 %ord, %ueq + ret i1 %and +} + + +declare half @llvm.fabs.f16(half) +declare <2 x half> @llvm.fabs.v2f16(<2 x half>) +declare half @llvm.copysign.f16(half, half) +declare <2 x half> @llvm.copysign.v2f16(<2 x half>, <2 x half>)