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; > +} >