From 9e39dba643323a8bf07e1435657eebd3985452db Mon Sep 17 00:00:00 2001 From: Richard Guenther Date: Thu, 19 Feb 2009 10:12:25 +0000 Subject: [PATCH] re PR tree-optimization/39207 (Strict aliasing warnings in libstdc++ headers) 2009-02-19 Richard Guenther 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 | 28 ++++++ gcc/testsuite/ChangeLog | 7 ++ gcc/testsuite/gcc.dg/torture/pr39074-2.c | 34 +++++++ gcc/testsuite/gcc.dg/torture/pr39074-3.c | 25 +++++ gcc/testsuite/gcc.dg/torture/pr39074.c | 31 ++++++ gcc/tree-ssa-structalias.c | 156 ++++++++++++++++++++----------- 6 files changed, 226 insertions(+), 55 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/torture/pr39074-2.c create mode 100644 gcc/testsuite/gcc.dg/torture/pr39074-3.c create mode 100644 gcc/testsuite/gcc.dg/torture/pr39074.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index b6b9124..4d9cf7d 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,31 @@ +2009-02-19 Richard Guenther + + 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 PR target/39224 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index bd0c95c..036d402 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,10 @@ +2009-02-19 Richard Guenther + + 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 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 index 0000000..89f7ebf --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr39074-2.c @@ -0,0 +1,34 @@ +/* { dg-do run } */ +/* { dg-require-effective-target stdint_types } */ +/* { dg-options "-fdump-tree-alias" } */ +/* { dg-skip-if "" { *-*-* } { "-O0" } { "" } } */ + +#include + +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 index 0000000..7c76048 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr39074-3.c @@ -0,0 +1,25 @@ +/* { dg-do run } */ +/* { dg-require-effective-target stdint_types } */ + +#include + +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 index 0000000..cc37c8e --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr39074.c @@ -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" } } */ diff --git a/gcc/tree-ssa-structalias.c b/gcc/tree-ssa-structalias.c index 8f88796..9de341b 100644 --- a/gcc/tree-ssa-structalias.c +++ b/gcc/tree-ssa-structalias.c @@ -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); -- 2.7.4