diff options
-rw-r--r-- | gcc/ChangeLog | 29 | ||||
-rw-r--r-- | gcc/Makefile.in | 4 | ||||
-rw-r--r-- | gcc/cfgcleanup.c | 1 | ||||
-rw-r--r-- | gcc/cfgrtl.c | 17 | ||||
-rw-r--r-- | gcc/combine.c | 9 | ||||
-rw-r--r-- | gcc/dce.c | 309 | ||||
-rw-r--r-- | gcc/dce.h | 4 | ||||
-rw-r--r-- | gcc/optabs.c | 14 | ||||
-rw-r--r-- | gcc/reg-notes.def | 4 | ||||
-rw-r--r-- | gcc/reload1.c | 1 | ||||
-rw-r--r-- | gcc/rtl.h | 1 | ||||
-rw-r--r-- | gcc/see.c | 11 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 4 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/pr33644.c | 19 |
14 files changed, 250 insertions, 177 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 35ca169bce1..0e9ca3c5316 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,32 @@ +2007-10-22 Eric Botcazou <ebotcazou@libertysurf.fr> + + PR rtl-optimization/33644 + * cfgcleanup.c: Do not include dce.h. + * cfgrtl.c (delete_insn_chain_and_edges): Resurrect. + * combine.c (distribute_notes): Delete REG_LIBCALL_ID case. + * dce.c (something_changed): Delete. + (libcall_dead_p): New predicate. + (delete_unmarked_insns): Use it to delete dead libcalls. + Deal with REG_LIBCALL and REG_RETVAL notes. + (prescan_libcall_for_dce): New function. + (prescan_insns_for_dce): Use it to deal with libcalls. + (mark_reg_dependencies): Do nothing special for libcalls. + (dce_process_block): Likewise. + (fast_dce): Delete unused local variable. + (run_fast_dce): Do not return a value. + * dce.h (struct df): Delete. + (run_fast_dce): Adjust prototype. + * optabs.c (libcall_id): Delete. + (maybe_encapsulate_block): Do not emit REG_LIBCALL_ID notes. + (emit_no_conflict_block): Do not look for REG_LIBCALL_ID notes. + * reload1.c (reload): Delete REG_LIBCALL_ID case. + * rtl.h (delete_insn_chain_and_edges): Resurrect prototype. + * see.c (see_update_relevancy): Look for REG_LIBCALL and REG_RETVAL + notes instead of REG_LIBCALL_ID notes. + * reg-notes.def (LIBCALL_ID): Delete. + * Makefile.in (see.o): Add dce.h dependency. + (cfgcleanup.o): Remove dce.h dependency. + 2007-10-22 Michael Matz <matz@suse.de> PR tree-optimization/33855 diff --git a/gcc/Makefile.in b/gcc/Makefile.in index 5aee30e42ba..ad62c6ac4ba 100644 --- a/gcc/Makefile.in +++ b/gcc/Makefile.in @@ -2543,7 +2543,7 @@ web.o : web.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \ $(DF_H) $(OBSTACK_H) $(TIMEVAR_H) tree-pass.h see.o : see.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \ hard-reg-set.h $(FLAGS_H) $(BASIC_BLOCK_H) $(FUNCTION_H) output.h toplev.h \ - $(DF_H) $(OBSTACK_H) $(TIMEVAR_H) tree-pass.h $(EXPR_H) + $(DF_H) $(OBSTACK_H) $(TIMEVAR_H) tree-pass.h $(EXPR_H) dce.h gcse.o : gcse.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \ $(REGS_H) hard-reg-set.h $(FLAGS_H) $(REAL_H) insn-config.h $(GGC_H) \ $(RECOG_H) $(EXPR_H) $(BASIC_BLOCK_H) $(FUNCTION_H) output.h toplev.h \ @@ -2648,7 +2648,7 @@ cfgcleanup.o : cfgcleanup.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \ $(RTL_H) $(TIMEVAR_H) hard-reg-set.h output.h $(FLAGS_H) $(RECOG_H) \ toplev.h insn-config.h cselib.h $(TARGET_H) $(TM_P_H) $(PARAMS_H) \ $(REGS_H) $(EMIT_RTL_H) $(CFGLAYOUT_H) tree-pass.h $(CFGLOOP_H) $(EXPR_H) \ - $(DF_H) dce.h + $(DF_H) cfgloop.o : cfgloop.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) coretypes.h $(TM_H) \ $(BASIC_BLOCK_H) hard-reg-set.h $(CFGLOOP_H) $(FLAGS_H) $(FUNCTION_H) \ $(OBSTACK_H) toplev.h $(TREE_FLOW_H) $(TREE_H) pointer-set.h output.h \ diff --git a/gcc/cfgcleanup.c b/gcc/cfgcleanup.c index 5086784cd4c..7b2ec0dd76c 100644 --- a/gcc/cfgcleanup.c +++ b/gcc/cfgcleanup.c @@ -54,7 +54,6 @@ along with GCC; see the file COPYING3. If not see #include "cfgloop.h" #include "expr.h" #include "df.h" -#include "dce.h" #define FORWARDER_BLOCK_P(BB) ((BB)->flags & BB_FORWARDER_BLOCK) diff --git a/gcc/cfgrtl.c b/gcc/cfgrtl.c index cfeca97eaee..d261b03eb9b 100644 --- a/gcc/cfgrtl.c +++ b/gcc/cfgrtl.c @@ -187,6 +187,7 @@ delete_insn (rtx insn) } /* Like delete_insn but also purge dead edges from BB. */ + rtx delete_insn_and_edges (rtx insn) { @@ -231,6 +232,22 @@ delete_insn_chain (rtx start, rtx finish, bool clear_bb) start = next; } } + +/* Like delete_insn_chain but also purge dead edges from BB. */ + +void +delete_insn_chain_and_edges (rtx first, rtx last) +{ + bool purge = false; + + if (INSN_P (last) + && BLOCK_FOR_INSN (last) + && BB_END (BLOCK_FOR_INSN (last)) == last) + purge = true; + delete_insn_chain (first, last, false); + if (purge) + purge_dead_edges (BLOCK_FOR_INSN (last)); +} /* Create a new basic block consisting of the instructions between HEAD and END inclusive. This function is designed to allow fast BB construction - reuses diff --git a/gcc/combine.c b/gcc/combine.c index ca378bd1c89..dae0baf8f47 100644 --- a/gcc/combine.c +++ b/gcc/combine.c @@ -12509,15 +12509,6 @@ distribute_notes (rtx notes, rtx from_insn, rtx i3, rtx i2, rtx elim_i2, to simply delete it. */ break; - case REG_LIBCALL_ID: - /* If the insn previously containing this note still exists, - put it back where it was. Otherwise move it to the previous - insn. */ - if (!NOTE_P (from_insn)) - place = from_insn; - else - place = prev_real_insn (from_insn); - break; case REG_RETVAL: /* If the insn previously containing this note still exists, put it back where it was. Otherwise move it to the previous diff --git a/gcc/dce.c b/gcc/dce.c index e38e79732da..bf8e7a3bc0e 100644 --- a/gcc/dce.c +++ b/gcc/dce.c @@ -46,9 +46,6 @@ DEF_VEC_ALLOC_I(int,heap); we don't want to reenter it. */ static bool df_in_progress = false; -/* True if we deleted at least one instruction. */ -static bool something_changed; - /* Instructions that have been marked but whose dependencies have not yet been processed. */ static VEC(rtx,heap) *worklist; @@ -203,6 +200,62 @@ mark_nonreg_stores (rtx body, rtx insn, bool fast) } +/* Return true if the entire libcall sequence starting at INSN is dead. + NOTE is the REG_LIBCALL note attached to INSN. + + A libcall sequence is a block of insns with no side-effects, i.e. + that is only used for its return value. The terminology derives + from that of a call, but a libcall sequence need not contain one. + It is only defined by a pair of REG_LIBCALL/REG_RETVAL notes. + + From a dataflow viewpoint, a libcall sequence has the property that + no UD chain can enter it from the outside. As a consequence, if a + libcall sequence has a dead return value, it is effectively dead. + This is both enforced by CSE (cse_extended_basic_block) and relied + upon by delete_trivially_dead_insns. + + However, in practice, the return value business is a tricky one and + only checking the liveness of the last insn is not sufficient to + decide whether the whole sequence is dead (e.g. PR middle-end/19551) + so we check the liveness of every insn starting from the call. */ + +static bool +libcall_dead_p (rtx insn, rtx note) +{ + rtx last = XEXP (note, 0); + + /* Find the call insn. */ + while (insn != last && !CALL_P (insn)) + insn = NEXT_INSN (insn); + + /* If there is none, do nothing special, since ordinary death handling + can understand these insns. */ + if (!CALL_P (insn)) + return false; + + /* If this is a call that returns a value via an invisible pointer, the + dataflow engine cannot see it so it has been marked unconditionally. + Skip it unless it has been made the last insn in the libcall, for + example by the combiner, in which case we're left with no easy way + of asserting its liveness. */ + if (!single_set (insn)) + { + if (insn == last) + return false; + insn = NEXT_INSN (insn); + } + + while (insn != NEXT_INSN (last)) + { + if (INSN_P (insn) && marked_insn_p (insn)) + return false; + insn = NEXT_INSN (insn); + } + + return true; +} + + /* Delete all REG_EQUAL notes of the registers INSN writes, to prevent bad dangling REG_EQUAL notes. */ @@ -236,8 +289,7 @@ delete_corresponding_reg_eq_notes (rtx insn) } -/* Delete every instruction that hasn't been marked. Clear the insn - from DCE_DF if DF_DELETE is true. */ +/* Delete every instruction that hasn't been marked. */ static void delete_unmarked_insns (void) @@ -245,107 +297,115 @@ delete_unmarked_insns (void) basic_block bb; rtx insn, next; - something_changed = false; - FOR_EACH_BB (bb) FOR_BB_INSNS_SAFE (bb, insn, next) if (INSN_P (insn)) { + rtx note = find_reg_note (insn, REG_LIBCALL, NULL_RTX); + + /* Always delete no-op moves. */ if (noop_move_p (insn)) + ; + + /* Try to delete libcall sequences as a whole. */ + else if (note && libcall_dead_p (insn, note)) { - /* Note that this code does not handle the case where - the last insn of libcall is deleted. As it turns out - this case is excluded in the call to noop_move_p. */ - rtx note = find_reg_note (insn, REG_LIBCALL, NULL_RTX); - if (note && (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; - } + rtx last = XEXP (note, 0); + + if (!dbg_cnt (dce)) + continue; + + if (dump_file) + fprintf (dump_file, "DCE: Deleting libcall %d-%d\n", + INSN_UID (insn), INSN_UID (last)); + + next = NEXT_INSN (last); + delete_insn_chain_and_edges (insn, last); + continue; } + + /* Otherwise rely only on the DCE algorithm. */ else if (marked_insn_p (insn)) continue; - /* WARNING, this debugging can itself cause problems if the - edge of the counter causes part of a libcall to be - deleted but not all of it. */ if (!dbg_cnt (dce)) continue; if (dump_file) fprintf (dump_file, "DCE: Deleting insn %d\n", INSN_UID (insn)); - /* Before we delete the insn, we have to delete - REG_EQUAL of the destination regs of the deleted insn - to prevent dangling REG_EQUAL. */ - delete_corresponding_reg_eq_notes (insn); + /* Before we delete the insn we have to delete REG_EQUAL notes + for the destination regs in order to avoid dangling notes. */ + delete_corresponding_reg_eq_notes (insn); + /* If we're about to delete the first insn of a libcall, then + move the REG_LIBCALL note to the next real insn and update + the REG_RETVAL note. */ + if (note && (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; + } + + /* If the insn contains a REG_RETVAL note and is dead, but the + libcall as a whole is not dead, then we want to remove the + insn, but not the whole libcall sequence. However, we also + need to remove the dangling REG_LIBCALL note in order to + avoid mismatched notes. We could find a new location for + the REG_RETVAL note, but it hardly seems worth the effort. */ + note = find_reg_note (insn, REG_RETVAL, NULL_RTX); + if (note && (XEXP (note, 0) != insn)) + { + rtx libcall_note + = find_reg_note (XEXP (note, 0), REG_LIBCALL, NULL_RTX); + remove_note (XEXP (note, 0), libcall_note); + } + + /* Now delete the insn. */ delete_insn_and_edges (insn); - something_changed = true; } } -/* Mark all insns using DELETE_PARM in the libcall that contains - START_INSN. */ +/* Helper function for prescan_insns_for_dce: prescan the entire libcall + sequence starting at INSN and return the insn following the libcall. + NOTE is the REG_LIBCALL note attached to INSN. */ -static void -mark_libcall (rtx start_insn, bool delete_parm) +static rtx +prescan_libcall_for_dce (rtx insn, rtx note, bool fast) { - rtx note = find_reg_note (start_insn, REG_LIBCALL_ID, NULL_RTX); - int id = INTVAL (XEXP (note, 0)); - rtx insn; + rtx last = XEXP (note, 0); - mark_insn (start_insn, delete_parm); - insn = NEXT_INSN (start_insn); - - /* There are tales, long ago and far away, of the mystical nested - libcall. No one alive has actually seen one, but other parts of - the compiler support them so we will here. */ - for (insn = NEXT_INSN (start_insn); insn; insn = NEXT_INSN (insn)) + /* A libcall is never necessary on its own but we need to mark the stores + to a non-register destination. */ + while (insn != last && !CALL_P (insn)) { if (INSN_P (insn)) - { - /* Stay in the loop as long as we are in any libcall. */ - if ((note = find_reg_note (insn, REG_LIBCALL_ID, NULL_RTX))) - { - if (id == INTVAL (XEXP (note, 0))) - { - mark_insn (insn, delete_parm); - if (dump_file) - fprintf (dump_file, "matching forward libcall %d[%d]\n", - INSN_UID (insn), id); - } - } - else - break; - } + mark_nonreg_stores (PATTERN (insn), insn, fast); + insn = NEXT_INSN (insn); } - - for (insn = PREV_INSN (start_insn); insn; insn = PREV_INSN (insn)) + + /* If this is a call that returns a value via an invisible pointer, the + dataflow engine cannot see it so it has to be marked unconditionally. */ + if (CALL_P (insn) && !single_set (insn)) + { + mark_insn (insn, fast); + insn = NEXT_INSN (insn); + } + + while (insn != NEXT_INSN (last)) { if (INSN_P (insn)) - { - /* Stay in the loop as long as we are in any libcall. */ - if ((note = find_reg_note (insn, REG_LIBCALL_ID, NULL_RTX))) - { - if (id == INTVAL (XEXP (note, 0))) - { - mark_insn (insn, delete_parm); - if (dump_file) - fprintf (dump_file, "matching backward libcall %d[%d]\n", - INSN_UID (insn), id); - } - } - else - break; - } + mark_nonreg_stores (PATTERN (insn), insn, fast); + insn = NEXT_INSN (insn); } + + return insn; } @@ -357,23 +417,23 @@ static void prescan_insns_for_dce (bool fast) { basic_block bb; - rtx insn; + rtx insn, next; if (dump_file) fprintf (dump_file, "Finding needed instructions:\n"); FOR_EACH_BB (bb) - FOR_BB_INSNS (bb, insn) - if (INSN_P (insn)) - { - rtx note = find_reg_note (insn, REG_LIBCALL_ID, NULL_RTX); - if (note) - mark_libcall (insn, fast); - else if (deletable_insn_p (insn, fast)) - mark_nonreg_stores (PATTERN (insn), insn, fast); - else - mark_insn (insn, fast); - } + FOR_BB_INSNS_SAFE (bb, insn, next) + if (INSN_P (insn)) + { + rtx note = find_reg_note (insn, REG_LIBCALL, NULL_RTX); + if (note) + next = prescan_libcall_for_dce (insn, note, fast); + else if (deletable_insn_p (insn, fast)) + mark_nonreg_stores (PATTERN (insn), insn, fast); + else + mark_insn (insn, fast); + } if (dump_file) fprintf (dump_file, "Finished finding needed instructions:\n"); @@ -410,10 +470,6 @@ mark_reg_dependencies (rtx insn) struct df_link *defs; struct df_ref **use_rec; - /* If this is part of a libcall, mark the entire libcall. */ - if (find_reg_note (insn, REG_LIBCALL_ID, NULL_RTX)) - mark_libcall (insn, false); - for (use_rec = DF_INSN_USES (insn); *use_rec; use_rec++) { struct df_ref *use = *use_rec; @@ -588,42 +644,19 @@ dce_process_block (basic_block bb, bool redo_out) FOR_BB_INSNS_REVERSE (bb, insn) if (INSN_P (insn)) { - /* If this is a recursive call, the libcall will have already - been marked. */ - if (!marked_insn_p (insn)) - { - bool needed = false; - - /* The insn is needed if there is someone who uses the output. */ - for (def_rec = DF_INSN_DEFS (insn); *def_rec; def_rec++) - if (bitmap_bit_p (local_live, DF_REF_REGNO (*def_rec)) - || bitmap_bit_p (au, DF_REF_REGNO (*def_rec))) - { - needed = true; - break; - } + bool needed = false; + + /* The insn is needed if there is someone who uses the output. */ + for (def_rec = DF_INSN_DEFS (insn); *def_rec; def_rec++) + if (bitmap_bit_p (local_live, DF_REF_REGNO (*def_rec)) + || bitmap_bit_p (au, DF_REF_REGNO (*def_rec))) + { + needed = true; + break; + } - if (needed) - { - rtx note = find_reg_note (insn, REG_LIBCALL_ID, NULL_RTX); - - /* If we need to mark an insn in the middle of a - libcall, we need to back up to mark the entire - libcall. Given that libcalls are rare, rescanning - the block should be a reasonable solution to trying - to figure out how to back up. */ - if (note) - { - if (dump_file) - fprintf (dump_file, "needed libcall %d\n", INSN_UID (insn)); - mark_libcall (insn, true); - BITMAP_FREE (local_live); - return dce_process_block (bb, false); - } - else - mark_insn (insn, true); - } - } + if (needed) + mark_insn (insn, true); /* No matter if the instruction is needed or not, we remove any regno in the defs from the live set. */ @@ -642,6 +675,7 @@ dce_process_block (basic_block bb, bool redo_out) && (!(DF_REF_FLAGS (def) & (DF_REF_PARTIAL | DF_REF_CONDITIONAL)))) bitmap_clear_bit (local_live, DF_REF_REGNO (def)); } + #ifdef EH_USES /* Process the uses that are live into an exception handler. */ for (use_rec = df_get_artificial_uses (bb_index); *use_rec; use_rec++) @@ -676,7 +710,7 @@ fast_dce (void) bitmap redo_out = BITMAP_ALLOC (&dce_blocks_bitmap_obstack); bitmap all_blocks = BITMAP_ALLOC (&dce_blocks_bitmap_obstack); bool global_changed = true; - int i, loop_count = 0; + int i; prescan_insns_for_dce (true); @@ -686,6 +720,7 @@ fast_dce (void) while (global_changed) { global_changed = false; + for (i = 0; i < n_blocks; i++) { int index = postorder[i]; @@ -739,9 +774,9 @@ fast_dce (void) if (old_flag & DF_LR_RUN_DCE) df_set_flags (DF_LR_RUN_DCE); + prescan_insns_for_dce (true); } - loop_count++; } delete_unmarked_insns (); @@ -793,22 +828,22 @@ run_fast_df_dce (void) } -static bool -gate_fast_dce (void) +/* Run a fast DCE pass. */ + +void +run_fast_dce (void) { - return optimize > 0 && flag_dce; + if (flag_dce) + rest_of_handle_fast_dce (); } -/* Run a fast DCE pass and return true if any instructions were deleted. */ - -bool -run_fast_dce (void) +static bool +gate_fast_dce (void) { - return gate_fast_dce () && (rest_of_handle_fast_dce (), something_changed); + return optimize > 0 && flag_dce; } - struct tree_opt_pass pass_fast_rtl_dce = { "dce", /* name */ diff --git a/gcc/dce.h b/gcc/dce.h index 65faf26a48a..2635d49922b 100644 --- a/gcc/dce.h +++ b/gcc/dce.h @@ -20,9 +20,7 @@ along with GCC; see the file COPYING3. If not see #ifndef GCC_DCE_H #define GCC_DCE_H -struct df; - -extern bool run_fast_dce (void); +extern void run_fast_dce (void); extern void run_fast_df_dce (void); #endif /* GCC_DCE_H */ diff --git a/gcc/optabs.c b/gcc/optabs.c index 7f2b5642ad7..3344b2cfa66 100644 --- a/gcc/optabs.c +++ b/gcc/optabs.c @@ -99,10 +99,6 @@ static void prepare_float_lib_cmp (rtx *, rtx *, enum rtx_code *, enum machine_mode *, int *); static rtx expand_unop_direct (enum machine_mode, optab, rtx, rtx, int); -/* Current libcall id. It doesn't matter what these are, as long - as they are unique to each libcall that is emitted. */ -static HOST_WIDE_INT libcall_id = 0; - /* Debug facility for use in GDB. */ void debug_optab_libfuncs (void); @@ -3824,12 +3820,6 @@ maybe_encapsulate_block (rtx first, rtx last, rtx equiv) REG_NOTES (first)); REG_NOTES (last) = gen_rtx_INSN_LIST (REG_RETVAL, first, REG_NOTES (last)); - next = NEXT_INSN (last); - for (insn = first; insn != next; insn = NEXT_INSN (insn)) - REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_LIBCALL_ID, - GEN_INT (libcall_id), - REG_NOTES (insn)); - libcall_id++; } } } @@ -3890,8 +3880,6 @@ emit_no_conflict_block (rtx insns, rtx target, rtx op0, rtx op1, rtx equiv) remove_note (insn, note); if ((note = find_reg_note (insn, REG_RETVAL, NULL)) != NULL) remove_note (insn, note); - if ((note = find_reg_note (insn, REG_LIBCALL_ID, NULL)) != NULL) - remove_note (insn, note); data.target = target; data.first = insns; @@ -4044,8 +4032,6 @@ emit_libcall_block (rtx insns, rtx target, rtx result, rtx equiv) remove_note (insn, note); if ((note = find_reg_note (insn, REG_RETVAL, NULL)) != NULL) remove_note (insn, note); - if ((note = find_reg_note (insn, REG_LIBCALL_ID, NULL)) != NULL) - remove_note (insn, note); next = NEXT_INSN (insn); diff --git a/gcc/reg-notes.def b/gcc/reg-notes.def index 713bc2878e5..36953242e29 100644 --- a/gcc/reg-notes.def +++ b/gcc/reg-notes.def @@ -163,7 +163,3 @@ REG_NOTE (CROSSING_JUMP) /* This kind of note is generated at each to `setjmp', and similar functions that can return twice. */ REG_NOTE (SETJMP) - -/* This kind of note identifies what libcall id an instruction is part of. */ -REG_NOTE (LIBCALL_ID) - diff --git a/gcc/reload1.c b/gcc/reload1.c index 6f6e4f42124..d0fec9b29af 100644 --- a/gcc/reload1.c +++ b/gcc/reload1.c @@ -1277,7 +1277,6 @@ reload (rtx first, int global) || REG_NOTE_KIND (*pnote) == REG_UNUSED || REG_NOTE_KIND (*pnote) == REG_INC || REG_NOTE_KIND (*pnote) == REG_RETVAL - || REG_NOTE_KIND (*pnote) == REG_LIBCALL_ID || REG_NOTE_KIND (*pnote) == REG_LIBCALL) *pnote = XEXP (*pnote, 1); else diff --git a/gcc/rtl.h b/gcc/rtl.h index fbb90447c72..28ab8f60e71 100644 --- a/gcc/rtl.h +++ b/gcc/rtl.h @@ -2093,6 +2093,7 @@ extern void emit_insn_at_entry (rtx); extern void delete_insn_chain (rtx, rtx, bool); extern rtx unlink_insn_chain (rtx, rtx); extern rtx delete_insn_and_edges (rtx); +extern void delete_insn_chain_and_edges (rtx, rtx); extern rtx gen_lowpart_SUBREG (enum machine_mode, rtx); extern rtx gen_const_mem (enum machine_mode, rtx); extern rtx gen_frame_mem (enum machine_mode, rtx); diff --git a/gcc/see.c b/gcc/see.c index 0302af2d94f..8191b2d8103 100644 --- a/gcc/see.c +++ b/gcc/see.c @@ -3649,9 +3649,9 @@ see_update_defs_relevancy (rtx insn, struct df_ref *ref, The information of the u'th use is stored in use_entry[u] and the information of the d'th definition is stored in def_entry[d]. - + Currently all the uses are relevant for the optimization except for - uses that are in LIBCALL instructions. */ + uses that are in LIBCALL or RETVAL instructions. */ static void see_update_relevancy (void) @@ -3676,13 +3676,12 @@ see_update_relevancy (void) unsigned int uid = INSN_UID (insn); if (INSN_P (insn)) { - - /* If this is an insn in a libcall, do not touch the uses. */ - if (find_reg_note (insn, REG_LIBCALL_ID, NULL_RTX)) + if (find_reg_note (insn, REG_LIBCALL, NULL_RTX) + || find_reg_note (insn, REG_RETVAL, NULL_RTX)) et = NOT_RELEVANT; else et = RELEVANT_USE; - + for (use_rec = DF_INSN_UID_USES (uid); *use_rec; use_rec++) { struct df_ref *use = *use_rec; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index e7308e905c1..01f6cd5b59a 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,9 @@ 2007-10-22 Jakub Jelinek <jakub@redhat.com> + * gcc.dg/pr33644.c: New test. + +2007-10-22 Jakub Jelinek <jakub@redhat.com> + PR c++/33372 * g++.dg/gomp/pr33372-1.C: New test. * g++.dg/gomp/pr33372-2.C: New test. diff --git a/gcc/testsuite/gcc.dg/pr33644.c b/gcc/testsuite/gcc.dg/pr33644.c new file mode 100644 index 00000000000..f3f543cbe99 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr33644.c @@ -0,0 +1,19 @@ +/* PR rtl-optimization/33644 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -ftrapv" } */ + +extern char *bar (const char *); + +int *m, *b; + +void foo (void) +{ + int *mv; + int p; + char a[17]; + + p = bar (a) - a; + for (mv = m; mv < b; mv++) + if (p && ((*mv & 7) != p)) + *mv=0; +} |