diff options
Diffstat (limited to 'gcc/cse.c')
-rw-r--r-- | gcc/cse.c | 28 |
1 files changed, 27 insertions, 1 deletions
@@ -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 @@ -5495,6 +5511,16 @@ cse_insn (rtx_insn *insn) 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; + 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 |