recog.c (check_asm_operands): Treat indeterminate operand ok results as success.

* recog.c (check_asm_operands): Treat indeterminate operand ok
        results as success.  Try harder to resolve a matching constraint.
        * stmt.c (expand_asm_operands): Recognize when an output operand's
        constraint does not allow memory.  Treat indeterminate operand ok
        results as failure.  Try harder to resolve a matching constraint.

From-SVN: r24959
This commit is contained in:
Richard Henderson 1999-02-01 12:03:23 -08:00 committed by Richard Henderson
parent 5326f06d7f
commit 1afbe1c4e6
3 changed files with 59 additions and 14 deletions

View File

@ -1,3 +1,11 @@
Mon Feb 1 20:00:40 1999 Richard Henderson <rth@cygnus.com>
* recog.c (check_asm_operands): Treat indeterminate operand ok
results as success. Try harder to resolve a matching constraint.
* stmt.c (expand_asm_operands): Recognize when an output operand's
constraint does not allow memory. Treat indeterminate operand ok
results as failure. Try harder to resolve a matching constraint.
Mon Feb 1 15:00:02 1999 Ken Raeburn <raeburn@cygnus.com> Mon Feb 1 15:00:02 1999 Ken Raeburn <raeburn@cygnus.com>
Use varrays for constant-equivalence data: Use varrays for constant-equivalence data:

View File

@ -188,7 +188,9 @@ check_asm_operands (x)
for (i = 0; i < noperands; i++) for (i = 0; i < noperands; i++)
{ {
const char *c = constraints[i]; const char *c = constraints[i];
if (ISDIGIT ((unsigned char)c[0])) if (c[0] == '%')
c++;
if (ISDIGIT ((unsigned char)c[0]) && c[1] == '\0')
c = constraints[c[0] - '0']; c = constraints[c[0] - '0'];
if (! asm_operand_ok (operands[i], c)) if (! asm_operand_ok (operands[i], c))
@ -1550,13 +1552,16 @@ decode_asm_operands (body, operands, operand_locs, constraints, modes)
return template; return template;
} }
/* Check if an asm_operand matches it's constraints. */ /* Check if an asm_operand matches it's constraints.
Return > 0 if ok, = 0 if bad, < 0 if inconclusive. */
int int
asm_operand_ok (op, constraint) asm_operand_ok (op, constraint)
rtx op; rtx op;
const char *constraint; const char *constraint;
{ {
int result = 0;
/* Use constrain_operands after reload. */ /* Use constrain_operands after reload. */
if (reload_completed) if (reload_completed)
abort (); abort ();
@ -1578,9 +1583,11 @@ asm_operand_ok (op, constraint)
case '0': case '1': case '2': case '3': case '4': case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9': case '5': case '6': case '7': case '8': case '9':
/* Our caller is supposed to have given us the proper /* For best results, our caller should have given us the
matching constraint. */ proper matching constraint, but we can't actually fail
/* abort (); */ the check if they didn't. Indicate that results are
inconclusive. */
result = -1;
break; break;
case 'p': case 'p':
@ -1600,15 +1607,24 @@ asm_operand_ok (op, constraint)
break; break;
case '<': case '<':
/* ??? Before flow, auto inc/dec insns are not supposed to exist,
excepting those that expand_call created. Further, on some
machines which do not have generalized auto inc/dec, an inc/dec
is not a memory_operand.
Match any memory and hope things are resolved after reload. */
if (GET_CODE (op) == MEM if (GET_CODE (op) == MEM
&& (GET_CODE (XEXP (op, 0)) == PRE_DEC && (1
|| GET_CODE (XEXP (op, 0)) == PRE_DEC
|| GET_CODE (XEXP (op, 0)) == POST_DEC)) || GET_CODE (XEXP (op, 0)) == POST_DEC))
return 1; return 1;
break; break;
case '>': case '>':
if (GET_CODE (op) == MEM if (GET_CODE (op) == MEM
&& (GET_CODE (XEXP (op, 0)) == PRE_INC && (1
|| GET_CODE (XEXP (op, 0)) == PRE_INC
|| GET_CODE (XEXP (op, 0)) == POST_INC)) || GET_CODE (XEXP (op, 0)) == POST_INC))
return 1; return 1;
break; break;
@ -1745,7 +1761,7 @@ asm_operand_ok (op, constraint)
} }
} }
return 0; return result;
} }
/* Given an rtx *P, if it is a sum containing an integer constant term, /* Given an rtx *P, if it is a sum containing an integer constant term,

View File

@ -1251,6 +1251,7 @@ expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line)
int j; int j;
int is_inout = 0; int is_inout = 0;
int allows_reg = 0; int allows_reg = 0;
int allows_mem = 0;
/* If there's an erroneous arg, emit no insn. */ /* If there's an erroneous arg, emit no insn. */
if (TREE_TYPE (val) == error_mark_node) if (TREE_TYPE (val) == error_mark_node)
@ -1316,8 +1317,7 @@ expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line)
break; break;
case '?': case '!': case '*': case '&': case '?': case '!': case '*': case '&':
case 'V': case 'm': case 'o': case '<': case '>': case 'E': case 'F': case 'G': case 'H':
case 'E': case 'F': case 'G': case 'H': case 'X':
case 's': case 'i': case 'n': case 's': case 'i': case 'n':
case 'I': case 'J': case 'K': case 'L': case 'M': case 'I': case 'J': case 'K': case 'L': case 'M':
case 'N': case 'O': case 'P': case ',': case 'N': case 'O': case 'P': case ',':
@ -1331,7 +1331,23 @@ expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line)
error ("matching constraint not valid in output operand"); error ("matching constraint not valid in output operand");
break; break;
case 'p': case 'g': case 'r': case 'V': case 'm': case 'o':
allows_mem = 1;
break;
case '<': case '>':
/* ??? Before flow, auto inc/dec insns are not supposed to exist,
excepting those that expand_call created. So match memory
and hope. */
allows_mem = 1;
break;
case 'g': case 'X':
allows_reg = 1;
allows_mem = 1;
break;
case 'p': case 'r':
default: default:
allows_reg = 1; allows_reg = 1;
break; break;
@ -1342,8 +1358,10 @@ expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line)
Make the asm insn write into that, then our caller will copy it to Make the asm insn write into that, then our caller will copy it to
the real output operand. Likewise for promoted variables. */ the real output operand. Likewise for promoted variables. */
if (TREE_CODE (val) == INDIRECT_REF if ((TREE_CODE (val) == INDIRECT_REF
&& allows_mem)
|| (TREE_CODE_CLASS (TREE_CODE (val)) == 'd' || (TREE_CODE_CLASS (TREE_CODE (val)) == 'd'
&& (allows_mem || GET_CODE (DECL_RTL (val)) == REG)
&& ! (GET_CODE (DECL_RTL (val)) == REG && ! (GET_CODE (DECL_RTL (val)) == REG
&& GET_MODE (DECL_RTL (val)) != TYPE_MODE (type))) && GET_MODE (DECL_RTL (val)) != TYPE_MODE (type)))
|| ! allows_reg || ! allows_reg
@ -1358,6 +1376,8 @@ expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line)
if (! allows_reg && GET_CODE (output_rtx[i]) != MEM) if (! allows_reg && GET_CODE (output_rtx[i]) != MEM)
error ("output number %d not directly addressable", i); error ("output number %d not directly addressable", i);
if (! allows_mem && GET_CODE (output_rtx[i]) == MEM)
error ("output number %d not restored to memory", i);
} }
else else
{ {
@ -1472,7 +1492,8 @@ expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line)
} }
/* Try and find the real constraint for this dup. */ /* Try and find the real constraint for this dup. */
if (j == 0 && c_len == 1) if ((j == 0 && c_len == 1)
|| (j == 1 && c_len == 2 && constraint[0] == '%'))
{ {
tree o = outputs; tree o = outputs;
for (j = constraint[j] - '0'; j > 0; --j) for (j = constraint[j] - '0'; j > 0; --j)
@ -1502,7 +1523,7 @@ expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line)
op = expand_expr (TREE_VALUE (tail), NULL_RTX, VOIDmode, 0); op = expand_expr (TREE_VALUE (tail), NULL_RTX, VOIDmode, 0);
if (! asm_operand_ok (op, constraint)) if (asm_operand_ok (op, constraint) <= 0)
{ {
if (allows_reg) if (allows_reg)
op = force_reg (TYPE_MODE (TREE_TYPE (TREE_VALUE (tail))), op); op = force_reg (TYPE_MODE (TREE_TYPE (TREE_VALUE (tail))), op);