aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/alias.cc14
-rw-r--r--gcc/alias.h1
-rw-r--r--gcc/cfgcleanup.cc2
-rw-r--r--gcc/cselib.cc70
-rw-r--r--gcc/cselib.h1
-rw-r--r--gcc/dse.cc7
-rw-r--r--gcc/postreload.cc15
7 files changed, 90 insertions, 20 deletions
diff --git a/gcc/alias.cc b/gcc/alias.cc
index 8c08452..d54feb1 100644
--- a/gcc/alias.cc
+++ b/gcc/alias.cc
@@ -389,6 +389,20 @@ refs_same_for_tbaa_p (tree earlier, tree later)
|| alias_set_subset_of (later_base_set, earlier_base_set));
}
+/* Similar to refs_same_for_tbaa_p() but for use on MEM rtxs. */
+bool
+mems_same_for_tbaa_p (rtx earlier, rtx later)
+{
+ gcc_assert (MEM_P (earlier));
+ gcc_assert (MEM_P (later));
+
+ return ((MEM_ALIAS_SET (earlier) == MEM_ALIAS_SET (later)
+ || alias_set_subset_of (MEM_ALIAS_SET (later),
+ MEM_ALIAS_SET (earlier)))
+ && (!MEM_EXPR (earlier)
+ || refs_same_for_tbaa_p (MEM_EXPR (earlier), MEM_EXPR (later))));
+}
+
/* Returns a pointer to the alias set entry for ALIAS_SET, if there is
such an entry, or NULL otherwise. */
diff --git a/gcc/alias.h b/gcc/alias.h
index b259651..ee3db46 100644
--- a/gcc/alias.h
+++ b/gcc/alias.h
@@ -40,6 +40,7 @@ tree reference_alias_ptr_type_1 (tree *);
bool alias_ptr_types_compatible_p (tree, tree);
int compare_base_decls (tree, tree);
bool refs_same_for_tbaa_p (tree, tree);
+bool mems_same_for_tbaa_p (rtx, rtx);
/* This alias set can be used to force a memory to conflict with all
other memories, creating a barrier across which no memory reference
diff --git a/gcc/cfgcleanup.cc b/gcc/cfgcleanup.cc
index 18047da..a8b0139 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 6769bee..6a56097 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 original dest (rather than just the
+ MEM). */
+ 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. We can
+ only remove the later store if the earlier aliases at
+ least all the accesses of the later one. */
+ if (rtx_equal_for_cselib_1 (dest_addr, XEXP (src_equiv, 0),
+ GET_MODE (dest), 0))
+ return mems_same_for_tbaa_p (src_equiv, dest);
+ }
+ }
+ }
+
+ /* We failed to find a recorded value in the cselib history, so try
+ the source of this set; this catches cases such as *p = *q when p
+ and q have the same value. */
+ 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 mems_same_for_tbaa_p (src, dest);
+
+ 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 9ae65e6..b090505 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/dse.cc b/gcc/dse.cc
index 90a4c1f..0f7b0fb 100644
--- a/gcc/dse.cc
+++ b/gcc/dse.cc
@@ -1570,12 +1570,7 @@ record_store (rtx body, bb_info_t bb_info)
width)
/* We can only remove the later store if the earlier aliases
at least all accesses the later one. */
- && ((MEM_ALIAS_SET (mem) == MEM_ALIAS_SET (s_info->mem)
- || alias_set_subset_of (MEM_ALIAS_SET (mem),
- MEM_ALIAS_SET (s_info->mem)))
- && (!MEM_EXPR (s_info->mem)
- || refs_same_for_tbaa_p (MEM_EXPR (s_info->mem),
- MEM_EXPR (mem)))))
+ && mems_same_for_tbaa_p (s_info->mem, mem))
{
if (GET_MODE (mem) == BLKmode)
{
diff --git a/gcc/postreload.cc b/gcc/postreload.cc
index d1c99fe..41f61d3 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)))