Improve address CSE

Message ID alpine.LSU.2.20.1808011401000.16707@zhemvz.fhfr.qr
State New
Headers show
Series
  • Improve address CSE
Related show

Commit Message

Richard Biener Aug. 1, 2018, 12:02 p.m.
This removes an odd CSE failure of invariant addresses vs. non-invariant
ones.

Bootstrapped and tested on x86_64-unknown-linux-gnu, applied to trunk.

Richard.

2018-08-01  Richard Biener  <rguenther@suse.de>

	* tree-ssa-sccvn.c (visit_phi): Compare invariant addresses
	as base and offset.

	* gcc.dg/tree-ssa/ssa-fre-68.c: New testcase.

Patch

Index: gcc/tree-ssa-sccvn.c
===================================================================
--- gcc/tree-ssa-sccvn.c	(revision 263190)
+++ gcc/tree-ssa-sccvn.c	(working copy)
@@ -3941,6 +3941,8 @@  static bool
 visit_phi (gimple *phi)
 {
   tree result, sameval = VN_TOP, seen_undef = NULL_TREE;
+  tree sameval_base = NULL_TREE;
+  poly_int64 soff, doff;
   unsigned n_executable = 0;
   bool allsame = true;
   edge_iterator ei;
@@ -3971,6 +3973,23 @@  visit_phi (gimple *phi)
 	  sameval = def;
 	else if (!expressions_equal_p (def, sameval))
 	  {
+	    /* We know we're arriving only with invariant addresses here,
+	       try harder comparing them.  We can do some caching here
+	       which we cannot do in expressions_equal_p.  */
+	    if (TREE_CODE (def) == ADDR_EXPR
+		&& TREE_CODE (sameval) == ADDR_EXPR
+		&& sameval_base != (void *)-1)
+	      {
+		if (!sameval_base)
+		  sameval_base = get_addr_base_and_unit_offset
+				   (TREE_OPERAND (sameval, 0), &soff);
+		if (!sameval_base)
+		  sameval_base = (tree)(void *)-1;
+		else if ((get_addr_base_and_unit_offset
+			    (TREE_OPERAND (def, 0), &doff) == sameval_base)
+			 && known_eq (soff, doff))
+		  continue;
+	      }
 	    allsame = false;
 	    break;
 	  }
Index: gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-68.c
===================================================================
--- gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-68.c	(nonexistent)
+++ gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-68.c	(working copy)
@@ -0,0 +1,28 @@ 
+/* { dg-do compile } */
+/* { dg-options "-O -fdump-tree-fre1" } */
+
+struct S { char a[3]; char b[5]; } s = { "abc", "defg" };
+
+__SIZE_TYPE__
+foo (struct S s, int a, int b)
+{
+  char *p = (char *) &s.a[0];
+  if (a)
+    p = (char *) &s.a;
+  else if (b)
+    p = (char *) &s;
+  return __builtin_strlen (p);
+}
+
+__SIZE_TYPE__
+bar (int a, int b)
+{
+  char *p = (char *) &s.a[0];
+  if (a)
+    p = (char *) &s.a;
+  else if (b)
+    p = (char *) &s;
+  return __builtin_strlen (p);
+}
+
+/* { dg-final { scan-tree-dump-times "strlen \\\(&s" 2 "fre1" } } */