diff options
author | Michael Matz <matz@suse.de> | 2007-09-28 13:31:50 +0000 |
---|---|---|
committer | Michael Matz <matz@gcc.gnu.org> | 2007-09-28 13:31:50 +0000 |
commit | 53220215a8926ffe3aef50e7a79f8e3bb15859f3 (patch) | |
tree | 4b854e7c1b701afce564e0ce3d39398bcbd379fa /gcc | |
parent | bd69daef031ae2afefc43f72e5050e006dc142fe (diff) | |
download | gcc-53220215a8926ffe3aef50e7a79f8e3bb15859f3.zip gcc-53220215a8926ffe3aef50e7a79f8e3bb15859f3.tar.gz gcc-53220215a8926ffe3aef50e7a79f8e3bb15859f3.tar.bz2 |
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
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/function.c | 51 |
2 files changed, 52 insertions, 5 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 8613621..46eaa22 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -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. diff --git a/gcc/function.c b/gcc/function.c index 5f2dd48..c373684 100644 --- a/gcc/function.c +++ b/gcc/function.c @@ -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; } |