diff options
Diffstat (limited to 'gcc/cse.c')
-rw-r--r-- | gcc/cse.c | 54 |
1 files changed, 42 insertions, 12 deletions
diff --git a/gcc/cse.c b/gcc/cse.c index 2665d9a2733..bce4fb0262e 100644 --- a/gcc/cse.c +++ b/gcc/cse.c @@ -4575,6 +4575,7 @@ cse_insn (rtx_insn *insn) for (i = 0; i < n_sets; i++) { bool repeat = false; + bool mem_noop_insn = false; rtx src, dest; rtx src_folded; struct table_elt *elt = 0, *p; @@ -5166,7 +5167,7 @@ cse_insn (rtx_insn *insn) } /* Avoid creation of overlapping memory moves. */ - if (MEM_P (trial) && MEM_P (SET_DEST (sets[i].rtl))) + if (MEM_P (trial) && MEM_P (dest) && !rtx_equal_p (trial, dest)) { rtx src, dest; @@ -5277,6 +5278,21 @@ cse_insn (rtx_insn *insn) break; } + /* Similarly, lots of targets don't allow no-op + (set (mem x) (mem x)) moves. */ + else if (n_sets == 1 + && MEM_P (trial) + && MEM_P (dest) + && rtx_equal_p (trial, dest) + && !side_effects_p (dest) + && (cfun->can_delete_dead_exceptions + || insn_nothrow_p (insn))) + { + SET_SRC (sets[i].rtl) = trial; + mem_noop_insn = true; + break; + } + /* Reject certain invalid forms of CONST that we create. */ else if (CONSTANT_P (trial) && GET_CODE (trial) == CONST @@ -5489,12 +5505,22 @@ cse_insn (rtx_insn *insn) else if (n_sets == 1 && dest == pc_rtx && src == pc_rtx) { /* One less use of the label this insn used to jump to. */ - delete_insn_and_edges (insn); + cse_cfg_altered |= delete_insn_and_edges (insn); cse_jumps_altered = true; /* No more processing for this set. */ sets[i].rtl = 0; } + /* Similarly for no-op MEM moves. */ + else if (mem_noop_insn) + { + if (cfun->can_throw_non_call_exceptions && can_throw_internal (insn)) + cse_cfg_altered = true; + cse_cfg_altered |= delete_insn_and_edges (insn); + /* No more processing for this set. */ + sets[i].rtl = 0; + } + /* If this SET is now setting PC to a label, we know it used to be a conditional or computed branch. */ else if (dest == pc_rtx && GET_CODE (src) == LABEL_REF @@ -5525,7 +5551,7 @@ cse_insn (rtx_insn *insn) REG_NOTES (new_rtx) = note; } - delete_insn_and_edges (insn); + cse_cfg_altered |= delete_insn_and_edges (insn); insn = new_rtx; } else @@ -6643,6 +6669,10 @@ cse_main (rtx_insn *f ATTRIBUTE_UNUSED, int nregs) int *rc_order = XNEWVEC (int, last_basic_block_for_fn (cfun)); int i, n_blocks; + /* CSE doesn't use dominane info but can invalidate it in different ways. + For simplicity free dominance info here. */ + free_dominance_info (CDI_DOMINATORS); + df_set_flags (DF_LR_RUN_DCE); df_note_add_problem (); df_analyze (); @@ -7105,7 +7135,7 @@ delete_trivially_dead_insns (rtx_insn *insns, int nreg) count_reg_usage (insn, counts, NULL_RTX, -1); ndead++; } - delete_insn_and_edges (insn); + cse_cfg_altered |= delete_insn_and_edges (insn); } } @@ -7401,7 +7431,7 @@ cse_cc_succs (basic_block bb, basic_block orig_bb, rtx cc_reg, rtx cc_src, newreg); } - delete_insn_and_edges (insns[i]); + cse_cfg_altered |= delete_insn_and_edges (insns[i]); } return mode; @@ -7536,11 +7566,11 @@ rest_of_handle_cse (void) { timevar_push (TV_JUMP); rebuild_jump_labels (get_insns ()); - cleanup_cfg (CLEANUP_CFG_CHANGED); + cse_cfg_altered |= cleanup_cfg (CLEANUP_CFG_CHANGED); timevar_pop (TV_JUMP); } else if (tem == 1 || optimize > 1) - cleanup_cfg (0); + cse_cfg_altered |= cleanup_cfg (0); return 0; } @@ -7605,11 +7635,11 @@ rest_of_handle_cse2 (void) { timevar_push (TV_JUMP); rebuild_jump_labels (get_insns ()); - cleanup_cfg (CLEANUP_CFG_CHANGED); + cse_cfg_altered |= cleanup_cfg (CLEANUP_CFG_CHANGED); timevar_pop (TV_JUMP); } else if (tem == 1) - cleanup_cfg (0); + cse_cfg_altered |= cleanup_cfg (0); cse_not_expected = 1; return 0; @@ -7669,7 +7699,7 @@ rest_of_handle_cse_after_global_opts (void) rebuild_jump_labels (get_insns ()); tem = cse_main (get_insns (), max_reg_num ()); - purge_all_dead_edges (); + cse_cfg_altered |= purge_all_dead_edges (); delete_trivially_dead_insns (get_insns (), max_reg_num ()); cse_not_expected = !flag_rerun_cse_after_loop; @@ -7679,11 +7709,11 @@ rest_of_handle_cse_after_global_opts (void) { timevar_push (TV_JUMP); rebuild_jump_labels (get_insns ()); - cleanup_cfg (CLEANUP_CFG_CHANGED); + cse_cfg_altered |= cleanup_cfg (CLEANUP_CFG_CHANGED); timevar_pop (TV_JUMP); } else if (tem == 1) - cleanup_cfg (0); + cse_cfg_altered |= cleanup_cfg (0); flag_cse_follow_jumps = save_cfj; return 0; |