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 <rguent...@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; + }