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] Re-implement restrict support


This patch, supposed to be applied on-top of a patch ripping out
the TBAA-based restrict support, re-implements restrict as part
of pointer analysis.

During points-to pointer equivalence sets are computed by adding
special RESTRICT heap-variables to points-to sets of targets of
pointer conversions to restrict, global restrict qualified pointers
and restrict qualified pointer arguments.

A RESTRICT in the points-to set of a restrict qualified pointer
acts as a filter for NONLOCAL and ANYTHING.  The RESTRICT in the
points-to sets make pointers based on each other conflict,
non-restrict qualified pointers conflict with restrict qualified
pointers if they point to anonymous memory (NONLOCAL or ANYTHING)
or otherwise.

This was designed in a way to make it useful enough to implement
fortran (and maybe Ada) semantics for global non-target attributed
allocatable arrays (it does not fully cover non-target attributed
function arguments).  The way to leverage fortran alias semantics
is to make the data pointer field of the gfortran array descriptor
restrict qualified for non-target/non-pointer attributed arrays.

One major improvement is that restrict keeps working even if
you supply -fno-strict-aliasing.

The testcases in the patch should give further ideas.

Bootstrapped and tested on x86_64-unknown-linux-gnu with the following
differences in testresults:

XPASS: gcc.dg/vect/no-scevccp-outer-6-global.c scan-tree-dump-times vect 
"OUTER LOOP VECTORIZED." 1
FAIL: libffi.call/cls_pointer.c -O2 output pattern test, is 0x00400aa0 
0x65eeac0
0: 0x662eb6a0
FAIL: libffi.call/cls_pointer_stack.c -O2 output pattern test, is
FAIL: InvokeReturn output - source compiled test
FAIL: InvokeReturn -findirect-dispatch output - source compiled test
FAIL: InvokeReturn -O3 output - source compiled test
FAIL: InvokeReturn -O3 -findirect-dispatch output - source compiled test
FAIL: Serialization execution - source compiled test
FAIL: Serialization -findirect-dispatch execution - source compiled test
FAIL: Serialization -O3 execution - source compiled test
FAIL: Serialization -O3 -findirect-dispatch execution - source compiled 
test

I have to double-check the extra fails, at least libffi doesn't use
restrict at all so maybe some unwanted side-effects are in the patch.

Comments?  Holes in my treatment of restrict?

Thanks,
Richard.

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

	PR middle-end/14187
	* 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.
	(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): For restrict qualified pointer points-to
	sets prune ANYTHING and NONLOCAL if the points-to set includes
	a restrict heap variable.

	* 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-23 12:02:02.000000000 +0200
--- trunk/gcc/tree-ssa-structalias.c	2009-06-23 14:20:04.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,3414 ----
    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;
+ }
+ 
  /* 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)
      {
--- 3463,3475 ----
  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");
      }
    else if (VEC_length (ce_s, rhsc) > 0)
      {
*************** find_func_aliases (gimple origt)
*** 3838,3843 ****
--- 3889,3907 ----
  	  && 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)))
+ 	{
+ 	  varinfo_t vi;
+ 	  vi = make_constraint_from_heapvar (get_vi_for_tree (lhsop),
+ 					     "CAST_RESTRICT");
+ 	  vi->is_restrict_var = 1;
+ 	}
      }
    /* For conversions of pointers to non-pointers the pointer escapes.  */
    else if (gimple_assign_cast_p (t)
*************** struct fieldoff
*** 4029,4034 ****
--- 4093,4100 ----
    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 ****
--- 4233,4242 ----
  		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.  */
  
--- 4247,4252 ----
*************** 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
--- 4394,4408 ----
    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);
  
!   gcc_assert (!var_ann (decl)
! 	      || (var_ann (decl)->noalias_state == 0
! 		  && !var_ann (decl)->is_heapvar));
!   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,4402 ****
      }
  
    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);
      }
--- 4425,4441 ----
      }
  
    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)))
! 	{
! 	  varinfo_t rvi;
! 	  rvi = make_constraint_from_heapvar (vi, "GLOBAL_RESTRICT");
! 	  make_copy_constraint (rvi, nonlocal_id);
! 	}
        else
  	make_copy_constraint (vi, nonlocal_id);
      }
*************** 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++;
  	}
--- 4514,4533 ----
  	  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)
! 		 {
! 		   varinfo_t rvi;
! 		   rvi = make_constraint_from_heapvar (newvi,
! 						       "GLOBAL_RESTRICT");
! 		   make_copy_constraint (rvi, nonlocal_id);
! 		 }
! 	       else
! 		 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.  */
--- 4580,4585 ----
*************** 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
  	{
--- 4597,4634 ----
        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 if (POINTER_TYPE_P (TREE_TYPE (t))
+ 	       && TYPE_RESTRICT (TREE_TYPE (t)))
+ 	{
+ 	  varinfo_t vi;
+ 
+ 	  vi = make_constraint_from_heapvar (get_vi_for_tree (t),
+ 					     "PARM_RESTRICT");
+ 	  vi->is_restrict_var = 1;
+ 	  make_copy_constraint (vi, nonlocal_id);
  	}
        else
  	{
*************** 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;
  	}
      }
--- 4753,4759 ----
  	  /* 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
*** 4734,4739 ****
--- 4771,4777 ----
    bitmap_iterator bi;
    bitmap finished_solution;
    bitmap result;
+   bool restrict_p = false;
  
    memset (pt, 0, sizeof (struct pt_solution));
  
*************** find_what_var_points_to (varinfo_t vi, s
*** 4765,4770 ****
--- 4803,4824 ----
  		   || vi->id == integer_id)
  	    pt->anything = 1;
  	}
+       if (vi->is_restrict_var)
+ 	restrict_p = true;
+     }
+ 
+   /* If this is a restrict qualified pointer based on a restrict qualified
+      pointer filter out anything and nonlocal.
+      ???  If the pointer doesn't point to anything or nonlocal or
+      global variables we should filter out the restrict vars that
+      are considered global.  In that case restrict only pessimizes.  */
+   if (restrict_p
+       && !vi->is_artificial_var
+       && POINTER_TYPE_P (TREE_TYPE (vi->decl))
+       && TYPE_RESTRICT (TREE_TYPE (vi->decl)))
+     {
+       pt->anything = 0;
+       pt->nonlocal = 0;
      }
  
    /* Instead of doing extra work, simply do not create
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-23 12:07: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-23 12:07: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-23 12:07: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-23 13:25:45.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-23 12:32:22.000000000 +0200
***************
*** 0 ****
--- 1,22 ----
+ /* { dg-do compile } */
+ /* { dg-options "-O -fno-strict-aliasing -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-23 14:06:11.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 *x, *y, tmp = 0.0;
+   x = (float *)a.data;
+   y = (float *)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 Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]