Commit 18abb35e by Richard Guenther Committed by Richard Biener

re PR tree-optimization/43879 (-fipa-pta causes various miscompilations)

2010-04-28  Richard Guenther  <rguenther@suse.de>

	PR tree-optimization/43879
	PR tree-optimization/43909
	* tree-ssa-structalias.c (struct variable_info): Add
	only_restrict_pointers flag.
	(new_var_info): Initialize it.  Increment stats.total_vars here.
	(create_function_info_for): Do not increment stats.total_vars
	here.
	(get_function_part_constraint): Fix build with C++.
	(insert_into_field_list): Remove.
	(push_fields_onto_fieldstack): Properly merge fields.
	(create_variable_info_for): Split and simplify.
	(create_variable_info_for_1): New piece.
	(intra_create_variable_infos): Properly make restrict constraints
	from parameters.

	* gcc.dg/ipa/ipa-pta-14.c: Adjust.

From-SVN: r158825
parent c718820a
2010-04-28 Richard Guenther <rguenther@suse.de> 2010-04-28 Richard Guenther <rguenther@suse.de>
PR tree-optimization/43879
PR tree-optimization/43909
* tree-ssa-structalias.c (struct variable_info): Add
only_restrict_pointers flag.
(new_var_info): Initialize it. Increment stats.total_vars here.
(create_function_info_for): Do not increment stats.total_vars
here.
(get_function_part_constraint): Fix build with C++.
(insert_into_field_list): Remove.
(push_fields_onto_fieldstack): Properly merge fields.
(create_variable_info_for): Split and simplify.
(create_variable_info_for_1): New piece.
(intra_create_variable_infos): Properly make restrict constraints
from parameters.
2010-04-28 Richard Guenther <rguenther@suse.de>
PR c++/43880 PR c++/43880
* tree-inline.c (copy_bind_expr): Also copy bind expr vars * tree-inline.c (copy_bind_expr): Also copy bind expr vars
value-exprs. value-exprs.
......
2010-04-28 Richard Guenther <rguenther@suse.de> 2010-04-28 Richard Guenther <rguenther@suse.de>
PR tree-optimization/43879
PR tree-optimization/43909
* gcc.dg/ipa/ipa-pta-14.c: Adjust.
2010-04-28 Richard Guenther <rguenther@suse.de>
PR c++/43880 PR c++/43880
* g++.dg/torture/pr43880.C: New testcase. * g++.dg/torture/pr43880.C: New testcase.
......
...@@ -21,8 +21,8 @@ int main() ...@@ -21,8 +21,8 @@ int main()
void *p; void *p;
a.p = (void *)&c; a.p = (void *)&c;
p = foo(&a, &a); p = foo(&a, &a);
/* { dg-final { scan-ipa-dump "foo.result = { NULL a c }" "pta" { xfail *-*-* } } } */ /* { dg-final { scan-ipa-dump "foo.result = { NULL a\[^ \]* c\[^ \]* }" "pta" { xfail *-*-* } } } */
/* { dg-final { scan-ipa-dump "foo.result = { NULL a a\[^ \]* c }" "pta" } } */ /* { dg-final { scan-ipa-dump "foo.result = { NULL a\[^ \]* a\[^ \]* c\[^ \]* }" "pta" } } */
((struct X *)p)->p = (void *)0; ((struct X *)p)->p = (void *)0;
if (a.p != (void *)0) if (a.p != (void *)0)
abort (); abort ();
......
...@@ -275,6 +275,9 @@ struct variable_info ...@@ -275,6 +275,9 @@ struct variable_info
/* True if this field may contain pointers. */ /* True if this field may contain pointers. */
unsigned int may_have_pointers : 1; unsigned int may_have_pointers : 1;
/* True if this field has only restrict qualified pointers. */
unsigned int only_restrict_pointers : 1;
/* True if this represents a global variable. */ /* True if this represents a global variable. */
unsigned int is_global_var : 1; unsigned int is_global_var : 1;
...@@ -412,6 +415,7 @@ new_var_info (tree t, const char *name) ...@@ -412,6 +415,7 @@ new_var_info (tree t, const char *name)
ret->is_heap_var = false; ret->is_heap_var = false;
ret->is_restrict_var = false; ret->is_restrict_var = false;
ret->may_have_pointers = true; ret->may_have_pointers = true;
ret->only_restrict_pointers = false;
ret->is_global_var = (t == NULL_TREE); ret->is_global_var = (t == NULL_TREE);
ret->is_fn_info = false; ret->is_fn_info = false;
if (t && DECL_P (t)) if (t && DECL_P (t))
...@@ -420,6 +424,8 @@ new_var_info (tree t, const char *name) ...@@ -420,6 +424,8 @@ new_var_info (tree t, const char *name)
ret->oldsolution = BITMAP_ALLOC (&oldpta_obstack); ret->oldsolution = BITMAP_ALLOC (&oldpta_obstack);
ret->next = NULL; ret->next = NULL;
stats.total_vars++;
VEC_safe_push (varinfo_t, heap, varmap, ret); VEC_safe_push (varinfo_t, heap, varmap, ret);
return ret; return ret;
...@@ -3641,7 +3647,10 @@ get_function_part_constraint (varinfo_t fi, unsigned part) ...@@ -3641,7 +3647,10 @@ get_function_part_constraint (varinfo_t fi, unsigned part)
else if (TREE_CODE (fi->decl) == FUNCTION_DECL) else if (TREE_CODE (fi->decl) == FUNCTION_DECL)
{ {
varinfo_t ai = first_vi_for_offset (fi, part); varinfo_t ai = first_vi_for_offset (fi, part);
c.var = ai ? ai->id : anything_id; if (ai)
c.var = ai->id;
else
c.var = anything_id;
c.offset = 0; c.offset = 0;
c.type = SCALAR; c.type = SCALAR;
} }
...@@ -4723,19 +4732,6 @@ first_or_preceding_vi_for_offset (varinfo_t start, ...@@ -4723,19 +4732,6 @@ first_or_preceding_vi_for_offset (varinfo_t start,
} }
/* Insert the varinfo FIELD into the field list for BASE, at the front
of the list. */
static void
insert_into_field_list (varinfo_t base, varinfo_t field)
{
varinfo_t prev = base;
varinfo_t curr = base->next;
field->next = curr;
prev->next = field;
}
/* This structure is used during pushing fields onto the fieldstack /* This structure is used during pushing fields onto the fieldstack
to track the offset of the field, since bitpos_of_field gives it to track the offset of the field, since bitpos_of_field gives it
relative to its immediate containing type, and we want it relative relative to its immediate containing type, and we want it relative
...@@ -4821,37 +4817,37 @@ var_can_have_subvars (const_tree v) ...@@ -4821,37 +4817,37 @@ var_can_have_subvars (const_tree v)
OFFSET is used to keep track of the offset in this entire OFFSET is used to keep track of the offset in this entire
structure, rather than just the immediately containing structure. structure, rather than just the immediately containing structure.
Returns the number of fields pushed. */ Returns false if the caller is supposed to handle the field we
recursed for. */
static int static bool
push_fields_onto_fieldstack (tree type, VEC(fieldoff_s,heap) **fieldstack, push_fields_onto_fieldstack (tree type, VEC(fieldoff_s,heap) **fieldstack,
HOST_WIDE_INT offset) HOST_WIDE_INT offset)
{ {
tree field; tree field;
int count = 0; bool empty_p = true;
if (TREE_CODE (type) != RECORD_TYPE) if (TREE_CODE (type) != RECORD_TYPE)
return 0; return false;
/* If the vector of fields is growing too big, bail out early. /* If the vector of fields is growing too big, bail out early.
Callers check for VEC_length <= MAX_FIELDS_FOR_FIELD_SENSITIVE, make Callers check for VEC_length <= MAX_FIELDS_FOR_FIELD_SENSITIVE, make
sure this fails. */ sure this fails. */
if (VEC_length (fieldoff_s, *fieldstack) > MAX_FIELDS_FOR_FIELD_SENSITIVE) if (VEC_length (fieldoff_s, *fieldstack) > MAX_FIELDS_FOR_FIELD_SENSITIVE)
return 0; return false;
for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field)) for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
if (TREE_CODE (field) == FIELD_DECL) if (TREE_CODE (field) == FIELD_DECL)
{ {
bool push = false; bool push = false;
int pushed = 0;
HOST_WIDE_INT foff = bitpos_of_field (field); HOST_WIDE_INT foff = bitpos_of_field (field);
if (!var_can_have_subvars (field) if (!var_can_have_subvars (field)
|| TREE_CODE (TREE_TYPE (field)) == QUAL_UNION_TYPE || TREE_CODE (TREE_TYPE (field)) == QUAL_UNION_TYPE
|| TREE_CODE (TREE_TYPE (field)) == UNION_TYPE) || TREE_CODE (TREE_TYPE (field)) == UNION_TYPE)
push = true; push = true;
else if (!(pushed = push_fields_onto_fieldstack else if (!push_fields_onto_fieldstack
(TREE_TYPE (field), fieldstack, offset + foff)) (TREE_TYPE (field), fieldstack, offset + foff)
&& (DECL_SIZE (field) && (DECL_SIZE (field)
&& !integer_zerop (DECL_SIZE (field)))) && !integer_zerop (DECL_SIZE (field))))
/* Empty structures may have actual size, like in C++. So /* Empty structures may have actual size, like in C++. So
...@@ -4874,12 +4870,11 @@ push_fields_onto_fieldstack (tree type, VEC(fieldoff_s,heap) **fieldstack, ...@@ -4874,12 +4870,11 @@ push_fields_onto_fieldstack (tree type, VEC(fieldoff_s,heap) **fieldstack,
/* If adjacent fields do not contain pointers merge them. */ /* If adjacent fields do not contain pointers merge them. */
if (pair if (pair
&& !pair->may_have_pointers && !pair->may_have_pointers
&& !could_have_pointers (field)
&& !pair->has_unknown_size && !pair->has_unknown_size
&& !has_unknown_size && !has_unknown_size
&& pair->offset + (HOST_WIDE_INT)pair->size == offset + foff) && pair->offset + (HOST_WIDE_INT)pair->size == offset + foff
&& !could_have_pointers (field))
{ {
pair = VEC_last (fieldoff_s, *fieldstack);
pair->size += TREE_INT_CST_LOW (DECL_SIZE (field)); pair->size += TREE_INT_CST_LOW (DECL_SIZE (field));
} }
else else
...@@ -4896,14 +4891,13 @@ push_fields_onto_fieldstack (tree type, VEC(fieldoff_s,heap) **fieldstack, ...@@ -4896,14 +4891,13 @@ push_fields_onto_fieldstack (tree type, VEC(fieldoff_s,heap) **fieldstack,
= (!has_unknown_size = (!has_unknown_size
&& POINTER_TYPE_P (TREE_TYPE (field)) && POINTER_TYPE_P (TREE_TYPE (field))
&& TYPE_RESTRICT (TREE_TYPE (field))); && TYPE_RESTRICT (TREE_TYPE (field)));
count++;
} }
} }
else
count += pushed; empty_p = false;
} }
return count; return !empty_p;
} }
/* Count the number of arguments DECL has, and set IS_VARARGS to true /* Count the number of arguments DECL has, and set IS_VARARGS to true
...@@ -4955,8 +4949,6 @@ create_function_info_for (tree decl, const char *name) ...@@ -4955,8 +4949,6 @@ create_function_info_for (tree decl, const char *name)
vi->fullsize = ~0; vi->fullsize = ~0;
insert_vi_for_tree (vi->decl, vi); insert_vi_for_tree (vi->decl, vi);
stats.total_vars++;
prev_vi = vi; prev_vi = vi;
/* Create a variable for things the function clobbers and one for /* Create a variable for things the function clobbers and one for
...@@ -4979,7 +4971,6 @@ create_function_info_for (tree decl, const char *name) ...@@ -4979,7 +4971,6 @@ create_function_info_for (tree decl, const char *name)
gcc_assert (prev_vi->offset < clobbervi->offset); gcc_assert (prev_vi->offset < clobbervi->offset);
prev_vi->next = clobbervi; prev_vi->next = clobbervi;
prev_vi = clobbervi; prev_vi = clobbervi;
stats.total_vars++;
asprintf (&tempname, "%s.use", name); asprintf (&tempname, "%s.use", name);
newname = ggc_strdup (tempname); newname = ggc_strdup (tempname);
...@@ -4994,7 +4985,6 @@ create_function_info_for (tree decl, const char *name) ...@@ -4994,7 +4985,6 @@ create_function_info_for (tree decl, const char *name)
gcc_assert (prev_vi->offset < usevi->offset); gcc_assert (prev_vi->offset < usevi->offset);
prev_vi->next = usevi; prev_vi->next = usevi;
prev_vi = usevi; prev_vi = usevi;
stats.total_vars++;
} }
/* And one for the static chain. */ /* And one for the static chain. */
...@@ -5017,7 +5007,6 @@ create_function_info_for (tree decl, const char *name) ...@@ -5017,7 +5007,6 @@ create_function_info_for (tree decl, const char *name)
gcc_assert (prev_vi->offset < chainvi->offset); gcc_assert (prev_vi->offset < chainvi->offset);
prev_vi->next = chainvi; prev_vi->next = chainvi;
prev_vi = chainvi; prev_vi = chainvi;
stats.total_vars++;
insert_vi_for_tree (fn->static_chain_decl, chainvi); insert_vi_for_tree (fn->static_chain_decl, chainvi);
} }
...@@ -5047,7 +5036,6 @@ create_function_info_for (tree decl, const char *name) ...@@ -5047,7 +5036,6 @@ create_function_info_for (tree decl, const char *name)
gcc_assert (prev_vi->offset < resultvi->offset); gcc_assert (prev_vi->offset < resultvi->offset);
prev_vi->next = resultvi; prev_vi->next = resultvi;
prev_vi = resultvi; prev_vi = resultvi;
stats.total_vars++;
if (DECL_RESULT (decl)) if (DECL_RESULT (decl))
insert_vi_for_tree (DECL_RESULT (decl), resultvi); insert_vi_for_tree (DECL_RESULT (decl), resultvi);
} }
...@@ -5078,7 +5066,6 @@ create_function_info_for (tree decl, const char *name) ...@@ -5078,7 +5066,6 @@ create_function_info_for (tree decl, const char *name)
gcc_assert (prev_vi->offset < argvi->offset); gcc_assert (prev_vi->offset < argvi->offset);
prev_vi->next = argvi; prev_vi->next = argvi;
prev_vi = argvi; prev_vi = argvi;
stats.total_vars++;
if (arg) if (arg)
{ {
insert_vi_for_tree (arg, argvi); insert_vi_for_tree (arg, argvi);
...@@ -5111,7 +5098,6 @@ create_function_info_for (tree decl, const char *name) ...@@ -5111,7 +5098,6 @@ create_function_info_for (tree decl, const char *name)
gcc_assert (prev_vi->offset < argvi->offset); gcc_assert (prev_vi->offset < argvi->offset);
prev_vi->next = argvi; prev_vi->next = argvi;
prev_vi = argvi; prev_vi = argvi;
stats.total_vars++;
} }
return vi->id; return vi->id;
...@@ -5141,107 +5127,51 @@ check_for_overlaps (VEC (fieldoff_s,heap) *fieldstack) ...@@ -5141,107 +5127,51 @@ check_for_overlaps (VEC (fieldoff_s,heap) *fieldstack)
This will also create any varinfo structures necessary for fields This will also create any varinfo structures necessary for fields
of DECL. */ of DECL. */
static unsigned int static varinfo_t
create_variable_info_for (tree decl, const char *name) create_variable_info_for_1 (tree decl, const char *name)
{ {
varinfo_t vi; varinfo_t vi, newvi;
tree decl_type = TREE_TYPE (decl); tree decl_type = TREE_TYPE (decl);
tree declsize = DECL_P (decl) ? DECL_SIZE (decl) : TYPE_SIZE (decl_type); tree declsize = DECL_P (decl) ? DECL_SIZE (decl) : TYPE_SIZE (decl_type);
VEC (fieldoff_s,heap) *fieldstack = NULL; VEC (fieldoff_s,heap) *fieldstack = NULL;
fieldoff_s *fo;
unsigned int i;
if (var_can_have_subvars (decl) && use_field_sensitive)
push_fields_onto_fieldstack (decl_type, &fieldstack, 0);
/* If the variable doesn't have subvars, we may end up needing to
sort the field list and create fake variables for all the
fields. */
vi = new_var_info (decl, name);
vi->offset = 0;
vi->may_have_pointers = could_have_pointers (decl);
if (!declsize if (!declsize
|| !host_integerp (declsize, 1)) || !host_integerp (declsize, 1))
{ {
vi->is_unknown_size_var = true; vi = new_var_info (decl, name);
vi->fullsize = ~0; vi->offset = 0;
vi->size = ~0; vi->size = ~0;
} vi->fullsize = ~0;
else vi->is_unknown_size_var = true;
{ vi->is_full_var = true;
vi->fullsize = TREE_INT_CST_LOW (declsize); vi->may_have_pointers = could_have_pointers (decl);
vi->size = vi->fullsize; return vi;
}
insert_vi_for_tree (vi->decl, vi);
/* ??? The setting of vi->may_have_pointers is too conservative here
and may get refined below. Thus we have superfluous constraints
here sometimes which triggers the commented assert in
dump_sa_points_to_info. */
if (vi->is_global_var
&& vi->may_have_pointers)
{
/* Mark global restrict qualified pointers. */
if (POINTER_TYPE_P (TREE_TYPE (decl))
&& TYPE_RESTRICT (TREE_TYPE (decl)))
make_constraint_from_restrict (vi, "GLOBAL_RESTRICT");
/* For escaped variables initialize them from nonlocal. */
if (!in_ipa_mode
|| DECL_EXTERNAL (decl) || TREE_PUBLIC (decl))
make_copy_constraint (vi, nonlocal_id);
/* If this is a global variable with an initializer and we are in
IPA mode generate constraints for it. In non-IPA mode
the initializer from nonlocal is all we need. */
if (in_ipa_mode
&& DECL_INITIAL (vi->decl))
{
VEC (ce_s, heap) *rhsc = NULL;
struct constraint_expr lhs, *rhsp;
unsigned i;
get_constraint_for (DECL_INITIAL (vi->decl), &rhsc);
lhs.var = vi->id;
lhs.offset = 0;
lhs.type = SCALAR;
for (i = 0; VEC_iterate (ce_s, rhsc, i, rhsp); ++i)
process_constraint (new_constraint (lhs, *rhsp));
/* If this is a variable that escapes from the unit
the initializer escapes as well. */
if (DECL_EXTERNAL (decl) || TREE_PUBLIC (decl))
{
lhs.var = escaped_id;
lhs.offset = 0;
lhs.type = SCALAR;
for (i = 0; VEC_iterate (ce_s, rhsc, i, rhsp); ++i)
process_constraint (new_constraint (lhs, *rhsp));
}
VEC_free (ce_s, heap, rhsc);
/* ??? Force us to not use subfields. Else we'd have to parse
arbitrary initializers. */
VEC_free (fieldoff_s, heap, fieldstack);
}
} }
stats.total_vars++; /* Collect field information. */
if (use_field_sensitive if (use_field_sensitive
&& !vi->is_unknown_size_var
&& var_can_have_subvars (decl) && var_can_have_subvars (decl)
&& VEC_length (fieldoff_s, fieldstack) > 1 /* ??? Force us to not use subfields for global initializers
&& VEC_length (fieldoff_s, fieldstack) <= MAX_FIELDS_FOR_FIELD_SENSITIVE) in IPA mode. Else we'd have to parse arbitrary initializers. */
&& !(in_ipa_mode
&& is_global_var (decl)
&& DECL_INITIAL (decl)))
{ {
fieldoff_s *fo = NULL; fieldoff_s *fo = NULL;
bool notokay = false; bool notokay = false;
unsigned int i; unsigned int i;
push_fields_onto_fieldstack (decl_type, &fieldstack, 0);
for (i = 0; !notokay && VEC_iterate (fieldoff_s, fieldstack, i, fo); i++) for (i = 0; !notokay && VEC_iterate (fieldoff_s, fieldstack, i, fo); i++)
{
if (fo->has_unknown_size if (fo->has_unknown_size
|| fo->offset < 0) || fo->offset < 0)
{ {
notokay = true; notokay = true;
break; break;
} }
}
/* We can't sort them if we have a field with a variable sized type, /* We can't sort them if we have a field with a variable sized type,
which will make notokay = true. In that case, we are going to return which will make notokay = true. In that case, we are going to return
...@@ -5257,69 +5187,112 @@ create_variable_info_for (tree decl, const char *name) ...@@ -5257,69 +5187,112 @@ create_variable_info_for (tree decl, const char *name)
notokay = check_for_overlaps (fieldstack); notokay = check_for_overlaps (fieldstack);
} }
if (notokay)
VEC_free (fieldoff_s, heap, fieldstack);
}
if (VEC_length (fieldoff_s, fieldstack) != 0) /* If we didn't end up collecting sub-variables create a full
fo = VEC_index (fieldoff_s, fieldstack, 0); variable for the decl. */
if (VEC_length (fieldoff_s, fieldstack) <= 1
if (fo == NULL || notokay) || VEC_length (fieldoff_s, fieldstack) > MAX_FIELDS_FOR_FIELD_SENSITIVE)
{ {
vi->is_unknown_size_var = 1; vi = new_var_info (decl, name);
vi->fullsize = ~0; vi->offset = 0;
vi->size = ~0; vi->may_have_pointers = could_have_pointers (decl);
vi->fullsize = TREE_INT_CST_LOW (declsize);
vi->size = vi->fullsize;
vi->is_full_var = true; vi->is_full_var = true;
VEC_free (fieldoff_s, heap, fieldstack); VEC_free (fieldoff_s, heap, fieldstack);
return vi->id; return vi;
} }
vi->size = fo->size; vi = new_var_info (decl, name);
vi->offset = fo->offset; vi->fullsize = TREE_INT_CST_LOW (declsize);
vi->may_have_pointers = fo->may_have_pointers; for (i = 0, newvi = vi;
if (vi->is_global_var VEC_iterate (fieldoff_s, fieldstack, i, fo);
&& vi->may_have_pointers) ++i, newvi = newvi->next)
{
if (fo->only_restrict_pointers)
make_constraint_from_restrict (vi, "GLOBAL_RESTRICT");
}
for (i = VEC_length (fieldoff_s, fieldstack) - 1;
i >= 1 && VEC_iterate (fieldoff_s, fieldstack, i, fo);
i--)
{ {
varinfo_t newvi;
const char *newname = "NULL"; const char *newname = "NULL";
char *tempname; char *tempname;
if (dump_file) if (dump_file)
{ {
asprintf (&tempname, "%s." HOST_WIDE_INT_PRINT_DEC asprintf (&tempname, "%s." HOST_WIDE_INT_PRINT_DEC
"+" HOST_WIDE_INT_PRINT_DEC, "+" HOST_WIDE_INT_PRINT_DEC, name, fo->offset, fo->size);
vi->name, fo->offset, fo->size);
newname = ggc_strdup (tempname); newname = ggc_strdup (tempname);
free (tempname); free (tempname);
} }
newvi = new_var_info (decl, newname); newvi->name = newname;
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; newvi->may_have_pointers = fo->may_have_pointers;
insert_into_field_list (vi, newvi); newvi->only_restrict_pointers = fo->only_restrict_pointers;
if ((newvi->is_global_var || TREE_CODE (decl) == PARM_DECL) if (i + 1 < VEC_length (fieldoff_s, fieldstack))
&& newvi->may_have_pointers) newvi->next = new_var_info (decl, name);
{
if (fo->only_restrict_pointers)
make_constraint_from_restrict (newvi, "GLOBAL_RESTRICT");
if (newvi->is_global_var && !in_ipa_mode)
make_copy_constraint (newvi, nonlocal_id);
} }
stats.total_vars++; VEC_free (fieldoff_s, heap, fieldstack);
return vi;
}
static unsigned int
create_variable_info_for (tree decl, const char *name)
{
varinfo_t vi = create_variable_info_for_1 (decl, name);
unsigned int id = vi->id;
insert_vi_for_tree (decl, vi);
/* Create initial constraints for globals. */
for (; vi; vi = vi->next)
{
if (!vi->may_have_pointers
|| !vi->is_global_var)
continue;
/* Mark global restrict qualified pointers. */
if ((POINTER_TYPE_P (TREE_TYPE (decl))
&& TYPE_RESTRICT (TREE_TYPE (decl)))
|| vi->only_restrict_pointers)
make_constraint_from_restrict (vi, "GLOBAL_RESTRICT");
/* For escaped variables initialize them from nonlocal. */
if (!in_ipa_mode
|| DECL_EXTERNAL (decl) || TREE_PUBLIC (decl))
make_copy_constraint (vi, nonlocal_id);
/* If this is a global variable with an initializer and we are in
IPA mode generate constraints for it. In non-IPA mode
the initializer from nonlocal is all we need. */
if (in_ipa_mode
&& DECL_INITIAL (decl))
{
VEC (ce_s, heap) *rhsc = NULL;
struct constraint_expr lhs, *rhsp;
unsigned i;
get_constraint_for (DECL_INITIAL (decl), &rhsc);
lhs.var = vi->id;
lhs.offset = 0;
lhs.type = SCALAR;
for (i = 0; VEC_iterate (ce_s, rhsc, i, rhsp); ++i)
process_constraint (new_constraint (lhs, *rhsp));
/* If this is a variable that escapes from the unit
the initializer escapes as well. */
if (DECL_EXTERNAL (decl) || TREE_PUBLIC (decl))
{
lhs.var = escaped_id;
lhs.offset = 0;
lhs.type = SCALAR;
for (i = 0; VEC_iterate (ce_s, rhsc, i, rhsp); ++i)
process_constraint (new_constraint (lhs, *rhsp));
}
VEC_free (ce_s, heap, rhsc);
} }
} }
else
vi->is_full_var = true;
VEC_free (fieldoff_s, heap, fieldstack);
return vi->id; return id;
} }
/* Print out the points-to solution for VAR to FILE. */ /* Print out the points-to solution for VAR to FILE. */
...@@ -5405,8 +5378,12 @@ intra_create_variable_infos (void) ...@@ -5405,8 +5378,12 @@ intra_create_variable_infos (void)
} }
for (p = get_vi_for_tree (t); p; p = p->next) for (p = get_vi_for_tree (t); p; p = p->next)
{
if (p->may_have_pointers) if (p->may_have_pointers)
make_constraint_from (p, nonlocal_id); make_constraint_from (p, nonlocal_id);
if (p->only_restrict_pointers)
make_constraint_from_restrict (p, "PARM_RESTRICT");
}
if (POINTER_TYPE_P (TREE_TYPE (t)) if (POINTER_TYPE_P (TREE_TYPE (t))
&& TYPE_RESTRICT (TREE_TYPE (t))) && TYPE_RESTRICT (TREE_TYPE (t)))
make_constraint_from_restrict (get_vi_for_tree (t), "PARM_RESTRICT"); make_constraint_from_restrict (get_vi_for_tree (t), "PARM_RESTRICT");
......
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