This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[RFC] tree-ssa-ccp.c: Propagate even more ADDR_EXPRs.
- From: Kazu Hirata <kazu at cs dot umass dot edu>
- To: gcc-patches at gcc dot gnu dot org
- Date: Fri, 27 May 2005 16:42:21 -0400 (EDT)
- Subject: [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" } } */