diff --git a/gcc/cfgcleanup.cc b/gcc/cfgcleanup.cc index 18047da7b24..a8b0139bb4d 100644 --- a/gcc/cfgcleanup.cc +++ b/gcc/cfgcleanup.cc @@ -208,7 +208,7 @@ mark_effect (rtx exp, regset nonequal) return false; case SET: - if (rtx_equal_for_cselib_p (SET_DEST (exp), SET_SRC (exp))) + if (cselib_redundant_set_p (exp)) return false; dest = SET_DEST (exp); if (dest == pc_rtx) diff --git a/gcc/cselib.cc b/gcc/cselib.cc index 6769beeeaf8..fcfd8340a4a 100644 --- a/gcc/cselib.cc +++ b/gcc/cselib.cc @@ -32,6 +32,7 @@ along with GCC; see the file COPYING3. If not see #include "dumpfile.h" #include "cselib.h" #include "function-abi.h" +#include "alias.h" /* A list of cselib_val structures. */ struct elt_list @@ -1157,6 +1158,75 @@ rtx_equal_for_cselib_1 (rtx x, rtx y, machine_mode memmode, int depth) return 1; } +/* Wrapper for rtx_equal_for_cselib_p to determine whether a SET is + truly redundant, taking into account aliasing information. */ +bool +cselib_redundant_set_p (rtx set) +{ + gcc_assert (GET_CODE (set) == SET); + rtx dest = SET_DEST (set); + if (cselib_reg_set_mode (dest) != GET_MODE (dest)) + return false; + + if (!rtx_equal_for_cselib_p (dest, SET_SRC (set))) + return false; + + while (GET_CODE (dest) == SUBREG + || GET_CODE (dest) == ZERO_EXTRACT + || GET_CODE (dest) == STRICT_LOW_PART) + dest = XEXP (dest, 0); + + if (!flag_strict_aliasing || !MEM_P (dest)) + return true; + + /* For a store we need to check that suppressing it will not change + the effective alias set. */ + rtx dest_addr = XEXP (dest, 0); + + /* Lookup the equivalents to the dest. This is more likely to succeed + than looking up the equivalents to the source (for example, when the + src is some form of constant). */ + cselib_val *src_val = cselib_lookup (SET_DEST (set), + GET_MODE (SET_DEST (set)), + 0, VOIDmode); + + if (src_val) + { + /* Walk the list of source equivalents to find the MEM accessing the same + location. */ + for (elt_loc_list *l = src_val->locs; l; l = l->next) + { + rtx src_equiv = l->loc; + while (GET_CODE (src_equiv) == SUBREG + || GET_CODE (src_equiv) == ZERO_EXTRACT + || GET_CODE (src_equiv) == STRICT_LOW_PART) + src_equiv = XEXP (src_equiv, 0); + + if (MEM_P (src_equiv)) + { + /* Match the MEMs by comparing the addresses. */ + if (rtx_equal_for_cselib_1 (dest_addr, XEXP (src_equiv, 0), + GET_MODE (dest), 0)) + return alias_sets_conflict_p (MEM_ALIAS_SET (dest), + MEM_ALIAS_SET (src_equiv)); + } + } + } + + /* We failed to find a recorded value in the cselib history, so try the + source of this set. */ + rtx src = SET_SRC (set); + while (GET_CODE (src) == SUBREG) + src = XEXP (src, 0); + + if (MEM_P (src) && rtx_equal_for_cselib_1 (dest_addr, XEXP (src, 0), + GET_MODE (dest), 0)) + return alias_sets_conflict_p (MEM_ALIAS_SET (dest), + MEM_ALIAS_SET (src)); + + return false; +} + /* Helper function for cselib_hash_rtx. Arguments like for cselib_hash_rtx, except that it hashes (plus:P x c). */ diff --git a/gcc/cselib.h b/gcc/cselib.h index 9ae65e6459e..b0905053ea5 100644 --- a/gcc/cselib.h +++ b/gcc/cselib.h @@ -83,6 +83,7 @@ extern void cselib_process_insn (rtx_insn *); extern bool fp_setter_insn (rtx_insn *); extern machine_mode cselib_reg_set_mode (const_rtx); extern int rtx_equal_for_cselib_1 (rtx, rtx, machine_mode, int); +extern bool cselib_redundant_set_p (rtx); extern int references_value_p (const_rtx, int); extern rtx cselib_expand_value_rtx (rtx, bitmap, int); typedef rtx (*cselib_expand_callback)(rtx, bitmap, int, void *); diff --git a/gcc/postreload.cc b/gcc/postreload.cc index d1c99fe6dc9..41f61d32648 100644 --- a/gcc/postreload.cc +++ b/gcc/postreload.cc @@ -43,7 +43,6 @@ along with GCC; see the file COPYING3. If not see #include "function-abi.h" #include "rtl-iter.h" -static int reload_cse_noop_set_p (rtx); static bool reload_cse_simplify (rtx_insn *, rtx); static void reload_cse_regs_1 (void); static int reload_cse_simplify_set (rtx, rtx_insn *); @@ -74,16 +73,6 @@ reload_cse_regs (rtx_insn *first ATTRIBUTE_UNUSED) } } -/* See whether a single set SET is a noop. */ -static int -reload_cse_noop_set_p (rtx set) -{ - if (cselib_reg_set_mode (SET_DEST (set)) != GET_MODE (SET_DEST (set))) - return 0; - - return rtx_equal_for_cselib_p (SET_DEST (set), SET_SRC (set)); -} - /* Try to simplify INSN. Return true if the CFG may have changed. */ static bool reload_cse_simplify (rtx_insn *insn, rtx testreg) @@ -118,7 +107,7 @@ reload_cse_simplify (rtx_insn *insn, rtx testreg) this out, so it's safer to simplify before we delete. */ count += reload_cse_simplify_set (body, insn); - if (!count && reload_cse_noop_set_p (body)) + if (!count && cselib_redundant_set_p (body)) { if (check_for_inc_dec (insn)) delete_insn_and_edges (insn); @@ -157,7 +146,7 @@ reload_cse_simplify (rtx_insn *insn, rtx testreg) rtx part = XVECEXP (body, 0, i); if (GET_CODE (part) == SET) { - if (! reload_cse_noop_set_p (part)) + if (! cselib_redundant_set_p (part)) break; if (REG_P (SET_DEST (part)) && REG_FUNCTION_VALUE_P (SET_DEST (part)))