diff options
author | Hans-Peter Nilsson <hp@axis.com> | 2005-11-19 21:56:17 +0000 |
---|---|---|
committer | Hans-Peter Nilsson <hp@gcc.gnu.org> | 2005-11-19 21:56:17 +0000 |
commit | ff0d9879ab0f30316f394523dfa3a1cb94a33a39 (patch) | |
tree | a4c70facc1afd964e0a764c2ee6dc7d1a06b87d7 /gcc | |
parent | 152f76ec3df4c21d3ffe641728cad33336912d8f (diff) | |
download | gcc-ff0d9879ab0f30316f394523dfa3a1cb94a33a39.zip gcc-ff0d9879ab0f30316f394523dfa3a1cb94a33a39.tar.gz gcc-ff0d9879ab0f30316f394523dfa3a1cb94a33a39.tar.bz2 |
re PR middle-end/24912 (m68k build failure: ICE: in reload_cse_simplify_operands)
PR middle-end/24912
PR middle-end/24750
* reload.c (find_reloads_address_1): Mention dependency on
gen_reload.
* reload1.c (gen_reload): For IN with an unary operation, try
moving inner expression to OUT if trivial SET is not valid.
Confirm that the result is valid. Move common code block into...
(emit_insn_if_valid_for_reload): New function.
From-SVN: r107231
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 11 | ||||
-rw-r--r-- | gcc/reload.c | 4 | ||||
-rw-r--r-- | gcc/reload1.c | 115 |
3 files changed, 95 insertions, 35 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 446c528..a06adad 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,14 @@ +2005-11-19 Hans-Peter Nilsson <hp@axis.com> + + PR middle-end/24912 + PR middle-end/24750 + * reload.c (find_reloads_address_1): Mention dependency on + gen_reload. + * reload1.c (gen_reload): For IN with an unary operation, try + moving inner expression to OUT if trivial SET is not valid. + Confirm that the result is valid. Move common code block into... + (emit_insn_if_valid_for_reload): New function. + 2005-11-19 Richard Guenther <rguenther@suse.de> * fold-const.c (fold_indirect_ref_1): Make sure we fold diff --git a/gcc/reload.c b/gcc/reload.c index 0503f5a..ed8aca5 100644 --- a/gcc/reload.c +++ b/gcc/reload.c @@ -5311,7 +5311,9 @@ update_auto_inc_notes (rtx insn ATTRIBUTE_UNUSED, int regno ATTRIBUTE_UNUSED, occurs as part of an address. Also, this is not fully machine-customizable; it works for machines such as VAXen and 68000's and 32000's, but other possible machines - could have addressing modes that this does not handle right. */ + could have addressing modes that this does not handle right. + If you add push_reload calls here, you need to make sure gen_reload + handles those cases gracefully. */ static int find_reloads_address_1 (enum machine_mode mode, rtx x, int context, diff --git a/gcc/reload1.c b/gcc/reload1.c index ba395da..4a7d22d 100644 --- a/gcc/reload1.c +++ b/gcc/reload1.c @@ -437,6 +437,7 @@ static void add_auto_inc_notes (rtx, rtx); static void copy_eh_notes (rtx, rtx); static int reloads_conflict (int, int); static rtx gen_reload (rtx, rtx, int, enum reload_type); +static rtx emit_insn_if_valid_for_reload (rtx); /* Initialize the reload pass once per compilation. */ @@ -7449,6 +7450,32 @@ emit_reload_insns (struct insn_chain *chain) IOR_HARD_REG_SET (reg_reloaded_dead, reg_reloaded_died); } +/* Go through the motions to emit INSN and test if it is strictly valid. + Return the emitted insn if valid, else return NULL. */ + +static rtx +emit_insn_if_valid_for_reload (rtx insn) +{ + rtx last = get_last_insn (); + int code; + + insn = emit_insn (insn); + code = recog_memoized (insn); + + if (code >= 0) + { + extract_insn (insn); + /* We want constrain operands to treat this insn strictly in its + validity determination, i.e., the way it would after reload has + completed. */ + if (constrain_operands (1)) + return insn; + } + + delete_insns_since (last); + return NULL; +} + /* Emit code to perform a reload from IN (which may be a reload register) to OUT (which may also be a reload register). IN or OUT is from operand OPNUM with reload type TYPE. @@ -7485,6 +7512,12 @@ gen_reload (rtx out, rtx in, int opnum, enum reload_type type) trying to emit a single insn to perform the add. If it is not valid, we use a two insn sequence. + Or we can be asked to reload an unary operand that was a fragment of + an addressing mode, into a register. If it isn't recognized as-is, + we try making the unop operand and the reload-register the same: + (set reg:X (unop:X expr:Y)) + -> (set reg:Y expr:Y) (set reg:X (unop:X reg:Y)). + Finally, we could be called to handle an 'o' constraint by putting an address into a register. In that case, we first try to do this with a named pattern of "reload_load_address". If no such pattern @@ -7542,20 +7575,9 @@ gen_reload (rtx out, rtx in, int opnum, enum reload_type type) if (op0 != XEXP (in, 0) || op1 != XEXP (in, 1)) in = gen_rtx_PLUS (GET_MODE (in), op0, op1); - insn = emit_insn (gen_rtx_SET (VOIDmode, out, in)); - code = recog_memoized (insn); - - if (code >= 0) - { - extract_insn (insn); - /* We want constrain operands to treat this insn strictly in - its validity determination, i.e., the way it would after reload - has completed. */ - if (constrain_operands (1)) - return insn; - } - - delete_insns_since (last); + insn = emit_insn_if_valid_for_reload (gen_rtx_SET (VOIDmode, out, in)); + if (insn) + return insn; /* If that failed, we must use a conservative two-insn sequence. @@ -7591,29 +7613,17 @@ gen_reload (rtx out, rtx in, int opnum, enum reload_type type) if (rtx_equal_p (op0, op1)) op1 = out; - insn = emit_insn (gen_add2_insn (out, op1)); - - /* If that failed, copy the address register to the reload register. - Then add the constant to the reload register. */ - - code = recog_memoized (insn); - - if (code >= 0) + insn = emit_insn_if_valid_for_reload (gen_add2_insn (out, op1)); + if (insn) { - extract_insn (insn); - /* We want constrain operands to treat this insn strictly in - its validity determination, i.e., the way it would after reload - has completed. */ - if (constrain_operands (1)) - { - /* Add a REG_EQUIV note so that find_equiv_reg can find it. */ - REG_NOTES (insn) - = gen_rtx_EXPR_LIST (REG_EQUIV, in, REG_NOTES (insn)); - return insn; - } + /* Add a REG_EQUIV note so that find_equiv_reg can find it. */ + REG_NOTES (insn) + = gen_rtx_EXPR_LIST (REG_EQUIV, in, REG_NOTES (insn)); + return insn; } - delete_insns_since (last); + /* If that failed, copy the address register to the reload register. + Then add the constant to the reload register. */ gen_reload (out, op1, opnum, type); insn = emit_insn (gen_add2_insn (out, op0)); @@ -7643,7 +7653,44 @@ gen_reload (rtx out, rtx in, int opnum, enum reload_type type) gen_reload (out, loc, opnum, type); } #endif + else if (REG_P (out) && UNARY_P (in)) + { + rtx insn; + rtx op1; + rtx out_moded; + rtx set; + + /* First, try a plain SET. */ + set = emit_insn_if_valid_for_reload (gen_rtx_SET (VOIDmode, out, in)); + if (set) + return set; + + /* If that failed, move the inner operand to the reload + register, and try the same unop with the inner expression + replaced with the reload register. */ + op1 = XEXP (in, 0); + + if (GET_MODE (op1) != GET_MODE (out)) + out_moded = gen_rtx_REG (GET_MODE (op1), REGNO (out)); + else + out_moded = out; + gen_reload (out_moded, op1, opnum, type); + + insn + = gen_rtx_SET (VOIDmode, out, + gen_rtx_fmt_e (GET_CODE (in), GET_MODE (in), + out_moded)); + insn = emit_insn_if_valid_for_reload (insn); + if (insn) + { + REG_NOTES (insn) + = gen_rtx_EXPR_LIST (REG_EQUIV, in, REG_NOTES (insn)); + return insn; + } + + fatal_insn ("Failure trying to reload:", set); + } /* If IN is a simple operand, use gen_move_insn. */ else if (OBJECT_P (in) || GET_CODE (in) == SUBREG) emit_insn (gen_move_insn (out, in)); |