This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[RFC] tree-ssa-ccp.c: Propagate even more ADDR_EXPRs.


Hi,

Attached is a patch to propagate even more ADDR_EXPRs.

Consider the testcase.

struct f {
  int i;
};

int
foo (void)
{
  struct f a;
  struct f *p;
  int *q;

  a.i = 1;
  p = &a;
  q = &p->i;
  return *q;
}

We hope to get the last two lines transformed into

  q = &a.i;
  return a.i;

Unfortunately, CCP misses this optimization.  The reason is that CCP
does not know how to fold &(&a)->i while evaluting q = &p->i.

The patch fixes the problem by special-casing ADDR_EXPRs in ccp_fold.

I put "RFC" because I am not sure if this is the best solution.
Should fold_addr_expr be a part of fold_unary?  Should I also handle
ARRAY_REFs?

Tested on i686-pc-linux-gnu.  Comments?

Kazu Hirata

2005-05-27  Kazu Hirata  <kazu@cs.umass.edu>

	PR tree-optimization/21636
	* tree-ssa-ccp.c (fold_hidden_indirect_ref, fold_addr_expr):
	New.
	(ccp_fold): Call fold_addr_expr.

2005-05-27  Kazu Hirata  <kazu@cs.umass.edu>

	PR tree-optimization/21636
	* gcc.dg/tree-ssa/pr21636.c: New.

Index: tree-ssa-ccp.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-ssa-ccp.c,v
retrieving revision 2.73
diff -u -d -p -r2.73 tree-ssa-ccp.c
--- tree-ssa-ccp.c	27 May 2005 16:31:20 -0000	2.73
+++ tree-ssa-ccp.c	27 May 2005 17:03:01 -0000
@@ -799,6 +799,53 @@ ccp_visit_phi_node (tree phi)
 }
 
 
+/* T is a tree expression with INDIRECT_REF hidden possibly deep
+   inside the expression.  Return a tree expression with the
+   INDIRECT_REF folded.  */
+
+static tree
+fold_hidden_indirect_ref (tree t)
+{
+  if (TREE_CODE (t) == INDIRECT_REF)
+    return fold_indirect_ref (t);
+  else if (handled_component_p (t))
+    {
+      tree op0 = TREE_OPERAND (t, 0);
+      tree folded = fold_hidden_indirect_ref (op0);
+      if (folded)
+	{
+	  tree tem = copy_node (t);
+	  TREE_OPERAND (tem, 0) = folded;
+	  return tem;
+	}
+    }
+
+  return NULL_TREE;
+}
+
+
+/* Fold EXPR, which is assumed to be an ADDR_EXPR.  */
+
+static tree
+fold_addr_expr (tree expr)
+{
+  tree base;
+
+  gcc_assert (TREE_CODE (expr) == ADDR_EXPR);
+  base = get_base_address (TREE_OPERAND (expr, 0));
+
+  if (base && TREE_CODE (base) == INDIRECT_REF)
+    {
+      tree t = fold_hidden_indirect_ref (TREE_OPERAND (expr, 0));
+      t = build1 (ADDR_EXPR, TREE_TYPE (expr), t);
+      recompute_tree_invarant_for_addr_expr (t);
+      return t;
+    }
+
+  return NULL_TREE;
+}
+
+
 /* CCP specific front-end to the non-destructive constant folding
    routines.
 
@@ -959,6 +1006,35 @@ ccp_fold (tree stmt)
 	  free (orig);
 	}
     }
+  else if (code == ADDR_EXPR
+	   && TREE_CODE (TREE_OPERAND (rhs, 0)) == COMPONENT_REF)
+    {
+      if (!ZERO_SSA_OPERANDS (stmt, SSA_OP_USE))
+	{
+	  tree *orig, var;
+	  size_t i = 0;
+	  ssa_op_iter iter;
+	  use_operand_p var_p;
+	  tree tem;
+
+	  /* Preserve the original values of every operand.  */
+	  orig = xmalloc (sizeof (tree) *  NUM_SSA_OPERANDS (stmt, SSA_OP_USE));
+	  FOR_EACH_SSA_TREE_OPERAND (var, stmt, iter, SSA_OP_USE)
+	    orig[i++] = var;
+
+	  /* Substitute operands with their values and try to fold.  */
+	  replace_uses_in (stmt, NULL, const_val);
+	  tem = fold_addr_expr (rhs);
+	  if (tem)
+	    rhs = tem;
+
+	  /* Restore operands to their original form.  */
+	  i = 0;
+	  FOR_EACH_SSA_USE_OPERAND (var_p, stmt, iter, SSA_OP_USE)
+	    SET_USE (var_p, orig[i++]);
+	  free (orig);
+	}
+    }
   else
     return rhs;
 
--- /dev/null	2005-05-20 10:05:10.845484096 -0400
+++ testsuite/gcc.dg/tree-ssa/pr21636.c	2005-05-27 13:01:28.000000000 -0400
@@ -0,0 +1,25 @@
+/* PR tree-optimization/21636
+   CCP did not fold ADDR_EXPRs like &((&a)->i) into &(a.i).  */
+
+/* { dg-do compile } */
+/* { dg-options "-O2 -fno-tree-dominator-opts -fdump-tree-ccp-details" } */
+
+struct f {
+  int i;
+};
+
+int
+foo (void)
+{
+  struct f a;
+  struct f *p;
+  int *q;
+
+  a.i = 1;
+  p = &a;
+  q = &p->i;
+  return *q;
+}
+
+/* { dg-final { scan-tree-dump-times "with .* = a.i" 1 "ccp"} } */
+/* { dg-final { cleanup-tree-dump "ccp" } } */


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]