public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH][4.3][RFT] Fix PR37868, backport some PTA fixes
@ 2008-10-22 20:09 Richard Guenther
  2008-10-25 18:29 ` Eric Botcazou
  2008-12-03 10:12 ` Eric Botcazou
  0 siblings, 2 replies; 10+ messages in thread
From: Richard Guenther @ 2008-10-22 20:09 UTC (permalink / raw)
  To: gcc-patches


This fixes PR37868 where wrong points-to solutions for pointer arithmetic
breaks code we consider valid with -fno-strict-aliasing.  With SFTs
still around the fix from trunk needs some adjustments.  I also didn't
backport mere code reorganization changes.

Still this is a quite big patch - so I appreciate testing and won't
install this at the moment.

Bootstrapped and tested on x86_64-unknown-linux-gnu.

Richard.

2008-10-22  Richard Guenther  <rguenther@suse.de>

	PR tree-optimization/37868
	* tree-ssa-structalias.c (set_uids_in_ptset): Add SFTs based on
	pointed to variable and access size.

	* gcc.dg/torture/pr37868.c: New testcase.

	Backport from mainline:
	2008-07-07  Richard Guenther  <rguenther@suse.de>

        * tree-ssa-structalias.c (struct variable_info): Add is_full_var flag.
        (new_var_info): Set it to false.
        (solution_set_add): Correctly handle pointers outside a var and
        inside a field.
        (type_safe): Treat variables with is_full_var properly.
        (do_sd_constraint): Likewise.
        (do_ds_constraint): Likewise.
        (process_constraint): Remove zeroing offset for !use_field_sensitive.
        (get_constraint_for_ptr_offset): New function.
        (get_constraint_for_component_ref): Handle is_full_vars properly.
        (get_constraint_for): Handle POINTER_PLUS_EXPR.
        (handle_ptr_arith): Remove.
        (find_func_aliases): Handle POINTER_PLUS_EXPR through generic
	get_constraint_for code.
        (create_function_info_for): For parameter and result varinfos set
        is_full_var flag.
        (create_variable_info_for): Set is_full_var flag whenever we
        just created a single varinfo for a decl.
        (init_alias_vars): Initialize use_field_sensitive from
        max-fields-for-field-sensitive parameter.

	* gcc.dg/torture/pta-ptrarith-1.c: New testcase.
	* gcc.dg/torture/pta-ptrarith-2.c: Likewise.

Index: gcc-4_3-branch/gcc/testsuite/gcc.dg/torture/pta-ptrarith-1.c
===================================================================
*** /dev/null	1970-01-01 00:00:00.000000000 +0000
--- gcc-4_3-branch/gcc/testsuite/gcc.dg/torture/pta-ptrarith-1.c	2008-10-22 15:28:30.000000000 +0200
***************
*** 0 ****
--- 1,29 ----
+ /* { dg-do run } */
+ 
+ struct Foo {
+   int *p;
+ };
+ 
+ void __attribute__((noinline))
+ foo (void *p)
+ {
+   struct Foo *f = (struct Foo *)p - 1;
+   *f->p = 0;
+ }
+ 
+ int bar (void)
+ {
+   struct Foo f;
+   int i = 1;
+   f.p = &i;
+   foo (&f + 1);
+   return i;
+ }
+ extern void abort (void);
+ int main()
+ {
+   if (bar () != 0)
+     abort ();
+   return 0;
+ }
+ 
Index: gcc-4_3-branch/gcc/testsuite/gcc.dg/torture/pta-ptrarith-2.c
===================================================================
*** /dev/null	1970-01-01 00:00:00.000000000 +0000
--- gcc-4_3-branch/gcc/testsuite/gcc.dg/torture/pta-ptrarith-2.c	2008-10-22 15:28:30.000000000 +0200
***************
*** 0 ****
--- 1,36 ----
+ /* { dg-do run } */
+ /* { dg-options "-fdump-tree-salias" } */
+ /* { dg-skip-if "" { *-*-* } { "-O0" } { "" } } */
+ 
+ struct Foo {
+   int **p;
+   int **q;
+ };
+ 
+ int __attribute__((noinline))
+ bar (void)
+ {
+   struct Foo f;
+   int j, i = 1;
+   char *p;
+   int *x = &i;
+   int *y = &j;
+   f.p = &y;
+   f.q = &x;
+   p = (char *)&f;
+   for (j = 0; j < sizeof (int *); ++j)
+     p++;
+   return ***(int ***)p;
+ }
+ extern void abort (void);
+ int main()
+ {
+   if (bar () != 1)
+     abort ();
+   return 0;
+ }
+ 
+ /* In theory = { i } is the correct solution.  But it's not easy to scan
+    for that reliably, so just use what we create now.  */
+ /* { dg-final { scan-tree-dump "= { i j }" "salias" } } */
+ /* { dg-final { cleanup-tree-dump "salias" } } */
Index: gcc-4_3-branch/gcc/tree-ssa-structalias.c
===================================================================
*** gcc-4_3-branch.orig/gcc/tree-ssa-structalias.c	2008-10-22 15:28:17.000000000 +0200
--- gcc-4_3-branch/gcc/tree-ssa-structalias.c	2008-10-22 18:12:58.000000000 +0200
***************
*** 241,246 ****
--- 241,249 ----
    /* True for variables that have unions somewhere in them.  */
    unsigned int has_union: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;
  
***************
*** 363,368 ****
--- 366,372 ----
    ret->is_heap_var = false;
    ret->is_special_var = false;
    ret->is_unknown_size_var = false;
+   ret->is_full_var = false;
    ret->has_union = false;
    var = t;
    if (TREE_CODE (var) == SSA_NAME)
***************
*** 742,764 ****
  
    EXECUTE_IF_SET_IN_BITMAP (set, 0, i, bi)
      {
!       /* If this is a properly sized variable, only add offset if it's
! 	 less than end.  Otherwise, it is globbed to a single
! 	 variable.  */
  
!       if ((get_varinfo (i)->offset + offset) < get_varinfo (i)->fullsize)
  	{
! 	  unsigned HOST_WIDE_INT fieldoffset = get_varinfo (i)->offset + offset;
! 	  varinfo_t v = first_vi_for_offset (get_varinfo (i), fieldoffset);
  	  if (!v)
! 	    continue;
  	  bitmap_set_bit (result, v->id);
! 	}
!       else if (get_varinfo (i)->is_artificial_var
! 	       || get_varinfo (i)->has_union
! 	       || get_varinfo (i)->is_unknown_size_var)
! 	{
! 	  bitmap_set_bit (result, i);
  	}
      }
  
--- 746,778 ----
  
    EXECUTE_IF_SET_IN_BITMAP (set, 0, i, bi)
      {
!       varinfo_t vi = get_varinfo (i);
  
!       /* If this is a variable with just one field just set its bit
! 	 in the result.  */
!       if (vi->is_artificial_var
! 	  || vi->is_unknown_size_var
! 	  || vi->has_union
! 	  || vi->is_full_var)
! 	bitmap_set_bit (result, i);
!       else
  	{
! 	  unsigned HOST_WIDE_INT fieldoffset = vi->offset + offset;
! 	  varinfo_t v = first_vi_for_offset (vi, fieldoffset);
! 	  /* If the result is outside of the variable use the last field.  */
  	  if (!v)
! 	    {
! 	      v = vi;
! 	      while (v->next != NULL)
! 		v = v->next;
! 	    }
  	  bitmap_set_bit (result, v->id);
! 	  /* If the result is not exactly at fieldoffset include the next
! 	     field as well.  See get_constraint_for_ptr_offset for more
! 	     rationale.  */
! 	  if (v->offset != fieldoffset
! 	      && v->next != NULL)
! 	    bitmap_set_bit (result, v->next->id);
  	}
      }
  
***************
*** 1371,1377 ****
       0.  */
    if (ninfo->is_special_var
        || ninfo->is_artificial_var
!       || ninfo->is_unknown_size_var)
      {
        *offset = 0;
        return true;
--- 1385,1392 ----
       0.  */
    if (ninfo->is_special_var
        || ninfo->is_artificial_var
!       || ninfo->is_unknown_size_var
!       || ninfo->is_full_var)
      {
        *offset = 0;
        return true;
***************
*** 1411,1416 ****
--- 1426,1432 ----
  	  unsigned int t;
  
  	  v = first_vi_for_offset (get_varinfo (j), fieldoffset);
+ 	  /* If the access is outside of the variable we can ignore it.  */
  	  if (!v)
  	    continue;
  	  t = find (v->id);
***************
*** 1460,1468 ****
  	 unsigned HOST_WIDE_INT fieldoffset = jvi->offset + loff;
  	 varinfo_t v;
  
! 	 v = first_vi_for_offset (get_varinfo (j), fieldoffset);
! 	 if (!v)
! 	   continue;
  	 t = find (v->id);
  
  	 if (!bitmap_bit_p (get_varinfo (t)->solution, anything_id))
--- 1476,1489 ----
  	 unsigned HOST_WIDE_INT fieldoffset = jvi->offset + loff;
  	 varinfo_t v;
  
! 	 v = get_varinfo (j);
! 	 if (!v->is_full_var)
! 	   {
! 	     v = first_vi_for_offset (v, fieldoffset);
! 	     /* If the access is outside of the variable we can ignore it.  */
! 	     if (!v)
! 	       continue;
! 	   }
  	 t = find (v->id);
  
  	 if (!bitmap_bit_p (get_varinfo (t)->solution, anything_id))
***************
*** 1491,1496 ****
--- 1512,1518 ----
  	  bitmap tmp;
  
  	  v = first_vi_for_offset (get_varinfo (j), fieldoffset);
+ 	  /* If the access is outside of the variable we can ignore it.  */
  	  if (!v)
  	    continue;
  	  t = find (v->id);
***************
*** 2519,2530 ****
    gcc_assert (rhs.var < VEC_length (varinfo_t, varmap));
    gcc_assert (lhs.var < VEC_length (varinfo_t, varmap));
  
-   if (!use_field_sensitive)
-     {
-       t->rhs.offset = 0;
-       t->lhs.offset = 0;
-     }
- 
    /* ANYTHING == ANYTHING is pointless.  */
    if (lhs.var == anything_id && rhs.var == anything_id)
      return;
--- 2541,2546 ----
***************
*** 2593,2600 ****
    tree type = TREE_TYPE (t);
  
    if (POINTER_TYPE_P (type)
!       || AGGREGATE_TYPE_P (type)
!       || TREE_CODE (type) == COMPLEX_TYPE)
      return true;
  
    return false;
--- 2609,2615 ----
    tree type = TREE_TYPE (t);
  
    if (POINTER_TYPE_P (type)
!       || AGGREGATE_TYPE_P (type))
      return true;
  
    return false;
***************
*** 2635,2640 ****
--- 2650,2769 ----
    return false;
  }
  
+ 
+ /* Get constraint expressions for offsetting PTR by OFFSET.  Stores the
+    resulting constraint expressions in *RESULTS.  */
+ 
+ static void
+ get_constraint_for_ptr_offset (tree ptr, tree offset,
+ 			       VEC (ce_s, heap) **results)
+ {
+   struct constraint_expr *c;
+   unsigned int j, n;
+   unsigned HOST_WIDE_INT rhsunitoffset, rhsoffset;
+ 
+   /* If we do not do field-sensitive PTA adding offsets to pointers
+      does not change the points-to solution.  */
+   if (!use_field_sensitive)
+     {
+       get_constraint_for (ptr, results);
+       return;
+     }
+ 
+   /* If the offset is not a non-negative integer constant that fits
+      in a HOST_WIDE_INT, we have to fall back to a conservative
+      solution which includes all sub-fields of all pointed-to
+      variables of ptr.
+      ???  As we do not have the ability to express this, fall back
+      to anything.  */
+   if (!host_integerp (offset, 1))
+     {
+       struct constraint_expr temp;
+       temp.var = anything_id;
+       temp.type = SCALAR;
+       temp.offset = 0;
+       VEC_safe_push (ce_s, heap, *results, &temp);
+       return;
+     }
+ 
+   /* Make sure the bit-offset also fits.  */
+   rhsunitoffset = TREE_INT_CST_LOW (offset);
+   rhsoffset = rhsunitoffset * BITS_PER_UNIT;
+   if (rhsunitoffset != rhsoffset / BITS_PER_UNIT)
+     {
+       struct constraint_expr temp;
+       temp.var = anything_id;
+       temp.type = SCALAR;
+       temp.offset = 0;
+       VEC_safe_push (ce_s, heap, *results, &temp);
+       return;
+     }
+ 
+   get_constraint_for (ptr, results);
+   if (rhsoffset == 0)
+     return;
+ 
+   /* As we are eventually appending to the solution do not use
+      VEC_iterate here.  */
+   n = VEC_length (ce_s, *results);
+   for (j = 0; j < n; j++)
+     {
+       varinfo_t curr;
+       c = VEC_index (ce_s, *results, j);
+       curr = get_varinfo (c->var);
+ 
+       if (c->type == ADDRESSOF
+ 	  && !curr->is_full_var)
+ 	{
+ 	  varinfo_t temp, curr = get_varinfo (c->var);
+ 
+ 	  /* Search the sub-field which overlaps with the
+ 	     pointed-to offset.  As we deal with positive offsets
+ 	     only, we can start the search from the current variable.  */
+ 	  temp = first_vi_for_offset (curr, curr->offset + rhsoffset);
+ 
+ 	  /* If the result is outside of the variable we have to provide
+ 	     a conservative result, as the variable is still reachable
+ 	     from the resulting pointer (even though it technically
+ 	     cannot point to anything).  The last sub-field is such
+ 	     a conservative result.
+ 	     ???  If we always had a sub-field for &object + 1 then
+ 	     we could represent this in a more precise way.  */
+ 	  if (temp == NULL)
+ 	    {
+ 	      temp = curr;
+ 	      while (temp->next != NULL)
+ 		temp = temp->next;
+ 	      continue;
+ 	    }
+ 
+ 	  /* If the found variable is not exactly at the pointed to
+ 	     result, we have to include the next variable in the
+ 	     solution as well.  Otherwise two increments by offset / 2
+ 	     do not result in the same or a conservative superset
+ 	     solution.  */
+ 	  if (temp->offset != curr->offset + rhsoffset
+ 	      && temp->next != NULL)
+ 	    {
+ 	      struct constraint_expr c2;
+ 	      c2.var = temp->next->id;
+ 	      c2.type = ADDRESSOF;
+ 	      c2.offset = 0;
+ 	      VEC_safe_push (ce_s, heap, *results, &c2);
+ 	    }
+ 	  c->var = temp->id;
+ 	  c->offset = 0;
+ 	}
+       else if (c->type == ADDRESSOF
+ 	       /* If this varinfo represents a full variable just use it.  */
+ 	       && curr->is_full_var)
+ 	c->offset = 0;
+       else
+ 	c->offset = rhsoffset;
+     }
+ }
+ 
+ 
  /* Given a COMPONENT_REF T, return the constraint_expr for it.  */
  
  static void
***************
*** 2682,2688 ****
    if (TREE_CODE (t) != ADDR_EXPR && result->type == ADDRESSOF)
      result->type = SCALAR;
  
!   if (result->type == SCALAR)
      {
        /* In languages like C, you can access one past the end of an
  	 array.  You aren't allowed to dereference it, so we can
--- 2811,2821 ----
    if (TREE_CODE (t) != ADDR_EXPR && result->type == ADDRESSOF)
      result->type = SCALAR;
  
!   if (result->type == SCALAR
!       && get_varinfo (result->var)->is_full_var)
!     /* For single-field vars do not bother about the offset.  */
!     result->offset = 0;
!   else if (result->type == SCALAR)
      {
        /* In languages like C, you can access one past the end of an
  	 array.  You aren't allowed to dereference it, so we can
***************
*** 2801,2833 ****
  	      struct constraint_expr *c;
  	      unsigned int i;
  	      tree exp = TREE_OPERAND (t, 0);
- 	      tree pttype = TREE_TYPE (TREE_TYPE (t));
  
  	      get_constraint_for (exp, results);
  
- 
- 	      /* Complex types are special. Taking the address of one
- 		 allows you to access either part of it through that
- 		 pointer.  */
- 	      if (VEC_length (ce_s, *results) == 1 &&
- 		  TREE_CODE (pttype) == COMPLEX_TYPE)
- 		{
- 		  struct constraint_expr *origrhs;
- 		  varinfo_t origvar;
- 		  struct constraint_expr tmp;
- 
- 		  gcc_assert (VEC_length (ce_s, *results) == 1);
- 		  origrhs = VEC_last (ce_s, *results);
- 		  tmp = *origrhs;
- 		  VEC_pop (ce_s, *results);
- 		  origvar = get_varinfo (origrhs->var);
- 		  for (; origvar; origvar = origvar->next)
- 		    {
- 		      tmp.var = origvar->id;
- 		      VEC_safe_push (ce_s, heap, *results, &tmp);
- 		    }
- 		}
- 
  	      for (i = 0; VEC_iterate (ce_s, *results, i, c); i++)
  		{
  		  if (c->type == DEREF)
--- 2934,2942 ----
***************
*** 2943,2948 ****
--- 3052,3067 ----
  	    }
  	  }
        }
+     case tcc_binary:
+       {
+ 	if (TREE_CODE (t) == POINTER_PLUS_EXPR)
+ 	  {
+ 	    get_constraint_for_ptr_offset (TREE_OPERAND (t, 0),
+ 					   TREE_OPERAND (t, 1), results);
+ 	    return;
+ 	  }
+ 	break;
+       }
      case tcc_exceptional:
        {
  	switch (TREE_CODE (t))
***************
*** 3512,3590 ****
  }
  
  
- /* Handle pointer arithmetic EXPR when creating aliasing constraints.
-    Expressions of the type PTR + CST can be handled in two ways:
- 
-    1- If the constraint for PTR is ADDRESSOF for a non-structure
-       variable, then we can use it directly because adding or
-       subtracting a constant may not alter the original ADDRESSOF
-       constraint (i.e., pointer arithmetic may not legally go outside
-       an object's boundaries).
- 
-    2- If the constraint for PTR is ADDRESSOF for a structure variable,
-       then if CST is a compile-time constant that can be used as an
-       offset, we can determine which sub-variable will be pointed-to
-       by the expression.
- 
-    Return true if the expression is handled.  For any other kind of
-    expression, return false so that each operand can be added as a
-    separate constraint by the caller.  */
- 
- static bool
- handle_ptr_arith (VEC (ce_s, heap) *lhsc, tree expr)
- {
-   tree op0, op1;
-   struct constraint_expr *c, *c2;
-   unsigned int i = 0;
-   unsigned int j = 0;
-   VEC (ce_s, heap) *temp = NULL;
-   unsigned HOST_WIDE_INT rhsunitoffset, rhsoffset;
- 
-   if (TREE_CODE (expr) != POINTER_PLUS_EXPR)
-     return false;
- 
-   op0 = TREE_OPERAND (expr, 0);
-   op1 = TREE_OPERAND (expr, 1);
-   gcc_assert (POINTER_TYPE_P (TREE_TYPE (op0)));
- 
-   /* If the offset is not a non-negative integer constant that fits
-      in a HOST_WIDE_INT, we cannot handle it here.  */
-   if (!host_integerp (op1, 1))
-     return false;
- 
-   /* Make sure the bit-offset also fits.  */
-   rhsunitoffset = TREE_INT_CST_LOW (op1);
-   rhsoffset = rhsunitoffset * BITS_PER_UNIT;
-   if (rhsunitoffset != rhsoffset / BITS_PER_UNIT)
-     return false;
- 
-   get_constraint_for (op0, &temp);
- 
-   for (i = 0; VEC_iterate (ce_s, lhsc, i, c); i++)
-     for (j = 0; VEC_iterate (ce_s, temp, j, c2); j++)
-       {
- 	if (c2->type == ADDRESSOF && rhsoffset != 0)
- 	  {
- 	    varinfo_t temp = get_varinfo (c2->var);
- 
- 	    /* An access one after the end of an array is valid,
- 	       so simply punt on accesses we cannot resolve.  */
- 	    temp = first_vi_for_offset (temp, rhsoffset);
- 	    if (temp == NULL)
- 	      continue;
- 	    c2->var = temp->id;
- 	    c2->offset = 0;
- 	  }
- 	else
- 	  c2->offset = rhsoffset;
- 	process_constraint (new_constraint (*c, *c2));
-       }
- 
-   VEC_free (ce_s, heap, temp);
- 
-   return true;
- }
- 
  /* For non-IPA mode, generate constraints necessary for a call on the
     RHS.  */
  
--- 3631,3636 ----
***************
*** 3815,3824 ****
        tree rhsop = GIMPLE_STMT_OPERAND (t, 1);
        int i;
  
!       if ((AGGREGATE_TYPE_P (TREE_TYPE (lhsop))
! 	   || TREE_CODE (TREE_TYPE (lhsop)) == COMPLEX_TYPE)
! 	  && (AGGREGATE_TYPE_P (TREE_TYPE (rhsop))
! 	      || TREE_CODE (TREE_TYPE (lhsop)) == COMPLEX_TYPE))
  	{
  	  do_structure_copy (lhsop, rhsop);
  	}
--- 3861,3868 ----
        tree rhsop = GIMPLE_STMT_OPERAND (t, 1);
        int i;
  
!       if (AGGREGATE_TYPE_P (TREE_TYPE (lhsop))
! 	  && AGGREGATE_TYPE_P (TREE_TYPE (rhsop)))
  	{
  	  do_structure_copy (lhsop, rhsop);
  	}
***************
*** 3842,3847 ****
--- 3886,3892 ----
  		  case tcc_expression:
  		  case tcc_vl_exp:
  		  case tcc_unary:
+ 		  case tcc_binary:
  		      {
  			unsigned int j;
  
***************
*** 3854,3874 ****
  			    for (k = 0; VEC_iterate (ce_s, rhsc, k, c2); k++)
  			      process_constraint (new_constraint (*c, *c2));
  			  }
- 
  		      }
  		    break;
  
- 		  case tcc_binary:
- 		      {
- 			/* For pointer arithmetic of the form
- 			   PTR + CST, we can simply use PTR's
- 			   constraint because pointer arithmetic is
- 			   not allowed to go out of bounds.  */
- 			if (handle_ptr_arith (lhsc, rhsop))
- 			  break;
- 		      }
- 		    /* FALLTHRU  */
- 
  		  /* Otherwise, walk each operand.  Notice that we
  		     can't use the operand interface because we need
  		     to process expressions other than simple operands
--- 3899,3907 ----
***************
*** 4257,4264 ****
    stats.total_vars++;
  
    /* If it's varargs, we don't know how many arguments it has, so we
!      can't do much.
!   */
    if (is_varargs)
      {
        vi->fullsize = ~0;
--- 4290,4296 ----
    stats.total_vars++;
  
    /* If it's varargs, we don't know how many arguments it has, so we
!      can't do much.  */
    if (is_varargs)
      {
        vi->fullsize = ~0;
***************
*** 4292,4297 ****
--- 4324,4330 ----
        VEC_safe_push (varinfo_t, heap, varmap, argvi);
        argvi->offset = i;
        argvi->size = 1;
+       argvi->is_full_var = true;
        argvi->fullsize = vi->fullsize;
        argvi->has_union = false;
        insert_into_field_list_sorted (vi, argvi);
***************
*** 4329,4334 ****
--- 4362,4368 ----
        resultvi->offset = i;
        resultvi->size = 1;
        resultvi->fullsize = vi->fullsize;
+       resultvi->is_full_var = true;
        resultvi->has_union = false;
        insert_into_field_list_sorted (vi, resultvi);
        stats.total_vars ++;
***************
*** 4464,4469 ****
--- 4498,4504 ----
  	  vi->is_unknown_size_var = 1;
  	  vi->fullsize = ~0;
  	  vi->size = ~0;
+ 	  vi->is_full_var = true;
  	  VEC_free (fieldoff_s, heap, fieldstack);
  	  return index;
  	}
***************
*** 4502,4507 ****
--- 4537,4544 ----
  	  stats.total_vars++;
  	}
      }
+   else
+     vi->is_full_var = true;
  
    VEC_free (fieldoff_s, heap, fieldstack);
  
***************
*** 4749,4765 ****
  	      && (sv = get_subvars_for_var (vi->decl)))
  	    {
  	      /* If VI->DECL is an aggregate for which we created
! 		 SFTs, add the SFT corresponding to VI->OFFSET.
  		 If we didn't do field-sensitive PTA we need to to
  		 add all overlapping SFTs.  */
  	      unsigned int j;
! 	      tree sft = get_first_overlapping_subvar (sv, vi->offset,
! 						       vi->size, &j);
  	      gcc_assert (sft);
  	      for (; VEC_iterate (tree, sv, j, sft); ++j)
  		{
  		  if (SFT_OFFSET (sft) > vi->offset
! 		      && vi->size <= SFT_OFFSET (sft) - vi->offset)
  		    break;
  
  		  bitmap_set_bit (into, DECL_UID (sft));
--- 4786,4807 ----
  	      && (sv = get_subvars_for_var (vi->decl)))
  	    {
  	      /* If VI->DECL is an aggregate for which we created
! 		 SFTs, add the SFT corresponding to VI->OFFSET (the
! 		 pointed-to location) and the access size.
  		 If we didn't do field-sensitive PTA we need to to
  		 add all overlapping SFTs.  */
  	      unsigned int j;
! 	      unsigned HOST_WIDE_INT size = -1;
! 	      tree sft, tsize = TYPE_SIZE (TREE_TYPE (TREE_TYPE (ptr)));
! 	      if (tsize
! 		  && host_integerp (tsize, 1))
! 		size = TREE_INT_CST_LOW (tsize);
! 	      sft = get_first_overlapping_subvar (sv, vi->offset, size, &j);
  	      gcc_assert (sft);
  	      for (; VEC_iterate (tree, sv, j, sft); ++j)
  		{
  		  if (SFT_OFFSET (sft) > vi->offset
! 		      && size <= SFT_OFFSET (sft) - vi->offset)
  		    break;
  
  		  bitmap_set_bit (into, DECL_UID (sft));
***************
*** 5156,5161 ****
--- 5198,5205 ----
  static void
  init_alias_vars (void)
  {
+   use_field_sensitive = (MAX_FIELDS_FOR_FIELD_SENSITIVE > 1);
+ 
    bitmap_obstack_initialize (&pta_obstack);
    bitmap_obstack_initialize (&oldpta_obstack);
    bitmap_obstack_initialize (&predbitmap_obstack);
Index: gcc-4_3-branch/gcc/testsuite/gcc.dg/torture/pr37868.c
===================================================================
*** /dev/null	1970-01-01 00:00:00.000000000 +0000
--- gcc-4_3-branch/gcc/testsuite/gcc.dg/torture/pr37868.c	2008-10-22 15:28:30.000000000 +0200
***************
*** 0 ****
--- 1,28 ----
+ /* { dg-do run } */
+ /* { dg-options "-fno-strict-aliasing" } */
+ 
+ extern void abort (void);
+ 
+ struct X {
+   unsigned char pad : 4;
+   unsigned int a : 32;
+   unsigned int b : 24;
+   unsigned int c : 6;
+ } __attribute__((packed));
+ 
+ int main (void)
+ {
+   struct X x;
+   unsigned int bad_bits;
+ 
+   x.pad = -1;
+   x.a = -1;
+   x.b = -1;
+   x.c = -1;
+ 
+   bad_bits = ((unsigned int)-1) ^ *(1+(unsigned int *) &x);
+   if (bad_bits != 0)
+     abort ();
+   return 0;
+ }
+ 

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH][4.3][RFT] Fix PR37868, backport some PTA fixes
  2008-10-22 20:09 [PATCH][4.3][RFT] Fix PR37868, backport some PTA fixes Richard Guenther
@ 2008-10-25 18:29 ` Eric Botcazou
  2008-11-03 12:54   ` Richard Guenther
  2008-12-03 10:12 ` Eric Botcazou
  1 sibling, 1 reply; 10+ messages in thread
From: Eric Botcazou @ 2008-10-25 18:29 UTC (permalink / raw)
  To: Richard Guenther; +Cc: gcc-patches

> Still this is a quite big patch - so I appreciate testing and won't
> install this at the moment.

Tested locally (C/C++/Ada) on i586-suse-linux and run through AdaCore's 
internal testsuite on x86 and x86-64.  No problems detected.

-- 
Eric Botcazou

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH][4.3][RFT] Fix PR37868, backport some PTA fixes
  2008-10-25 18:29 ` Eric Botcazou
@ 2008-11-03 12:54   ` Richard Guenther
  2008-11-20 13:20     ` Richard Guenther
  0 siblings, 1 reply; 10+ messages in thread
From: Richard Guenther @ 2008-11-03 12:54 UTC (permalink / raw)
  To: Eric Botcazou; +Cc: gcc-patches

On Sat, 25 Oct 2008, Eric Botcazou wrote:

> > Still this is a quite big patch - so I appreciate testing and won't
> > install this at the moment.
> 
> Tested locally (C/C++/Ada) on i586-suse-linux and run through AdaCore's 
> internal testsuite on x86 and x86-64.  No problems detected.

Thanks for testing.  I'll throw it on openSUSE and likely will apply it
if there are no problems detected.  Other opinions welcome of course.

Richard.

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH][4.3][RFT] Fix PR37868, backport some PTA fixes
  2008-11-03 12:54   ` Richard Guenther
@ 2008-11-20 13:20     ` Richard Guenther
  2008-11-20 13:23       ` Eric Botcazou
  0 siblings, 1 reply; 10+ messages in thread
From: Richard Guenther @ 2008-11-20 13:20 UTC (permalink / raw)
  To: Eric Botcazou; +Cc: gcc-patches

On Mon, 3 Nov 2008, Richard Guenther wrote:

> On Sat, 25 Oct 2008, Eric Botcazou wrote:
> 
> > > Still this is a quite big patch - so I appreciate testing and won't
> > > install this at the moment.
> > 
> > Tested locally (C/C++/Ada) on i586-suse-linux and run through AdaCore's 
> > internal testsuite on x86 and x86-64.  No problems detected.
> 
> Thanks for testing.  I'll throw it on openSUSE and likely will apply it
> if there are no problems detected.  Other opinions welcome of course.

Successfully tested on our other architectures and with a re-build of
openSUSE packages.  Applied to the branch.

Patch appended for reference.  I'll apply the new testcases to the
trunk as well.

Richard.

2008-11-20  Richard Guenther  <rguenther@suse.de>

	PR tree-optimization/37868
	* tree-ssa-structalias.c (set_uids_in_ptset): Add SFTs based on
	pointed to variable and access size.

	* gcc.dg/torture/pr37868.c: New testcase.
	* gcc.c-torture/execute/pr38048-1.c: Likewise.
	* gcc.c-torture/execute/pr38048-2.c: Likewise.

	Backport from mainline:
	2008-07-07  Richard Guenther  <rguenther@suse.de>

        * tree-ssa-structalias.c (struct variable_info): Add is_full_var flag.
        (new_var_info): Set it to false.
        (solution_set_add): Correctly handle pointers outside a var and
        inside a field.
        (type_safe): Treat variables with is_full_var properly.
        (do_sd_constraint): Likewise.
        (do_ds_constraint): Likewise.
        (process_constraint): Remove zeroing offset for !use_field_sensitive.
        (get_constraint_for_ptr_offset): New function.
        (get_constraint_for_component_ref): Handle is_full_vars properly.
        (get_constraint_for): Handle POINTER_PLUS_EXPR.
        (handle_ptr_arith): Remove.
        (find_func_aliases): Handle POINTER_PLUS_EXPR through generic
	get_constraint_for code.
        (create_function_info_for): For parameter and result varinfos set
        is_full_var flag.
        (create_variable_info_for): Set is_full_var flag whenever we
        just created a single varinfo for a decl.
        (init_alias_vars): Initialize use_field_sensitive from
        max-fields-for-field-sensitive parameter.

	* gcc.dg/torture/pta-ptrarith-1.c: New testcase.
	* gcc.dg/torture/pta-ptrarith-2.c: Likewise.

Index: gcc-4_3-branch/gcc/testsuite/gcc.dg/torture/pta-ptrarith-1.c
===================================================================
*** /dev/null	1970-01-01 00:00:00.000000000 +0000
--- gcc-4_3-branch/gcc/testsuite/gcc.dg/torture/pta-ptrarith-1.c	2008-10-22 15:28:30.000000000 +0200
***************
*** 0 ****
--- 1,29 ----
+ /* { dg-do run } */
+ 
+ struct Foo {
+   int *p;
+ };
+ 
+ void __attribute__((noinline))
+ foo (void *p)
+ {
+   struct Foo *f = (struct Foo *)p - 1;
+   *f->p = 0;
+ }
+ 
+ int bar (void)
+ {
+   struct Foo f;
+   int i = 1;
+   f.p = &i;
+   foo (&f + 1);
+   return i;
+ }
+ extern void abort (void);
+ int main()
+ {
+   if (bar () != 0)
+     abort ();
+   return 0;
+ }
+ 
Index: gcc-4_3-branch/gcc/testsuite/gcc.dg/torture/pta-ptrarith-2.c
===================================================================
*** /dev/null	1970-01-01 00:00:00.000000000 +0000
--- gcc-4_3-branch/gcc/testsuite/gcc.dg/torture/pta-ptrarith-2.c	2008-10-22 15:28:30.000000000 +0200
***************
*** 0 ****
--- 1,36 ----
+ /* { dg-do run } */
+ /* { dg-options "-fdump-tree-salias" } */
+ /* { dg-skip-if "" { *-*-* } { "-O0" } { "" } } */
+ 
+ struct Foo {
+   int **p;
+   int **q;
+ };
+ 
+ int __attribute__((noinline))
+ bar (void)
+ {
+   struct Foo f;
+   int j, i = 1;
+   char *p;
+   int *x = &i;
+   int *y = &j;
+   f.p = &y;
+   f.q = &x;
+   p = (char *)&f;
+   for (j = 0; j < sizeof (int *); ++j)
+     p++;
+   return ***(int ***)p;
+ }
+ extern void abort (void);
+ int main()
+ {
+   if (bar () != 1)
+     abort ();
+   return 0;
+ }
+ 
+ /* In theory = { i } is the correct solution.  But it's not easy to scan
+    for that reliably, so just use what we create now.  */
+ /* { dg-final { scan-tree-dump "= { i j }" "salias" } } */
+ /* { dg-final { cleanup-tree-dump "salias" } } */
Index: gcc-4_3-branch/gcc/tree-ssa-structalias.c
===================================================================
*** gcc-4_3-branch.orig/gcc/tree-ssa-structalias.c	2008-10-22 15:28:17.000000000 +0200
--- gcc-4_3-branch/gcc/tree-ssa-structalias.c	2008-10-22 18:12:58.000000000 +0200
***************
*** 241,246 ****
--- 241,249 ----
    /* True for variables that have unions somewhere in them.  */
    unsigned int has_union: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;
  
***************
*** 363,368 ****
--- 366,372 ----
    ret->is_heap_var = false;
    ret->is_special_var = false;
    ret->is_unknown_size_var = false;
+   ret->is_full_var = false;
    ret->has_union = false;
    var = t;
    if (TREE_CODE (var) == SSA_NAME)
***************
*** 742,764 ****
  
    EXECUTE_IF_SET_IN_BITMAP (set, 0, i, bi)
      {
!       /* If this is a properly sized variable, only add offset if it's
! 	 less than end.  Otherwise, it is globbed to a single
! 	 variable.  */
  
!       if ((get_varinfo (i)->offset + offset) < get_varinfo (i)->fullsize)
  	{
! 	  unsigned HOST_WIDE_INT fieldoffset = get_varinfo (i)->offset + offset;
! 	  varinfo_t v = first_vi_for_offset (get_varinfo (i), fieldoffset);
  	  if (!v)
! 	    continue;
  	  bitmap_set_bit (result, v->id);
! 	}
!       else if (get_varinfo (i)->is_artificial_var
! 	       || get_varinfo (i)->has_union
! 	       || get_varinfo (i)->is_unknown_size_var)
! 	{
! 	  bitmap_set_bit (result, i);
  	}
      }
  
--- 746,778 ----
  
    EXECUTE_IF_SET_IN_BITMAP (set, 0, i, bi)
      {
!       varinfo_t vi = get_varinfo (i);
  
!       /* If this is a variable with just one field just set its bit
! 	 in the result.  */
!       if (vi->is_artificial_var
! 	  || vi->is_unknown_size_var
! 	  || vi->has_union
! 	  || vi->is_full_var)
! 	bitmap_set_bit (result, i);
!       else
  	{
! 	  unsigned HOST_WIDE_INT fieldoffset = vi->offset + offset;
! 	  varinfo_t v = first_vi_for_offset (vi, fieldoffset);
! 	  /* If the result is outside of the variable use the last field.  */
  	  if (!v)
! 	    {
! 	      v = vi;
! 	      while (v->next != NULL)
! 		v = v->next;
! 	    }
  	  bitmap_set_bit (result, v->id);
! 	  /* If the result is not exactly at fieldoffset include the next
! 	     field as well.  See get_constraint_for_ptr_offset for more
! 	     rationale.  */
! 	  if (v->offset != fieldoffset
! 	      && v->next != NULL)
! 	    bitmap_set_bit (result, v->next->id);
  	}
      }
  
***************
*** 1371,1377 ****
       0.  */
    if (ninfo->is_special_var
        || ninfo->is_artificial_var
!       || ninfo->is_unknown_size_var)
      {
        *offset = 0;
        return true;
--- 1385,1392 ----
       0.  */
    if (ninfo->is_special_var
        || ninfo->is_artificial_var
!       || ninfo->is_unknown_size_var
!       || ninfo->is_full_var)
      {
        *offset = 0;
        return true;
***************
*** 1411,1416 ****
--- 1426,1432 ----
  	  unsigned int t;
  
  	  v = first_vi_for_offset (get_varinfo (j), fieldoffset);
+ 	  /* If the access is outside of the variable we can ignore it.  */
  	  if (!v)
  	    continue;
  	  t = find (v->id);
***************
*** 1460,1468 ****
  	 unsigned HOST_WIDE_INT fieldoffset = jvi->offset + loff;
  	 varinfo_t v;
  
! 	 v = first_vi_for_offset (get_varinfo (j), fieldoffset);
! 	 if (!v)
! 	   continue;
  	 t = find (v->id);
  
  	 if (!bitmap_bit_p (get_varinfo (t)->solution, anything_id))
--- 1476,1489 ----
  	 unsigned HOST_WIDE_INT fieldoffset = jvi->offset + loff;
  	 varinfo_t v;
  
! 	 v = get_varinfo (j);
! 	 if (!v->is_full_var)
! 	   {
! 	     v = first_vi_for_offset (v, fieldoffset);
! 	     /* If the access is outside of the variable we can ignore it.  */
! 	     if (!v)
! 	       continue;
! 	   }
  	 t = find (v->id);
  
  	 if (!bitmap_bit_p (get_varinfo (t)->solution, anything_id))
***************
*** 1491,1496 ****
--- 1512,1518 ----
  	  bitmap tmp;
  
  	  v = first_vi_for_offset (get_varinfo (j), fieldoffset);
+ 	  /* If the access is outside of the variable we can ignore it.  */
  	  if (!v)
  	    continue;
  	  t = find (v->id);
***************
*** 2519,2530 ****
    gcc_assert (rhs.var < VEC_length (varinfo_t, varmap));
    gcc_assert (lhs.var < VEC_length (varinfo_t, varmap));
  
-   if (!use_field_sensitive)
-     {
-       t->rhs.offset = 0;
-       t->lhs.offset = 0;
-     }
- 
    /* ANYTHING == ANYTHING is pointless.  */
    if (lhs.var == anything_id && rhs.var == anything_id)
      return;
--- 2541,2546 ----
***************
*** 2593,2600 ****
    tree type = TREE_TYPE (t);
  
    if (POINTER_TYPE_P (type)
!       || AGGREGATE_TYPE_P (type)
!       || TREE_CODE (type) == COMPLEX_TYPE)
      return true;
  
    return false;
--- 2609,2615 ----
    tree type = TREE_TYPE (t);
  
    if (POINTER_TYPE_P (type)
!       || AGGREGATE_TYPE_P (type))
      return true;
  
    return false;
***************
*** 2635,2640 ****
--- 2650,2769 ----
    return false;
  }
  
+ 
+ /* Get constraint expressions for offsetting PTR by OFFSET.  Stores the
+    resulting constraint expressions in *RESULTS.  */
+ 
+ static void
+ get_constraint_for_ptr_offset (tree ptr, tree offset,
+ 			       VEC (ce_s, heap) **results)
+ {
+   struct constraint_expr *c;
+   unsigned int j, n;
+   unsigned HOST_WIDE_INT rhsunitoffset, rhsoffset;
+ 
+   /* If we do not do field-sensitive PTA adding offsets to pointers
+      does not change the points-to solution.  */
+   if (!use_field_sensitive)
+     {
+       get_constraint_for (ptr, results);
+       return;
+     }
+ 
+   /* If the offset is not a non-negative integer constant that fits
+      in a HOST_WIDE_INT, we have to fall back to a conservative
+      solution which includes all sub-fields of all pointed-to
+      variables of ptr.
+      ???  As we do not have the ability to express this, fall back
+      to anything.  */
+   if (!host_integerp (offset, 1))
+     {
+       struct constraint_expr temp;
+       temp.var = anything_id;
+       temp.type = SCALAR;
+       temp.offset = 0;
+       VEC_safe_push (ce_s, heap, *results, &temp);
+       return;
+     }
+ 
+   /* Make sure the bit-offset also fits.  */
+   rhsunitoffset = TREE_INT_CST_LOW (offset);
+   rhsoffset = rhsunitoffset * BITS_PER_UNIT;
+   if (rhsunitoffset != rhsoffset / BITS_PER_UNIT)
+     {
+       struct constraint_expr temp;
+       temp.var = anything_id;
+       temp.type = SCALAR;
+       temp.offset = 0;
+       VEC_safe_push (ce_s, heap, *results, &temp);
+       return;
+     }
+ 
+   get_constraint_for (ptr, results);
+   if (rhsoffset == 0)
+     return;
+ 
+   /* As we are eventually appending to the solution do not use
+      VEC_iterate here.  */
+   n = VEC_length (ce_s, *results);
+   for (j = 0; j < n; j++)
+     {
+       varinfo_t curr;
+       c = VEC_index (ce_s, *results, j);
+       curr = get_varinfo (c->var);
+ 
+       if (c->type == ADDRESSOF
+ 	  && !curr->is_full_var)
+ 	{
+ 	  varinfo_t temp, curr = get_varinfo (c->var);
+ 
+ 	  /* Search the sub-field which overlaps with the
+ 	     pointed-to offset.  As we deal with positive offsets
+ 	     only, we can start the search from the current variable.  */
+ 	  temp = first_vi_for_offset (curr, curr->offset + rhsoffset);
+ 
+ 	  /* If the result is outside of the variable we have to provide
+ 	     a conservative result, as the variable is still reachable
+ 	     from the resulting pointer (even though it technically
+ 	     cannot point to anything).  The last sub-field is such
+ 	     a conservative result.
+ 	     ???  If we always had a sub-field for &object + 1 then
+ 	     we could represent this in a more precise way.  */
+ 	  if (temp == NULL)
+ 	    {
+ 	      temp = curr;
+ 	      while (temp->next != NULL)
+ 		temp = temp->next;
+ 	      continue;
+ 	    }
+ 
+ 	  /* If the found variable is not exactly at the pointed to
+ 	     result, we have to include the next variable in the
+ 	     solution as well.  Otherwise two increments by offset / 2
+ 	     do not result in the same or a conservative superset
+ 	     solution.  */
+ 	  if (temp->offset != curr->offset + rhsoffset
+ 	      && temp->next != NULL)
+ 	    {
+ 	      struct constraint_expr c2;
+ 	      c2.var = temp->next->id;
+ 	      c2.type = ADDRESSOF;
+ 	      c2.offset = 0;
+ 	      VEC_safe_push (ce_s, heap, *results, &c2);
+ 	    }
+ 	  c->var = temp->id;
+ 	  c->offset = 0;
+ 	}
+       else if (c->type == ADDRESSOF
+ 	       /* If this varinfo represents a full variable just use it.  */
+ 	       && curr->is_full_var)
+ 	c->offset = 0;
+       else
+ 	c->offset = rhsoffset;
+     }
+ }
+ 
+ 
  /* Given a COMPONENT_REF T, return the constraint_expr for it.  */
  
  static void
***************
*** 2682,2688 ****
    if (TREE_CODE (t) != ADDR_EXPR && result->type == ADDRESSOF)
      result->type = SCALAR;
  
!   if (result->type == SCALAR)
      {
        /* In languages like C, you can access one past the end of an
  	 array.  You aren't allowed to dereference it, so we can
--- 2811,2821 ----
    if (TREE_CODE (t) != ADDR_EXPR && result->type == ADDRESSOF)
      result->type = SCALAR;
  
!   if (result->type == SCALAR
!       && get_varinfo (result->var)->is_full_var)
!     /* For single-field vars do not bother about the offset.  */
!     result->offset = 0;
!   else if (result->type == SCALAR)
      {
        /* In languages like C, you can access one past the end of an
  	 array.  You aren't allowed to dereference it, so we can
***************
*** 2801,2833 ****
  	      struct constraint_expr *c;
  	      unsigned int i;
  	      tree exp = TREE_OPERAND (t, 0);
- 	      tree pttype = TREE_TYPE (TREE_TYPE (t));
  
  	      get_constraint_for (exp, results);
  
- 
- 	      /* Complex types are special. Taking the address of one
- 		 allows you to access either part of it through that
- 		 pointer.  */
- 	      if (VEC_length (ce_s, *results) == 1 &&
- 		  TREE_CODE (pttype) == COMPLEX_TYPE)
- 		{
- 		  struct constraint_expr *origrhs;
- 		  varinfo_t origvar;
- 		  struct constraint_expr tmp;
- 
- 		  gcc_assert (VEC_length (ce_s, *results) == 1);
- 		  origrhs = VEC_last (ce_s, *results);
- 		  tmp = *origrhs;
- 		  VEC_pop (ce_s, *results);
- 		  origvar = get_varinfo (origrhs->var);
- 		  for (; origvar; origvar = origvar->next)
- 		    {
- 		      tmp.var = origvar->id;
- 		      VEC_safe_push (ce_s, heap, *results, &tmp);
- 		    }
- 		}
- 
  	      for (i = 0; VEC_iterate (ce_s, *results, i, c); i++)
  		{
  		  if (c->type == DEREF)
--- 2934,2942 ----
***************
*** 2943,2948 ****
--- 3052,3067 ----
  	    }
  	  }
        }
+     case tcc_binary:
+       {
+ 	if (TREE_CODE (t) == POINTER_PLUS_EXPR)
+ 	  {
+ 	    get_constraint_for_ptr_offset (TREE_OPERAND (t, 0),
+ 					   TREE_OPERAND (t, 1), results);
+ 	    return;
+ 	  }
+ 	break;
+       }
      case tcc_exceptional:
        {
  	switch (TREE_CODE (t))
***************
*** 3512,3590 ****
  }
  
  
- /* Handle pointer arithmetic EXPR when creating aliasing constraints.
-    Expressions of the type PTR + CST can be handled in two ways:
- 
-    1- If the constraint for PTR is ADDRESSOF for a non-structure
-       variable, then we can use it directly because adding or
-       subtracting a constant may not alter the original ADDRESSOF
-       constraint (i.e., pointer arithmetic may not legally go outside
-       an object's boundaries).
- 
-    2- If the constraint for PTR is ADDRESSOF for a structure variable,
-       then if CST is a compile-time constant that can be used as an
-       offset, we can determine which sub-variable will be pointed-to
-       by the expression.
- 
-    Return true if the expression is handled.  For any other kind of
-    expression, return false so that each operand can be added as a
-    separate constraint by the caller.  */
- 
- static bool
- handle_ptr_arith (VEC (ce_s, heap) *lhsc, tree expr)
- {
-   tree op0, op1;
-   struct constraint_expr *c, *c2;
-   unsigned int i = 0;
-   unsigned int j = 0;
-   VEC (ce_s, heap) *temp = NULL;
-   unsigned HOST_WIDE_INT rhsunitoffset, rhsoffset;
- 
-   if (TREE_CODE (expr) != POINTER_PLUS_EXPR)
-     return false;
- 
-   op0 = TREE_OPERAND (expr, 0);
-   op1 = TREE_OPERAND (expr, 1);
-   gcc_assert (POINTER_TYPE_P (TREE_TYPE (op0)));
- 
-   /* If the offset is not a non-negative integer constant that fits
-      in a HOST_WIDE_INT, we cannot handle it here.  */
-   if (!host_integerp (op1, 1))
-     return false;
- 
-   /* Make sure the bit-offset also fits.  */
-   rhsunitoffset = TREE_INT_CST_LOW (op1);
-   rhsoffset = rhsunitoffset * BITS_PER_UNIT;
-   if (rhsunitoffset != rhsoffset / BITS_PER_UNIT)
-     return false;
- 
-   get_constraint_for (op0, &temp);
- 
-   for (i = 0; VEC_iterate (ce_s, lhsc, i, c); i++)
-     for (j = 0; VEC_iterate (ce_s, temp, j, c2); j++)
-       {
- 	if (c2->type == ADDRESSOF && rhsoffset != 0)
- 	  {
- 	    varinfo_t temp = get_varinfo (c2->var);
- 
- 	    /* An access one after the end of an array is valid,
- 	       so simply punt on accesses we cannot resolve.  */
- 	    temp = first_vi_for_offset (temp, rhsoffset);
- 	    if (temp == NULL)
- 	      continue;
- 	    c2->var = temp->id;
- 	    c2->offset = 0;
- 	  }
- 	else
- 	  c2->offset = rhsoffset;
- 	process_constraint (new_constraint (*c, *c2));
-       }
- 
-   VEC_free (ce_s, heap, temp);
- 
-   return true;
- }
- 
  /* For non-IPA mode, generate constraints necessary for a call on the
     RHS.  */
  
--- 3631,3636 ----
***************
*** 3815,3824 ****
        tree rhsop = GIMPLE_STMT_OPERAND (t, 1);
        int i;
  
!       if ((AGGREGATE_TYPE_P (TREE_TYPE (lhsop))
! 	   || TREE_CODE (TREE_TYPE (lhsop)) == COMPLEX_TYPE)
! 	  && (AGGREGATE_TYPE_P (TREE_TYPE (rhsop))
! 	      || TREE_CODE (TREE_TYPE (lhsop)) == COMPLEX_TYPE))
  	{
  	  do_structure_copy (lhsop, rhsop);
  	}
--- 3861,3868 ----
        tree rhsop = GIMPLE_STMT_OPERAND (t, 1);
        int i;
  
!       if (AGGREGATE_TYPE_P (TREE_TYPE (lhsop))
! 	  && AGGREGATE_TYPE_P (TREE_TYPE (rhsop)))
  	{
  	  do_structure_copy (lhsop, rhsop);
  	}
***************
*** 3842,3847 ****
--- 3886,3892 ----
  		  case tcc_expression:
  		  case tcc_vl_exp:
  		  case tcc_unary:
+ 		  case tcc_binary:
  		      {
  			unsigned int j;
  
***************
*** 3854,3874 ****
  			    for (k = 0; VEC_iterate (ce_s, rhsc, k, c2); k++)
  			      process_constraint (new_constraint (*c, *c2));
  			  }
- 
  		      }
  		    break;
  
- 		  case tcc_binary:
- 		      {
- 			/* For pointer arithmetic of the form
- 			   PTR + CST, we can simply use PTR's
- 			   constraint because pointer arithmetic is
- 			   not allowed to go out of bounds.  */
- 			if (handle_ptr_arith (lhsc, rhsop))
- 			  break;
- 		      }
- 		    /* FALLTHRU  */
- 
  		  /* Otherwise, walk each operand.  Notice that we
  		     can't use the operand interface because we need
  		     to process expressions other than simple operands
--- 3899,3907 ----
***************
*** 4257,4264 ****
    stats.total_vars++;
  
    /* If it's varargs, we don't know how many arguments it has, so we
!      can't do much.
!   */
    if (is_varargs)
      {
        vi->fullsize = ~0;
--- 4290,4296 ----
    stats.total_vars++;
  
    /* If it's varargs, we don't know how many arguments it has, so we
!      can't do much.  */
    if (is_varargs)
      {
        vi->fullsize = ~0;
***************
*** 4292,4297 ****
--- 4324,4330 ----
        VEC_safe_push (varinfo_t, heap, varmap, argvi);
        argvi->offset = i;
        argvi->size = 1;
+       argvi->is_full_var = true;
        argvi->fullsize = vi->fullsize;
        argvi->has_union = false;
        insert_into_field_list_sorted (vi, argvi);
***************
*** 4329,4334 ****
--- 4362,4368 ----
        resultvi->offset = i;
        resultvi->size = 1;
        resultvi->fullsize = vi->fullsize;
+       resultvi->is_full_var = true;
        resultvi->has_union = false;
        insert_into_field_list_sorted (vi, resultvi);
        stats.total_vars ++;
***************
*** 4464,4469 ****
--- 4498,4504 ----
  	  vi->is_unknown_size_var = 1;
  	  vi->fullsize = ~0;
  	  vi->size = ~0;
+ 	  vi->is_full_var = true;
  	  VEC_free (fieldoff_s, heap, fieldstack);
  	  return index;
  	}
***************
*** 4502,4507 ****
--- 4537,4544 ----
  	  stats.total_vars++;
  	}
      }
+   else
+     vi->is_full_var = true;
  
    VEC_free (fieldoff_s, heap, fieldstack);
  
***************
*** 4749,4765 ****
  	      && (sv = get_subvars_for_var (vi->decl)))
  	    {
  	      /* If VI->DECL is an aggregate for which we created
! 		 SFTs, add the SFT corresponding to VI->OFFSET.
  		 If we didn't do field-sensitive PTA we need to to
  		 add all overlapping SFTs.  */
  	      unsigned int j;
! 	      tree sft = get_first_overlapping_subvar (sv, vi->offset,
! 						       vi->size, &j);
  	      gcc_assert (sft);
  	      for (; VEC_iterate (tree, sv, j, sft); ++j)
  		{
  		  if (SFT_OFFSET (sft) > vi->offset
! 		      && vi->size <= SFT_OFFSET (sft) - vi->offset)
  		    break;
  
  		  bitmap_set_bit (into, DECL_UID (sft));
--- 4786,4807 ----
  	      && (sv = get_subvars_for_var (vi->decl)))
  	    {
  	      /* If VI->DECL is an aggregate for which we created
! 		 SFTs, add the SFT corresponding to VI->OFFSET (the
! 		 pointed-to location) and the access size.
  		 If we didn't do field-sensitive PTA we need to to
  		 add all overlapping SFTs.  */
  	      unsigned int j;
! 	      unsigned HOST_WIDE_INT size = -1;
! 	      tree sft, tsize = TYPE_SIZE (TREE_TYPE (TREE_TYPE (ptr)));
! 	      if (tsize
! 		  && host_integerp (tsize, 1))
! 		size = TREE_INT_CST_LOW (tsize);
! 	      sft = get_first_overlapping_subvar (sv, vi->offset, size, &j);
  	      gcc_assert (sft);
  	      for (; VEC_iterate (tree, sv, j, sft); ++j)
  		{
  		  if (SFT_OFFSET (sft) > vi->offset
! 		      && size <= SFT_OFFSET (sft) - vi->offset)
  		    break;
  
  		  bitmap_set_bit (into, DECL_UID (sft));
***************
*** 5156,5161 ****
--- 5198,5205 ----
  static void
  init_alias_vars (void)
  {
+   use_field_sensitive = (MAX_FIELDS_FOR_FIELD_SENSITIVE > 1);
+ 
    bitmap_obstack_initialize (&pta_obstack);
    bitmap_obstack_initialize (&oldpta_obstack);
    bitmap_obstack_initialize (&predbitmap_obstack);
Index: gcc-4_3-branch/gcc/testsuite/gcc.dg/torture/pr37868.c
===================================================================
*** /dev/null	1970-01-01 00:00:00.000000000 +0000
--- gcc-4_3-branch/gcc/testsuite/gcc.dg/torture/pr37868.c	2008-10-22 15:28:30.000000000 +0200
***************
*** 0 ****
--- 1,28 ----
+ /* { dg-do run } */
+ /* { dg-options "-fno-strict-aliasing" } */
+ 
+ extern void abort (void);
+ 
+ struct X {
+   unsigned char pad : 4;
+   unsigned int a : 32;
+   unsigned int b : 24;
+   unsigned int c : 6;
+ } __attribute__((packed));
+ 
+ int main (void)
+ {
+   struct X x;
+   unsigned int bad_bits;
+ 
+   x.pad = -1;
+   x.a = -1;
+   x.b = -1;
+   x.c = -1;
+ 
+   bad_bits = ((unsigned int)-1) ^ *(1+(unsigned int *) &x);
+   if (bad_bits != 0)
+     abort ();
+   return 0;
+ }
+ 
Index: gcc-4_3-branch/gcc/testsuite/gcc.c-torture/execute/pr38048-1.c
===================================================================
*** gcc-4_3-branch/gcc/testsuite/gcc.c-torture/execute/pr38048-1.c	(revision 0)
--- gcc-4_3-branch/gcc/testsuite/gcc.c-torture/execute/pr38048-1.c	(revision 0)
***************
*** 0 ****
--- 1,22 ----
+ extern void abort(void);
+ 
+ int foo ()
+ {
+   int mat[2][1];
+   int (*a)[1] = mat;
+   int det = 0;
+   int i;
+   mat[0][0] = 1;
+   mat[1][0] = 2;
+   for (i = 0; i < 2; ++i)
+     det += a[i][0];
+   return det;
+ }
+ 
+ int main()
+ {
+   if (foo () != 3)
+     abort ();
+   return 0;
+ }
+ 
Index: gcc-4_3-branch/gcc/testsuite/gcc.c-torture/execute/pr38048-2.c
===================================================================
*** gcc-4_3-branch/gcc/testsuite/gcc.c-torture/execute/pr38048-2.c	(revision 0)
--- gcc-4_3-branch/gcc/testsuite/gcc.c-torture/execute/pr38048-2.c	(revision 0)
***************
*** 0 ****
--- 1,28 ----
+ extern void abort (void);
+ 
+ static int inv_J(int a[][2])
+ {
+   int i, j;
+   int det = 0.0;
+    for (j=0; j<2; ++j)
+      det += a[j][0] + a[j][1];
+   return det;
+ }
+ 
+ int foo()
+ {
+   int mat[2][2];
+   mat[0][0] = 1;
+   mat[0][1] = 2;
+   mat[1][0] = 4;
+   mat[1][1] = 8;
+   return inv_J(mat);
+ }
+ 
+ int main()
+ {
+   if (foo () != 15)
+     abort ();
+   return 0;
+ }
+ 

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH][4.3][RFT] Fix PR37868, backport some PTA fixes
  2008-11-20 13:20     ` Richard Guenther
@ 2008-11-20 13:23       ` Eric Botcazou
  2008-12-01  9:28         ` Matthias Klose
  0 siblings, 1 reply; 10+ messages in thread
From: Eric Botcazou @ 2008-11-20 13:23 UTC (permalink / raw)
  To: Richard Guenther; +Cc: gcc-patches

> Successfully tested on our other architectures and with a re-build of
> openSUSE packages.  Applied to the branch.

I'll be monitoring what happens for Ada on other architectures as well.

-- 
Eric Botcazou

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH][4.3][RFT] Fix PR37868, backport some PTA fixes
  2008-11-20 13:23       ` Eric Botcazou
@ 2008-12-01  9:28         ` Matthias Klose
  2008-12-01 10:37           ` Eric Botcazou
  0 siblings, 1 reply; 10+ messages in thread
From: Matthias Klose @ 2008-12-01  9:28 UTC (permalink / raw)
  To: Eric Botcazou; +Cc: Richard Guenther, gcc-patches

Eric Botcazou schrieb:
>> Successfully tested on our other architectures and with a re-build of
>> openSUSE packages.  Applied to the branch.
> 
> I'll be monitoring what happens for Ada on other architectures as well.

PR37868 still fails on the 4.3 branch and the trunk, for a sparc-linux biarch
compiler defaulting to 32bit.

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH][4.3][RFT] Fix PR37868, backport some PTA fixes
  2008-12-01  9:28         ` Matthias Klose
@ 2008-12-01 10:37           ` Eric Botcazou
  0 siblings, 0 replies; 10+ messages in thread
From: Eric Botcazou @ 2008-12-01 10:37 UTC (permalink / raw)
  To: Matthias Klose; +Cc: gcc-patches, Richard Guenther

> PR37868 still fails on the 4.3 branch and the trunk, for a sparc-linux
> biarch compiler defaulting to 32bit.

Yes, the testcase doesn't pass on Solaris either, 32-bit or 64-bit.  I'll take 
a look shortly.

-- 
Eric Botcazou

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH][4.3][RFT] Fix PR37868, backport some PTA fixes
  2008-10-22 20:09 [PATCH][4.3][RFT] Fix PR37868, backport some PTA fixes Richard Guenther
  2008-10-25 18:29 ` Eric Botcazou
@ 2008-12-03 10:12 ` Eric Botcazou
  2008-12-03 10:25   ` Richard Guenther
  1 sibling, 1 reply; 10+ messages in thread
From: Eric Botcazou @ 2008-12-03 10:12 UTC (permalink / raw)
  To: Richard Guenther; +Cc: gcc-patches

> --- gcc-4_3-branch/gcc/testsuite/gcc.dg/torture/pr37868.c	2008-10-22
> 15:28:30.000000000 +0200 ***************
> *** 0 ****
> --- 1,28 ----
> + /* { dg-do run } */
> + /* { dg-options "-fno-strict-aliasing" } */
> +
> + extern void abort (void);
> +
> + struct X {
> +   unsigned char pad : 4;
> +   unsigned int a : 32;
> +   unsigned int b : 24;
> +   unsigned int c : 6;
> + } __attribute__((packed));
> +
> + int main (void)
> + {
> +   struct X x;
> +   unsigned int bad_bits;
> +
> +   x.pad = -1;
> +   x.a = -1;
> +   x.b = -1;
> +   x.c = -1;
> +
> +   bad_bits = ((unsigned int)-1) ^ *(1+(unsigned int *) &x);
> +   if (bad_bits != 0)
> +     abort ();
> +   return 0;
> + }
> +

Any particular reason for the __attribute__((packed)) on the structure?  This 
causes it to be given alignment 8 so

*(unsigned int *) &x

may raise SIGBUS on strict-alignment platforms (e.g. SPARC).  Removing it 
shouldn't change the internal layout and is sufficient since the structure 
contains 'unsigned int' bitfields.

-- 
Eric Botcazou

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH][4.3][RFT] Fix PR37868, backport some PTA fixes
  2008-12-03 10:12 ` Eric Botcazou
@ 2008-12-03 10:25   ` Richard Guenther
  2008-12-03 11:03     ` Eric Botcazou
  0 siblings, 1 reply; 10+ messages in thread
From: Richard Guenther @ 2008-12-03 10:25 UTC (permalink / raw)
  To: Eric Botcazou; +Cc: gcc-patches

On Wed, 3 Dec 2008, Eric Botcazou wrote:

> > --- gcc-4_3-branch/gcc/testsuite/gcc.dg/torture/pr37868.c	2008-10-22
> > 15:28:30.000000000 +0200 ***************
> > *** 0 ****
> > --- 1,28 ----
> > + /* { dg-do run } */
> > + /* { dg-options "-fno-strict-aliasing" } */
> > +
> > + extern void abort (void);
> > +
> > + struct X {
> > +   unsigned char pad : 4;
> > +   unsigned int a : 32;
> > +   unsigned int b : 24;
> > +   unsigned int c : 6;
> > + } __attribute__((packed));
> > +
> > + int main (void)
> > + {
> > +   struct X x;
> > +   unsigned int bad_bits;
> > +
> > +   x.pad = -1;
> > +   x.a = -1;
> > +   x.b = -1;
> > +   x.c = -1;
> > +
> > +   bad_bits = ((unsigned int)-1) ^ *(1+(unsigned int *) &x);
> > +   if (bad_bits != 0)
> > +     abort ();
> > +   return 0;
> > + }
> > +
> 
> Any particular reason for the __attribute__((packed)) on the structure?  This 
> causes it to be given alignment 8 so
> 
> *(unsigned int *) &x
> 
> may raise SIGBUS on strict-alignment platforms (e.g. SPARC).  Removing it 
> shouldn't change the internal layout and is sufficient since the structure 
> contains 'unsigned int' bitfields.

I think dependent on ABI the char bitfield may not be packed together
with the int bitfields.  But, if you can check a 4.3 version without the
backported fix and simply replacing the char bitfield with an integer
one (that shouldn't change the bug) and it still breaks such a change
would be fine (and then obviously the packed attribute can be removed).

Thanks,
Richard.

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH][4.3][RFT] Fix PR37868, backport some PTA fixes
  2008-12-03 10:25   ` Richard Guenther
@ 2008-12-03 11:03     ` Eric Botcazou
  0 siblings, 0 replies; 10+ messages in thread
From: Eric Botcazou @ 2008-12-03 11:03 UTC (permalink / raw)
  To: Richard Guenther; +Cc: gcc-patches

> I think dependent on ABI the char bitfield may not be packed together
> with the int bitfields.  But, if you can check a 4.3 version without the
> backported fix and simply replacing the char bitfield with an integer
> one (that shouldn't change the bug) and it still breaks such a change
> would be fine (and then obviously the packed attribute can be removed).

OK, reverting the patch and changing (or not) the 'unsigned char' bitfield to 
an 'unsigned int' yields on the 4.3 branch for x86:

FAIL: gcc.dg/torture/pr37868.c  -O2  execution test
FAIL: gcc.dg/torture/pr37868.c  -O3 -fomit-frame-pointer  execution test
FAIL: gcc.dg/torture/pr37868.c  -O3 -g  execution test
FAIL: gcc.dg/torture/pr37868.c  -Os  execution test

Then removing the __attribute__((packed)) makes the failures go away again!

It looks like I misremembered 6.7.2.1 (10): in the structure

struct X {
  unsigned int pad : 4;
  unsigned int a : 32;
  unsigned int b : 24;
  unsigned int c : 6;
};

'a' is placed at the start of the next 'unsigned int' (this doesn't happen up 
to and including 28 bits).

I'm just going to XFAIL the testcase on SPARC.

-- 
Eric Botcazou

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2008-12-03 11:03 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2008-10-22 20:09 [PATCH][4.3][RFT] Fix PR37868, backport some PTA fixes Richard Guenther
2008-10-25 18:29 ` Eric Botcazou
2008-11-03 12:54   ` Richard Guenther
2008-11-20 13:20     ` Richard Guenther
2008-11-20 13:23       ` Eric Botcazou
2008-12-01  9:28         ` Matthias Klose
2008-12-01 10:37           ` Eric Botcazou
2008-12-03 10:12 ` Eric Botcazou
2008-12-03 10:25   ` Richard Guenther
2008-12-03 11:03     ` Eric Botcazou

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).