Commit 9e39dba6 by Richard Guenther Committed by Richard Biener

re PR tree-optimization/39207 (Strict aliasing warnings in libstdc++ headers)

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
parent aac2878e
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> 2009-02-18 H.J. Lu <hongjiu.lu@intel.com>
PR target/39224 PR target/39224
......
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> 2009-02-18 H.J. Lu <hongjiu.lu@intel.com>
PR c++/39219 PR c++/39219
......
/* { 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" } } */
/* { 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;
}
/* { 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" } } */
...@@ -230,6 +230,9 @@ struct variable_info ...@@ -230,6 +230,9 @@ struct variable_info
variable. This is used for C++ placement new. */ variable. This is used for C++ placement new. */
unsigned int no_tbaa_pruning : 1; 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 /* Variable id this was collapsed to due to type unsafety. Zero if
this variable was not collapsed. This should be unused completely this variable was not collapsed. This should be unused completely
after build_succ_graph, or something is broken. */ after build_succ_graph, or something is broken. */
...@@ -297,7 +300,8 @@ get_varinfo_fc (unsigned int n) ...@@ -297,7 +300,8 @@ get_varinfo_fc (unsigned int n)
/* Static IDs for the special variables. */ /* Static IDs for the special variables. */
enum { nothing_id = 0, anything_id = 1, readonly_id = 2, 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. */ /* Variable that represents the unknown pointer. */
static varinfo_t var_anything; static varinfo_t var_anything;
...@@ -323,6 +327,10 @@ static tree nonlocal_tree; ...@@ -323,6 +327,10 @@ static tree nonlocal_tree;
static varinfo_t var_callused; static varinfo_t var_callused;
static tree callused_tree; 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 /* Variable that represents integers. This is used for when people do things
like &0->a.b. */ like &0->a.b. */
static varinfo_t var_integer; static varinfo_t var_integer;
...@@ -377,6 +385,7 @@ new_var_info (tree t, unsigned int id, const char *name) ...@@ -377,6 +385,7 @@ new_var_info (tree t, unsigned int id, const char *name)
ret->is_special_var = false; ret->is_special_var = false;
ret->is_unknown_size_var = false; ret->is_unknown_size_var = false;
ret->is_full_var = false; ret->is_full_var = false;
ret->may_have_pointers = true;
var = t; var = t;
if (TREE_CODE (var) == SSA_NAME) if (TREE_CODE (var) == SSA_NAME)
var = SSA_NAME_VAR (var); var = SSA_NAME_VAR (var);
...@@ -1182,7 +1191,7 @@ build_pred_graph (void) ...@@ -1182,7 +1191,7 @@ build_pred_graph (void)
static void static void
build_succ_graph (void) build_succ_graph (void)
{ {
int i; unsigned i, t;
constraint_t c; constraint_t c;
for (i = 0; VEC_iterate (constraint_t, constraints, i, c); i++) for (i = 0; VEC_iterate (constraint_t, constraints, i, c); i++)
...@@ -1223,6 +1232,14 @@ build_succ_graph (void) ...@@ -1223,6 +1232,14 @@ build_succ_graph (void)
add_graph_edge (graph, lhsvar, rhsvar); 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,33 +1625,31 @@ do_ds_constraint (constraint_t c, bitmap delta) ...@@ -1608,33 +1625,31 @@ do_ds_constraint (constraint_t c, bitmap delta)
unsigned int j; unsigned int j;
bitmap_iterator bi; 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)) 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))
{ {
EXECUTE_IF_SET_IN_BITMAP (delta, 0, j, bi) unsigned t = find (storedanything_id);
if (add_graph_edge (graph, t, rhs))
{ {
varinfo_t jvi = get_varinfo (j); if (bitmap_ior_into (get_varinfo (t)->solution, sol))
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 (!TEST_BIT (changed, t))
/* 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); SET_BIT (changed, t);
changed_count++; changed_count++;
} }
} }
}
return; return;
} }
...@@ -1648,15 +1663,15 @@ do_ds_constraint (constraint_t c, bitmap delta) ...@@ -1648,15 +1663,15 @@ do_ds_constraint (constraint_t c, bitmap delta)
varinfo_t v; varinfo_t v;
unsigned int t; unsigned int t;
unsigned HOST_WIDE_INT fieldoffset = get_varinfo (j)->offset + loff; unsigned HOST_WIDE_INT fieldoffset = get_varinfo (j)->offset + loff;
bitmap tmp;
v = first_vi_for_offset (get_varinfo (j), fieldoffset); v = first_vi_for_offset (get_varinfo (j), fieldoffset);
/* If the access is outside of the variable we can ignore it. */ /* If the access is outside of the variable we can ignore it. */
if (!v) if (!v)
continue; continue;
t = find (v->id);
tmp = get_varinfo (t)->solution;
if (v->may_have_pointers)
{
t = find (v->id);
if (add_graph_edge (graph, t, rhs)) if (add_graph_edge (graph, t, rhs))
{ {
if (bitmap_ior_into (get_varinfo (t)->solution, sol)) if (bitmap_ior_into (get_varinfo (t)->solution, sol))
...@@ -1672,6 +1687,7 @@ do_ds_constraint (constraint_t c, bitmap delta) ...@@ -1672,6 +1687,7 @@ do_ds_constraint (constraint_t c, bitmap delta)
} }
} }
} }
}
} }
/* Handle a non-simple (simple meaning requires no iteration), /* Handle a non-simple (simple meaning requires no iteration),
...@@ -2740,19 +2756,27 @@ process_constraint (constraint_t t) ...@@ -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 /* Return true if T is a variable of a type that could contain
pointers. */ pointers. */
static bool static bool
could_have_pointers (tree t) could_have_pointers (tree t)
{ {
tree type = TREE_TYPE (t); return type_could_have_pointers (TREE_TYPE (t));
if (POINTER_TYPE_P (type)
|| AGGREGATE_TYPE_P (type))
return true;
return false;
} }
/* Return the position, in bits, of FIELD_DECL from the beginning of its /* Return the position, in bits, of FIELD_DECL from the beginning of its
...@@ -3516,6 +3540,9 @@ handle_lhs_call (tree lhs, int flags) ...@@ -3516,6 +3540,9 @@ handle_lhs_call (tree lhs, int flags)
vi = get_varinfo (rhsc.var); vi = get_varinfo (rhsc.var);
vi->is_artificial_var = 1; vi->is_artificial_var = 1;
vi->is_heap_var = 1; vi->is_heap_var = 1;
vi->is_unknown_size_var = true;
vi->fullsize = ~0;
vi->size = ~0;
rhsc.type = ADDRESSOF; rhsc.type = ADDRESSOF;
rhsc.offset = 0; rhsc.offset = 0;
} }
...@@ -4356,6 +4383,7 @@ create_variable_info_for (tree decl, const char *name) ...@@ -4356,6 +4383,7 @@ create_variable_info_for (tree decl, const char *name)
vi = new_var_info (decl, index, name); vi = new_var_info (decl, index, name);
vi->decl = decl; vi->decl = decl;
vi->offset = 0; vi->offset = 0;
vi->may_have_pointers = could_have_pointers (decl);
if (!declsize if (!declsize
|| !host_integerp (declsize, 1)) || !host_integerp (declsize, 1))
{ {
...@@ -4372,7 +4400,7 @@ create_variable_info_for (tree decl, const char *name) ...@@ -4372,7 +4400,7 @@ create_variable_info_for (tree decl, const char *name)
insert_vi_for_tree (vi->decl, vi); insert_vi_for_tree (vi->decl, vi);
VEC_safe_push (varinfo_t, heap, varmap, vi); VEC_safe_push (varinfo_t, heap, varmap, vi);
if (is_global && (!flag_whole_program || !in_ipa_mode) if (is_global && (!flag_whole_program || !in_ipa_mode)
&& could_have_pointers (decl)) && vi->may_have_pointers)
{ {
if (var_ann (decl) if (var_ann (decl)
&& var_ann (decl)->noalias_state == NO_ALIAS_ANYTHING) && var_ann (decl)->noalias_state == NO_ALIAS_ANYTHING)
...@@ -4433,6 +4461,7 @@ create_variable_info_for (tree decl, const char *name) ...@@ -4433,6 +4461,7 @@ create_variable_info_for (tree decl, const char *name)
vi->size = fo->size; vi->size = fo->size;
vi->offset = fo->offset; vi->offset = fo->offset;
vi->may_have_pointers = fo->may_have_pointers;
for (i = VEC_length (fieldoff_s, fieldstack) - 1; for (i = VEC_length (fieldoff_s, fieldstack) - 1;
i >= 1 && VEC_iterate (fieldoff_s, fieldstack, i, fo); i >= 1 && VEC_iterate (fieldoff_s, fieldstack, i, fo);
i--) i--)
...@@ -4454,10 +4483,11 @@ create_variable_info_for (tree decl, const char *name) ...@@ -4454,10 +4483,11 @@ create_variable_info_for (tree decl, const char *name)
newvi->offset = fo->offset; newvi->offset = fo->offset;
newvi->size = fo->size; newvi->size = fo->size;
newvi->fullsize = vi->fullsize; newvi->fullsize = vi->fullsize;
newvi->may_have_pointers = fo->may_have_pointers;
insert_into_field_list (vi, newvi); insert_into_field_list (vi, newvi);
VEC_safe_push (varinfo_t, heap, varmap, newvi); VEC_safe_push (varinfo_t, heap, varmap, newvi);
if (is_global && (!flag_whole_program || !in_ipa_mode) if (is_global && (!flag_whole_program || !in_ipa_mode)
&& fo->may_have_pointers) && newvi->may_have_pointers)
make_constraint_from (newvi, escaped_id); make_constraint_from (newvi, escaped_id);
stats.total_vars++; stats.total_vars++;
...@@ -4541,7 +4571,7 @@ intra_create_variable_infos (void) ...@@ -4541,7 +4571,7 @@ intra_create_variable_infos (void)
if (heapvar == NULL_TREE) if (heapvar == NULL_TREE)
{ {
var_ann_t ann; var_ann_t ann;
heapvar = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (t)), heapvar = create_tmp_var_raw (ptr_type_node,
"PARM_NOALIAS"); "PARM_NOALIAS");
DECL_EXTERNAL (heapvar) = 1; DECL_EXTERNAL (heapvar) = 1;
if (gimple_referenced_vars (cfun)) if (gimple_referenced_vars (cfun))
...@@ -4564,6 +4594,9 @@ intra_create_variable_infos (void) ...@@ -4564,6 +4594,9 @@ intra_create_variable_infos (void)
vi = get_vi_for_tree (heapvar); vi = get_vi_for_tree (heapvar);
vi->is_artificial_var = 1; vi->is_artificial_var = 1;
vi->is_heap_var = 1; vi->is_heap_var = 1;
vi->is_unknown_size_var = true;
vi->fullsize = ~0;
vi->size = ~0;
rhs.var = vi->id; rhs.var = vi->id;
rhs.type = ADDRESSOF; rhs.type = ADDRESSOF;
rhs.offset = 0; rhs.offset = 0;
...@@ -5239,6 +5272,19 @@ init_base_vars (void) ...@@ -5239,6 +5272,19 @@ init_base_vars (void)
rhs.offset = 0; rhs.offset = 0;
process_constraint (new_constraint (lhs, rhs)); 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 /* Create the INTEGER variable, used to represent that a variable points
to an INTEGER. */ to an INTEGER. */
integer_tree = create_tmp_var_raw (void_type_node, "INTEGER"); integer_tree = create_tmp_var_raw (void_type_node, "INTEGER");
...@@ -5537,9 +5583,9 @@ compute_points_to_sets (void) ...@@ -5537,9 +5583,9 @@ compute_points_to_sets (void)
fprintf (dump_file, "Rewriting constraints and unifying " fprintf (dump_file, "Rewriting constraints and unifying "
"variables\n"); "variables\n");
rewrite_constraints (graph, si); rewrite_constraints (graph, si);
free_var_substitution_info (si);
build_succ_graph (); build_succ_graph ();
free_var_substitution_info (si);
if (dump_file && (dump_flags & TDF_GRAPH)) if (dump_file && (dump_flags & TDF_GRAPH))
dump_constraint_graph (dump_file); dump_constraint_graph (dump_file);
...@@ -5698,9 +5744,9 @@ ipa_pta_execute (void) ...@@ -5698,9 +5744,9 @@ ipa_pta_execute (void)
build_pred_graph (); build_pred_graph ();
si = perform_var_substitution (graph); si = perform_var_substitution (graph);
rewrite_constraints (graph, si); rewrite_constraints (graph, si);
free_var_substitution_info (si);
build_succ_graph (); build_succ_graph ();
free_var_substitution_info (si);
move_complex_constraints (graph); move_complex_constraints (graph);
unite_pointer_equivalences (graph); unite_pointer_equivalences (graph);
find_indirect_cycles (graph); find_indirect_cycles (graph);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment