[Patch] Teach genrecog/genoutput that scratch registers require write constraint modifiers

gcc/

	* doc/md.texi (Modifiers): Consistently use "read/write"
	nomenclature rather than "input/output".
	* genrecog.c (constraints_supported_in_insn_p): New.
	(validate_pattern): If needed, also check constraints on
	MATCH_SCRATCH operands.
	* genoutput.c (validate_insn_alternatives): Catch earlyclobber
	operands with no '=' or '+' modifier.

From-SVN: r215388
This commit is contained in:
James Greenhalgh 2014-09-19 10:37:40 +00:00 committed by James Greenhalgh
parent 727dc1217d
commit 5fd4bc9630
4 changed files with 87 additions and 28 deletions

View File

@ -1,3 +1,13 @@
2014-09-19 James Greenhalgh <james.greenhalgh@arm.com>
* doc/md.texi (Modifiers): Consistently use "read/write"
nomenclature rather than "input/output".
* genrecog.c (constraints_supported_in_insn_p): New.
(validate_pattern): If needed, also check constraints on
MATCH_SCRATCH operands.
* genoutput.c (validate_insn_alternatives): Catch earlyclobber
operands with no '=' or '+' modifier.
2014-09-19 James Greenhalgh <james.greenhalgh@arm.com>
* config/aarch64/aarch64.md (stack_protect_test_<mode>): Mark

View File

@ -1546,18 +1546,18 @@ Here are constraint modifier characters.
@table @samp
@cindex @samp{=} in constraint
@item =
Means that this operand is write-only for this instruction: the previous
value is discarded and replaced by output data.
Means that this operand is written to by this instruction:
the previous value is discarded and replaced by new data.
@cindex @samp{+} in constraint
@item +
Means that this operand is both read and written by the instruction.
When the compiler fixes up the operands to satisfy the constraints,
it needs to know which operands are inputs to the instruction and
which are outputs from it. @samp{=} identifies an output; @samp{+}
identifies an operand that is both input and output; all other operands
are assumed to be input only.
it needs to know which operands are read by the instruction and
which are written by it. @samp{=} identifies an operand which is only
written; @samp{+} identifies an operand that is both read and written; all
other operands are assumed to only be read.
If you specify @samp{=} or @samp{+} in a constraint, you put it in the
first character of the constraint string.
@ -1566,9 +1566,9 @@ first character of the constraint string.
@cindex earlyclobber operand
@item &
Means (in a particular alternative) that this operand is an
@dfn{earlyclobber} operand, which is modified before the instruction is
@dfn{earlyclobber} operand, which is written before the instruction is
finished using the input operands. Therefore, this operand may not lie
in a register that is used as an input operand or as part of any memory
in a register that is read by the instruction or as part of any memory
address.
@samp{&} applies only to the alternative in which it is written. In
@ -1576,16 +1576,19 @@ constraints with multiple alternatives, sometimes one alternative
requires @samp{&} while others do not. See, for example, the
@samp{movdf} insn of the 68000.
An input operand can be tied to an earlyclobber operand if its only
use as an input occurs before the early result is written. Adding
alternatives of this form often allows GCC to produce better code
when only some of the inputs can be affected by the earlyclobber.
See, for example, the @samp{mulsi3} insn of the ARM@.
A operand which is read by the instruction can be tied to an earlyclobber
operand if its only use as an input occurs before the early result is
written. Adding alternatives of this form often allows GCC to produce
better code when only some of the read operands can be affected by the
earlyclobber. See, for example, the @samp{mulsi3} insn of the ARM@.
Furthermore, if the @dfn{earlyclobber} operand is also read/write operand, then
that operand is modified only after it's used.
Furthermore, if the @dfn{earlyclobber} operand is also a read/write
operand, then that operand is written only after it's used.
@samp{&} does not obviate the need to write @samp{=} or @samp{+}.
@samp{&} does not obviate the need to write @samp{=} or @samp{+}. As
@dfn{earlyclobber} operands are always written, a read-only
@dfn{earlyclobber} operand is ill-formed and will be rejected by the
compiler.
@cindex @samp{%} in constraint
@item %
@ -1593,7 +1596,7 @@ Declares the instruction to be commutative for this operand and the
following operand. This means that the compiler may interchange the
two operands if that is the cheapest way to make all operands fit the
constraints. @samp{%} applies to all alternatives and must appear as
the first character in the constraint. Only input operands can use
the first character in the constraint. Only read-only operands can use
@samp{%}.
@ifset INTERNALS

View File

@ -769,6 +769,7 @@ validate_insn_alternatives (struct data *d)
char c;
int which_alternative = 0;
int alternative_count_unsure = 0;
bool seen_write = false;
for (p = d->operand[start].constraint; (c = *p); p += len)
{
@ -777,6 +778,18 @@ validate_insn_alternatives (struct data *d)
error_with_line (d->lineno,
"character '%c' can only be used at the"
" beginning of a constraint string", c);
if (c == '=' || c == '+')
seen_write = true;
/* Earlyclobber operands must always be marked write-only
or read/write. */
if (!seen_write && c == '&')
error_with_line (d->lineno,
"earlyclobber operands may not be"
" read-only in alternative %d",
which_alternative);
if (ISSPACE (c) || strchr (indep_constraints, c))
len = 1;
else if (ISDIGIT (c))

View File

@ -415,6 +415,18 @@ find_matching_operand (rtx pattern, int n)
return NULL;
}
/* In DEFINE_EXPAND, DEFINE_SPLIT, and DEFINE_PEEPHOLE2, we
don't use the MATCH_OPERAND constraint, only the predicate.
This is confusing to folks doing new ports, so help them
not make the mistake. */
static bool
constraints_supported_in_insn_p (rtx insn)
{
return !(GET_CODE (insn) == DEFINE_EXPAND
|| GET_CODE (insn) == DEFINE_SPLIT
|| GET_CODE (insn) == DEFINE_PEEPHOLE2);
}
/* Check for various errors in patterns. SET is nonnull for a destination,
and is the complete set pattern. SET_CODE is '=' for normal sets, and
@ -432,7 +444,32 @@ validate_pattern (rtx pattern, rtx insn, rtx set, int set_code)
switch (code)
{
case MATCH_SCRATCH:
return;
{
const char constraints0 = XSTR (pattern, 1)[0];
if (!constraints_supported_in_insn_p (insn))
{
if (constraints0)
{
error_with_line (pattern_lineno,
"constraints not supported in %s",
rtx_name[GET_CODE (insn)]);
}
return;
}
/* If a MATCH_SCRATCH is used in a context requiring an write-only
or read/write register, validate that. */
if (set_code == '='
&& constraints0 != '='
&& constraints0 != '+')
{
error_with_line (pattern_lineno,
"operand %d missing output reload",
XINT (pattern, 0));
}
return;
}
case MATCH_DUP:
case MATCH_OP_DUP:
case MATCH_PAR_DUP:
@ -467,18 +504,14 @@ validate_pattern (rtx pattern, rtx insn, rtx set, int set_code)
{
const char constraints0 = XSTR (pattern, 2)[0];
/* In DEFINE_EXPAND, DEFINE_SPLIT, and DEFINE_PEEPHOLE2, we
don't use the MATCH_OPERAND constraint, only the predicate.
This is confusing to folks doing new ports, so help them
not make the mistake. */
if (GET_CODE (insn) == DEFINE_EXPAND
|| GET_CODE (insn) == DEFINE_SPLIT
|| GET_CODE (insn) == DEFINE_PEEPHOLE2)
if (!constraints_supported_in_insn_p (insn))
{
if (constraints0)
error_with_line (pattern_lineno,
"constraints not supported in %s",
rtx_name[GET_CODE (insn)]);
{
error_with_line (pattern_lineno,
"constraints not supported in %s",
rtx_name[GET_CODE (insn)]);
}
}
/* A MATCH_OPERAND that is a SET should have an output reload. */