]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
Backport PRs 71848, 77646, 77648, 77879, 78188
authorRichard Biener <rguenther@suse.de>
Tue, 24 Jan 2017 11:30:44 +0000 (11:30 +0000)
committerRichard Biener <rguenth@gcc.gnu.org>
Tue, 24 Jan 2017 11:30:44 +0000 (11:30 +0000)
2017-01-24  Richard Biener  <rguenther@suse.de>

Backport from mainline
2016-09-20  Richard Biener  <rguenther@suse.de>

PR tree-optimization/77646
* tree-ssa-sccvn.c (visit_reference_op_call): Always value-number
a VDEF.

* gcc.dg/torture/pr77646.c: New testcase.

2016-11-05  David Edelsohn  <dje.gcc@gmail.com>
Richard Biener  <rguenther@suse.de>

PR bootstrap/78188
PR c++/71848
* ipa-comdats.c (pass_ipa_comdats::gate): Require HAVE_COMDAT_GROUP.

* g++.dg/ipa/pr78188.C: New test.

2016-09-21  Richard Biener  <rguenther@suse.de>

PR tree-optimization/77648
* tree-ssa-structalias.c (process_constraint): Handle all DEREF
with complex RHS.
(make_transitive_closure_constraints): Adjust comment.
(make_any_offset_constraints): New function.
(handle_rhs_call): Make sure to first expand a pointer to all
subfields before transitively closing it.
(handle_const_call): Likewise.  Properly expand returned
pointers as well.
(handle_pure_call): Likewise.

* gcc.dg/torture/pr77648-1.c: New testcase.
* gcc.dg/torture/pr77648-2.c: Likewise.

2016-10-07  Richard Biener  <rguenther@suse.de>

PR tree-optimization/77879
* tree-ssa-structalias.c (handle_const_call): Properly handle
NRV return slots.
(handle_pure_call): Likewise.

From-SVN: r244864

gcc/ChangeLog
gcc/ipa-comdats.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/ipa/pr78188.C [new file with mode: 0644]
gcc/testsuite/gcc.dg/torture/pr77646.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/torture/pr77648-1.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/torture/pr77648-2.c [new file with mode: 0644]
gcc/tree-ssa-sccvn.c
gcc/tree-ssa-structalias.c

index a132be1c9b8c3eee5fe5bff6ef3a70852242b552..c6875f40bf90420b03c1507122fb4e8c369fedda 100644 (file)
@@ -1,3 +1,39 @@
+2017-01-24  Richard Biener  <rguenther@suse.de>
+
+       Backport from mainline
+       2016-09-20  Richard Biener  <rguenther@suse.de>
+
+       PR tree-optimization/77646
+       * tree-ssa-sccvn.c (visit_reference_op_call): Always value-number
+       a VDEF.
+
+       2016-11-05  David Edelsohn  <dje.gcc@gmail.com>
+               Richard Biener  <rguenther@suse.de>
+
+       PR bootstrap/78188
+       PR c++/71848
+       * ipa-comdats.c (pass_ipa_comdats::gate): Require HAVE_COMDAT_GROUP.
+
+       2016-09-21  Richard Biener  <rguenther@suse.de>
+
+       PR tree-optimization/77648
+       * tree-ssa-structalias.c (process_constraint): Handle all DEREF
+       with complex RHS.
+       (make_transitive_closure_constraints): Adjust comment.
+       (make_any_offset_constraints): New function.
+       (handle_rhs_call): Make sure to first expand a pointer to all
+       subfields before transitively closing it.
+       (handle_const_call): Likewise.  Properly expand returned
+       pointers as well.
+       (handle_pure_call): Likewise.
+
+       2016-10-07  Richard Biener  <rguenther@suse.de>
+
+       PR tree-optimization/77879
+       * tree-ssa-structalias.c (handle_const_call): Properly handle
+       NRV return slots.
+       (handle_pure_call): Likewise.
+
 2017-01-24  Richard Biener  <rguenther@suse.de>
 
        Backport from mainline
index 3e6fc1d030ea0659dd4b6e83f4a4fb7e5254f807..d4726753a94e398bc620723923dbe875dd53981c 100644 (file)
@@ -433,7 +433,7 @@ public:
 bool
 pass_ipa_comdats::gate (function *)
 {
-  return optimize;
+  return HAVE_COMDAT_GROUP && optimize;
 }
 
 } // anon namespace
index 25255d437c5e5ddd83d9e6557f0f0c22aa8e3410..6b1b2983358dc34d0f729b6f7f677bc2ee27b233 100644 (file)
@@ -1,3 +1,24 @@
+2017-01-24  Richard Biener  <rguenther@suse.de>
+
+       Backport from mainline
+       2016-09-20  Richard Biener  <rguenther@suse.de>
+
+       PR tree-optimization/77646
+       * gcc.dg/torture/pr77646.c: New testcase.
+
+       2016-11-05  David Edelsohn  <dje.gcc@gmail.com>
+               Richard Biener  <rguenther@suse.de>
+
+       PR bootstrap/78188
+       PR c++/71848
+       * g++.dg/ipa/pr78188.C: New test.       
+
+       2016-09-21  Richard Biener  <rguenther@suse.de>
+
+       PR tree-optimization/77648
+       * gcc.dg/torture/pr77648-1.c: New testcase.
+       * gcc.dg/torture/pr77648-2.c: Likewise.
+
 2017-01-24  Richard Biener  <rguenther@suse.de>
 
        Backport from mainline
diff --git a/gcc/testsuite/g++.dg/ipa/pr78188.C b/gcc/testsuite/g++.dg/ipa/pr78188.C
new file mode 100644 (file)
index 0000000..f6ee654
--- /dev/null
@@ -0,0 +1,20 @@
+// { dg-do compile }
+// { dg-options "-O2 -fno-exceptions" }
+
+int a;
+static void __attribute__((noinline)) foo () { a = 1; }
+static void __attribute__((noinline)) foo2 () { a = 2; }
+
+struct X
+{
+  virtual void bar (int i) { if (!i) { foo (); __builtin_abort (); } }
+};
+
+void baz (int i)
+{
+  if (!i)
+     { foo2 (); __builtin_abort (); }
+}
+
+X xx;
+
diff --git a/gcc/testsuite/gcc.dg/torture/pr77646.c b/gcc/testsuite/gcc.dg/torture/pr77646.c
new file mode 100644 (file)
index 0000000..1b19900
--- /dev/null
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+
+struct e {
+    int (*f)();
+    void (*g)();
+} * c;
+int a;
+void *h();
+typedef struct { struct e j; } k;
+int l() { return a; }
+const struct e b = {l};
+void m()
+{
+  k *d = h();
+  d->j = b;
+  c = (struct e *)d;
+  struct e *i = c;
+  if (i->f(c))
+    while (i->f(c))
+      i->g();
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr77648-1.c b/gcc/testsuite/gcc.dg/torture/pr77648-1.c
new file mode 100644 (file)
index 0000000..3597e2e
--- /dev/null
@@ -0,0 +1,24 @@
+/* { dg-do run } */
+
+struct S { int *p; int *q; };
+
+int **__attribute__((noinline,noclone,pure)) foo (struct S *s)
+{
+  int tem;
+  __asm__ ("" : "=g" (tem) : "g" (s->p));
+  return &s->q;
+}
+
+int main()
+{
+  struct S s;
+  int i = 1, j = 2;
+  int **x;
+  s.p = &i;
+  s.q = &j;
+  x = foo (&s);
+  **x = 7;
+  if (j != 7)
+    __builtin_abort ();
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr77648-2.c b/gcc/testsuite/gcc.dg/torture/pr77648-2.c
new file mode 100644 (file)
index 0000000..1c3734d
--- /dev/null
@@ -0,0 +1,22 @@
+/* { dg-do run } */
+
+struct S { int *p; int *q; };
+
+int **__attribute__((noinline,noclone,const)) foo (struct S *s)
+{
+  return &s->q;
+}
+
+int main()
+{
+  struct S s;
+  int i = 1, j = 2;
+  int **x;
+  s.p = &i;
+  s.q = &j;
+  x = foo (&s);
+  **x = 7;
+  if (j != 7)
+    __builtin_abort ();
+  return 0;
+}
index db554d6fea316eb7ddd2a7dd95c0c3e53ba39fe4..349bae7b0e430148374d8a612789e8a7728312d2 100644 (file)
@@ -2980,6 +2980,10 @@ visit_reference_op_call (tree lhs, gcall *stmt)
     {
       if (vnresult->result_vdef && vdef)
        changed |= set_ssa_val_to (vdef, vnresult->result_vdef);
+      else if (vdef)
+       /* If the call was discovered to be pure or const reflect
+          that as far as possible.  */
+       changed |= set_ssa_val_to (vdef, vuse_ssa_val (gimple_vuse (stmt)));
 
       if (!vnresult->result && lhs)
        vnresult->result = lhs;
index bf1b989d83732025e44ff285337eb0e17d005b46..d1eaae2f5c42aeadb3f0d2b1f9e82494e69fef88 100644 (file)
@@ -3037,7 +3037,7 @@ process_constraint (constraint_t t)
       process_constraint (new_constraint (tmplhs, rhs));
       process_constraint (new_constraint (lhs, tmplhs));
     }
-  else if (rhs.type == ADDRESSOF && lhs.type == DEREF)
+  else if ((rhs.type != SCALAR || rhs.offset != 0) && lhs.type == DEREF)
     {
       /* Split into tmp = &rhs, *lhs = tmp */
       struct constraint_expr tmplhs;
@@ -3756,7 +3756,7 @@ make_transitive_closure_constraints (varinfo_t vi)
 {
   struct constraint_expr lhs, rhs;
 
-  /* VAR = *VAR;  */
+  /* VAR = *(VAR + UNKNOWN);  */
   lhs.type = SCALAR;
   lhs.var = vi->id;
   lhs.offset = 0;
@@ -3766,6 +3766,23 @@ make_transitive_closure_constraints (varinfo_t vi)
   process_constraint (new_constraint (lhs, rhs));
 }
 
+/* Add constraints to that the solution of VI has all subvariables added.  */
+
+static void
+make_any_offset_constraints (varinfo_t vi)
+{
+  struct constraint_expr lhs, rhs;
+
+  /* VAR = VAR + UNKNOWN;  */
+  lhs.type = SCALAR;
+  lhs.var = vi->id;
+  lhs.offset = 0;
+  rhs.type = SCALAR;
+  rhs.var = vi->id;
+  rhs.offset = UNKNOWN_OFFSET;
+  process_constraint (new_constraint (lhs, rhs));
+}
+
 /* Temporary storage for fake var decls.  */
 struct obstack fake_var_decl_obstack;
 
@@ -3910,15 +3927,12 @@ handle_rhs_call (gcall *stmt, vec<ce_s> *results)
           && (flags & EAF_NOESCAPE))
        {
          varinfo_t uses = get_call_use_vi (stmt);
+         varinfo_t tem = new_var_info (NULL_TREE, "callarg");
+         make_constraint_to (tem->id, arg);
+         make_any_offset_constraints (tem);
          if (!(flags & EAF_DIRECT))
-           {
-             varinfo_t tem = new_var_info (NULL_TREE, "callarg");
-             make_constraint_to (tem->id, arg);
-             make_transitive_closure_constraints (tem);
-             make_copy_constraint (uses, tem->id);
-           }
-         else
-           make_constraint_to (uses->id, arg);
+           make_transitive_closure_constraints (tem);
+         make_copy_constraint (uses, tem->id);
          returns_uses = true;
        }
       else if (flags & EAF_NOESCAPE)
@@ -3928,6 +3942,7 @@ handle_rhs_call (gcall *stmt, vec<ce_s> *results)
          varinfo_t clobbers = get_call_clobber_vi (stmt);
          varinfo_t tem = new_var_info (NULL_TREE, "callarg");
          make_constraint_to (tem->id, arg);
+         make_any_offset_constraints (tem);
          if (!(flags & EAF_DIRECT))
            make_transitive_closure_constraints (tem);
          make_copy_constraint (uses, tem->id);
@@ -3953,7 +3968,7 @@ handle_rhs_call (gcall *stmt, vec<ce_s> *results)
   if (returns_uses)
     {
       rhsc.var = get_call_use_vi (stmt)->id;
-      rhsc.offset = 0;
+      rhsc.offset = UNKNOWN_OFFSET;
       rhsc.type = SCALAR;
       results->safe_push (rhsc);
     }
@@ -4056,30 +4071,58 @@ handle_const_call (gcall *stmt, vec<ce_s> *results)
 {
   struct constraint_expr rhsc;
   unsigned int k;
+  bool need_uses = false;
 
   /* Treat nested const functions the same as pure functions as far
      as the static chain is concerned.  */
   if (gimple_call_chain (stmt))
     {
       varinfo_t uses = get_call_use_vi (stmt);
-      make_transitive_closure_constraints (uses);
       make_constraint_to (uses->id, gimple_call_chain (stmt));
+      need_uses = true;
+    }
+
+  /* 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 (TREE_TYPE (gimple_call_lhs (stmt))))
+    {
+      varinfo_t uses = get_call_use_vi (stmt);
+      auto_vec<ce_s> tmpc;
+      get_constraint_for_address_of (gimple_call_lhs (stmt), &tmpc);
+      make_constraints_to (uses->id, tmpc);
+      need_uses = true;
+    }
+
+  if (need_uses)
+    {
+      varinfo_t uses = get_call_use_vi (stmt);
+      make_any_offset_constraints (uses);
+      make_transitive_closure_constraints (uses);
       rhsc.var = uses->id;
       rhsc.offset = 0;
       rhsc.type = SCALAR;
       results->safe_push (rhsc);
     }
 
-  /* May return arguments.  */
+  /* May return offsetted arguments.  */
+  varinfo_t tem = NULL;
+  if (gimple_call_num_args (stmt) != 0)
+    tem = new_var_info (NULL_TREE, "callarg");
   for (k = 0; k < gimple_call_num_args (stmt); ++k)
     {
       tree arg = gimple_call_arg (stmt, k);
       auto_vec<ce_s> argc;
-      unsigned i;
-      struct constraint_expr *argp;
       get_constraint_for_rhs (arg, &argc);
-      FOR_EACH_VEC_ELT (argc, i, argp)
-       results->safe_push (*argp);
+      make_constraints_to (tem->id, argc);
+    }
+  if (tem)
+    {
+      ce_s ce;
+      ce.type = SCALAR;
+      ce.var = tem->id;
+      ce.offset = UNKNOWN_OFFSET;
+      results->safe_push (ce);
     }
 
   /* May return addresses of globals.  */
@@ -4106,6 +4149,7 @@ handle_pure_call (gcall *stmt, vec<ce_s> *results)
       if (!uses)
        {
          uses = get_call_use_vi (stmt);
+         make_any_offset_constraints (uses);
          make_transitive_closure_constraints (uses);
        }
       make_constraint_to (uses->id, arg);
@@ -4117,11 +4161,28 @@ handle_pure_call (gcall *stmt, vec<ce_s> *results)
       if (!uses)
        {
          uses = get_call_use_vi (stmt);
+         make_any_offset_constraints (uses);
          make_transitive_closure_constraints (uses);
        }
       make_constraint_to (uses->id, gimple_call_chain (stmt));
     }
 
+  /* And if we applied NRV the address of the return slot.  */
+  if (gimple_call_return_slot_opt_p (stmt)
+      && gimple_call_lhs (stmt) != NULL_TREE
+      && TREE_ADDRESSABLE (TREE_TYPE (gimple_call_lhs (stmt))))
+    {
+      if (!uses)
+       {
+         uses = get_call_use_vi (stmt);
+         make_any_offset_constraints (uses);
+         make_transitive_closure_constraints (uses);
+       }
+      auto_vec<ce_s> tmpc;
+      get_constraint_for_address_of (gimple_call_lhs (stmt), &tmpc);
+      make_constraints_to (uses->id, tmpc);
+    }
+
   /* Pure functions may return call-used and nonlocal memory.  */
   if (uses)
     {