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] Add decomposed ref interface to the alias-oracle, make SCCVN look-through-copies work for unions


This adds a decomposed ref interface to the alias-oracle.  This avoids
the need to re-generate trees from the SCCVN internal IL during stmt
walking done by PRE phi-translation and VN iteration.  It also works
around the issue that with unions we cannot re-create the reference
if we did the union-trick during FRE that allows value-numbering
union member accesses the same (to create VIEW_CONVERT_EXPRs).

With this patch it should be also easier to feed RTL MEM information
to the oracle - it is sufficient to know a base object and an alias-set
(and size and offset).

We should create a lot less garbage during PRE/FRE with that patch
as well.

Bootstrapped and tested on x86_64-unknown-linux-gnu, applied to trunk.

Richard.

2009-05-28  Richard Guenther  <rguenther@suse.de>

	* tree-ssa-alias.c (ao_ref_init): New function.
	(ao_ref_base): Likewise.
	(ao_ref_base_alias_set): Likewise.
	(ao_ref_alias_set): Likewise.
	(refs_may_alias_p_1): Change signature.
	(refs_may_alias_p): Adjust.
	(refs_anti_dependent_p): Likewise.
	(refs_output_dependent_p): Likewise.
	(call_may_clobber_ref_p_1): Change signature.
	(call_may_clobber_ref_p): Adjust.
	(stmt_may_clobber_ref_p_1): New function split out from ...
	(stmt_may_clobber_ref_p): ... here.
	(maybe_skip_until): Adjust signature.
	(get_continuation_for_phi): Likewise.
	(walk_non_aliased_vuses): Likewise.
	* tree-ssa-alias.h (struct ao_ref_s): New structure type.
	(ao_ref_init): Declare.
	(ao_ref_base): Likewise.
	(ao_ref_alias_set): Likewise.
	(stmt_may_clobber_ref_p_1): Likewise.
	(walk_non_aliased_vuses): Adjust.
	* tree-ssa-sccvn.c (ao_ref_init_from_vn_reference): New function.
	(get_ref_from_reference_ops): remove.
	(vn_reference_lookup_2): Adjust signature.
	(vn_reference_lookup_3): Do not re-build trees.  Handle unions.
	(vn_reference_lookup_pieces): Adjust signature, do not re-build
	trees.
	(vn_reference_lookup): Adjust.
	(vn_reference_insert): Likewise.
	(vn_reference_insert_pieces): Adjust signature.
	(visit_reference_op_call): Adjust.
	* tree-ssa-pre.c (get_expr_type): Simplify.
	(phi_translate_1): Adjust.
	(compute_avail): Likewise.
	(translate_vuse_through_block): Do not re-build trees.
	(value_dies_in_block_x): Likewise.
	* tree-ssa-sccvn.h (struct vn_reference_s): Add type and alias-set
	fields.
	(vn_reference_lookup_pieces): Adjust declaration.
	(vn_reference_insert_pieces): Likewise.

	* gcc.dg/tree-ssa/ssa-fre-26.c: New testcase.
	* gcc.c-torture/execute/20090527-1.c: Likewise.

Index: gcc/tree-ssa-alias.c
===================================================================
*** gcc/tree-ssa-alias.c.orig	2009-05-27 17:01:14.000000000 +0200
--- gcc/tree-ssa-alias.c	2009-05-28 11:52:52.000000000 +0200
*************** debug_points_to_info_for (tree var)
*** 439,444 ****
--- 439,493 ----
    dump_points_to_info_for (stderr, var);
  }
  
+ 
+ /* Initializes the alias-oracle reference representation *R from REF.  */
+ 
+ void
+ ao_ref_init (ao_ref *r, tree ref)
+ {
+   r->ref = ref;
+   r->base = NULL_TREE;
+   r->offset = 0;
+   r->size = -1;
+   r->max_size = -1;
+   r->ref_alias_set = -1;
+   r->base_alias_set = -1;
+ }
+ 
+ /* Returns the base object of the memory reference *REF.  */
+ 
+ tree
+ ao_ref_base (ao_ref *ref)
+ {
+   if (ref->base)
+     return ref->base;
+   ref->base = get_ref_base_and_extent (ref->ref, &ref->offset, &ref->size,
+ 				       &ref->max_size);
+   return ref->base;
+ }
+ 
+ /* Returns the base object alias set of the memory reference *REF.  */
+ 
+ static alias_set_type ATTRIBUTE_UNUSED
+ ao_ref_base_alias_set (ao_ref *ref)
+ {
+   if (ref->base_alias_set != -1)
+     return ref->base_alias_set;
+   ref->base_alias_set = get_alias_set (ao_ref_base (ref));
+   return ref->base_alias_set;
+ }
+ 
+ /* Returns the reference alias set of the memory reference *REF.  */
+ 
+ alias_set_type
+ ao_ref_alias_set (ao_ref *ref)
+ {
+   if (ref->ref_alias_set != -1)
+     return ref->ref_alias_set;
+   ref->ref_alias_set = get_alias_set (ref->ref);
+   return ref->ref_alias_set;
+ }
+ 
  /* Return 1 if TYPE1 and TYPE2 are to be considered equivalent for the
     purpose of TBAA.  Return 0 if they are distinct and -1 if we cannot
     decide.  */
*************** indirect_refs_may_alias_p (tree ref1, tr
*** 675,681 ****
  /* Return true, if the two memory references REF1 and REF2 may alias.  */
  
  static bool
! refs_may_alias_p_1 (tree ref1, tree ref2, bool tbaa_p)
  {
    tree base1, base2;
    HOST_WIDE_INT offset1 = 0, offset2 = 0;
--- 724,730 ----
  /* Return true, if the two memory references REF1 and REF2 may alias.  */
  
  static bool
! refs_may_alias_p_1 (ao_ref *ref1, ao_ref *ref2, bool tbaa_p)
  {
    tree base1, base2;
    HOST_WIDE_INT offset1 = 0, offset2 = 0;
*************** refs_may_alias_p_1 (tree ref1, tree ref2
*** 684,701 ****
    bool var1_p, var2_p, ind1_p, ind2_p;
    alias_set_type set;
  
!   gcc_assert ((SSA_VAR_P (ref1)
! 	       || handled_component_p (ref1)
! 	       || INDIRECT_REF_P (ref1)
! 	       || TREE_CODE (ref1) == TARGET_MEM_REF)
! 	      && (SSA_VAR_P (ref2)
! 		  || handled_component_p (ref2)
! 		  || INDIRECT_REF_P (ref2)
! 		  || TREE_CODE (ref2) == TARGET_MEM_REF));
  
    /* Decompose the references into their base objects and the access.  */
!   base1 = get_ref_base_and_extent (ref1, &offset1, &size1, &max_size1);
!   base2 = get_ref_base_and_extent (ref2, &offset2, &size2, &max_size2);
  
    /* We can end up with registers or constants as bases for example from
       *D.1663_44 = VIEW_CONVERT_EXPR<struct DB_LSN>(__tmp$B0F64_59);
--- 733,758 ----
    bool var1_p, var2_p, ind1_p, ind2_p;
    alias_set_type set;
  
!   gcc_assert ((!ref1->ref
! 	       || SSA_VAR_P (ref1->ref)
! 	       || handled_component_p (ref1->ref)
! 	       || INDIRECT_REF_P (ref1->ref)
! 	       || TREE_CODE (ref1->ref) == TARGET_MEM_REF)
! 	      && (!ref2->ref
! 		  || SSA_VAR_P (ref2->ref)
! 		  || handled_component_p (ref2->ref)
! 		  || INDIRECT_REF_P (ref2->ref)
! 		  || TREE_CODE (ref2->ref) == TARGET_MEM_REF));
  
    /* Decompose the references into their base objects and the access.  */
!   base1 = ao_ref_base (ref1);
!   offset1 = ref1->offset;
!   size1 = ref1->size;
!   max_size1 = ref1->max_size;
!   base2 = ao_ref_base (ref2);
!   offset2 = ref2->offset;
!   size2 = ref2->size;
!   max_size2 = ref2->max_size;
  
    /* We can end up with registers or constants as bases for example from
       *D.1663_44 = VIEW_CONVERT_EXPR<struct DB_LSN>(__tmp$B0F64_59);
*************** refs_may_alias_p_1 (tree ref1, tree ref2
*** 719,732 ****
    /* First defer to TBAA if possible.  */
    if (tbaa_p
        && flag_strict_aliasing
!       && !alias_sets_conflict_p (get_alias_set (ref1), get_alias_set (ref2)))
      return false;
  
    /* If one reference is a TARGET_MEM_REF weird things are allowed.  Still
       TBAA disambiguation based on the access type is possible, so bail
       out only after that check.  */
!   if (TREE_CODE (ref1) == TARGET_MEM_REF
!       || TREE_CODE (ref2) == TARGET_MEM_REF)
      return true;
  
    /* Dispatch to the pointer-vs-decl or pointer-vs-pointer disambiguators.  */
--- 776,790 ----
    /* First defer to TBAA if possible.  */
    if (tbaa_p
        && flag_strict_aliasing
!       && !alias_sets_conflict_p (ao_ref_alias_set (ref1),
! 				 ao_ref_alias_set (ref2)))
      return false;
  
    /* If one reference is a TARGET_MEM_REF weird things are allowed.  Still
       TBAA disambiguation based on the access type is possible, so bail
       out only after that check.  */
!   if ((ref1->ref && TREE_CODE (ref1->ref) == TARGET_MEM_REF)
!       || (ref2->ref && TREE_CODE (ref2->ref) == TARGET_MEM_REF))
      return true;
  
    /* Dispatch to the pointer-vs-decl or pointer-vs-pointer disambiguators.  */
*************** refs_may_alias_p_1 (tree ref1, tree ref2
*** 734,752 ****
    ind2_p = INDIRECT_REF_P (base2);
    set = tbaa_p ? -1 : 0;
    if (var1_p && ind2_p)
!     return indirect_ref_may_alias_decl_p (ref2, TREE_OPERAND (base2, 0),
  					  offset2, max_size2, set,
! 					  ref1, base1,
  					  offset1, max_size1, set);
    else if (ind1_p && var2_p)
!     return indirect_ref_may_alias_decl_p (ref1, TREE_OPERAND (base1, 0),
  					  offset1, max_size1, set,
! 					  ref2, base2,
  					  offset2, max_size2, set);
    else if (ind1_p && ind2_p)
!     return indirect_refs_may_alias_p (ref1, TREE_OPERAND (base1, 0),
  				      offset1, max_size1, set,
! 				      ref2, TREE_OPERAND (base2, 0),
  				      offset2, max_size2, set);
  
    gcc_unreachable ();
--- 792,810 ----
    ind2_p = INDIRECT_REF_P (base2);
    set = tbaa_p ? -1 : 0;
    if (var1_p && ind2_p)
!     return indirect_ref_may_alias_decl_p (ref2->ref, TREE_OPERAND (base2, 0),
  					  offset2, max_size2, set,
! 					  ref1->ref, base1,
  					  offset1, max_size1, set);
    else if (ind1_p && var2_p)
!     return indirect_ref_may_alias_decl_p (ref1->ref, TREE_OPERAND (base1, 0),
  					  offset1, max_size1, set,
! 					  ref2->ref, base2,
  					  offset2, max_size2, set);
    else if (ind1_p && ind2_p)
!     return indirect_refs_may_alias_p (ref1->ref, TREE_OPERAND (base1, 0),
  				      offset1, max_size1, set,
! 				      ref2->ref, TREE_OPERAND (base2, 0),
  				      offset2, max_size2, set);
  
    gcc_unreachable ();
*************** refs_may_alias_p_1 (tree ref1, tree ref2
*** 755,761 ****
  bool
  refs_may_alias_p (tree ref1, tree ref2)
  {
!   bool res = refs_may_alias_p_1 (ref1, ref2, true);
    if (res)
      ++alias_stats.refs_may_alias_p_may_alias;
    else
--- 813,823 ----
  bool
  refs_may_alias_p (tree ref1, tree ref2)
  {
!   ao_ref r1, r2;
!   bool res;
!   ao_ref_init (&r1, ref1);
!   ao_ref_init (&r2, ref2);
!   res = refs_may_alias_p_1 (&r1, &r2, true);
    if (res)
      ++alias_stats.refs_may_alias_p_may_alias;
    else
*************** refs_may_alias_p (tree ref1, tree ref2)
*** 769,775 ****
  bool
  refs_anti_dependent_p (tree load, tree store)
  {
!   return refs_may_alias_p_1 (load, store, false);
  }
  
  /* Returns true if there is a output dependence for the stores
--- 831,840 ----
  bool
  refs_anti_dependent_p (tree load, tree store)
  {
!   ao_ref r1, r2;
!   ao_ref_init (&r1, load);
!   ao_ref_init (&r2, store);
!   return refs_may_alias_p_1 (&r1, &r2, false);
  }
  
  /* Returns true if there is a output dependence for the stores
*************** refs_anti_dependent_p (tree load, tree s
*** 778,784 ****
  bool
  refs_output_dependent_p (tree store1, tree store2)
  {
!   return refs_may_alias_p_1 (store1, store2, false);
  }
  
  /* If the call CALL may use the memory reference REF return true,
--- 843,852 ----
  bool
  refs_output_dependent_p (tree store1, tree store2)
  {
!   ao_ref r1, r2;
!   ao_ref_init (&r1, store1);
!   ao_ref_init (&r2, store2);
!   return refs_may_alias_p_1 (&r1, &r2, false);
  }
  
  /* If the call CALL may use the memory reference REF return true,
*************** ref_maybe_used_by_stmt_p (gimple stmt, t
*** 907,913 ****
     return true, otherwise return false.  */
  
  static bool
! call_may_clobber_ref_p_1 (gimple call, tree ref)
  {
    tree base;
  
--- 975,981 ----
     return true, otherwise return false.  */
  
  static bool
! call_may_clobber_ref_p_1 (gimple call, ao_ref *ref)
  {
    tree base;
  
*************** call_may_clobber_ref_p_1 (gimple call, t
*** 916,922 ****
        & (ECF_PURE|ECF_CONST|ECF_LOOPING_CONST_OR_PURE|ECF_NOVOPS))
      return false;
  
!   base = get_base_address (ref);
    if (!base)
      return true;
  
--- 984,990 ----
        & (ECF_PURE|ECF_CONST|ECF_LOOPING_CONST_OR_PURE|ECF_NOVOPS))
      return false;
  
!   base = ao_ref_base (ref);
    if (!base)
      return true;
  
*************** call_may_clobber_ref_p_1 (gimple call, t
*** 957,966 ****
    return true;
  }
  
! static bool
  call_may_clobber_ref_p (gimple call, tree ref)
  {
!   bool res = call_may_clobber_ref_p_1 (call, ref);
    if (res)
      ++alias_stats.call_may_clobber_ref_p_may_alias;
    else
--- 1025,1037 ----
    return true;
  }
  
! static bool ATTRIBUTE_UNUSED
  call_may_clobber_ref_p (gimple call, tree ref)
  {
!   bool res;
!   ao_ref r;
!   ao_ref_init (&r, ref);
!   res = call_may_clobber_ref_p_1 (call, &r);
    if (res)
      ++alias_stats.call_may_clobber_ref_p_may_alias;
    else
*************** call_may_clobber_ref_p (gimple call, tre
*** 973,1006 ****
     otherwise return false.  */
  
  bool
! stmt_may_clobber_ref_p (gimple stmt, tree ref)
  {
    if (is_gimple_call (stmt))
      {
        tree lhs = gimple_call_lhs (stmt);
        if (lhs
! 	  && !is_gimple_reg (lhs)
! 	  && refs_may_alias_p (ref, lhs))
! 	return true;
  
!       return call_may_clobber_ref_p (stmt, ref);
      }
    else if (is_gimple_assign (stmt))
!     return refs_may_alias_p (ref, gimple_assign_lhs (stmt));
    else if (gimple_code (stmt) == GIMPLE_ASM)
      return true;
  
    return false;
  }
  
! static tree get_continuation_for_phi (gimple, tree, bitmap *);
  
  /* Walk the virtual use-def chain of VUSE until hitting the virtual operand
     TARGET or a statement clobbering the memory reference REF in which
     case false is returned.  The walk starts with VUSE, one argument of PHI.  */
  
  static bool
! maybe_skip_until (gimple phi, tree target, tree ref, tree vuse, bitmap *visited)
  {
    if (!*visited)
      *visited = BITMAP_ALLOC (NULL);
--- 1044,1095 ----
     otherwise return false.  */
  
  bool
! stmt_may_clobber_ref_p_1 (gimple stmt, ao_ref *ref)
  {
    if (is_gimple_call (stmt))
      {
        tree lhs = gimple_call_lhs (stmt);
        if (lhs
! 	  && !is_gimple_reg (lhs))
! 	{
! 	  ao_ref r;
! 	  ao_ref_init (&r, lhs);
! 	  if (refs_may_alias_p_1 (ref, &r, true))
! 	    return true;
! 	}
  
!       return call_may_clobber_ref_p_1 (stmt, ref);
      }
    else if (is_gimple_assign (stmt))
!     {
!       ao_ref r;
!       ao_ref_init (&r, gimple_assign_lhs (stmt));
!       return refs_may_alias_p_1 (ref, &r, true);
!     }
    else if (gimple_code (stmt) == GIMPLE_ASM)
      return true;
  
    return false;
  }
  
! bool
! stmt_may_clobber_ref_p (gimple stmt, tree ref)
! {
!   ao_ref r;
!   ao_ref_init (&r, ref);
!   return stmt_may_clobber_ref_p_1 (stmt, &r);
! }
! 
! 
! static tree get_continuation_for_phi (gimple, ao_ref *, bitmap *);
  
  /* Walk the virtual use-def chain of VUSE until hitting the virtual operand
     TARGET or a statement clobbering the memory reference REF in which
     case false is returned.  The walk starts with VUSE, one argument of PHI.  */
  
  static bool
! maybe_skip_until (gimple phi, tree target, ao_ref *ref,
! 		  tree vuse, bitmap *visited)
  {
    if (!*visited)
      *visited = BITMAP_ALLOC (NULL);
*************** maybe_skip_until (gimple phi, tree targe
*** 1024,1030 ****
  	}
        /* A clobbering statement or the end of the IL ends it failing.  */
        else if (gimple_nop_p (def_stmt)
! 	       || stmt_may_clobber_ref_p (def_stmt, ref))
  	return false;
        vuse = gimple_vuse (def_stmt);
      }
--- 1113,1119 ----
  	}
        /* A clobbering statement or the end of the IL ends it failing.  */
        else if (gimple_nop_p (def_stmt)
! 	       || stmt_may_clobber_ref_p_1 (def_stmt, ref))
  	return false;
        vuse = gimple_vuse (def_stmt);
      }
*************** maybe_skip_until (gimple phi, tree targe
*** 1038,1044 ****
     be found.  */
  
  static tree
! get_continuation_for_phi (gimple phi, tree ref, bitmap *visited)
  {
    unsigned nargs = gimple_phi_num_args (phi);
  
--- 1127,1133 ----
     be found.  */
  
  static tree
! get_continuation_for_phi (gimple phi, ao_ref *ref, bitmap *visited)
  {
    unsigned nargs = gimple_phi_num_args (phi);
  
*************** get_continuation_for_phi (gimple phi, tr
*** 1096,1104 ****
     TODO: Cache the vector of equivalent vuses per ref, vuse pair.  */
  
  void *
! walk_non_aliased_vuses (tree ref, tree vuse,
! 			void *(*walker)(tree, tree, void *),
! 			void *(*translate)(tree *, tree, void *),void *data)
  {
    bitmap visited = NULL;
    void *res;
--- 1185,1193 ----
     TODO: Cache the vector of equivalent vuses per ref, vuse pair.  */
  
  void *
! walk_non_aliased_vuses (ao_ref *ref, tree vuse,
! 			void *(*walker)(ao_ref *, tree, void *),
! 			void *(*translate)(ao_ref *, tree, void *), void *data)
  {
    bitmap visited = NULL;
    void *res;
*************** walk_non_aliased_vuses (tree ref, tree v
*** 1121,1131 ****
  	vuse = get_continuation_for_phi (def_stmt, ref, &visited);
        else
  	{
! 	  if (stmt_may_clobber_ref_p (def_stmt, ref))
  	    {
  	      if (!translate)
  		break;
! 	      res = (*translate) (&ref, vuse, data);
  	      /* Failed lookup and translation.  */
  	      if (res == (void *)-1)
  		{
--- 1210,1220 ----
  	vuse = get_continuation_for_phi (def_stmt, ref, &visited);
        else
  	{
! 	  if (stmt_may_clobber_ref_p_1 (def_stmt, ref))
  	    {
  	      if (!translate)
  		break;
! 	      res = (*translate) (ref, vuse, data);
  	      /* Failed lookup and translation.  */
  	      if (res == (void *)-1)
  		{
Index: gcc/tree-ssa-alias.h
===================================================================
*** gcc/tree-ssa-alias.h.orig	2009-05-27 17:01:14.000000000 +0200
--- gcc/tree-ssa-alias.h	2009-05-28 11:52:40.000000000 +0200
*************** struct GTY(()) pt_solution
*** 74,80 ****
--- 74,112 ----
  };
  
  
+ /* Simplified and cached information about a memory reference tree.
+    Used by the alias-oracle internally and externally in alternate
+    interfaces.  */
+ typedef struct ao_ref_s
+ {
+   /* The original full memory reference tree or NULL_TREE if that is
+      not available.  */
+   tree ref;
+ 
+   /* The following fields are the decomposed reference as returned
+      by get_ref_base_and_extent.  */
+   /* The base object of the memory reference or NULL_TREE if all of
+      the following fields are not yet computed.  */
+   tree base;
+   /* The offset relative to the base.  */
+   HOST_WIDE_INT offset;
+   /* The size of the access.  */
+   HOST_WIDE_INT size;
+   /* The maximum possible extent of the access or -1 if unconstrained.  */
+   HOST_WIDE_INT max_size;
+ 
+   /* The alias set of the access or -1 if not yet computed.  */
+   alias_set_type ref_alias_set;
+ 
+   /* The alias set of the base object or -1 if not yet computed.  */
+   alias_set_type base_alias_set;
+ } ao_ref;
+ 
+ 
  /* In tree-ssa-alias.c  */
+ extern void ao_ref_init (ao_ref *, tree);
+ extern tree ao_ref_base (ao_ref *);
+ extern alias_set_type ao_ref_alias_set (ao_ref *);
  extern enum escape_type is_escape_site (gimple);
  extern bool ptr_deref_may_alias_global_p (tree);
  extern bool refs_may_alias_p (tree, tree);
*************** extern bool refs_anti_dependent_p (tree,
*** 82,90 ****
  extern bool refs_output_dependent_p (tree, tree);
  extern bool ref_maybe_used_by_stmt_p (gimple, tree);
  extern bool stmt_may_clobber_ref_p (gimple, tree);
! extern void *walk_non_aliased_vuses (tree, tree,
! 				     void *(*)(tree, tree, void *),
! 				     void *(*)(tree *, tree, void *), void *);
  extern unsigned int walk_aliased_vdefs (tree, tree,
  					bool (*)(tree, tree, void *), void *,
  					bitmap *);
--- 114,123 ----
  extern bool refs_output_dependent_p (tree, tree);
  extern bool ref_maybe_used_by_stmt_p (gimple, tree);
  extern bool stmt_may_clobber_ref_p (gimple, tree);
! extern bool stmt_may_clobber_ref_p_1 (gimple, ao_ref *);
! extern void *walk_non_aliased_vuses (ao_ref *, tree,
! 				     void *(*)(ao_ref *, tree, void *),
! 				     void *(*)(ao_ref *, tree, void *), void *);
  extern unsigned int walk_aliased_vdefs (tree, tree,
  					bool (*)(tree, tree, void *), void *,
  					bitmap *);
Index: gcc/tree-ssa-sccvn.c
===================================================================
*** gcc/tree-ssa-sccvn.c.orig	2009-05-27 17:01:14.000000000 +0200
--- gcc/tree-ssa-sccvn.c	2009-05-28 12:49:34.000000000 +0200
*************** copy_reference_ops_from_ref (tree ref, V
*** 543,570 ****
  	     a matching type is not necessary and a mismatching type
  	     is always a spurious difference.  */
  	  temp.type = NULL_TREE;
  	  /* If this is a reference to a union member, record the union
  	     member size as operand.  Do so only if we are doing
  	     expression insertion (during FRE), as PRE currently gets
  	     confused with this.  */
  	  if (may_insert
! 	      && TREE_OPERAND (ref, 2) == NULL_TREE
! 	      && TREE_CODE (DECL_CONTEXT (TREE_OPERAND (ref, 1))) == UNION_TYPE
! 	      && integer_zerop (DECL_FIELD_OFFSET (TREE_OPERAND (ref, 1)))
! 	      && integer_zerop (DECL_FIELD_BIT_OFFSET (TREE_OPERAND (ref, 1))))
! 	    temp.op0 = TYPE_SIZE (TREE_TYPE (TREE_OPERAND (ref, 1)));
! 	  else
! 	    {
! 	      /* Record field as operand.  */
! 	      temp.op0 = TREE_OPERAND (ref, 1);
! 	      temp.op1 = TREE_OPERAND (ref, 2);
! 	    }
  	  break;
  	case ARRAY_RANGE_REF:
  	case ARRAY_REF:
  	  /* Record index as operand.  */
  	  temp.op0 = TREE_OPERAND (ref, 1);
! 	  temp.op1 = TREE_OPERAND (ref, 2);
  	  temp.op2 = TREE_OPERAND (ref, 3);
  	  break;
  	case STRING_CST:
--- 543,577 ----
  	     a matching type is not necessary and a mismatching type
  	     is always a spurious difference.  */
  	  temp.type = NULL_TREE;
+ 	  temp.op0 = TREE_OPERAND (ref, 1);
+ 	  temp.op1 = TREE_OPERAND (ref, 2);
  	  /* If this is a reference to a union member, record the union
  	     member size as operand.  Do so only if we are doing
  	     expression insertion (during FRE), as PRE currently gets
  	     confused with this.  */
  	  if (may_insert
! 	      && temp.op1 == NULL_TREE
! 	      && TREE_CODE (DECL_CONTEXT (temp.op0)) == UNION_TYPE
! 	      && integer_zerop (DECL_FIELD_OFFSET (temp.op0))
! 	      && integer_zerop (DECL_FIELD_BIT_OFFSET (temp.op0))
! 	      && host_integerp (TYPE_SIZE (TREE_TYPE (temp.op0)), 0))
! 	    temp.op0 = TYPE_SIZE (TREE_TYPE (temp.op0));
  	  break;
  	case ARRAY_RANGE_REF:
  	case ARRAY_REF:
  	  /* Record index as operand.  */
  	  temp.op0 = TREE_OPERAND (ref, 1);
! 	  /* Record even constant lower bounds.  */
! 	  if (TREE_OPERAND (ref, 2))
! 	    temp.op1 = TREE_OPERAND (ref, 2);
! 	  else
! 	    {
! 	      tree domain = TYPE_DOMAIN (TREE_TYPE (TREE_OPERAND (ref, 0)));
! 	      if (domain
! 		  && TYPE_MIN_VALUE (domain)
! 		  && !integer_zerop (TYPE_MIN_VALUE (domain)))
! 		temp.op1 = TYPE_MIN_VALUE (domain);
! 	    }
  	  temp.op2 = TREE_OPERAND (ref, 3);
  	  break;
  	case STRING_CST:
*************** copy_reference_ops_from_ref (tree ref, V
*** 612,635 ****
      }
  }
  
! /* Re-create a reference tree from the reference ops OPS.
!    Returns NULL_TREE if the ops were not handled.
!    This routine needs to be kept in sync with copy_reference_ops_from_ref.  */
! 
! tree
! get_ref_from_reference_ops (VEC(vn_reference_op_s, heap) *ops)
  {
    vn_reference_op_t op;
    unsigned i;
!   tree ref, *op0_p = &ref;
  
    for (i = 0; VEC_iterate (vn_reference_op_s, ops, i, op); ++i)
      {
        switch (op->opcode)
  	{
  	case CALL_EXPR:
! 	  return NULL_TREE;
  
  	case ALIGN_INDIRECT_REF:
  	case INDIRECT_REF:
  	  *op0_p = build1 (op->opcode, op->type, NULL_TREE);
--- 619,686 ----
      }
  }
  
! /* Build a alias-oracle reference abstraction in *REF from the vn_reference
!    operands in *OPS, the reference alias set SET and the reference type TYPE.
!    Return true if something useful was produced.  */
! 
! bool
! ao_ref_init_from_vn_reference (ao_ref *ref,
! 			       alias_set_type set, tree type,
! 			       VEC (vn_reference_op_s, heap) *ops)
  {
    vn_reference_op_t op;
    unsigned i;
!   tree base = NULL_TREE;
!   tree *op0_p = &base;
!   HOST_WIDE_INT offset = 0;
!   HOST_WIDE_INT max_size;
!   HOST_WIDE_INT size = -1;
!   tree size_tree = NULL_TREE;
! 
!   /* First get the final access size from just the outermost expression.  */
!   op = VEC_index (vn_reference_op_s, ops, 0);
!   if (op->opcode == COMPONENT_REF)
!     {
!       if (TREE_CODE (op->op0) == INTEGER_CST)
! 	size_tree = op->op0;
!       else
! 	size_tree = DECL_SIZE (op->op0);
!     }
!   else if (op->opcode == BIT_FIELD_REF)
!     size_tree = op->op0;
!   else
!     {
!       enum machine_mode mode = TYPE_MODE (type);
!       if (mode == BLKmode)
! 	size_tree = TYPE_SIZE (type);
!       else
!         size = GET_MODE_BITSIZE (mode);
!     }
!   if (size_tree != NULL_TREE)
!     {
!       if (!host_integerp (size_tree, 1))
! 	size = -1;
!       else
! 	size = TREE_INT_CST_LOW (size_tree);
!     }
! 
!   /* Initially, maxsize is the same as the accessed element size.
!      In the following it will only grow (or become -1).  */
!   max_size = size;
  
+   /* Compute cumulative bit-offset for nested component-refs and array-refs,
+      and find the ultimate containing object.  */
    for (i = 0; VEC_iterate (vn_reference_op_s, ops, i, op); ++i)
      {
        switch (op->opcode)
  	{
+ 	/* These may be in the reference ops, but we cannot do anything
+ 	   sensible with them here.  */
  	case CALL_EXPR:
! 	case ADDR_EXPR:
! 	  return false;
  
+ 	/* Record the base objects.  */
  	case ALIGN_INDIRECT_REF:
  	case INDIRECT_REF:
  	  *op0_p = build1 (op->opcode, op->type, NULL_TREE);
*************** get_ref_from_reference_ops (VEC(vn_refer
*** 642,667 ****
  	  op0_p = &TREE_OPERAND (*op0_p, 0);
  	  break;
  
  	case BIT_FIELD_REF:
! 	  *op0_p = build3 (BIT_FIELD_REF, op->type, NULL_TREE,
! 			   op->op0, op->op1);
! 	  op0_p = &TREE_OPERAND (*op0_p, 0);
  	  break;
  
  	case COMPONENT_REF:
! 	  /* We cannot re-construct our fancy union reference handling.  */
! 	  if (TREE_CODE (op->op0) == INTEGER_CST)
! 	    return NULL_TREE;
! 	  *op0_p = build3 (COMPONENT_REF, TREE_TYPE (op->op0), NULL_TREE,
! 			   op->op0, op->op1);
! 	  op0_p = &TREE_OPERAND (*op0_p, 0);
! 	  break;
  
  	case ARRAY_RANGE_REF:
  	case ARRAY_REF:
! 	  *op0_p = build4 (op->opcode, op->type, NULL_TREE,
! 			   op->op0, op->op1, op->op2);
! 	  op0_p = &TREE_OPERAND (*op0_p, 0);
  	  break;
  
  	case STRING_CST:
--- 693,761 ----
  	  op0_p = &TREE_OPERAND (*op0_p, 0);
  	  break;
  
+ 	case VAR_DECL:
+ 	case PARM_DECL:
+ 	case RESULT_DECL:
+ 	case SSA_NAME:
+ 	case FILTER_EXPR:
+ 	case EXC_PTR_EXPR:
+ 	  *op0_p = op->op0;
+ 	  break;
+ 
+ 	/* And now the usual component-reference style ops.  */
  	case BIT_FIELD_REF:
! 	  offset += tree_low_cst (op->op1, 0);
  	  break;
  
  	case COMPONENT_REF:
! 	  {
! 	    tree field = op->op0;
! 	    /* We do not have a complete COMPONENT_REF tree here so we
! 	       cannot use component_ref_field_offset.  Do the interesting
! 	       parts manually.  */
! 
! 	    /* Our union trick, done for offset zero only.  */
! 	    if (TREE_CODE (field) == INTEGER_CST)
! 	      ;
! 	    else if (op->op1
! 		     || !host_integerp (DECL_FIELD_OFFSET (field), 1))
! 	      max_size = -1;
! 	    else
! 	      {
! 		offset += (TREE_INT_CST_LOW (DECL_FIELD_OFFSET (field))
! 			   * BITS_PER_UNIT);
! 		offset += TREE_INT_CST_LOW (DECL_FIELD_BIT_OFFSET (field));
! 	      }
! 	    break;
! 	  }
  
  	case ARRAY_RANGE_REF:
  	case ARRAY_REF:
! 	  /* Same for ARRAY_REFs.  We do not have access to the array
! 	     type here, but we recorded the lower bound in op1.  */
! 	  if (op->op2
! 	      || !host_integerp (op->op0, 0)
! 	      || (op->op1 && !host_integerp (op->op1, 0))
! 	      || !host_integerp (TYPE_SIZE (op->type), 1))
! 	    max_size = -1;
! 	  else
! 	    {
! 	      HOST_WIDE_INT hindex = TREE_INT_CST_LOW (op->op0);
! 	      if (op->op1)
! 		hindex -= TREE_INT_CST_LOW (op->op1);
! 	      hindex *= TREE_INT_CST_LOW (TYPE_SIZE (op->type));
! 	      offset += hindex;
! 	    }
! 	  break;
! 
! 	case REALPART_EXPR:
! 	  break;
! 
! 	case IMAGPART_EXPR:
! 	  offset += size;
! 	  break;
! 
! 	case VIEW_CONVERT_EXPR:
  	  break;
  
  	case STRING_CST:
*************** get_ref_from_reference_ops (VEC(vn_refer
*** 670,706 ****
  	case VECTOR_CST:
  	case REAL_CST:
  	case CONSTRUCTOR:
- 	case VAR_DECL:
- 	case PARM_DECL:
  	case CONST_DECL:
! 	case RESULT_DECL:
! 	case SSA_NAME:
! 	case FILTER_EXPR:
! 	case EXC_PTR_EXPR:
! 	  *op0_p = op->op0;
! 	  break;
! 
! 	case ADDR_EXPR:
! 	  if (op->op0 != NULL_TREE)
! 	    {
! 	      gcc_assert (is_gimple_min_invariant (op->op0));
! 	      *op0_p = op->op0;
! 	      break;
! 	    }
! 	  /* Fallthrough.  */
! 	case IMAGPART_EXPR:
! 	case REALPART_EXPR:
! 	case VIEW_CONVERT_EXPR:
! 	  *op0_p = build1 (op->opcode, op->type, NULL_TREE);
! 	  op0_p = &TREE_OPERAND (*op0_p, 0);
! 	  break;
  
  	default:
! 	  return NULL_TREE;
  	}
      }
  
!   return ref;
  }
  
  /* Copy the operations present in load/store/call REF into RESULT, a vector of
--- 764,789 ----
  	case VECTOR_CST:
  	case REAL_CST:
  	case CONSTRUCTOR:
  	case CONST_DECL:
! 	  return false;
  
  	default:
! 	  return false;
  	}
      }
  
!   if (base == NULL_TREE)
!     return false;
! 
!   ref->ref = NULL_TREE;
!   ref->base = base;
!   ref->offset = offset;
!   ref->size = size;
!   ref->max_size = max_size;
!   ref->ref_alias_set = set;
!   ref->base_alias_set = -1;
! 
!   return true;
  }
  
  /* Copy the operations present in load/store/call REF into RESULT, a vector of
*************** vn_reference_lookup_1 (vn_reference_t vr
*** 920,926 ****
     with the current VUSE and performs the expression lookup.  */
  
  static void *
! vn_reference_lookup_2 (tree op ATTRIBUTE_UNUSED, tree vuse, void *vr_)
  {
    vn_reference_t vr = (vn_reference_t)vr_;
    void **slot;
--- 1003,1009 ----
     with the current VUSE and performs the expression lookup.  */
  
  static void *
! vn_reference_lookup_2 (ao_ref *op ATTRIBUTE_UNUSED, tree vuse, void *vr_)
  {
    vn_reference_t vr = (vn_reference_t)vr_;
    void **slot;
*************** vn_reference_lookup_2 (tree op ATTRIBUTE
*** 949,964 ****
     of VUSE.  */
  
  static void *
! vn_reference_lookup_3 (tree *refp, tree vuse, void *vr_)
  {
    vn_reference_t vr = (vn_reference_t)vr_;
    gimple def_stmt = SSA_NAME_DEF_STMT (vuse);
    tree fndecl;
-   tree ref = *refp;
    tree base;
    HOST_WIDE_INT offset, size, maxsize;
  
!   base = get_ref_base_and_extent (ref, &offset, &size, &maxsize);
  
    /* If we cannot constrain the size of the reference we cannot
       test if anything kills it.  */
--- 1032,1049 ----
     of VUSE.  */
  
  static void *
! vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *vr_)
  {
    vn_reference_t vr = (vn_reference_t)vr_;
    gimple def_stmt = SSA_NAME_DEF_STMT (vuse);
    tree fndecl;
    tree base;
    HOST_WIDE_INT offset, size, maxsize;
  
!   base = ao_ref_base (ref);
!   offset = ref->offset;
!   size = ref->size;
!   maxsize = ref->max_size;
  
    /* If we cannot constrain the size of the reference we cannot
       test if anything kills it.  */
*************** vn_reference_lookup_3 (tree *refp, tree
*** 968,974 ****
    /* def_stmt may-defs *ref.  See if we can derive a value for *ref
       from that defintion.
       1) Memset.  */
!   if (is_gimple_reg_type (TREE_TYPE (ref))
        && is_gimple_call (def_stmt)
        && (fndecl = gimple_call_fndecl (def_stmt))
        && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
--- 1053,1059 ----
    /* def_stmt may-defs *ref.  See if we can derive a value for *ref
       from that defintion.
       1) Memset.  */
!   if (is_gimple_reg_type (vr->type)
        && is_gimple_call (def_stmt)
        && (fndecl = gimple_call_fndecl (def_stmt))
        && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
*************** vn_reference_lookup_3 (tree *refp, tree
*** 987,999 ****
  	  && operand_equal_p (base, base2, 0)
  	  && offset2 <= offset
  	  && offset2 + size2 >= offset + maxsize)
! 	return vn_reference_insert (ref,
! 				    fold_convert (TREE_TYPE (ref),
! 						  integer_zero_node), vuse);
      }
  
    /* 2) Assignment from an empty CONSTRUCTOR.  */
!   else if (is_gimple_reg_type (TREE_TYPE (ref))
  	   && gimple_assign_single_p (def_stmt)
  	   && gimple_assign_rhs_code (def_stmt) == CONSTRUCTOR
  	   && CONSTRUCTOR_NELTS (gimple_assign_rhs1 (def_stmt)) == 0)
--- 1072,1089 ----
  	  && operand_equal_p (base, base2, 0)
  	  && offset2 <= offset
  	  && offset2 + size2 >= offset + maxsize)
! 	{
! 	  tree val = fold_convert (vr->type, integer_zero_node);
! 	  unsigned int value_id = get_or_alloc_constant_value_id (val);
! 	  return vn_reference_insert_pieces (vuse, vr->set, vr->type,
! 					     VEC_copy (vn_reference_op_s,
! 						       heap, vr->operands),
! 					     val, value_id);
! 	}
      }
  
    /* 2) Assignment from an empty CONSTRUCTOR.  */
!   else if (is_gimple_reg_type (vr->type)
  	   && gimple_assign_single_p (def_stmt)
  	   && gimple_assign_rhs_code (def_stmt) == CONSTRUCTOR
  	   && CONSTRUCTOR_NELTS (gimple_assign_rhs1 (def_stmt)) == 0)
*************** vn_reference_lookup_3 (tree *refp, tree
*** 1005,1013 ****
        if (operand_equal_p (base, base2, 0)
  	  && offset2 <= offset
  	  && offset2 + size2 >= offset + maxsize)
! 	return vn_reference_insert (ref,
! 				    fold_convert (TREE_TYPE (ref),
! 						  integer_zero_node), vuse);
      }
  
    /* For aggregate copies translate the reference through them if
--- 1095,1108 ----
        if (operand_equal_p (base, base2, 0)
  	  && offset2 <= offset
  	  && offset2 + size2 >= offset + maxsize)
! 	{
! 	  tree val = fold_convert (vr->type, integer_zero_node);
! 	  unsigned int value_id = get_or_alloc_constant_value_id (val);
! 	  return vn_reference_insert_pieces (vuse, vr->set, vr->type,
! 					     VEC_copy (vn_reference_op_s,
! 						       heap, vr->operands),
! 					     val, value_id);
! 	}
      }
  
    /* For aggregate copies translate the reference through them if
*************** vn_reference_lookup_3 (tree *refp, tree
*** 1022,1027 ****
--- 1117,1123 ----
        int i, j;
        VEC (vn_reference_op_s, heap) *lhs = NULL, *rhs = NULL;
        vn_reference_op_t vro;
+       ao_ref r;
  
        /* See if the assignment kills REF.  */
        base2 = get_ref_base_and_extent (gimple_assign_lhs (def_stmt),
*************** vn_reference_lookup_3 (tree *refp, tree
*** 1071,1079 ****
  	VEC_replace (vn_reference_op_s, vr->operands, i + 1 + j, vro);
        VEC_free (vn_reference_op_s, heap, rhs);
        vr->hashcode = vn_reference_compute_hash (vr);
!       *refp = get_ref_from_reference_ops (vr->operands);
!       if (!*refp)
  	return (void *)-1;
  
        /* Keep looking for the adjusted *REF / VR pair.  */
        return NULL;
--- 1167,1178 ----
  	VEC_replace (vn_reference_op_s, vr->operands, i + 1 + j, vro);
        VEC_free (vn_reference_op_s, heap, rhs);
        vr->hashcode = vn_reference_compute_hash (vr);
! 
!       /* Adjust *ref from the new operands.  */
!       if (!ao_ref_init_from_vn_reference (&r, vr->set, vr->type, vr->operands))
  	return (void *)-1;
+       gcc_assert (ref->size == r.size);
+       *ref = r;
  
        /* Keep looking for the adjusted *REF / VR pair.  */
        return NULL;
*************** vn_reference_lookup_3 (tree *refp, tree
*** 1089,1095 ****
     vn_reference_t stored in the hashtable if something is found.  */
  
  tree
! vn_reference_lookup_pieces (tree vuse,
  			    VEC (vn_reference_op_s, heap) *operands,
  			    vn_reference_t *vnresult, bool maywalk)
  {
--- 1188,1194 ----
     vn_reference_t stored in the hashtable if something is found.  */
  
  tree
! vn_reference_lookup_pieces (tree vuse, alias_set_type set, tree type,
  			    VEC (vn_reference_op_s, heap) *operands,
  			    vn_reference_t *vnresult, bool maywalk)
  {
*************** vn_reference_lookup_pieces (tree vuse,
*** 1110,1115 ****
--- 1209,1216 ----
  	  * VEC_length (vn_reference_op_s, operands));
    vr1.operands = operands = shared_lookup_references
      = valueize_refs (shared_lookup_references);
+   vr1.type = type;
+   vr1.set = set;
    vr1.hashcode = vn_reference_compute_hash (&vr1);
    vn_reference_lookup_1 (&vr1, vnresult);
  
*************** vn_reference_lookup_pieces (tree vuse,
*** 1117,1126 ****
        && maywalk
        && vr1.vuse)
      {
!       tree ref = get_ref_from_reference_ops (operands);
!       if (ref)
  	*vnresult =
! 	  (vn_reference_t)walk_non_aliased_vuses (ref, vr1.vuse,
  						  vn_reference_lookup_2,
  						  vn_reference_lookup_3, &vr1);
        if (vr1.operands != operands)
--- 1218,1227 ----
        && maywalk
        && vr1.vuse)
      {
!       ao_ref r;
!       if (ao_ref_init_from_vn_reference (&r, set, type, vr1.operands))
  	*vnresult =
! 	  (vn_reference_t)walk_non_aliased_vuses (&r, vr1.vuse,
  						  vn_reference_lookup_2,
  						  vn_reference_lookup_3, &vr1);
        if (vr1.operands != operands)
*************** vn_reference_lookup (tree op, tree vuse,
*** 1151,1164 ****
  
    vr1.vuse = vuse ? SSA_VAL (vuse) : NULL_TREE;
    vr1.operands = operands = valueize_shared_reference_ops_from_ref (op);
    vr1.hashcode = vn_reference_compute_hash (&vr1);
  
    if (maywalk
        && vr1.vuse)
      {
        vn_reference_t wvnresult;
        wvnresult =
! 	(vn_reference_t)walk_non_aliased_vuses (op, vr1.vuse,
  						vn_reference_lookup_2,
  						vn_reference_lookup_3, &vr1);
        if (vr1.operands != operands)
--- 1252,1269 ----
  
    vr1.vuse = vuse ? SSA_VAL (vuse) : NULL_TREE;
    vr1.operands = operands = valueize_shared_reference_ops_from_ref (op);
+   vr1.type = TREE_TYPE (op);
+   vr1.set = get_alias_set (op);
    vr1.hashcode = vn_reference_compute_hash (&vr1);
  
    if (maywalk
        && vr1.vuse)
      {
        vn_reference_t wvnresult;
+       ao_ref r;
+       ao_ref_init (&r, op);
        wvnresult =
! 	(vn_reference_t)walk_non_aliased_vuses (&r, vr1.vuse,
  						vn_reference_lookup_2,
  						vn_reference_lookup_3, &vr1);
        if (vr1.operands != operands)
*************** vn_reference_insert (tree op, tree resul
*** 1193,1198 ****
--- 1298,1305 ----
      vr1->value_id = get_or_alloc_constant_value_id (result);
    vr1->vuse = vuse ? SSA_VAL (vuse) : NULL_TREE;
    vr1->operands = valueize_refs (create_reference_ops_from_ref (op));
+   vr1->type = TREE_TYPE (op);
+   vr1->set = get_alias_set (op);
    vr1->hashcode = vn_reference_compute_hash (vr1);
    vr1->result = TREE_CODE (result) == SSA_NAME ? SSA_VAL (result) : result;
  
*************** vn_reference_insert (tree op, tree resul
*** 1220,1226 ****
     structure we created.  */
  
  vn_reference_t
! vn_reference_insert_pieces (tree vuse,
  			    VEC (vn_reference_op_s, heap) *operands,
  			    tree result, unsigned int value_id)
  
--- 1327,1333 ----
     structure we created.  */
  
  vn_reference_t
! vn_reference_insert_pieces (tree vuse, alias_set_type set, tree type,
  			    VEC (vn_reference_op_s, heap) *operands,
  			    tree result, unsigned int value_id)
  
*************** vn_reference_insert_pieces (tree vuse,
*** 1232,1237 ****
--- 1339,1346 ----
    vr1->value_id = value_id;
    vr1->vuse = vuse ? SSA_VAL (vuse) : NULL_TREE;
    vr1->operands = valueize_refs (operands);
+   vr1->type = type;
+   vr1->set = set;
    vr1->hashcode = vn_reference_compute_hash (vr1);
    if (result && TREE_CODE (result) == SSA_NAME)
      result = SSA_VAL (result);
*************** visit_reference_op_call (tree lhs, gimpl
*** 1825,1830 ****
--- 1934,1941 ----
  
    vr1.vuse = vuse ? SSA_VAL (vuse) : NULL_TREE;
    vr1.operands = valueize_shared_reference_ops_from_call (stmt);
+   vr1.type = gimple_expr_type (stmt);
+   vr1.set = 0;
    vr1.hashcode = vn_reference_compute_hash (&vr1);
    result = vn_reference_lookup_1 (&vr1, NULL);
    if (result)
*************** visit_reference_op_call (tree lhs, gimpl
*** 1842,1847 ****
--- 1953,1960 ----
        vr2 = (vn_reference_t) pool_alloc (current_info->references_pool);
        vr2->vuse = vr1.vuse;
        vr2->operands = valueize_refs (create_reference_ops_from_call (stmt));
+       vr2->type = vr1.type;
+       vr2->set = vr1.set;
        vr2->hashcode = vr1.hashcode;
        vr2->result = lhs;
        slot = htab_find_slot_with_hash (current_info->references,
Index: gcc/tree-ssa-pre.c
===================================================================
*** gcc/tree-ssa-pre.c.orig	2009-05-27 17:01:14.000000000 +0200
--- gcc/tree-ssa-pre.c	2009-05-28 12:09:40.000000000 +0200
*************** do_unary:
*** 1252,1263 ****
  
  static tree
  translate_vuse_through_block (VEC (vn_reference_op_s, heap) *operands,
! 			      tree vuse,
  			      basic_block phiblock,
  			      basic_block block)
  {
    gimple phi = SSA_NAME_DEF_STMT (vuse);
!   tree ref;
  
    if (gimple_bb (phi) != phiblock)
      return vuse;
--- 1252,1263 ----
  
  static tree
  translate_vuse_through_block (VEC (vn_reference_op_s, heap) *operands,
! 			      alias_set_type set, tree type, tree vuse,
  			      basic_block phiblock,
  			      basic_block block)
  {
    gimple phi = SSA_NAME_DEF_STMT (vuse);
!   ao_ref ref;
  
    if (gimple_bb (phi) != phiblock)
      return vuse;
*************** translate_vuse_through_block (VEC (vn_re
*** 1268,1280 ****
        return PHI_ARG_DEF (phi, e->dest_idx);
      }
  
!   if (!(ref = get_ref_from_reference_ops (operands)))
      return NULL_TREE;
  
    /* Use the alias-oracle to find either the PHI node in this block,
       the first VUSE used in this block that is equivalent to vuse or
       the first VUSE which definition in this block kills the value.  */
!   while (!stmt_may_clobber_ref_p (phi, ref))
      {
        vuse = gimple_vuse (phi);
        phi = SSA_NAME_DEF_STMT (vuse);
--- 1268,1280 ----
        return PHI_ARG_DEF (phi, e->dest_idx);
      }
  
!   if (!ao_ref_init_from_vn_reference (&ref, set, type, operands))
      return NULL_TREE;
  
    /* Use the alias-oracle to find either the PHI node in this block,
       the first VUSE used in this block that is equivalent to vuse or
       the first VUSE which definition in this block kills the value.  */
!   while (!stmt_may_clobber_ref_p_1 (phi, &ref))
      {
        vuse = gimple_vuse (phi);
        phi = SSA_NAME_DEF_STMT (vuse);
*************** get_expr_type (const pre_expr e)
*** 1317,1339 ****
      case CONSTANT:
        return TREE_TYPE (PRE_EXPR_CONSTANT (e));
      case REFERENCE:
!       {
! 	vn_reference_op_t vro;
! 
! 	gcc_assert (PRE_EXPR_REFERENCE (e)->operands);
! 	vro = VEC_index (vn_reference_op_s,
! 			 PRE_EXPR_REFERENCE (e)->operands,
! 			 0);
! 	/* We don't store type along with COMPONENT_REF because it is
! 	   always the same as FIELD_DECL's type.  */
! 	if (!vro->type)
! 	  {
! 	    gcc_assert (vro->opcode == COMPONENT_REF);
! 	    return TREE_TYPE (vro->op0);
! 	  }
! 	return vro->type;
!       }
! 
      case NARY:
        return PRE_EXPR_NARY (e)->type;
      }
--- 1317,1323 ----
      case CONSTANT:
        return TREE_TYPE (PRE_EXPR_CONSTANT (e));
      case REFERENCE:
!       return PRE_EXPR_REFERENCE (e)->type;
      case NARY:
        return PRE_EXPR_NARY (e)->type;
      }
*************** phi_translate_1 (pre_expr expr, bitmap_s
*** 1661,1666 ****
--- 1645,1651 ----
  	if (vuse)
  	  {
  	    newvuse = translate_vuse_through_block (newoperands,
+ 						    ref->set, ref->type,
  						    vuse, phiblock, pred);
  	    if (newvuse == NULL_TREE)
  	      {
*************** phi_translate_1 (pre_expr expr, bitmap_s
*** 1675,1681 ****
  	    unsigned int new_val_id;
  	    pre_expr constant;
  
! 	    tree result = vn_reference_lookup_pieces (newvuse,
  						      newoperands,
  						      &newref, true);
  	    if (newref)
--- 1660,1667 ----
  	    unsigned int new_val_id;
  	    pre_expr constant;
  
! 	    tree result = vn_reference_lookup_pieces (newvuse, ref->set,
! 						      ref->type,
  						      newoperands,
  						      &newref, true);
  	    if (newref)
*************** phi_translate_1 (pre_expr expr, bitmap_s
*** 1706,1712 ****
  		new_val_id = get_next_value_id ();
  		VEC_safe_grow_cleared (bitmap_set_t, heap, value_expressions,
  				       get_max_value_id() + 1);
! 		newref = vn_reference_insert_pieces (newvuse,
  						     newoperands,
  						     result, new_val_id);
  		newoperands = NULL;
--- 1692,1699 ----
  		new_val_id = get_next_value_id ();
  		VEC_safe_grow_cleared (bitmap_set_t, heap, value_expressions,
  				       get_max_value_id() + 1);
! 		newref = vn_reference_insert_pieces (newvuse, ref->set,
! 						     ref->type,
  						     newoperands,
  						     result, new_val_id);
  		newoperands = NULL;
*************** value_dies_in_block_x (pre_expr expr, ba
*** 1884,1893 ****
    tree vuse = PRE_EXPR_REFERENCE (expr)->vuse;
    vn_reference_t refx = PRE_EXPR_REFERENCE (expr);
    gimple def;
-   tree ref = NULL_TREE;
    gimple_stmt_iterator gsi;
    unsigned id = get_expression_id (expr);
    bool res = false;
  
    if (!vuse)
      return false;
--- 1871,1880 ----
    tree vuse = PRE_EXPR_REFERENCE (expr)->vuse;
    vn_reference_t refx = PRE_EXPR_REFERENCE (expr);
    gimple def;
    gimple_stmt_iterator gsi;
    unsigned id = get_expression_id (expr);
    bool res = false;
+   ao_ref ref;
  
    if (!vuse)
      return false;
*************** value_dies_in_block_x (pre_expr expr, ba
*** 1902,1907 ****
--- 1889,1895 ----
       top of the basic block, a statement uses VUSE there can be no kill
       inbetween that use and the original statement that loaded {e, VUSE},
       so we can stop walking.  */
+   ref.base = NULL_TREE;
    for (gsi = gsi_start_bb (block); !gsi_end_p (gsi); gsi_next (&gsi))
      {
        tree def_vuse, def_vdef;
*************** value_dies_in_block_x (pre_expr expr, ba
*** 1924,1939 ****
  	}
  
        /* Init ref only if we really need it.  */
!       if (ref == NULL_TREE)
  	{
! 	  if (!(ref = get_ref_from_reference_ops (refx->operands)))
! 	    {
! 	      res = true;
! 	      break;
! 	    }
  	}
        /* If the statement may clobber expr, it dies.  */
!       if (stmt_may_clobber_ref_p (def, ref))
  	{
  	  res = true;
  	  break;
--- 1912,1926 ----
  	}
  
        /* Init ref only if we really need it.  */
!       if (ref.base == NULL_TREE
! 	  && !ao_ref_init_from_vn_reference (&ref, refx->set, refx->type,
! 					     refx->operands))
  	{
! 	  res = true;
! 	  break;
  	}
        /* If the statement may clobber expr, it dies.  */
!       if (stmt_may_clobber_ref_p_1 (def, &ref))
  	{
  	  res = true;
  	  break;
*************** compute_avail (void)
*** 3793,3799 ****
  		  continue;
  
  		copy_reference_ops_from_call (stmt, &ops);
! 		vn_reference_lookup_pieces (gimple_vuse (stmt),
  					    ops, &ref, false);
  		VEC_free (vn_reference_op_s, heap, ops);
  		if (!ref)
--- 3780,3787 ----
  		  continue;
  
  		copy_reference_ops_from_call (stmt, &ops);
! 		vn_reference_lookup_pieces (gimple_vuse (stmt), 0,
! 					    gimple_expr_type (stmt),
  					    ops, &ref, false);
  		VEC_free (vn_reference_op_s, heap, ops);
  		if (!ref)
Index: gcc/tree-ssa-sccvn.h
===================================================================
*** gcc/tree-ssa-sccvn.h.orig	2009-05-27 17:01:14.000000000 +0200
--- gcc/tree-ssa-sccvn.h	2009-05-28 12:49:43.000000000 +0200
*************** typedef struct vn_reference_s
*** 92,97 ****
--- 92,99 ----
    unsigned int value_id;
    hashval_t hashcode;
    tree vuse;
+   alias_set_type set;
+   tree type;
    VEC (vn_reference_op_s, heap) *operands;
    tree result;
  } *vn_reference_t;
*************** void vn_reference_fold_indirect (VEC (vn
*** 177,189 ****
  				 unsigned int *);
  void copy_reference_ops_from_ref (tree, VEC(vn_reference_op_s, heap) **);
  void copy_reference_ops_from_call (gimple, VEC(vn_reference_op_s, heap) **);
! tree get_ref_from_reference_ops (VEC(vn_reference_op_s, heap) *ops);
! tree vn_reference_lookup_pieces (tree,
  				 VEC (vn_reference_op_s, heap) *,
  				 vn_reference_t *, bool);
  tree vn_reference_lookup (tree, tree, bool, vn_reference_t *);
  vn_reference_t vn_reference_insert (tree, tree, tree);
! vn_reference_t vn_reference_insert_pieces (tree,
  					   VEC (vn_reference_op_s, heap) *,
  					   tree, unsigned int);
  
--- 179,192 ----
  				 unsigned int *);
  void copy_reference_ops_from_ref (tree, VEC(vn_reference_op_s, heap) **);
  void copy_reference_ops_from_call (gimple, VEC(vn_reference_op_s, heap) **);
! bool ao_ref_init_from_vn_reference (ao_ref *, alias_set_type, tree,
! 				    VEC (vn_reference_op_s, heap) *);
! tree vn_reference_lookup_pieces (tree, alias_set_type, tree,
  				 VEC (vn_reference_op_s, heap) *,
  				 vn_reference_t *, bool);
  tree vn_reference_lookup (tree, tree, bool, vn_reference_t *);
  vn_reference_t vn_reference_insert (tree, tree, tree);
! vn_reference_t vn_reference_insert_pieces (tree, alias_set_type, tree,
  					   VEC (vn_reference_op_s, heap) *,
  					   tree, unsigned int);
  
Index: gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-26.c
===================================================================
*** /dev/null	1970-01-01 00:00:00.000000000 +0000
--- gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-26.c	2009-05-28 11:48:34.000000000 +0200
***************
*** 0 ****
--- 1,18 ----
+ /* { dg-do compile } */
+ /* { dg-options "-O -fno-tree-sra -fdump-tree-fre-details" } */
+ 
+ union U {
+   float f;
+   int i;
+ };
+ 
+ int foo (union U *p)
+ {
+   union U u;
+   p->f = 0.0;
+   u = *p;
+   return u.i;
+ }
+ 
+ /* { dg-final { scan-tree-dump "Replaced u.i with 0 in" "fre" } } */
+ /* { dg-final { cleanup-tree-dump "fre" } } */
Index: gcc/testsuite/gcc.c-torture/execute/20090527-1.c
===================================================================
*** /dev/null	1970-01-01 00:00:00.000000000 +0000
--- gcc/testsuite/gcc.c-torture/execute/20090527-1.c	2009-05-28 11:48:34.000000000 +0200
***************
*** 0 ****
--- 1,38 ----
+ typedef enum { POSITION_ASIS, POSITION_UNSPECIFIED } unit_position;
+ 
+ typedef enum { STATUS_UNKNOWN, STATUS_UNSPECIFIED } unit_status;
+ 
+ typedef struct
+ {
+   unit_position position;
+   unit_status status;
+ } unit_flags;
+ 
+ extern void abort (void);
+ 
+ void
+ new_unit (unit_flags * flags)
+ {
+   if (flags->status == STATUS_UNSPECIFIED)
+     flags->status = STATUS_UNKNOWN;
+ 
+   if (flags->position == POSITION_UNSPECIFIED)
+     flags->position = POSITION_ASIS;
+ 
+   switch (flags->status)
+     {
+     case STATUS_UNKNOWN:
+       break;
+ 
+     default:
+       abort ();
+     }
+ }
+ 
+ int main()
+ {
+   unit_flags f;
+   f.status = STATUS_UNSPECIFIED;
+   new_unit (&f);
+   return 0;
+ }


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