aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog13
-rw-r--r--gcc/gimple.c5
-rw-r--r--gcc/testsuite/ChangeLog7
-rw-r--r--gcc/testsuite/g++.dg/torture/pr40389.C84
-rw-r--r--gcc/tree-ssa-structalias.c57
5 files changed, 147 insertions, 19 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 0fe65b2..264e5cc 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,14 @@
+2009-06-14 Richard Guenther <rguenther@suse.de>
+
+ PR middle-end/40389
+ * gimple.c (walk_stmt_load_store_addr_ops): The LHS of a call
+ has its address taken if NRV was applied and it is addressable.
+ * tree-ssa-structalias.c (get_constraint_for_address_of): New
+ function split out from ...
+ (get_constraint_for_1): ... here.
+ (handle_rhs_call): Use it to mark the return slot escaped if
+ it is addressable and NRV was applied.
+
2009-06-13 Aldy Hernandez <aldyh@redhat.com>
* config/rs6000/rs6000-protos.h (altivec_resolve_overloaded_builtin):
@@ -8,7 +19,7 @@
2009-06-13 Richard Guenther <rguenther@suse.de>
- PR tree-optimization/40389
+ PR tree-optimization/40421
* tree-predcom.c (should_unroll_loop_p): Remove.
(tree_predictive_commoning_loop): Use can_unroll_loop_p.
diff --git a/gcc/gimple.c b/gcc/gimple.c
index d3578da..24727bc 100644
--- a/gcc/gimple.c
+++ b/gcc/gimple.c
@@ -3264,6 +3264,11 @@ walk_stmt_load_store_addr_ops (gimple stmt, void *data,
&& TREE_CODE (gimple_call_chain (stmt)) == ADDR_EXPR)
ret |= visit_addr (stmt, TREE_OPERAND (gimple_call_chain (stmt), 0),
data);
+ if (visit_addr
+ && gimple_call_return_slot_opt_p (stmt)
+ && gimple_call_lhs (stmt) != NULL_TREE
+ && TREE_ADDRESSABLE (gimple_call_lhs (stmt)))
+ ret |= visit_addr (stmt, gimple_call_lhs (stmt), data);
}
else if (gimple_code (stmt) == GIMPLE_ASM)
{
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 4461910..4b7d929 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,6 +1,11 @@
+2009-06-14 Richard Guenther <rguenther@suse.de>
+
+ PR middle-end/40389
+ * g++.dg/torture/pr40389.C: New testcase.
+
2009-06-13 Richard Guenther <rguenther@suse.de>
- PR tree-optimization/40389
+ PR tree-optimization/40421
* gfortran.fortran-torture/compile/pr40421.f: New testcase.
2009-06-12 Aldy Hernandez <aldyh@redhat.com>
diff --git a/gcc/testsuite/g++.dg/torture/pr40389.C b/gcc/testsuite/g++.dg/torture/pr40389.C
new file mode 100644
index 0000000..e3ceb12
--- /dev/null
+++ b/gcc/testsuite/g++.dg/torture/pr40389.C
@@ -0,0 +1,84 @@
+/* { dg-do run } */
+
+template <typename V> struct S
+{
+ V *f, *l;
+ __attribute__ ((noinline)) S (void) { f = 0, l = 0; }
+ void foo (V *x)
+ {
+ if (x->p != 0)
+ x->p->n = x->n;
+ else
+ f = x->n;
+ if (x->n != 0)
+ x->n->p = x->p;
+ else
+ l = x->p;
+ }
+ __attribute__ ((noinline)) void bar (V *x)
+ {
+ x->n = 0;
+ x->p = l;
+ if (l != 0)
+ l->n = x;
+ else
+ f = x;
+ l = x;
+ }
+};
+
+struct H;
+
+struct A
+{
+ S <H> k;
+};
+
+struct H
+{
+ A *a;
+ H *p, *n;
+ __attribute__ ((noinline)) H (void) { p = 0, n = 0, a = 0; }
+ __attribute__ ((noinline)) H (A *b) : a (b)
+ {
+ p = 0;
+ n = 0;
+ if (a != 0)
+ a->k.bar (this);
+ }
+ __attribute__ ((noinline)) H (const H &h) : a (h.a)
+ {
+ p = 0;
+ n = 0;
+ if (a != 0)
+ a->k.bar (this);
+ }
+ ~H (void) { if (a != 0) a->k.foo (this); }
+ H &operator= (const H &o)
+ {
+ if (a != 0 || &o == this)
+ __builtin_abort ();
+ a = o.a;
+ if (a != 0)
+ a->k.bar (this);
+ return *this;
+ }
+};
+
+__attribute__ ((noinline))
+H baz (void)
+{
+ return H (new A);
+}
+
+H g;
+
+int
+main (void)
+{
+ g = baz ();
+ if (g.a->k.f != &g)
+ __builtin_abort ();
+ return 0;
+}
+
diff --git a/gcc/tree-ssa-structalias.c b/gcc/tree-ssa-structalias.c
index 827a916..7c95de4 100644
--- a/gcc/tree-ssa-structalias.c
+++ b/gcc/tree-ssa-structalias.c
@@ -3080,6 +3080,28 @@ do_deref (VEC (ce_s, heap) **constraints)
}
}
+static void get_constraint_for_1 (tree, VEC (ce_s, heap) **, bool);
+
+/* Given a tree T, return the constraint expression for taking the
+ address of it. */
+
+static void
+get_constraint_for_address_of (tree t, VEC (ce_s, heap) **results)
+{
+ struct constraint_expr *c;
+ unsigned int i;
+
+ get_constraint_for_1 (t, results, true);
+
+ for (i = 0; VEC_iterate (ce_s, *results, i, c); i++)
+ {
+ if (c->type == DEREF)
+ c->type = SCALAR;
+ else
+ c->type = ADDRESSOF;
+ }
+}
+
/* Given a tree T, return the constraint expression for it. */
static void
@@ -3131,23 +3153,8 @@ get_constraint_for_1 (tree t, VEC (ce_s, heap) **results, bool address_p)
switch (TREE_CODE (t))
{
case ADDR_EXPR:
- {
- struct constraint_expr *c;
- unsigned int i;
- tree exp = TREE_OPERAND (t, 0);
-
- get_constraint_for_1 (exp, results, true);
-
- for (i = 0; VEC_iterate (ce_s, *results, i, c); i++)
- {
- if (c->type == DEREF)
- c->type = SCALAR;
- else
- c->type = ADDRESSOF;
- }
- return;
- }
- break;
+ get_constraint_for_address_of (TREE_OPERAND (t, 0), results);
+ return;
default:;
}
break;
@@ -3333,6 +3340,22 @@ handle_rhs_call (gimple stmt, VEC(ce_s, heap) **results)
if (gimple_call_chain (stmt))
make_escape_constraint (gimple_call_chain (stmt));
+ /* And if we applied NRV the address of the return slot escapes as well. */
+ if (gimple_call_return_slot_opt_p (stmt)
+ && gimple_call_lhs (stmt) != NULL_TREE
+ && TREE_ADDRESSABLE (gimple_call_lhs (stmt)))
+ {
+ VEC(ce_s, heap) *tmpc = NULL;
+ struct constraint_expr lhsc, *c;
+ get_constraint_for_address_of (gimple_call_lhs (stmt), &tmpc);
+ lhsc.var = escaped_id;
+ lhsc.offset = 0;
+ lhsc.type = SCALAR;
+ for (i = 0; VEC_iterate (ce_s, tmpc, i, c); ++i)
+ process_constraint (new_constraint (lhsc, *c));
+ VEC_free(ce_s, heap, tmpc);
+ }
+
/* Regular functions return nonlocal memory. */
rhsc.var = nonlocal_id;
rhsc.offset = 0;