Hi Haochen, on 2024/7/9 15:18, HAO CHEN GUI wrote: > 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
Nit: s/mask/mask bits/ > +;; > + > +(define_constants > + [(VSX_TEST_DATA_CLASS_NAN 0x40) > + (VSX_TEST_DATA_CLASS_POS_INF 0x20) > + (VSX_TEST_DATA_CLASS_NEG_INF 0x10) Formatting nit: Move 0x20 and 0x10 align with the others? > + (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")]) Nit: May be more meaningful with fp_register_op? > + > +; A constraint attribute, for IEEE floating point Nit: Maybe "wa" or "v", for IEEE_FP constraints for example. > +(define_mode_attr wa_v [(SF "wa") (DF "wa") > + (TF "v") (KF "v")]) > + > +; A register attribute, for IEEE floating point Nit: Just follow the existing "s", say: "x" or nothing, for IEEE_FP for example. > +(define_mode_attr x [(SF "x") (DF "x") > + (TF "") (KF "")]) > + Nit: it's would be good to move these three vsx_altivec, wa_v and x to ... > ; "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]) > + ... here, then they can closely follow the relevant IEEE_FP. OK with these nits fixed, thanks! BR, Kewen > ; 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 } } */ > >