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]

[PATCH][RFC] Take 2: Re-implement restrict support


On top of the patch to rip out the old restrict implementation this
is take 2 in re-implementing restrict support to be integrated with
PTA and the alias-oracle.
(http://gcc.gnu.org/ml/gcc-patches/2009-06/msg01885.html)

Compared to the first try this does not apply filtering of NONLOCAL
or ANYTHING but instead defers everything to the alias-oracle which
queries restrict information (which is still encoded in the points-to
bitmap) using the new pt_solutions_same_restrict_base from the
ptr_derefs_may_alias_p disambiguator.

The main features remain the same.  We use the points-to analysis
propagator to compute the 'based on' property, encoding it in
restrict tags pointed to.  Sources of restrict tags include
struct fields and the implementation should be more forgiving to
not 100% standard conforming code (see the testcase added by
the patch removing the old implementation, PR38212).  The new
implementation also handles merging two restrict pointers
correctly, so restrict1 can be disambiguated against
flag ? restrict2 : restrict3 which was not possible before.

Bootstrapped and tested on x86_64-unknown-linux-gnu without any
regressions / false progressions this time.

Comments?  I'd like to get an ack on this (and the removal of
the old implementation), even though I can technically approve
the patch myself.

The next step is to re-work how we deal with the Fortran
parameters-do-not-alias fact - which we do not handle correctly
right now.  The plan is to rip out the -fargument-noalias-* stuff
and instead teach the frontend to properly use restrict qualification
on arguments.  A slight middle-end semantic change for restrict
and decl-by-reference parms should improve things some more here.

Thanks,
Richard.


2009-06-24  Richard Guenther  <rguenther@suse.de>

	PR middle-end/14187
	* tree-ssa-alias.h (struct pt_solution): Add vars_contains_restrict
	flag.
	(pt_solutions_same_restrict_base): Declare.
	* tree-ssa-structalias.c (struct variable_info): Add is_restrict_var
	flag.
	(new_var_info): Initialize is_global_var properly for SSA_NAMEs.
	(make_constraint_from, make_copy_constraint): Move earlier.
	(make_constraint_from_heapvar): New function.
	(make_constraint_from_restrict): Likewise.
	(handle_lhs_call): Use it.
	(find_func_aliases): Use it to track conversions to restrict
	qualified pointers.
	(struct fieldoff): Add only_restrict_pointers flag.
	(push_fields_onto_fieldstack): Initialize it.
	(create_variable_info_for): Track global restrict qualified pointers.
	(intra_create_variable_infos): Use make_constraint_from_heapvar.
	Track restrict qualified pointer arguments.
	(set_uids_in_ptset): Use varinfo is_global_var flag.
	(find_what_var_points_to): Set the vars_contains_restrict flag.
	Always create the points-to solution for sets including restrict tags.
	(pt_solutions_same_restrict_base): New function.
	* tree-ssa-alias.c (ptr_derefs_may_alias_p): For two restrict
	qualified pointers use pt_solutions_same_restrict_base as
	additional source for disambiguation.

	* gcc.dg/tree-ssa/restrict-1.c: New testcase.
	* gcc.dg/tree-ssa/restrict-2.c: Likewise.
	* gcc.dg/tree-ssa/restrict-3.c: Likewise.
	* gcc.c-torture/execute/20090623-1.c: Likewise.
	* gcc.dg/tree-ssa/ldist-13.c: Likewise.
	* gcc.dg/tree-ssa/ldist-14.c: Likewise.

Index: trunk/gcc/tree-ssa-structalias.c
===================================================================
*** trunk.orig/gcc/tree-ssa-structalias.c	2009-06-24 15:38:15.000000000 +0200
--- trunk/gcc/tree-ssa-structalias.c	2009-06-24 15:51:48.000000000 +0200
*************** struct variable_info
*** 211,230 ****
  
    /* True if this is a variable created by the constraint analysis, such as
       heap variables and constraints we had to break up.  */
!   unsigned int is_artificial_var:1;
  
    /* True if this is a special variable whose solution set should not be
       changed.  */
!   unsigned int is_special_var:1;
  
    /* True for variables whose size is not known or variable.  */
!   unsigned int is_unknown_size_var:1;
  
    /* True for (sub-)fields that represent a whole variable.  */
    unsigned int is_full_var : 1;
  
    /* True if this is a heap variable.  */
!   unsigned int is_heap_var:1;
  
    /* True if this field may contain pointers.  */
    unsigned int may_have_pointers : 1;
--- 211,233 ----
  
    /* True if this is a variable created by the constraint analysis, such as
       heap variables and constraints we had to break up.  */
!   unsigned int is_artificial_var : 1;
  
    /* True if this is a special variable whose solution set should not be
       changed.  */
!   unsigned int is_special_var : 1;
  
    /* True for variables whose size is not known or variable.  */
!   unsigned int is_unknown_size_var : 1;
  
    /* True for (sub-)fields that represent a whole variable.  */
    unsigned int is_full_var : 1;
  
    /* 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;
*************** new_var_info (tree t, const char *name)
*** 339,345 ****
    ret->is_special_var = false;
    ret->is_unknown_size_var = false;
    ret->may_have_pointers = true;
!   ret->is_global_var = true;
    if (t && DECL_P (t))
      ret->is_global_var = is_global_var (t);
    ret->solution = BITMAP_ALLOC (&pta_obstack);
--- 342,348 ----
    ret->is_special_var = false;
    ret->is_unknown_size_var = false;
    ret->may_have_pointers = true;
!   ret->is_global_var = (t == NULL_TREE);
    if (t && DECL_P (t))
      ret->is_global_var = is_global_var (t);
    ret->solution = BITMAP_ALLOC (&pta_obstack);
*************** make_constraint_to (unsigned id, tree op
*** 3324,3329 ****
--- 3327,3366 ----
    VEC_free (ce_s, heap, rhsc);
  }
  
+ /* Create a constraint ID = &FROM.  */
+ 
+ static void
+ make_constraint_from (varinfo_t vi, int from)
+ {
+   struct constraint_expr lhs, rhs;
+ 
+   lhs.var = vi->id;
+   lhs.offset = 0;
+   lhs.type = SCALAR;
+ 
+   rhs.var = from;
+   rhs.offset = 0;
+   rhs.type = ADDRESSOF;
+   process_constraint (new_constraint (lhs, rhs));
+ }
+ 
+ /* Create a constraint ID = FROM.  */
+ 
+ static void
+ make_copy_constraint (varinfo_t vi, int from)
+ {
+   struct constraint_expr lhs, rhs;
+ 
+   lhs.var = vi->id;
+   lhs.offset = 0;
+   lhs.type = SCALAR;
+ 
+   rhs.var = from;
+   rhs.offset = 0;
+   rhs.type = SCALAR;
+   process_constraint (new_constraint (lhs, rhs));
+ }
+ 
  /* Make constraints necessary to make OP escape.  */
  
  static void
*************** make_escape_constraint (tree op)
*** 3332,3337 ****
--- 3369,3429 ----
    make_constraint_to (escaped_id, op);
  }
  
+ /* 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;
+   tree heapvar = heapvar_lookup (lhs->decl);
+ 
+   if (heapvar == NULL_TREE)
+     {
+       var_ann_t ann;
+       heapvar = create_tmp_var_raw (ptr_type_node, name);
+       DECL_EXTERNAL (heapvar) = 1;
+ 
+       heapvar_insert (lhs->decl, heapvar);
+ 
+       ann = get_var_ann (heapvar);
+       ann->is_heapvar = 1;
+     }
+ 
+   /* For global vars we need to add a heapvar to the list of referenced
+      vars of a different function than it was created for originally.  */
+   if (gimple_referenced_vars (cfun))
+     add_referenced_var (heapvar);
+ 
+   vi = new_var_info (heapvar, name);
+   vi->is_artificial_var = true;
+   vi->is_heap_var = true;
+   vi->is_unknown_size_var = true;
+   vi->fullsize = ~0;
+   vi->size = ~0;
+   vi->is_full_var = true;
+   insert_vi_for_tree (heapvar, vi);
+ 
+   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;
+ }
+ 
  /* For non-IPA mode, generate constraints necessary for a call on the
     RHS.  */
  
*************** static void
*** 3386,3424 ****
  handle_lhs_call (tree lhs, int flags, VEC(ce_s, heap) *rhsc)
  {
    VEC(ce_s, heap) *lhsc = NULL;
-   unsigned int j;
-   struct constraint_expr *lhsp;
  
    get_constraint_for (lhs, &lhsc);
  
    if (flags & ECF_MALLOC)
      {
-       struct constraint_expr rhsc;
-       tree heapvar = heapvar_lookup (lhs);
        varinfo_t vi;
! 
!       if (heapvar == NULL)
! 	{
! 	  heapvar = create_tmp_var_raw (ptr_type_node, "HEAP");
! 	  DECL_EXTERNAL (heapvar) = 1;
! 	  get_var_ann (heapvar)->is_heapvar = 1;
! 	  if (gimple_referenced_vars (cfun))
! 	    add_referenced_var (heapvar);
! 	  heapvar_insert (lhs, heapvar);
! 	}
! 
!       rhsc.var = create_variable_info_for (heapvar,
! 					   alias_get_name (heapvar));
!       vi = get_varinfo (rhsc.var);
!       vi->is_artificial_var = 1;
!       vi->is_heap_var = 1;
!       vi->is_unknown_size_var = true;
!       vi->fullsize = ~0;
!       vi->size = ~0;
!       rhsc.type = ADDRESSOF;
!       rhsc.offset = 0;
!       for (j = 0; VEC_iterate (ce_s, lhsc, j, lhsp); j++)
! 	process_constraint (new_constraint (*lhsp, rhsc));
      }
    else if (VEC_length (ce_s, rhsc) > 0)
      {
--- 3478,3491 ----
  handle_lhs_call (tree lhs, int flags, VEC(ce_s, heap) *rhsc)
  {
    VEC(ce_s, heap) *lhsc = NULL;
  
    get_constraint_for (lhs, &lhsc);
  
    if (flags & ECF_MALLOC)
      {
        varinfo_t vi;
!       vi = make_constraint_from_heapvar (get_vi_for_tree (lhs), "HEAP");
!       make_copy_constraint (vi, nonlocal_id);
      }
    else if (VEC_length (ce_s, rhsc) > 0)
      {
*************** find_func_aliases (gimple origt)
*** 3838,3843 ****
--- 3905,3919 ----
  	  && DECL_P (lhsop)
  	  && is_global_var (lhsop))
  	make_escape_constraint (rhsop);
+       /* If this is a conversion of a non-restrict pointer to a
+ 	 restrict pointer track it with a new heapvar.  */
+       else if (gimple_assign_cast_p (t)
+ 	       && POINTER_TYPE_P (TREE_TYPE (rhsop))
+ 	       && POINTER_TYPE_P (TREE_TYPE (lhsop))
+ 	       && !TYPE_RESTRICT (TREE_TYPE (rhsop))
+ 	       && TYPE_RESTRICT (TREE_TYPE (lhsop)))
+ 	make_constraint_from_restrict (get_vi_for_tree (lhsop),
+ 				       "CAST_RESTRICT");
      }
    /* For conversions of pointers to non-pointers the pointer escapes.  */
    else if (gimple_assign_cast_p (t)
*************** struct fieldoff
*** 4029,4034 ****
--- 4105,4112 ----
    unsigned has_unknown_size : 1;
  
    unsigned may_have_pointers : 1;
+ 
+   unsigned only_restrict_pointers : 1;
  };
  typedef struct fieldoff fieldoff_s;
  
*************** push_fields_onto_fieldstack (tree type,
*** 4167,4172 ****
--- 4245,4254 ----
  		else
  		  pair->size = -1;
  		pair->may_have_pointers = could_have_pointers (field);
+ 		pair->only_restrict_pointers
+ 		  = (!has_unknown_size
+ 		     && POINTER_TYPE_P (TREE_TYPE (field))
+ 		     && TYPE_RESTRICT (TREE_TYPE (field)));
  		count++;
  	      }
  	  }
*************** push_fields_onto_fieldstack (tree type,
*** 4177,4216 ****
    return count;
  }
  
- /* Create a constraint ID = &FROM.  */
- 
- static void
- make_constraint_from (varinfo_t vi, int from)
- {
-   struct constraint_expr lhs, rhs;
- 
-   lhs.var = vi->id;
-   lhs.offset = 0;
-   lhs.type = SCALAR;
- 
-   rhs.var = from;
-   rhs.offset = 0;
-   rhs.type = ADDRESSOF;
-   process_constraint (new_constraint (lhs, rhs));
- }
- 
- /* Create a constraint ID = FROM.  */
- 
- static void
- make_copy_constraint (varinfo_t vi, int from)
- {
-   struct constraint_expr lhs, rhs;
- 
-   lhs.var = vi->id;
-   lhs.offset = 0;
-   lhs.type = SCALAR;
- 
-   rhs.var = from;
-   rhs.offset = 0;
-   rhs.type = SCALAR;
-   process_constraint (new_constraint (lhs, rhs));
- }
- 
  /* Count the number of arguments DECL has, and set IS_VARARGS to true
     if it is a varargs function.  */
  
--- 4259,4264 ----
*************** create_variable_info_for (tree decl, con
*** 4358,4374 ****
    varinfo_t vi;
    tree decl_type = TREE_TYPE (decl);
    tree declsize = DECL_P (decl) ? DECL_SIZE (decl) : TYPE_SIZE (decl_type);
-   bool is_global = DECL_P (decl) ? is_global_var (decl) : false;
    VEC (fieldoff_s,heap) *fieldstack = NULL;
  
    if (TREE_CODE (decl) == FUNCTION_DECL && in_ipa_mode)
      return create_function_info_for (decl, name);
  
!   if (var_can_have_subvars (decl) && use_field_sensitive
!       && (!var_ann (decl)
! 	  || var_ann (decl)->noalias_state == 0)
!       && (!var_ann (decl)
! 	  || !var_ann (decl)->is_heapvar))
      push_fields_onto_fieldstack (decl_type, &fieldstack, 0);
  
    /* If the variable doesn't have subvars, we may end up needing to
--- 4406,4417 ----
    varinfo_t vi;
    tree decl_type = TREE_TYPE (decl);
    tree declsize = DECL_P (decl) ? DECL_SIZE (decl) : TYPE_SIZE (decl_type);
    VEC (fieldoff_s,heap) *fieldstack = NULL;
  
    if (TREE_CODE (decl) == FUNCTION_DECL && in_ipa_mode)
      return create_function_info_for (decl, name);
  
!   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
*************** create_variable_info_for (tree decl, con
*** 4391,4404 ****
      }
  
    insert_vi_for_tree (vi->decl, vi);
!   if (is_global && (!flag_whole_program || !in_ipa_mode)
        && vi->may_have_pointers)
      {
!       if (var_ann (decl)
! 	  && var_ann (decl)->noalias_state == NO_ALIAS_ANYTHING)
! 	make_constraint_from (vi, vi->id);
!       else
! 	make_copy_constraint (vi, nonlocal_id);
      }
  
    stats.total_vars++;
--- 4434,4447 ----
      }
  
    insert_vi_for_tree (vi->decl, vi);
!   if (vi->is_global_var
!       && (!flag_whole_program || !in_ipa_mode)
        && vi->may_have_pointers)
      {
!       if (POINTER_TYPE_P (TREE_TYPE (decl))
! 	  && TYPE_RESTRICT (TREE_TYPE (decl)))
! 	make_constraint_from_restrict (vi, "GLOBAL_RESTRICT");
!       make_copy_constraint (vi, nonlocal_id);
      }
  
    stats.total_vars++;
*************** create_variable_info_for (tree decl, con
*** 4475,4483 ****
  	  newvi->fullsize = vi->fullsize;
  	  newvi->may_have_pointers = fo->may_have_pointers;
  	  insert_into_field_list (vi, newvi);
! 	  if (is_global && (!flag_whole_program || !in_ipa_mode)
  	      && newvi->may_have_pointers)
! 	    make_copy_constraint (newvi, nonlocal_id);
  
  	  stats.total_vars++;
  	}
--- 4518,4531 ----
  	  newvi->fullsize = vi->fullsize;
  	  newvi->may_have_pointers = fo->may_have_pointers;
  	  insert_into_field_list (vi, newvi);
! 	  if (newvi->is_global_var
! 	      && (!flag_whole_program || !in_ipa_mode)
  	      && newvi->may_have_pointers)
! 	    {
! 	       if (fo->only_restrict_pointers)
! 		 make_constraint_from_restrict (newvi, "GLOBAL_RESTRICT");
! 	       make_copy_constraint (newvi, nonlocal_id);
! 	    }
  
  	  stats.total_vars++;
  	}
*************** static void
*** 4530,4536 ****
  intra_create_variable_infos (void)
  {
    tree t;
-   struct constraint_expr lhs, rhs;
  
    /* For each incoming pointer argument arg, create the constraint ARG
       = NONLOCAL or a dummy variable if flag_argument_noalias is set.  */
--- 4578,4583 ----
*************** intra_create_variable_infos (void)
*** 4548,4597 ****
        if (POINTER_TYPE_P (TREE_TYPE (t)) && flag_argument_noalias > 0)
  	{
  	  varinfo_t vi;
! 	  tree heapvar = heapvar_lookup (t);
! 
! 	  lhs.offset = 0;
! 	  lhs.type = SCALAR;
! 	  lhs.var  = get_vi_for_tree (t)->id;
  
! 	  if (heapvar == NULL_TREE)
  	    {
! 	      var_ann_t ann;
! 	      heapvar = create_tmp_var_raw (ptr_type_node,
! 					    "PARM_NOALIAS");
! 	      DECL_EXTERNAL (heapvar) = 1;
! 	      if (gimple_referenced_vars (cfun))
! 		add_referenced_var (heapvar);
! 
! 	      heapvar_insert (t, heapvar);
! 
! 	      ann = get_var_ann (heapvar);
! 	      ann->is_heapvar = 1;
! 	      if (flag_argument_noalias == 1)
! 		ann->noalias_state = NO_ALIAS;
! 	      else if (flag_argument_noalias == 2)
! 		ann->noalias_state = NO_ALIAS_GLOBAL;
! 	      else if (flag_argument_noalias == 3)
! 		ann->noalias_state = NO_ALIAS_ANYTHING;
! 	      else
! 		gcc_unreachable ();
  	    }
! 
! 	  vi = get_vi_for_tree (heapvar);
! 	  vi->is_artificial_var = 1;
! 	  vi->is_heap_var = 1;
! 	  vi->is_unknown_size_var = true;
! 	  vi->fullsize = ~0;
! 	  vi->size = ~0;
! 	  rhs.var = vi->id;
! 	  rhs.type = ADDRESSOF;
! 	  rhs.offset = 0;
! 	  for (p = get_varinfo (lhs.var); p; p = p->next)
  	    {
! 	      struct constraint_expr temp = lhs;
! 	      temp.var = p->id;
! 	      process_constraint (new_constraint (temp, rhs));
  	    }
  	}
        else
  	{
--- 4595,4622 ----
        if (POINTER_TYPE_P (TREE_TYPE (t)) && flag_argument_noalias > 0)
  	{
  	  varinfo_t vi;
! 	  var_ann_t ann;
  
! 	  vi = make_constraint_from_heapvar (get_vi_for_tree (t),
! 					     "PARM_NOALIAS");
! 	  ann = get_var_ann (vi->decl);
! 	  if (flag_argument_noalias == 1)
  	    {
! 	      ann->noalias_state = NO_ALIAS;
! 	      make_copy_constraint (vi, nonlocal_id);
  	    }
! 	  else if (flag_argument_noalias == 2)
  	    {
! 	      ann->noalias_state = NO_ALIAS_GLOBAL;
! 	      make_constraint_from (vi, vi->id);
  	    }
+ 	  else if (flag_argument_noalias == 3)
+ 	    {
+ 	      ann->noalias_state = NO_ALIAS_ANYTHING;
+ 	      make_constraint_from (vi, vi->id);
+ 	    }
+ 	  else
+ 	    gcc_unreachable ();
  	}
        else
  	{
*************** intra_create_variable_infos (void)
*** 4600,4605 ****
--- 4625,4633 ----
  	  for (p = arg_vi; p; p = p->next)
  	    make_constraint_from (p, nonlocal_id);
  	}
+       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.  */
*************** set_uids_in_ptset (bitmap into, bitmap f
*** 4716,4722 ****
  	  /* Add the decl to the points-to set.  Note that the points-to
  	     set contains global variables.  */
  	  bitmap_set_bit (into, DECL_UID (vi->decl));
! 	  if (is_global_var (vi->decl))
  	    pt->vars_contains_global = true;
  	}
      }
--- 4744,4750 ----
  	  /* Add the decl to the points-to set.  Note that the points-to
  	     set contains global variables.  */
  	  bitmap_set_bit (into, DECL_UID (vi->decl));
! 	  if (vi->is_global_var)
  	    pt->vars_contains_global = true;
  	}
      }
*************** find_what_var_points_to (varinfo_t vi, s
*** 4765,4775 ****
  		   || 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.  */
--- 4793,4807 ----
  		   || 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
!       && (vi->is_artificial_var
! 	  || !pt->vars_contains_restrict))
      return;
  
    /* Share the final set of variables when possible.  */
*************** pt_solutions_intersect (struct pt_soluti
*** 4979,4984 ****
--- 5011,5037 ----
    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.  */
  
Index: trunk/gcc/testsuite/gcc.dg/tree-ssa/restrict-1.c
===================================================================
*** /dev/null	1970-01-01 00:00:00.000000000 +0000
--- trunk/gcc/testsuite/gcc.dg/tree-ssa/restrict-1.c	2009-06-24 15:43:10.000000000 +0200
***************
*** 0 ****
--- 1,20 ----
+ /* { dg-do link } */
+ /* { dg-options "-O -fno-strict-aliasing -fdump-tree-optimized" } */
+ 
+ extern void link_error (void);
+ 
+ void bar0 (int * __restrict__ arr1, int * __restrict__ arr2)
+ {
+   arr1[0] = 1;
+   arr2[0] = 1;
+   if (arr1[0] != 1)
+     link_error ();
+ }
+ 
+ int main()
+ {
+   return 0;
+ }
+ 
+ /* { dg-final { scan-tree-dump-not "link_error" "optimized" } } */
+ /* { dg-final { cleanup-tree-dump "optimized" } } */
Index: trunk/gcc/testsuite/gcc.dg/tree-ssa/restrict-2.c
===================================================================
*** /dev/null	1970-01-01 00:00:00.000000000 +0000
--- trunk/gcc/testsuite/gcc.dg/tree-ssa/restrict-2.c	2009-06-24 15:43:10.000000000 +0200
***************
*** 0 ****
--- 1,14 ----
+ /* { dg-do compile } */
+ /* { dg-options "-O -fno-strict-aliasing -fdump-tree-lim-details" } */
+ 
+ void foo (float * __restrict__ a, float * __restrict__ b, int n, int j)
+ {
+   int i;
+   for(i = 0; i < n; ++i)
+     a[i] = (b[j+50] + b[j-50]) * 0.5f;
+ }
+ 
+ /* We should move the RHS of the store out of the loop.  */
+ 
+ /* { dg-final { scan-tree-dump-times "Moving statement" 11 "lim" } } */
+ /* { dg-final { cleanup-tree-dump "lim" } } */
Index: trunk/gcc/testsuite/gcc.dg/tree-ssa/restrict-3.c
===================================================================
*** /dev/null	1970-01-01 00:00:00.000000000 +0000
--- trunk/gcc/testsuite/gcc.dg/tree-ssa/restrict-3.c	2009-06-24 15:43:10.000000000 +0200
***************
*** 0 ****
--- 1,18 ----
+ /* { dg-do compile } */
+ /* { dg-options "-O -fno-strict-aliasing -fdump-tree-lim-details" } */
+ 
+ void f(int * __restrict__ r,
+        int a[__restrict__ 16][16],
+        int b[__restrict__ 16][16],
+        int i, int j)
+ {
+   int x;
+   *r = 0;
+   for (x = 1; x < 16; ++x)
+     *r = *r + a[i][x] * b[x][j];
+ }
+ 
+ /* We should apply store motion to the store to *r.  */
+ 
+ /* { dg-final { scan-tree-dump "Executing store motion of \\\*r" "lim" } } */
+ /* { dg-final { cleanup-tree-dump "lim" } } */
Index: trunk/gcc/testsuite/gcc.c-torture/execute/20090623-1.c
===================================================================
*** /dev/null	1970-01-01 00:00:00.000000000 +0000
--- trunk/gcc/testsuite/gcc.c-torture/execute/20090623-1.c	2009-06-24 15:43:10.000000000 +0200
***************
*** 0 ****
--- 1,18 ----
+ int * __restrict__ x;
+ 
+ int foo (int y)
+ {
+   *x = y;
+   return *x;
+ }
+ 
+ extern void abort (void);
+ 
+ int main()
+ {
+   int i = 0;
+   x = &i;
+   if (foo(1) != 1)
+     abort ();
+   return 0;
+ }
Index: trunk/gcc/testsuite/gcc.dg/tree-ssa/ldist-13.c
===================================================================
*** /dev/null	1970-01-01 00:00:00.000000000 +0000
--- trunk/gcc/testsuite/gcc.dg/tree-ssa/ldist-13.c	2009-06-24 15:43:10.000000000 +0200
***************
*** 0 ****
--- 1,22 ----
+ /* { dg-do compile } */
+ /* { dg-options "-O2 -ftree-loop-distribution -fdump-tree-ldist-details" } */
+ 
+ float * __restrict__ x;
+ float * __restrict__ y;
+ 
+ float foo (int n)
+ {
+   int i;
+   float tmp = 0.0;
+   for (i = 0; i < n; ++i)
+     {
+       x[i] = 0.0;
+       tmp += y[i];
+     }
+   return tmp;
+ }
+ 
+ /* We should apply loop distribution.  */
+ 
+ /* { dg-final { scan-tree-dump "Loop 1 distributed: split to 2 loops" "ldist" } } */
+ /* { dg-final { cleanup-tree-dump "ldist" } } */
Index: trunk/gcc/testsuite/gcc.dg/tree-ssa/ldist-14.c
===================================================================
*** /dev/null	1970-01-01 00:00:00.000000000 +0000
--- trunk/gcc/testsuite/gcc.dg/tree-ssa/ldist-14.c	2009-06-24 15:43:10.000000000 +0200
***************
*** 0 ****
--- 1,27 ----
+ /* { dg-do compile } */
+ /* { dg-options "-O2 -fno-strict-aliasing -ftree-loop-distribution -fdump-tree-ldist-details" } */
+ 
+ struct desc {
+   int i;
+   void * __restrict__ data;
+   int j;
+ } a, b;
+ 
+ float foo (int n)
+ {
+   int i;
+   float * __restrict__ x, * __restrict__ y, tmp = 0.0;
+   x = (float * __restrict__)a.data;
+   y = (float * __restrict__)b.data;
+   for (i = 0; i < n; ++i)
+     {
+       x[i] = 0.0;
+       tmp += y[i];
+     }
+   return tmp;
+ }
+ 
+ /* We should apply loop distribution.  */
+ 
+ /* { dg-final { scan-tree-dump "Loop 1 distributed: split to 2 loops" "ldist" } } */
+ /* { dg-final { cleanup-tree-dump "ldist" } } */
Index: trunk/gcc/tree-ssa-alias.c
===================================================================
*** trunk.orig/gcc/tree-ssa-alias.c	2009-06-24 15:38:15.000000000 +0200
--- trunk/gcc/tree-ssa-alias.c	2009-06-24 15:43:10.000000000 +0200
*************** ptr_derefs_may_alias_p (tree ptr1, tree
*** 273,278 ****
--- 273,285 ----
    if (!pi1 || !pi2)
      return true;
  
+   /* If both pointers are restrict-qualified try to disambiguate
+      with restrict information.  */
+   if (TYPE_RESTRICT (TREE_TYPE (ptr1))
+       && TYPE_RESTRICT (TREE_TYPE (ptr2))
+       && !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);
Index: trunk/gcc/tree-ssa-alias.h
===================================================================
*** trunk.orig/gcc/tree-ssa-alias.h	2009-06-24 15:38:15.000000000 +0200
--- trunk/gcc/tree-ssa-alias.h	2009-06-24 15:43:10.000000000 +0200
*************** struct GTY(()) pt_solution
*** 49,54 ****
--- 49,57 ----
    /* 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;
  };
*************** extern void delete_alias_heapvars (void)
*** 115,120 ****
--- 118,125 ----
  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 dump_pta_stats (FILE *);
  


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