tree-ssa-structalias.c: Include tree-cfg.h.
authorRichard Biener <rguenther@suse.de>
Thu, 6 Jun 2019 07:25:19 +0000 (07:25 +0000)
committerRichard Biener <rguenth@gcc.gnu.org>
Thu, 6 Jun 2019 07:25:19 +0000 (07:25 +0000)
2019-06-06  Richard Biener  <rguenther@suse.de>

* tree-ssa-structalias.c: Include tree-cfg.h.
(make_heapvar): Do not make heap vars artificial.
(find_func_aliases_for_builtin_call): Handle stack allocation
functions.
(find_func_aliases): Delay processing of simple enough returns
in non-IPA mode.
(set_uids_in_ptset): Adjust.
(find_what_var_points_to): Likewise.
(solve_constraints): Do not dump points-to sets here.
(compute_points_to_sets): Post-process return statements,
amending the escaped solution.  Dump points-to sets afterwards.
(ipa_pta_execute): Dump points-to sets.

* gcc.dg/tree-ssa/alias-37.c: New testcase.
* gcc.dg/torture/20190604-1.c: Likewise.
* gcc.dg/tree-ssa/pta-callused.c: Adjust.

From-SVN: r271989

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/torture/20190604-1.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tree-ssa/alias-37.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tree-ssa/pta-callused.c
gcc/tree-ssa-structalias.c

index d260c5d8b780883b05d1ba5756a63405f620a767..0cc05c765571fe0484b8b37774927a06f6600b73 100644 (file)
@@ -1,3 +1,18 @@
+2019-06-06  Richard Biener  <rguenther@suse.de>
+
+       * tree-ssa-structalias.c: Include tree-cfg.h.
+       (make_heapvar): Do not make heap vars artificial.
+       (find_func_aliases_for_builtin_call): Handle stack allocation
+       functions.
+       (find_func_aliases): Delay processing of simple enough returns
+       in non-IPA mode.
+       (set_uids_in_ptset): Adjust.
+       (find_what_var_points_to): Likewise.
+       (solve_constraints): Do not dump points-to sets here.
+       (compute_points_to_sets): Post-process return statements,
+       amending the escaped solution.  Dump points-to sets afterwards.
+       (ipa_pta_execute): Dump points-to sets.
+
 2019-06-06  Martin Liska  <mliska@suse.cz>
 
        PR web/87933
index 622624618341682e266135ed0eff8d36aaf7b490..8213e33ce25ee19551cda00d2e667deb12312407 100644 (file)
@@ -1,3 +1,9 @@
+2019-06-06  Richard Biener  <rguenther@suse.de>
+
+       * gcc.dg/tree-ssa/alias-37.c: New testcase.
+       * gcc.dg/torture/20190604-1.c: Likewise.
+       * gcc.dg/tree-ssa/pta-callused.c: Adjust.
+
 2019-06-06  Claudiu Zissulescu  <claziss@synopsys.com>
 
        * gcc.target/arc/tmac-1.c: Reoreder dg-directives.
diff --git a/gcc/testsuite/gcc.dg/torture/20190604-1.c b/gcc/testsuite/gcc.dg/torture/20190604-1.c
new file mode 100644 (file)
index 0000000..884d3d5
--- /dev/null
@@ -0,0 +1,21 @@
+/* { dg-do run } */
+
+struct S { int *mem; };
+
+struct S * __attribute__((noinline,noipa))
+foo ()
+{
+  struct S *s = __builtin_malloc (sizeof (struct S));
+  s->mem = __builtin_malloc (sizeof (int));
+  s->mem[0] = 1;
+  return s;
+}
+
+int
+main()
+{
+  struct S *s = foo();
+  if (s->mem[0] != 1)
+    __builtin_abort ();
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/alias-37.c b/gcc/testsuite/gcc.dg/tree-ssa/alias-37.c
new file mode 100644 (file)
index 0000000..37eaaa6
--- /dev/null
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-dse1-details" } */
+
+int i;
+int *foo (int bogus, int n)
+{
+  int a[n];
+  a[2] = bogus; /* Should elide this store since a cannot escape.  */
+  int *p;
+  if (bogus)
+    p = &a[2];
+  else
+    p = &i;
+  return p;
+}
+
+/* { dg-final { scan-tree-dump "Deleted dead store" "dse1" } } */
index b9a57d8d13513c17abfd5c28a4a872589d53d814..cb85ec18bbcc6f6e56a631fe3e46b5cc734d23dc 100644 (file)
@@ -22,5 +22,5 @@ int bar (int b)
   return *foo (&q);
 }
 
-/* { dg-final { scan-tree-dump "CALLUSED\\(\[0-9\]+\\) = { ESCAPED NONLOCAL f.* i q }" "alias" } } */
+/* { dg-final { scan-tree-dump "CALLUSED\\(\[0-9\]+\\) = { f.* i q }" "alias" } } */
 
index d8ff2ce6dfe393205ecad7cd61fcd8f3061d91c1..07791519c6cff0a395ee8b5267f201fde2230868 100644 (file)
@@ -43,6 +43,7 @@
 #include "stringpool.h"
 #include "attribs.h"
 #include "tree-ssa.h"
+#include "tree-cfg.h"
 
 /* The idea behind this analyzer is to generate set constraints from the
    program, then solve the resulting constraints in order to generate the
@@ -3854,7 +3855,6 @@ make_heapvar (const char *name, bool add_id)
   DECL_EXTERNAL (heapvar) = 1;
 
   vi = new_var_info (heapvar, name, add_id);
-  vi->is_artificial_var = true;
   vi->is_heap_var = true;
   vi->is_unknown_size_var = true;
   vi->offset = 0;
@@ -4409,6 +4409,32 @@ find_func_aliases_for_builtin_call (struct function *fn, gcall *t)
              process_constraint (new_constraint (*lhsp, ac));
          return true;
        }
+      case BUILT_IN_STACK_SAVE:
+      case BUILT_IN_STACK_RESTORE:
+        /* Nothing interesting happens.  */
+        return true;
+      case BUILT_IN_ALLOCA:
+      case BUILT_IN_ALLOCA_WITH_ALIGN:
+      case BUILT_IN_ALLOCA_WITH_ALIGN_AND_MAX:
+       {
+         tree ptr = gimple_call_lhs (t);
+         if (ptr == NULL_TREE)
+           return true;
+         get_constraint_for (ptr, &lhsc);
+         varinfo_t vi = make_heapvar ("HEAP", true);
+         /* Alloca storage is never global.  To exempt it from escaped
+            handling make it a non-heap var.  */
+         DECL_EXTERNAL (vi->decl) = 0;
+         vi->is_global_var = 0;
+         vi->is_heap_var = 0;
+         struct constraint_expr tmpc;
+         tmpc.var = vi->id;
+         tmpc.offset = 0;
+         tmpc.type = ADDRESSOF;
+         rhsc.safe_push (tmpc);
+         process_all_all_constraints (lhsc, rhsc);
+         return true;
+       }
       case BUILT_IN_POSIX_MEMALIGN:
         {
          tree ptrptr = gimple_call_arg (t, 0);
@@ -4976,7 +5002,12 @@ find_func_aliases (struct function *fn, gimple *origt)
       greturn *return_stmt = as_a <greturn *> (t);
       fi = NULL;
       if (!in_ipa_mode
-         || !(fi = get_vi_for_tree (fn->decl)))
+         && SSA_VAR_P (gimple_return_retval (return_stmt)))
+       {
+         /* We handle simple returns by post-processing the solutions.  */
+         ;
+       }
+      if (!(fi = get_vi_for_tree (fn->decl)))
        make_escape_constraint (gimple_return_retval (return_stmt));
       else if (in_ipa_mode)
        {
@@ -6422,9 +6453,7 @@ set_uids_in_ptset (bitmap into, bitmap from, struct pt_solution *pt,
     {
       varinfo_t vi = get_varinfo (i);
 
-      /* The only artificial variables that are allowed in a may-alias
-        set are heap variables.  */
-      if (vi->is_artificial_var && !vi->is_heap_var)
+      if (vi->is_artificial_var)
        continue;
 
       if (everything_escaped
@@ -6544,9 +6573,6 @@ find_what_var_points_to (tree fndecl, varinfo_t orig_vi)
            }
          else if (vi->id == nonlocal_id)
            pt->nonlocal = 1;
-         else if (vi->is_heap_var)
-           /* We represent heapvars in the points-to set properly.  */
-           ;
          else if (vi->id == string_id)
            /* Nobody cares - STRING_CSTs are read-only entities.  */
            ;
@@ -7254,9 +7280,6 @@ solve_constraints (void)
       dump_constraint_graph (dump_file);
       fprintf (dump_file, "\n\n");
     }
-
-  if (dump_file)
-    dump_sa_points_to_info (dump_file);
 }
 
 /* Create points-to sets for the current function.  See the comments
@@ -7304,6 +7327,73 @@ compute_points_to_sets (void)
   /* From the constraints compute the points-to sets.  */
   solve_constraints ();
 
+  /* Post-process solutions for escapes through returns.  */
+  edge_iterator ei;
+  edge e;
+  FOR_EACH_EDGE (e, ei, EXIT_BLOCK_PTR_FOR_FN (cfun)->preds)
+    if (greturn *ret = safe_dyn_cast <greturn *> (last_stmt (e->src)))
+      {
+       tree val = gimple_return_retval (ret);
+       /* ???  Easy to handle simple indirections with some work.
+          Arbitrary references like foo.bar.baz are more difficult
+          (but conservatively easy enough with just looking at the base).
+          Mind to fixup find_func_aliases as well.  */
+       if (!val || !SSA_VAR_P (val))
+         continue;
+       /* returns happen last in non-IPA so they only influence
+          the ESCAPED solution and we can filter local variables.  */
+       varinfo_t escaped_vi = get_varinfo (find (escaped_id));
+       varinfo_t vi = lookup_vi_for_tree (val);
+       bitmap delta = BITMAP_ALLOC (&pta_obstack);
+       bitmap_iterator bi;
+       unsigned i;
+       for (; vi; vi = vi_next (vi))
+         {
+           varinfo_t part_vi = get_varinfo (find (vi->id));
+           EXECUTE_IF_AND_COMPL_IN_BITMAP (part_vi->solution,
+                                           escaped_vi->solution, 0, i, bi)
+             {
+               varinfo_t pointed_to_vi = get_varinfo (i);
+               if (pointed_to_vi->is_global_var
+                   /* We delay marking of heap memory as global.  */
+                   || pointed_to_vi->is_heap_var)
+                 bitmap_set_bit (delta, i);
+             }
+         }
+
+       /* Now compute the transitive closure.  */
+       bitmap_ior_into (escaped_vi->solution, delta);
+       bitmap new_delta = BITMAP_ALLOC (&pta_obstack);
+       while (!bitmap_empty_p (delta))
+         {
+           EXECUTE_IF_SET_IN_BITMAP (delta, 0, i, bi)
+             {
+               varinfo_t pointed_to_vi = get_varinfo (i);
+               pointed_to_vi = get_varinfo (find (pointed_to_vi->id));
+               unsigned j;
+               bitmap_iterator bi2;
+               EXECUTE_IF_AND_COMPL_IN_BITMAP (pointed_to_vi->solution,
+                                               escaped_vi->solution,
+                                               0, j, bi2)
+                 {
+                   varinfo_t pointed_to_vi2 = get_varinfo (j);
+                   if (pointed_to_vi2->is_global_var
+                       /* We delay marking of heap memory as global.  */
+                       || pointed_to_vi2->is_heap_var)
+                     bitmap_set_bit (new_delta, j);
+                 }
+             }
+           bitmap_ior_into (escaped_vi->solution, new_delta);
+           bitmap_clear (delta);
+           std::swap (delta, new_delta);
+         }
+       BITMAP_FREE (delta);
+       BITMAP_FREE (new_delta);
+      }
+
+  if (dump_file)
+    dump_sa_points_to_info (dump_file);
+
   /* Compute the points-to set for ESCAPED used for call-clobber analysis.  */
   cfun->gimple_df->escaped = find_what_var_points_to (cfun->decl,
                                                      get_varinfo (escaped_id));
@@ -8109,6 +8199,9 @@ ipa_pta_execute (void)
   /* From the constraints compute the points-to sets.  */
   solve_constraints ();
 
+  if (dump_file)
+    dump_sa_points_to_info (dump_file);
+
   /* Now post-process solutions to handle locals from different
      runtime instantiations coming in through recursive invocations.  */
   unsigned shadow_var_cnt = 0;