From: Stefan Schulze Frielinghaus <[email protected]>
With the current implementation, for an alternative like {r0}{r1}...{rn}
the last hard register constraint {rn} would always win which is not
what users expect. Therefore, error out in case of multiple hard
register constraints in one alternative.
As far as I can tell right now, there is no inherent problem with
supporting multiple hard register constraints in one alternative or even
ad-hoc register classes. However, in light of reaching stage 4, this is
something for another release.
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:
* 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.
---
Bootstrapped and regtested on s390 and x86_64. Ok for mainline?
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 +++++++++++
3 files changed, 100 insertions(+), 4 deletions(-)
create mode 100644 gcc/testsuite/gcc.dg/asm-hard-reg-error-6.c
diff --git a/gcc/stmt.cc b/gcc/stmt.cc
index 5816fb9b3b6..382a2d75c07 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 0a31c8508c7..3569c6d28ad 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 00000000000..f5829bda921
--- /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;
+}
--
2.52.0