+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
@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.
@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
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 %
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
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)
{
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))
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
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:
{
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. */