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.

Reply via email to