X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Fpostreload-gcse.c;h=76b7b8c9ae0c54572f1138798c3f8beef5bb0390;hb=3dfef819d79660d4c38cf6ad2f9e09fa912a3f6b;hp=5558e9362b7f7934ddaade95cebc4478ad839b99;hpb=67ce556b47830dd825524e8370969b814c355216;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/postreload-gcse.c b/gcc/postreload-gcse.c index 5558e9362b7..76b7b8c9ae0 100644 --- a/gcc/postreload-gcse.c +++ b/gcc/postreload-gcse.c @@ -44,6 +44,8 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA #include "hashtab.h" #include "params.h" #include "target.h" +#include "timevar.h" +#include "tree-pass.h" /* The following code implements gcse after reload, the purpose of this pass is to cleanup redundant loads generated by reload and other @@ -222,8 +224,8 @@ alloc_mem (void) rtx insn; /* Find the largest UID and create a mapping from UIDs to CUIDs. */ - uid_cuid = xcalloc (get_max_uid () + 1, sizeof (int)); - i = 0; + uid_cuid = XCNEWVEC (int, get_max_uid () + 1); + i = 1; FOR_EACH_BB (bb) FOR_BB_INSNS (bb, insn) { @@ -669,10 +671,18 @@ record_last_set_info (rtx dest, rtx setter ATTRIBUTE_UNUSED, void *data) if (REG_P (dest)) record_last_reg_set_info (last_set_insn, REGNO (dest)); - else if (MEM_P (dest) - /* Ignore pushes, they clobber nothing. */ - && ! push_operand (dest, GET_MODE (dest))) - record_last_mem_set_info (last_set_insn); + else if (MEM_P (dest)) + { + /* Ignore pushes, they don't clobber memory. They may still + clobber the stack pointer though. Some targets do argument + pushes without adding REG_INC notes. See e.g. PR25196, + where a pushsi2 on i386 doesn't have REG_INC notes. Note + such changes here too. */ + if (! push_operand (dest, GET_MODE (dest))) + record_last_mem_set_info (last_set_insn); + else + record_last_reg_set_info (last_set_insn, STACK_POINTER_REGNUM); + } } @@ -743,6 +753,12 @@ hash_scan_set (rtx insn) can_copy_p (GET_MODE (dest)) /* Is SET_SRC something we want to gcse? */ && general_operand (src, GET_MODE (src)) +#ifdef STACK_REGS + /* Never consider insns touching the register stack. It may + create situations that reg-stack cannot handle (e.g. a stack + register live across an abnormal edge). */ + && (REGNO (dest) < FIRST_STACK_REG || REGNO (dest) > LAST_STACK_REG) +#endif /* An expression is not available if its operands are subsequently modified, including this insn. */ && oprs_unchanged_p (src, insn, true)) @@ -757,6 +773,10 @@ hash_scan_set (rtx insn) can_copy_p (GET_MODE (src)) /* Is SET_DEST something we want to gcse? */ && general_operand (dest, GET_MODE (dest)) +#ifdef STACK_REGS + /* As above for STACK_REGS. */ + && (REGNO (src) < FIRST_STACK_REG || REGNO (src) > LAST_STACK_REG) +#endif && ! (flag_float_store && FLOAT_MODE_P (GET_MODE (dest))) /* Check if the memory expression is killed after insn. */ && ! load_killed_in_block_p (INSN_CUID (insn) + 1, dest, true) @@ -1073,7 +1093,7 @@ eliminate_partially_redundant_load (basic_block bb, rtx insn, else /* Its a dead move no need to generate. */ continue; occr = (struct unoccr *) obstack_alloc (&unoccr_obstack, - sizeof (struct occr)); + sizeof (struct unoccr)); occr->insn = avail_insn; occr->pred = pred; occr->next = avail_occrs; @@ -1083,7 +1103,7 @@ eliminate_partially_redundant_load (basic_block bb, rtx insn, } else { - /* Adding a load on a critical edge will cuase a split. */ + /* Adding a load on a critical edge will cause a split. */ if (EDGE_CRITICAL_P (pred)) critical_edge_split = true; not_ok_count += pred->count; @@ -1298,7 +1318,7 @@ delete_redundant_insns (void) /* Main entry point of the GCSE after reload - clean some redundant loads due to spilling. */ -void +static void gcse_after_reload_main (rtx f ATTRIBUTE_UNUSED) { @@ -1337,3 +1357,38 @@ gcse_after_reload_main (rtx f ATTRIBUTE_UNUSED) free_mem (); } + +static bool +gate_handle_gcse2 (void) +{ + return (optimize > 0 && flag_gcse_after_reload); +} + + +static unsigned int +rest_of_handle_gcse2 (void) +{ + gcse_after_reload_main (get_insns ()); + rebuild_jump_labels (get_insns ()); + delete_trivially_dead_insns (get_insns (), max_reg_num ()); + return 0; +} + +struct tree_opt_pass pass_gcse2 = +{ + "gcse2", /* name */ + gate_handle_gcse2, /* gate */ + rest_of_handle_gcse2, /* execute */ + NULL, /* sub */ + NULL, /* next */ + 0, /* static_pass_number */ + TV_GCSE_AFTER_RELOAD, /* tv_id */ + 0, /* properties_required */ + 0, /* properties_provided */ + 0, /* properties_destroyed */ + 0, /* todo_flags_start */ + TODO_dump_func | + TODO_verify_flow | TODO_ggc_collect, /* todo_flags_finish */ + 'J' /* letter */ +}; +