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