public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc r11-10232] cselib: add function to check if SET is redundant [PR106187]
@ 2022-09-02 14:07 Richard Earnshaw
  0 siblings, 0 replies; only message in thread
From: Richard Earnshaw @ 2022-09-02 14:07 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:50982aa1145fbdb315162349833412639aa8bc4c

commit r11-10232-g50982aa1145fbdb315162349833412639aa8bc4c
Author: Richard Earnshaw <rearnsha@arm.com>
Date:   Wed Aug 3 10:01:51 2022 +0100

    cselib: add function to check if SET is redundant [PR106187]
    
    A SET operation that writes memory may have the same value as an
    earlier store but if the alias sets of the new and earlier store do
    not conflict then the set is not truly redundant.  This can happen,
    for example, if objects of different types share a stack slot.
    
    To fix this we define a new function in cselib that first checks for
    equality and if that is successful then finds the earlier store in the
    value history and checks the alias sets.
    
    The routine is used in two places elsewhere in the compiler:
    cfgcleanup and postreload.
    
    gcc/ChangeLog:
    
            PR rtl-optimization/106187
            * alias.h (mems_same_for_tbaa_p): Declare.
            * alias.c (mems_same_for_tbaa_p): New function.
            * dse.c (record_store): Use it instead of open-coding
            alias check.
            * cselib.h (cselib_redundant_set_p): Declare.
            * cselib.c: Include alias.h
            (cselib_redundant_set_p): New function.
            * cfgcleanup.c: (mark_effect): Use cselib_redundant_set_p instead
            of rtx_equal_for_cselib_p.
            * postreload.c (reload_cse_simplify): Use cselib_redundant_set_p.
            (reload_cse_noop_set_p): Delete.
    
    (cherry picked from commit 64ce76d940501cb04d14a0d36752b4f93473531c)

Diff:
---
 gcc/alias.c      | 14 ++++++++++++
 gcc/alias.h      |  1 +
 gcc/cfgcleanup.c |  2 +-
 gcc/cselib.c     | 70 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 gcc/cselib.h     |  1 +
 gcc/dse.c        |  7 +-----
 gcc/postreload.c | 15 ++----------
 7 files changed, 90 insertions(+), 20 deletions(-)

diff --git a/gcc/alias.c b/gcc/alias.c
index 69e1eb89ac6..ba4aa4dc8d9 100644
--- a/gcc/alias.c
+++ b/gcc/alias.c
@@ -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 f427698a8e1..f38da75e040 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.c b/gcc/cfgcleanup.c
index 4086b647585..06586ddf083 100644
--- a/gcc/cfgcleanup.c
+++ b/gcc/cfgcleanup.c
@@ -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.c b/gcc/cselib.c
index 779874eeb2d..342c3cfdda8 100644
--- a/gcc/cselib.c
+++ b/gcc/cselib.c
@@ -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 af112fd0985..14478eec238 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.c b/gcc/dse.c
index b634429449c..dd99756d151 100644
--- a/gcc/dse.c
+++ b/gcc/dse.c
@@ -1562,12 +1562,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.c b/gcc/postreload.c
index 60a622dbaf3..ed5f54aaeb0 100644
--- a/gcc/postreload.c
+++ b/gcc/postreload.c
@@ -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)))

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2022-09-02 14:07 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-09-02 14:07 [gcc r11-10232] cselib: add function to check if SET is redundant [PR106187] Richard Earnshaw

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).