]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
re PR c++/40389 (optimizer bug (possibly))
authorRichard Guenther <rguenther@suse.de>
Sat, 13 Jun 2009 22:58:13 +0000 (22:58 +0000)
committerRichard Biener <rguenth@gcc.gnu.org>
Sat, 13 Jun 2009 22:58:13 +0000 (22:58 +0000)
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.

* g++.dg/torture/pr40389.C: New testcase.

From-SVN: r148462

gcc/ChangeLog
gcc/gimple.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/torture/pr40389.C [new file with mode: 0644]
gcc/tree-ssa-structalias.c

index 0fe65b23ea38b50b126ea4a859df70dc3af729c1..264e5cc576837c2380fbc8879290025097f7467f 100644 (file)
@@ -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.
 
index d3578da28dacc3ef7d871a2fe143385e29f5b315..24727bc88735691debf46d4ad2343fdfb68336da 100644 (file)
@@ -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)
     {
index 44619103befe9fa486342f45dca67bc7121fc206..4b7d929e5b0f3f2932cbe439113d97d087f25676 100644 (file)
@@ -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 (file)
index 0000000..e3ceb12
--- /dev/null
@@ -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;
+}
+
index 827a9162234cb931363e2c6a86a033e8c2b8f7ba..7c95de4f3eceec2fcc6c82845e5560a4338d7cf9 100644 (file)
@@ -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;