This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [PATCH] Simplify and fix restrict handling
On Mon, 17 Oct 2011, Richard Guenther wrote:
> On Fri, 14 Oct 2011, Richard Guenther wrote:
>
> >
> > This follows up Michas testcase where we fail to handle the
> > conservatively propagated restrict tags properly. The following
> > patch simplifies handling of restrict in the oracle and thus
> > only excludes NONLOCAL (as designed), but not ESCAPED from
> > conflict checking.
> >
> > Bootstrapped on x86_64-unknown-linux-gnu, testing in progress.
>
> So, after some regressions caused by this patch and some more thinking
> (about more possible issues) I concluded that we can simplify things
> even more by not making restrict vars point to NONLOCAL, but only
> to their tag (but marking that as global and able to have a points-to
> set). This way the special-casing of NONLOCAL vs. restrict can go
> away, and with it all its possible problems. Restrict is now
> similar to malloc () memory that escapes.
>
> Hopefully this one is without regressions ;)
>
> Bootstrap and regtest running on x86_64-unknown-linux-gnu.
And this is what I ended up applying after fixing constraints
again. For restrict qualified global (or parameter) pointers
we now generate
p = &RESTRICT_TAG
RESTRICT_TAG = NONLOCAL
if we implmenent the proposed RESTRICT_CAST expression from
p = RESTRICT_CAST <q, TAG>;
we'd need to generate
p = &TAG;
TAG = *q;
With this in place we can now disambiguate restrict qualified
pointers against global decls which wasn't possible before
(we invented the DECL_IS_RESTRICTED_P flag for this).
Bootstrapped and tested on x86_64-unknown-linux-gnu, applied to trunk.
Richard.
2011-10-17 Richard Guenther <rguenther@suse.de>
* tree-ssa-alias.h (struct pt_solution): Remove
vars_contains_restrict member.
(pt_solutions_same_restrict_base): Remove.
(pt_solution_set): Adjust.
* tree-ssa-alias.c (ptr_deref_may_alias_decl_p): Remove
vars_contains_restrict handling.
(dump_points_to_solution): Likewise.
(ptr_derefs_may_alias_p): Do not call pt_solutions_same_restrict_base.
* tree-ssa-structalias.c (struct variable_info): Remove is_restrict_var
field.
(new_var_info): Do not initialize it.
(ipa_escaped_pt): Adjust.
(make_constraint_from_restrict): Make the tag global.
(make_constraint_from_global_restrict): New function.
(make_constraint_from_heapvar): Remove.
(create_variable_info_for): Do not make restrict vars point
to NONLOCAL.
(intra_create_variable_infos): Likewise.
(find_what_var_points_to): Remove vars_contains_restrict handling.
(pt_solution_set): Adjust.
(pt_solution_ior_into): Likewise.
(pt_solutions_same_restrict_base): Remove.
(compute_points_to_sets): Do not test is_restrict_var.
* cfgexpand.c (update_alias_info_with_stack_vars): Adjust.
* gimple-pretty-print.c (pp_points_to_solution): Likewise.
* gcc.dg/torture/restrict-1.c: New testcase.
Index: gcc/tree-ssa-alias.c
===================================================================
*** gcc/tree-ssa-alias.c.orig 2011-10-17 16:56:54.000000000 +0200
--- gcc/tree-ssa-alias.c 2011-10-17 16:57:21.000000000 +0200
*************** ptr_deref_may_alias_decl_p (tree ptr, tr
*** 219,231 ****
if (!pi)
return true;
- /* If the decl can be used as a restrict tag and we have a restrict
- pointer and that pointers points-to set doesn't contain this decl
- then they can't alias. */
- if (DECL_RESTRICTED_P (decl)
- && pi->pt.vars_contains_restrict)
- return bitmap_bit_p (pi->pt.vars, DECL_PT_UID (decl));
-
return pt_solution_includes (&pi->pt, decl);
}
--- 219,224 ----
*************** ptr_derefs_may_alias_p (tree ptr1, tree
*** 316,326 ****
if (!pi1 || !pi2)
return true;
- /* If both pointers are restrict-qualified try to disambiguate
- with restrict information. */
- if (!pt_solutions_same_restrict_base (&pi1->pt, &pi2->pt))
- return false;
-
/* ??? This does not use TBAA to prune decls from the intersection
that not both pointers may access. */
return pt_solutions_intersect (&pi1->pt, &pi2->pt);
--- 309,314 ----
*************** dump_points_to_solution (FILE *file, str
*** 426,433 ****
dump_decl_set (file, pt->vars);
if (pt->vars_contains_global)
fprintf (file, " (includes global vars)");
- if (pt->vars_contains_restrict)
- fprintf (file, " (includes restrict tags)");
}
}
--- 414,419 ----
Index: gcc/tree-ssa-alias.h
===================================================================
*** gcc/tree-ssa-alias.h.orig 2011-10-17 16:56:54.000000000 +0200
--- gcc/tree-ssa-alias.h 2011-10-17 16:57:21.000000000 +0200
*************** struct GTY(()) pt_solution
*** 54,61 ****
/* Nonzero if the pt_vars bitmap includes a global variable. */
unsigned int vars_contains_global : 1;
- /* Nonzero if the pt_vars bitmap includes a restrict tag variable. */
- unsigned int vars_contains_restrict : 1;
/* Set of variables that this pointer may point to. */
bitmap vars;
--- 54,59 ----
*************** extern bool pt_solution_singleton_p (str
*** 130,139 ****
extern bool pt_solution_includes_global (struct pt_solution *);
extern bool pt_solution_includes (struct pt_solution *, const_tree);
extern bool pt_solutions_intersect (struct pt_solution *, struct pt_solution *);
- extern bool pt_solutions_same_restrict_base (struct pt_solution *,
- struct pt_solution *);
extern void pt_solution_reset (struct pt_solution *);
! extern void pt_solution_set (struct pt_solution *, bitmap, bool, bool);
extern void pt_solution_set_var (struct pt_solution *, tree);
extern void dump_pta_stats (FILE *);
--- 128,135 ----
extern bool pt_solution_includes_global (struct pt_solution *);
extern bool pt_solution_includes (struct pt_solution *, const_tree);
extern bool pt_solutions_intersect (struct pt_solution *, struct pt_solution *);
extern void pt_solution_reset (struct pt_solution *);
! extern void pt_solution_set (struct pt_solution *, bitmap, bool);
extern void pt_solution_set_var (struct pt_solution *, tree);
extern void dump_pta_stats (FILE *);
Index: gcc/tree-ssa-structalias.c
===================================================================
*** gcc/tree-ssa-structalias.c.orig 2011-10-17 16:56:54.000000000 +0200
--- gcc/tree-ssa-structalias.c 2011-10-17 17:08:28.000000000 +0200
*************** struct variable_info
*** 261,269 ****
/* True if this is a heap variable. */
unsigned int is_heap_var : 1;
- /* True if this is a variable tracking a restrict pointer source. */
- unsigned int is_restrict_var : 1;
-
/* True if this field may contain pointers. */
unsigned int may_have_pointers : 1;
--- 261,266 ----
*************** new_var_info (tree t, const char *name)
*** 350,356 ****
ret->is_unknown_size_var = false;
ret->is_full_var = (t == NULL_TREE);
ret->is_heap_var = false;
- ret->is_restrict_var = false;
ret->may_have_pointers = true;
ret->only_restrict_pointers = false;
ret->is_global_var = (t == NULL_TREE);
--- 347,352 ----
*************** make_heapvar (const char *name)
*** 3643,3672 ****
}
/* Create a new artificial heap variable with NAME and make a
! constraint from it to LHS. Return the created variable. */
static varinfo_t
! make_constraint_from_heapvar (varinfo_t lhs, const char *name)
{
varinfo_t vi = make_heapvar (name);
make_constraint_from (lhs, vi->id);
-
return vi;
}
/* Create a new artificial heap variable with NAME and make a
constraint from it to LHS. Set flags according to a tag used
! for tracking restrict pointers. */
! static void
! make_constraint_from_restrict (varinfo_t lhs, const char *name)
{
! varinfo_t vi;
! vi = make_constraint_from_heapvar (lhs, name);
! vi->is_restrict_var = 1;
! vi->is_global_var = 0;
! vi->is_special_var = 1;
! vi->may_have_pointers = 0;
}
/* In IPA mode there are varinfos for different aspects of reach
--- 3639,3668 ----
}
/* Create a new artificial heap variable with NAME and make a
! constraint from it to LHS. Set flags according to a tag used
! for tracking restrict pointers. */
static varinfo_t
! make_constraint_from_restrict (varinfo_t lhs, const char *name)
{
varinfo_t vi = make_heapvar (name);
+ vi->is_global_var = 1;
+ vi->may_have_pointers = 1;
make_constraint_from (lhs, vi->id);
return vi;
}
/* Create a new artificial heap variable with NAME and make a
constraint from it to LHS. Set flags according to a tag used
! for tracking restrict pointers and make the artificial heap
! point to global memory. */
! static varinfo_t
! make_constraint_from_global_restrict (varinfo_t lhs, const char *name)
{
! varinfo_t vi = make_constraint_from_restrict (lhs, name);
! make_copy_constraint (vi, nonlocal_id);
! return vi;
}
/* In IPA mode there are varinfos for different aspects of reach
*************** create_variable_info_for (tree decl, con
*** 5504,5516 ****
if ((POINTER_TYPE_P (TREE_TYPE (decl))
&& TYPE_RESTRICT (TREE_TYPE (decl)))
|| vi->only_restrict_pointers)
! make_constraint_from_restrict (vi, "GLOBAL_RESTRICT");
/* In non-IPA mode the initializer from nonlocal is all we need. */
if (!in_ipa_mode
|| DECL_HARD_REGISTER (decl))
make_copy_constraint (vi, nonlocal_id);
else
{
struct varpool_node *vnode = varpool_get_node (decl);
--- 5500,5517 ----
if ((POINTER_TYPE_P (TREE_TYPE (decl))
&& TYPE_RESTRICT (TREE_TYPE (decl)))
|| vi->only_restrict_pointers)
! {
! make_constraint_from_global_restrict (vi, "GLOBAL_RESTRICT");
! continue;
! }
/* In non-IPA mode the initializer from nonlocal is all we need. */
if (!in_ipa_mode
|| DECL_HARD_REGISTER (decl))
make_copy_constraint (vi, nonlocal_id);
+ /* In IPA mode parse the initializer and generate proper constraints
+ for it. */
else
{
struct varpool_node *vnode = varpool_get_node (decl);
*************** intra_create_variable_infos (void)
*** 5595,5601 ****
passed-by-reference argument. */
for (t = DECL_ARGUMENTS (current_function_decl); t; t = DECL_CHAIN (t))
{
! varinfo_t p;
/* For restrict qualified pointers to objects passed by
reference build a real representative for the pointed-to object.
--- 5596,5602 ----
passed-by-reference argument. */
for (t = DECL_ARGUMENTS (current_function_decl); t; t = DECL_CHAIN (t))
{
! varinfo_t p = get_vi_for_tree (t);
/* For restrict qualified pointers to objects passed by
reference build a real representative for the pointed-to object.
*************** intra_create_variable_infos (void)
*** 5610,5643 ****
DECL_EXTERNAL (heapvar) = 1;
vi = create_variable_info_for_1 (heapvar, "PARM_NOALIAS");
insert_vi_for_tree (heapvar, vi);
! lhsc.var = get_vi_for_tree (t)->id;
lhsc.type = SCALAR;
lhsc.offset = 0;
rhsc.var = vi->id;
rhsc.type = ADDRESSOF;
rhsc.offset = 0;
process_constraint (new_constraint (lhsc, rhsc));
- vi->is_restrict_var = 1;
for (; vi; vi = vi->next)
if (vi->may_have_pointers)
{
if (vi->only_restrict_pointers)
! make_constraint_from_restrict (vi, "GLOBAL_RESTRICT");
! make_copy_constraint (vi, nonlocal_id);
}
continue;
}
- for (p = get_vi_for_tree (t); p; p = p->next)
- {
- if (p->may_have_pointers)
- 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))
&& TYPE_RESTRICT (TREE_TYPE (t)))
! make_constraint_from_restrict (get_vi_for_tree (t), "PARM_RESTRICT");
}
/* Add a constraint for a result decl that is passed by reference. */
--- 5611,5647 ----
DECL_EXTERNAL (heapvar) = 1;
vi = create_variable_info_for_1 (heapvar, "PARM_NOALIAS");
insert_vi_for_tree (heapvar, vi);
! lhsc.var = p->id;
lhsc.type = SCALAR;
lhsc.offset = 0;
rhsc.var = vi->id;
rhsc.type = ADDRESSOF;
rhsc.offset = 0;
process_constraint (new_constraint (lhsc, rhsc));
for (; vi; vi = vi->next)
if (vi->may_have_pointers)
{
if (vi->only_restrict_pointers)
! make_constraint_from_global_restrict (vi, "GLOBAL_RESTRICT");
! else
! make_copy_constraint (vi, nonlocal_id);
}
continue;
}
if (POINTER_TYPE_P (TREE_TYPE (t))
&& TYPE_RESTRICT (TREE_TYPE (t)))
! make_constraint_from_global_restrict (p, "PARM_RESTRICT");
! else
! {
! for (; p; p = p->next)
! {
! if (p->only_restrict_pointers)
! make_constraint_from_global_restrict (p, "PARM_RESTRICT");
! else if (p->may_have_pointers)
! make_constraint_from (p, nonlocal_id);
! }
! }
}
/* Add a constraint for a result decl that is passed by reference. */
*************** find_what_var_points_to (varinfo_t orig_
*** 5813,5827 ****
|| vi->id == integer_id)
pt->anything = 1;
}
- if (vi->is_restrict_var)
- pt->vars_contains_restrict = true;
}
/* Instead of doing extra work, simply do not create
elaborate points-to information for pt_anything pointers. */
! if (pt->anything
! && (orig_vi->is_artificial_var
! || !pt->vars_contains_restrict))
return;
/* Share the final set of variables when possible. */
--- 5817,5827 ----
|| vi->id == integer_id)
pt->anything = 1;
}
}
/* Instead of doing extra work, simply do not create
elaborate points-to information for pt_anything pointers. */
! if (pt->anything)
return;
/* Share the final set of variables when possible. */
*************** pt_solution_reset (struct pt_solution *p
*** 5912,5924 ****
it contains restrict tag variables. */
void
! pt_solution_set (struct pt_solution *pt, bitmap vars,
! bool vars_contains_global, bool vars_contains_restrict)
{
memset (pt, 0, sizeof (struct pt_solution));
pt->vars = vars;
pt->vars_contains_global = vars_contains_global;
- pt->vars_contains_restrict = vars_contains_restrict;
}
/* Set the points-to solution *PT to point only to the variable VAR. */
--- 5912,5922 ----
it contains restrict tag variables. */
void
! pt_solution_set (struct pt_solution *pt, bitmap vars, bool vars_contains_global)
{
memset (pt, 0, sizeof (struct pt_solution));
pt->vars = vars;
pt->vars_contains_global = vars_contains_global;
}
/* Set the points-to solution *PT to point only to the variable VAR. */
*************** pt_solution_ior_into (struct pt_solution
*** 5953,5959 ****
dest->ipa_escaped |= src->ipa_escaped;
dest->null |= src->null;
dest->vars_contains_global |= src->vars_contains_global;
- dest->vars_contains_restrict |= src->vars_contains_restrict;
if (!src->vars)
return;
--- 5951,5956 ----
*************** pt_solutions_intersect (struct pt_soluti
*** 6141,6167 ****
return res;
}
- /* Return true if both points-to solutions PT1 and PT2 for two restrict
- qualified pointers are possibly based on the same pointer. */
-
- bool
- pt_solutions_same_restrict_base (struct pt_solution *pt1,
- struct pt_solution *pt2)
- {
- /* If we deal with points-to solutions of two restrict qualified
- pointers solely rely on the pointed-to variable bitmap intersection.
- For two pointers that are based on each other the bitmaps will
- intersect. */
- if (pt1->vars_contains_restrict
- && pt2->vars_contains_restrict)
- {
- gcc_assert (pt1->vars && pt2->vars);
- return bitmap_intersect_p (pt1->vars, pt2->vars);
- }
-
- return true;
- }
-
/* Dump points-to information to OUTFILE. */
--- 6138,6143 ----
*************** compute_points_to_sets (void)
*** 6574,6580 ****
/* Mark escaped HEAP variables as global. */
FOR_EACH_VEC_ELT (varinfo_t, varmap, i, vi)
if (vi->is_heap_var
- && !vi->is_restrict_var
&& !vi->is_global_var)
DECL_EXTERNAL (vi->decl) = vi->is_global_var
= pt_solution_includes (&cfun->gimple_df->escaped, vi->decl);
--- 6550,6555 ----
*************** gate_ipa_pta (void)
*** 6794,6800 ****
/* IPA PTA solutions for ESCAPED. */
struct pt_solution ipa_escaped_pt
! = { true, false, false, false, false, false, false, NULL };
/* Associate node with varinfo DATA. Worker for
cgraph_for_node_and_aliases. */
--- 6769,6775 ----
/* IPA PTA solutions for ESCAPED. */
struct pt_solution ipa_escaped_pt
! = { true, false, false, false, false, false, NULL };
/* Associate node with varinfo DATA. Worker for
cgraph_for_node_and_aliases. */
Index: gcc/cfgexpand.c
===================================================================
*** gcc/cfgexpand.c.orig 2011-10-17 16:56:54.000000000 +0200
--- gcc/cfgexpand.c 2011-10-17 16:57:21.000000000 +0200
*************** update_alias_info_with_stack_vars (void)
*** 530,536 ****
/* Make the SSA name point to all partition members. */
pi = get_ptr_info (name);
! pt_solution_set (&pi->pt, part, false, false);
}
/* Make all points-to sets that contain one member of a partition
--- 530,536 ----
/* Make the SSA name point to all partition members. */
pi = get_ptr_info (name);
! pt_solution_set (&pi->pt, part, false);
}
/* Make all points-to sets that contain one member of a partition
Index: gcc/gimple-pretty-print.c
===================================================================
*** gcc/gimple-pretty-print.c.orig 2011-10-17 16:56:54.000000000 +0200
--- gcc/gimple-pretty-print.c 2011-10-17 16:57:21.000000000 +0200
*************** pp_points_to_solution (pretty_printer *b
*** 610,617 ****
pp_character (buffer, '}');
if (pt->vars_contains_global)
pp_string (buffer, " (glob)");
- if (pt->vars_contains_restrict)
- pp_string (buffer, " (restr)");
}
}
--- 610,615 ----
Index: gcc/testsuite/gcc.dg/torture/restrict-1.c
===================================================================
*** /dev/null 1970-01-01 00:00:00.000000000 +0000
--- gcc/testsuite/gcc.dg/torture/restrict-1.c 2011-10-17 17:07:17.000000000 +0200
***************
*** 0 ****
--- 1,16 ----
+ /* { dg-do run } */
+
+ extern void abort (void);
+ void __attribute__((noinline,noclone))
+ foo (int ** __restrict__ p, int ** __restrict__ q)
+ {
+ **p = **q;
+ }
+ int main()
+ {
+ int x = 0, y = 1, *i = &x, *j = &y;
+ foo (&i, &j);
+ if (x != 1)
+ abort ();
+ return 0;
+ }