X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;ds=sidebyside;f=gcc%2Fflow.c;h=78c23281c6b25c4d4c5a8b9dea4ed274b11fd689;hb=b14c02a04727808dac2422180577d05d09880f22;hp=436bfd7b29bcdaaaad1394a7894894c988ac9485;hpb=4d2e5d528864f897011ae82014889955d1558c97;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/flow.c b/gcc/flow.c index 436bfd7b29b..78c23281c6b 100644 --- a/gcc/flow.c +++ b/gcc/flow.c @@ -1,6 +1,7 @@ /* Data flow analysis for GNU compiler. Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, - 1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. + 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, + Inc. This file is part of GCC. @@ -181,7 +182,7 @@ int max_regno; /* Indexed by n, giving various register information */ -varray_type reg_n_info; +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? */ @@ -353,7 +354,7 @@ first_insn_after_basic_block_note (basic_block block) FLAGS is a set of PROP_* flags to be used in accumulating flow info. */ void -life_analysis (FILE *file, int flags) +life_analysis (int flags) { #ifdef ELIMINABLE_REGS int i; @@ -436,8 +437,8 @@ life_analysis (FILE *file, int flags) if (optimize && (flags & PROP_SCAN_DEAD_STORES)) end_alias_analysis (); - if (file) - dump_flow_info (file); + if (dump_file) + dump_flow_info (dump_file, dump_flags); /* Removing dead insns should have made jumptables really dead. */ delete_dead_jumptables (); @@ -489,7 +490,7 @@ verify_wide_reg (int regno, basic_block bb) fprintf (dump_file, "Register %d died unexpectedly.\n", regno); dump_bb (bb, dump_file, 0); } - fatal_error ("internal consistency failure"); + internal_error ("internal consistency failure"); } /* A subroutine of update_life_info. Verify that there are no untoward @@ -514,7 +515,7 @@ verify_local_live_at_start (regset new_live_at_start, basic_block bb) fputs ("Old:\n", dump_file); dump_bb (bb, dump_file, 0); } - fatal_error ("internal consistency failure"); + internal_error ("internal consistency failure"); } } else @@ -536,7 +537,7 @@ verify_local_live_at_start (regset new_live_at_start, basic_block bb) "Register %d died unexpectedly.\n", i); dump_bb (bb, dump_file, 0); } - fatal_error ("internal consistency failure"); + internal_error ("internal consistency failure"); } /* Verify that the now-live register is wider than word_mode. */ verify_wide_reg (i, bb); @@ -577,7 +578,7 @@ update_life_info (sbitmap blocks, enum update_life_extent extent, ndead = 0; if ((prop_flags & PROP_REG_INFO) && !reg_deaths) - reg_deaths = xcalloc (sizeof (*reg_deaths), max_regno); + reg_deaths = XCNEWVEC (int, max_regno); timevar_push ((extent == UPDATE_LIFE_LOCAL || blocks) ? TV_LIFE_UPDATE : TV_LIFE); @@ -646,6 +647,17 @@ update_life_info (sbitmap blocks, enum update_life_extent extent, 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) @@ -658,12 +670,16 @@ update_life_info (sbitmap blocks, enum update_life_extent extent, EXECUTE_IF_SET_IN_SBITMAP (blocks, 0, i, sbi) { bb = BASIC_BLOCK (i); - - 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); + 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 @@ -810,8 +826,10 @@ delete_noop_moves (void) } } } + if (nnoops && dump_file) - fprintf (dump_file, "deleted %i noop moves", nnoops); + fprintf (dump_file, "deleted %i noop moves\n", nnoops); + return nnoops; } @@ -1022,7 +1040,7 @@ 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_call; + regset tmp, new_live_at_end, invalidated_by_eh_edge; regset registers_made_dead; bool failure_strategy_required = false; int *block_accesses; @@ -1045,21 +1063,32 @@ calculate_global_regs_live (sbitmap blocks_in, sbitmap blocks_out, int flags) tmp = ALLOC_REG_SET (®_obstack); new_live_at_end = ALLOC_REG_SET (®_obstack); - invalidated_by_call = 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_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 = xcalloc (last_basic_block, sizeof (regset)); - cond_local_sets = xcalloc (last_basic_block, sizeof (regset)); + 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 = xmalloc ((n_basic_blocks + 1) * sizeof (*queue)); + queue = XNEWVEC (basic_block, n_basic_blocks + 1); qtail = queue; qhead = qend = queue + n_basic_blocks; @@ -1084,7 +1113,7 @@ calculate_global_regs_live (sbitmap blocks_in, sbitmap blocks_out, int flags) } } - block_accesses = xcalloc (last_basic_block, sizeof (int)); + 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 @@ -1184,7 +1213,7 @@ calculate_global_regs_live (sbitmap blocks_in, sbitmap blocks_out, int flags) if (e->flags & EDGE_EH) bitmap_ior_and_compl_into (new_live_at_end, sb->il.rtl->global_live_at_start, - invalidated_by_call); + invalidated_by_eh_edge); else IOR_REG_SET (new_live_at_end, sb->il.rtl->global_live_at_start); @@ -1389,6 +1418,9 @@ calculate_global_regs_live (sbitmap blocks_in, sbitmap blocks_out, int flags) 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; @@ -1401,7 +1433,7 @@ calculate_global_regs_live (sbitmap blocks_in, sbitmap blocks_out, int flags) FREE_REG_SET (tmp); FREE_REG_SET (new_live_at_end); - FREE_REG_SET (invalidated_by_call); + FREE_REG_SET (invalidated_by_eh_edge); FREE_REG_SET (registers_made_dead); if (blocks_out) @@ -1490,7 +1522,7 @@ find_regno_partial (rtx *ptr, void *data) registers whose value is unknown, and may contain some kind of sticky bits we don't want. */ -int +static int initialize_uninitialized_subregs (void) { rtx insn; @@ -1554,8 +1586,16 @@ allocate_bb_life_data (void) FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, NULL, next_bb) { - bb->il.rtl->global_live_at_start = ALLOC_REG_SET (®_obstack); - bb->il.rtl->global_live_at_end = ALLOC_REG_SET (®_obstack); + 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); @@ -1568,7 +1608,7 @@ allocate_reg_life_data (void) max_regno = max_reg_num (); gcc_assert (!reg_deaths); - reg_deaths = xcalloc (sizeof (*reg_deaths), max_regno); + 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. */ @@ -1934,7 +1974,7 @@ 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 = xmalloc (sizeof (*pbi)); + struct propagate_block_info *pbi = XNEW (struct propagate_block_info); pbi->bb = bb; pbi->reg_live = live; @@ -1947,7 +1987,7 @@ init_propagate_block_info (basic_block bb, regset live, regset local_set, pbi->insn_num = 0; if (flags & (PROP_LOG_LINKS | PROP_AUTOINC)) - pbi->reg_next_use = xcalloc (max_reg_num (), sizeof (rtx)); + pbi->reg_next_use = XCNEWVEC (rtx, max_reg_num ()); else pbi->reg_next_use = NULL; @@ -2037,7 +2077,7 @@ init_propagate_block_info (basic_block bb, regset live, regset local_set, struct reg_cond_life_info *rcli; rtx cond; - rcli = xmalloc (sizeof (*rcli)); + rcli = XNEW (struct reg_cond_life_info); if (REGNO_REG_SET_P (bb_true->il.rtl->global_live_at_start, i)) @@ -2185,6 +2225,28 @@ propagate_block (basic_block bb, regset live, regset local_set, 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; @@ -2729,8 +2791,7 @@ mark_set_1 (struct propagate_block_info *pbi, enum rtx_code code, rtx reg, rtx c 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); + regno_last = regno_first + subreg_nregs (reg) - 1; /* Since we've just adjusted the register number ranges, make sure REG matches. Otherwise some_was_live will be clear @@ -3052,7 +3113,7 @@ mark_regno_cond_dead (struct propagate_block_info *pbi, int regno, rtx cond) /* The register was unconditionally live previously. Record the current condition as the condition under which it is dead. */ - rcli = xmalloc (sizeof (*rcli)); + rcli = XNEW (struct reg_cond_life_info); rcli->condition = cond; rcli->stores = cond; rcli->orig_condition = const0_rtx; @@ -3852,7 +3913,7 @@ mark_used_reg (struct propagate_block_info *pbi, rtx reg, { /* The register was not previously live at all. Record the condition under which it is still dead. */ - rcli = xmalloc (sizeof (*rcli)); + rcli = XNEW (struct reg_cond_life_info); rcli->condition = not_reg_cond (cond); rcli->stores = const0_rtx; rcli->orig_condition = const0_rtx; @@ -4399,7 +4460,7 @@ debug_regset (regset r) It might be worthwhile to update REG_LIVE_LENGTH, REG_BASIC_BLOCK and possibly other information which is used by the register allocators. */ -void +static unsigned int recompute_reg_usage (void) { allocate_reg_life_data (); @@ -4410,7 +4471,8 @@ recompute_reg_usage (void) update_life_info (NULL, UPDATE_LIFE_LOCAL, PROP_REG_INFO | PROP_DEATH_NOTES); if (dump_file) - dump_flow_info (dump_file); + dump_flow_info (dump_file, dump_flags); + return 0; } struct tree_opt_pass pass_recompute_reg_usage = @@ -4456,7 +4518,11 @@ count_or_remove_death_notes (sbitmap blocks, int kill) EXECUTE_IF_SET_IN_SBITMAP (blocks, 0, i, sbi) { - count += count_or_remove_death_notes_bb (BASIC_BLOCK (i), kill); + 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 @@ -4594,10 +4660,11 @@ gate_remove_death_notes (void) return flag_profile_values; } -static void +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 = @@ -4618,17 +4685,17 @@ struct tree_opt_pass pass_remove_death_notes = }; /* Perform life analysis. */ -static void +static unsigned int rest_of_handle_life (void) { regclass_init (); - life_analysis (dump_file, PROP_FINAL); + 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) + if (warn_clobbered) { setjmp_vars_warning (DECL_INITIAL (current_function_decl)); setjmp_args_warning (); @@ -4647,6 +4714,7 @@ rest_of_handle_life (void) } no_new_pseudos = 1; + return 0; } struct tree_opt_pass pass_life = @@ -4667,7 +4735,7 @@ struct tree_opt_pass pass_life = 'f' /* letter */ }; -static void +static unsigned int rest_of_handle_flow2 (void) { /* If optimizing, then go ahead and split insns now. */ @@ -4689,6 +4757,7 @@ rest_of_handle_flow2 (void) thread_prologue_and_epilogue_insns (get_insns ()); epilogue_completed = 1; flow2_completed = 1; + return 0; } struct tree_opt_pass pass_flow2 =