[PATCH] Fix PR39207, bogus strict-aliasing warning, PR39074, wrong PTA
Richard Guenther
rguenther@suse.de
Wed Feb 18 14:51:00 GMT 2009
This "backports" the fix for PR39074 from alias-improvements branch to
trunk, thereby fixing PR39207, bogus strict-aliasing warnings from
libstdc++ headers. On the branch I needed the second patch appended
below to avoid performance regressions, so I will backport this as well.
Bootstrapped and tested on x86_64-unknown-linux-gnu. I have put the
patches on x86_64 and ia64 SPEC2000 testing (I hope we're not going
the 4.3 way of very late performance regressions due to bug fixes...).
I plan to apply this tomorrow after testresults have arrived.
Richard.
2009-02-18 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_pred_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.
Index: gcc/tree-ssa-structalias.c
===================================================================
*** gcc/tree-ssa-structalias.c (revision 144259)
--- gcc/tree-ssa-structalias.c (working copy)
*************** get_varinfo_fc (unsigned int n)
*** 297,303 ****
/* 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 };
/* Variable that represents the unknown pointer. */
static varinfo_t var_anything;
--- 297,304 ----
/* 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,
! storedanything_id = 6, integer_id = 7 };
/* Variable that represents the unknown pointer. */
static varinfo_t var_anything;
*************** static tree nonlocal_tree;
*** 323,328 ****
--- 324,333 ----
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;
*************** build_pred_graph (void)
*** 1182,1188 ****
static void
build_succ_graph (void)
{
! int i;
constraint_t c;
for (i = 0; VEC_iterate (constraint_t, constraints, i, c); i++)
--- 1187,1193 ----
static void
build_succ_graph (void)
{
! unsigned i, t;
constraint_t c;
for (i = 0; VEC_iterate (constraint_t, constraints, i, c); i++)
*************** build_succ_graph (void)
*** 1223,1228 ****
--- 1228,1241 ----
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);
+ }
}
*************** do_ds_constraint (constraint_t c, bitmap
*** 1608,1642 ****
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;
! }
/* For each member j of delta (Sol(x)), add an edge from y to j and
union Sol(y) into Sol(j) */
--- 1621,1653 ----
unsigned int j;
bitmap_iterator bi;
! /* 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) */
*************** init_base_vars (void)
*** 5239,5244 ****
--- 5250,5268 ----
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");
*************** compute_points_to_sets (void)
*** 5537,5545 ****
fprintf (dump_file, "Rewriting constraints and unifying "
"variables\n");
rewrite_constraints (graph, si);
- free_var_substitution_info (si);
build_succ_graph ();
if (dump_file && (dump_flags & TDF_GRAPH))
dump_constraint_graph (dump_file);
--- 5561,5569 ----
fprintf (dump_file, "Rewriting constraints and unifying "
"variables\n");
rewrite_constraints (graph, si);
build_succ_graph ();
+ free_var_substitution_info (si);
if (dump_file && (dump_flags & TDF_GRAPH))
dump_constraint_graph (dump_file);
*************** ipa_pta_execute (void)
*** 5698,5706 ****
build_pred_graph ();
si = perform_var_substitution (graph);
rewrite_constraints (graph, si);
- free_var_substitution_info (si);
build_succ_graph ();
move_complex_constraints (graph);
unite_pointer_equivalences (graph);
find_indirect_cycles (graph);
--- 5722,5730 ----
build_pred_graph ();
si = perform_var_substitution (graph);
rewrite_constraints (graph, si);
build_succ_graph ();
+ free_var_substitution_info (si);
move_complex_constraints (graph);
unite_pointer_equivalences (graph);
find_indirect_cycles (graph);
Index: gcc/testsuite/gcc.dg/torture/pr39074-2.c
===================================================================
*** gcc/testsuite/gcc.dg/torture/pr39074-2.c (revision 0)
--- gcc/testsuite/gcc.dg/torture/pr39074-2.c (revision 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" } } */
Index: gcc/testsuite/gcc.dg/torture/pr39074-3.c
===================================================================
*** gcc/testsuite/gcc.dg/torture/pr39074-3.c (revision 0)
--- gcc/testsuite/gcc.dg/torture/pr39074-3.c (revision 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;
+ }
+
Index: gcc/testsuite/gcc.dg/torture/pr39074.c
===================================================================
*** gcc/testsuite/gcc.dg/torture/pr39074.c (revision 0)
--- gcc/testsuite/gcc.dg/torture/pr39074.c (revision 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" } } */
2009-02-18 Richard Guenther <rguenther@suse.de>
* 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.
Index: gcc/tree-ssa-structalias.c
===================================================================
--- gcc/tree-ssa-structalias.c.orig 2009-02-18 13:32:32.000000000 +0100
+++ gcc/tree-ssa-structalias.c 2009-02-18 13:32:05.000000000 +0100
@@ -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. */
@@ -382,6 +385,7 @@ new_var_info (tree t, unsigned int id, c
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);
@@ -1659,26 +1663,27 @@ do_ds_constraint (constraint_t c, bitmap
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++;
+ }
+ }
}
}
}
@@ -2751,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
@@ -3527,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;
}
@@ -4367,6 +4383,7 @@ create_variable_info_for (tree decl, con
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))
{
@@ -4383,7 +4400,7 @@ create_variable_info_for (tree decl, con
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)
@@ -4444,6 +4461,7 @@ create_variable_info_for (tree decl, con
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--)
@@ -4465,10 +4483,11 @@ create_variable_info_for (tree decl, con
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++;
@@ -4552,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))
@@ -4575,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;
More information about the Gcc-patches
mailing list