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][improved-aliasing-branch] RFC: Array aliasing (take N)


This is the latest incarnation of the array aliasing patch.  It adds
some precision over the previous versions by enhancing (locally in
tree-dfa.c for now) get_inner_reference to give an upper (constant) bound
for variable offset accesses.  This information is used to constrain the
set of virtual defs created for f.i.

 struct {
   int i;
   struct {
     int j;
     int a[2];
     int k;
   } a[2];
   int l;
 } a;

 a.a[i].a[1] = 0;

where V_MAY_DEFs are only emitted for a.a[0].a[1], a.a[0].k,
a.a[1].j, a.a[1].a[0] and a.a[1].a[1], instead of all SFTs
with offsets greater than a.a[0].a[1] as done previously.

I have done SPEC testing of the patch vs. an unpatched IAB
with -O2, results attached.  As expected, we improve on mesa
and eon, while we regress on sixtrack and crafty.

Bootstrapped and regtested on x86_64-unknown-linux-gnu and
i686-pc-linux-gnu.

The patch is large, piecewise merging is possible starting
with the changes to struct fieldoff and the changes to
get_inner_reference/dfa_get_inner_reference (dependent on
the preference, I can try merging all into the expr.c version
or specialize the dfa version even more for the use in
aliasing).

Comments?  Ok in principle for IAB?  Ok in principle for
mainline after IAB merge (which I heared starts soon)?
(after an ok in principle I'll split the patch up -- I did so
once before, for 4.1, so I didn't want to waste my time
again before a principle agreement on the ideas of the patch)

Thanks,
Richard.


2005-11-30  Richard Guenther  <rguenther@suse.de>

	PR tree-optimization/22548
	PR tree-optimization/22555
	* Makefile.in (tree-ssa-structalias.o): Depend on $(PARAMS_H).
	* expr.c (get_inner_reference): Fold constant offsets
        in COMPONENT_REF and ARRAY_REF into bit_offset, if possible.
        Handles a.a[1].a[i].
	* params.def (salias-max-array-elements): New parameter.
	* params.h (SALIAS_MAX_ARRAY_ELEMENTS): Define.
	* doc/invoke.texi (salias-max-array-elements): Document.
	* tree-dfa.c (dfa_get_inner_reference): New function,
	get_inner_reference with more precision.
	(okay_component_ref_for_subvars): Use it.
	* tree-flow-inline.h (var_can_have_subvars): We also handle
	arrays now.
	* tree-flow.h (struct fieldoff): Use separate type and size
	field instead of storing FIELD_DECL in field.
	* tree-ssa-alias.c (create_sft): We now take field type as
	2nd argument.
	(find_used_portions): Handle ARRAY_REF like COMPONENT_REF.
	Use more precise information from get_inner_reference.
	(create_overlap_variables_for):  Adjust for struct fieldoff now
	storing field type and size.  Adjust call to create_sft.
	* tree-ssa-structalias.c (create_variable_info_for): Likewise.
	(fieldoff_compare): Likewise.
	(push_fields_onto_fieldstack): Likewise.  Handle ARRAY_TYPE.
	(params.h): Include.
	(find_func_aliases): Remove unused need_anyoffset.  Handle
	multiple constraints from ARRAY_REF.
	(get_constraint_for): For ADDR_EXPR operating on something
	containing an ARRAY_REF, add all subvars to the solution.
	(handle_ptr_arith): Handle ARRAY_TYPE like RECORD_TYPE types,
	for accesses beyond the end of an array simply give up.
	* tree-ssa-operands.c (parse_ssa_operands): Handle ARRAY_REF
	for creating MUST_DEFs.
	(get_expr_operands): Treat ARRAY_REF like COMPONENT_REF wrt subvars.
	* tree-ssa-loop.c (pass_iv_optimize): Schedule TODO_update_ssa.

	* gcc.dg/tree-ssa/alias-[456789].c: New testcases.
	* gcc.dg/tree-ssa/alias-1[012].c: Likewise.

Index: gcc/doc/invoke.texi
===================================================================
*** gcc/doc/invoke.texi	(revision 107713)
--- gcc/doc/invoke.texi	(working copy)
*************** The maximum number of fields in a variab
*** 5726,5731 ****
--- 5726,5735 ----
  structure accesses for which structure aliasing will consider trying 
  to track each field.  The default is 5
  
+ @item salias-max-array-elements
+ The maximum number of elements an array can have and its elements
+ still be tracked individually by structure aliasing. The default is 4
+ 
  @item sra-max-structure-size
  The maximum structure size, in bytes, at which the scalar replacement
  of aggregates (SRA) optimization will perform block copies.  The
Index: gcc/params.h
===================================================================
*** gcc/params.h	(revision 107713)
--- gcc/params.h	(working copy)
*************** typedef enum compiler_param
*** 91,96 ****
--- 91,98 ----
  /* Macros for the various parameters.  */
  #define SALIAS_MAX_IMPLICIT_FIELDS \
    PARAM_VALUE (PARAM_SALIAS_MAX_IMPLICIT_FIELDS)
+ #define SALIAS_MAX_ARRAY_ELEMENTS \
+   PARAM_VALUE (PARAM_SALIAS_MAX_ARRAY_ELEMENTS)
  #define SRA_MAX_STRUCTURE_SIZE \
    PARAM_VALUE (PARAM_SRA_MAX_STRUCTURE_SIZE)
  #define SRA_MAX_STRUCTURE_COUNT \
Index: gcc/tree-ssa-alias.c
===================================================================
*** gcc/tree-ssa-alias.c	(revision 107713)
--- gcc/tree-ssa-alias.c	(working copy)
*************** get_or_create_used_part_for (size_t uid)
*** 2747,2760 ****
  }
  
  
! /* Create and return a structure sub-variable for field FIELD of
     variable VAR.  */
  
  static tree
  create_sft (tree var, tree field)
  {
    var_ann_t ann;
!   tree subvar = create_tag_raw (STRUCT_FIELD_TAG, TREE_TYPE (field), "SFT");
  
    /* We need to copy the various flags from VAR to SUBVAR, so that
       they are is_global_var iff the original variable was.  */
--- 2747,2760 ----
  }
  
  
! /* Create and return a structure sub-variable for field type FIELD of
     variable VAR.  */
  
  static tree
  create_sft (tree var, tree field)
  {
    var_ann_t ann;
!   tree subvar = create_tag_raw (STRUCT_FIELD_TAG, field, "SFT");
  
    /* We need to copy the various flags from VAR to SUBVAR, so that
       they are is_global_var iff the original variable was.  */
*************** create_overlap_variables_for (tree var)
*** 2811,2818 ****
  
        for (i = 0; VEC_iterate (fieldoff_s, fieldstack, i, fo); i++)
  	{
! 	  if (!DECL_SIZE (fo->field) 
! 	      || TREE_CODE (DECL_SIZE (fo->field)) != INTEGER_CST
  	      || fo->offset < 0)
  	    {
  	      notokay = true;
--- 2811,2818 ----
  
        for (i = 0; VEC_iterate (fieldoff_s, fieldstack, i, fo); i++)
  	{
! 	  if (! fo->size
! 	      || TREE_CODE (fo->size) != INTEGER_CST
  	      || fo->offset < 0)
  	    {
  	      notokay = true;
*************** create_overlap_variables_for (tree var)
*** 2864,2871 ****
  	  HOST_WIDE_INT fosize;
  	  tree currfotype;
  
! 	  fosize = TREE_INT_CST_LOW (DECL_SIZE (fo->field));
! 	  currfotype = TREE_TYPE (fo->field);
  
  	  /* If this field isn't in the used portion,
  	     or it has the exact same offset and size as the last
--- 2864,2871 ----
  	  HOST_WIDE_INT fosize;
  	  tree currfotype;
  
! 	  fosize = TREE_INT_CST_LOW (fo->size);
! 	  currfotype = fo->type;
  
  	  /* If this field isn't in the used portion,
  	     or it has the exact same offset and size as the last
*************** create_overlap_variables_for (tree var)
*** 2882,2888 ****
  	  sv->offset = fo->offset;
  	  sv->size = fosize;
  	  sv->next = *subvars;
! 	  sv->var = create_sft (var, fo->field);
  
  	  if (dump_file)
  	    {
--- 2882,2888 ----
  	  sv->offset = fo->offset;
  	  sv->size = fosize;
  	  sv->next = *subvars;
! 	  sv->var = create_sft (var, fo->type);
  
  	  if (dump_file)
  	    {
*************** find_used_portions (tree *tp, int *walk_
*** 2928,2933 ****
--- 2928,2934 ----
    switch (TREE_CODE (*tp))
      {
      case COMPONENT_REF:
+     case ARRAY_REF:
        {
  	HOST_WIDE_INT bitsize;
  	HOST_WIDE_INT bitpos;
*************** find_used_portions (tree *tp, int *walk_
*** 2956,2961 ****
--- 2957,2984 ----
  	    *walk_subtrees = 0;
  	    return NULL_TREE;
  	  }
+ 	else if (DECL_P (ref) && offset && bitsize != -1)
+ 	  {
+ 	    if (DECL_SIZE (ref)
+ 		&& var_can_have_subvars (ref)
+ 		&& TREE_CODE (DECL_SIZE (ref)) == INTEGER_CST)
+ 	      {
+ 		used_part_t up;
+ 		size_t uid = DECL_UID (ref);
+ 
+ 		up = get_or_create_used_part_for (uid);
+ 
+ 		if (bitpos <= up->minused)
+ 		  up->minused = bitpos;
+ 		up->maxused = TREE_INT_CST_LOW (DECL_SIZE (ref));
+ 
+ 		up->implicit_uses = true;
+ 		up_insert (uid, up);
+ 
+ 		*walk_subtrees = 0;
+ 		return NULL_TREE;
+ 	      }
+ 	  }
  	else if (DECL_P (ref))
  	  {
  	    if (DECL_SIZE (ref)
Index: gcc/expr.c
===================================================================
*** gcc/expr.c	(revision 107713)
--- gcc/expr.c	(working copy)
*************** get_inner_reference (tree exp, HOST_WIDE
*** 5496,5501 ****
--- 5496,5502 ----
    tree size_tree = 0;
    enum machine_mode mode = VOIDmode;
    tree offset = size_zero_node;
+   tree coffset = size_zero_node;
    tree bit_offset = bitsize_zero_node;
    tree tem;
  
*************** get_inner_reference (tree exp, HOST_WIDE
*** 5555,5561 ****
  	    if (this_offset == 0)
  	      break;
  
! 	    offset = size_binop (PLUS_EXPR, offset, this_offset);
  	    bit_offset = size_binop (PLUS_EXPR, bit_offset,
  				     DECL_FIELD_BIT_OFFSET (field));
  
--- 5556,5566 ----
  	    if (this_offset == 0)
  	      break;
  
! 	    if (TREE_CODE (this_offset) == INTEGER_CST)
! 	      coffset = size_binop (PLUS_EXPR, coffset, this_offset); 
! 	    else
! 	      offset = size_binop (PLUS_EXPR, offset, this_offset);
! 
  	    bit_offset = size_binop (PLUS_EXPR, bit_offset,
  				     DECL_FIELD_BIT_OFFSET (field));
  
*************** get_inner_reference (tree exp, HOST_WIDE
*** 5577,5587 ****
  	    if (! integer_zerop (low_bound))
  	      index = fold_build2 (MINUS_EXPR, TREE_TYPE (index),
  				   index, low_bound);
! 
! 	    offset = size_binop (PLUS_EXPR, offset,
! 			         size_binop (MULT_EXPR,
! 					     convert (sizetype, index),
! 					     unit_size));
  	  }
  	  break;
  
--- 5582,5592 ----
  	    if (! integer_zerop (low_bound))
  	      index = fold_build2 (MINUS_EXPR, TREE_TYPE (index),
  				   index, low_bound);
! 	    index = size_binop (MULT_EXPR, convert (sizetype, index), unit_size);
! 	    if (TREE_CODE (index) == INTEGER_CST)
! 	      coffset = size_binop (PLUS_EXPR, coffset, index);
! 	    else
! 	      offset = size_binop (PLUS_EXPR, offset, index);
  	  }
  	  break;
  
*************** get_inner_reference (tree exp, HOST_WIDE
*** 5616,5631 ****
      }
   done:
  
!   /* If OFFSET is constant, see if we can return the whole thing as a
!      constant bit position.  Otherwise, split it up.  */
!   if (host_integerp (offset, 0)
!       && 0 != (tem = size_binop (MULT_EXPR, convert (bitsizetype, offset),
  				 bitsize_unit_node))
        && 0 != (tem = size_binop (PLUS_EXPR, tem, bit_offset))
        && host_integerp (tem, 0))
!     *pbitpos = tree_low_cst (tem, 0), *poffset = 0;
    else
!     *pbitpos = tree_low_cst (bit_offset, 0), *poffset = offset;
  
    *pmode = mode;
    return exp;
--- 5621,5644 ----
      }
   done:
  
!   /* See, if we can return COFFSET in the constant bit position, otherwise
!      fold into OFFSET.  */
!   if (host_integerp (coffset, 0)
!       && 0 != (tem = size_binop (MULT_EXPR, convert (bitsizetype, coffset),
  				 bitsize_unit_node))
        && 0 != (tem = size_binop (PLUS_EXPR, tem, bit_offset))
        && host_integerp (tem, 0))
!     {
!       *pbitpos = tree_low_cst (tem, 0);
!       *poffset = offset;
!     }
    else
!     {
!       *pbitpos = tree_low_cst (bit_offset, 0);
!       *poffset = size_binop (PLUS_EXPR, coffset, offset);
!     }
!   if (integer_zerop (*poffset))
!     *poffset = NULL_TREE;
  
    *pmode = mode;
    return exp;
Index: gcc/tree-flow-inline.h
===================================================================
*** gcc/tree-flow-inline.h	(revision 107713)
--- gcc/tree-flow-inline.h	(working copy)
*************** get_subvar_at (tree var, unsigned HOST_W
*** 1501,1508 ****
  static inline bool
  var_can_have_subvars (tree v)
  {
!   return (AGGREGATE_TYPE_P (TREE_TYPE (v)) &&
! 	  TREE_CODE (TREE_TYPE (v)) != ARRAY_TYPE);
  }
  
    
--- 1501,1507 ----
  static inline bool
  var_can_have_subvars (tree v)
  {
!   return (AGGREGATE_TYPE_P (TREE_TYPE (v)));
  }
  
    
Index: gcc/tree-dfa.c
===================================================================
*** gcc/tree-dfa.c	(revision 107713)
--- gcc/tree-dfa.c	(working copy)
*************** static void collect_dfa_stats (struct df
*** 78,83 ****
--- 78,88 ----
  static tree collect_dfa_stats_r (tree *, int *, void *);
  static tree find_vars_r (tree *, int *, void *);
  static void add_referenced_var (tree, struct walk_state *);
+ static tree dfa_get_inner_reference (tree exp, HOST_WIDE_INT *pbitsize,
+ 		     HOST_WIDE_INT *maxsize,
+ 		     HOST_WIDE_INT *pbitpos, tree *poffset,
+ 		     enum machine_mode *pmode, int *punsignedp,
+ 		     int *pvolatilep, bool keep_aligning);
  
  
  /* Global declarations.  */
*************** find_new_referenced_vars (tree *stmt_p)
*** 836,841 ****
--- 841,1064 ----
  }
  
  
+ /* Given an expression EXP that may be a COMPONENT_REF, a BIT_FIELD_REF,
+    an ARRAY_REF, or an ARRAY_RANGE_REF, look for nested operations of these
+    codes and find the ultimate containing object, which we return.
+ 
+    We set *PBITSIZE to the size in bits that we want, *PBITPOS to the
+    bit position, and *PUNSIGNEDP to the signedness of the field.
+    If the position of the field is variable, we store a tree
+    giving the variable offset (in units) in *POFFSET.
+    This offset is in addition to the bit position.
+    If the position is not variable, we store 0 in *POFFSET.
+ 
+    If any of the extraction expressions is volatile,
+    we store 1 in *PVOLATILEP.  Otherwise we don't change that.
+ 
+    If the field is a bit-field, *PMODE is set to VOIDmode.  Otherwise, it
+    is a mode that can be used to access the field.  In that case, *PBITSIZE
+    is redundant.
+ 
+    If the field describes a variable-sized object, *PMODE is set to
+    VOIDmode and *PBITSIZE is set to -1.  An access cannot be made in
+    this case, but the address of the object can be found.
+ 
+    *MAXSIZE is set to *PBITSIZE, if the position is not variable and
+    otherwise to the minimum value to have all possible accesses
+    within *PBITPOS and *PBITPOS + *MAXSIZE.  If it is not possible to
+    constrain *MAXSIZE, it is set to -1.
+ 
+    If KEEP_ALIGNING is true and the target is STRICT_ALIGNMENT, we don't
+    look through nodes that serve as markers of a greater alignment than
+    the one that can be deduced from the expression.  These nodes make it
+    possible for front-ends to prevent temporaries from being created by
+    the middle-end on alignment considerations.  For that purpose, the
+    normal operating mode at high-level is to always pass FALSE so that
+    the ultimate containing object is really returned; moreover, the
+    associated predicate handled_component_p will always return TRUE
+    on these nodes, thus indicating that they are essentially handled
+    by get_inner_reference.  TRUE should only be passed when the caller
+    is scanning the expression in order to build another representation
+    and specifically knows how to handle these nodes; as such, this is
+    the normal operating mode in the RTL expanders.  */
+ 
+ static tree
+ dfa_get_inner_reference (tree exp, HOST_WIDE_INT *pbitsize,
+ 		     HOST_WIDE_INT *maxsize,
+ 		     HOST_WIDE_INT *pbitpos, tree *poffset,
+ 		     enum machine_mode *pmode, int *punsignedp,
+ 		     int *pvolatilep, bool keep_aligning)
+ {
+   tree size_tree = 0;
+   enum machine_mode mode = VOIDmode;
+   tree offset = size_zero_node;
+   tree coffset = size_zero_node;
+   tree bit_offset = bitsize_zero_node;
+   tree tem;
+ 
+   /* First get the mode, signedness, and size.  We do this from just the
+      outermost expression.  */
+   if (TREE_CODE (exp) == COMPONENT_REF)
+     {
+       size_tree = DECL_SIZE (TREE_OPERAND (exp, 1));
+       if (! DECL_BIT_FIELD (TREE_OPERAND (exp, 1)))
+ 	mode = DECL_MODE (TREE_OPERAND (exp, 1));
+ 
+       *punsignedp = DECL_UNSIGNED (TREE_OPERAND (exp, 1));
+     }
+   else if (TREE_CODE (exp) == BIT_FIELD_REF)
+     {
+       size_tree = TREE_OPERAND (exp, 1);
+       *punsignedp = BIT_FIELD_REF_UNSIGNED (exp);
+     }
+   else
+     {
+       mode = TYPE_MODE (TREE_TYPE (exp));
+       *punsignedp = TYPE_UNSIGNED (TREE_TYPE (exp));
+ 
+       if (mode == BLKmode)
+ 	size_tree = TYPE_SIZE (TREE_TYPE (exp));
+       else
+ 	*pbitsize = GET_MODE_BITSIZE (mode);
+     }
+ 
+   if (size_tree != 0)
+     {
+       if (! host_integerp (size_tree, 1))
+ 	mode = BLKmode, *pbitsize = -1;
+       else
+ 	*pbitsize = tree_low_cst (size_tree, 1);
+     }
+   *maxsize = *pbitsize;
+ 
+   /* Compute cumulative bit-offset for nested component-refs and array-refs,
+      and find the ultimate containing object.  */
+   while (1)
+     {
+       switch (TREE_CODE (exp))
+ 	{
+ 	case BIT_FIELD_REF:
+ 	  bit_offset = size_binop (PLUS_EXPR, bit_offset,
+ 				   TREE_OPERAND (exp, 2));
+ 	  break;
+ 
+ 	case COMPONENT_REF:
+ 	  {
+ 	    tree field = TREE_OPERAND (exp, 1);
+ 	    tree this_offset = component_ref_field_offset (exp);
+ 
+ 	    /* If this field hasn't been filled in yet, don't go past it.
+ 	       This should only happen when folding expressions made during
+ 	       type construction.  */
+ 	    if (this_offset == 0)
+ 	      break;
+ 
+ 	    if (TREE_CODE (this_offset) == INTEGER_CST)
+ 	      coffset = size_binop (PLUS_EXPR, coffset, this_offset); 
+ 	    else
+ 	      /* ??? Handle this case for maxsize.  */
+ 	      offset = size_binop (PLUS_EXPR, offset, this_offset);
+ 
+ 	    bit_offset = size_binop (PLUS_EXPR, bit_offset,
+ 				     DECL_FIELD_BIT_OFFSET (field));
+ 
+ 	    /* ??? Right now we don't do anything with DECL_OFFSET_ALIGN.  */
+ 	  }
+ 	  break;
+ 
+ 	case ARRAY_REF:
+ 	case ARRAY_RANGE_REF:
+ 	  {
+ 	    tree index = TREE_OPERAND (exp, 1);
+ 	    tree low_bound = array_ref_low_bound (exp);
+ 	    tree unit_size = array_ref_element_size (exp);
+ 
+ 	    /* We assume all arrays have sizes that are a multiple of a byte.
+ 	       First subtract the lower bound, if any, in the type of the
+ 	       index, then convert to sizetype and multiply by the size of
+ 	       the array element.  */
+ 	    if (! integer_zerop (low_bound))
+ 	      index = fold_build2 (MINUS_EXPR, TREE_TYPE (index),
+ 				   index, low_bound);
+ 	    index = size_binop (MULT_EXPR, convert (sizetype, index), unit_size);
+ 	    if (TREE_CODE (index) == INTEGER_CST)
+ 	      coffset = size_binop (PLUS_EXPR, coffset, index);
+ 	    else
+ 	      {
+ 		tree asize = TYPE_SIZE (TREE_TYPE (TREE_OPERAND (exp, 0)));
+ 	        offset = size_binop (PLUS_EXPR, offset, index);
+ 		/* We need to adjust maxsize to the whole array bitsize.
+ 		   But we can subtract any constant offset seen sofar,
+ 		   because that would get us outside of the array otherwise.  */
+ 		if (*maxsize != -1
+ 		    && asize && host_integerp (asize, 1))
+ 		  {
+ 		    tree delta = size_binop (MULT_EXPR, fold_convert (bitsizetype, coffset),
+ 				 	     bitsize_unit_node);
+ 		    delta = size_binop (PLUS_EXPR, delta, bit_offset);
+ 		    gcc_assert (host_integerp (delta, 1));
+ 		    *maxsize = TREE_INT_CST_LOW (asize) - TREE_INT_CST_LOW (delta);
+ 		  }
+ 		else
+ 		  *maxsize = -1;
+ 	      }
+ 	  }
+ 	  break;
+ 
+ 	case REALPART_EXPR:
+ 	  break;
+ 
+ 	case IMAGPART_EXPR:
+ 	  bit_offset = size_binop (PLUS_EXPR, bit_offset,
+ 				   bitsize_int (*pbitsize));
+ 	  break;
+ 
+ 	case VIEW_CONVERT_EXPR:
+ 	  if (keep_aligning && STRICT_ALIGNMENT
+ 	      && (TYPE_ALIGN (TREE_TYPE (exp))
+ 	       > TYPE_ALIGN (TREE_TYPE (TREE_OPERAND (exp, 0))))
+ 	      && (TYPE_ALIGN (TREE_TYPE (TREE_OPERAND (exp, 0)))
+ 		  < BIGGEST_ALIGNMENT)
+ 	      && (TYPE_ALIGN_OK (TREE_TYPE (exp))
+ 		  || TYPE_ALIGN_OK (TREE_TYPE (TREE_OPERAND (exp, 0)))))
+ 	    goto done;
+ 	  break;
+ 
+ 	default:
+ 	  goto done;
+ 	}
+ 
+       /* If any reference in the chain is volatile, the effect is volatile.  */
+       if (TREE_THIS_VOLATILE (exp))
+ 	*pvolatilep = 1;
+ 
+       exp = TREE_OPERAND (exp, 0);
+     }
+  done:
+ 
+   /* See, if we can return COFFSET in the constant bit position, otherwise
+      fold into OFFSET.  */
+   if (host_integerp (coffset, 0)
+       && 0 != (tem = size_binop (MULT_EXPR, convert (bitsizetype, coffset),
+ 				 bitsize_unit_node))
+       && 0 != (tem = size_binop (PLUS_EXPR, tem, bit_offset))
+       && host_integerp (tem, 0))
+     {
+       *pbitpos = tree_low_cst (tem, 0);
+       *poffset = offset;
+     }
+   else
+     {
+       *pbitpos = tree_low_cst (bit_offset, 0);
+       *poffset = size_binop (PLUS_EXPR, coffset, offset);
+     }
+   if (integer_zerop (*poffset))
+     *poffset = NULL_TREE;
+ 
+   *pmode = mode;
+   return exp;
+ }
+ 
  /* If REF is a COMPONENT_REF for a structure that can have sub-variables, and
     we know where REF is accessing, return the variable in REF that has the
     sub-variables.  If the return value is not NULL, POFFSET will be the
*************** okay_component_ref_for_subvars (tree ref
*** 848,853 ****
--- 1071,1077 ----
  {
    tree result = NULL;
    HOST_WIDE_INT bitsize;
+   HOST_WIDE_INT maxsize;
    HOST_WIDE_INT bitpos;
    tree offset;
    enum machine_mode mode;
*************** okay_component_ref_for_subvars (tree ref
*** 857,864 ****
    gcc_assert (!SSA_VAR_P (ref));
    *poffset = 0;  
    *psize = (unsigned int) -1;
!   
!   ref = get_inner_reference (ref, &bitsize, &bitpos, &offset, &mode,
  			     &unsignedp, &volatilep, false);
    if (TREE_CODE (ref) == INDIRECT_REF)
      return result;
--- 1081,1089 ----
    gcc_assert (!SSA_VAR_P (ref));
    *poffset = 0;  
    *psize = (unsigned int) -1;
!  
!   ref = dfa_get_inner_reference (ref, &bitsize, &maxsize,
! 			     &bitpos, &offset, &mode,
  			     &unsignedp, &volatilep, false);
    if (TREE_CODE (ref) == INDIRECT_REF)
      return result;
*************** okay_component_ref_for_subvars (tree ref
*** 869,874 ****
--- 1094,1107 ----
        if (get_subvars_for_var (ref) != NULL)
  	return ref;
      }
+   else if (offset && bitsize != -1 && SSA_VAR_P (ref))
+     {
+       /* We assume the offset part is positive only.  */
+       *poffset = bitpos; 
+       *psize = (unsigned HOST_WIDE_INT) maxsize;
+       if (get_subvars_for_var (ref) != NULL)
+ 	return ref;
+     }
    else if (SSA_VAR_P (ref))
      {
        if (get_subvars_for_var (ref) != NULL)
Index: gcc/tree-flow.h
===================================================================
*** gcc/tree-flow.h	(revision 107713)
--- gcc/tree-flow.h	(working copy)
*************** tree maybe_fold_tmr (tree);
*** 897,903 ****
  
  struct fieldoff
  {
!   tree field;
    HOST_WIDE_INT offset;  
  };
  typedef struct fieldoff fieldoff_s;
--- 897,904 ----
  
  struct fieldoff
  {
!   tree type;
!   tree size;
    HOST_WIDE_INT offset;  
  };
  typedef struct fieldoff fieldoff_s;
Index: gcc/Makefile.in
===================================================================
*** gcc/Makefile.in	(revision 107713)
--- gcc/Makefile.in	(working copy)
*************** stor-layout.o : stor-layout.c $(CONFIG_H
*** 1744,1750 ****
  tree-ssa-structalias.o: tree-ssa-structalias.c tree-ssa-structalias.h \
     $(SYSTEM_H) $(CONFIG_H) $(GGC_H) $(TREE_H) $(TREE_FLOW_H) \
     $(TM_H) coretypes.h cgraph.h tree-pass.h $(TIMEVAR_H) \
!    gt-tree-ssa-structalias.h
  tree-ssa.o : tree-ssa.c $(TREE_FLOW_H) $(CONFIG_H) $(SYSTEM_H) \
     $(RTL_H) $(TREE_H) $(TM_P_H) $(EXPR_H) output.h $(DIAGNOSTIC_H) \
     toplev.h function.h $(TIMEVAR_H) $(TM_H) coretypes.h \
--- 1744,1750 ----
  tree-ssa-structalias.o: tree-ssa-structalias.c tree-ssa-structalias.h \
     $(SYSTEM_H) $(CONFIG_H) $(GGC_H) $(TREE_H) $(TREE_FLOW_H) \
     $(TM_H) coretypes.h cgraph.h tree-pass.h $(TIMEVAR_H) \
!    gt-tree-ssa-structalias.h $(PARAMS_H)
  tree-ssa.o : tree-ssa.c $(TREE_FLOW_H) $(CONFIG_H) $(SYSTEM_H) \
     $(RTL_H) $(TREE_H) $(TM_P_H) $(EXPR_H) output.h $(DIAGNOSTIC_H) \
     toplev.h function.h $(TIMEVAR_H) $(TM_H) coretypes.h \
Index: gcc/tree-ssa-structalias.c
===================================================================
*** gcc/tree-ssa-structalias.c	(revision 107713)
--- gcc/tree-ssa-structalias.c	(working copy)
*************** Foundation, Inc., 51 Franklin Street, Fi
*** 48,53 ****
--- 48,54 ----
  #include "timevar.h"
  #include "alloc-pool.h"
  #include "splay-tree.h"
+ #include "params.h"
  #include "tree-ssa-structalias.h"
  #include "cgraph.h"
  
*************** static struct constraint_expr
*** 2215,2220 ****
--- 2216,2222 ----
  get_constraint_exp_from_ssa_var (tree t)
  {
    struct constraint_expr cexpr;
+   tree heapvar;
  
    gcc_assert (SSA_VAR_P (t) || DECL_P (t));
  
*************** get_constraint_exp_from_ssa_var (tree t)
*** 2226,2232 ****
      return get_constraint_exp_from_ssa_var (SSA_NAME_VAR (t));
  
    cexpr.type = SCALAR;
!   
    cexpr.var = get_id_for_tree (t);
    /* If we determine the result is "anything", and we know this is readonly,
       say it points to readonly memory instead.  */
--- 2228,2234 ----
      return get_constraint_exp_from_ssa_var (SSA_NAME_VAR (t));
  
    cexpr.type = SCALAR;
! 
    cexpr.var = get_id_for_tree (t);
    /* If we determine the result is "anything", and we know this is readonly,
       say it points to readonly memory instead.  */
*************** get_constraint_for (tree t, VEC (ce_s, h
*** 2514,2519 ****
--- 2516,2540 ----
  	      unsigned int i;
  
  	      get_constraint_for (TREE_OPERAND (t, 0), results, anyoffset);
+ 	      if ((handled_component_p (TREE_OPERAND (t, 0))
+ 		   && ref_contains_array_ref (TREE_OPERAND (t, 0)))
+ 		  || TREE_CODE (TREE_TYPE (TREE_OPERAND (t, 0))) == ARRAY_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)
*************** handle_ptr_arith (VEC (ce_s, heap) *lhsc
*** 3174,3180 ****
  
    get_constraint_for (op0, &temp, NULL);
    if (POINTER_TYPE_P (TREE_TYPE (op0))
-       && TREE_CODE (TREE_TYPE (TREE_TYPE (op0))) == RECORD_TYPE
        && TREE_CODE (op1) == INTEGER_CST)
      {
        rhsoffset = TREE_INT_CST_LOW (op1) * BITS_PER_UNIT;
--- 3195,3200 ----
*************** handle_ptr_arith (VEC (ce_s, heap) *lhsc
*** 3187,3194 ****
  	if (c2->type == ADDRESSOF && rhsoffset != 0)
  	  {
  	    varinfo_t temp = get_varinfo (c2->var);
! 	    
! 	    gcc_assert (first_vi_for_offset (temp, rhsoffset) != NULL);
  	    c2->var = first_vi_for_offset (temp, rhsoffset)->id;
  	    c2->offset = 0;
  	  }
--- 3207,3218 ----
  	if (c2->type == ADDRESSOF && rhsoffset != 0)
  	  {
  	    varinfo_t temp = get_varinfo (c2->var);
! 
! 	    /* It is legal to access one past the end of an array.
! 	       And computing arbitrary addresses anyway.  */
! 	    /* gcc_assert (first_vi_for_offset (temp, rhsoffset) != NULL); */
! 	    if (first_vi_for_offset (temp, rhsoffset) == NULL)
! 	      continue;
  	    c2->var = first_vi_for_offset (temp, rhsoffset)->id;
  	    c2->offset = 0;
  	  }
*************** find_func_aliases (tree origt)
*** 3411,3423 ****
  		  case tcc_unary:
  		      {
  			unsigned int j;
- 			bool need_anyoffset = false;
  			tree strippedrhs = rhsop;
  			STRIP_NOPS (strippedrhs);
  			
! 			get_constraint_for (rhsop, &rhsc, &need_anyoffset);
  			if (TREE_CODE (strippedrhs) == ADDR_EXPR
! 			    && AGGREGATE_TYPE_P (TREE_TYPE (TREE_TYPE (strippedrhs))))
  			  {
  			    struct constraint_expr *origrhs;
  			    varinfo_t origvar;
--- 3435,3447 ----
  		  case tcc_unary:
  		      {
  			unsigned int j;
  			tree strippedrhs = rhsop;
  			STRIP_NOPS (strippedrhs);
  			
! 			get_constraint_for (rhsop, &rhsc, NULL);
  			if (TREE_CODE (strippedrhs) == ADDR_EXPR
! 			    && AGGREGATE_TYPE_P (TREE_TYPE (TREE_TYPE (strippedrhs)))
! 			    && VEC_length (ce_s, rhsc) == 1)
  			  {
  			    struct constraint_expr *origrhs;
  			    varinfo_t origvar;
*************** fieldoff_compare (const void *pa, const 
*** 3561,3568 ****
    if (foa->offset != fob->offset)
      return foa->offset - fob->offset;
  
!   foasize = TREE_INT_CST_LOW (DECL_SIZE (foa->field));
!   fobsize = TREE_INT_CST_LOW (DECL_SIZE (fob->field));
    return foasize - fobsize;
  }
  
--- 3585,3592 ----
    if (foa->offset != fob->offset)
      return foa->offset - fob->offset;
  
!   foasize = TREE_INT_CST_LOW (foa->size);
!   fobsize = TREE_INT_CST_LOW (fob->size);
    return foasize - fobsize;
  }
  
*************** push_fields_onto_fieldstack (tree type, 
*** 3590,3595 ****
--- 3614,3668 ----
    tree field;
    int count = 0;
  
+   if (TREE_CODE (type) == ARRAY_TYPE)
+     {
+       tree sz = TYPE_SIZE (type);
+       tree elsz = TYPE_SIZE (TREE_TYPE (type));
+       HOST_WIDE_INT nr;
+       int i;
+       if (! sz || ! host_integerp (sz, 1)
+ 	  || ! elsz || ! host_integerp (elsz, 1))
+ 	return 0;
+       nr = TREE_INT_CST_LOW (sz) / TREE_INT_CST_LOW (elsz);
+       if (nr > SALIAS_MAX_ARRAY_ELEMENTS)
+ 	return 0;
+       for (i = 0; i<nr; ++i)
+ 	{
+ 	bool push = false;
+ 	int pushed = 0;
+ 	
+ 	if (has_union 
+ 	    && (TREE_CODE (TREE_TYPE (type)) == QUAL_UNION_TYPE
+ 		|| TREE_CODE (TREE_TYPE (type)) == UNION_TYPE))
+ 	  *has_union = true;
+ 	
+ 	if (!AGGREGATE_TYPE_P (TREE_TYPE (type))) /* var_can_have_subvars */
+ 	  push = true;
+ 	else if (!(pushed = push_fields_onto_fieldstack
+ 		   (TREE_TYPE (type), fieldstack,
+ 		    offset + i * TREE_INT_CST_LOW (elsz), has_union)))
+ 	  /* Empty structures may have actual size, like in C++. So
+ 	     see if we didn't push any subfields and the size is
+ 	     nonzero, push the field onto the stack */
+ 	  push = true;
+ 	
+ 	if (push)
+ 	  {
+ 	    fieldoff_s *pair;
+ 
+ 	    pair = VEC_safe_push (fieldoff_s, heap, *fieldstack, NULL);
+ 	    pair->type = TREE_TYPE (type);
+ 	    pair->size = elsz;
+ 	    pair->offset = offset + i * TREE_INT_CST_LOW (elsz);
+ 	    count++;
+ 	  }
+ 	else
+ 	  count += pushed;
+ 	}
+       /*return 1;*/
+     }
+   else
+     {
    for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
      if (TREE_CODE (field) == FIELD_DECL)
        {
*************** push_fields_onto_fieldstack (tree type, 
*** 3618,3631 ****
  	    fieldoff_s *pair;
  
  	    pair = VEC_safe_push (fieldoff_s, heap, *fieldstack, NULL);
! 	    pair->field = field;
  	    pair->offset = offset + bitpos_of_field (field);
  	    count++;
  	  }
  	else
  	  count += pushed;
        }
! 
    return count;
  }
  
--- 3691,3705 ----
  	    fieldoff_s *pair;
  
  	    pair = VEC_safe_push (fieldoff_s, heap, *fieldstack, NULL);
! 	    pair->type = TREE_TYPE (field);
! 	    pair->size = DECL_SIZE (field);
  	    pair->offset = offset + bitpos_of_field (field);
  	    count++;
  	  }
  	else
  	  count += pushed;
        }
!     }
    return count;
  }
  
*************** create_variable_info_for (tree decl, con
*** 3863,3874 ****
        unsigned int newindex = VEC_length (varinfo_t, varmap);
        fieldoff_s *fo = NULL;
        unsigned int i;
-       tree field;
  
        for (i = 0; !notokay && VEC_iterate (fieldoff_s, fieldstack, i, fo); i++)
  	{
! 	  if (!DECL_SIZE (fo->field) 
! 	      || TREE_CODE (DECL_SIZE (fo->field)) != INTEGER_CST
  	      || fo->offset < 0)
  	    {
  	      notokay = true;
--- 3937,3947 ----
        unsigned int newindex = VEC_length (varinfo_t, varmap);
        fieldoff_s *fo = NULL;
        unsigned int i;
  
        for (i = 0; !notokay && VEC_iterate (fieldoff_s, fieldstack, i, fo); i++)
  	{
! 	  if (! fo->size
! 	      || TREE_CODE (fo->size) != INTEGER_CST
  	      || fo->offset < 0)
  	    {
  	      notokay = true;
*************** create_variable_info_for (tree decl, con
*** 3903,3910 ****
  	  return index;
  	}
        
!       field = fo->field;
!       vi->size = TREE_INT_CST_LOW (DECL_SIZE (field));
        vi->offset = fo->offset;
        for (i = 1; VEC_iterate (fieldoff_s, fieldstack, i, fo); i++)
  	{
--- 3976,3982 ----
  	  return index;
  	}
        
!       vi->size = TREE_INT_CST_LOW (fo->size);
        vi->offset = fo->offset;
        for (i = 1; VEC_iterate (fieldoff_s, fieldstack, i, fo); i++)
  	{
*************** create_variable_info_for (tree decl, con
*** 3912,3925 ****
  	  const char *newname;
  	  char *tempname;
  
- 	  field = fo->field;
  	  newindex = VEC_length (varinfo_t, varmap);
! 	  asprintf (&tempname, "%s.%s", vi->name, alias_get_name (field));
  	  newname = ggc_strdup (tempname);
  	  free (tempname);
  	  newvi = new_var_info (decl, newindex, newname, newindex);
  	  newvi->offset = fo->offset;
! 	  newvi->size = TREE_INT_CST_LOW (DECL_SIZE (field));
  	  newvi->fullsize = vi->fullsize;
  	  insert_into_field_list (vi, newvi);
  	  VEC_safe_push (varinfo_t, heap, varmap, newvi);
--- 3984,3996 ----
  	  const char *newname;
  	  char *tempname;
  
  	  newindex = VEC_length (varinfo_t, varmap);
! 	  asprintf (&tempname, "%s.%u", vi->name, i);
  	  newname = ggc_strdup (tempname);
  	  free (tempname);
  	  newvi = new_var_info (decl, newindex, newname, newindex);
  	  newvi->offset = fo->offset;
! 	  newvi->size = TREE_INT_CST_LOW (fo->size);
  	  newvi->fullsize = vi->fullsize;
  	  insert_into_field_list (vi, newvi);
  	  VEC_safe_push (varinfo_t, heap, varmap, newvi);
Index: gcc/params.def
===================================================================
*** gcc/params.def	(revision 107713)
--- gcc/params.def	(working copy)
*************** DEFPARAM (PARAM_SALIAS_MAX_IMPLICIT_FIEL
*** 47,53 ****
  	  "salias-max-implicit-fields",
  	  "The maximum number of fields in a structure variable without direct structure accesses that GCC will attempt to track separately",
  	  5, 0, 0)
!    
  /* The maximum structure size at which the scalar replacement of
     aggregates (SRA) pass will perform block copies.  The default
     value, 0, implies that GCC will select the most appropriate size
--- 47,60 ----
  	  "salias-max-implicit-fields",
  	  "The maximum number of fields in a structure variable without direct structure accesses that GCC will attempt to track separately",
  	  5, 0, 0)
! 
! /* The maximum number of array elements structure aliasing will decompose
!    an array for.  The default is 4.  */
! DEFPARAM (PARAM_SALIAS_MAX_ARRAY_ELEMENTS,
! 	  "salias-max-array-elements",
! 	  "The maximum number of elements in an array for wich we track its elements separately",
! 	  4, 0, 0)
! 
  /* The maximum structure size at which the scalar replacement of
     aggregates (SRA) pass will perform block copies.  The default
     value, 0, implies that GCC will select the most appropriate size
Index: gcc/tree-ssa-operands.c
===================================================================
*** gcc/tree-ssa-operands.c	(revision 107713)
--- gcc/tree-ssa-operands.c	(working copy)
*************** parse_ssa_operands (tree stmt)
*** 748,755 ****
  	if (TREE_CODE (lhs) == VIEW_CONVERT_EXPR)
  	  lhs = TREE_OPERAND (lhs, 0);
  
! 	if (TREE_CODE (lhs) != ARRAY_REF
! 	    && TREE_CODE (lhs) != ARRAY_RANGE_REF
  	    && TREE_CODE (lhs) != BIT_FIELD_REF
  	    && TREE_CODE (lhs) != REALPART_EXPR
  	    && TREE_CODE (lhs) != IMAGPART_EXPR)
--- 748,754 ----
  	if (TREE_CODE (lhs) == VIEW_CONVERT_EXPR)
  	  lhs = TREE_OPERAND (lhs, 0);
  
! 	if (TREE_CODE (lhs) != ARRAY_RANGE_REF
  	    && TREE_CODE (lhs) != BIT_FIELD_REF
  	    && TREE_CODE (lhs) != REALPART_EXPR
  	    && TREE_CODE (lhs) != IMAGPART_EXPR)
*************** get_expr_operands (tree stmt, tree *expr
*** 1145,1167 ****
  
      case ARRAY_REF:
      case ARRAY_RANGE_REF:
-       /* Treat array references as references to the virtual variable
- 	 representing the array.  The virtual variable for an ARRAY_REF
- 	 is the VAR_DECL for the array.  */
- 
-       /* Add the virtual variable for the ARRAY_REF to VDEFS or VUSES
- 	 according to the value of IS_DEF.  Recurse if the LHS of the
- 	 ARRAY_REF node is not a regular variable.  */
-       if (SSA_VAR_P (TREE_OPERAND (expr, 0)))
- 	add_stmt_operand (expr_p, s_ann, flags);
-       else
- 	get_expr_operands (stmt, &TREE_OPERAND (expr, 0), flags);
- 
-       get_expr_operands (stmt, &TREE_OPERAND (expr, 1), opf_none);
-       get_expr_operands (stmt, &TREE_OPERAND (expr, 2), opf_none);
-       get_expr_operands (stmt, &TREE_OPERAND (expr, 3), opf_none);
-       return;
- 
      case COMPONENT_REF:
      case REALPART_EXPR:
      case IMAGPART_EXPR:
--- 1144,1149 ----
*************** get_expr_operands (tree stmt, tree *expr
*** 1187,1193 ****
  		  {
  	            int subvar_flags = flags;
  		    none = false;
! 		    if (!exact)
  		      subvar_flags &= ~opf_kill_def;
  		    add_stmt_operand (&sv->var, s_ann, subvar_flags);
  		  }
--- 1169,1177 ----
  		  {
  	            int subvar_flags = flags;
  		    none = false;
! 		    if (!exact
! 			|| TREE_CODE (TREE_TYPE (sv->var)) == ARRAY_TYPE)
! 		/*	|| AGGREGATE_TYPE_P (TREE_TYPE (sv->var)))*/
  		      subvar_flags &= ~opf_kill_def;
  		    add_stmt_operand (&sv->var, s_ann, subvar_flags);
  		  }
*************** get_expr_operands (tree stmt, tree *expr
*** 1207,1212 ****
--- 1191,1203 ----
  	      s_ann->has_volatile_ops = true; 
  	    get_expr_operands (stmt, &TREE_OPERAND (expr, 2), opf_none);
  	  }
+ 	else if (code == ARRAY_REF
+ 		 || code == ARRAY_RANGE_REF)
+ 	  {
+             get_expr_operands (stmt, &TREE_OPERAND (expr, 1), opf_none);
+             get_expr_operands (stmt, &TREE_OPERAND (expr, 2), opf_none);
+             get_expr_operands (stmt, &TREE_OPERAND (expr, 3), opf_none);
+ 	  }
  	return;
        }
      case WITH_SIZE_EXPR:
*************** get_expr_operands (tree stmt, tree *expr
*** 1237,1244 ****
  	op = TREE_OPERAND (expr, 0);
  	if (TREE_CODE (op) == WITH_SIZE_EXPR)
  	  op = TREE_OPERAND (expr, 0);
! 	if (TREE_CODE (op) == ARRAY_REF
! 	    || TREE_CODE (op) == ARRAY_RANGE_REF
  	    || TREE_CODE (op) == REALPART_EXPR
  	    || TREE_CODE (op) == IMAGPART_EXPR)
  	  subflags = opf_is_def;
--- 1228,1234 ----
  	op = TREE_OPERAND (expr, 0);
  	if (TREE_CODE (op) == WITH_SIZE_EXPR)
  	  op = TREE_OPERAND (expr, 0);
! 	if (TREE_CODE (op) == ARRAY_RANGE_REF
  	    || TREE_CODE (op) == REALPART_EXPR
  	    || TREE_CODE (op) == IMAGPART_EXPR)
  	  subflags = opf_is_def;
/* { dg-do compile } */
/* { dg-options "-O2 -fdump-tree-vars" } */

struct {
	int i;
	struct {
		int x[2];
	} b;
} a;

int foo(void)
{
	a.i = 1;
	a.b.x[0] = 0;
	a.b.x[1] = 1;
	return a.i + a.b.x[0];
}

/* { dg-final { scan-tree-dump "return 1;" "vars" } } */
/* { dg-final { cleanup-tree-dump "vars" } } */

/* { dg-do compile } */
/* { dg-options "-O2 -fdump-tree-vars" } */

struct {
	int i;
	struct {
		struct {
			int i;
		} x[2];
	} b;
} a;

int foo(void)
{
	a.i = 1;
	a.b.x[0].i = 0;
	a.b.x[1].i = 1;
	return a.i + a.b.x[0].i;
}

/* { dg-final { scan-tree-dump "return 1;" "vars" } } */
/* { dg-final { cleanup-tree-dump "vars" } } */

/* { dg-do compile } */
/* { dg-options "-O2 -fdump-tree-vars" } */

struct param { int *a; };
void foo(struct param *p);
int bar(void)
{
  int a[2];
  struct param p;
  a[0] = 1;
  a[1] = 1;
  p.a = &a[0];
  foo(&p);
  return a[0] + *p.a;
}

/* { dg-final { scan-tree-dump "return a.0. \\\+ \\*p\\.a;" "vars" } } */
/* { dg-final { cleanup-tree-dump "vars" } } */

/* { dg-do run } */
/* { dg-options "-O2" } */

void abort(void);
int main()
{
  int a[2];
  int *p = a;
  int i;
  a[0] = 1;
  a[1] = 2;
  for (i=0; i<2; ++i)
    if (p[i] != i+1)
      abort();
  return 0;
}

/* { dg-do run } */
/* { dg-options "-O2" } */

void abort(void);
int main()
{
  int a[2];
  int i = 1;
  a[0] = 1;
  a[1] = 2;
  if (*(a + i) != 2)
    abort();
  return 0;
}

/* { dg-do run } */
/* { dg-options "-O2" } */

void abort(void);
int main()
{
  int a[32];
  int i = 1;
  a[0] = 1;
  a[1] = 2;
  if (*(a + i) != 2)
    abort();
  return 0;
}

/* { dg-do compile } */
/* { dg-options "-O2 -fdump-tree-vars" } */

struct {
	int i;
	int x[2];
	int j;
} a;

int foo(int i)
{
	a.i = 1;
	a.j = 2;
	a.x[i] = 0;
	return a.i + a.j;
}

/* { dg-final { scan-tree-dump "return 3;" "vars" } } */
/* { dg-final { cleanup-tree-dump "vars" } } */

/* { dg-do compile } */
/* { dg-options "-O2 -fdump-tree-vars" } */

struct param { int *a; };
void foo(struct param *p);
int bar(void)
{
  int a[32];
  struct param p;
  a[0] = 1;
  a[1] = 1;
  p.a = &a[0];
  foo(&p);
  return a[0] + *p.a;
}

/* { dg-final { scan-tree-dump "return a.0. \\\+ \\*p\\.a;" "vars" } } */
/* { dg-final { cleanup-tree-dump "vars" } } */

/* { dg-do compile } */
/* { dg-options "-O2 -fdump-tree-alias1-vops" } */

struct {
	int i;
	int x[128];
	int j;
} a;

int foo(int i)
{
	a.x[i] = 0;
	return a.x[i];
}

/* { dg-final { scan-tree-dump "V_MAY_DEF" "alias1" } } */
/* { dg-final { cleanup-tree-dump "alias1" } } */

Attachment: iab-vs-array-alias-CINT2000.asc
Description: specint

Attachment: iab-vs-array-alias-CFP2000.asc
Description: specfp


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