re PR rtl-optimization/33552 (wrong code for multiple output asm, wrong df?)

PR rtl-optimization/33552
        * function.c (match_asm_constraints_1): Check for overlap in
        inputs and replace all occurences.

From-SVN: r128864
This commit is contained in:
Michael Matz 2007-09-28 13:31:50 +00:00 committed by Michael Matz
parent bd69daef03
commit 53220215a8
2 changed files with 52 additions and 5 deletions

View File

@ -1,3 +1,9 @@
2007-09-28 Michael Matz <matz@suse.de>
PR rtl-optimization/33552
* function.c (match_asm_constraints_1): Check for overlap in
inputs and replace all occurences.
2007-09-28 Richard Sandiford <rsandifo@nildram.co.uk>
* config/mips/mips.c (override_options): Fix comment typo.

View File

@ -5663,7 +5663,7 @@ match_asm_constraints_1 (rtx insn, rtx *p_sets, int noutputs)
rtx input, output, insns;
const char *constraint = ASM_OPERANDS_INPUT_CONSTRAINT (op, i);
char *end;
int match;
int match, j;
match = strtoul (constraint, &end, 10);
if (end == constraint)
@ -5672,18 +5672,59 @@ match_asm_constraints_1 (rtx insn, rtx *p_sets, int noutputs)
gcc_assert (match < noutputs);
output = SET_DEST (p_sets[match]);
input = RTVEC_ELT (inputs, i);
if (rtx_equal_p (output, input)
/* Only do the transformation for pseudos. */
if (! REG_P (output)
|| rtx_equal_p (output, input)
|| (GET_MODE (input) != VOIDmode
&& GET_MODE (input) != GET_MODE (output)))
continue;
/* We can't do anything if the output is also used as input,
as we're going to overwrite it. */
for (j = 0; j < ninputs; j++)
if (reg_overlap_mentioned_p (output, RTVEC_ELT (inputs, j)))
break;
if (j != ninputs)
continue;
start_sequence ();
emit_move_insn (copy_rtx (output), input);
RTVEC_ELT (inputs, i) = copy_rtx (output);
emit_move_insn (output, input);
insns = get_insns ();
end_sequence ();
emit_insn_before (insns, insn);
/* Now replace all mentions of the input with output. We can't
just replace the occurence in inputs[i], as the register might
also be used in some other input (or even in an address of an
output), which would mean possibly increasing the number of
inputs by one (namely 'output' in addition), which might pose
a too complicated problem for reload to solve. E.g. this situation:
asm ("" : "=r" (output), "=m" (input) : "0" (input))
Here 'input' is used in two occurences as input (once for the
input operand, once for the address in the second output operand).
If we would replace only the occurence of the input operand (to
make the matching) we would be left with this:
output = input
asm ("" : "=r" (output), "=m" (input) : "0" (output))
Now we suddenly have two different input values (containing the same
value, but different pseudos) where we formerly had only one.
With more complicated asms this might lead to reload failures
which wouldn't have happen without this pass. So, iterate over
all operands and replace all occurences of the register used. */
for (j = 0; j < noutputs; j++)
if (!rtx_equal_p (SET_DEST (p_sets[j]), output)
&& reg_overlap_mentioned_p (input, SET_DEST (p_sets[j])))
SET_DEST (p_sets[j]) = replace_rtx (SET_DEST (p_sets[j]),
input, output);
for (j = 0; j < ninputs; j++)
if (reg_overlap_mentioned_p (input, RTVEC_ELT (inputs, j)))
RTVEC_ELT (inputs, j) = replace_rtx (RTVEC_ELT (inputs, j),
input, output);
changed = true;
}