Hi, This patch implemented optab_isinf for SFDF and IEEE128 by test data class instructions.
Compared with previous version, the main changes are: 1 Define 3 mode attributes which are used for predicate, constraint and asm print selection. They help merge sp/dp/qp patterns to one. 2 Remove original sp/dp and qp patterns and combine them into one. 3 Rename corresponding icode name in rs6000-builtin.cc and rs6000-builtins.def. https://gcc.gnu.org/pipermail/gcc-patches/2024-June/655779.html The expand "isinf<mode>2" and following insn pattern for TF and KF mode should be guarded on "TARGET_FLOAT128_HW". It will be changed in sequential patch as some other "qp" insn patterns are also need to be changed. Bootstrapped and tested on powerpc64-linux BE and LE with no regressions. Is it OK for trunk? Thanks Gui Haochen ChangeLog rs6000: Implement optab_isinf for SFDF and IEEE128 gcc/ PR target/97786 * config/rs6000/rs6000.md (constant VSX_TEST_DATA_CLASS_NAN, VSX_TEST_DATA_CLASS_POS_INF, VSX_TEST_DATA_CLASS_NEG_INF, VSX_TEST_DATA_CLASS_POS_ZERO, VSX_TEST_DATA_CLASS_NEG_ZERO, VSX_TEST_DATA_CLASS_POS_DENORMAL, VSX_TEST_DATA_CLASS_NEG_DENORMAL): Define. (mode_attr sdq, vsx_altivec, wa_v, x): Define. (mode_iterator IEEE_FP): Define. * config/rs6000/vsx.md (isinf<mode>2): New expand. (expand xststdcqp_<mode>, xststdc<sd>p): Combine into... (expand xststdc_<mode>): ...this. (insn *xststdcqp_<mode>, *xststdc<sd>p): Combine into... (insn *xststdc_<mode>): ...this. * config/rs6000/rs6000-builtin.cc (rs6000_expand_builtin): Rename CODE_FOR_xststdcqp_kf as CODE_FOR_xststdc_kf, CODE_FOR_xststdcqp_tf as CODE_FOR_xststdc_tf. * config/rs6000/rs6000-builtins.def: Rename xststdcdp as xststdc_df, xststdcsp as xststdc_sf, xststdcqp_kf as xststdc_kf. gcc/testsuite/ PR target/97786 * gcc.target/powerpc/pr97786-1.c: New test. * gcc.target/powerpc/pr97786-2.c: New test. patch.diff diff --git a/gcc/config/rs6000/rs6000-builtin.cc b/gcc/config/rs6000/rs6000-builtin.cc index bb9da68edc7..a62a5d4afa7 100644 --- a/gcc/config/rs6000/rs6000-builtin.cc +++ b/gcc/config/rs6000/rs6000-builtin.cc @@ -3357,8 +3357,8 @@ rs6000_expand_builtin (tree exp, rtx target, rtx /* subtarget */, case CODE_FOR_xsiexpqpf_kf: icode = CODE_FOR_xsiexpqpf_tf; break; - case CODE_FOR_xststdcqp_kf: - icode = CODE_FOR_xststdcqp_tf; + case CODE_FOR_xststdc_kf: + icode = CODE_FOR_xststdc_tf; break; case CODE_FOR_xscmpexpqp_eq_kf: icode = CODE_FOR_xscmpexpqp_eq_tf; diff --git a/gcc/config/rs6000/rs6000-builtins.def b/gcc/config/rs6000/rs6000-builtins.def index 3bc7fed6956..8ac4cc200c9 100644 --- a/gcc/config/rs6000/rs6000-builtins.def +++ b/gcc/config/rs6000/rs6000-builtins.def @@ -2752,11 +2752,11 @@ const signed int \ __builtin_vsx_scalar_test_data_class_dp (double, const int<7>); - VSTDCDP xststdcdp {} + VSTDCDP xststdc_df {} const signed int \ __builtin_vsx_scalar_test_data_class_sp (float, const int<7>); - VSTDCSP xststdcsp {} + VSTDCSP xststdc_sf {} const signed int __builtin_vsx_scalar_test_neg_dp (double); VSTDCNDP xststdcnegdp {} @@ -2925,7 +2925,7 @@ const signed int __builtin_vsx_scalar_test_data_class_qp (_Float128, \ const int<7>); - VSTDCQP xststdcqp_kf {} + VSTDCQP xststdc_kf {} const signed int __builtin_vsx_scalar_test_neg_qp (_Float128); VSTDCNQP xststdcnegqp_kf {} diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md index a5d20594789..2d7f227e362 100644 --- a/gcc/config/rs6000/rs6000.md +++ b/gcc/config/rs6000/rs6000.md @@ -53,6 +53,20 @@ (define_constants (FRAME_POINTER_REGNUM 110) ]) +;; +;; Test data class mask +;; + +(define_constants + [(VSX_TEST_DATA_CLASS_NAN 0x40) + (VSX_TEST_DATA_CLASS_POS_INF 0x20) + (VSX_TEST_DATA_CLASS_NEG_INF 0x10) + (VSX_TEST_DATA_CLASS_POS_ZERO 0x8) + (VSX_TEST_DATA_CLASS_NEG_ZERO 0x4) + (VSX_TEST_DATA_CLASS_POS_DENORMAL 0x2) + (VSX_TEST_DATA_CLASS_NEG_DENORMAL 0x1) + ]) + ;; ;; UNSPEC usage ;; @@ -605,6 +619,24 @@ (define_mode_iterator SFDF2 [SF DF]) (define_mode_attr sd [(SF "s") (DF "d") (V4SF "s") (V2DF "d")]) +; A generic s/d/q attribute, for sp/dp/qp for example. +(define_mode_attr sdq [(SF "s") (DF "d") + (TF "q") (KF "q")]) + +; A predicate attribute, for IEEE floating point +(define_mode_attr vsx_altivec [(SF "vsx_register_operand") + (DF "vsx_register_operand") + (TF "altivec_register_operand") + (KF "altivec_register_operand")]) + +; A constraint attribute, for IEEE floating point +(define_mode_attr wa_v [(SF "wa") (DF "wa") + (TF "v") (KF "v")]) + +; A register attribute, for IEEE floating point +(define_mode_attr x [(SF "x") (DF "x") + (TF "") (KF "")]) + ; "s" or nothing, for fmuls/fmul for example. (define_mode_attr s [(SF "s") (DF "")]) @@ -616,6 +648,9 @@ (define_mode_iterator IBM128 [(IF "FLOAT128_IBM_P (IFmode)") (define_mode_iterator IEEE128 [(KF "FLOAT128_IEEE_P (KFmode)") (TF "FLOAT128_IEEE_P (TFmode)")]) +; Iterator for IEEE floating point +(define_mode_iterator IEEE_FP [SFDF IEEE128]) + ; Iterator for 128-bit floating point (define_mode_iterator FLOAT128 [(KF "TARGET_FLOAT128_TYPE") (IF "TARGET_FLOAT128_TYPE") diff --git a/gcc/config/rs6000/vsx.md b/gcc/config/rs6000/vsx.md index 48ba262f7e4..56d1d8c737e 100644 --- a/gcc/config/rs6000/vsx.md +++ b/gcc/config/rs6000/vsx.md @@ -5300,36 +5300,15 @@ (define_insn "*xscmpexpqp" "xscmpexpqp %0,%1,%2" [(set_attr "type" "fpcompare")]) -;; VSX Scalar Test Data Class Quad-Precision -;; (Expansion for scalar_test_data_class (__ieee128, int)) -;; (Has side effect of setting the lt bit if operand 1 is negative, -;; setting the eq bit if any of the conditions tested by operand 2 -;; are satisfied, and clearing the gt and undordered bits to zero.) -(define_expand "xststdcqp_<mode>" - [(set (match_dup 3) - (compare:CCFP - (unspec:IEEE128 - [(match_operand:IEEE128 1 "altivec_register_operand" "v") - (match_operand:SI 2 "u7bit_cint_operand" "n")] - UNSPEC_VSX_STSTDC) - (const_int 0))) - (set (match_operand:SI 0 "register_operand" "=r") - (eq:SI (match_dup 3) - (const_int 0)))] - "TARGET_P9_VECTOR" -{ - operands[3] = gen_reg_rtx (CCFPmode); -}) - -;; VSX Scalar Test Data Class Double- and Single-Precision +;; VSX Scalar Test Data Class Quad-/Double-/Single-Precision ;; (The lt bit is set if operand 1 is negative. The eq bit is set ;; if any of the conditions tested by operand 2 are satisfied. ;; The gt and unordered bits are cleared to zero.) -(define_expand "xststdc<sd>p" +(define_expand "xststdc_<mode>" [(set (match_dup 3) (compare:CCFP - (unspec:SFDF - [(match_operand:SFDF 1 "vsx_register_operand" "wa") + (unspec:IEEE_FP + [(match_operand:IEEE_FP 1 "<vsx_altivec>" "<wa_v>") (match_operand:SI 2 "u7bit_cint_operand" "n")] UNSPEC_VSX_STSTDC) (match_dup 4))) @@ -5342,6 +5321,16 @@ (define_expand "xststdc<sd>p" operands[4] = CONST0_RTX (SImode); }) +(define_expand "isinf<mode>2" + [(use (match_operand:SI 0 "gpc_reg_operand")) + (use (match_operand:IEEE_FP 1 "<vsx_altivec>"))] + "TARGET_HARD_FLOAT && TARGET_P9_VECTOR" +{ + int mask = VSX_TEST_DATA_CLASS_POS_INF | VSX_TEST_DATA_CLASS_NEG_INF; + emit_insn (gen_xststdc_<mode> (operands[0], operands[1], GEN_INT (mask))); + DONE; +}) + ;; The VSX Scalar Test Negative Quad-Precision (define_expand "xststdcnegqp_<mode>" [(set (match_dup 2) @@ -5377,27 +5366,16 @@ (define_expand "xststdcneg<sd>p" operands[3] = CONST0_RTX (SImode); }) -(define_insn "*xststdcqp_<mode>" +(define_insn "*xststdc_<mode>" [(set (match_operand:CCFP 0 "" "=y") (compare:CCFP - (unspec:IEEE128 - [(match_operand:IEEE128 1 "altivec_register_operand" "v") + (unspec:IEEE_FP + [(match_operand:IEEE_FP 1 "<vsx_altivec>" "<wa_v>") (match_operand:SI 2 "u7bit_cint_operand" "n")] UNSPEC_VSX_STSTDC) (const_int 0)))] "TARGET_P9_VECTOR" - "xststdcqp %0,%1,%2" - [(set_attr "type" "fpcompare")]) - -(define_insn "*xststdc<sd>p" - [(set (match_operand:CCFP 0 "" "=y") - (compare:CCFP - (unspec:SFDF [(match_operand:SFDF 1 "vsx_register_operand" "wa") - (match_operand:SI 2 "u7bit_cint_operand" "n")] - UNSPEC_VSX_STSTDC) - (match_operand:SI 3 "zero_constant" "j")))] - "TARGET_P9_VECTOR" - "xststdc<sd>p %0,%x1,%2" + "xststdc<sdq>p %0,%<x>1,%2" [(set_attr "type" "fpcompare")]) ;; VSX Vector Extract Exponent Double and Single Precision diff --git a/gcc/testsuite/gcc.target/powerpc/pr97786-1.c b/gcc/testsuite/gcc.target/powerpc/pr97786-1.c new file mode 100644 index 00000000000..3951770f65b --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/pr97786-1.c @@ -0,0 +1,22 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -mdejagnu-cpu=power9" } */ +/* { dg-require-effective-target powerpc_vsx } */ + +int test1 (double x) +{ + return __builtin_isinf (x); +} + +int test2 (float x) +{ + return __builtin_isinf (x); +} + +int test3 (float x) +{ + return __builtin_isinff (x); +} + +/* { dg-final { scan-assembler-not {\mfcmp} } } */ +/* { dg-final { scan-assembler-times {\mxststdcsp\M} 2 } } */ +/* { dg-final { scan-assembler-times {\mxststdcdp\M} 1 } } */ diff --git a/gcc/testsuite/gcc.target/powerpc/pr97786-2.c b/gcc/testsuite/gcc.target/powerpc/pr97786-2.c new file mode 100644 index 00000000000..cea2d0dd48e --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/pr97786-2.c @@ -0,0 +1,17 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target ppc_float128_hw } */ +/* { dg-options "-O2 -mdejagnu-cpu=power9 -mabi=ieeelongdouble -Wno-psabi" } */ +/* { dg-require-effective-target powerpc_vsx } */ + +int test1 (long double x) +{ + return __builtin_isinf (x); +} + +int test2 (long double x) +{ + return __builtin_isinfl (x); +} + +/* { dg-final { scan-assembler-not {\mxscmpuqp\M} } } */ +/* { dg-final { scan-assembler-times {\mxststdcqp\M} 2 } } */