tree-optimization/104162 - CSE of &MEM[ptr].a[i] and ptr + CST

Message ID 20220126155614.88F5413E1A@imap2.suse-dmz.suse.de
State New
Headers
Series tree-optimization/104162 - CSE of &MEM[ptr].a[i] and ptr + CST |

Commit Message

Richard Biener Jan. 26, 2022, 3:56 p.m. UTC
  This adds the capability to value-numbering of treating complex
address expressions where the offset becomes invariant as equal
to a POINTER_PLUS_EXPR.  This restores CSE that is now prevented
by early lowering of &MEM[ptr + CST] to a POINTER_PLUS_EXPR.

Unfortunately this regresses gcc.dg/asan/pr99673.c again.

Bootstrapped and tested on x86_64-unknown-linux-gnu - any
opinions?

Richard.

2022-01-26  Richard Biener  <rguenther@suse.de>

	PR tree-optimization/104162
	* tree-ssa-sccvn.cc (vn_reference_lookup): Handle
	&MEM[_1 + 5].a[i] like a POINTER_PLUS_EXPR if the offset
	becomes invariant.
	(vn_reference_insert): Likewise.

	* gcc.dg/tree-ssa/ssa-fre-99.c: New testcase.
---
 gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-99.c | 27 ++++++++++
 gcc/tree-ssa-sccvn.cc                      | 62 +++++++++++++++++++++-
 2 files changed, 88 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-99.c
  

Comments

Jeff Law Jan. 26, 2022, 4:03 p.m. UTC | #1
On 1/26/2022 8:56 AM, Richard Biener via Gcc-patches wrote:
> This adds the capability to value-numbering of treating complex
> address expressions where the offset becomes invariant as equal
> to a POINTER_PLUS_EXPR.  This restores CSE that is now prevented
> by early lowering of &MEM[ptr + CST] to a POINTER_PLUS_EXPR.
>
> Unfortunately this regresses gcc.dg/asan/pr99673.c again.
>
> Bootstrapped and tested on x86_64-unknown-linux-gnu - any
> opinions?
>
> Richard.
>
> 2022-01-26  Richard Biener  <rguenther@suse.de>
>
> 	PR tree-optimization/104162
> 	* tree-ssa-sccvn.cc (vn_reference_lookup): Handle
> 	&MEM[_1 + 5].a[i] like a POINTER_PLUS_EXPR if the offset
> 	becomes invariant.
> 	(vn_reference_insert): Likewise.
>
> 	* gcc.dg/tree-ssa/ssa-fre-99.c: New testcase.
IIRC there's a handful of old regressions this might help.  More than 
once I've been tempted to do something similar in DOM -- with this 
addition it's just one more reason we should be looking to drop DOM and 
replace it with FRE going forward.

jeff
  

Patch

diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-99.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-99.c
new file mode 100644
index 00000000000..101d0d63f7a
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-99.c
@@ -0,0 +1,27 @@ 
+/* { dg-do compile } */
+/* Disable FRE1 because that for the sake of __builtin_object_size
+   will not consider the equality but still valueize 'i', defeating
+   the purpose of the check.  */
+/* { dg-options "-O -fdump-tree-fre3 -fdisable-tree-fre1" } */
+
+struct S { int a[4]; };
+
+int i;
+int bar (struct S *p)
+{
+  char *q = (char *)p + 4;
+  i = 1;
+  int *r = &((struct S *)p)->a[i];
+  return q == (char *)r;
+}
+int baz (struct S *p)
+{
+  i = 1;
+  int *r = &((struct S *)p)->a[i];
+  char *q = (char *)p + 4;
+  return q == (char *)r;
+}
+
+/* Verify FRE can handle valueizing &p->a[i] and value-numbering it
+   equal to a POINTER_PLUS_EXPR.  */
+/* { dg-final { scan-tree-dump-times "return 1;" 2 "fre3" } } */
diff --git a/gcc/tree-ssa-sccvn.cc b/gcc/tree-ssa-sccvn.cc
index a03f0aae924..482cf372686 100644
--- a/gcc/tree-ssa-sccvn.cc
+++ b/gcc/tree-ssa-sccvn.cc
@@ -3669,6 +3669,36 @@  vn_reference_lookup (tree op, tree vuse, vn_lookup_kind kind,
   vr1.vuse = vuse_ssa_val (vuse);
   vr1.operands = operands
     = valueize_shared_reference_ops_from_ref (op, &valueized_anything);
+
+  /* Handle &MEM[ptr + 5].b[1].c as POINTER_PLUS_EXPR.  */
+  if (operands[0].opcode == ADDR_EXPR
+      && operands.last ().opcode == SSA_NAME)
+    {
+      poly_int64 off = 0;
+      vn_reference_op_t vro;
+      unsigned i;
+      for (i = 1; operands.iterate (i, &vro); ++i)
+	{
+	  if (vro->opcode == SSA_NAME)
+	    break;
+	  else if (known_eq (vro->off, -1))
+	    break;
+	  off += vro->off;
+	}
+      if (i == operands.length () - 1)
+	{
+	  gcc_assert (operands[i-1].opcode == MEM_REF);
+	  tree ops[2];
+	  ops[0] = operands[i].op0;
+	  ops[1] = wide_int_to_tree (sizetype, off);
+	  tree res = vn_nary_op_lookup_pieces (2, POINTER_PLUS_EXPR,
+					       TREE_TYPE (op), ops, NULL);
+	  if (res)
+	    return res;
+	  return NULL_TREE;
+	}
+    }
+
   vr1.type = TREE_TYPE (op);
   ao_ref op_ref;
   ao_ref_init (&op_ref, op);
@@ -3760,13 +3790,43 @@  vn_reference_insert (tree op, tree result, tree vuse, tree vdef)
   vn_reference_t vr1;
   bool tem;
 
+  vec<vn_reference_op_s> operands
+    = valueize_shared_reference_ops_from_ref (op, &tem);
+  /* Handle &MEM[ptr + 5].b[1].c as POINTER_PLUS_EXPR.  */
+  if (operands[0].opcode == ADDR_EXPR
+      && operands.last ().opcode == SSA_NAME)
+    {
+      poly_int64 off = 0;
+      vn_reference_op_t vro;
+      unsigned i;
+      for (i = 1; operands.iterate (i, &vro); ++i)
+	{
+	  if (vro->opcode == SSA_NAME)
+	    break;
+	  else if (known_eq (vro->off, -1))
+	    break;
+	  off += vro->off;
+	}
+      if (i == operands.length () - 1)
+	{
+	  gcc_assert (operands[i-1].opcode == MEM_REF);
+	  tree ops[2];
+	  ops[0] = operands[i].op0;
+	  ops[1] = wide_int_to_tree (sizetype, off);
+	  vn_nary_op_insert_pieces (2, POINTER_PLUS_EXPR,
+				    TREE_TYPE (op), ops, result,
+				    VN_INFO (result)->value_id);
+	  return;
+	}
+    }
+
   vr1 = XOBNEW (&vn_tables_obstack, vn_reference_s);
   if (TREE_CODE (result) == SSA_NAME)
     vr1->value_id = VN_INFO (result)->value_id;
   else
     vr1->value_id = get_or_alloc_constant_value_id (result);
   vr1->vuse = vuse_ssa_val (vuse);
-  vr1->operands = valueize_shared_reference_ops_from_ref (op, &tem).copy ();
+  vr1->operands = operands.copy ();
   vr1->type = TREE_TYPE (op);
   vr1->punned = false;
   ao_ref op_ref;