Re: [PATCH v3, rs6000] Implement mffscrni pattern

2021-12-21 Thread HAO CHEN GUI via Gcc-patches
Hi Segher,
  Thanks for your advice. Please see my explanation below.

On 22/12/2021 上午 1:05, Segher Boessenkool wrote:
> Hi!
> 
> On Tue, Dec 21, 2021 at 04:08:06PM +0800, HAO CHEN GUI wrote:
>>   This patch defines a pattern for mffscrni. If the RN is a constant, it can 
>> call
>> gen_rs6000_mffscrni directly.
> 
> And that isn't more work than just falling through to the general case.
> Okay.
> 
>> 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.
> 
> I don't understand that bit.  Do you mean it is a const_int, or do you
> mean it is an "int" as in C source code, i.e. a 32-bit integer?

With the trunk, the new test case hits following ICE.

test_fpscr_rn_builtin.c: In function ‘wrap_set_fpscr_rn’:
test_fpscr_rn_builtin.c:13:3: internal compiler error: in copy_to_mode_reg, at 
explow.c:652
   13 |   __builtin_set_fpscr_rn (val);
  |   ^~~~
0x1065892f copy_to_mode_reg(machine_mode, rtx_def*)
/home/guihaoc/gcc/gcc-mainline-base/gcc/explow.c:652
0x11206127 rs6000_expand_new_builtin

/home/guihaoc/gcc/gcc-mainline-base/gcc/config/rs6000/rs6000-call.c:15974
0x11206127 rs6000_expand_builtin(tree_node*, rtx_def*, rtx_def*, machine_mode, 
int)

/home/guihaoc/gcc/gcc-mainline-base/gcc/config/rs6000/rs6000-call.c:14591

The val is int variable, so its mode is SImode. But rs6000_set_fpscr_rn 
requires DImode.

  for (int i = 0; i < nargs; i++)
if (!insn_data[icode].operand[i+k].predicate (op[i], mode[i+k]))
  op[i] = copy_to_mode_reg (mode[i+k], op[i]);

So it executes copy_to_mode_reg to copy it to DImode. Then it fails at 
assertion in
copy_to_mode_reg.

gcc_assert (GET_MODE (x) == mode || GET_MODE (x) == VOIDmode);

The original test case only tests the val as const int(E_VOIDmode). So it never 
hits
copy_to_mode_reg.

> 
>>  * 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.
> 
> "Do not copy"
> 
>>  * config/rs6000/rs6000.md (rs6000_mffscrni): Defined.
> 
> "Define".
> 
>>  (rs6000_set_fpscr_rn): Change the type of operand[0] form DI to SI.
> 
> "from"
> 
>>  Call gen_rs6000_mffscrni when operand[0] is a const int[0,3].
> 
> "if operands[0] is a const_0_to_3_operand"
> 
>>  * 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.
> 
> "Test for mffscrn and mffscrni separately."
> 
> Everything you say in a changelog is "modify this" or "modify that", and
> (almost) all things in gcc/testsuite/ are testcases :-)
> 
>> @@ -6357,7 +6370,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 (3)));
>>
>>/* Insert new RN mode into FSCPR.  */
>>emit_insn (gen_rs6000_mffs (tmp_df));
> 
> It doesn't seem correct to use DImode with -m32, hrm.  Not new of
> course, but I wonder how this worked.

With m32 on BE, it sets the low part to 0 when converting SI to DI.
As it just needs last two bits of high part, I set the signed to false.

rtx op0 = convert_to_mode (DImode, operands[0], false)

(insn 110 109 111 21 (set (subreg:SI (reg:DI 179 [ ll_value ]) 0)
(const_int 0 [0])) "test_fpscr_rn_builtin.c":167:12 556 
{*movsi_internal1}
 (nil))

> 
> Okay for trunk with such changelog fixes.  Thanks!
> 
> 
> Segher


Re: [PATCH v3, rs6000] Implement mffscrni pattern

2021-12-21 Thread Segher Boessenkool
Hi!

On Tue, Dec 21, 2021 at 04:08:06PM +0800, HAO CHEN GUI wrote:
>   This patch defines a pattern for mffscrni. If the RN is a constant, it can 
> call
> gen_rs6000_mffscrni directly.

And that isn't more work than just falling through to the general case.
Okay.

> 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.

I don't understand that bit.  Do you mean it is a const_int, or do you
mean it is an "int" as in C source code, i.e. a 32-bit integer?

>   * 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.

"Do not copy"

>   * config/rs6000/rs6000.md (rs6000_mffscrni): Defined.

"Define".

>   (rs6000_set_fpscr_rn): Change the type of operand[0] form DI to SI.

"from"

>   Call gen_rs6000_mffscrni when operand[0] is a const int[0,3].

"if operands[0] is a const_0_to_3_operand"

>   * 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.

"Test for mffscrn and mffscrni separately."

Everything you say in a changelog is "modify this" or "modify that", and
(almost) all things in gcc/testsuite/ are testcases :-)

> @@ -6357,7 +6370,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 (3)));
> 
>/* Insert new RN mode into FSCPR.  */
>emit_insn (gen_rs6000_mffs (tmp_df));

It doesn't seem correct to use DImode with -m32, hrm.  Not new of
course, but I wonder how this worked.

Okay for trunk with such changelog fixes.  Thanks!


Segher


[PATCH v3, rs6000] Implement mffscrni pattern

2021-12-21 Thread HAO CHEN GUI via Gcc-patches
Hi,
  I modified the patch according to reviewers' 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-21 Haochen Gui 

gcc/
* 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 (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/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..452a77f2033 100644
--- a/gcc/config/rs6000/rs6000.md
+++ b/gcc/config/rs6000/rs6000.md
@@ -6315,6 +6315,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 "const_0_to_3_operand" "n")]
+   UNSPECV_MFFSCRN))]
+   "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 +6332,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 +6341,14 @@ (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_0_to_3_operand (operands[0], VOIDmode))
+   emit_insn (gen_rs6000_mffscrni (tmp_df, operands[0]));
+  else
+   {
+ rtx op0 = convert_to_mode (DImode, operands[0], false);
+ rtx src_df = simplify_gen_subreg (DFmode, op0, DImode, 0);
+ emit_insn (gen_rs6000_mffscrn (tmp_df, src_df));
+   }
   DONE;
 }

@@ -6357,7 +6370,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 (3)));

   /* Insert new RN mode into FSCPR.  */
   emit_insn (gen_rs6000_mffs (tmp_df));
diff --git a/gcc/testsuite/gcc.target/powerpc/mffscrni_p9.c 
b/gcc/testsuite/gcc.target/powerpc/mffscrni_p9.c
new file mode 100644
index 000..d97c6db8002
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/mffscrni_p9.c
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mdejagnu-cpu=power9" } */
+/* { dg-final { scan-assembler-times {\mmffscrni\M} 1 } } */
+
+void foo ()
+{
+  int val = 2;
+  __builtin_set_fpscr_rn (val);
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/test_fpscr_rn_builtin.c 
b/gcc/testsuite/gcc.target/powerpc/test_fpscr_rn_builtin.c
index 0d0d3f0f96b..04707ad8a56