Re: [PATCH, rs6000] Implement mffscrni pattern
Hi! On Mon, Dec 20, 2021 at 01:55:51PM +0800, HAO CHEN GUI wrote: > * config/rs6000/rs6000-call.c > (rs6000_expand_set_fpscr_rn_builtin): Not copy argument to a reg if > it's a constant. The pattern for constant can be recognized now. (Two spaces after full stop). > +;; Return 1 if op is an unsigned 2-bit constant integer. > +(define_predicate "u2bit_cint_operand" > + (and (match_code "const_int") > + (match_test "INTVAL (op) >= 0 && INTVAL (op) <= 3"))) Simple project for anyone: use IN_RANGE more :-) > --- a/gcc/config/rs6000/rs6000.md > +++ b/gcc/config/rs6000/rs6000.md > @@ -177,6 +177,7 @@ (define_c_enum "unspecv" > UNSPECV_MFFS ; Move from FPSCR > UNSPECV_MFFSL ; Move from FPSCR light instruction version > UNSPECV_MFFSCRN ; Move from FPSCR float rounding mode > + UNSPECV_MFFSCRNI ; Move from FPSCR float rounding mode with imm Why can this not just use the existing UNSPECV_MFFSCRN? That way, an mffsrcn can automatically morph into an mffscrni if the argument is a constant integer, etc. > @@ -6333,9 +6342,15 @@ (define_expand "rs6000_set_fpscr_rn" > new rounding mode bits from operands[0][62:63] into FPSCR[62:63]. */ >if (TARGET_P9_MISC) > { > - rtx src_df = force_reg (DImode, operands[0]); > - src_df = simplify_gen_subreg (DFmode, src_df, DImode, 0); > - emit_insn (gen_rs6000_mffscrn (tmp_df, src_df)); > + if (CONST_INT_P (operands[0]) > + && const_0_to_3_operand (operands[0], VOIDmode)) const_0_to_3_operand already checks that CONST_INT_P is true (so you do not need to test the latter separately). > @@ -6357,7 +6372,8 @@ (define_expand "rs6000_set_fpscr_rn" >rtx tmp_di = gen_reg_rtx (DImode); > >/* Extract new RN mode from operand. */ > - emit_insn (gen_anddi3 (tmp_rn, operands[0], GEN_INT (0x3))); > + rtx op0 = convert_to_mode (DImode, operands[0], false); > + emit_insn (gen_anddi3 (tmp_rn, op0, GEN_INT (0x3))); Please write 3 as 3. Not as 0x0003, not as 0x03, not as 0x3. I realise you just copied this, but :-) > --- /dev/null > +++ b/gcc/testsuite/gcc.target/powerpc/mffscrni_p9.c > @@ -0,0 +1,9 @@ > +/* { dg-do compile { target { has_arch_pwr9 } } } */ Don't do that? Instead, use -mdejagnu-cpu=power9. This will give more coverage, and also will make us need less future test maintenance (if on Power28 we will generate different code for this, for example). > +void __attribute__ ((noinline)) wrap_set_fpscr_rn (int val) > +{ > + __builtin_set_fpscr_rn (val); > +} Should be noipa, not just noinline? Segher
Re: [PATCH, rs6000] Implement mffscrni pattern
On Mon, Dec 20, 2021 at 12:56 AM HAO CHEN GUI wrote: > > Hi, > I modified the patch according to David and Segher's advice. > > This patch defines a pattern for mffscrni. If the RN is a constant, it can > call > gen_rs6000_mffscrni directly. The "rs6000-builtin-new.def" defines prototype > for builtin arguments. > The pattern "rs6000_set_fpscr_rn" is then broken as the mode of its argument > is DI while its > corresponding builtin has a const int argument. The patch also fixed it. > > Bootstrapped and tested on powerpc64-linux BE and LE with no regressions. > Is this okay for trunk? > Any recommendations? Thanks a lot. > > ChangeLog > 2021-12-17 Haochen Gui > > gcc/ > * config/rs6000/predicates.md (u2bit_cint_operand): Defined. > * config/rs6000/rs6000-call.c > (rs6000_expand_set_fpscr_rn_builtin): Not copy argument to a reg if > it's a constant. The pattern for constant can be recognized now. > * config/rs6000/rs6000.md (UNSPECV_MFFSCRNI): Defined. > (rs6000_mffscrni): Defined. > (rs6000_set_fpscr_rn): Change the type of operand[0] form DI to SI. > Call gen_rs6000_mffscrni when operand[0] is a const int[0,3]. > > gcc/testsuite/ > * gcc.target/powerpc/mffscrni_p9.c: New testcase for mffscrni. > * gcc.target/powerpc/test_fpscr_rn_builtin.c: Modify the test cases to > test mffscrn and mffscrni separately. This revised patch is okay. Thanks, David > > > patch.diff > diff --git a/gcc/config/rs6000/predicates.md b/gcc/config/rs6000/predicates.md > index f216ffdf410..b10b4ce6065 100644 > --- a/gcc/config/rs6000/predicates.md > +++ b/gcc/config/rs6000/predicates.md > @@ -219,6 +219,11 @@ (define_predicate "u1bit_cint_operand" >(and (match_code "const_int") > (match_test "INTVAL (op) >= 0 && INTVAL (op) <= 1"))) > > +;; Return 1 if op is an unsigned 2-bit constant integer. > +(define_predicate "u2bit_cint_operand" > + (and (match_code "const_int") > + (match_test "INTVAL (op) >= 0 && INTVAL (op) <= 3"))) > + > ;; Return 1 if op is a unsigned 3-bit constant integer. > (define_predicate "u3bit_cint_operand" >(and (match_code "const_int") > diff --git a/gcc/config/rs6000/rs6000-call.c b/gcc/config/rs6000/rs6000-call.c > index d9736eaf21c..81261a0f24d 100644 > --- a/gcc/config/rs6000/rs6000-call.c > +++ b/gcc/config/rs6000/rs6000-call.c > @@ -9610,13 +9610,15 @@ rs6000_expand_set_fpscr_rn_builtin (enum insn_code > icode, tree exp) > compile time if the argument is a variable. The least significant two > bits of the argument, regardless of type, are used to set the rounding > mode. All other bits are ignored. */ > - if (CONST_INT_P (op0) && !const_0_to_3_operand(op0, VOIDmode)) > + if (CONST_INT_P (op0)) > { > - error ("Argument must be a value between 0 and 3."); > - return const0_rtx; > + if (!const_0_to_3_operand (op0, VOIDmode)) > + { > + error ("Argument must be a value between 0 and 3."); > + return const0_rtx; > + } > } > - > - if (! (*insn_data[icode].operand[0].predicate) (op0, mode0)) > + else if (! (*insn_data[icode].operand[0].predicate) (op0, mode0)) > op0 = copy_to_mode_reg (mode0, op0); > >pat = GEN_FCN (icode) (op0); > diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md > index 6bec2bddbde..b18746af7ea 100644 > --- a/gcc/config/rs6000/rs6000.md > +++ b/gcc/config/rs6000/rs6000.md > @@ -177,6 +177,7 @@ (define_c_enum "unspecv" > UNSPECV_MFFS; Move from FPSCR > UNSPECV_MFFSL ; Move from FPSCR light instruction version > UNSPECV_MFFSCRN ; Move from FPSCR float rounding mode > + UNSPECV_MFFSCRNI; Move from FPSCR float rounding mode with imm > UNSPECV_MFFSCDRN; Move from FPSCR decimal float rounding mode > UNSPECV_MTFSF ; Move to FPSCR Fields 8 to 15 > UNSPECV_MTFSF_HI; Move to FPSCR Fields 0 to 7 > @@ -6315,6 +6316,14 @@ (define_insn "rs6000_mffscrn" > "mffscrn %0,%1" >[(set_attr "type" "fp")]) > > +(define_insn "rs6000_mffscrni" > + [(set (match_operand:DF 0 "gpc_reg_operand" "=d") > + (unspec_volatile:DF [(match_operand:SI 1 "u2bit_cint_operand" "n")] > + UNSPECV_MFFSCRNI))] > + "TARGET_P9_MISC" > + "mffscrni %0,%1" > + [(set_attr "type" "fp")]) > + > (define_insn "rs6000_mffscdrn" >[(set (match_operand:DF 0 "gpc_reg_operand" "=d") > (unspec_volatile:DF [(const_int 0)] UNSPECV_MFFSCDRN)) > @@ -6324,7 +6333,7 @@ (define_insn "rs6000_mffscdrn" >[(set_attr "type" "fp")]) > > (define_expand "rs6000_set_fpscr_rn" > - [(match_operand:DI 0 "reg_or_cint_operand")] > + [(match_operand:SI 0 "reg_or_cint_operand")] >"TARGET_HARD_FLOAT" > { >rtx tmp_df = gen_reg_rtx (DFmode); > @@ -6333,9 +6342,15 @@ (define_expand "rs6000_set_fpscr_rn" > new rounding mode bits from operands[0][62:63]
Re: [PATCH, rs6000] Implement mffscrni pattern
On Fri, Dec 17, 2021 at 10:33:12PM -0500, David Edelsohn wrote: > On Thu, Dec 16, 2021 at 9:43 PM HAO CHEN GUI wrote: > > +(define_insn "rs6000_mffscrni" > > + [(set (match_operand:DF 0 "gpc_reg_operand" "=d") > > + (unspec_volatile:DF [(match_operand:DF 1 "u2bit_cint_operand" "n")] > > Why is this input operand 1 DFmode? This is a 2 bit integer value. > This pattern is called from rs6000_set_fpscr_rn with an SImode > operand, and it seems that this should be SImode as well. Yup. This predicate will only allow const_int, and matching a const_int ignores the mode, so most (or all?) things will work whatever mode you give here. But only MODE_INT modes make sense (and possibly VOIDmode, but VOIDmode in machine descriptions means anything is allowed, also not what you want here). Segher
Re: [PATCH, rs6000] Implement mffscrni pattern
On Thu, Dec 16, 2021 at 9:43 PM HAO CHEN GUI wrote: > > Hi, >This patch defines a pattern for mffscrni. If the RN is a constant, it can > call > gen_rs6000_mffscrni directly. The "rs6000-builtin-new.def" defines prototype > for builtin arguments. > The pattern "rs6000_set_fpscr_rn" is then broken as the mode of its argument > is DI while its > corresponding builtin has a const int argument. The patch also fixed it. > >Bootstrapped and tested on powerpc64-linux BE and LE with no regressions. > Is this okay for trunk? > Any recommendations? Thanks a lot. Hi, Haochen I have a question about the mode of the input operand in the new pattern below. > > ChangeLog > 2021-12-17 Haochen Gui > > gcc/ > * config/rs6000/predicates.md (u2bit_cint_operand): Defined. > * config/rs6000/rs6000-call.c > (rs6000_expand_set_fpscr_rn_builtin): Not copy argument to a reg if > it's a constant. The pattern for constant can be recognized now. > * config/rs6000/rs6000.md (UNSPECV_MFFSCRNI): Defined. > (rs6000_mffscrni): Defined. > (rs6000_set_fpscr_rn): Change the type of operand[0] form DI to SI. > Call gen_rs6000_mffscrni when operand[0] is a const int[0,3]. > > gcc/testsuite/ > * gcc.target/powerpc/mffscrni_p9.c: New testcase for mffscrni. > * gcc.target/powerpc/test_fpscr_rn_builtin.c: Modify the test cases to > test mffscrn and mffscrni separately. > > patch.diff > diff --git a/gcc/config/rs6000/predicates.md b/gcc/config/rs6000/predicates.md > index f216ffd..b10b4ce 100644 > --- a/gcc/config/rs6000/predicates.md > +++ b/gcc/config/rs6000/predicates.md > @@ -219,6 +219,11 @@ (define_predicate "u1bit_cint_operand" >(and (match_code "const_int") > (match_test "INTVAL (op) >= 0 && INTVAL (op) <= 1"))) > > +;; Return 1 if op is an unsigned 2-bit constant integer. > +(define_predicate "u2bit_cint_operand" > + (and (match_code "const_int") > + (match_test "INTVAL (op) >= 0 && INTVAL (op) <= 3"))) > + > ;; Return 1 if op is a unsigned 3-bit constant integer. > (define_predicate "u3bit_cint_operand" >(and (match_code "const_int") > diff --git a/gcc/config/rs6000/rs6000-call.c b/gcc/config/rs6000/rs6000-call.c > index d9736ea..81261a0 100644 > --- a/gcc/config/rs6000/rs6000-call.c > +++ b/gcc/config/rs6000/rs6000-call.c > @@ -9610,13 +9610,15 @@ rs6000_expand_set_fpscr_rn_builtin (enum insn_code > icode, tree exp) > compile time if the argument is a variable. The least significant two > bits of the argument, regardless of type, are used to set the rounding > mode. All other bits are ignored. */ > - if (CONST_INT_P (op0) && !const_0_to_3_operand(op0, VOIDmode)) > + if (CONST_INT_P (op0)) > { > - error ("Argument must be a value between 0 and 3."); > - return const0_rtx; > + if (!const_0_to_3_operand (op0, VOIDmode)) > + { > + error ("Argument must be a value between 0 and 3."); > + return const0_rtx; > + } > } > - > - if (! (*insn_data[icode].operand[0].predicate) (op0, mode0)) > + else if (! (*insn_data[icode].operand[0].predicate) (op0, mode0)) > op0 = copy_to_mode_reg (mode0, op0); > >pat = GEN_FCN (icode) (op0); > diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md > index 6bec2bd..291396c 100644 > --- a/gcc/config/rs6000/rs6000.md > +++ b/gcc/config/rs6000/rs6000.md > @@ -177,6 +177,7 @@ (define_c_enum "unspecv" > UNSPECV_MFFS; Move from FPSCR > UNSPECV_MFFSL ; Move from FPSCR light instruction version > UNSPECV_MFFSCRN ; Move from FPSCR float rounding mode > + UNSPECV_MFFSCRNI; Move from FPSCR float rounding mode with imm > UNSPECV_MFFSCDRN; Move from FPSCR decimal float rounding mode > UNSPECV_MTFSF ; Move to FPSCR Fields 8 to 15 > UNSPECV_MTFSF_HI; Move to FPSCR Fields 0 to 7 > @@ -6315,6 +6316,14 @@ (define_insn "rs6000_mffscrn" > "mffscrn %0,%1" >[(set_attr "type" "fp")]) > > +(define_insn "rs6000_mffscrni" > + [(set (match_operand:DF 0 "gpc_reg_operand" "=d") > + (unspec_volatile:DF [(match_operand:DF 1 "u2bit_cint_operand" "n")] Why is this input operand 1 DFmode? This is a 2 bit integer value. This pattern is called from rs6000_set_fpscr_rn with an SImode operand, and it seems that this should be SImode as well. Thanks, David > + UNSPECV_MFFSCRNI))] > + "TARGET_P9_MISC" > + "mffscrni %0,%1" > + [(set_attr "type" "fp")]) > + > (define_insn "rs6000_mffscdrn" >[(set (match_operand:DF 0 "gpc_reg_operand" "=d") > (unspec_volatile:DF [(const_int 0)] UNSPECV_MFFSCDRN)) > @@ -6324,7 +6333,7 @@ (define_insn "rs6000_mffscdrn" >[(set_attr "type" "fp")]) > > (define_expand "rs6000_set_fpscr_rn" > - [(match_operand:DI 0 "reg_or_cint_operand")] > + [(match_operand:SI 0 "reg_or_cint_operand")] >"TARGET_HARD_FLOAT" >