From b60a8416357bb6e8166547bef7bc67c56f104557 Mon Sep 17 00:00:00 2001 From: "J\"orn Rennecke" Date: Fri, 1 May 1998 17:40:53 +0000 Subject: [PATCH] reload.c (find_reloads): Emit USEs to mark where a pseudo is reloaced with the MEM of its stack slot. * reload.c (find_reloads): Emit USEs to mark where a pseudo is reloaced with the MEM of its stack slot. * reload1.c (cannot_omit_stores): Delete. (reload): Don't initialize it. Don't apply avoid_return_reg logic to USEs. When done, remove USEs that have a REG_EQUAL note on them. (emit_reload_insns): Handle case where we have inherited a MEM. (delete_output_reload): Don't use cannot_omit_stores. From-SVN: r19508 --- gcc/ChangeLog | 11 ++++++ gcc/reload.c | 45 ++++++++++++++-------- gcc/reload1.c | 101 +++++++++++++++++++++++++++++++++++++------------- gcc/rtl.texi | 4 ++ 4 files changed, 120 insertions(+), 41 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 0d0fb27e401..21f6017738c 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,14 @@ +Sat May 2 01:37:29 1998 J"orn Rennecke + + * reload.c (find_reloads): Emit USEs to mark where a pseudo + is reloaced with the MEM of its stack slot. + * reload1.c (cannot_omit_stores): Delete. + (reload): Don't initialize it. + Don't apply avoid_return_reg logic to USEs. + When done, remove USEs that have a REG_EQUAL note on them. + (emit_reload_insns): Handle case where we have inherited a MEM. + (delete_output_reload): Don't use cannot_omit_stores. + Thu Apr 30 18:59:03 1998 Jim Wilson * Makefile.in (cpp.info, gcc.info): Put -o option before input file. diff --git a/gcc/reload.c b/gcc/reload.c index 333b1eae729..5f02f2cd3e6 100644 --- a/gcc/reload.c +++ b/gcc/reload.c @@ -2577,11 +2577,29 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p) substed_operand[i] = recog_operand[i] = *recog_operand_loc[i]; } else if (code == SUBREG) - substed_operand[i] = recog_operand[i] = *recog_operand_loc[i] - = find_reloads_toplev (recog_operand[i], i, address_type[i], - ind_levels, - set != 0 - && &SET_DEST (set) == recog_operand_loc[i]); + { + rtx reg = SUBREG_REG (recog_operand[i]); + rtx op + = find_reloads_toplev (recog_operand[i], i, address_type[i], + ind_levels, + set != 0 + && &SET_DEST (set) == recog_operand_loc[i]); + + /* If we made a MEM to load (a part of) the stackslot of a pseudo + that didn't get a hard register, emit a USE with a REG_EQUAL + note in front so that we might inherit a previous, possibly + wider reload. */ + + if (GET_CODE (op) == MEM + && GET_CODE (reg) == REG + && (GET_MODE_SIZE (GET_MODE (reg)) + >= GET_MODE_SIZE (GET_MODE (op)))) + REG_NOTES (emit_insn_before (gen_rtx_USE (VOIDmode, reg), insn)) + = gen_rtx_EXPR_LIST (REG_EQUAL, + reg_equiv_memory_loc[REGNO (reg)], NULL_RTX); + + substed_operand[i] = recog_operand[i] = *recog_operand_loc[i] = op; + } else if (code == PLUS || GET_RTX_CLASS (code) == '1') /* We can get a PLUS as an "operand" as a result of register elimination. See eliminate_regs and gen_reload. We handle @@ -2621,16 +2639,13 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p) if (rtx_varies_p (address)) address = copy_rtx (address); - /* If this is an output operand, we must output a CLOBBER - after INSN so find_equiv_reg knows REGNO is being written. - Mark this insn specially, do we can put our output reloads - after it. */ - - if (modified[i] != RELOAD_READ) - PUT_MODE (emit_insn_after (gen_rtx_CLOBBER (VOIDmode, - recog_operand[i]), - insn), - DImode); + /* Emit a USE that shows what register is being used/modified. */ + REG_NOTES (emit_insn_before (gen_rtx_USE (VOIDmode, + recog_operand[i]), + insn)) + = gen_rtx_EXPR_LIST (REG_EQUAL, + reg_equiv_memory_loc[regno], + NULL_RTX); *recog_operand_loc[i] = recog_operand[i] = gen_rtx_MEM (GET_MODE (recog_operand[i]), address); diff --git a/gcc/reload1.c b/gcc/reload1.c index e1f56d2335b..c8fb2efbd0f 100644 --- a/gcc/reload1.c +++ b/gcc/reload1.c @@ -204,12 +204,6 @@ static HARD_REG_SET counted_for_groups; as part of a group, even if it seems to be otherwise ok. */ static HARD_REG_SET counted_for_nongroups; -/* Indexed by pseudo reg number N, - says may not delete stores into the real (memory) home of pseudo N. - This is set if we already substituted a memory equivalent in some uses, - which happens when we have to eliminate the fp from it. */ -static char *cannot_omit_stores; - /* Nonzero if indirect addressing is supported on the machine; this means that spilling (REG n) does not require reloading it into a register in order to do (MEM (REG n)) or (MEM (PLUS (REG n) (CONST_INT c))). The @@ -634,8 +628,6 @@ reload (first, global, dumpfile) bzero ((char *) reg_equiv_address, max_regno * sizeof (rtx)); reg_max_ref_width = (int *) alloca (max_regno * sizeof (int)); bzero ((char *) reg_max_ref_width, max_regno * sizeof (int)); - cannot_omit_stores = (char *) alloca (max_regno); - bzero (cannot_omit_stores, max_regno); if (SMALL_REGISTER_CLASSES) CLEAR_HARD_REG_SET (forbidden_regs); @@ -1111,7 +1103,8 @@ reload (first, global, dumpfile) } else if (SMALL_REGISTER_CLASSES && after_call != 0 && !(GET_CODE (PATTERN (insn)) == SET - && SET_DEST (PATTERN (insn)) == stack_pointer_rtx)) + && SET_DEST (PATTERN (insn)) == stack_pointer_rtx) + && GET_CODE (PATTERN (insn)) != USE) { if (reg_referenced_p (after_call, PATTERN (insn))) avoid_return_reg = after_call; @@ -2131,16 +2124,26 @@ reload (first, global, dumpfile) } } -#ifdef PRESERVE_DEATH_INFO_REGNO_P - /* Make a pass over all the insns and remove death notes for things that - are no longer registers or no longer die in the insn (e.g., an input - and output pseudo being tied). */ + /* Make a pass over all the insns and delete all USEs which we inserted + only to tag a REG_EQUAL note on them; if PRESERVE_DEATH_INFO_REGNO_P + is defined, also remove death notes for things that are no longer + registers or no longer die in the insn (e.g., an input and output + pseudo being tied). */ for (insn = first; insn; insn = NEXT_INSN (insn)) if (GET_RTX_CLASS (GET_CODE (insn)) == 'i') { rtx note, next; + if (GET_CODE (insn) == USE + && find_reg_note (insn, REG_EQUAL, NULL_RTX)) + { + PUT_CODE (insn, NOTE); + NOTE_SOURCE_FILE (insn) = 0; + NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED; + continue; + } +#ifdef PRESERVE_DEATH_INFO_REGNO_P for (note = REG_NOTES (insn); note; note = next) { next = XEXP (note, 1); @@ -2149,8 +2152,8 @@ reload (first, global, dumpfile) || reg_set_p (XEXP (note, 0), PATTERN (insn)))) remove_note (insn, note); } - } #endif + } /* If we are doing stack checking, give a warning if this function's frame size is larger than we expect. */ @@ -2884,7 +2887,10 @@ eliminate_regs (x, mem_mode, insn) new = eliminate_regs (reg_equiv_memory_loc[regno], mem_mode, insn); if (new != reg_equiv_memory_loc[regno]) { - cannot_omit_stores[regno] = 1; + if (insn != 0 && GET_CODE (insn) != EXPR_LIST + && GET_CODE (insn) != INSN_LIST) + REG_NOTES (emit_insn_before (gen_rtx_USE (VOIDmode, x), insn)) + = gen_rtx_EXPR_LIST (REG_EQUAL, new, NULL_RTX); return copy_rtx (new); } } @@ -3103,16 +3109,17 @@ eliminate_regs (x, mem_mode, insn) new = SUBREG_REG (x); else { - /* Otherwise, ensure NEW isn't shared in case we have to reload - it. */ - new = copy_rtx (new); - /* In this case, we must show that the pseudo is used in this insn so that delete_output_reload will do the right thing. */ if (insn != 0 && GET_CODE (insn) != EXPR_LIST && GET_CODE (insn) != INSN_LIST) - emit_insn_before (gen_rtx_USE (VOIDmode, SUBREG_REG (x)), - insn); + REG_NOTES (emit_insn_before (gen_rtx_USE (VOIDmode, + SUBREG_REG (x)), + insn)) + = gen_rtx_EXPR_LIST (REG_EQUAL, new, NULL_RTX); + + /* Ensure NEW isn't shared in case we have to reload it. */ + new = copy_rtx (new); } } else @@ -4056,7 +4063,8 @@ reload_as_needed (first, live_known) } else if (SMALL_REGISTER_CLASSES && after_call != 0 && !(GET_CODE (PATTERN (insn)) == SET - && SET_DEST (PATTERN (insn)) == stack_pointer_rtx)) + && SET_DEST (PATTERN (insn)) == stack_pointer_rtx) + && GET_CODE (PATTERN (insn)) != USE) { if (reg_referenced_p (after_call, PATTERN (insn))) avoid_return_reg = after_call; @@ -5465,6 +5473,7 @@ choose_reload_regs (insn, avoid_return_reg) { register int regno = -1; enum machine_mode mode; + rtx in, use_insn = 0; if (reload_in[r] == 0) ; @@ -5478,6 +5487,34 @@ choose_reload_regs (insn, avoid_return_reg) regno = REGNO (reload_in_reg[r]); mode = GET_MODE (reload_in_reg[r]); } + else if (GET_CODE (reload_in[r]) == MEM) + { + rtx prev = prev_nonnote_insn (insn), note; + + if (prev && GET_CODE (prev) == INSN + && GET_CODE (PATTERN (prev)) == USE + && GET_CODE (XEXP (PATTERN (prev), 0)) == REG + && (REGNO (XEXP (PATTERN (prev), 0)) + >= FIRST_PSEUDO_REGISTER) + && (note = find_reg_note (prev, REG_EQUAL, NULL_RTX)) + && GET_CODE (XEXP (note, 0)) == MEM) + { + rtx addr = XEXP (XEXP (note, 0), 0); + int size_diff + = (GET_MODE_SIZE (GET_MODE (addr)) + - GET_MODE_SIZE (GET_MODE (reload_in[r]))); + if (size_diff >= 0 + && rtx_equal_p ((BYTES_BIG_ENDIAN + ? plus_constant (addr, size_diff) + : addr), + XEXP (reload_in[r], 0))) + { + regno = REGNO (XEXP (PATTERN (prev), 0)); + mode = GET_MODE (reload_in[r]); + use_insn = prev; + } + } + } #if 0 /* This won't work, since REGNO can be a pseudo reg number. Also, it takes much more hair to keep track of all the things @@ -5995,6 +6032,7 @@ emit_reload_insns (insn) register rtx old; rtx oldequiv_reg = 0; rtx this_reload_insn = 0; + int expect_occurrences = 1; if (reload_spill_index[j] >= 0) new_spill_reg_store[reload_spill_index[j]] = 0; @@ -6428,6 +6466,19 @@ emit_reload_insns (insn) end_sequence (); } + /* When inheriting a wider reload, we have a MEM in reload_in[j], + e.g. inheriting a SImode output reload for + (mem:HI (plus:SI (reg:SI 14 fp) (const_int 10))) */ + if (optimize && reload_inherited[j] && reload_in[j] + && GET_CODE (reload_in[j]) == MEM + && reload_spill_index[j] >= 0 + && TEST_HARD_REG_BIT (reg_reloaded_valid, reload_spill_index[j])) + { + expect_occurrences + = count_occurrences (PATTERN (insn), reload_in[j]) == 1 ? 0 : -1; + reload_in[j] + = regno_reg_rtx[reg_reloaded_contents[reload_spill_index[j]]]; + } /* Add a note saying the input reload reg dies in this insn, if anyone cares. */ #ifdef PRESERVE_DEATH_INFO_REGNO_P @@ -6561,7 +6612,8 @@ emit_reload_insns (insn) && dead_or_set_p (insn, reload_in[j]) /* This is unsafe if operand occurs more than once in current insn. Perhaps some occurrences weren't reloaded. */ - && count_occurrences (PATTERN (insn), reload_in[j]) == 1) + && (count_occurrences (PATTERN (insn), reload_in[j]) + == expect_occurrences)) delete_output_reload (insn, j, spill_reg_store[reload_spill_index[j]]); @@ -7296,9 +7348,6 @@ delete_output_reload (insn, j, output_reload_insn) return; } - if (cannot_omit_stores[REGNO (reg)]) - return; - /* If this insn will store in the pseudo again, the previous store can be removed. */ if (reload_out[j] == reload_in[j]) diff --git a/gcc/rtl.texi b/gcc/rtl.texi index a715b8a8cf6..0127fcea456 100644 --- a/gcc/rtl.texi +++ b/gcc/rtl.texi @@ -1892,6 +1892,10 @@ it may not be apparent why this is so. Therefore, the compiler will not attempt to delete previous instructions whose only effect is to store a value in @var{x}. @var{x} must be a @code{reg} expression. +During the reload phase, an insn that has a @code{use} as pattern +can carry a reg_equal note. These @code{use} insns will be deleted +before the reload phase exits. + During the delayed branch scheduling phase, @var{x} may be an insn. This indicates that @var{x} previously was located at this place in the code and its data dependencies need to be taken into account. These -- 2.30.2