This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

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;
+ }


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]