| ; 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: [[TMP1:%.*]] = fneg half [[Z:%.*]] |
| ; CHECK-NEXT: [[FNEG_COPYSIGN:%.*]] = call half @llvm.copysign.f16(half [[X:%.*]], half [[TMP1]]) |
| ; 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>) |