While working on PR99454 I found that IR incorrectly processes
constraints starting with '0'..'9' and containing more one digit. It is
probably a rare event and it does not result in wrong code generation.
Simply, the generated code will be more efficient.
In any case the following patch fixes this pitfall. The patch was
successfully bootstrapped and tested on x86-64.
commit 63d74fed4566f1de583c368ecb9e2fc423fb1c87 (HEAD -> master)
Author: Vladimir N. Makarov <vmaka...@redhat.com>
Date: Tue Mar 9 17:18:58 2021 -0500
IRA: Process digital constraints containing more one digit
gcc/ChangeLog:
* ira.c (ira_setup_alts, ira_get_dup_out_num): Process digital
constraints > 9.
* ira-lives.c (single_reg_class): Ditto.
diff --git a/gcc/ira-lives.c b/gcc/ira-lives.c
index f63da79a78e..f3341313bd1 100644
--- a/gcc/ira-lives.c
+++ b/gcc/ira-lives.c
@@ -855,53 +855,61 @@ single_reg_class (const char *constraints, rtx op, rtx
equiv_const)
cl = NO_REGS;
alternative_mask preferred = preferred_alternatives;
- for (; (c = *constraints); constraints += CONSTRAINT_LEN (c, constraints))
- if (c == '#')
- preferred &= ~ALTERNATIVE_BIT (0);
- else if (c == ',')
- preferred >>= 1;
- else if (preferred & 1)
- switch (c)
- {
- case 'g':
- return NO_REGS;
-
- default:
- /* ??? Is this the best way to handle memory constraints? */
- cn = lookup_constraint (constraints);
- if (insn_extra_memory_constraint (cn)
- || insn_extra_special_memory_constraint (cn)
- || insn_extra_address_constraint (cn))
- return NO_REGS;
- if (constraint_satisfied_p (op, cn)
- || (equiv_const != NULL_RTX
- && CONSTANT_P (equiv_const)
- && constraint_satisfied_p (equiv_const, cn)))
+ while ((c = *constraints))
+ {
+ if (c == '#')
+ preferred &= ~ALTERNATIVE_BIT (0);
+ else if (c == ',')
+ preferred >>= 1;
+ else if (preferred & 1)
+ switch (c)
+ {
+ case 'g':
return NO_REGS;
- next_cl = reg_class_for_constraint (cn);
- if (next_cl == NO_REGS)
+
+ default:
+ /* ??? Is this the best way to handle memory constraints? */
+ cn = lookup_constraint (constraints);
+ if (insn_extra_memory_constraint (cn)
+ || insn_extra_special_memory_constraint (cn)
+ || insn_extra_address_constraint (cn))
+ return NO_REGS;
+ if (constraint_satisfied_p (op, cn)
+ || (equiv_const != NULL_RTX
+ && CONSTANT_P (equiv_const)
+ && constraint_satisfied_p (equiv_const, cn)))
+ return NO_REGS;
+ next_cl = reg_class_for_constraint (cn);
+ if (next_cl == NO_REGS)
+ break;
+ if (cl == NO_REGS
+ ? ira_class_singleton[next_cl][GET_MODE (op)] < 0
+ : (ira_class_singleton[cl][GET_MODE (op)]
+ != ira_class_singleton[next_cl][GET_MODE (op)]))
+ return NO_REGS;
+ cl = next_cl;
break;
- if (cl == NO_REGS
- ? ira_class_singleton[next_cl][GET_MODE (op)] < 0
- : (ira_class_singleton[cl][GET_MODE (op)]
- != ira_class_singleton[next_cl][GET_MODE (op)]))
- return NO_REGS;
- cl = next_cl;
- break;
-
- case '0': case '1': case '2': case '3': case '4':
- case '5': case '6': case '7': case '8': case '9':
- next_cl
- = single_reg_class (recog_data.constraints[c - '0'],
- recog_data.operand[c - '0'], NULL_RTX);
- if (cl == NO_REGS
- ? ira_class_singleton[next_cl][GET_MODE (op)] < 0
- : (ira_class_singleton[cl][GET_MODE (op)]
- != ira_class_singleton[next_cl][GET_MODE (op)]))
- return NO_REGS;
- cl = next_cl;
- break;
- }
+
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ {
+ char *end;
+ unsigned long dup = strtoul (constraints, &end, 10);
+ constraints = end;
+ next_cl
+ = single_reg_class (recog_data.constraints[dup],
+ recog_data.operand[dup], NULL_RTX);
+ if (cl == NO_REGS
+ ? ira_class_singleton[next_cl][GET_MODE (op)] < 0
+ : (ira_class_singleton[cl][GET_MODE (op)]
+ != ira_class_singleton[next_cl][GET_MODE (op)]))
+ return NO_REGS;
+ cl = next_cl;
+ continue;
+ }
+ }
+ constraints += CONSTRAINT_LEN (c, constraints);
+ }
return cl;
}
diff --git a/gcc/ira.c b/gcc/ira.c
index c32ecf814fd..fc77131491d 100644
--- a/gcc/ira.c
+++ b/gcc/ira.c
@@ -1829,7 +1829,10 @@ ira_setup_alts (rtx_insn *insn)
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
{
- rtx other = recog_data.operand[c - '0'];
+ char *end;
+ unsigned long dup = strtoul (p, &end, 10);
+ rtx other = recog_data.operand[dup];
+ len = end - p;
if (MEM_P (other)
? rtx_equal_p (other, op)
: REG_P (op) || SUBREG_P (op))
@@ -1922,7 +1925,7 @@ ira_setup_alts (rtx_insn *insn)
int
ira_get_dup_out_num (int op_num, alternative_mask alts)
{
- int curr_alt, c, original, dup;
+ int curr_alt, c, original;
bool ignore_p, use_commut_op_p;
const char *str;
@@ -1969,18 +1972,22 @@ ira_get_dup_out_num (int op_num, alternative_mask alts)
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
- if (original != -1 && original != c)
- goto fail;
- original = c;
- break;
+ {
+ char *end;
+ int n = (int) strtoul (str, &end, 10);
+ str = end;
+ if (original != -1 && original != n)
+ goto fail;
+ original = n;
+ continue;
+ }
}
str += CONSTRAINT_LEN (c, str);
}
if (original == -1)
goto fail;
- dup = original - '0';
- if (recog_data.operand_type[dup] == OP_OUT)
- return dup;
+ if (recog_data.operand_type[original] == OP_OUT)
+ return original;
fail:
if (use_commut_op_p)
break;