diff options
author | Bernd Schmidt <bernd.schmidt@analog.com> | 2005-06-15 09:35:15 +0000 |
---|---|---|
committer | Bernd Schmidt <bernds@gcc.gnu.org> | 2005-06-15 09:35:15 +0000 |
commit | d7f88d86489c2d9868994347173c0b9d5f7ef285 (patch) | |
tree | b40cadba77aa51e2ccdab31a99a181393d469ee4 /gcc/reload1.c | |
parent | ae973d6ae8d82bb7612603c8a08b21374a8aab29 (diff) | |
download | gcc-d7f88d86489c2d9868994347173c0b9d5f7ef285.zip gcc-d7f88d86489c2d9868994347173c0b9d5f7ef285.tar.gz gcc-d7f88d86489c2d9868994347173c0b9d5f7ef285.tar.bz2 |
Makefile.in (local-alloc.o): Depend on $(GGC_H) and reload.h.
* Makefile.in (local-alloc.o): Depend on $(GGC_H) and reload.h.
* local-alloc.c: Include "ggc.h" and "reload.h".
(struct equivalence): New member is_arg_equivalence.
(local_alloc): Always call update_equiv_regs.
(update_equiv_regs): Allocate reg_equiv_init; set reg_equiv_init_size.
Detect equivalences made by stores to memory in a second pass.
Return early if not optimizing.
Initialize reg_equiv_init for all equivalences; treat equivalences for
REG_EQUIV notes existing before this pass specially.
(no_equiv): Don't clear reg_equiv_init or remove notes if the
is_arg_equivalence field is set.
* reload.h (reg_equiv_init, reg_equiv_init_size): Declare.
* reload1.c (reg_equiv_init): No longer static.
(reg_equiv_init_size): New variable.
(reload): Don't allocate reg_equiv_init; don't free it when done but
clear it.
Restructure equivalence set up code not to set reg_equiv_init, but to
clear it when we can't use an equivalence.
Undo change disabling equivalences for MEM_READONLY_P memrefs.
Dump equivalencing insns to dump_file.
From-SVN: r100975
Diffstat (limited to 'gcc/reload1.c')
-rw-r--r-- | gcc/reload1.c | 153 |
1 files changed, 70 insertions, 83 deletions
diff --git a/gcc/reload1.c b/gcc/reload1.c index 0caa411..3176dca 100644 --- a/gcc/reload1.c +++ b/gcc/reload1.c @@ -120,7 +120,8 @@ static unsigned int *reg_max_ref_width; /* Element N is the list of insns that initialized reg N from its equivalent constant or memory slot. */ -static rtx *reg_equiv_init; +rtx *reg_equiv_init; +int reg_equiv_init_size; /* Vector to remember old contents of reg_renumber before spilling. */ static short *reg_old_renumber; @@ -693,7 +694,6 @@ reload (rtx first, int global) reg_equiv_constant = xcalloc (max_regno, sizeof (rtx)); reg_equiv_mem = xcalloc (max_regno, sizeof (rtx)); - reg_equiv_init = xcalloc (max_regno, sizeof (rtx)); reg_equiv_address = xcalloc (max_regno, sizeof (rtx)); reg_max_ref_width = xcalloc (max_regno, sizeof (int)); reg_old_renumber = xcalloc (max_regno, sizeof (short)); @@ -719,101 +719,88 @@ reload (rtx first, int global) && GET_MODE (insn) != VOIDmode) PUT_MODE (insn, VOIDmode); + if (INSN_P (insn)) + scan_paradoxical_subregs (PATTERN (insn)); + if (set != 0 && REG_P (SET_DEST (set))) { rtx note = find_reg_note (insn, REG_EQUIV, NULL_RTX); - if (note - && (! function_invariant_p (XEXP (note, 0)) - || ! flag_pic - /* A function invariant is often CONSTANT_P but may - include a register. We promise to only pass - CONSTANT_P objects to LEGITIMATE_PIC_OPERAND_P. */ - || (CONSTANT_P (XEXP (note, 0)) - && LEGITIMATE_PIC_OPERAND_P (XEXP (note, 0))))) + rtx x; + + if (! note) + continue; + + i = REGNO (SET_DEST (set)); + x = XEXP (note, 0); + + if (i <= LAST_VIRTUAL_REGISTER) + continue; + + if (! function_invariant_p (x) + || ! flag_pic + /* A function invariant is often CONSTANT_P but may + include a register. We promise to only pass + CONSTANT_P objects to LEGITIMATE_PIC_OPERAND_P. */ + || (CONSTANT_P (x) + && LEGITIMATE_PIC_OPERAND_P (x))) { - rtx x = XEXP (note, 0); - i = REGNO (SET_DEST (set)); - if (i > LAST_VIRTUAL_REGISTER) + /* It can happen that a REG_EQUIV note contains a MEM + that is not a legitimate memory operand. As later + stages of reload assume that all addresses found + in the reg_equiv_* arrays were originally legitimate, + we ignore such REG_EQUIV notes. */ + if (memory_operand (x, VOIDmode)) { - /* It can happen that a REG_EQUIV note contains a MEM - that is not a legitimate memory operand. As later - stages of reload assume that all addresses found - in the reg_equiv_* arrays were originally legitimate, - - It can also happen that a REG_EQUIV note contains a - readonly memory location. If the destination pseudo - is set from some other value (typically a different - pseudo), and the destination pseudo does not get a - hard reg, then reload will replace the destination - pseudo with its equivalent memory location. This - is horribly bad as it creates a store to a readonly - memory location and a runtime segfault. To avoid - this problem we reject readonly memory locations - for equivalences. This is overly conservative as - we could find all sets of the destination pseudo - and remove them as they should be redundant. */ - if (memory_operand (x, VOIDmode) && ! MEM_READONLY_P (x)) + /* Always unshare the equivalence, so we can + substitute into this insn without touching the + equivalence. */ + reg_equiv_memory_loc[i] = copy_rtx (x); + } + else if (function_invariant_p (x)) + { + if (GET_CODE (x) == PLUS) { - /* Always unshare the equivalence, so we can - substitute into this insn without touching the - equivalence. */ - reg_equiv_memory_loc[i] = copy_rtx (x); + /* This is PLUS of frame pointer and a constant, + and might be shared. Unshare it. */ + reg_equiv_constant[i] = copy_rtx (x); + num_eliminable_invariants++; } - else if (function_invariant_p (x)) + else if (x == frame_pointer_rtx + || x == arg_pointer_rtx) { - if (GET_CODE (x) == PLUS) - { - /* This is PLUS of frame pointer and a constant, - and might be shared. Unshare it. */ - reg_equiv_constant[i] = copy_rtx (x); - num_eliminable_invariants++; - } - else if (x == frame_pointer_rtx - || x == arg_pointer_rtx) - { - reg_equiv_constant[i] = x; - num_eliminable_invariants++; - } - else if (LEGITIMATE_CONSTANT_P (x)) - reg_equiv_constant[i] = x; - else - { - reg_equiv_memory_loc[i] - = force_const_mem (GET_MODE (SET_DEST (set)), x); - if (!reg_equiv_memory_loc[i]) - continue; - } + reg_equiv_constant[i] = x; + num_eliminable_invariants++; } + else if (LEGITIMATE_CONSTANT_P (x)) + reg_equiv_constant[i] = x; else - continue; - - /* If this register is being made equivalent to a MEM - and the MEM is not SET_SRC, the equivalencing insn - is one with the MEM as a SET_DEST and it occurs later. - So don't mark this insn now. */ - if (!MEM_P (x) - || rtx_equal_p (SET_SRC (set), x)) - reg_equiv_init[i] - = gen_rtx_INSN_LIST (VOIDmode, insn, reg_equiv_init[i]); + { + reg_equiv_memory_loc[i] + = force_const_mem (GET_MODE (SET_DEST (set)), x); + if (! reg_equiv_memory_loc[i]) + reg_equiv_init[i] = NULL_RTX; + } + } + else + { + reg_equiv_init[i] = NULL_RTX; + continue; } } + else + reg_equiv_init[i] = NULL_RTX; } - - /* If this insn is setting a MEM from a register equivalent to it, - this is the equivalencing insn. */ - else if (set && MEM_P (SET_DEST (set)) - && REG_P (SET_SRC (set)) - && reg_equiv_memory_loc[REGNO (SET_SRC (set))] - && rtx_equal_p (SET_DEST (set), - reg_equiv_memory_loc[REGNO (SET_SRC (set))])) - reg_equiv_init[REGNO (SET_SRC (set))] - = gen_rtx_INSN_LIST (VOIDmode, insn, - reg_equiv_init[REGNO (SET_SRC (set))]); - - if (INSN_P (insn)) - scan_paradoxical_subregs (PATTERN (insn)); } + if (dump_file) + for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++) + if (reg_equiv_init[i]) + { + fprintf (dump_file, "init_insns for %u: ", i); + print_inline_rtx (dump_file, reg_equiv_init[i], 20); + fprintf (dump_file, "\n"); + } + init_elim_table (); first_label_num = get_first_label_num (); @@ -1260,7 +1247,7 @@ reload (rtx first, int global) free (offsets_at); free (reg_equiv_mem); - free (reg_equiv_init); + reg_equiv_init = 0; free (reg_equiv_address); free (reg_max_ref_width); free (reg_old_renumber); |