On Fri, Jun 20, 2025 at 10:17:20AM -0400, Vladimir Makarov wrote:
> 
> On 5/20/25 3:22 AM, Stefan Schulze Frielinghaus wrote:
> > Implement hard register constraints of the form {regname} where regname
> > must be a valid register name for the target.  Such constraints may be
> > used in asm statements as a replacement for register asm and in machine
> > descriptions.
> > 
> > ---
> >   gcc/config/cris/cris.cc                       |   6 +-
> >   gcc/config/i386/i386.cc                       |   6 +
> >   gcc/config/s390/s390.cc                       |   6 +-
> >   gcc/doc/extend.texi                           | 178 ++++++++++++++++++
> >   gcc/doc/md.texi                               |   6 +
> >   gcc/function.cc                               | 116 ++++++++++++
> >   gcc/genoutput.cc                              |  14 ++
> >   gcc/genpreds.cc                               |   4 +-
> >   gcc/ira.cc                                    |  79 +++++++-
> >   gcc/lra-constraints.cc                        |  13 ++
> >   gcc/recog.cc                                  |  11 +-
> >   gcc/stmt.cc                                   |  39 ++++
> >   gcc/stmt.h                                    |   1 +
> >   gcc/testsuite/gcc.dg/asm-hard-reg-1.c         |  85 +++++++++
> >   gcc/testsuite/gcc.dg/asm-hard-reg-2.c         |  33 ++++
> >   gcc/testsuite/gcc.dg/asm-hard-reg-3.c         |  25 +++
> >   gcc/testsuite/gcc.dg/asm-hard-reg-4.c         |  50 +++++
> >   gcc/testsuite/gcc.dg/asm-hard-reg-5.c         |  36 ++++
> >   gcc/testsuite/gcc.dg/asm-hard-reg-6.c         |  60 ++++++
> >   gcc/testsuite/gcc.dg/asm-hard-reg-7.c         |  41 ++++
> >   gcc/testsuite/gcc.dg/asm-hard-reg-8.c         |  49 +++++
> >   .../gcc.target/aarch64/asm-hard-reg-1.c       |  55 ++++++
> >   .../gcc.target/i386/asm-hard-reg-1.c          | 115 +++++++++++
> >   .../gcc.target/s390/asm-hard-reg-1.c          | 103 ++++++++++
> >   .../gcc.target/s390/asm-hard-reg-2.c          |  43 +++++
> >   .../gcc.target/s390/asm-hard-reg-3.c          |  42 +++++
> >   .../gcc.target/s390/asm-hard-reg-4.c          |   6 +
> >   .../gcc.target/s390/asm-hard-reg-5.c          |   6 +
> >   .../gcc.target/s390/asm-hard-reg-6.c          | 152 +++++++++++++++
> >   .../gcc.target/s390/asm-hard-reg-longdouble.h |  18 ++
> >   30 files changed, 1391 insertions(+), 7 deletions(-)
> >   create mode 100644 gcc/testsuite/gcc.dg/asm-hard-reg-1.c
> >   create mode 100644 gcc/testsuite/gcc.dg/asm-hard-reg-2.c
> >   create mode 100644 gcc/testsuite/gcc.dg/asm-hard-reg-3.c
> >   create mode 100644 gcc/testsuite/gcc.dg/asm-hard-reg-4.c
> >   create mode 100644 gcc/testsuite/gcc.dg/asm-hard-reg-5.c
> >   create mode 100644 gcc/testsuite/gcc.dg/asm-hard-reg-6.c
> >   create mode 100644 gcc/testsuite/gcc.dg/asm-hard-reg-7.c
> >   create mode 100644 gcc/testsuite/gcc.dg/asm-hard-reg-8.c
> >   create mode 100644 gcc/testsuite/gcc.target/aarch64/asm-hard-reg-1.c
> >   create mode 100644 gcc/testsuite/gcc.target/i386/asm-hard-reg-1.c
> >   create mode 100644 gcc/testsuite/gcc.target/s390/asm-hard-reg-1.c
> >   create mode 100644 gcc/testsuite/gcc.target/s390/asm-hard-reg-2.c
> >   create mode 100644 gcc/testsuite/gcc.target/s390/asm-hard-reg-3.c
> >   create mode 100644 gcc/testsuite/gcc.target/s390/asm-hard-reg-4.c
> >   create mode 100644 gcc/testsuite/gcc.target/s390/asm-hard-reg-5.c
> >   create mode 100644 gcc/testsuite/gcc.target/s390/asm-hard-reg-6.c
> >   create mode 100644 gcc/testsuite/gcc.target/s390/asm-hard-reg-longdouble.h
> > diff --git a/gcc/ira.cc b/gcc/ira.cc
> > index 885239d1b43..c32d4ceab88 100644
> > --- a/gcc/ira.cc
> > +++ b/gcc/ira.cc
> > @@ -2113,6 +2113,82 @@ ira_get_dup_out_num (int op_num, alternative_mask 
> > alts,
> >   
> > +/* Return true if a replacement of SRC by DEST does not lead to 
> > unsatisfiable
> > +   asm.  Thus, a replacement is valid if and only if SRC and DEST are not
> > +   constrained in asm inputs of a single asm statement.  See
> > +   match_asm_constraints_2() for more details.  TODO: As in
> > +   match_asm_constraints_2() consider alternatives more precisely.  */
> > +
> > +static bool
> > +valid_replacement_for_asm_input_p_1 (const_rtx asmops, const_rtx src, 
> > const_rtx dest)
> > +{
> > +  int ninputs = ASM_OPERANDS_INPUT_LENGTH (asmops);
> > +  rtvec inputs = ASM_OPERANDS_INPUT_VEC (asmops);
> > +  for (int i = 0; i < ninputs; ++i)
> > +    {
> > +      rtx input_src = RTVEC_ELT (inputs, i);
> > +      const char *constraint_src
> > +   = ASM_OPERANDS_INPUT_CONSTRAINT (asmops, i);
> > +      if (rtx_equal_p (input_src, src)
> > +     && strchr (constraint_src, '{') != nullptr)
> > +   for (int j = 0; j < ninputs; ++j)
> > +     {
> > +       rtx input_dest = RTVEC_ELT (inputs, j);
> > +       const char *constraint_dest
> > +         = ASM_OPERANDS_INPUT_CONSTRAINT (asmops, j);
> > +       if (rtx_equal_p (input_dest, dest)
> > +           && strchr (constraint_dest, '{') != nullptr)
> > +         return false;
> > +     }
> > +    }
> > +  return true;
> > +}
> > +
> > +static bool
> > +valid_replacement_for_asm_input_p (const_rtx src, const_rtx dest)
> > +{
> > +  /* Bail out early if there is no asm statement.  */
> > +  if (!crtl->has_asm_statement)
> > +    return true;
> > +  for (df_ref use = DF_REG_USE_CHAIN (REGNO (src));
> > +       use;
> > +       use = DF_REF_NEXT_REG (use))
> > +    {
> > +      struct df_insn_info *use_info = DF_REF_INSN_INFO (use);
> > +      /* Only check real uses, not artificial ones.  */
> > +      if (use_info)
> > +   {
> > +     rtx_insn *insn = DF_REF_INSN (use);
> > +     rtx pat = PATTERN (insn);
> > +     if (asm_noperands (pat) <= 0)
> > +       continue;
> > +     if (GET_CODE (pat) == SET)
> > +       {
> > +         if (!valid_replacement_for_asm_input_p_1 (SET_SRC (pat), src, 
> > dest))
> > +           return false;
> > +       }
> > +     else if (GET_CODE (pat) == PARALLEL)
> > +       for (int i = 0, len = XVECLEN (pat, 0); i < len; ++i)
> > +         {
> > +           rtx asmops = XVECEXP (pat, 0, i);
> > +           if (GET_CODE (asmops) == SET)
> > +             asmops = SET_SRC (asmops);
> > +           if (GET_CODE (asmops) == ASM_OPERANDS
> > +               && !valid_replacement_for_asm_input_p_1 (asmops, src, dest))
> > +             return false;
> > +         }
> > +     else if (GET_CODE (pat) == ASM_OPERANDS)
> > +       {
> > +         if (!valid_replacement_for_asm_input_p_1 (pat, src, dest))
> > +           return false;
> > +       }
> > +     else
> > +       gcc_unreachable ();
> > +   }
> > +    }
> > +  return true;
> > +}
> > +
> >   /* Search forward to see if the source register of a copy insn dies
> >      before either it or the destination register is modified, but don't
> >      scan past the end of the basic block.  If so, we can replace the
> > @@ -2162,7 +2238,8 @@ decrease_live_ranges_number (void)
> >            auto-inc memory reference, so we must disallow this
> >            optimization on them.  */
> >         || sregno == STACK_POINTER_REGNUM
> > -       || dregno == STACK_POINTER_REGNUM)
> > +       || dregno == STACK_POINTER_REGNUM
> > +       || !valid_replacement_for_asm_input_p (src, dest))
> >       continue;
> >     dest_death = NULL_RTX;
> > diff --git a/gcc/lra-constraints.cc b/gcc/lra-constraints.cc
> > index 7dbc7fe1e00..689a12b2c71 100644
> > --- a/gcc/lra-constraints.cc
> > +++ b/gcc/lra-constraints.cc
> > @@ -114,6 +114,7 @@
> >   #include "target.h"
> >   #include "rtl.h"
> >   #include "tree.h"
> > +#include "stmt.h"
> >   #include "predict.h"
> >   #include "df.h"
> >   #include "memmodel.h"
> > @@ -2175,6 +2176,7 @@ process_alt_operands (int only_alternative)
> >     bool costly_p;
> >     enum reg_class cl;
> >     const HARD_REG_SET *cl_filter;
> > +  HARD_REG_SET hard_reg_constraint;
> >     /* Calculate some data common for all alternatives to speed up the
> >        function.    */
> > @@ -2551,6 +2553,17 @@ process_alt_operands (int only_alternative)
> >               cl_filter = nullptr;
> >               goto reg;
> > +           case '{':
> > +               {
> > +                 int regno = decode_hard_reg_constraint (p);
> > +                 gcc_assert (regno >= 0);
> > +                 cl = REGNO_REG_CLASS (regno);
> > +                 CLEAR_HARD_REG_SET (hard_reg_constraint);
> > +                 SET_HARD_REG_BIT (hard_reg_constraint, regno);
> > +                 cl_filter = &hard_reg_constraint;
> > +                 goto reg;
> > +               }
> > +
> >             default:
> >               cn = lookup_constraint (p);
> >               switch (get_constraint_type (cn))
> 
> 
> The RA part of the patch is OK for me. The changes are pretty obvious.  It
> would be nice to add  a short comment to valid_replacement_for_asm_input_p
> mentioning valid_replacement_for_asm_input_p_1 but it is not obligatory.
> 
> Thank you for your work on this new GCC feature.

Thanks for the review.  Very much appreciated!

I added a comment to valid_replacement_for_asm_input_p().

Out of curiosity, do you have any idea how to tackle fixed registers?
This is the last remaining piece for a full fledged solution.  Certainly
not required for this patch but something I would like to look into in
the future.

Cheers,
Stefan

Reply via email to