]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
re PR tree-optimization/39207 (Strict aliasing warnings in libstdc++ headers)
authorRichard Guenther <rguenther@suse.de>
Thu, 19 Feb 2009 10:12:25 +0000 (10:12 +0000)
committerRichard Biener <rguenth@gcc.gnu.org>
Thu, 19 Feb 2009 10:12:25 +0000 (10:12 +0000)
2009-02-19  Richard Guenther  <rguenther@suse.de>

PR tree-optimization/39207
PR tree-optimization/39074
* tree-ssa-structalias.c (storedanything_id, var_storedanything,
storedanything_tree): New.
(do_ds_constraint): Simplify ANYTHING shortcutting.  Update
the STOREDANYTHING solution if the lhs solution contains
ANYTHING.
(build_succ_graph): Add edges from STOREDANYTHING to all
non-direct nodes.
(init_base_vars): Initialize STOREDANYTHING.
(compute_points_to_sets): Free substitution info after
building the succ graph.
(ipa_pta_execute): Likewise.

* gcc.dg/torture/pr39074.c: New testcase.
* gcc.dg/torture/pr39074-2.c: Likewise.
* gcc.dg/torture/pr39074-3.c: Likewise.

* tree-ssa-structalias.c (struct variable_info): Add may_have_pointers
field.
(do_ds_constraint): Do not add to special var or non-pointer
field solutions.
(type_could_have_pointers): Split out from ...
(could_have_pointers): ... here.  For arrays use the element type.
(create_variable_info_for): Initialize may_have_pointers.
(new_var_info): Likewise.
(handle_lhs_call): Make the HEAP variable unknown-sized.
(intra_create_variable_infos): Use a type with pointers for
PARM_NOALIAS, make it unknown-sized.

From-SVN: r144292

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/torture/pr39074-2.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/torture/pr39074-3.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/torture/pr39074.c [new file with mode: 0644]
gcc/tree-ssa-structalias.c

index b6b912439bc7887cd5625f9ae637429c8400ebfa..4d9cf7d554bdbbb334959c1e5b90f22b16c44188 100644 (file)
@@ -1,3 +1,31 @@
+2009-02-19  Richard Guenther  <rguenther@suse.de>
+
+       PR tree-optimization/39207
+       PR tree-optimization/39074
+       * tree-ssa-structalias.c (storedanything_id, var_storedanything,
+       storedanything_tree): New.
+       (do_ds_constraint): Simplify ANYTHING shortcutting.  Update
+       the STOREDANYTHING solution if the lhs solution contains
+       ANYTHING.
+       (build_succ_graph): Add edges from STOREDANYTHING to all
+       non-direct nodes.
+       (init_base_vars): Initialize STOREDANYTHING.
+       (compute_points_to_sets): Free substitution info after
+       building the succ graph.
+       (ipa_pta_execute): Likewise.
+
+       * tree-ssa-structalias.c (struct variable_info): Add may_have_pointers
+       field.
+       (do_ds_constraint): Do not add to special var or non-pointer
+       field solutions.
+       (type_could_have_pointers): Split out from ...
+       (could_have_pointers): ... here.  For arrays use the element type.
+       (create_variable_info_for): Initialize may_have_pointers.
+       (new_var_info): Likewise.
+       (handle_lhs_call): Make the HEAP variable unknown-sized.
+       (intra_create_variable_infos): Use a type with pointers for
+       PARM_NOALIAS, make it unknown-sized.
+
 2009-02-18  H.J. Lu  <hongjiu.lu@intel.com>
 
        PR target/39224
index bd0c95cc6ba0fe1049a5a792ef262f55095b3359..036d40215f905d557c37c531d6072bb8b6437c42 100644 (file)
@@ -1,3 +1,10 @@
+2009-02-19  Richard Guenther  <rguenther@suse.de>
+
+       PR tree-optimization/39074
+       * gcc.dg/torture/pr39074.c: New testcase.
+       * gcc.dg/torture/pr39074-2.c: Likewise.
+       * gcc.dg/torture/pr39074-3.c: Likewise.
+
 2009-02-18  H.J. Lu  <hongjiu.lu@intel.com>
 
        PR c++/39219
diff --git a/gcc/testsuite/gcc.dg/torture/pr39074-2.c b/gcc/testsuite/gcc.dg/torture/pr39074-2.c
new file mode 100644 (file)
index 0000000..89f7ebf
--- /dev/null
@@ -0,0 +1,34 @@
+/* { dg-do run } */
+/* { dg-require-effective-target stdint_types } */
+/* { dg-options "-fdump-tree-alias" } */
+/* { dg-skip-if "" { *-*-* } { "-O0" } { "" } } */
+
+#include <stdint.h>
+
+int i;
+uintptr_t __attribute__((noinline,const)) bar(int ***p) { return (uintptr_t)p; }
+void __attribute__((noinline))
+foo(void)
+{
+  int *y;
+  int **a = &y, **x;
+  int ***p;
+  uintptr_t b;
+  b = bar(&a);
+  p = (int ***)b;
+  x = *p;
+  *x = &i; /* *ANYTHING = &i has to make sure that y points to i.  */
+  *y = 0;
+}
+extern void abort (void);
+int main()
+{
+  i = 1;
+  foo ();
+  if (i != 0)
+    abort ();
+  return 0;
+}
+
+/* { dg-final { scan-tree-dump "y.._., name memory tag: NMT..., is dereferenced, points-to vars: { i }" "alias" } } */
+/* { dg-final { cleanup-tree-dump "alias" } } */
diff --git a/gcc/testsuite/gcc.dg/torture/pr39074-3.c b/gcc/testsuite/gcc.dg/torture/pr39074-3.c
new file mode 100644 (file)
index 0000000..7c76048
--- /dev/null
@@ -0,0 +1,25 @@
+/* { dg-do run } */
+/* { dg-require-effective-target stdint_types } */
+
+#include <stdint.h>
+
+uintptr_t __attribute__((noinline,const)) bar(int ***p) { return (uintptr_t)p; }
+extern void abort (void);
+int main()
+{
+  int i, j;
+  int *y = &j;
+  int **a = &y, **x;
+  int ***p;
+  uintptr_t b;
+  b = bar(&a);
+  p = (int ***)b;
+  x = *p;
+  *x = &i;
+  i = 1;
+  *y = 0;
+  if (i != 0)
+    abort ();
+  return 0;
+}
+
diff --git a/gcc/testsuite/gcc.dg/torture/pr39074.c b/gcc/testsuite/gcc.dg/torture/pr39074.c
new file mode 100644 (file)
index 0000000..cc37c8e
--- /dev/null
@@ -0,0 +1,31 @@
+/* { dg-do run } */
+/* { dg-options "-fdump-tree-alias" } */
+/* { dg-skip-if "" { *-*-* } { "-O0" } { "" } } */
+
+int i;
+void __attribute__((noinline))
+foo(long b, long q)
+{
+  int *y;
+  int **a = &y, **x;
+  int ***p;
+  if (b)
+    p = (int ***)q;
+  else
+    p = &a;
+  x = *p;
+  *x = &i;  /* *ANYTHING = &i has to make sure that y points to i.  */
+  *y = 0;
+}
+extern void abort (void);
+int main()
+{
+  i = 1;
+  foo (0, 0);
+  if (i != 0)
+    abort ();
+  return 0;
+}
+
+/* { dg-final { scan-tree-dump "y.._., name memory tag: NMT..., is dereferenced, points-to vars: { i }" "alias" } } */
+/* { dg-final { cleanup-tree-dump "alias" } } */
index 8f8879694275eeb3e7256bd36b301d0cb1bbd722..9de341b68ab60a096987be7443c9772e5025863a 100644 (file)
@@ -230,6 +230,9 @@ struct variable_info
      variable.  This is used for C++ placement new.  */
   unsigned int no_tbaa_pruning : 1;
 
+  /* True if this field may contain pointers.  */
+  unsigned int may_have_pointers : 1;
+
   /* Variable id this was collapsed to due to type unsafety.  Zero if
      this variable was not collapsed.  This should be unused completely
      after build_succ_graph, or something is broken.  */
@@ -297,7 +300,8 @@ get_varinfo_fc (unsigned int n)
 
 /* Static IDs for the special variables.  */
 enum { nothing_id = 0, anything_id = 1, readonly_id = 2,
-       escaped_id = 3, nonlocal_id = 4, callused_id = 5, integer_id = 6 };
+       escaped_id = 3, nonlocal_id = 4, callused_id = 5,
+       storedanything_id = 6, integer_id = 7 };
 
 /* Variable that represents the unknown pointer.  */
 static varinfo_t var_anything;
@@ -323,6 +327,10 @@ static tree nonlocal_tree;
 static varinfo_t var_callused;
 static tree callused_tree;
 
+/* Variable that represents variables that are stored to anything.  */
+static varinfo_t var_storedanything;
+static tree storedanything_tree;
+
 /* Variable that represents integers.  This is used for when people do things
    like &0->a.b.  */
 static varinfo_t var_integer;
@@ -377,6 +385,7 @@ new_var_info (tree t, unsigned int id, const char *name)
   ret->is_special_var = false;
   ret->is_unknown_size_var = false;
   ret->is_full_var = false;
+  ret->may_have_pointers = true;
   var = t;
   if (TREE_CODE (var) == SSA_NAME)
     var = SSA_NAME_VAR (var);
@@ -1182,7 +1191,7 @@ build_pred_graph (void)
 static void
 build_succ_graph (void)
 {
-  int i;
+  unsigned i, t;
   constraint_t c;
 
   for (i = 0; VEC_iterate (constraint_t, constraints, i, c); i++)
@@ -1223,6 +1232,14 @@ build_succ_graph (void)
          add_graph_edge (graph, lhsvar, rhsvar);
        }
     }
+
+  /* Add edges from STOREDANYTHING to all non-direct nodes.  */
+  t = find (storedanything_id);
+  for (i = integer_id + 1; i < FIRST_REF_NODE; ++i)
+    {
+      if (!TEST_BIT (graph->direct_nodes, i))
+       add_graph_edge (graph, find (i), t);
+    }
 }
 
 
@@ -1608,35 +1625,33 @@ do_ds_constraint (constraint_t c, bitmap delta)
   unsigned int j;
   bitmap_iterator bi;
 
- if (bitmap_bit_p (sol, anything_id))
-   {
-     EXECUTE_IF_SET_IN_BITMAP (delta, 0, j, bi)
-       {
-        varinfo_t jvi = get_varinfo (j);
-        unsigned int t;
-        unsigned int loff = c->lhs.offset;
-        unsigned HOST_WIDE_INT fieldoffset = jvi->offset + loff;
-        varinfo_t v;
-
-        v = get_varinfo (j);
-        if (!v->is_full_var)
-          {
-            v = first_vi_for_offset (v, fieldoffset);
-            /* If the access is outside of the variable we can ignore it.  */
-            if (!v)
-              continue;
-          }
-        t = find (v->id);
-
-        if (bitmap_set_bit (get_varinfo (t)->solution, anything_id)
-            && !TEST_BIT (changed, t))
-          {
-            SET_BIT (changed, t);
-            changed_count++;
-          }
-       }
-     return;
-   }
+  /* Our IL does not allow this.  */
+  gcc_assert (c->rhs.offset == 0);
+
+  /* If the solution of y contains ANYTHING simply use the ANYTHING
+     solution.  This avoids needlessly increasing the points-to sets.  */
+  if (bitmap_bit_p (sol, anything_id))
+    sol = get_varinfo (find (anything_id))->solution;
+
+  /* If the solution for x contains ANYTHING we have to merge the
+     solution of y into all pointer variables which we do via
+     STOREDANYTHING.  */
+  if (bitmap_bit_p (delta, anything_id))
+    {
+      unsigned t = find (storedanything_id);
+      if (add_graph_edge (graph, t, rhs))
+       {
+         if (bitmap_ior_into (get_varinfo (t)->solution, sol))
+           {
+             if (!TEST_BIT (changed, t))
+               {
+                 SET_BIT (changed, t);
+                 changed_count++;
+               }
+           }
+       }
+      return;
+    }
 
   /* For each member j of delta (Sol(x)), add an edge from y to j and
      union Sol(y) into Sol(j) */
@@ -1648,26 +1663,27 @@ do_ds_constraint (constraint_t c, bitmap delta)
          varinfo_t v;
          unsigned int t;
          unsigned HOST_WIDE_INT fieldoffset = get_varinfo (j)->offset + loff;
-         bitmap tmp;
 
          v = first_vi_for_offset (get_varinfo (j), fieldoffset);
          /* If the access is outside of the variable we can ignore it.  */
          if (!v)
            continue;
-         t = find (v->id);
-         tmp = get_varinfo (t)->solution;
 
-            if (add_graph_edge (graph, t, rhs))
+         if (v->may_have_pointers)
            {
-                if (bitmap_ior_into (get_varinfo (t)->solution, sol))
+             t = find (v->id);
+             if (add_graph_edge (graph, t, rhs))
                {
-                    if (t == rhs)
-                      sol = get_varinfo (rhs)->solution;
-                    if (!TEST_BIT (changed, t))
-                      {
-                        SET_BIT (changed, t);
-                        changed_count++;
-                      }
+                 if (bitmap_ior_into (get_varinfo (t)->solution, sol))
+                   {
+                     if (t == rhs)
+                       sol = get_varinfo (rhs)->solution;
+                     if (!TEST_BIT (changed, t))
+                       {
+                         SET_BIT (changed, t);
+                         changed_count++;
+                       }
+                   }
                }
            }
        }
@@ -2740,19 +2756,27 @@ process_constraint (constraint_t t)
     }
 }
 
+/* Return true if T is a type that could contain pointers.  */
+
+static bool
+type_could_have_pointers (tree type)
+{
+  if (POINTER_TYPE_P (type))
+    return true;
+
+  if (TREE_CODE (type) == ARRAY_TYPE)
+    return type_could_have_pointers (TREE_TYPE (type));
+
+  return AGGREGATE_TYPE_P (type);
+}
+
 /* Return true if T is a variable of a type that could contain
    pointers.  */
 
 static bool
 could_have_pointers (tree t)
 {
-  tree type = TREE_TYPE (t);
-
-  if (POINTER_TYPE_P (type)
-      || AGGREGATE_TYPE_P (type))
-    return true;
-
-  return false;
+  return type_could_have_pointers (TREE_TYPE (t));
 }
 
 /* Return the position, in bits, of FIELD_DECL from the beginning of its
@@ -3516,6 +3540,9 @@ handle_lhs_call (tree lhs, int flags)
       vi = get_varinfo (rhsc.var);
       vi->is_artificial_var = 1;
       vi->is_heap_var = 1;
+      vi->is_unknown_size_var = true;
+      vi->fullsize = ~0;
+      vi->size = ~0;
       rhsc.type = ADDRESSOF;
       rhsc.offset = 0;
     }
@@ -4356,6 +4383,7 @@ create_variable_info_for (tree decl, const char *name)
   vi = new_var_info (decl, index, name);
   vi->decl = decl;
   vi->offset = 0;
+  vi->may_have_pointers = could_have_pointers (decl);
   if (!declsize
       || !host_integerp (declsize, 1))
     {
@@ -4372,7 +4400,7 @@ create_variable_info_for (tree decl, const char *name)
   insert_vi_for_tree (vi->decl, vi);
   VEC_safe_push (varinfo_t, heap, varmap, vi);
   if (is_global && (!flag_whole_program || !in_ipa_mode)
-      && could_have_pointers (decl))
+      && vi->may_have_pointers)
     {
       if (var_ann (decl)
          && var_ann (decl)->noalias_state == NO_ALIAS_ANYTHING)
@@ -4433,6 +4461,7 @@ create_variable_info_for (tree decl, const char *name)
 
       vi->size = fo->size;
       vi->offset = fo->offset;
+      vi->may_have_pointers = fo->may_have_pointers;
       for (i = VEC_length (fieldoff_s, fieldstack) - 1;
           i >= 1 && VEC_iterate (fieldoff_s, fieldstack, i, fo);
           i--)
@@ -4454,10 +4483,11 @@ create_variable_info_for (tree decl, const char *name)
          newvi->offset = fo->offset;
          newvi->size = fo->size;
          newvi->fullsize = vi->fullsize;
+         newvi->may_have_pointers = fo->may_have_pointers;
          insert_into_field_list (vi, newvi);
          VEC_safe_push (varinfo_t, heap, varmap, newvi);
          if (is_global && (!flag_whole_program || !in_ipa_mode)
-             && fo->may_have_pointers)
+             && newvi->may_have_pointers)
            make_constraint_from (newvi, escaped_id);
 
          stats.total_vars++;
@@ -4541,7 +4571,7 @@ intra_create_variable_infos (void)
          if (heapvar == NULL_TREE)
            {
              var_ann_t ann;
-             heapvar = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (t)),
+             heapvar = create_tmp_var_raw (ptr_type_node,
                                            "PARM_NOALIAS");
              DECL_EXTERNAL (heapvar) = 1;
              if (gimple_referenced_vars (cfun))
@@ -4564,6 +4594,9 @@ intra_create_variable_infos (void)
          vi = get_vi_for_tree (heapvar);
          vi->is_artificial_var = 1;
          vi->is_heap_var = 1;
+         vi->is_unknown_size_var = true;
+         vi->fullsize = ~0;
+         vi->size = ~0;
          rhs.var = vi->id;
          rhs.type = ADDRESSOF;
          rhs.offset = 0;
@@ -5239,6 +5272,19 @@ init_base_vars (void)
   rhs.offset = 0;
   process_constraint (new_constraint (lhs, rhs));
 
+  /* Create the STOREDANYTHING variable, used to represent the set of
+     variables stored to *ANYTHING.  */
+  storedanything_tree = create_tmp_var_raw (ptr_type_node, "STOREDANYTHING");
+  var_storedanything = new_var_info (storedanything_tree, storedanything_id,
+                                    "STOREDANYTHING");
+  insert_vi_for_tree (storedanything_tree, var_storedanything);
+  var_storedanything->is_artificial_var = 1;
+  var_storedanything->offset = 0;
+  var_storedanything->size = ~0;
+  var_storedanything->fullsize = ~0;
+  var_storedanything->is_special_var = 0;
+  VEC_safe_push (varinfo_t, heap, varmap, var_storedanything);
+
   /* Create the INTEGER variable, used to represent that a variable points
      to an INTEGER.  */
   integer_tree = create_tmp_var_raw (void_type_node, "INTEGER");
@@ -5537,9 +5583,9 @@ compute_points_to_sets (void)
     fprintf (dump_file, "Rewriting constraints and unifying "
             "variables\n");
   rewrite_constraints (graph, si);
-  free_var_substitution_info (si);
 
   build_succ_graph ();
+  free_var_substitution_info (si);
 
   if (dump_file && (dump_flags & TDF_GRAPH))
     dump_constraint_graph (dump_file);
@@ -5698,9 +5744,9 @@ ipa_pta_execute (void)
   build_pred_graph ();
   si = perform_var_substitution (graph);
   rewrite_constraints (graph, si);
-  free_var_substitution_info (si);
 
   build_succ_graph ();
+  free_var_substitution_info (si);
   move_complex_constraints (graph);
   unite_pointer_equivalences (graph);
   find_indirect_cycles (graph);