diff mbox series

IBM Z: Fix "+fvm" constraint with long doubles

Message ID 20210316001658.193590-1-iii@linux.ibm.com
State New
Headers show
Series IBM Z: Fix "+fvm" constraint with long doubles | expand

Commit Message

Ilya Leoshkevich March 16, 2021, 12:16 a.m. UTC
Bootstrapped and regtested on s390x-redhat-linux.  Ok for master?



When a long double is passed to an asm statement with a "+fvm"
constraint, a LRA loop occurs.  This happens, because LRA chooses the
widest register class in this case (VEC_REGS), but the code generated
by s390_md_asm_adjust() always wants FP_REGS.  Mismatching register
classes cause infinite reloading.

Fix by treating "fv" constraints as "v" in s390_md_asm_adjust().

gcc/ChangeLog:

	* config/s390/s390.c (f_constraint_p): Treat "fv" constraints
	as "v".

gcc/testsuite/ChangeLog:

	* gcc.target/s390/vector/long-double-asm-fprvrmem.c: New test.
---
 gcc/config/s390/s390.c                               | 12 ++++++++++--
 .../s390/vector/long-double-asm-fprvrmem.c           | 11 +++++++++++
 2 files changed, 21 insertions(+), 2 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/s390/vector/long-double-asm-fprvrmem.c

Comments

Andreas Krebbel March 16, 2021, 6:58 a.m. UTC | #1
On 3/16/21 1:16 AM, Ilya Leoshkevich wrote:
> Bootstrapped and regtested on s390x-redhat-linux.  Ok for master?
> 
> 
> 
> When a long double is passed to an asm statement with a "+fvm"
> constraint, a LRA loop occurs.  This happens, because LRA chooses the
> widest register class in this case (VEC_REGS), but the code generated
> by s390_md_asm_adjust() always wants FP_REGS.  Mismatching register
> classes cause infinite reloading.
> 
> Fix by treating "fv" constraints as "v" in s390_md_asm_adjust().
> 
> gcc/ChangeLog:
> 
> 	* config/s390/s390.c (f_constraint_p): Treat "fv" constraints
> 	as "v".
> 
> gcc/testsuite/ChangeLog:
> 
> 	* gcc.target/s390/vector/long-double-asm-fprvrmem.c: New test.

Ok. Thanks!

Andreas

> ---
>  gcc/config/s390/s390.c                               | 12 ++++++++++--
>  .../s390/vector/long-double-asm-fprvrmem.c           | 11 +++++++++++
>  2 files changed, 21 insertions(+), 2 deletions(-)
>  create mode 100644 gcc/testsuite/gcc.target/s390/vector/long-double-asm-fprvrmem.c
> 
> diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c
> index 151136bedbc..f7b1c03561e 100644
> --- a/gcc/config/s390/s390.c
> +++ b/gcc/config/s390/s390.c
> @@ -16714,13 +16714,21 @@ s390_shift_truncation_mask (machine_mode mode)
>  static bool
>  f_constraint_p (const char *constraint)
>  {
> +  bool seen_f_p = false;
> +  bool seen_v_p = false;
> +
>    for (size_t i = 0, c_len = strlen (constraint); i < c_len;
>         i += CONSTRAINT_LEN (constraint[i], constraint + i))
>      {
>        if (constraint[i] == 'f')
> -	return true;
> +	seen_f_p = true;
> +      if (constraint[i] == 'v')
> +	seen_v_p = true;
>      }
> -  return false;
> +
> +  /* Treat "fv" constraints as "v", because LRA will choose the widest register
> +   * class.  */
> +  return seen_f_p && !seen_v_p;
>  }
>  
>  /* Implement TARGET_MD_ASM_ADJUST hook in order to fix up "f"
> diff --git a/gcc/testsuite/gcc.target/s390/vector/long-double-asm-fprvrmem.c b/gcc/testsuite/gcc.target/s390/vector/long-double-asm-fprvrmem.c
> new file mode 100644
> index 00000000000..f95656c5723
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/s390/vector/long-double-asm-fprvrmem.c
> @@ -0,0 +1,11 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O3 -march=z14 -mzarch" } */
> +
> +long double
> +foo (long double x)
> +{
> +  x = x * x;
> +  asm("# %0" : "+fvm"(x));
> +  x = x + x;
> +  return x;
> +}
>
diff mbox series

Patch

diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c
index 151136bedbc..f7b1c03561e 100644
--- a/gcc/config/s390/s390.c
+++ b/gcc/config/s390/s390.c
@@ -16714,13 +16714,21 @@  s390_shift_truncation_mask (machine_mode mode)
 static bool
 f_constraint_p (const char *constraint)
 {
+  bool seen_f_p = false;
+  bool seen_v_p = false;
+
   for (size_t i = 0, c_len = strlen (constraint); i < c_len;
        i += CONSTRAINT_LEN (constraint[i], constraint + i))
     {
       if (constraint[i] == 'f')
-	return true;
+	seen_f_p = true;
+      if (constraint[i] == 'v')
+	seen_v_p = true;
     }
-  return false;
+
+  /* Treat "fv" constraints as "v", because LRA will choose the widest register
+   * class.  */
+  return seen_f_p && !seen_v_p;
 }
 
 /* Implement TARGET_MD_ASM_ADJUST hook in order to fix up "f"
diff --git a/gcc/testsuite/gcc.target/s390/vector/long-double-asm-fprvrmem.c b/gcc/testsuite/gcc.target/s390/vector/long-double-asm-fprvrmem.c
new file mode 100644
index 00000000000..f95656c5723
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/vector/long-double-asm-fprvrmem.c
@@ -0,0 +1,11 @@ 
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzarch" } */
+
+long double
+foo (long double x)
+{
+  x = x * x;
+  asm("# %0" : "+fvm"(x));
+  x = x + x;
+  return x;
+}