From 2e1253f38590eb4bd47b3635e0f04c28423764d0 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Fri, 31 Jan 1997 22:09:12 +0000 Subject: [PATCH] If we can't substitute an equiv reg only used once, move the assignment From-SVN: r13572 --- gcc/local-alloc.c | 118 ++++++++++++++++++++++++++++++++++++---------- 1 file changed, 93 insertions(+), 25 deletions(-) diff --git a/gcc/local-alloc.c b/gcc/local-alloc.c index b41a99b75f9..0657cc7797a 100644 --- a/gcc/local-alloc.c +++ b/gcc/local-alloc.c @@ -1,5 +1,5 @@ /* Allocate registers within a basic block, for GNU compiler. - Copyright (C) 1987, 88, 91, 93, 94, 95, 1996 Free Software Foundation, Inc. + Copyright (C) 1987, 88, 91, 93-6, 1997 Free Software Foundation, Inc. This file is part of GNU CC. @@ -965,6 +965,7 @@ update_equiv_regs () char *reg_equiv_replace = (char *) alloca (max_regno * sizeof *reg_equiv_replace); rtx insn; + int block, depth; reg_equiv_replacement = (rtx *) alloca (max_regno * sizeof (rtx *)); @@ -1114,36 +1115,103 @@ update_equiv_regs () } } - /* Now scan all regs killed in an insn to see if any of them are registers - only used that once. If so, see if we can replace the reference with - the equivalent from. If we can, delete the initializing reference - and this register will go away. */ - for (insn = next_active_insn (get_insns ()); - insn; - insn = next_active_insn (insn)) + /* Now scan all regs killed in an insn to see if any of them are + registers only used that once. If so, see if we can replace the + reference with the equivalent from. If we can, delete the + initializing reference and this register will go away. If we + can't replace the reference, and the instruction is not in a + loop, then move the register initialization just before the use, + so that they are in the same basic block. */ + block = -1; + depth = 0; + for (insn = get_insns (); insn; insn = NEXT_INSN (insn)) { rtx link; + /* Keep track of which basic block we are in. */ + if (block + 1 < n_basic_blocks + && basic_block_head[block + 1] == insn) + ++block; + + if (GET_RTX_CLASS (GET_CODE (insn)) != 'i') + { + if (GET_CODE (insn) == NOTE) + { + if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_BEG) + ++depth; + else if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_END) + { + --depth; + if (depth < 0) + abort (); + } + } + + continue; + } + for (link = REG_NOTES (insn); link; link = XEXP (link, 1)) - if (REG_NOTE_KIND (link) == REG_DEAD - /* Make sure this insn still refers to the register. */ - && reg_mentioned_p (XEXP (link, 0), PATTERN (insn))) - { - int regno = REGNO (XEXP (link, 0)); + { + if (REG_NOTE_KIND (link) == REG_DEAD + /* Make sure this insn still refers to the register. */ + && reg_mentioned_p (XEXP (link, 0), PATTERN (insn))) + { + int regno = REGNO (XEXP (link, 0)); + rtx equiv_insn; - if (reg_equiv_replace[regno] - && validate_replace_rtx (regno_reg_rtx[regno], - reg_equiv_replacement[regno], insn)) - { - rtx equiv_insn = reg_equiv_init_insn[regno]; + if (! reg_equiv_replace[regno]) + continue; - remove_death (regno, insn); - reg_n_refs[regno] = 0; - PUT_CODE (equiv_insn, NOTE); - NOTE_LINE_NUMBER (equiv_insn) = NOTE_INSN_DELETED; - NOTE_SOURCE_FILE (equiv_insn) = 0; - } - } + equiv_insn = reg_equiv_init_insn[regno]; + + if (validate_replace_rtx (regno_reg_rtx[regno], + reg_equiv_replacement[regno], insn)) + { + remove_death (regno, insn); + reg_n_refs[regno] = 0; + PUT_CODE (equiv_insn, NOTE); + NOTE_LINE_NUMBER (equiv_insn) = NOTE_INSN_DELETED; + NOTE_SOURCE_FILE (equiv_insn) = 0; + } + /* If we aren't in a loop, and there are no calls in + INSN or in the initialization of the register, then + move the initialization of the register to just + before INSN. Update the flow information. */ + else if (depth == 0 + && GET_CODE (equiv_insn) == INSN + && GET_CODE (insn) == INSN + && reg_basic_block[regno] < 0) + { + int l, offset, bit; + + emit_insn_before (copy_rtx (PATTERN (equiv_insn)), + insn); + REG_NOTES (PREV_INSN (insn)) = + REG_NOTES (equiv_insn); + + PUT_CODE (equiv_insn, NOTE); + NOTE_LINE_NUMBER (equiv_insn) = NOTE_INSN_DELETED; + NOTE_SOURCE_FILE (equiv_insn) = 0; + REG_NOTES (equiv_insn) = 0; + + if (block < 0) + reg_basic_block[regno] = 0; + else + reg_basic_block[regno] = block; + reg_n_calls_crossed[regno] = 0; + reg_live_length[regno] = 2; + + if (block >= 0 && insn == basic_block_head[block]) + basic_block_head[block] = PREV_INSN (insn); + + offset = regno / REGSET_ELT_BITS; + bit = ((REGSET_ELT_TYPE) 1 + << (regno % REGSET_ELT_BITS)); + for (l = 0; l < n_basic_blocks; l++) + basic_block_live_at_start[l][offset] &= ~ bit; + } + } + } } }