diff options
Diffstat (limited to 'contrib/gcc/flow.c')
-rw-r--r-- | contrib/gcc/flow.c | 4781 |
1 files changed, 4781 insertions, 0 deletions
diff --git a/contrib/gcc/flow.c b/contrib/gcc/flow.c new file mode 100644 index 0000000..2b5d303 --- /dev/null +++ b/contrib/gcc/flow.c @@ -0,0 +1,4781 @@ +/* Data flow analysis for GNU compiler. + Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, + 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, + Inc. + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 2, or (at your option) any later +version. + +GCC is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with GCC; see the file COPYING. If not, write to the Free +Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301, USA. */ + +/* This file contains the data flow analysis pass of the compiler. It + computes data flow information which tells combine_instructions + which insns to consider combining and controls register allocation. + + Additional data flow information that is too bulky to record is + generated during the analysis, and is used at that time to create + autoincrement and autodecrement addressing. + + The first step is dividing the function into basic blocks. + find_basic_blocks does this. Then life_analysis determines + where each register is live and where it is dead. + + ** find_basic_blocks ** + + find_basic_blocks divides the current function's rtl into basic + blocks and constructs the CFG. The blocks are recorded in the + basic_block_info array; the CFG exists in the edge structures + referenced by the blocks. + + find_basic_blocks also finds any unreachable loops and deletes them. + + ** life_analysis ** + + life_analysis is called immediately after find_basic_blocks. + It uses the basic block information to determine where each + hard or pseudo register is live. + + ** live-register info ** + + The information about where each register is live is in two parts: + the REG_NOTES of insns, and the vector basic_block->global_live_at_start. + + basic_block->global_live_at_start has an element for each basic + block, and the element is a bit-vector with a bit for each hard or + pseudo register. The bit is 1 if the register is live at the + beginning of the basic block. + + Two types of elements can be added to an insn's REG_NOTES. + A REG_DEAD note is added to an insn's REG_NOTES for any register + that meets both of two conditions: The value in the register is not + needed in subsequent insns and the insn does not replace the value in + the register (in the case of multi-word hard registers, the value in + each register must be replaced by the insn to avoid a REG_DEAD note). + + In the vast majority of cases, an object in a REG_DEAD note will be + used somewhere in the insn. The (rare) exception to this is if an + insn uses a multi-word hard register and only some of the registers are + needed in subsequent insns. In that case, REG_DEAD notes will be + provided for those hard registers that are not subsequently needed. + Partial REG_DEAD notes of this type do not occur when an insn sets + only some of the hard registers used in such a multi-word operand; + omitting REG_DEAD notes for objects stored in an insn is optional and + the desire to do so does not justify the complexity of the partial + REG_DEAD notes. + + REG_UNUSED notes are added for each register that is set by the insn + but is unused subsequently (if every register set by the insn is unused + and the insn does not reference memory or have some other side-effect, + the insn is deleted instead). If only part of a multi-word hard + register is used in a subsequent insn, REG_UNUSED notes are made for + the parts that will not be used. + + To determine which registers are live after any insn, one can + start from the beginning of the basic block and scan insns, noting + which registers are set by each insn and which die there. + + ** Other actions of life_analysis ** + + life_analysis sets up the LOG_LINKS fields of insns because the + information needed to do so is readily available. + + life_analysis deletes insns whose only effect is to store a value + that is never used. + + life_analysis notices cases where a reference to a register as + a memory address can be combined with a preceding or following + incrementation or decrementation of the register. The separate + instruction to increment or decrement is deleted and the address + is changed to a POST_INC or similar rtx. + + Each time an incrementing or decrementing address is created, + a REG_INC element is added to the insn's REG_NOTES list. + + life_analysis fills in certain vectors containing information about + register usage: REG_N_REFS, REG_N_DEATHS, REG_N_SETS, REG_LIVE_LENGTH, + REG_N_CALLS_CROSSED, REG_N_THROWING_CALLS_CROSSED and REG_BASIC_BLOCK. + + life_analysis sets current_function_sp_is_unchanging if the function + doesn't modify the stack pointer. */ + +/* TODO: + + Split out from life_analysis: + - local property discovery + - global property computation + - log links creation + - pre/post modify transformation +*/ + +#include "config.h" +#include "system.h" +#include "coretypes.h" +#include "tm.h" +#include "tree.h" +#include "rtl.h" +#include "tm_p.h" +#include "hard-reg-set.h" +#include "basic-block.h" +#include "insn-config.h" +#include "regs.h" +#include "flags.h" +#include "output.h" +#include "function.h" +#include "except.h" +#include "toplev.h" +#include "recog.h" +#include "expr.h" +#include "timevar.h" + +#include "obstack.h" +#include "splay-tree.h" +#include "tree-pass.h" +#include "params.h" + +#ifndef HAVE_epilogue +#define HAVE_epilogue 0 +#endif +#ifndef HAVE_prologue +#define HAVE_prologue 0 +#endif +#ifndef HAVE_sibcall_epilogue +#define HAVE_sibcall_epilogue 0 +#endif + +#ifndef EPILOGUE_USES +#define EPILOGUE_USES(REGNO) 0 +#endif +#ifndef EH_USES +#define EH_USES(REGNO) 0 +#endif + +#ifdef HAVE_conditional_execution +#ifndef REVERSE_CONDEXEC_PREDICATES_P +#define REVERSE_CONDEXEC_PREDICATES_P(x, y) \ + (GET_CODE ((x)) == reversed_comparison_code ((y), NULL)) +#endif +#endif + +/* This is the maximum number of times we process any given block if the + latest loop depth count is smaller than this number. Only used for the + failure strategy to avoid infinite loops in calculate_global_regs_live. */ +#define MAX_LIVENESS_ROUNDS 20 + +/* Nonzero if the second flow pass has completed. */ +int flow2_completed; + +/* Maximum register number used in this function, plus one. */ + +int max_regno; + +/* Indexed by n, giving various register information */ + +VEC(reg_info_p,heap) *reg_n_info; + +/* Regset of regs live when calls to `setjmp'-like functions happen. */ +/* ??? Does this exist only for the setjmp-clobbered warning message? */ + +static regset regs_live_at_setjmp; + +/* List made of EXPR_LIST rtx's which gives pairs of pseudo registers + that have to go in the same hard reg. + The first two regs in the list are a pair, and the next two + are another pair, etc. */ +rtx regs_may_share; + +/* Set of registers that may be eliminable. These are handled specially + in updating regs_ever_live. */ + +static HARD_REG_SET elim_reg_set; + +/* Holds information for tracking conditional register life information. */ +struct reg_cond_life_info +{ + /* A boolean expression of conditions under which a register is dead. */ + rtx condition; + /* Conditions under which a register is dead at the basic block end. */ + rtx orig_condition; + + /* A boolean expression of conditions under which a register has been + stored into. */ + rtx stores; + + /* ??? Could store mask of bytes that are dead, so that we could finally + track lifetimes of multi-word registers accessed via subregs. */ +}; + +/* For use in communicating between propagate_block and its subroutines. + Holds all information needed to compute life and def-use information. */ + +struct propagate_block_info +{ + /* The basic block we're considering. */ + basic_block bb; + + /* Bit N is set if register N is conditionally or unconditionally live. */ + regset reg_live; + + /* Bit N is set if register N is set this insn. */ + regset new_set; + + /* Element N is the next insn that uses (hard or pseudo) register N + within the current basic block; or zero, if there is no such insn. */ + rtx *reg_next_use; + + /* Contains a list of all the MEMs we are tracking for dead store + elimination. */ + rtx mem_set_list; + + /* If non-null, record the set of registers set unconditionally in the + basic block. */ + regset local_set; + + /* If non-null, record the set of registers set conditionally in the + basic block. */ + regset cond_local_set; + +#ifdef HAVE_conditional_execution + /* Indexed by register number, holds a reg_cond_life_info for each + register that is not unconditionally live or dead. */ + splay_tree reg_cond_dead; + + /* Bit N is set if register N is in an expression in reg_cond_dead. */ + regset reg_cond_reg; +#endif + + /* The length of mem_set_list. */ + int mem_set_list_len; + + /* Nonzero if the value of CC0 is live. */ + int cc0_live; + + /* Flags controlling the set of information propagate_block collects. */ + int flags; + /* Index of instruction being processed. */ + int insn_num; +}; + +/* Number of dead insns removed. */ +static int ndead; + +/* When PROP_REG_INFO set, array contains pbi->insn_num of instruction + where given register died. When the register is marked alive, we use the + information to compute amount of instructions life range cross. + (remember, we are walking backward). This can be computed as current + pbi->insn_num - reg_deaths[regno]. + At the end of processing each basic block, the remaining live registers + are inspected and live ranges are increased same way so liverange of global + registers are computed correctly. + + The array is maintained clear for dead registers, so it can be safely reused + for next basic block without expensive memset of the whole array after + reseting pbi->insn_num to 0. */ + +static int *reg_deaths; + +/* Forward declarations */ +static int verify_wide_reg_1 (rtx *, void *); +static void verify_wide_reg (int, basic_block); +static void verify_local_live_at_start (regset, basic_block); +static void notice_stack_pointer_modification_1 (rtx, rtx, void *); +static void notice_stack_pointer_modification (void); +static void mark_reg (rtx, void *); +static void mark_regs_live_at_end (regset); +static void calculate_global_regs_live (sbitmap, sbitmap, int); +static void propagate_block_delete_insn (rtx); +static rtx propagate_block_delete_libcall (rtx, rtx); +static int insn_dead_p (struct propagate_block_info *, rtx, int, rtx); +static int libcall_dead_p (struct propagate_block_info *, rtx, rtx); +static void mark_set_regs (struct propagate_block_info *, rtx, rtx); +static void mark_set_1 (struct propagate_block_info *, enum rtx_code, rtx, + rtx, rtx, int); +static int find_regno_partial (rtx *, void *); + +#ifdef HAVE_conditional_execution +static int mark_regno_cond_dead (struct propagate_block_info *, int, rtx); +static void free_reg_cond_life_info (splay_tree_value); +static int flush_reg_cond_reg_1 (splay_tree_node, void *); +static void flush_reg_cond_reg (struct propagate_block_info *, int); +static rtx elim_reg_cond (rtx, unsigned int); +static rtx ior_reg_cond (rtx, rtx, int); +static rtx not_reg_cond (rtx); +static rtx and_reg_cond (rtx, rtx, int); +#endif +#ifdef AUTO_INC_DEC +static void attempt_auto_inc (struct propagate_block_info *, rtx, rtx, rtx, + rtx, rtx); +static void find_auto_inc (struct propagate_block_info *, rtx, rtx); +static int try_pre_increment_1 (struct propagate_block_info *, rtx); +static int try_pre_increment (rtx, rtx, HOST_WIDE_INT); +#endif +static void mark_used_reg (struct propagate_block_info *, rtx, rtx, rtx); +static void mark_used_regs (struct propagate_block_info *, rtx, rtx, rtx); +void debug_flow_info (void); +static void add_to_mem_set_list (struct propagate_block_info *, rtx); +static int invalidate_mems_from_autoinc (rtx *, void *); +static void invalidate_mems_from_set (struct propagate_block_info *, rtx); +static void clear_log_links (sbitmap); +static int count_or_remove_death_notes_bb (basic_block, int); +static void allocate_bb_life_data (void); + +/* Return the INSN immediately following the NOTE_INSN_BASIC_BLOCK + note associated with the BLOCK. */ + +rtx +first_insn_after_basic_block_note (basic_block block) +{ + rtx insn; + + /* Get the first instruction in the block. */ + insn = BB_HEAD (block); + + if (insn == NULL_RTX) + return NULL_RTX; + if (LABEL_P (insn)) + insn = NEXT_INSN (insn); + gcc_assert (NOTE_INSN_BASIC_BLOCK_P (insn)); + + return NEXT_INSN (insn); +} + +/* Perform data flow analysis for the whole control flow graph. + FLAGS is a set of PROP_* flags to be used in accumulating flow info. */ + +void +life_analysis (int flags) +{ +#ifdef ELIMINABLE_REGS + int i; + static const struct {const int from, to; } eliminables[] = ELIMINABLE_REGS; +#endif + + /* Record which registers will be eliminated. We use this in + mark_used_regs. */ + + CLEAR_HARD_REG_SET (elim_reg_set); + +#ifdef ELIMINABLE_REGS + for (i = 0; i < (int) ARRAY_SIZE (eliminables); i++) + SET_HARD_REG_BIT (elim_reg_set, eliminables[i].from); +#else + SET_HARD_REG_BIT (elim_reg_set, FRAME_POINTER_REGNUM); +#endif + + +#ifdef CANNOT_CHANGE_MODE_CLASS + if (flags & PROP_REG_INFO) + init_subregs_of_mode (); +#endif + + if (! optimize) + flags &= ~(PROP_LOG_LINKS | PROP_AUTOINC | PROP_ALLOW_CFG_CHANGES); + + /* The post-reload life analysis have (on a global basis) the same + registers live as was computed by reload itself. elimination + Otherwise offsets and such may be incorrect. + + Reload will make some registers as live even though they do not + appear in the rtl. + + We don't want to create new auto-incs after reload, since they + are unlikely to be useful and can cause problems with shared + stack slots. */ + if (reload_completed) + flags &= ~(PROP_REG_INFO | PROP_AUTOINC); + + /* We want alias analysis information for local dead store elimination. */ + if (optimize && (flags & PROP_SCAN_DEAD_STORES)) + init_alias_analysis (); + + /* Always remove no-op moves. Do this before other processing so + that we don't have to keep re-scanning them. */ + delete_noop_moves (); + + /* Some targets can emit simpler epilogues if they know that sp was + not ever modified during the function. After reload, of course, + we've already emitted the epilogue so there's no sense searching. */ + if (! reload_completed) + notice_stack_pointer_modification (); + + /* Allocate and zero out data structures that will record the + data from lifetime analysis. */ + allocate_reg_life_data (); + allocate_bb_life_data (); + + /* Find the set of registers live on function exit. */ + mark_regs_live_at_end (EXIT_BLOCK_PTR->il.rtl->global_live_at_start); + + /* "Update" life info from zero. It'd be nice to begin the + relaxation with just the exit and noreturn blocks, but that set + is not immediately handy. */ + + if (flags & PROP_REG_INFO) + { + memset (regs_ever_live, 0, sizeof (regs_ever_live)); + memset (regs_asm_clobbered, 0, sizeof (regs_asm_clobbered)); + } + update_life_info (NULL, UPDATE_LIFE_GLOBAL, flags); + if (reg_deaths) + { + free (reg_deaths); + reg_deaths = NULL; + } + + /* Clean up. */ + if (optimize && (flags & PROP_SCAN_DEAD_STORES)) + end_alias_analysis (); + + if (dump_file) + dump_flow_info (dump_file, dump_flags); + + /* Removing dead insns should have made jumptables really dead. */ + delete_dead_jumptables (); +} + +/* A subroutine of verify_wide_reg, called through for_each_rtx. + Search for REGNO. If found, return 2 if it is not wider than + word_mode. */ + +static int +verify_wide_reg_1 (rtx *px, void *pregno) +{ + rtx x = *px; + unsigned int regno = *(int *) pregno; + + if (REG_P (x) && REGNO (x) == regno) + { + if (GET_MODE_BITSIZE (GET_MODE (x)) <= BITS_PER_WORD) + return 2; + return 1; + } + return 0; +} + +/* A subroutine of verify_local_live_at_start. Search through insns + of BB looking for register REGNO. */ + +static void +verify_wide_reg (int regno, basic_block bb) +{ + rtx head = BB_HEAD (bb), end = BB_END (bb); + + while (1) + { + if (INSN_P (head)) + { + int r = for_each_rtx (&PATTERN (head), verify_wide_reg_1, ®no); + if (r == 1) + return; + if (r == 2) + break; + } + if (head == end) + break; + head = NEXT_INSN (head); + } + if (dump_file) + { + fprintf (dump_file, "Register %d died unexpectedly.\n", regno); + dump_bb (bb, dump_file, 0); + } + internal_error ("internal consistency failure"); +} + +/* A subroutine of update_life_info. Verify that there are no untoward + changes in live_at_start during a local update. */ + +static void +verify_local_live_at_start (regset new_live_at_start, basic_block bb) +{ + if (reload_completed) + { + /* After reload, there are no pseudos, nor subregs of multi-word + registers. The regsets should exactly match. */ + if (! REG_SET_EQUAL_P (new_live_at_start, + bb->il.rtl->global_live_at_start)) + { + if (dump_file) + { + fprintf (dump_file, + "live_at_start mismatch in bb %d, aborting\nNew:\n", + bb->index); + debug_bitmap_file (dump_file, new_live_at_start); + fputs ("Old:\n", dump_file); + dump_bb (bb, dump_file, 0); + } + internal_error ("internal consistency failure"); + } + } + else + { + unsigned i; + reg_set_iterator rsi; + + /* Find the set of changed registers. */ + XOR_REG_SET (new_live_at_start, bb->il.rtl->global_live_at_start); + + EXECUTE_IF_SET_IN_REG_SET (new_live_at_start, 0, i, rsi) + { + /* No registers should die. */ + if (REGNO_REG_SET_P (bb->il.rtl->global_live_at_start, i)) + { + if (dump_file) + { + fprintf (dump_file, + "Register %d died unexpectedly.\n", i); + dump_bb (bb, dump_file, 0); + } + internal_error ("internal consistency failure"); + } + /* Verify that the now-live register is wider than word_mode. */ + verify_wide_reg (i, bb); + } + } +} + +/* Updates life information starting with the basic blocks set in BLOCKS. + If BLOCKS is null, consider it to be the universal set. + + If EXTENT is UPDATE_LIFE_LOCAL, such as after splitting or peepholing, + we are only expecting local modifications to basic blocks. If we find + extra registers live at the beginning of a block, then we either killed + useful data, or we have a broken split that wants data not provided. + If we find registers removed from live_at_start, that means we have + a broken peephole that is killing a register it shouldn't. + + ??? This is not true in one situation -- when a pre-reload splitter + generates subregs of a multi-word pseudo, current life analysis will + lose the kill. So we _can_ have a pseudo go live. How irritating. + + It is also not true when a peephole decides that it doesn't need one + or more of the inputs. + + Including PROP_REG_INFO does not properly refresh regs_ever_live + unless the caller resets it to zero. */ + +int +update_life_info (sbitmap blocks, enum update_life_extent extent, + int prop_flags) +{ + regset tmp; + unsigned i = 0; + int stabilized_prop_flags = prop_flags; + basic_block bb; + + tmp = ALLOC_REG_SET (®_obstack); + ndead = 0; + + if ((prop_flags & PROP_REG_INFO) && !reg_deaths) + reg_deaths = XCNEWVEC (int, max_regno); + + timevar_push ((extent == UPDATE_LIFE_LOCAL || blocks) + ? TV_LIFE_UPDATE : TV_LIFE); + + /* Changes to the CFG are only allowed when + doing a global update for the entire CFG. */ + gcc_assert (!(prop_flags & PROP_ALLOW_CFG_CHANGES) + || (extent != UPDATE_LIFE_LOCAL && !blocks)); + + /* For a global update, we go through the relaxation process again. */ + if (extent != UPDATE_LIFE_LOCAL) + { + for ( ; ; ) + { + int changed = 0; + + calculate_global_regs_live (blocks, blocks, + prop_flags & (PROP_SCAN_DEAD_CODE + | PROP_SCAN_DEAD_STORES + | PROP_ALLOW_CFG_CHANGES)); + + if ((prop_flags & (PROP_KILL_DEAD_CODE | PROP_ALLOW_CFG_CHANGES)) + != (PROP_KILL_DEAD_CODE | PROP_ALLOW_CFG_CHANGES)) + break; + + /* Removing dead code may allow the CFG to be simplified which + in turn may allow for further dead code detection / removal. */ + FOR_EACH_BB_REVERSE (bb) + { + COPY_REG_SET (tmp, bb->il.rtl->global_live_at_end); + changed |= propagate_block (bb, tmp, NULL, NULL, + prop_flags & (PROP_SCAN_DEAD_CODE + | PROP_SCAN_DEAD_STORES + | PROP_KILL_DEAD_CODE)); + } + + /* Don't pass PROP_SCAN_DEAD_CODE or PROP_KILL_DEAD_CODE to + subsequent propagate_block calls, since removing or acting as + removing dead code can affect global register liveness, which + is supposed to be finalized for this call after this loop. */ + stabilized_prop_flags + &= ~(PROP_SCAN_DEAD_CODE | PROP_SCAN_DEAD_STORES + | PROP_KILL_DEAD_CODE); + + if (! changed) + break; + + /* We repeat regardless of what cleanup_cfg says. If there were + instructions deleted above, that might have been only a + partial improvement (see PARAM_MAX_FLOW_MEMORY_LOCATIONS usage). + Further improvement may be possible. */ + cleanup_cfg (CLEANUP_EXPENSIVE); + + /* Zap the life information from the last round. If we don't + do this, we can wind up with registers that no longer appear + in the code being marked live at entry. */ + FOR_EACH_BB (bb) + { + CLEAR_REG_SET (bb->il.rtl->global_live_at_start); + CLEAR_REG_SET (bb->il.rtl->global_live_at_end); + } + } + + /* If asked, remove notes from the blocks we'll update. */ + if (extent == UPDATE_LIFE_GLOBAL_RM_NOTES) + count_or_remove_death_notes (blocks, + prop_flags & PROP_POST_REGSTACK ? -1 : 1); + } + else + { + /* FIXME: This can go when the dataflow branch has been merged in. */ + /* For a local update, if we are creating new REG_DEAD notes, then we + must delete the old ones first to avoid conflicts if they are + different. */ + if (prop_flags & PROP_DEATH_NOTES) + count_or_remove_death_notes (blocks, + prop_flags & PROP_POST_REGSTACK ? -1 : 1); + } + + + /* Clear log links in case we are asked to (re)compute them. */ + if (prop_flags & PROP_LOG_LINKS) + clear_log_links (blocks); + + if (blocks) + { + sbitmap_iterator sbi; + + EXECUTE_IF_SET_IN_SBITMAP (blocks, 0, i, sbi) + { + bb = BASIC_BLOCK (i); + if (bb) + { + /* The bitmap may be flawed in that one of the basic + blocks may have been deleted before you get here. */ + COPY_REG_SET (tmp, bb->il.rtl->global_live_at_end); + propagate_block (bb, tmp, NULL, NULL, stabilized_prop_flags); + + if (extent == UPDATE_LIFE_LOCAL) + verify_local_live_at_start (tmp, bb); + } + }; + } + else + { + FOR_EACH_BB_REVERSE (bb) + { + COPY_REG_SET (tmp, bb->il.rtl->global_live_at_end); + + propagate_block (bb, tmp, NULL, NULL, stabilized_prop_flags); + + if (extent == UPDATE_LIFE_LOCAL) + verify_local_live_at_start (tmp, bb); + } + } + + FREE_REG_SET (tmp); + + if (prop_flags & PROP_REG_INFO) + { + reg_set_iterator rsi; + + /* The only pseudos that are live at the beginning of the function + are those that were not set anywhere in the function. local-alloc + doesn't know how to handle these correctly, so mark them as not + local to any one basic block. */ + EXECUTE_IF_SET_IN_REG_SET (ENTRY_BLOCK_PTR->il.rtl->global_live_at_end, + FIRST_PSEUDO_REGISTER, i, rsi) + REG_BASIC_BLOCK (i) = REG_BLOCK_GLOBAL; + + /* We have a problem with any pseudoreg that lives across the setjmp. + ANSI says that if a user variable does not change in value between + the setjmp and the longjmp, then the longjmp preserves it. This + includes longjmp from a place where the pseudo appears dead. + (In principle, the value still exists if it is in scope.) + If the pseudo goes in a hard reg, some other value may occupy + that hard reg where this pseudo is dead, thus clobbering the pseudo. + Conclusion: such a pseudo must not go in a hard reg. */ + EXECUTE_IF_SET_IN_REG_SET (regs_live_at_setjmp, + FIRST_PSEUDO_REGISTER, i, rsi) + { + if (regno_reg_rtx[i] != 0) + { + REG_LIVE_LENGTH (i) = -1; + REG_BASIC_BLOCK (i) = REG_BLOCK_UNKNOWN; + } + } + } + if (reg_deaths) + { + free (reg_deaths); + reg_deaths = NULL; + } + timevar_pop ((extent == UPDATE_LIFE_LOCAL || blocks) + ? TV_LIFE_UPDATE : TV_LIFE); + if (ndead && dump_file) + fprintf (dump_file, "deleted %i dead insns\n", ndead); + return ndead; +} + +/* Update life information in all blocks where BB_DIRTY is set. */ + +int +update_life_info_in_dirty_blocks (enum update_life_extent extent, int prop_flags) +{ + sbitmap update_life_blocks = sbitmap_alloc (last_basic_block); + int n = 0; + basic_block bb; + int retval = 0; + + sbitmap_zero (update_life_blocks); + FOR_EACH_BB (bb) + { + if (bb->flags & BB_DIRTY) + { + SET_BIT (update_life_blocks, bb->index); + n++; + } + } + + if (n) + retval = update_life_info (update_life_blocks, extent, prop_flags); + + sbitmap_free (update_life_blocks); + return retval; +} + +/* Free the variables allocated by find_basic_blocks. */ + +void +free_basic_block_vars (void) +{ + if (basic_block_info) + { + clear_edges (); + basic_block_info = NULL; + } + n_basic_blocks = 0; + last_basic_block = 0; + n_edges = 0; + + label_to_block_map = NULL; + + ENTRY_BLOCK_PTR->aux = NULL; + ENTRY_BLOCK_PTR->il.rtl->global_live_at_end = NULL; + EXIT_BLOCK_PTR->aux = NULL; + EXIT_BLOCK_PTR->il.rtl->global_live_at_start = NULL; +} + +/* Delete any insns that copy a register to itself. */ + +int +delete_noop_moves (void) +{ + rtx insn, next; + basic_block bb; + int nnoops = 0; + + FOR_EACH_BB (bb) + { + for (insn = BB_HEAD (bb); insn != NEXT_INSN (BB_END (bb)); insn = next) + { + next = NEXT_INSN (insn); + if (INSN_P (insn) && noop_move_p (insn)) + { + rtx note; + + /* If we're about to remove the first insn of a libcall + then move the libcall note to the next real insn and + update the retval note. */ + if ((note = find_reg_note (insn, REG_LIBCALL, NULL_RTX)) + && XEXP (note, 0) != insn) + { + rtx new_libcall_insn = next_real_insn (insn); + rtx retval_note = find_reg_note (XEXP (note, 0), + REG_RETVAL, NULL_RTX); + REG_NOTES (new_libcall_insn) + = gen_rtx_INSN_LIST (REG_LIBCALL, XEXP (note, 0), + REG_NOTES (new_libcall_insn)); + XEXP (retval_note, 0) = new_libcall_insn; + } + + delete_insn_and_edges (insn); + nnoops++; + } + } + } + + if (nnoops && dump_file) + fprintf (dump_file, "deleted %i noop moves\n", nnoops); + + return nnoops; +} + +/* Delete any jump tables never referenced. We can't delete them at the + time of removing tablejump insn as they are referenced by the preceding + insns computing the destination, so we delay deleting and garbagecollect + them once life information is computed. */ +void +delete_dead_jumptables (void) +{ + basic_block bb; + + /* A dead jump table does not belong to any basic block. Scan insns + between two adjacent basic blocks. */ + FOR_EACH_BB (bb) + { + rtx insn, next; + + for (insn = NEXT_INSN (BB_END (bb)); + insn && !NOTE_INSN_BASIC_BLOCK_P (insn); + insn = next) + { + next = NEXT_INSN (insn); + if (LABEL_P (insn) + && LABEL_NUSES (insn) == LABEL_PRESERVE_P (insn) + && JUMP_P (next) + && (GET_CODE (PATTERN (next)) == ADDR_VEC + || GET_CODE (PATTERN (next)) == ADDR_DIFF_VEC)) + { + rtx label = insn, jump = next; + + if (dump_file) + fprintf (dump_file, "Dead jumptable %i removed\n", + INSN_UID (insn)); + + next = NEXT_INSN (next); + delete_insn (jump); + delete_insn (label); + } + } + } +} + +/* Determine if the stack pointer is constant over the life of the function. + Only useful before prologues have been emitted. */ + +static void +notice_stack_pointer_modification_1 (rtx x, rtx pat ATTRIBUTE_UNUSED, + void *data ATTRIBUTE_UNUSED) +{ + if (x == stack_pointer_rtx + /* The stack pointer is only modified indirectly as the result + of a push until later in flow. See the comments in rtl.texi + regarding Embedded Side-Effects on Addresses. */ + || (MEM_P (x) + && GET_RTX_CLASS (GET_CODE (XEXP (x, 0))) == RTX_AUTOINC + && XEXP (XEXP (x, 0), 0) == stack_pointer_rtx)) + current_function_sp_is_unchanging = 0; +} + +static void +notice_stack_pointer_modification (void) +{ + basic_block bb; + rtx insn; + + /* Assume that the stack pointer is unchanging if alloca hasn't + been used. */ + current_function_sp_is_unchanging = !current_function_calls_alloca; + if (! current_function_sp_is_unchanging) + return; + + FOR_EACH_BB (bb) + FOR_BB_INSNS (bb, insn) + { + if (INSN_P (insn)) + { + /* Check if insn modifies the stack pointer. */ + note_stores (PATTERN (insn), + notice_stack_pointer_modification_1, + NULL); + if (! current_function_sp_is_unchanging) + return; + } + } +} + +/* Mark a register in SET. Hard registers in large modes get all + of their component registers set as well. */ + +static void +mark_reg (rtx reg, void *xset) +{ + regset set = (regset) xset; + int regno = REGNO (reg); + + gcc_assert (GET_MODE (reg) != BLKmode); + + SET_REGNO_REG_SET (set, regno); + if (regno < FIRST_PSEUDO_REGISTER) + { + int n = hard_regno_nregs[regno][GET_MODE (reg)]; + while (--n > 0) + SET_REGNO_REG_SET (set, regno + n); + } +} + +/* Mark those regs which are needed at the end of the function as live + at the end of the last basic block. */ + +static void +mark_regs_live_at_end (regset set) +{ + unsigned int i; + + /* If exiting needs the right stack value, consider the stack pointer + live at the end of the function. */ + if ((HAVE_epilogue && epilogue_completed) + || ! EXIT_IGNORE_STACK + || (! FRAME_POINTER_REQUIRED + && ! current_function_calls_alloca + && flag_omit_frame_pointer) + || current_function_sp_is_unchanging) + { + SET_REGNO_REG_SET (set, STACK_POINTER_REGNUM); + } + + /* Mark the frame pointer if needed at the end of the function. If + we end up eliminating it, it will be removed from the live list + of each basic block by reload. */ + + if (! reload_completed || frame_pointer_needed) + { + SET_REGNO_REG_SET (set, FRAME_POINTER_REGNUM); +#if FRAME_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM + /* If they are different, also mark the hard frame pointer as live. */ + if (! LOCAL_REGNO (HARD_FRAME_POINTER_REGNUM)) + SET_REGNO_REG_SET (set, HARD_FRAME_POINTER_REGNUM); +#endif + } + +#ifndef PIC_OFFSET_TABLE_REG_CALL_CLOBBERED + /* Many architectures have a GP register even without flag_pic. + Assume the pic register is not in use, or will be handled by + other means, if it is not fixed. */ + if ((unsigned) PIC_OFFSET_TABLE_REGNUM != INVALID_REGNUM + && fixed_regs[PIC_OFFSET_TABLE_REGNUM]) + SET_REGNO_REG_SET (set, PIC_OFFSET_TABLE_REGNUM); +#endif + + /* Mark all global registers, and all registers used by the epilogue + as being live at the end of the function since they may be + referenced by our caller. */ + for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) + if (global_regs[i] || EPILOGUE_USES (i)) + SET_REGNO_REG_SET (set, i); + + if (HAVE_epilogue && epilogue_completed) + { + /* Mark all call-saved registers that we actually used. */ + for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) + if (regs_ever_live[i] && ! LOCAL_REGNO (i) + && ! TEST_HARD_REG_BIT (regs_invalidated_by_call, i)) + SET_REGNO_REG_SET (set, i); + } + +#ifdef EH_RETURN_DATA_REGNO + /* Mark the registers that will contain data for the handler. */ + if (reload_completed && current_function_calls_eh_return) + for (i = 0; ; ++i) + { + unsigned regno = EH_RETURN_DATA_REGNO(i); + if (regno == INVALID_REGNUM) + break; + SET_REGNO_REG_SET (set, regno); + } +#endif +#ifdef EH_RETURN_STACKADJ_RTX + if ((! HAVE_epilogue || ! epilogue_completed) + && current_function_calls_eh_return) + { + rtx tmp = EH_RETURN_STACKADJ_RTX; + if (tmp && REG_P (tmp)) + mark_reg (tmp, set); + } +#endif +#ifdef EH_RETURN_HANDLER_RTX + if ((! HAVE_epilogue || ! epilogue_completed) + && current_function_calls_eh_return) + { + rtx tmp = EH_RETURN_HANDLER_RTX; + if (tmp && REG_P (tmp)) + mark_reg (tmp, set); + } +#endif + + /* Mark function return value. */ + diddle_return_value (mark_reg, set); +} + +/* Propagate global life info around the graph of basic blocks. Begin + considering blocks with their corresponding bit set in BLOCKS_IN. + If BLOCKS_IN is null, consider it the universal set. + + BLOCKS_OUT is set for every block that was changed. */ + +static void +calculate_global_regs_live (sbitmap blocks_in, sbitmap blocks_out, int flags) +{ + basic_block *queue, *qhead, *qtail, *qend, bb; + regset tmp, new_live_at_end, invalidated_by_eh_edge; + regset registers_made_dead; + bool failure_strategy_required = false; + int *block_accesses; + + /* The registers that are modified within this in block. */ + regset *local_sets; + + /* The registers that are conditionally modified within this block. + In other words, regs that are set only as part of a COND_EXEC. */ + regset *cond_local_sets; + + unsigned int i; + + /* Some passes used to forget clear aux field of basic block causing + sick behavior here. */ +#ifdef ENABLE_CHECKING + FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, NULL, next_bb) + gcc_assert (!bb->aux); +#endif + + tmp = ALLOC_REG_SET (®_obstack); + new_live_at_end = ALLOC_REG_SET (®_obstack); + invalidated_by_eh_edge = ALLOC_REG_SET (®_obstack); + registers_made_dead = ALLOC_REG_SET (®_obstack); + + /* Inconveniently, this is only readily available in hard reg set form. */ + for (i = 0; i < FIRST_PSEUDO_REGISTER; ++i) + if (TEST_HARD_REG_BIT (regs_invalidated_by_call, i)) + SET_REGNO_REG_SET (invalidated_by_eh_edge, i); + + /* The exception handling registers die at eh edges. */ +#ifdef EH_RETURN_DATA_REGNO + for (i = 0; ; ++i) + { + unsigned regno = EH_RETURN_DATA_REGNO (i); + if (regno == INVALID_REGNUM) + break; + SET_REGNO_REG_SET (invalidated_by_eh_edge, regno); + } +#endif + + /* Allocate space for the sets of local properties. */ + local_sets = XCNEWVEC (bitmap, last_basic_block); + cond_local_sets = XCNEWVEC (bitmap, last_basic_block); + + /* Create a worklist. Allocate an extra slot for the `head == tail' + style test for an empty queue doesn't work with a full queue. */ + queue = XNEWVEC (basic_block, n_basic_blocks + 1); + qtail = queue; + qhead = qend = queue + n_basic_blocks; + + /* Queue the blocks set in the initial mask. Do this in reverse block + number order so that we are more likely for the first round to do + useful work. We use AUX non-null to flag that the block is queued. */ + if (blocks_in) + { + FOR_EACH_BB (bb) + if (TEST_BIT (blocks_in, bb->index)) + { + *--qhead = bb; + bb->aux = bb; + } + } + else + { + FOR_EACH_BB (bb) + { + *--qhead = bb; + bb->aux = bb; + } + } + + block_accesses = XCNEWVEC (int, last_basic_block); + + /* We clean aux when we remove the initially-enqueued bbs, but we + don't enqueue ENTRY and EXIT initially, so clean them upfront and + unconditionally. */ + ENTRY_BLOCK_PTR->aux = EXIT_BLOCK_PTR->aux = NULL; + + if (blocks_out) + sbitmap_zero (blocks_out); + + /* We work through the queue until there are no more blocks. What + is live at the end of this block is precisely the union of what + is live at the beginning of all its successors. So, we set its + GLOBAL_LIVE_AT_END field based on the GLOBAL_LIVE_AT_START field + for its successors. Then, we compute GLOBAL_LIVE_AT_START for + this block by walking through the instructions in this block in + reverse order and updating as we go. If that changed + GLOBAL_LIVE_AT_START, we add the predecessors of the block to the + queue; they will now need to recalculate GLOBAL_LIVE_AT_END. + + We are guaranteed to terminate, because GLOBAL_LIVE_AT_START + never shrinks. If a register appears in GLOBAL_LIVE_AT_START, it + must either be live at the end of the block, or used within the + block. In the latter case, it will certainly never disappear + from GLOBAL_LIVE_AT_START. In the former case, the register + could go away only if it disappeared from GLOBAL_LIVE_AT_START + for one of the successor blocks. By induction, that cannot + occur. + + ??? This reasoning doesn't work if we start from non-empty initial + GLOBAL_LIVE_AT_START sets. And there are actually two problems: + 1) Updating may not terminate (endless oscillation). + 2) Even if it does (and it usually does), the resulting information + may be inaccurate. Consider for example the following case: + + a = ...; + while (...) {...} -- 'a' not mentioned at all + ... = a; + + If the use of 'a' is deleted between two calculations of liveness + information and the initial sets are not cleared, the information + about a's liveness will get stuck inside the loop and the set will + appear not to be dead. + + We do not attempt to solve 2) -- the information is conservatively + correct (i.e. we never claim that something live is dead) and the + amount of optimization opportunities missed due to this problem is + not significant. + + 1) is more serious. In order to fix it, we monitor the number of times + each block is processed. Once one of the blocks has been processed more + times than the maximum number of rounds, we use the following strategy: + When a register disappears from one of the sets, we add it to a MAKE_DEAD + set, remove all registers in this set from all GLOBAL_LIVE_AT_* sets and + add the blocks with changed sets into the queue. Thus we are guaranteed + to terminate (the worst case corresponds to all registers in MADE_DEAD, + in which case the original reasoning above is valid), but in general we + only fix up a few offending registers. + + The maximum number of rounds for computing liveness is the largest of + MAX_LIVENESS_ROUNDS and the latest loop depth count for this function. */ + + while (qhead != qtail) + { + int rescan, changed; + basic_block bb; + edge e; + edge_iterator ei; + + bb = *qhead++; + if (qhead == qend) + qhead = queue; + bb->aux = NULL; + + /* Should we start using the failure strategy? */ + if (bb != ENTRY_BLOCK_PTR) + { + int max_liveness_rounds = + MAX (MAX_LIVENESS_ROUNDS, cfun->max_loop_depth); + + block_accesses[bb->index]++; + if (block_accesses[bb->index] > max_liveness_rounds) + failure_strategy_required = true; + } + + /* Begin by propagating live_at_start from the successor blocks. */ + CLEAR_REG_SET (new_live_at_end); + + if (EDGE_COUNT (bb->succs) > 0) + FOR_EACH_EDGE (e, ei, bb->succs) + { + basic_block sb = e->dest; + + /* Call-clobbered registers die across exception and + call edges. */ + /* ??? Abnormal call edges ignored for the moment, as this gets + confused by sibling call edges, which crashes reg-stack. */ + if (e->flags & EDGE_EH) + bitmap_ior_and_compl_into (new_live_at_end, + sb->il.rtl->global_live_at_start, + invalidated_by_eh_edge); + else + IOR_REG_SET (new_live_at_end, sb->il.rtl->global_live_at_start); + + /* If a target saves one register in another (instead of on + the stack) the save register will need to be live for EH. */ + if (e->flags & EDGE_EH) + for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) + if (EH_USES (i)) + SET_REGNO_REG_SET (new_live_at_end, i); + } + else + { + /* This might be a noreturn function that throws. And + even if it isn't, getting the unwind info right helps + debugging. */ + for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) + if (EH_USES (i)) + SET_REGNO_REG_SET (new_live_at_end, i); + } + + /* The all-important stack pointer must always be live. */ + SET_REGNO_REG_SET (new_live_at_end, STACK_POINTER_REGNUM); + + /* Before reload, there are a few registers that must be forced + live everywhere -- which might not already be the case for + blocks within infinite loops. */ + if (! reload_completed) + { + /* Any reference to any pseudo before reload is a potential + reference of the frame pointer. */ + SET_REGNO_REG_SET (new_live_at_end, FRAME_POINTER_REGNUM); + +#if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM + /* Pseudos with argument area equivalences may require + reloading via the argument pointer. */ + if (fixed_regs[ARG_POINTER_REGNUM]) + SET_REGNO_REG_SET (new_live_at_end, ARG_POINTER_REGNUM); +#endif + + /* Any constant, or pseudo with constant equivalences, may + require reloading from memory using the pic register. */ + if ((unsigned) PIC_OFFSET_TABLE_REGNUM != INVALID_REGNUM + && fixed_regs[PIC_OFFSET_TABLE_REGNUM]) + SET_REGNO_REG_SET (new_live_at_end, PIC_OFFSET_TABLE_REGNUM); + } + + if (bb == ENTRY_BLOCK_PTR) + { + COPY_REG_SET (bb->il.rtl->global_live_at_end, new_live_at_end); + continue; + } + + /* On our first pass through this block, we'll go ahead and continue. + Recognize first pass by checking if local_set is NULL for this + basic block. On subsequent passes, we get to skip out early if + live_at_end wouldn't have changed. */ + + if (local_sets[bb->index] == NULL) + { + local_sets[bb->index] = ALLOC_REG_SET (®_obstack); + cond_local_sets[bb->index] = ALLOC_REG_SET (®_obstack); + rescan = 1; + } + else + { + /* If any bits were removed from live_at_end, we'll have to + rescan the block. This wouldn't be necessary if we had + precalculated local_live, however with PROP_SCAN_DEAD_CODE + local_live is really dependent on live_at_end. */ + rescan = bitmap_intersect_compl_p (bb->il.rtl->global_live_at_end, + new_live_at_end); + + if (!rescan) + { + regset cond_local_set; + + /* If any of the registers in the new live_at_end set are + conditionally set in this basic block, we must rescan. + This is because conditional lifetimes at the end of the + block do not just take the live_at_end set into + account, but also the liveness at the start of each + successor block. We can miss changes in those sets if + we only compare the new live_at_end against the + previous one. */ + cond_local_set = cond_local_sets[bb->index]; + rescan = bitmap_intersect_p (new_live_at_end, cond_local_set); + } + + if (!rescan) + { + regset local_set; + + /* Find the set of changed bits. Take this opportunity + to notice that this set is empty and early out. */ + bitmap_xor (tmp, bb->il.rtl->global_live_at_end, new_live_at_end); + if (bitmap_empty_p (tmp)) + continue; + + /* If any of the changed bits overlap with local_sets[bb], + we'll have to rescan the block. */ + local_set = local_sets[bb->index]; + rescan = bitmap_intersect_p (tmp, local_set); + } + } + + /* Let our caller know that BB changed enough to require its + death notes updated. */ + if (blocks_out) + SET_BIT (blocks_out, bb->index); + + if (! rescan) + { + /* Add to live_at_start the set of all registers in + new_live_at_end that aren't in the old live_at_end. */ + + changed = bitmap_ior_and_compl_into (bb->il.rtl->global_live_at_start, + new_live_at_end, + bb->il.rtl->global_live_at_end); + COPY_REG_SET (bb->il.rtl->global_live_at_end, new_live_at_end); + if (! changed) + continue; + } + else + { + COPY_REG_SET (bb->il.rtl->global_live_at_end, new_live_at_end); + + /* Rescan the block insn by insn to turn (a copy of) live_at_end + into live_at_start. */ + propagate_block (bb, new_live_at_end, + local_sets[bb->index], + cond_local_sets[bb->index], + flags); + + /* If live_at start didn't change, no need to go farther. */ + if (REG_SET_EQUAL_P (bb->il.rtl->global_live_at_start, + new_live_at_end)) + continue; + + if (failure_strategy_required) + { + /* Get the list of registers that were removed from the + bb->global_live_at_start set. */ + bitmap_and_compl (tmp, bb->il.rtl->global_live_at_start, + new_live_at_end); + if (!bitmap_empty_p (tmp)) + { + bool pbb_changed; + basic_block pbb; + + /* It should not happen that one of registers we have + removed last time is disappears again before any other + register does. */ + pbb_changed = bitmap_ior_into (registers_made_dead, tmp); + gcc_assert (pbb_changed); + + /* Now remove the registers from all sets. */ + FOR_EACH_BB (pbb) + { + pbb_changed = false; + + pbb_changed + |= bitmap_and_compl_into + (pbb->il.rtl->global_live_at_start, + registers_made_dead); + pbb_changed + |= bitmap_and_compl_into + (pbb->il.rtl->global_live_at_end, + registers_made_dead); + if (!pbb_changed) + continue; + + /* Note the (possible) change. */ + if (blocks_out) + SET_BIT (blocks_out, pbb->index); + + /* Makes sure to really rescan the block. */ + if (local_sets[pbb->index]) + { + FREE_REG_SET (local_sets[pbb->index]); + FREE_REG_SET (cond_local_sets[pbb->index]); + local_sets[pbb->index] = 0; + } + + /* Add it to the queue. */ + if (pbb->aux == NULL) + { + *qtail++ = pbb; + if (qtail == qend) + qtail = queue; + pbb->aux = pbb; + } + } + continue; + } + } /* end of failure_strategy_required */ + + COPY_REG_SET (bb->il.rtl->global_live_at_start, new_live_at_end); + } + + /* Queue all predecessors of BB so that we may re-examine + their live_at_end. */ + FOR_EACH_EDGE (e, ei, bb->preds) + { + basic_block pb = e->src; + + gcc_assert ((e->flags & EDGE_FAKE) == 0); + + if (pb->aux == NULL) + { + *qtail++ = pb; + if (qtail == qend) + qtail = queue; + pb->aux = pb; + } + } + } + + FREE_REG_SET (tmp); + FREE_REG_SET (new_live_at_end); + FREE_REG_SET (invalidated_by_eh_edge); + FREE_REG_SET (registers_made_dead); + + if (blocks_out) + { + sbitmap_iterator sbi; + + EXECUTE_IF_SET_IN_SBITMAP (blocks_out, 0, i, sbi) + { + basic_block bb = BASIC_BLOCK (i); + FREE_REG_SET (local_sets[bb->index]); + FREE_REG_SET (cond_local_sets[bb->index]); + }; + } + else + { + FOR_EACH_BB (bb) + { + FREE_REG_SET (local_sets[bb->index]); + FREE_REG_SET (cond_local_sets[bb->index]); + } + } + + free (block_accesses); + free (queue); + free (cond_local_sets); + free (local_sets); +} + + +/* This structure is used to pass parameters to and from the + the function find_regno_partial(). It is used to pass in the + register number we are looking, as well as to return any rtx + we find. */ + +typedef struct { + unsigned regno_to_find; + rtx retval; +} find_regno_partial_param; + + +/* Find the rtx for the reg numbers specified in 'data' if it is + part of an expression which only uses part of the register. Return + it in the structure passed in. */ +static int +find_regno_partial (rtx *ptr, void *data) +{ + find_regno_partial_param *param = (find_regno_partial_param *)data; + unsigned reg = param->regno_to_find; + param->retval = NULL_RTX; + + if (*ptr == NULL_RTX) + return 0; + + switch (GET_CODE (*ptr)) + { + case ZERO_EXTRACT: + case SIGN_EXTRACT: + case STRICT_LOW_PART: + if (REG_P (XEXP (*ptr, 0)) && REGNO (XEXP (*ptr, 0)) == reg) + { + param->retval = XEXP (*ptr, 0); + return 1; + } + break; + + case SUBREG: + if (REG_P (SUBREG_REG (*ptr)) + && REGNO (SUBREG_REG (*ptr)) == reg) + { + param->retval = SUBREG_REG (*ptr); + return 1; + } + break; + + default: + break; + } + + return 0; +} + +/* Process all immediate successors of the entry block looking for pseudo + registers which are live on entry. Find all of those whose first + instance is a partial register reference of some kind, and initialize + them to 0 after the entry block. This will prevent bit sets within + registers whose value is unknown, and may contain some kind of sticky + bits we don't want. */ + +static int +initialize_uninitialized_subregs (void) +{ + rtx insn; + edge e; + unsigned reg, did_something = 0; + find_regno_partial_param param; + edge_iterator ei; + + FOR_EACH_EDGE (e, ei, ENTRY_BLOCK_PTR->succs) + { + basic_block bb = e->dest; + regset map = bb->il.rtl->global_live_at_start; + reg_set_iterator rsi; + + EXECUTE_IF_SET_IN_REG_SET (map, FIRST_PSEUDO_REGISTER, reg, rsi) + { + int uid = REGNO_FIRST_UID (reg); + rtx i; + + /* Find an insn which mentions the register we are looking for. + Its preferable to have an instance of the register's rtl since + there may be various flags set which we need to duplicate. + If we can't find it, its probably an automatic whose initial + value doesn't matter, or hopefully something we don't care about. */ + for (i = get_insns (); i && INSN_UID (i) != uid; i = NEXT_INSN (i)) + ; + if (i != NULL_RTX) + { + /* Found the insn, now get the REG rtx, if we can. */ + param.regno_to_find = reg; + for_each_rtx (&i, find_regno_partial, ¶m); + if (param.retval != NULL_RTX) + { + start_sequence (); + emit_move_insn (param.retval, + CONST0_RTX (GET_MODE (param.retval))); + insn = get_insns (); + end_sequence (); + insert_insn_on_edge (insn, e); + did_something = 1; + } + } + } + } + + if (did_something) + commit_edge_insertions (); + return did_something; +} + + +/* Subroutines of life analysis. */ + +/* Allocate the permanent data structures that represent the results + of life analysis. */ + +static void +allocate_bb_life_data (void) +{ + basic_block bb; + + FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, NULL, next_bb) + { + if (bb->il.rtl->global_live_at_start) + { + CLEAR_REG_SET (bb->il.rtl->global_live_at_start); + CLEAR_REG_SET (bb->il.rtl->global_live_at_end); + } + else + { + bb->il.rtl->global_live_at_start = ALLOC_REG_SET (®_obstack); + bb->il.rtl->global_live_at_end = ALLOC_REG_SET (®_obstack); + } + } + + regs_live_at_setjmp = ALLOC_REG_SET (®_obstack); +} + +void +allocate_reg_life_data (void) +{ + int i; + + max_regno = max_reg_num (); + gcc_assert (!reg_deaths); + reg_deaths = XCNEWVEC (int, max_regno); + + /* Recalculate the register space, in case it has grown. Old style + vector oriented regsets would set regset_{size,bytes} here also. */ + allocate_reg_info (max_regno, FALSE, FALSE); + + /* Reset all the data we'll collect in propagate_block and its + subroutines. */ + for (i = 0; i < max_regno; i++) + { + REG_N_SETS (i) = 0; + REG_N_REFS (i) = 0; + REG_N_DEATHS (i) = 0; + REG_N_CALLS_CROSSED (i) = 0; + REG_N_THROWING_CALLS_CROSSED (i) = 0; + REG_LIVE_LENGTH (i) = 0; + REG_FREQ (i) = 0; + REG_BASIC_BLOCK (i) = REG_BLOCK_UNKNOWN; + } +} + +/* Delete dead instructions for propagate_block. */ + +static void +propagate_block_delete_insn (rtx insn) +{ + rtx inote = find_reg_note (insn, REG_LABEL, NULL_RTX); + + /* If the insn referred to a label, and that label was attached to + an ADDR_VEC, it's safe to delete the ADDR_VEC. In fact, it's + pretty much mandatory to delete it, because the ADDR_VEC may be + referencing labels that no longer exist. + + INSN may reference a deleted label, particularly when a jump + table has been optimized into a direct jump. There's no + real good way to fix up the reference to the deleted label + when the label is deleted, so we just allow it here. */ + + if (inote && LABEL_P (inote)) + { + rtx label = XEXP (inote, 0); + rtx next; + + /* The label may be forced if it has been put in the constant + pool. If that is the only use we must discard the table + jump following it, but not the label itself. */ + if (LABEL_NUSES (label) == 1 + LABEL_PRESERVE_P (label) + && (next = next_nonnote_insn (label)) != NULL + && JUMP_P (next) + && (GET_CODE (PATTERN (next)) == ADDR_VEC + || GET_CODE (PATTERN (next)) == ADDR_DIFF_VEC)) + { + rtx pat = PATTERN (next); + int diff_vec_p = GET_CODE (pat) == ADDR_DIFF_VEC; + int len = XVECLEN (pat, diff_vec_p); + int i; + + for (i = 0; i < len; i++) + LABEL_NUSES (XEXP (XVECEXP (pat, diff_vec_p, i), 0))--; + + delete_insn_and_edges (next); + ndead++; + } + } + + delete_insn_and_edges (insn); + ndead++; +} + +/* Delete dead libcalls for propagate_block. Return the insn + before the libcall. */ + +static rtx +propagate_block_delete_libcall (rtx insn, rtx note) +{ + rtx first = XEXP (note, 0); + rtx before = PREV_INSN (first); + + delete_insn_chain_and_edges (first, insn); + ndead++; + return before; +} + +/* Update the life-status of regs for one insn. Return the previous insn. */ + +rtx +propagate_one_insn (struct propagate_block_info *pbi, rtx insn) +{ + rtx prev = PREV_INSN (insn); + int flags = pbi->flags; + int insn_is_dead = 0; + int libcall_is_dead = 0; + rtx note; + unsigned i; + + if (! INSN_P (insn)) + return prev; + + note = find_reg_note (insn, REG_RETVAL, NULL_RTX); + if (flags & PROP_SCAN_DEAD_CODE) + { + insn_is_dead = insn_dead_p (pbi, PATTERN (insn), 0, REG_NOTES (insn)); + libcall_is_dead = (insn_is_dead && note != 0 + && libcall_dead_p (pbi, note, insn)); + } + + /* If an instruction consists of just dead store(s) on final pass, + delete it. */ + if ((flags & PROP_KILL_DEAD_CODE) && insn_is_dead) + { + /* If we're trying to delete a prologue or epilogue instruction + that isn't flagged as possibly being dead, something is wrong. + But if we are keeping the stack pointer depressed, we might well + be deleting insns that are used to compute the amount to update + it by, so they are fine. */ + if (reload_completed + && !(TREE_CODE (TREE_TYPE (current_function_decl)) == FUNCTION_TYPE + && (TYPE_RETURNS_STACK_DEPRESSED + (TREE_TYPE (current_function_decl)))) + && (((HAVE_epilogue || HAVE_prologue) + && prologue_epilogue_contains (insn)) + || (HAVE_sibcall_epilogue + && sibcall_epilogue_contains (insn))) + && find_reg_note (insn, REG_MAYBE_DEAD, NULL_RTX) == 0) + fatal_insn ("Attempt to delete prologue/epilogue insn:", insn); + + /* Record sets. Do this even for dead instructions, since they + would have killed the values if they hadn't been deleted. To + be consistent, we also have to emit a clobber when we delete + an insn that clobbers a live register. */ + pbi->flags |= PROP_DEAD_INSN; + mark_set_regs (pbi, PATTERN (insn), insn); + pbi->flags &= ~PROP_DEAD_INSN; + + /* CC0 is now known to be dead. Either this insn used it, + in which case it doesn't anymore, or clobbered it, + so the next insn can't use it. */ + pbi->cc0_live = 0; + + if (libcall_is_dead) + prev = propagate_block_delete_libcall (insn, note); + else + { + + /* If INSN contains a RETVAL note and is dead, but the libcall + as a whole is not dead, then we want to remove INSN, but + not the whole libcall sequence. + + However, we need to also remove the dangling REG_LIBCALL + note so that we do not have mis-matched LIBCALL/RETVAL + notes. In theory we could find a new location for the + REG_RETVAL note, but it hardly seems worth the effort. + + NOTE at this point will be the RETVAL note if it exists. */ + if (note) + { + rtx libcall_note; + + libcall_note + = find_reg_note (XEXP (note, 0), REG_LIBCALL, NULL_RTX); + remove_note (XEXP (note, 0), libcall_note); + } + + /* Similarly if INSN contains a LIBCALL note, remove the + dangling REG_RETVAL note. */ + note = find_reg_note (insn, REG_LIBCALL, NULL_RTX); + if (note) + { + rtx retval_note; + + retval_note + = find_reg_note (XEXP (note, 0), REG_RETVAL, NULL_RTX); + remove_note (XEXP (note, 0), retval_note); + } + + /* Now delete INSN. */ + propagate_block_delete_insn (insn); + } + + return prev; + } + + /* See if this is an increment or decrement that can be merged into + a following memory address. */ +#ifdef AUTO_INC_DEC + { + rtx x = single_set (insn); + + /* Does this instruction increment or decrement a register? */ + if ((flags & PROP_AUTOINC) + && x != 0 + && REG_P (SET_DEST (x)) + && (GET_CODE (SET_SRC (x)) == PLUS + || GET_CODE (SET_SRC (x)) == MINUS) + && XEXP (SET_SRC (x), 0) == SET_DEST (x) + && GET_CODE (XEXP (SET_SRC (x), 1)) == CONST_INT + /* Ok, look for a following memory ref we can combine with. + If one is found, change the memory ref to a PRE_INC + or PRE_DEC, cancel this insn, and return 1. + Return 0 if nothing has been done. */ + && try_pre_increment_1 (pbi, insn)) + return prev; + } +#endif /* AUTO_INC_DEC */ + + CLEAR_REG_SET (pbi->new_set); + + /* If this is not the final pass, and this insn is copying the value of + a library call and it's dead, don't scan the insns that perform the + library call, so that the call's arguments are not marked live. */ + if (libcall_is_dead) + { + /* Record the death of the dest reg. */ + mark_set_regs (pbi, PATTERN (insn), insn); + + insn = XEXP (note, 0); + return PREV_INSN (insn); + } + else if (GET_CODE (PATTERN (insn)) == SET + && SET_DEST (PATTERN (insn)) == stack_pointer_rtx + && GET_CODE (SET_SRC (PATTERN (insn))) == PLUS + && XEXP (SET_SRC (PATTERN (insn)), 0) == stack_pointer_rtx + && GET_CODE (XEXP (SET_SRC (PATTERN (insn)), 1)) == CONST_INT) + { + /* We have an insn to pop a constant amount off the stack. + (Such insns use PLUS regardless of the direction of the stack, + and any insn to adjust the stack by a constant is always a pop + or part of a push.) + These insns, if not dead stores, have no effect on life, though + they do have an effect on the memory stores we are tracking. */ + invalidate_mems_from_set (pbi, stack_pointer_rtx); + /* Still, we need to update local_set, lest ifcvt.c:dead_or_predicable + concludes that the stack pointer is not modified. */ + mark_set_regs (pbi, PATTERN (insn), insn); + } + else + { + /* Any regs live at the time of a call instruction must not go + in a register clobbered by calls. Find all regs now live and + record this for them. */ + + if (CALL_P (insn) && (flags & PROP_REG_INFO)) + { + reg_set_iterator rsi; + EXECUTE_IF_SET_IN_REG_SET (pbi->reg_live, 0, i, rsi) + REG_N_CALLS_CROSSED (i)++; + if (can_throw_internal (insn)) + EXECUTE_IF_SET_IN_REG_SET (pbi->reg_live, 0, i, rsi) + REG_N_THROWING_CALLS_CROSSED (i)++; + } + + /* Record sets. Do this even for dead instructions, since they + would have killed the values if they hadn't been deleted. */ + mark_set_regs (pbi, PATTERN (insn), insn); + + if (CALL_P (insn)) + { + regset live_at_end; + bool sibcall_p; + rtx note, cond; + int i; + + cond = NULL_RTX; + if (GET_CODE (PATTERN (insn)) == COND_EXEC) + cond = COND_EXEC_TEST (PATTERN (insn)); + + /* Non-constant calls clobber memory, constant calls do not + clobber memory, though they may clobber outgoing arguments + on the stack. */ + if (! CONST_OR_PURE_CALL_P (insn)) + { + free_EXPR_LIST_list (&pbi->mem_set_list); + pbi->mem_set_list_len = 0; + } + else + invalidate_mems_from_set (pbi, stack_pointer_rtx); + + /* There may be extra registers to be clobbered. */ + for (note = CALL_INSN_FUNCTION_USAGE (insn); + note; + note = XEXP (note, 1)) + if (GET_CODE (XEXP (note, 0)) == CLOBBER) + mark_set_1 (pbi, CLOBBER, XEXP (XEXP (note, 0), 0), + cond, insn, pbi->flags); + + /* Calls change all call-used and global registers; sibcalls do not + clobber anything that must be preserved at end-of-function, + except for return values. */ + + sibcall_p = SIBLING_CALL_P (insn); + live_at_end = EXIT_BLOCK_PTR->il.rtl->global_live_at_start; + for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) + if (TEST_HARD_REG_BIT (regs_invalidated_by_call, i) + && ! (sibcall_p + && REGNO_REG_SET_P (live_at_end, i) + && ! refers_to_regno_p (i, i+1, + current_function_return_rtx, + (rtx *) 0))) + { + enum rtx_code code = global_regs[i] ? SET : CLOBBER; + /* We do not want REG_UNUSED notes for these registers. */ + mark_set_1 (pbi, code, regno_reg_rtx[i], cond, insn, + pbi->flags & ~(PROP_DEATH_NOTES | PROP_REG_INFO)); + } + } + + /* If an insn doesn't use CC0, it becomes dead since we assume + that every insn clobbers it. So show it dead here; + mark_used_regs will set it live if it is referenced. */ + pbi->cc0_live = 0; + + /* Record uses. */ + if (! insn_is_dead) + mark_used_regs (pbi, PATTERN (insn), NULL_RTX, insn); + + /* Sometimes we may have inserted something before INSN (such as a move) + when we make an auto-inc. So ensure we will scan those insns. */ +#ifdef AUTO_INC_DEC + prev = PREV_INSN (insn); +#endif + + if (! insn_is_dead && CALL_P (insn)) + { + int i; + rtx note, cond; + + cond = NULL_RTX; + if (GET_CODE (PATTERN (insn)) == COND_EXEC) + cond = COND_EXEC_TEST (PATTERN (insn)); + + /* Calls use their arguments, and may clobber memory which + address involves some register. */ + for (note = CALL_INSN_FUNCTION_USAGE (insn); + note; + note = XEXP (note, 1)) + /* We find USE or CLOBBER entities in a FUNCTION_USAGE list: both + of which mark_used_regs knows how to handle. */ + mark_used_regs (pbi, XEXP (XEXP (note, 0), 0), cond, insn); + + /* The stack ptr is used (honorarily) by a CALL insn. */ + if ((flags & PROP_REG_INFO) + && !REGNO_REG_SET_P (pbi->reg_live, STACK_POINTER_REGNUM)) + reg_deaths[STACK_POINTER_REGNUM] = pbi->insn_num; + SET_REGNO_REG_SET (pbi->reg_live, STACK_POINTER_REGNUM); + + /* Calls may also reference any of the global registers, + so they are made live. */ + for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) + if (global_regs[i]) + mark_used_reg (pbi, regno_reg_rtx[i], cond, insn); + } + } + + pbi->insn_num++; + + return prev; +} + +/* Initialize a propagate_block_info struct for public consumption. + Note that the structure itself is opaque to this file, but that + the user can use the regsets provided here. */ + +struct propagate_block_info * +init_propagate_block_info (basic_block bb, regset live, regset local_set, + regset cond_local_set, int flags) +{ + struct propagate_block_info *pbi = XNEW (struct propagate_block_info); + + pbi->bb = bb; + pbi->reg_live = live; + pbi->mem_set_list = NULL_RTX; + pbi->mem_set_list_len = 0; + pbi->local_set = local_set; + pbi->cond_local_set = cond_local_set; + pbi->cc0_live = 0; + pbi->flags = flags; + pbi->insn_num = 0; + + if (flags & (PROP_LOG_LINKS | PROP_AUTOINC)) + pbi->reg_next_use = XCNEWVEC (rtx, max_reg_num ()); + else + pbi->reg_next_use = NULL; + + pbi->new_set = BITMAP_ALLOC (NULL); + +#ifdef HAVE_conditional_execution + pbi->reg_cond_dead = splay_tree_new (splay_tree_compare_ints, NULL, + free_reg_cond_life_info); + pbi->reg_cond_reg = BITMAP_ALLOC (NULL); + + /* If this block ends in a conditional branch, for each register + live from one side of the branch and not the other, record the + register as conditionally dead. */ + if (JUMP_P (BB_END (bb)) + && any_condjump_p (BB_END (bb))) + { + regset diff = ALLOC_REG_SET (®_obstack); + basic_block bb_true, bb_false; + unsigned i; + + /* Identify the successor blocks. */ + bb_true = EDGE_SUCC (bb, 0)->dest; + if (!single_succ_p (bb)) + { + bb_false = EDGE_SUCC (bb, 1)->dest; + + if (EDGE_SUCC (bb, 0)->flags & EDGE_FALLTHRU) + { + basic_block t = bb_false; + bb_false = bb_true; + bb_true = t; + } + else + gcc_assert (EDGE_SUCC (bb, 1)->flags & EDGE_FALLTHRU); + } + else + { + /* This can happen with a conditional jump to the next insn. */ + gcc_assert (JUMP_LABEL (BB_END (bb)) == BB_HEAD (bb_true)); + + /* Simplest way to do nothing. */ + bb_false = bb_true; + } + + /* Compute which register lead different lives in the successors. */ + bitmap_xor (diff, bb_true->il.rtl->global_live_at_start, + bb_false->il.rtl->global_live_at_start); + + if (!bitmap_empty_p (diff)) + { + /* Extract the condition from the branch. */ + rtx set_src = SET_SRC (pc_set (BB_END (bb))); + rtx cond_true = XEXP (set_src, 0); + rtx reg = XEXP (cond_true, 0); + enum rtx_code inv_cond; + + if (GET_CODE (reg) == SUBREG) + reg = SUBREG_REG (reg); + + /* We can only track conditional lifetimes if the condition is + in the form of a reversible comparison of a register against + zero. If the condition is more complex than that, then it is + safe not to record any information. */ + inv_cond = reversed_comparison_code (cond_true, BB_END (bb)); + if (inv_cond != UNKNOWN + && REG_P (reg) + && XEXP (cond_true, 1) == const0_rtx) + { + rtx cond_false + = gen_rtx_fmt_ee (inv_cond, + GET_MODE (cond_true), XEXP (cond_true, 0), + XEXP (cond_true, 1)); + reg_set_iterator rsi; + + if (GET_CODE (XEXP (set_src, 1)) == PC) + { + rtx t = cond_false; + cond_false = cond_true; + cond_true = t; + } + + SET_REGNO_REG_SET (pbi->reg_cond_reg, REGNO (reg)); + + /* For each such register, mark it conditionally dead. */ + EXECUTE_IF_SET_IN_REG_SET (diff, 0, i, rsi) + { + struct reg_cond_life_info *rcli; + rtx cond; + + rcli = XNEW (struct reg_cond_life_info); + + if (REGNO_REG_SET_P (bb_true->il.rtl->global_live_at_start, + i)) + cond = cond_false; + else + cond = cond_true; + rcli->condition = cond; + rcli->stores = const0_rtx; + rcli->orig_condition = cond; + + splay_tree_insert (pbi->reg_cond_dead, i, + (splay_tree_value) rcli); + } + } + } + + FREE_REG_SET (diff); + } +#endif + + /* If this block has no successors, any stores to the frame that aren't + used later in the block are dead. So make a pass over the block + recording any such that are made and show them dead at the end. We do + a very conservative and simple job here. */ + if (optimize + && ! (TREE_CODE (TREE_TYPE (current_function_decl)) == FUNCTION_TYPE + && (TYPE_RETURNS_STACK_DEPRESSED + (TREE_TYPE (current_function_decl)))) + && (flags & PROP_SCAN_DEAD_STORES) + && (EDGE_COUNT (bb->succs) == 0 + || (single_succ_p (bb) + && single_succ (bb) == EXIT_BLOCK_PTR + && ! current_function_calls_eh_return))) + { + rtx insn, set; + for (insn = BB_END (bb); insn != BB_HEAD (bb); insn = PREV_INSN (insn)) + if (NONJUMP_INSN_P (insn) + && (set = single_set (insn)) + && MEM_P (SET_DEST (set))) + { + rtx mem = SET_DEST (set); + rtx canon_mem = canon_rtx (mem); + + if (XEXP (canon_mem, 0) == frame_pointer_rtx + || (GET_CODE (XEXP (canon_mem, 0)) == PLUS + && XEXP (XEXP (canon_mem, 0), 0) == frame_pointer_rtx + && GET_CODE (XEXP (XEXP (canon_mem, 0), 1)) == CONST_INT)) + add_to_mem_set_list (pbi, canon_mem); + } + } + + return pbi; +} + +/* Release a propagate_block_info struct. */ + +void +free_propagate_block_info (struct propagate_block_info *pbi) +{ + free_EXPR_LIST_list (&pbi->mem_set_list); + + BITMAP_FREE (pbi->new_set); + +#ifdef HAVE_conditional_execution + splay_tree_delete (pbi->reg_cond_dead); + BITMAP_FREE (pbi->reg_cond_reg); +#endif + + if (pbi->flags & PROP_REG_INFO) + { + int num = pbi->insn_num; + unsigned i; + reg_set_iterator rsi; + + EXECUTE_IF_SET_IN_REG_SET (pbi->reg_live, 0, i, rsi) + { + REG_LIVE_LENGTH (i) += num - reg_deaths[i]; + reg_deaths[i] = 0; + } + } + if (pbi->reg_next_use) + free (pbi->reg_next_use); + + free (pbi); +} + +/* Compute the registers live at the beginning of a basic block BB from + those live at the end. + + When called, REG_LIVE contains those live at the end. On return, it + contains those live at the beginning. + + LOCAL_SET, if non-null, will be set with all registers killed + unconditionally by this basic block. + Likewise, COND_LOCAL_SET, if non-null, will be set with all registers + killed conditionally by this basic block. If there is any unconditional + set of a register, then the corresponding bit will be set in LOCAL_SET + and cleared in COND_LOCAL_SET. + It is valid for LOCAL_SET and COND_LOCAL_SET to be the same set. In this + case, the resulting set will be equal to the union of the two sets that + would otherwise be computed. + + Return nonzero if an INSN is deleted (i.e. by dead code removal). */ + +int +propagate_block (basic_block bb, regset live, regset local_set, + regset cond_local_set, int flags) +{ + struct propagate_block_info *pbi; + rtx insn, prev; + int changed; + + pbi = init_propagate_block_info (bb, live, local_set, cond_local_set, flags); + + if (flags & PROP_REG_INFO) + { + unsigned i; + reg_set_iterator rsi; + + /* Process the regs live at the end of the block. + Mark them as not local to any one basic block. */ + EXECUTE_IF_SET_IN_REG_SET (live, 0, i, rsi) + REG_BASIC_BLOCK (i) = REG_BLOCK_GLOBAL; + } + + /* Scan the block an insn at a time from end to beginning. */ + + changed = 0; + for (insn = BB_END (bb); ; insn = prev) + { + /* If this is a call to `setjmp' et al, warn if any + non-volatile datum is live. */ + if ((flags & PROP_REG_INFO) + && CALL_P (insn) + && find_reg_note (insn, REG_SETJMP, NULL)) + IOR_REG_SET (regs_live_at_setjmp, pbi->reg_live); + + prev = propagate_one_insn (pbi, insn); + if (!prev) + changed |= insn != get_insns (); + else + changed |= NEXT_INSN (prev) != insn; + + if (insn == BB_HEAD (bb)) + break; + } + +#ifdef EH_RETURN_DATA_REGNO + if (bb_has_eh_pred (bb)) + { + unsigned int i; + for (i = 0; ; ++i) + { + unsigned regno = EH_RETURN_DATA_REGNO (i); + if (regno == INVALID_REGNUM) + break; + if (pbi->local_set) + { + CLEAR_REGNO_REG_SET (pbi->cond_local_set, regno); + SET_REGNO_REG_SET (pbi->local_set, regno); + } + if (REGNO_REG_SET_P (pbi->reg_live, regno)) + SET_REGNO_REG_SET (pbi->new_set, regno); + + regs_ever_live[regno] = 1; + } + } +#endif + + free_propagate_block_info (pbi); + + return changed; +} + +/* Return 1 if X (the body of an insn, or part of it) is just dead stores + (SET expressions whose destinations are registers dead after the insn). + NEEDED is the regset that says which regs are alive after the insn. + + Unless CALL_OK is nonzero, an insn is needed if it contains a CALL. + + If X is the entire body of an insn, NOTES contains the reg notes + pertaining to the insn. */ + +static int +insn_dead_p (struct propagate_block_info *pbi, rtx x, int call_ok, + rtx notes ATTRIBUTE_UNUSED) +{ + enum rtx_code code = GET_CODE (x); + + /* Don't eliminate insns that may trap. */ + if (flag_non_call_exceptions && may_trap_p (x)) + return 0; + +#ifdef AUTO_INC_DEC + /* As flow is invoked after combine, we must take existing AUTO_INC + expressions into account. */ + for (; notes; notes = XEXP (notes, 1)) + { + if (REG_NOTE_KIND (notes) == REG_INC) + { + int regno = REGNO (XEXP (notes, 0)); + + /* Don't delete insns to set global regs. */ + if ((regno < FIRST_PSEUDO_REGISTER && global_regs[regno]) + || REGNO_REG_SET_P (pbi->reg_live, regno)) + return 0; + } + } +#endif + + /* If setting something that's a reg or part of one, + see if that register's altered value will be live. */ + + if (code == SET) + { + rtx r = SET_DEST (x); + +#ifdef HAVE_cc0 + if (GET_CODE (r) == CC0) + return ! pbi->cc0_live; +#endif + + /* A SET that is a subroutine call cannot be dead. */ + if (GET_CODE (SET_SRC (x)) == CALL) + { + if (! call_ok) + return 0; + } + + /* Don't eliminate loads from volatile memory or volatile asms. */ + else if (volatile_refs_p (SET_SRC (x))) + return 0; + + if (MEM_P (r)) + { + rtx temp, canon_r; + + if (MEM_VOLATILE_P (r) || GET_MODE (r) == BLKmode) + return 0; + + canon_r = canon_rtx (r); + + /* Walk the set of memory locations we are currently tracking + and see if one is an identical match to this memory location. + If so, this memory write is dead (remember, we're walking + backwards from the end of the block to the start). Since + rtx_equal_p does not check the alias set or flags, we also + must have the potential for them to conflict (anti_dependence). */ + for (temp = pbi->mem_set_list; temp != 0; temp = XEXP (temp, 1)) + if (anti_dependence (r, XEXP (temp, 0))) + { + rtx mem = XEXP (temp, 0); + + if (rtx_equal_p (XEXP (canon_r, 0), XEXP (mem, 0)) + && (GET_MODE_SIZE (GET_MODE (canon_r)) + <= GET_MODE_SIZE (GET_MODE (mem)))) + return 1; + +#ifdef AUTO_INC_DEC + /* Check if memory reference matches an auto increment. Only + post increment/decrement or modify are valid. */ + if (GET_MODE (mem) == GET_MODE (r) + && (GET_CODE (XEXP (mem, 0)) == POST_DEC + || GET_CODE (XEXP (mem, 0)) == POST_INC + || GET_CODE (XEXP (mem, 0)) == POST_MODIFY) + && GET_MODE (XEXP (mem, 0)) == GET_MODE (r) + && rtx_equal_p (XEXP (XEXP (mem, 0), 0), XEXP (r, 0))) + return 1; +#endif + } + } + else + { + while (GET_CODE (r) == SUBREG + || GET_CODE (r) == STRICT_LOW_PART + || GET_CODE (r) == ZERO_EXTRACT) + r = XEXP (r, 0); + + if (REG_P (r)) + { + int regno = REGNO (r); + + /* Obvious. */ + if (REGNO_REG_SET_P (pbi->reg_live, regno)) + return 0; + + /* If this is a hard register, verify that subsequent + words are not needed. */ + if (regno < FIRST_PSEUDO_REGISTER) + { + int n = hard_regno_nregs[regno][GET_MODE (r)]; + + while (--n > 0) + if (REGNO_REG_SET_P (pbi->reg_live, regno+n)) + return 0; + } + + /* Don't delete insns to set global regs. */ + if (regno < FIRST_PSEUDO_REGISTER && global_regs[regno]) + return 0; + + /* Make sure insns to set the stack pointer aren't deleted. */ + if (regno == STACK_POINTER_REGNUM) + return 0; + + /* ??? These bits might be redundant with the force live bits + in calculate_global_regs_live. We would delete from + sequential sets; whether this actually affects real code + for anything but the stack pointer I don't know. */ + /* Make sure insns to set the frame pointer aren't deleted. */ + if (regno == FRAME_POINTER_REGNUM + && (! reload_completed || frame_pointer_needed)) + return 0; +#if FRAME_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM + if (regno == HARD_FRAME_POINTER_REGNUM + && (! reload_completed || frame_pointer_needed)) + return 0; +#endif + +#if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM + /* Make sure insns to set arg pointer are never deleted + (if the arg pointer isn't fixed, there will be a USE + for it, so we can treat it normally). */ + if (regno == ARG_POINTER_REGNUM && fixed_regs[regno]) + return 0; +#endif + + /* Otherwise, the set is dead. */ + return 1; + } + } + } + + /* If performing several activities, insn is dead if each activity + is individually dead. Also, CLOBBERs and USEs can be ignored; a + CLOBBER or USE that's inside a PARALLEL doesn't make the insn + worth keeping. */ + else if (code == PARALLEL) + { + int i = XVECLEN (x, 0); + + for (i--; i >= 0; i--) + if (GET_CODE (XVECEXP (x, 0, i)) != CLOBBER + && GET_CODE (XVECEXP (x, 0, i)) != USE + && ! insn_dead_p (pbi, XVECEXP (x, 0, i), call_ok, NULL_RTX)) + return 0; + + return 1; + } + + /* A CLOBBER of a pseudo-register that is dead serves no purpose. That + is not necessarily true for hard registers until after reload. */ + else if (code == CLOBBER) + { + if (REG_P (XEXP (x, 0)) + && (REGNO (XEXP (x, 0)) >= FIRST_PSEUDO_REGISTER + || reload_completed) + && ! REGNO_REG_SET_P (pbi->reg_live, REGNO (XEXP (x, 0)))) + return 1; + } + + /* ??? A base USE is a historical relic. It ought not be needed anymore. + Instances where it is still used are either (1) temporary and the USE + escaped the pass, (2) cruft and the USE need not be emitted anymore, + or (3) hiding bugs elsewhere that are not properly representing data + flow. */ + + return 0; +} + +/* If INSN is the last insn in a libcall, and assuming INSN is dead, + return 1 if the entire library call is dead. + This is true if INSN copies a register (hard or pseudo) + and if the hard return reg of the call insn is dead. + (The caller should have tested the destination of the SET inside + INSN already for death.) + + If this insn doesn't just copy a register, then we don't + have an ordinary libcall. In that case, cse could not have + managed to substitute the source for the dest later on, + so we can assume the libcall is dead. + + PBI is the block info giving pseudoregs live before this insn. + NOTE is the REG_RETVAL note of the insn. */ + +static int +libcall_dead_p (struct propagate_block_info *pbi, rtx note, rtx insn) +{ + rtx x = single_set (insn); + + if (x) + { + rtx r = SET_SRC (x); + + if (REG_P (r) || GET_CODE (r) == SUBREG) + { + rtx call = XEXP (note, 0); + rtx call_pat; + int i; + + /* Find the call insn. */ + while (call != insn && !CALL_P (call)) + call = NEXT_INSN (call); + + /* If there is none, do nothing special, + since ordinary death handling can understand these insns. */ + if (call == insn) + return 0; + + /* See if the hard reg holding the value is dead. + If this is a PARALLEL, find the call within it. */ + call_pat = PATTERN (call); + if (GET_CODE (call_pat) == PARALLEL) + { + for (i = XVECLEN (call_pat, 0) - 1; i >= 0; i--) + if (GET_CODE (XVECEXP (call_pat, 0, i)) == SET + && GET_CODE (SET_SRC (XVECEXP (call_pat, 0, i))) == CALL) + break; + + /* This may be a library call that is returning a value + via invisible pointer. Do nothing special, since + ordinary death handling can understand these insns. */ + if (i < 0) + return 0; + + call_pat = XVECEXP (call_pat, 0, i); + } + + if (! insn_dead_p (pbi, call_pat, 1, REG_NOTES (call))) + return 0; + + while ((insn = PREV_INSN (insn)) != call) + { + if (! INSN_P (insn)) + continue; + if (! insn_dead_p (pbi, PATTERN (insn), 0, REG_NOTES (insn))) + return 0; + } + return 1; + } + } + return 0; +} + +/* 1 if register REGNO was alive at a place where `setjmp' was called + and was set more than once or is an argument. + Such regs may be clobbered by `longjmp'. */ + +int +regno_clobbered_at_setjmp (int regno) +{ + if (n_basic_blocks == NUM_FIXED_BLOCKS) + return 0; + + return ((REG_N_SETS (regno) > 1 + || REGNO_REG_SET_P (ENTRY_BLOCK_PTR->il.rtl->global_live_at_end, + regno)) + && REGNO_REG_SET_P (regs_live_at_setjmp, regno)); +} + +/* Add MEM to PBI->MEM_SET_LIST. MEM should be canonical. Respect the + maximal list size; look for overlaps in mode and select the largest. */ +static void +add_to_mem_set_list (struct propagate_block_info *pbi, rtx mem) +{ + rtx i; + + /* We don't know how large a BLKmode store is, so we must not + take them into consideration. */ + if (GET_MODE (mem) == BLKmode) + return; + + for (i = pbi->mem_set_list; i ; i = XEXP (i, 1)) + { + rtx e = XEXP (i, 0); + if (rtx_equal_p (XEXP (mem, 0), XEXP (e, 0))) + { + if (GET_MODE_SIZE (GET_MODE (mem)) > GET_MODE_SIZE (GET_MODE (e))) + { +#ifdef AUTO_INC_DEC + /* If we must store a copy of the mem, we can just modify + the mode of the stored copy. */ + if (pbi->flags & PROP_AUTOINC) + PUT_MODE (e, GET_MODE (mem)); + else +#endif + XEXP (i, 0) = mem; + } + return; + } + } + + if (pbi->mem_set_list_len < PARAM_VALUE (PARAM_MAX_FLOW_MEMORY_LOCATIONS)) + { +#ifdef AUTO_INC_DEC + /* Store a copy of mem, otherwise the address may be + scrogged by find_auto_inc. */ + if (pbi->flags & PROP_AUTOINC) + mem = shallow_copy_rtx (mem); +#endif + pbi->mem_set_list = alloc_EXPR_LIST (0, mem, pbi->mem_set_list); + pbi->mem_set_list_len++; + } +} + +/* INSN references memory, possibly using autoincrement addressing modes. + Find any entries on the mem_set_list that need to be invalidated due + to an address change. */ + +static int +invalidate_mems_from_autoinc (rtx *px, void *data) +{ + rtx x = *px; + struct propagate_block_info *pbi = data; + + if (GET_RTX_CLASS (GET_CODE (x)) == RTX_AUTOINC) + { + invalidate_mems_from_set (pbi, XEXP (x, 0)); + return -1; + } + + return 0; +} + +/* EXP is a REG or MEM. Remove any dependent entries from + pbi->mem_set_list. */ + +static void +invalidate_mems_from_set (struct propagate_block_info *pbi, rtx exp) +{ + rtx temp = pbi->mem_set_list; + rtx prev = NULL_RTX; + rtx next; + + while (temp) + { + next = XEXP (temp, 1); + if ((REG_P (exp) && reg_overlap_mentioned_p (exp, XEXP (temp, 0))) + /* When we get an EXP that is a mem here, we want to check if EXP + overlaps the *address* of any of the mems in the list (i.e. not + whether the mems actually overlap; that's done elsewhere). */ + || (MEM_P (exp) + && reg_overlap_mentioned_p (exp, XEXP (XEXP (temp, 0), 0)))) + { + /* Splice this entry out of the list. */ + if (prev) + XEXP (prev, 1) = next; + else + pbi->mem_set_list = next; + free_EXPR_LIST_node (temp); + pbi->mem_set_list_len--; + } + else + prev = temp; + temp = next; + } +} + +/* Process the registers that are set within X. Their bits are set to + 1 in the regset DEAD, because they are dead prior to this insn. + + If INSN is nonzero, it is the insn being processed. + + FLAGS is the set of operations to perform. */ + +static void +mark_set_regs (struct propagate_block_info *pbi, rtx x, rtx insn) +{ + rtx cond = NULL_RTX; + rtx link; + enum rtx_code code; + int flags = pbi->flags; + + if (insn) + for (link = REG_NOTES (insn); link; link = XEXP (link, 1)) + { + if (REG_NOTE_KIND (link) == REG_INC) + mark_set_1 (pbi, SET, XEXP (link, 0), + (GET_CODE (x) == COND_EXEC + ? COND_EXEC_TEST (x) : NULL_RTX), + insn, flags); + } + retry: + switch (code = GET_CODE (x)) + { + case SET: + if (GET_CODE (XEXP (x, 1)) == ASM_OPERANDS) + flags |= PROP_ASM_SCAN; + /* Fall through */ + case CLOBBER: + mark_set_1 (pbi, code, SET_DEST (x), cond, insn, flags); + return; + + case COND_EXEC: + cond = COND_EXEC_TEST (x); + x = COND_EXEC_CODE (x); + goto retry; + + case PARALLEL: + { + int i; + + /* We must scan forwards. If we have an asm, we need to set + the PROP_ASM_SCAN flag before scanning the clobbers. */ + for (i = 0; i < XVECLEN (x, 0); i++) + { + rtx sub = XVECEXP (x, 0, i); + switch (code = GET_CODE (sub)) + { + case COND_EXEC: + gcc_assert (!cond); + + cond = COND_EXEC_TEST (sub); + sub = COND_EXEC_CODE (sub); + if (GET_CODE (sub) == SET) + goto mark_set; + if (GET_CODE (sub) == CLOBBER) + goto mark_clob; + break; + + case SET: + mark_set: + if (GET_CODE (XEXP (sub, 1)) == ASM_OPERANDS) + flags |= PROP_ASM_SCAN; + /* Fall through */ + case CLOBBER: + mark_clob: + mark_set_1 (pbi, code, SET_DEST (sub), cond, insn, flags); + break; + + case ASM_OPERANDS: + flags |= PROP_ASM_SCAN; + break; + + default: + break; + } + } + break; + } + + default: + break; + } +} + +/* Process a single set, which appears in INSN. REG (which may not + actually be a REG, it may also be a SUBREG, PARALLEL, etc.) is + being set using the CODE (which may be SET, CLOBBER, or COND_EXEC). + If the set is conditional (because it appear in a COND_EXEC), COND + will be the condition. */ + +static void +mark_set_1 (struct propagate_block_info *pbi, enum rtx_code code, rtx reg, rtx cond, rtx insn, int flags) +{ + int regno_first = -1, regno_last = -1; + unsigned long not_dead = 0; + int i; + + /* Modifying just one hardware register of a multi-reg value or just a + byte field of a register does not mean the value from before this insn + is now dead. Of course, if it was dead after it's unused now. */ + + switch (GET_CODE (reg)) + { + case PARALLEL: + /* Some targets place small structures in registers for return values of + functions. We have to detect this case specially here to get correct + flow information. */ + for (i = XVECLEN (reg, 0) - 1; i >= 0; i--) + if (XEXP (XVECEXP (reg, 0, i), 0) != 0) + mark_set_1 (pbi, code, XEXP (XVECEXP (reg, 0, i), 0), cond, insn, + flags); + return; + + case SIGN_EXTRACT: + /* SIGN_EXTRACT cannot be an lvalue. */ + gcc_unreachable (); + + case ZERO_EXTRACT: + case STRICT_LOW_PART: + /* ??? Assumes STRICT_LOW_PART not used on multi-word registers. */ + do + reg = XEXP (reg, 0); + while (GET_CODE (reg) == SUBREG + || GET_CODE (reg) == ZERO_EXTRACT + || GET_CODE (reg) == STRICT_LOW_PART); + if (MEM_P (reg)) + break; + not_dead = (unsigned long) REGNO_REG_SET_P (pbi->reg_live, REGNO (reg)); + /* Fall through. */ + + case REG: + regno_last = regno_first = REGNO (reg); + if (regno_first < FIRST_PSEUDO_REGISTER) + regno_last += hard_regno_nregs[regno_first][GET_MODE (reg)] - 1; + break; + + case SUBREG: + if (REG_P (SUBREG_REG (reg))) + { + enum machine_mode outer_mode = GET_MODE (reg); + enum machine_mode inner_mode = GET_MODE (SUBREG_REG (reg)); + + /* Identify the range of registers affected. This is moderately + tricky for hard registers. See alter_subreg. */ + + regno_last = regno_first = REGNO (SUBREG_REG (reg)); + if (regno_first < FIRST_PSEUDO_REGISTER) + { + regno_first += subreg_regno_offset (regno_first, inner_mode, + SUBREG_BYTE (reg), + outer_mode); + regno_last = (regno_first + + hard_regno_nregs[regno_first][outer_mode] - 1); + + /* Since we've just adjusted the register number ranges, make + sure REG matches. Otherwise some_was_live will be clear + when it shouldn't have been, and we'll create incorrect + REG_UNUSED notes. */ + reg = gen_rtx_REG (outer_mode, regno_first); + } + else + { + /* If the number of words in the subreg is less than the number + of words in the full register, we have a well-defined partial + set. Otherwise the high bits are undefined. + + This is only really applicable to pseudos, since we just took + care of multi-word hard registers. */ + if (((GET_MODE_SIZE (outer_mode) + + UNITS_PER_WORD - 1) / UNITS_PER_WORD) + < ((GET_MODE_SIZE (inner_mode) + + UNITS_PER_WORD - 1) / UNITS_PER_WORD)) + not_dead = (unsigned long) REGNO_REG_SET_P (pbi->reg_live, + regno_first); + + reg = SUBREG_REG (reg); + } + } + else + reg = SUBREG_REG (reg); + break; + + default: + break; + } + + /* If this set is a MEM, then it kills any aliased writes and any + other MEMs which use it. + If this set is a REG, then it kills any MEMs which use the reg. */ + if (optimize && (flags & PROP_SCAN_DEAD_STORES)) + { + if (REG_P (reg) || MEM_P (reg)) + invalidate_mems_from_set (pbi, reg); + + /* If the memory reference had embedded side effects (autoincrement + address modes) then we may need to kill some entries on the + memory set list. */ + if (insn && MEM_P (reg)) + for_each_rtx (&PATTERN (insn), invalidate_mems_from_autoinc, pbi); + + if (MEM_P (reg) && ! side_effects_p (reg) + /* ??? With more effort we could track conditional memory life. */ + && ! cond) + add_to_mem_set_list (pbi, canon_rtx (reg)); + } + + if (REG_P (reg) + && ! (regno_first == FRAME_POINTER_REGNUM + && (! reload_completed || frame_pointer_needed)) +#if FRAME_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM + && ! (regno_first == HARD_FRAME_POINTER_REGNUM + && (! reload_completed || frame_pointer_needed)) +#endif +#if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM + && ! (regno_first == ARG_POINTER_REGNUM && fixed_regs[regno_first]) +#endif + ) + { + int some_was_live = 0, some_was_dead = 0; + + for (i = regno_first; i <= regno_last; ++i) + { + int needed_regno = REGNO_REG_SET_P (pbi->reg_live, i); + if (pbi->local_set) + { + /* Order of the set operation matters here since both + sets may be the same. */ + CLEAR_REGNO_REG_SET (pbi->cond_local_set, i); + if (cond != NULL_RTX + && ! REGNO_REG_SET_P (pbi->local_set, i)) + SET_REGNO_REG_SET (pbi->cond_local_set, i); + else + SET_REGNO_REG_SET (pbi->local_set, i); + } + if (code != CLOBBER || needed_regno) + SET_REGNO_REG_SET (pbi->new_set, i); + + some_was_live |= needed_regno; + some_was_dead |= ! needed_regno; + } + +#ifdef HAVE_conditional_execution + /* Consider conditional death in deciding that the register needs + a death note. */ + if (some_was_live && ! not_dead + /* The stack pointer is never dead. Well, not strictly true, + but it's very difficult to tell from here. Hopefully + combine_stack_adjustments will fix up the most egregious + errors. */ + && regno_first != STACK_POINTER_REGNUM) + { + for (i = regno_first; i <= regno_last; ++i) + if (! mark_regno_cond_dead (pbi, i, cond)) + not_dead |= ((unsigned long) 1) << (i - regno_first); + } +#endif + + /* Additional data to record if this is the final pass. */ + if (flags & (PROP_LOG_LINKS | PROP_REG_INFO + | PROP_DEATH_NOTES | PROP_AUTOINC)) + { + rtx y; + int blocknum = pbi->bb->index; + + y = NULL_RTX; + if (flags & (PROP_LOG_LINKS | PROP_AUTOINC)) + { + y = pbi->reg_next_use[regno_first]; + + /* The next use is no longer next, since a store intervenes. */ + for (i = regno_first; i <= regno_last; ++i) + pbi->reg_next_use[i] = 0; + } + + if (flags & PROP_REG_INFO) + { + for (i = regno_first; i <= regno_last; ++i) + { + /* Count (weighted) references, stores, etc. This counts a + register twice if it is modified, but that is correct. */ + REG_N_SETS (i) += 1; + REG_N_REFS (i) += 1; + REG_FREQ (i) += REG_FREQ_FROM_BB (pbi->bb); + + /* The insns where a reg is live are normally counted + elsewhere, but we want the count to include the insn + where the reg is set, and the normal counting mechanism + would not count it. */ + REG_LIVE_LENGTH (i) += 1; + } + + /* If this is a hard reg, record this function uses the reg. */ + if (regno_first < FIRST_PSEUDO_REGISTER) + { + for (i = regno_first; i <= regno_last; i++) + regs_ever_live[i] = 1; + if (flags & PROP_ASM_SCAN) + for (i = regno_first; i <= regno_last; i++) + regs_asm_clobbered[i] = 1; + } + else + { + /* Keep track of which basic blocks each reg appears in. */ + if (REG_BASIC_BLOCK (regno_first) == REG_BLOCK_UNKNOWN) + REG_BASIC_BLOCK (regno_first) = blocknum; + else if (REG_BASIC_BLOCK (regno_first) != blocknum) + REG_BASIC_BLOCK (regno_first) = REG_BLOCK_GLOBAL; + } + } + + if (! some_was_dead) + { + if (flags & PROP_LOG_LINKS) + { + /* Make a logical link from the next following insn + that uses this register, back to this insn. + The following insns have already been processed. + + We don't build a LOG_LINK for hard registers containing + in ASM_OPERANDs. If these registers get replaced, + we might wind up changing the semantics of the insn, + even if reload can make what appear to be valid + assignments later. + + We don't build a LOG_LINK for global registers to + or from a function call. We don't want to let + combine think that it knows what is going on with + global registers. */ + if (y && (BLOCK_NUM (y) == blocknum) + && (regno_first >= FIRST_PSEUDO_REGISTER + || (asm_noperands (PATTERN (y)) < 0 + && ! ((CALL_P (insn) + || CALL_P (y)) + && global_regs[regno_first])))) + LOG_LINKS (y) = alloc_INSN_LIST (insn, LOG_LINKS (y)); + } + } + else if (not_dead) + ; + else if (! some_was_live) + { + if (flags & PROP_REG_INFO) + REG_N_DEATHS (regno_first) += 1; + + if (flags & PROP_DEATH_NOTES +#ifdef STACK_REGS + && (!(flags & PROP_POST_REGSTACK) + || !IN_RANGE (REGNO (reg), FIRST_STACK_REG, + LAST_STACK_REG)) +#endif + ) + { + /* Note that dead stores have already been deleted + when possible. If we get here, we have found a + dead store that cannot be eliminated (because the + same insn does something useful). Indicate this + by marking the reg being set as dying here. */ + REG_NOTES (insn) + = alloc_EXPR_LIST (REG_UNUSED, reg, REG_NOTES (insn)); + } + } + else + { + if (flags & PROP_DEATH_NOTES +#ifdef STACK_REGS + && (!(flags & PROP_POST_REGSTACK) + || !IN_RANGE (REGNO (reg), FIRST_STACK_REG, + LAST_STACK_REG)) +#endif + ) + { + /* This is a case where we have a multi-word hard register + and some, but not all, of the words of the register are + needed in subsequent insns. Write REG_UNUSED notes + for those parts that were not needed. This case should + be rare. */ + + for (i = regno_first; i <= regno_last; ++i) + if (! REGNO_REG_SET_P (pbi->reg_live, i)) + REG_NOTES (insn) + = alloc_EXPR_LIST (REG_UNUSED, + regno_reg_rtx[i], + REG_NOTES (insn)); + } + } + } + + /* Mark the register as being dead. */ + if (some_was_live + /* The stack pointer is never dead. Well, not strictly true, + but it's very difficult to tell from here. Hopefully + combine_stack_adjustments will fix up the most egregious + errors. */ + && regno_first != STACK_POINTER_REGNUM) + { + for (i = regno_first; i <= regno_last; ++i) + if (!(not_dead & (((unsigned long) 1) << (i - regno_first)))) + { + if ((pbi->flags & PROP_REG_INFO) + && REGNO_REG_SET_P (pbi->reg_live, i)) + { + REG_LIVE_LENGTH (i) += pbi->insn_num - reg_deaths[i]; + reg_deaths[i] = 0; + } + CLEAR_REGNO_REG_SET (pbi->reg_live, i); + } + if (flags & PROP_DEAD_INSN) + emit_insn_after (gen_rtx_CLOBBER (VOIDmode, reg), insn); + } + } + else if (REG_P (reg)) + { + if (flags & (PROP_LOG_LINKS | PROP_AUTOINC)) + pbi->reg_next_use[regno_first] = 0; + + if ((flags & PROP_REG_INFO) != 0 + && (flags & PROP_ASM_SCAN) != 0 + && regno_first < FIRST_PSEUDO_REGISTER) + { + for (i = regno_first; i <= regno_last; i++) + regs_asm_clobbered[i] = 1; + } + } + + /* If this is the last pass and this is a SCRATCH, show it will be dying + here and count it. */ + else if (GET_CODE (reg) == SCRATCH) + { + if (flags & PROP_DEATH_NOTES +#ifdef STACK_REGS + && (!(flags & PROP_POST_REGSTACK) + || !IN_RANGE (REGNO (reg), FIRST_STACK_REG, LAST_STACK_REG)) +#endif + ) + REG_NOTES (insn) + = alloc_EXPR_LIST (REG_UNUSED, reg, REG_NOTES (insn)); + } +} + +#ifdef HAVE_conditional_execution +/* Mark REGNO conditionally dead. + Return true if the register is now unconditionally dead. */ + +static int +mark_regno_cond_dead (struct propagate_block_info *pbi, int regno, rtx cond) +{ + /* If this is a store to a predicate register, the value of the + predicate is changing, we don't know that the predicate as seen + before is the same as that seen after. Flush all dependent + conditions from reg_cond_dead. This will make all such + conditionally live registers unconditionally live. */ + if (REGNO_REG_SET_P (pbi->reg_cond_reg, regno)) + flush_reg_cond_reg (pbi, regno); + + /* If this is an unconditional store, remove any conditional + life that may have existed. */ + if (cond == NULL_RTX) + splay_tree_remove (pbi->reg_cond_dead, regno); + else + { + splay_tree_node node; + struct reg_cond_life_info *rcli; + rtx ncond; + + /* Otherwise this is a conditional set. Record that fact. + It may have been conditionally used, or there may be a + subsequent set with a complementary condition. */ + + node = splay_tree_lookup (pbi->reg_cond_dead, regno); + if (node == NULL) + { + /* The register was unconditionally live previously. + Record the current condition as the condition under + which it is dead. */ + rcli = XNEW (struct reg_cond_life_info); + rcli->condition = cond; + rcli->stores = cond; + rcli->orig_condition = const0_rtx; + splay_tree_insert (pbi->reg_cond_dead, regno, + (splay_tree_value) rcli); + + SET_REGNO_REG_SET (pbi->reg_cond_reg, REGNO (XEXP (cond, 0))); + + /* Not unconditionally dead. */ + return 0; + } + else + { + /* The register was conditionally live previously. + Add the new condition to the old. */ + rcli = (struct reg_cond_life_info *) node->value; + ncond = rcli->condition; + ncond = ior_reg_cond (ncond, cond, 1); + if (rcli->stores == const0_rtx) + rcli->stores = cond; + else if (rcli->stores != const1_rtx) + rcli->stores = ior_reg_cond (rcli->stores, cond, 1); + + /* If the register is now unconditionally dead, remove the entry + in the splay_tree. A register is unconditionally dead if the + dead condition ncond is true. A register is also unconditionally + dead if the sum of all conditional stores is an unconditional + store (stores is true), and the dead condition is identically the + same as the original dead condition initialized at the end of + the block. This is a pointer compare, not an rtx_equal_p + compare. */ + if (ncond == const1_rtx + || (ncond == rcli->orig_condition && rcli->stores == const1_rtx)) + splay_tree_remove (pbi->reg_cond_dead, regno); + else + { + rcli->condition = ncond; + + SET_REGNO_REG_SET (pbi->reg_cond_reg, REGNO (XEXP (cond, 0))); + + /* Not unconditionally dead. */ + return 0; + } + } + } + + return 1; +} + +/* Called from splay_tree_delete for pbi->reg_cond_life. */ + +static void +free_reg_cond_life_info (splay_tree_value value) +{ + struct reg_cond_life_info *rcli = (struct reg_cond_life_info *) value; + free (rcli); +} + +/* Helper function for flush_reg_cond_reg. */ + +static int +flush_reg_cond_reg_1 (splay_tree_node node, void *data) +{ + struct reg_cond_life_info *rcli; + int *xdata = (int *) data; + unsigned int regno = xdata[0]; + + /* Don't need to search if last flushed value was farther on in + the in-order traversal. */ + if (xdata[1] >= (int) node->key) + return 0; + + /* Splice out portions of the expression that refer to regno. */ + rcli = (struct reg_cond_life_info *) node->value; + rcli->condition = elim_reg_cond (rcli->condition, regno); + if (rcli->stores != const0_rtx && rcli->stores != const1_rtx) + rcli->stores = elim_reg_cond (rcli->stores, regno); + + /* If the entire condition is now false, signal the node to be removed. */ + if (rcli->condition == const0_rtx) + { + xdata[1] = node->key; + return -1; + } + else + gcc_assert (rcli->condition != const1_rtx); + + return 0; +} + +/* Flush all (sub) expressions referring to REGNO from REG_COND_LIVE. */ + +static void +flush_reg_cond_reg (struct propagate_block_info *pbi, int regno) +{ + int pair[2]; + + pair[0] = regno; + pair[1] = -1; + while (splay_tree_foreach (pbi->reg_cond_dead, + flush_reg_cond_reg_1, pair) == -1) + splay_tree_remove (pbi->reg_cond_dead, pair[1]); + + CLEAR_REGNO_REG_SET (pbi->reg_cond_reg, regno); +} + +/* Logical arithmetic on predicate conditions. IOR, NOT and AND. + For ior/and, the ADD flag determines whether we want to add the new + condition X to the old one unconditionally. If it is zero, we will + only return a new expression if X allows us to simplify part of + OLD, otherwise we return NULL to the caller. + If ADD is nonzero, we will return a new condition in all cases. The + toplevel caller of one of these functions should always pass 1 for + ADD. */ + +static rtx +ior_reg_cond (rtx old, rtx x, int add) +{ + rtx op0, op1; + + if (COMPARISON_P (old)) + { + if (COMPARISON_P (x) + && REVERSE_CONDEXEC_PREDICATES_P (x, old) + && REGNO (XEXP (x, 0)) == REGNO (XEXP (old, 0))) + return const1_rtx; + if (GET_CODE (x) == GET_CODE (old) + && REGNO (XEXP (x, 0)) == REGNO (XEXP (old, 0))) + return old; + if (! add) + return NULL; + return gen_rtx_IOR (0, old, x); + } + + switch (GET_CODE (old)) + { + case IOR: + op0 = ior_reg_cond (XEXP (old, 0), x, 0); + op1 = ior_reg_cond (XEXP (old, 1), x, 0); + if (op0 != NULL || op1 != NULL) + { + if (op0 == const0_rtx) + return op1 ? op1 : gen_rtx_IOR (0, XEXP (old, 1), x); + if (op1 == const0_rtx) + return op0 ? op0 : gen_rtx_IOR (0, XEXP (old, 0), x); + if (op0 == const1_rtx || op1 == const1_rtx) + return const1_rtx; + if (op0 == NULL) + op0 = gen_rtx_IOR (0, XEXP (old, 0), x); + else if (rtx_equal_p (x, op0)) + /* (x | A) | x ~ (x | A). */ + return old; + if (op1 == NULL) + op1 = gen_rtx_IOR (0, XEXP (old, 1), x); + else if (rtx_equal_p (x, op1)) + /* (A | x) | x ~ (A | x). */ + return old; + return gen_rtx_IOR (0, op0, op1); + } + if (! add) + return NULL; + return gen_rtx_IOR (0, old, x); + + case AND: + op0 = ior_reg_cond (XEXP (old, 0), x, 0); + op1 = ior_reg_cond (XEXP (old, 1), x, 0); + if (op0 != NULL || op1 != NULL) + { + if (op0 == const1_rtx) + return op1 ? op1 : gen_rtx_IOR (0, XEXP (old, 1), x); + if (op1 == const1_rtx) + return op0 ? op0 : gen_rtx_IOR (0, XEXP (old, 0), x); + if (op0 == const0_rtx || op1 == const0_rtx) + return const0_rtx; + if (op0 == NULL) + op0 = gen_rtx_IOR (0, XEXP (old, 0), x); + else if (rtx_equal_p (x, op0)) + /* (x & A) | x ~ x. */ + return op0; + if (op1 == NULL) + op1 = gen_rtx_IOR (0, XEXP (old, 1), x); + else if (rtx_equal_p (x, op1)) + /* (A & x) | x ~ x. */ + return op1; + return gen_rtx_AND (0, op0, op1); + } + if (! add) + return NULL; + return gen_rtx_IOR (0, old, x); + + case NOT: + op0 = and_reg_cond (XEXP (old, 0), not_reg_cond (x), 0); + if (op0 != NULL) + return not_reg_cond (op0); + if (! add) + return NULL; + return gen_rtx_IOR (0, old, x); + + default: + gcc_unreachable (); + } +} + +static rtx +not_reg_cond (rtx x) +{ + if (x == const0_rtx) + return const1_rtx; + else if (x == const1_rtx) + return const0_rtx; + if (GET_CODE (x) == NOT) + return XEXP (x, 0); + if (COMPARISON_P (x) + && REG_P (XEXP (x, 0))) + { + gcc_assert (XEXP (x, 1) == const0_rtx); + + return gen_rtx_fmt_ee (reversed_comparison_code (x, NULL), + VOIDmode, XEXP (x, 0), const0_rtx); + } + return gen_rtx_NOT (0, x); +} + +static rtx +and_reg_cond (rtx old, rtx x, int add) +{ + rtx op0, op1; + + if (COMPARISON_P (old)) + { + if (COMPARISON_P (x) + && GET_CODE (x) == reversed_comparison_code (old, NULL) + && REGNO (XEXP (x, 0)) == REGNO (XEXP (old, 0))) + return const0_rtx; + if (GET_CODE (x) == GET_CODE (old) + && REGNO (XEXP (x, 0)) == REGNO (XEXP (old, 0))) + return old; + if (! add) + return NULL; + return gen_rtx_AND (0, old, x); + } + + switch (GET_CODE (old)) + { + case IOR: + op0 = and_reg_cond (XEXP (old, 0), x, 0); + op1 = and_reg_cond (XEXP (old, 1), x, 0); + if (op0 != NULL || op1 != NULL) + { + if (op0 == const0_rtx) + return op1 ? op1 : gen_rtx_AND (0, XEXP (old, 1), x); + if (op1 == const0_rtx) + return op0 ? op0 : gen_rtx_AND (0, XEXP (old, 0), x); + if (op0 == const1_rtx || op1 == const1_rtx) + return const1_rtx; + if (op0 == NULL) + op0 = gen_rtx_AND (0, XEXP (old, 0), x); + else if (rtx_equal_p (x, op0)) + /* (x | A) & x ~ x. */ + return op0; + if (op1 == NULL) + op1 = gen_rtx_AND (0, XEXP (old, 1), x); + else if (rtx_equal_p (x, op1)) + /* (A | x) & x ~ x. */ + return op1; + return gen_rtx_IOR (0, op0, op1); + } + if (! add) + return NULL; + return gen_rtx_AND (0, old, x); + + case AND: + op0 = and_reg_cond (XEXP (old, 0), x, 0); + op1 = and_reg_cond (XEXP (old, 1), x, 0); + if (op0 != NULL || op1 != NULL) + { + if (op0 == const1_rtx) + return op1 ? op1 : gen_rtx_AND (0, XEXP (old, 1), x); + if (op1 == const1_rtx) + return op0 ? op0 : gen_rtx_AND (0, XEXP (old, 0), x); + if (op0 == const0_rtx || op1 == const0_rtx) + return const0_rtx; + if (op0 == NULL) + op0 = gen_rtx_AND (0, XEXP (old, 0), x); + else if (rtx_equal_p (x, op0)) + /* (x & A) & x ~ (x & A). */ + return old; + if (op1 == NULL) + op1 = gen_rtx_AND (0, XEXP (old, 1), x); + else if (rtx_equal_p (x, op1)) + /* (A & x) & x ~ (A & x). */ + return old; + return gen_rtx_AND (0, op0, op1); + } + if (! add) + return NULL; + return gen_rtx_AND (0, old, x); + + case NOT: + op0 = ior_reg_cond (XEXP (old, 0), not_reg_cond (x), 0); + if (op0 != NULL) + return not_reg_cond (op0); + if (! add) + return NULL; + return gen_rtx_AND (0, old, x); + + default: + gcc_unreachable (); + } +} + +/* Given a condition X, remove references to reg REGNO and return the + new condition. The removal will be done so that all conditions + involving REGNO are considered to evaluate to false. This function + is used when the value of REGNO changes. */ + +static rtx +elim_reg_cond (rtx x, unsigned int regno) +{ + rtx op0, op1; + + if (COMPARISON_P (x)) + { + if (REGNO (XEXP (x, 0)) == regno) + return const0_rtx; + return x; + } + + switch (GET_CODE (x)) + { + case AND: + op0 = elim_reg_cond (XEXP (x, 0), regno); + op1 = elim_reg_cond (XEXP (x, 1), regno); + if (op0 == const0_rtx || op1 == const0_rtx) + return const0_rtx; + if (op0 == const1_rtx) + return op1; + if (op1 == const1_rtx) + return op0; + if (op0 == XEXP (x, 0) && op1 == XEXP (x, 1)) + return x; + return gen_rtx_AND (0, op0, op1); + + case IOR: + op0 = elim_reg_cond (XEXP (x, 0), regno); + op1 = elim_reg_cond (XEXP (x, 1), regno); + if (op0 == const1_rtx || op1 == const1_rtx) + return const1_rtx; + if (op0 == const0_rtx) + return op1; + if (op1 == const0_rtx) + return op0; + if (op0 == XEXP (x, 0) && op1 == XEXP (x, 1)) + return x; + return gen_rtx_IOR (0, op0, op1); + + case NOT: + op0 = elim_reg_cond (XEXP (x, 0), regno); + if (op0 == const0_rtx) + return const1_rtx; + if (op0 == const1_rtx) + return const0_rtx; + if (op0 != XEXP (x, 0)) + return not_reg_cond (op0); + return x; + + default: + gcc_unreachable (); + } +} +#endif /* HAVE_conditional_execution */ + +#ifdef AUTO_INC_DEC + +/* Try to substitute the auto-inc expression INC as the address inside + MEM which occurs in INSN. Currently, the address of MEM is an expression + involving INCR_REG, and INCR is the next use of INCR_REG; it is an insn + that has a single set whose source is a PLUS of INCR_REG and something + else. */ + +static void +attempt_auto_inc (struct propagate_block_info *pbi, rtx inc, rtx insn, + rtx mem, rtx incr, rtx incr_reg) +{ + int regno = REGNO (incr_reg); + rtx set = single_set (incr); + rtx q = SET_DEST (set); + rtx y = SET_SRC (set); + int opnum = XEXP (y, 0) == incr_reg ? 0 : 1; + int changed; + + /* Make sure this reg appears only once in this insn. */ + if (count_occurrences (PATTERN (insn), incr_reg, 1) != 1) + return; + + if (dead_or_set_p (incr, incr_reg) + /* Mustn't autoinc an eliminable register. */ + && (regno >= FIRST_PSEUDO_REGISTER + || ! TEST_HARD_REG_BIT (elim_reg_set, regno))) + { + /* This is the simple case. Try to make the auto-inc. If + we can't, we are done. Otherwise, we will do any + needed updates below. */ + if (! validate_change (insn, &XEXP (mem, 0), inc, 0)) + return; + } + else if (REG_P (q) + /* PREV_INSN used here to check the semi-open interval + [insn,incr). */ + && ! reg_used_between_p (q, PREV_INSN (insn), incr) + /* We must also check for sets of q as q may be + a call clobbered hard register and there may + be a call between PREV_INSN (insn) and incr. */ + && ! reg_set_between_p (q, PREV_INSN (insn), incr)) + { + /* We have *p followed sometime later by q = p+size. + Both p and q must be live afterward, + and q is not used between INSN and its assignment. + Change it to q = p, ...*q..., q = q+size. + Then fall into the usual case. */ + rtx insns, temp; + + start_sequence (); + emit_move_insn (q, incr_reg); + insns = get_insns (); + end_sequence (); + + /* If we can't make the auto-inc, or can't make the + replacement into Y, exit. There's no point in making + the change below if we can't do the auto-inc and doing + so is not correct in the pre-inc case. */ + + XEXP (inc, 0) = q; + validate_change (insn, &XEXP (mem, 0), inc, 1); + validate_change (incr, &XEXP (y, opnum), q, 1); + if (! apply_change_group ()) + return; + + /* We now know we'll be doing this change, so emit the + new insn(s) and do the updates. */ + emit_insn_before (insns, insn); + + if (BB_HEAD (pbi->bb) == insn) + BB_HEAD (pbi->bb) = insns; + + /* INCR will become a NOTE and INSN won't contain a + use of INCR_REG. If a use of INCR_REG was just placed in + the insn before INSN, make that the next use. + Otherwise, invalidate it. */ + if (NONJUMP_INSN_P (PREV_INSN (insn)) + && GET_CODE (PATTERN (PREV_INSN (insn))) == SET + && SET_SRC (PATTERN (PREV_INSN (insn))) == incr_reg) + pbi->reg_next_use[regno] = PREV_INSN (insn); + else + pbi->reg_next_use[regno] = 0; + + incr_reg = q; + regno = REGNO (q); + + if ((pbi->flags & PROP_REG_INFO) + && !REGNO_REG_SET_P (pbi->reg_live, regno)) + reg_deaths[regno] = pbi->insn_num; + + /* REGNO is now used in INCR which is below INSN, but + it previously wasn't live here. If we don't mark + it as live, we'll put a REG_DEAD note for it + on this insn, which is incorrect. */ + SET_REGNO_REG_SET (pbi->reg_live, regno); + + /* If there are any calls between INSN and INCR, show + that REGNO now crosses them. */ + for (temp = insn; temp != incr; temp = NEXT_INSN (temp)) + if (CALL_P (temp)) + { + REG_N_CALLS_CROSSED (regno)++; + if (can_throw_internal (temp)) + REG_N_THROWING_CALLS_CROSSED (regno)++; + } + + /* Invalidate alias info for Q since we just changed its value. */ + clear_reg_alias_info (q); + } + else + return; + + /* If we haven't returned, it means we were able to make the + auto-inc, so update the status. First, record that this insn + has an implicit side effect. */ + + REG_NOTES (insn) = alloc_EXPR_LIST (REG_INC, incr_reg, REG_NOTES (insn)); + + /* Modify the old increment-insn to simply copy + the already-incremented value of our register. */ + changed = validate_change (incr, &SET_SRC (set), incr_reg, 0); + gcc_assert (changed); + + /* If that makes it a no-op (copying the register into itself) delete + it so it won't appear to be a "use" and a "set" of this + register. */ + if (REGNO (SET_DEST (set)) == REGNO (incr_reg)) + { + /* If the original source was dead, it's dead now. */ + rtx note; + + while ((note = find_reg_note (incr, REG_DEAD, NULL_RTX)) != NULL_RTX) + { + remove_note (incr, note); + if (XEXP (note, 0) != incr_reg) + { + unsigned int regno = REGNO (XEXP (note, 0)); + + if ((pbi->flags & PROP_REG_INFO) + && REGNO_REG_SET_P (pbi->reg_live, regno)) + { + REG_LIVE_LENGTH (regno) += pbi->insn_num - reg_deaths[regno]; + reg_deaths[regno] = 0; + } + CLEAR_REGNO_REG_SET (pbi->reg_live, REGNO (XEXP (note, 0))); + } + } + + SET_INSN_DELETED (incr); + } + + if (regno >= FIRST_PSEUDO_REGISTER) + { + /* Count an extra reference to the reg. When a reg is + incremented, spilling it is worse, so we want to make + that less likely. */ + REG_FREQ (regno) += REG_FREQ_FROM_BB (pbi->bb); + + /* Count the increment as a setting of the register, + even though it isn't a SET in rtl. */ + REG_N_SETS (regno)++; + } +} + +/* X is a MEM found in INSN. See if we can convert it into an auto-increment + reference. */ + +static void +find_auto_inc (struct propagate_block_info *pbi, rtx x, rtx insn) +{ + rtx addr = XEXP (x, 0); + HOST_WIDE_INT offset = 0; + rtx set, y, incr, inc_val; + int regno; + int size = GET_MODE_SIZE (GET_MODE (x)); + + if (JUMP_P (insn)) + return; + + /* Here we detect use of an index register which might be good for + postincrement, postdecrement, preincrement, or predecrement. */ + + if (GET_CODE (addr) == PLUS && GET_CODE (XEXP (addr, 1)) == CONST_INT) + offset = INTVAL (XEXP (addr, 1)), addr = XEXP (addr, 0); + + if (!REG_P (addr)) + return; + + regno = REGNO (addr); + + /* Is the next use an increment that might make auto-increment? */ + incr = pbi->reg_next_use[regno]; + if (incr == 0 || BLOCK_NUM (incr) != BLOCK_NUM (insn)) + return; + set = single_set (incr); + if (set == 0 || GET_CODE (set) != SET) + return; + y = SET_SRC (set); + + if (GET_CODE (y) != PLUS) + return; + + if (REG_P (XEXP (y, 0)) && REGNO (XEXP (y, 0)) == REGNO (addr)) + inc_val = XEXP (y, 1); + else if (REG_P (XEXP (y, 1)) && REGNO (XEXP (y, 1)) == REGNO (addr)) + inc_val = XEXP (y, 0); + else + return; + + if (GET_CODE (inc_val) == CONST_INT) + { + if (HAVE_POST_INCREMENT + && (INTVAL (inc_val) == size && offset == 0)) + attempt_auto_inc (pbi, gen_rtx_POST_INC (Pmode, addr), insn, x, + incr, addr); + else if (HAVE_POST_DECREMENT + && (INTVAL (inc_val) == -size && offset == 0)) + attempt_auto_inc (pbi, gen_rtx_POST_DEC (Pmode, addr), insn, x, + incr, addr); + else if (HAVE_PRE_INCREMENT + && (INTVAL (inc_val) == size && offset == size)) + attempt_auto_inc (pbi, gen_rtx_PRE_INC (Pmode, addr), insn, x, + incr, addr); + else if (HAVE_PRE_DECREMENT + && (INTVAL (inc_val) == -size && offset == -size)) + attempt_auto_inc (pbi, gen_rtx_PRE_DEC (Pmode, addr), insn, x, + incr, addr); + else if (HAVE_POST_MODIFY_DISP && offset == 0) + attempt_auto_inc (pbi, gen_rtx_POST_MODIFY (Pmode, addr, + gen_rtx_PLUS (Pmode, + addr, + inc_val)), + insn, x, incr, addr); + else if (HAVE_PRE_MODIFY_DISP && offset == INTVAL (inc_val)) + attempt_auto_inc (pbi, gen_rtx_PRE_MODIFY (Pmode, addr, + gen_rtx_PLUS (Pmode, + addr, + inc_val)), + insn, x, incr, addr); + } + else if (REG_P (inc_val) + && ! reg_set_between_p (inc_val, PREV_INSN (insn), + NEXT_INSN (incr))) + + { + if (HAVE_POST_MODIFY_REG && offset == 0) + attempt_auto_inc (pbi, gen_rtx_POST_MODIFY (Pmode, addr, + gen_rtx_PLUS (Pmode, + addr, + inc_val)), + insn, x, incr, addr); + } +} + +#endif /* AUTO_INC_DEC */ + +static void +mark_used_reg (struct propagate_block_info *pbi, rtx reg, + rtx cond ATTRIBUTE_UNUSED, rtx insn) +{ + unsigned int regno_first, regno_last, i; + int some_was_live, some_was_dead, some_not_set; + + regno_last = regno_first = REGNO (reg); + if (regno_first < FIRST_PSEUDO_REGISTER) + regno_last += hard_regno_nregs[regno_first][GET_MODE (reg)] - 1; + + /* Find out if any of this register is live after this instruction. */ + some_was_live = some_was_dead = 0; + for (i = regno_first; i <= regno_last; ++i) + { + int needed_regno = REGNO_REG_SET_P (pbi->reg_live, i); + some_was_live |= needed_regno; + some_was_dead |= ! needed_regno; + } + + /* Find out if any of the register was set this insn. */ + some_not_set = 0; + for (i = regno_first; i <= regno_last; ++i) + some_not_set |= ! REGNO_REG_SET_P (pbi->new_set, i); + + if (pbi->flags & (PROP_LOG_LINKS | PROP_AUTOINC)) + { + /* Record where each reg is used, so when the reg is set we know + the next insn that uses it. */ + pbi->reg_next_use[regno_first] = insn; + } + + if (pbi->flags & PROP_REG_INFO) + { + if (regno_first < FIRST_PSEUDO_REGISTER) + { + /* If this is a register we are going to try to eliminate, + don't mark it live here. If we are successful in + eliminating it, it need not be live unless it is used for + pseudos, in which case it will have been set live when it + was allocated to the pseudos. If the register will not + be eliminated, reload will set it live at that point. + + Otherwise, record that this function uses this register. */ + /* ??? The PPC backend tries to "eliminate" on the pic + register to itself. This should be fixed. In the mean + time, hack around it. */ + + if (! (TEST_HARD_REG_BIT (elim_reg_set, regno_first) + && (regno_first == FRAME_POINTER_REGNUM + || regno_first == ARG_POINTER_REGNUM))) + for (i = regno_first; i <= regno_last; ++i) + regs_ever_live[i] = 1; + } + else + { + /* Keep track of which basic block each reg appears in. */ + + int blocknum = pbi->bb->index; + if (REG_BASIC_BLOCK (regno_first) == REG_BLOCK_UNKNOWN) + REG_BASIC_BLOCK (regno_first) = blocknum; + else if (REG_BASIC_BLOCK (regno_first) != blocknum) + REG_BASIC_BLOCK (regno_first) = REG_BLOCK_GLOBAL; + + /* Count (weighted) number of uses of each reg. */ + REG_FREQ (regno_first) += REG_FREQ_FROM_BB (pbi->bb); + REG_N_REFS (regno_first)++; + } + for (i = regno_first; i <= regno_last; ++i) + if (! REGNO_REG_SET_P (pbi->reg_live, i)) + { + gcc_assert (!reg_deaths[i]); + reg_deaths[i] = pbi->insn_num; + } + } + + /* Record and count the insns in which a reg dies. If it is used in + this insn and was dead below the insn then it dies in this insn. + If it was set in this insn, we do not make a REG_DEAD note; + likewise if we already made such a note. */ + if ((pbi->flags & (PROP_DEATH_NOTES | PROP_REG_INFO)) + && some_was_dead + && some_not_set) + { + /* Check for the case where the register dying partially + overlaps the register set by this insn. */ + if (regno_first != regno_last) + for (i = regno_first; i <= regno_last; ++i) + some_was_live |= REGNO_REG_SET_P (pbi->new_set, i); + + /* If none of the words in X is needed, make a REG_DEAD note. + Otherwise, we must make partial REG_DEAD notes. */ + if (! some_was_live) + { + if ((pbi->flags & PROP_DEATH_NOTES) +#ifdef STACK_REGS + && (!(pbi->flags & PROP_POST_REGSTACK) + || !IN_RANGE (REGNO (reg), FIRST_STACK_REG, LAST_STACK_REG)) +#endif + && ! find_regno_note (insn, REG_DEAD, regno_first)) + REG_NOTES (insn) + = alloc_EXPR_LIST (REG_DEAD, reg, REG_NOTES (insn)); + + if (pbi->flags & PROP_REG_INFO) + REG_N_DEATHS (regno_first)++; + } + else + { + /* Don't make a REG_DEAD note for a part of a register + that is set in the insn. */ + for (i = regno_first; i <= regno_last; ++i) + if (! REGNO_REG_SET_P (pbi->reg_live, i) + && ! dead_or_set_regno_p (insn, i)) + REG_NOTES (insn) + = alloc_EXPR_LIST (REG_DEAD, + regno_reg_rtx[i], + REG_NOTES (insn)); + } + } + + /* Mark the register as being live. */ + for (i = regno_first; i <= regno_last; ++i) + { +#ifdef HAVE_conditional_execution + int this_was_live = REGNO_REG_SET_P (pbi->reg_live, i); +#endif + + SET_REGNO_REG_SET (pbi->reg_live, i); + +#ifdef HAVE_conditional_execution + /* If this is a conditional use, record that fact. If it is later + conditionally set, we'll know to kill the register. */ + if (cond != NULL_RTX) + { + splay_tree_node node; + struct reg_cond_life_info *rcli; + rtx ncond; + + if (this_was_live) + { + node = splay_tree_lookup (pbi->reg_cond_dead, i); + if (node == NULL) + { + /* The register was unconditionally live previously. + No need to do anything. */ + } + else + { + /* The register was conditionally live previously. + Subtract the new life cond from the old death cond. */ + rcli = (struct reg_cond_life_info *) node->value; + ncond = rcli->condition; + ncond = and_reg_cond (ncond, not_reg_cond (cond), 1); + + /* If the register is now unconditionally live, + remove the entry in the splay_tree. */ + if (ncond == const0_rtx) + splay_tree_remove (pbi->reg_cond_dead, i); + else + { + rcli->condition = ncond; + SET_REGNO_REG_SET (pbi->reg_cond_reg, + REGNO (XEXP (cond, 0))); + } + } + } + else + { + /* The register was not previously live at all. Record + the condition under which it is still dead. */ + rcli = XNEW (struct reg_cond_life_info); + rcli->condition = not_reg_cond (cond); + rcli->stores = const0_rtx; + rcli->orig_condition = const0_rtx; + splay_tree_insert (pbi->reg_cond_dead, i, + (splay_tree_value) rcli); + + SET_REGNO_REG_SET (pbi->reg_cond_reg, REGNO (XEXP (cond, 0))); + } + } + else if (this_was_live) + { + /* The register may have been conditionally live previously, but + is now unconditionally live. Remove it from the conditionally + dead list, so that a conditional set won't cause us to think + it dead. */ + splay_tree_remove (pbi->reg_cond_dead, i); + } +#endif + } +} + +/* Scan expression X for registers which have to be marked used in PBI. + X is considered to be the SET_DEST rtx of SET. TRUE is returned if + X could be handled by this function. */ + +static bool +mark_used_dest_regs (struct propagate_block_info *pbi, rtx x, rtx cond, rtx insn) +{ + int regno; + bool mark_dest = false; + rtx dest = x; + + /* On some platforms calls return values spread over several + locations. These locations are wrapped in a EXPR_LIST rtx + together with a CONST_INT offset. */ + if (GET_CODE (x) == EXPR_LIST + && GET_CODE (XEXP (x, 1)) == CONST_INT) + x = XEXP (x, 0); + + if (x == NULL_RTX) + return false; + + /* If storing into MEM, don't show it as being used. But do + show the address as being used. */ + if (MEM_P (x)) + { +#ifdef AUTO_INC_DEC + if (pbi->flags & PROP_AUTOINC) + find_auto_inc (pbi, x, insn); +#endif + mark_used_regs (pbi, XEXP (x, 0), cond, insn); + return true; + } + + /* Storing in STRICT_LOW_PART is like storing in a reg + in that this SET might be dead, so ignore it in TESTREG. + but in some other ways it is like using the reg. + + Storing in a SUBREG or a bit field is like storing the entire + register in that if the register's value is not used + then this SET is not needed. */ + while (GET_CODE (x) == STRICT_LOW_PART + || GET_CODE (x) == ZERO_EXTRACT + || GET_CODE (x) == SUBREG) + { +#ifdef CANNOT_CHANGE_MODE_CLASS + if ((pbi->flags & PROP_REG_INFO) && GET_CODE (x) == SUBREG) + record_subregs_of_mode (x); +#endif + + /* Modifying a single register in an alternate mode + does not use any of the old value. But these other + ways of storing in a register do use the old value. */ + if (GET_CODE (x) == SUBREG + && !((REG_BYTES (SUBREG_REG (x)) + + UNITS_PER_WORD - 1) / UNITS_PER_WORD + > (REG_BYTES (x) + + UNITS_PER_WORD - 1) / UNITS_PER_WORD)) + ; + else + mark_dest = true; + + x = XEXP (x, 0); + } + + /* If this is a store into a register or group of registers, + recursively scan the value being stored. */ + if (REG_P (x) + && (regno = REGNO (x), + !(regno == FRAME_POINTER_REGNUM + && (!reload_completed || frame_pointer_needed))) +#if FRAME_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM + && !(regno == HARD_FRAME_POINTER_REGNUM + && (!reload_completed || frame_pointer_needed)) +#endif +#if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM + && !(regno == ARG_POINTER_REGNUM && fixed_regs[regno]) +#endif + ) + { + if (mark_dest) + mark_used_regs (pbi, dest, cond, insn); + return true; + } + return false; +} + +/* Scan expression X and store a 1-bit in NEW_LIVE for each reg it uses. + This is done assuming the registers needed from X are those that + have 1-bits in PBI->REG_LIVE. + + INSN is the containing instruction. If INSN is dead, this function + is not called. */ + +static void +mark_used_regs (struct propagate_block_info *pbi, rtx x, rtx cond, rtx insn) +{ + RTX_CODE code; + int flags = pbi->flags; + + retry: + if (!x) + return; + code = GET_CODE (x); + switch (code) + { + case LABEL_REF: + case SYMBOL_REF: + case CONST_INT: + case CONST: + case CONST_DOUBLE: + case CONST_VECTOR: + case PC: + case ADDR_VEC: + case ADDR_DIFF_VEC: + return; + +#ifdef HAVE_cc0 + case CC0: + pbi->cc0_live = 1; + return; +#endif + + case CLOBBER: + /* If we are clobbering a MEM, mark any registers inside the address + as being used. */ + if (MEM_P (XEXP (x, 0))) + mark_used_regs (pbi, XEXP (XEXP (x, 0), 0), cond, insn); + return; + + case MEM: + /* Don't bother watching stores to mems if this is not the + final pass. We'll not be deleting dead stores this round. */ + if (optimize && (flags & PROP_SCAN_DEAD_STORES)) + { + /* Invalidate the data for the last MEM stored, but only if MEM is + something that can be stored into. */ + if (GET_CODE (XEXP (x, 0)) == SYMBOL_REF + && CONSTANT_POOL_ADDRESS_P (XEXP (x, 0))) + /* Needn't clear the memory set list. */ + ; + else + { + rtx temp = pbi->mem_set_list; + rtx prev = NULL_RTX; + rtx next; + + while (temp) + { + next = XEXP (temp, 1); + if (anti_dependence (XEXP (temp, 0), x)) + { + /* Splice temp out of the list. */ + if (prev) + XEXP (prev, 1) = next; + else + pbi->mem_set_list = next; + free_EXPR_LIST_node (temp); + pbi->mem_set_list_len--; + } + else + prev = temp; + temp = next; + } + } + + /* If the memory reference had embedded side effects (autoincrement + address modes. Then we may need to kill some entries on the + memory set list. */ + if (insn) + for_each_rtx (&PATTERN (insn), invalidate_mems_from_autoinc, pbi); + } + +#ifdef AUTO_INC_DEC + if (flags & PROP_AUTOINC) + find_auto_inc (pbi, x, insn); +#endif + break; + + case SUBREG: +#ifdef CANNOT_CHANGE_MODE_CLASS + if (flags & PROP_REG_INFO) + record_subregs_of_mode (x); +#endif + + /* While we're here, optimize this case. */ + x = SUBREG_REG (x); + if (!REG_P (x)) + goto retry; + /* Fall through. */ + + case REG: + /* See a register other than being set => mark it as needed. */ + mark_used_reg (pbi, x, cond, insn); + return; + + case SET: + { + rtx dest = SET_DEST (x); + int i; + bool ret = false; + + if (GET_CODE (dest) == PARALLEL) + for (i = 0; i < XVECLEN (dest, 0); i++) + ret |= mark_used_dest_regs (pbi, XVECEXP (dest, 0, i), cond, insn); + else + ret = mark_used_dest_regs (pbi, dest, cond, insn); + + if (ret) + { + mark_used_regs (pbi, SET_SRC (x), cond, insn); + return; + } + } + break; + + case ASM_OPERANDS: + case UNSPEC_VOLATILE: + case TRAP_IF: + case ASM_INPUT: + { + /* Traditional and volatile asm instructions must be considered to use + and clobber all hard registers, all pseudo-registers and all of + memory. So must TRAP_IF and UNSPEC_VOLATILE operations. + + Consider for instance a volatile asm that changes the fpu rounding + mode. An insn should not be moved across this even if it only uses + pseudo-regs because it might give an incorrectly rounded result. + + ?!? Unfortunately, marking all hard registers as live causes massive + problems for the register allocator and marking all pseudos as live + creates mountains of uninitialized variable warnings. + + So for now, just clear the memory set list and mark any regs + we can find in ASM_OPERANDS as used. */ + if (code != ASM_OPERANDS || MEM_VOLATILE_P (x)) + { + free_EXPR_LIST_list (&pbi->mem_set_list); + pbi->mem_set_list_len = 0; + } + + /* For all ASM_OPERANDS, we must traverse the vector of input operands. + We can not just fall through here since then we would be confused + by the ASM_INPUT rtx inside ASM_OPERANDS, which do not indicate + traditional asms unlike their normal usage. */ + if (code == ASM_OPERANDS) + { + int j; + + for (j = 0; j < ASM_OPERANDS_INPUT_LENGTH (x); j++) + mark_used_regs (pbi, ASM_OPERANDS_INPUT (x, j), cond, insn); + } + break; + } + + case COND_EXEC: + gcc_assert (!cond); + + mark_used_regs (pbi, COND_EXEC_TEST (x), NULL_RTX, insn); + + cond = COND_EXEC_TEST (x); + x = COND_EXEC_CODE (x); + goto retry; + + default: + break; + } + + /* Recursively scan the operands of this expression. */ + + { + const char * const fmt = GET_RTX_FORMAT (code); + int i; + + for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--) + { + if (fmt[i] == 'e') + { + /* Tail recursive case: save a function call level. */ + if (i == 0) + { + x = XEXP (x, 0); + goto retry; + } + mark_used_regs (pbi, XEXP (x, i), cond, insn); + } + else if (fmt[i] == 'E') + { + int j; + for (j = 0; j < XVECLEN (x, i); j++) + mark_used_regs (pbi, XVECEXP (x, i, j), cond, insn); + } + } + } +} + +#ifdef AUTO_INC_DEC + +static int +try_pre_increment_1 (struct propagate_block_info *pbi, rtx insn) +{ + /* Find the next use of this reg. If in same basic block, + make it do pre-increment or pre-decrement if appropriate. */ + rtx x = single_set (insn); + HOST_WIDE_INT amount = ((GET_CODE (SET_SRC (x)) == PLUS ? 1 : -1) + * INTVAL (XEXP (SET_SRC (x), 1))); + int regno = REGNO (SET_DEST (x)); + rtx y = pbi->reg_next_use[regno]; + if (y != 0 + && SET_DEST (x) != stack_pointer_rtx + && BLOCK_NUM (y) == BLOCK_NUM (insn) + /* Don't do this if the reg dies, or gets set in y; a standard addressing + mode would be better. */ + && ! dead_or_set_p (y, SET_DEST (x)) + && try_pre_increment (y, SET_DEST (x), amount)) + { + /* We have found a suitable auto-increment and already changed + insn Y to do it. So flush this increment instruction. */ + propagate_block_delete_insn (insn); + + /* Count a reference to this reg for the increment insn we are + deleting. When a reg is incremented, spilling it is worse, + so we want to make that less likely. */ + if (regno >= FIRST_PSEUDO_REGISTER) + { + REG_FREQ (regno) += REG_FREQ_FROM_BB (pbi->bb); + REG_N_SETS (regno)++; + } + + /* Flush any remembered memories depending on the value of + the incremented register. */ + invalidate_mems_from_set (pbi, SET_DEST (x)); + + return 1; + } + return 0; +} + +/* Try to change INSN so that it does pre-increment or pre-decrement + addressing on register REG in order to add AMOUNT to REG. + AMOUNT is negative for pre-decrement. + Returns 1 if the change could be made. + This checks all about the validity of the result of modifying INSN. */ + +static int +try_pre_increment (rtx insn, rtx reg, HOST_WIDE_INT amount) +{ + rtx use; + + /* Nonzero if we can try to make a pre-increment or pre-decrement. + For example, addl $4,r1; movl (r1),... can become movl +(r1),... */ + int pre_ok = 0; + /* Nonzero if we can try to make a post-increment or post-decrement. + For example, addl $4,r1; movl -4(r1),... can become movl (r1)+,... + It is possible for both PRE_OK and POST_OK to be nonzero if the machine + supports both pre-inc and post-inc, or both pre-dec and post-dec. */ + int post_ok = 0; + + /* Nonzero if the opportunity actually requires post-inc or post-dec. */ + int do_post = 0; + + /* From the sign of increment, see which possibilities are conceivable + on this target machine. */ + if (HAVE_PRE_INCREMENT && amount > 0) + pre_ok = 1; + if (HAVE_POST_INCREMENT && amount > 0) + post_ok = 1; + + if (HAVE_PRE_DECREMENT && amount < 0) + pre_ok = 1; + if (HAVE_POST_DECREMENT && amount < 0) + post_ok = 1; + + if (! (pre_ok || post_ok)) + return 0; + + /* It is not safe to add a side effect to a jump insn + because if the incremented register is spilled and must be reloaded + there would be no way to store the incremented value back in memory. */ + + if (JUMP_P (insn)) + return 0; + + use = 0; + if (pre_ok) + use = find_use_as_address (PATTERN (insn), reg, 0); + if (post_ok && (use == 0 || use == (rtx) (size_t) 1)) + { + use = find_use_as_address (PATTERN (insn), reg, -amount); + do_post = 1; + } + + if (use == 0 || use == (rtx) (size_t) 1) + return 0; + + if (GET_MODE_SIZE (GET_MODE (use)) != (amount > 0 ? amount : - amount)) + return 0; + + /* See if this combination of instruction and addressing mode exists. */ + if (! validate_change (insn, &XEXP (use, 0), + gen_rtx_fmt_e (amount > 0 + ? (do_post ? POST_INC : PRE_INC) + : (do_post ? POST_DEC : PRE_DEC), + Pmode, reg), 0)) + return 0; + + /* Record that this insn now has an implicit side effect on X. */ + REG_NOTES (insn) = alloc_EXPR_LIST (REG_INC, reg, REG_NOTES (insn)); + return 1; +} + +#endif /* AUTO_INC_DEC */ + +/* Find the place in the rtx X where REG is used as a memory address. + Return the MEM rtx that so uses it. + If PLUSCONST is nonzero, search instead for a memory address equivalent to + (plus REG (const_int PLUSCONST)). + + If such an address does not appear, return 0. + If REG appears more than once, or is used other than in such an address, + return (rtx) 1. */ + +rtx +find_use_as_address (rtx x, rtx reg, HOST_WIDE_INT plusconst) +{ + enum rtx_code code = GET_CODE (x); + const char * const fmt = GET_RTX_FORMAT (code); + int i; + rtx value = 0; + rtx tem; + + if (code == MEM && XEXP (x, 0) == reg && plusconst == 0) + return x; + + if (code == MEM && GET_CODE (XEXP (x, 0)) == PLUS + && XEXP (XEXP (x, 0), 0) == reg + && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT + && INTVAL (XEXP (XEXP (x, 0), 1)) == plusconst) + return x; + + if (code == SIGN_EXTRACT || code == ZERO_EXTRACT) + { + /* If REG occurs inside a MEM used in a bit-field reference, + that is unacceptable. */ + if (find_use_as_address (XEXP (x, 0), reg, 0) != 0) + return (rtx) (size_t) 1; + } + + if (x == reg) + return (rtx) (size_t) 1; + + for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--) + { + if (fmt[i] == 'e') + { + tem = find_use_as_address (XEXP (x, i), reg, plusconst); + if (value == 0) + value = tem; + else if (tem != 0) + return (rtx) (size_t) 1; + } + else if (fmt[i] == 'E') + { + int j; + for (j = XVECLEN (x, i) - 1; j >= 0; j--) + { + tem = find_use_as_address (XVECEXP (x, i, j), reg, plusconst); + if (value == 0) + value = tem; + else if (tem != 0) + return (rtx) (size_t) 1; + } + } + } + + return value; +} + +/* Write information about registers and basic blocks into FILE. + This is part of making a debugging dump. */ + +void +dump_regset (regset r, FILE *outf) +{ + unsigned i; + reg_set_iterator rsi; + + if (r == NULL) + { + fputs (" (nil)", outf); + return; + } + + EXECUTE_IF_SET_IN_REG_SET (r, 0, i, rsi) + { + fprintf (outf, " %d", i); + if (i < FIRST_PSEUDO_REGISTER) + fprintf (outf, " [%s]", + reg_names[i]); + } +} + +/* Print a human-readable representation of R on the standard error + stream. This function is designed to be used from within the + debugger. */ + +void +debug_regset (regset r) +{ + dump_regset (r, stderr); + putc ('\n', stderr); +} + +/* Recompute register set/reference counts immediately prior to register + allocation. + + This avoids problems with set/reference counts changing to/from values + which have special meanings to the register allocators. + + Additionally, the reference counts are the primary component used by the + register allocators to prioritize pseudos for allocation to hard regs. + More accurate reference counts generally lead to better register allocation. + + It might be worthwhile to update REG_LIVE_LENGTH, REG_BASIC_BLOCK and + possibly other information which is used by the register allocators. */ + +static unsigned int +recompute_reg_usage (void) +{ + allocate_reg_life_data (); + /* distribute_notes in combiner fails to convert some of the + REG_UNUSED notes to REG_DEAD notes. This causes CHECK_DEAD_NOTES + in sched1 to die. To solve this update the DEATH_NOTES + here. */ + update_life_info (NULL, UPDATE_LIFE_LOCAL, PROP_REG_INFO | PROP_DEATH_NOTES); + + if (dump_file) + dump_flow_info (dump_file, dump_flags); + return 0; +} + +struct tree_opt_pass pass_recompute_reg_usage = +{ + "life2", /* name */ + NULL, /* gate */ + recompute_reg_usage, /* execute */ + NULL, /* sub */ + NULL, /* next */ + 0, /* static_pass_number */ + 0, /* tv_id */ + 0, /* properties_required */ + 0, /* properties_provided */ + 0, /* properties_destroyed */ + 0, /* todo_flags_start */ + TODO_dump_func, /* todo_flags_finish */ + 'f' /* letter */ +}; + +/* Optionally removes all the REG_DEAD and REG_UNUSED notes from a set of + blocks. If BLOCKS is NULL, assume the universal set. Returns a count + of the number of registers that died. + If KILL is 1, remove old REG_DEAD / REG_UNUSED notes. If it is 0, don't. + if it is -1, remove them unless they pertain to a stack reg. */ + +int +count_or_remove_death_notes (sbitmap blocks, int kill) +{ + int count = 0; + unsigned int i = 0; + basic_block bb; + + /* This used to be a loop over all the blocks with a membership test + inside the loop. That can be amazingly expensive on a large CFG + when only a small number of bits are set in BLOCKs (for example, + the calls from the scheduler typically have very few bits set). + + For extra credit, someone should convert BLOCKS to a bitmap rather + than an sbitmap. */ + if (blocks) + { + sbitmap_iterator sbi; + + EXECUTE_IF_SET_IN_SBITMAP (blocks, 0, i, sbi) + { + basic_block bb = BASIC_BLOCK (i); + /* The bitmap may be flawed in that one of the basic blocks + may have been deleted before you get here. */ + if (bb) + count += count_or_remove_death_notes_bb (bb, kill); + }; + } + else + { + FOR_EACH_BB (bb) + { + count += count_or_remove_death_notes_bb (bb, kill); + } + } + + return count; +} + +/* Optionally removes all the REG_DEAD and REG_UNUSED notes from basic + block BB. Returns a count of the number of registers that died. */ + +static int +count_or_remove_death_notes_bb (basic_block bb, int kill) +{ + int count = 0; + rtx insn; + + for (insn = BB_HEAD (bb); ; insn = NEXT_INSN (insn)) + { + if (INSN_P (insn)) + { + rtx *pprev = ®_NOTES (insn); + rtx link = *pprev; + + while (link) + { + switch (REG_NOTE_KIND (link)) + { + case REG_DEAD: + if (REG_P (XEXP (link, 0))) + { + rtx reg = XEXP (link, 0); + int n; + + if (REGNO (reg) >= FIRST_PSEUDO_REGISTER) + n = 1; + else + n = hard_regno_nregs[REGNO (reg)][GET_MODE (reg)]; + count += n; + } + + /* Fall through. */ + + case REG_UNUSED: + if (kill > 0 + || (kill +#ifdef STACK_REGS + && (!REG_P (XEXP (link, 0)) + || !IN_RANGE (REGNO (XEXP (link, 0)), + FIRST_STACK_REG, LAST_STACK_REG)) +#endif + )) + { + rtx next = XEXP (link, 1); + free_EXPR_LIST_node (link); + *pprev = link = next; + break; + } + /* Fall through. */ + + default: + pprev = &XEXP (link, 1); + link = *pprev; + break; + } + } + } + + if (insn == BB_END (bb)) + break; + } + + return count; +} + +/* Clear LOG_LINKS fields of insns in a selected blocks or whole chain + if blocks is NULL. */ + +static void +clear_log_links (sbitmap blocks) +{ + rtx insn; + + if (!blocks) + { + for (insn = get_insns (); insn; insn = NEXT_INSN (insn)) + if (INSN_P (insn)) + free_INSN_LIST_list (&LOG_LINKS (insn)); + } + else + { + unsigned int i = 0; + sbitmap_iterator sbi; + + EXECUTE_IF_SET_IN_SBITMAP (blocks, 0, i, sbi) + { + basic_block bb = BASIC_BLOCK (i); + + for (insn = BB_HEAD (bb); insn != NEXT_INSN (BB_END (bb)); + insn = NEXT_INSN (insn)) + if (INSN_P (insn)) + free_INSN_LIST_list (&LOG_LINKS (insn)); + } + } +} + +/* Given a register bitmap, turn on the bits in a HARD_REG_SET that + correspond to the hard registers, if any, set in that map. This + could be done far more efficiently by having all sorts of special-cases + with moving single words, but probably isn't worth the trouble. */ + +void +reg_set_to_hard_reg_set (HARD_REG_SET *to, bitmap from) +{ + unsigned i; + bitmap_iterator bi; + + EXECUTE_IF_SET_IN_BITMAP (from, 0, i, bi) + { + if (i >= FIRST_PSEUDO_REGISTER) + return; + SET_HARD_REG_BIT (*to, i); + } +} + + +static bool +gate_remove_death_notes (void) +{ + return flag_profile_values; +} + +static unsigned int +rest_of_handle_remove_death_notes (void) +{ + count_or_remove_death_notes (NULL, 1); + return 0; +} + +struct tree_opt_pass pass_remove_death_notes = +{ + "ednotes", /* name */ + gate_remove_death_notes, /* gate */ + rest_of_handle_remove_death_notes, /* execute */ + NULL, /* sub */ + NULL, /* next */ + 0, /* static_pass_number */ + 0, /* tv_id */ + 0, /* properties_required */ + 0, /* properties_provided */ + 0, /* properties_destroyed */ + 0, /* todo_flags_start */ + 0, /* todo_flags_finish */ + 0 /* letter */ +}; + +/* Perform life analysis. */ +static unsigned int +rest_of_handle_life (void) +{ + regclass_init (); + + life_analysis (PROP_FINAL); + if (optimize) + cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_UPDATE_LIFE | CLEANUP_LOG_LINKS + | (flag_thread_jumps ? CLEANUP_THREADING : 0)); + + if (extra_warnings) + { + setjmp_vars_warning (DECL_INITIAL (current_function_decl)); + setjmp_args_warning (); + } + + if (optimize) + { + if (initialize_uninitialized_subregs ()) + { + /* Insns were inserted, and possibly pseudos created, so + things might look a bit different. */ + allocate_reg_life_data (); + update_life_info (NULL, UPDATE_LIFE_GLOBAL_RM_NOTES, + PROP_LOG_LINKS | PROP_REG_INFO | PROP_DEATH_NOTES); + } + } + + no_new_pseudos = 1; + return 0; +} + +struct tree_opt_pass pass_life = +{ + "life1", /* name */ + NULL, /* gate */ + rest_of_handle_life, /* execute */ + NULL, /* sub */ + NULL, /* next */ + 0, /* static_pass_number */ + TV_FLOW, /* tv_id */ + 0, /* properties_required */ + 0, /* properties_provided */ + 0, /* properties_destroyed */ + TODO_verify_flow, /* todo_flags_start */ + TODO_dump_func | + TODO_ggc_collect, /* todo_flags_finish */ + 'f' /* letter */ +}; + +static unsigned int +rest_of_handle_flow2 (void) +{ + /* If optimizing, then go ahead and split insns now. */ +#ifndef STACK_REGS + if (optimize > 0) +#endif + split_all_insns (0); + + if (flag_branch_target_load_optimize) + branch_target_load_optimize (epilogue_completed); + + if (optimize) + cleanup_cfg (CLEANUP_EXPENSIVE); + + /* On some machines, the prologue and epilogue code, or parts thereof, + can be represented as RTL. Doing so lets us schedule insns between + it and the rest of the code and also allows delayed branch + scheduling to operate in the epilogue. */ + thread_prologue_and_epilogue_insns (get_insns ()); + epilogue_completed = 1; + flow2_completed = 1; + return 0; +} + +struct tree_opt_pass pass_flow2 = +{ + "flow2", /* name */ + NULL, /* gate */ + rest_of_handle_flow2, /* execute */ + NULL, /* sub */ + NULL, /* next */ + 0, /* static_pass_number */ + TV_FLOW2, /* tv_id */ + 0, /* properties_required */ + 0, /* properties_provided */ + 0, /* properties_destroyed */ + TODO_verify_flow, /* todo_flags_start */ + TODO_dump_func | + TODO_ggc_collect, /* todo_flags_finish */ + 'w' /* letter */ +}; + |