https://gcc.gnu.org/g:804912edbfc93b6f68869aff736eec159423fd43

commit r16-6805-g804912edbfc93b6f68869aff736eec159423fd43
Author: Stefan Schulze Frielinghaus <[email protected]>
Date:   Thu Jan 15 15:14:59 2026 +0100

    Deal with combinations of hard register constraints
    
    Currently, multiple hard register constraints in one alternative are not
    supported.  Likewise, a combination of hard register constraints and
    regular register constraints is not supported.  Note, a combination of
    hard register constraints and non-register constraints as e.g. immediate
    constraints is supported.  This is inspired by the i386 target where
    constraints like aI are used which could be expressed as {ax}I, too.
    
    gcc/ChangeLog:
    
            * doc/extend.texi: Document current limitations of hard register
            constraints.
            * stmt.cc (parse_output_constraint): Reject multiple hard
            register constraints or a combination of hard register
            constraints and regular register constraints in one alternative.
            (parse_input_constraint): Ditto.
    
    gcc/testsuite/ChangeLog:
    
            * gcc.dg/asm-hard-reg-error-1.c: Remove tests containing
            multiple hard register constraints in one alternative.
            * gcc.dg/asm-hard-reg-error-6.c: New test.

Diff:
---
 gcc/doc/extend.texi                         |  4 ++
 gcc/stmt.cc                                 | 66 ++++++++++++++++++++++++++++-
 gcc/testsuite/gcc.dg/asm-hard-reg-error-1.c |  3 +-
 gcc/testsuite/gcc.dg/asm-hard-reg-error-6.c | 35 +++++++++++++++
 4 files changed, 104 insertions(+), 4 deletions(-)

diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
index a5c687f2667e..b4879b3d82ff 100644
--- a/gcc/doc/extend.texi
+++ b/gcc/doc/extend.texi
@@ -13544,6 +13544,10 @@ asm ("" : "=r" (x));
 
 are not supported for hard register constraints.  This might be lifted.
 
+Multiple hard register constraints in one alternative are also not supported.
+Furthermore, combinations of hard register constraints and regular register
+constraints in one alternative are not supported, too.
+
 @node Size of an asm
 @subsection Size of an @code{asm}
 
diff --git a/gcc/stmt.cc b/gcc/stmt.cc
index 5816fb9b3b6e..382a2d75c076 100644
--- a/gcc/stmt.cc
+++ b/gcc/stmt.cc
@@ -322,6 +322,11 @@ parse_output_constraint (const char **constraint_p, int 
operand_num,
 
   unsigned int alt = 0;
   bool early_clobbered = false;
+  /* Currently, multiple hard register constraints in one alternative are not
+     supported.  A combination of hard register constraints and regular
+     register constraints is also not supported.  */
+  bool alt_has_hard_reg_cstr = false;
+  bool alt_has_reg_cstr = false;
 
   /* Loop through the constraint string.  */
   for (p = constraint + 1; *p; )
@@ -357,6 +362,8 @@ parse_output_constraint (const char **constraint_p, int 
operand_num,
        case ',':
          ++alt;
          early_clobbered = false;
+         alt_has_hard_reg_cstr = false;
+         alt_has_reg_cstr = false;
          break;
 
        case '0':  case '1':  case '2':  case '3':  case '4':
@@ -390,6 +397,21 @@ parse_output_constraint (const char **constraint_p, int 
operand_num,
              }
            if (reg_info)
              {
+               if (alt_has_reg_cstr)
+                 {
+                   error (
+                       "hard register constraints and regular register "
+                       "constraints in one alternative are not supported");
+                   return false;
+                 }
+               if (alt_has_hard_reg_cstr)
+                 {
+                   error (
+                       "multiple hard register constraints in one "
+                       "alternative are not supported");
+                   return false;
+                 }
+               alt_has_hard_reg_cstr = true;
                int regno = decode_hard_reg_constraint (p);
                if (regno < 0)
                  {
@@ -441,7 +463,17 @@ parse_output_constraint (const char **constraint_p, int 
operand_num,
          enum constraint_num cn = lookup_constraint (p);
          if (reg_class_for_constraint (cn) != NO_REGS
              || insn_extra_address_constraint (cn))
-           *allows_reg = true;
+           {
+             if (alt_has_hard_reg_cstr)
+               {
+                 error (
+                     "hard register constraints and regular register "
+                     "constraints in one alternative are not supported");
+                 return false;
+               }
+             alt_has_reg_cstr = true;
+             *allows_reg = true;
+           }
          else if (insn_extra_memory_constraint (cn))
            *allows_mem = true;
          else
@@ -503,6 +535,9 @@ parse_input_constraint (const char **constraint_p, int 
input_num,
   *allows_mem = false;
   *allows_reg = false;
 
+  bool alt_has_hard_reg_cstr = false;
+  bool alt_has_reg_cstr = false;
+
   /* Make sure constraint has neither `=', `+', nor '&'.  */
 
   unsigned int alt = 0;
@@ -555,6 +590,8 @@ repeat:
 
       case ',':
        ++alt;
+       alt_has_hard_reg_cstr = false;
+       alt_has_reg_cstr = false;
        break;
 
        /* Whether or not a numeric constraint allows a register is
@@ -607,6 +644,21 @@ repeat:
            }
          if (reg_info)
            {
+             if (alt_has_reg_cstr)
+               {
+                 error (
+                     "hard register constraints and regular register "
+                     "constraints in one alternative are not supported");
+                 return false;
+               }
+             if (alt_has_hard_reg_cstr)
+               {
+                 error (
+                     "multiple hard register constraints in one "
+                     "alternative are not supported");
+                 return false;
+               }
+             alt_has_hard_reg_cstr = true;
              int regno = decode_hard_reg_constraint (constraint + j);
              if (regno < 0)
                {
@@ -666,7 +718,17 @@ repeat:
        enum constraint_num cn = lookup_constraint (constraint + j);
        if (reg_class_for_constraint (cn) != NO_REGS
            || insn_extra_address_constraint (cn))
-         *allows_reg = true;
+         {
+           if (alt_has_hard_reg_cstr)
+             {
+               error (
+                   "hard register constraints and regular register "
+                   "constraints in one alternative are not supported");
+               return false;
+             }
+           alt_has_reg_cstr = true;
+           *allows_reg = true;
+         }
        else if (insn_extra_memory_constraint (cn)
                 || insn_extra_special_memory_constraint (cn)
                 || insn_extra_relaxed_memory_constraint (cn))
diff --git a/gcc/testsuite/gcc.dg/asm-hard-reg-error-1.c 
b/gcc/testsuite/gcc.dg/asm-hard-reg-error-1.c
index 0a31c8508c76..3569c6d28adc 100644
--- a/gcc/testsuite/gcc.dg/asm-hard-reg-error-1.c
+++ b/gcc/testsuite/gcc.dg/asm-hard-reg-error-1.c
@@ -65,7 +65,6 @@ test (void)
   __asm__ ("" :: GPR1","GPR2 (42), GPR2","GPR3 (42));
   __asm__ ("" :: GPR1","GPR2 (42), GPR3","GPR2 (42)); /* { dg-error "multiple 
inputs to hard register" } */
   __asm__ ("" :: GPR1","GPR2 (42), GPR1","GPR3 (42)); /* { dg-error "multiple 
inputs to hard register" } */
-  __asm__ ("" :: GPR1 GPR2 (42), GPR2 (42)); /* { dg-error "multiple inputs to 
hard register" } */
   __asm__ ("" : "+"GPR1 (x), "="GPR1 (y)); /* { dg-error "multiple outputs to 
hard register" } */
   __asm__ ("" : "="GPR1 (y) : GPR1 (42), "0" (42)); /* { dg-error "multiple 
inputs to hard register" } */
   __asm__ ("" : "+"GPR1 (x) : GPR1 (42)); /* { dg-error "multiple inputs to 
hard register" } */
@@ -74,7 +73,7 @@ test (void)
   __asm__ ("" : "="GPR2 (gpr1)); /* { dg-error "constraint and register 'asm' 
for output operand 0 are unsatisfiable" } */
   __asm__ ("" :: GPR2 (gpr1)); /* { dg-error "constraint and register 'asm' 
for input operand 0 are unsatisfiable" } */
   __asm__ ("" : "="GPR1 (x) : "0" (gpr1));
-  __asm__ ("" : "="GPR1 GPR2 (x) : "0" (gpr1)); /* { dg-error "constraint and 
register 'asm' for input operand 0 are unsatisfiable" } */
+  __asm__ ("" : "="GPR2 (x) : "0" (gpr1)); /* { dg-error "constraint and 
register 'asm' for input operand 0 are unsatisfiable" } */
 
   __asm__ ("" : "=&"GPR1 (x) : "0" (gpr1));
   __asm__ ("" : "=&"GPR1 (x) : "0" (42));
diff --git a/gcc/testsuite/gcc.dg/asm-hard-reg-error-6.c 
b/gcc/testsuite/gcc.dg/asm-hard-reg-error-6.c
new file mode 100644
index 000000000000..f5829bda9213
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/asm-hard-reg-error-6.c
@@ -0,0 +1,35 @@
+/* { dg-do compile { target lra } } */
+
+#if defined __hppa__
+# define R0 "20"
+# define R1 "21"
+#elif defined __AVR__
+# define R0 "20"
+# define R1 "24"
+#elif defined __PRU__
+# define R0 "0"
+# define R1 "4"
+#else
+# define R0 "0"
+# define R1 "1"
+#endif
+
+int
+test (void)
+{
+  int x;
+
+  __asm__ ("" : "={"R0"}{"R1"}" (x));            /* { dg-error "multiple hard 
register constraints in one alternative are not supported" } */
+  __asm__ ("" : "={"R0"}m{"R1"}" (x) : "r" (x)); /* { dg-error "multiple hard 
register constraints in one alternative are not supported" } */
+  __asm__ ("" : "={"R0"}m" (x) : "r" (x));
+  __asm__ ("" : "=r" (x) : "{"R0"}{"R1"}" (x));  /* { dg-error "multiple hard 
register constraints in one alternative are not supported" } */
+  __asm__ ("" : "=r" (x) : "{"R0"}i{"R1"}" (x)); /* { dg-error "multiple hard 
register constraints in one alternative are not supported" } */
+  __asm__ ("" : "=r" (x) : "{"R0"}i" (x));
+
+  __asm__ ("" : "={"R0"}r" (x) : "r" (x)); /* { dg-error "hard register 
constraints and regular register constraints in one alternative are not 
supported" } */
+  __asm__ ("" : "=r{"R0"}" (x) : "r" (x)); /* { dg-error "hard register 
constraints and regular register constraints in one alternative are not 
supported" } */
+  __asm__ ("" : "=r" (x) : "{"R0"}r" (x)); /* { dg-error "hard register 
constraints and regular register constraints in one alternative are not 
supported" } */
+  __asm__ ("" : "=r" (x) : "r{"R0"}" (x)); /* { dg-error "hard register 
constraints and regular register constraints in one alternative are not 
supported" } */
+
+  return x;
+}

Reply via email to