[PATCH] Alias oracle for SCCVN (updated)

Richard Guenther rguenther@suse.de
Tue Mar 4 19:40:00 GMT 2008


This is an updated version of the SCCVN alias oracle patch I posted
last year.  It now can look through PHI nodes optimizing some interesting
Fortran testcases the FE emits regularly.

The patch also contains some unrelated cleanup stuff (I'll separate
this out), the core parts are in tree-ssa-sccvn.c and the single
refs_may_alias_p function in tree-ssa-alias.c (actually I don't know
if this is the right place to stick it).

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

I'll have some SPEC results for you tomorrow.

Are the SCCVN and tree-ssa-alias.c parts ok for trunk?

Thanks,
Richard.

2007-12-05  Richard Guenther  <rguenther@suse.de>

	* tree-ssa-structalias.c (get_constraint_for_component_ref):
	Use ranges_overlap_p.
	(offset_overlaps_with_access): Rename
	to ranges_overlap_p and move ...
	* tree-flow-inline.h (ranges_overlap_p): ... here.

	* tree.h (get_inner_reference, handled_component_p): Update
	comments.

	* tree.h (record_component_aliases, get_alias_set,
	alias_sets_conflict_p, alias_sets_must_conflict_p,
	objects_must_conflict_p): Move declarations ...
	* alias.h (record_component_aliases, get_alias_set,
	alias_sets_conflict_p, alias_sets_must_conflict_p,
	objects_must_conflict_p): ... here.
	Include coretypes.h.
	* Makefile.in (ALIAS_H): Add coretypes.h dependency.

	PR tree-optimization/34172
	* tree-ssa-alias.c (refs_may_alias_p): New function.
	(refs_must_alias_p): Likewise.
	(ref_killed_by_def_p): Likewise.
	* tree-ssa-structalias.h (refs_may_alias_p): Declare.
	(refs_must_alias_p): Likewise.
	(ref_killed_by_def_p): Likewise.
	* tree-dfa.c (get_single_def_stmt): New function.
	* tree-flow.h (get_single_def_stmt): Declare.
	* tree-ssa-sccvn.c: Include tree-ssa-structalias.h.
	(vn_reference_lookup): Walk the virtual use-def chain to
	continue searching for a match if the def does not alias the
	reference we are looking for.
	* tree-ssa-dse.c: Include tree-ssa-structalias.h.
	(get_kill_of_stmt_lhs): Use ref_killed_by_def_p.
	* Makefile.in (tree-ssa-sccvn.o): Add tree-ssa-structalias.h
	dependency.
	(tree-ssa-dse.o): Likewise.

	* gcc.dg/tree-ssa/ssa-fre-7.c: New testcase.
	* gcc.dg/tree-ssa/ssa-fre-8.c: Likewise.
	* gcc.dg/tree-ssa/20031106-4.c: Remove XFAIL.


Index: trunk/gcc/tree-flow-inline.h
===================================================================
*** trunk.orig/gcc/tree-flow-inline.h	2008-03-03 11:28:17.000000000 +0100
--- trunk/gcc/tree-flow-inline.h	2008-03-03 15:05:56.000000000 +0100
*************** var_can_have_subvars (const_tree v)
*** 1725,1731 ****
    return false;
  }
  
!   
  /* Return true if OFFSET and SIZE define a range that overlaps with some
     portion of the range of SV, a subvar.  If there was an exact overlap,
     *EXACT will be set to true upon return. */
--- 1725,1754 ----
    return false;
  }
  
! 
! /* Return true, if the two ranges [POS1, SIZE1] and [POS2, SIZE2]
!    overlap.  SIZE1 and/or SIZE2 can be (unsigned)-1 in which case the
!    range is open-ended.  Otherwise return false.  */
! 
! static inline bool
! ranges_overlap_p (unsigned HOST_WIDE_INT pos1,
! 		  unsigned HOST_WIDE_INT size1,
! 		  unsigned HOST_WIDE_INT pos2,
! 		  unsigned HOST_WIDE_INT size2)
! {
!   if (pos1 >= pos2
!       && (size2 == (unsigned HOST_WIDE_INT)-1
! 	  || pos1 < (pos2 + size2)))
!     return true;
!   if (pos2 >= pos1
!       && (size1 == (unsigned HOST_WIDE_INT)-1
! 	  || pos2 < (pos1 + size1)))
!     return true;
! 
!   return false;
! }
! 
! 
  /* Return true if OFFSET and SIZE define a range that overlaps with some
     portion of the range of SV, a subvar.  If there was an exact overlap,
     *EXACT will be set to true upon return. */
Index: trunk/gcc/tree-ssa-sccvn.c
===================================================================
*** trunk.orig/gcc/tree-ssa-sccvn.c	2008-03-03 14:59:40.000000000 +0100
--- trunk/gcc/tree-ssa-sccvn.c	2008-03-03 15:05:56.000000000 +0100
*************** along with GCC; see the file COPYING3.  
*** 45,50 ****
--- 45,51 ----
  #include "params.h"
  #include "tree-ssa-propagate.h"
  #include "tree-ssa-sccvn.h"
+ #include "tree-ssa-structalias.h"
  
  /* This algorithm is based on the SCC algorithm presented by Keith
     Cooper and L. Taylor Simpson in "SCC-Based Value numbering"
*************** valueize_vuses (VEC (tree, gc) *orig)
*** 665,670 ****
--- 666,835 ----
    return orig;
  }
  
+ /* Given a stmt STMT that references memory, return the single stmt
+    that is reached by following the VUSE -> VDEF link.  Returns
+    NULL_TREE, if there is no single stmt that defines all VUSEs of
+    STMT.
+    Note that for a stmt with a single virtual operand this may return
+    a default definition or a PHI node as well.  */
+ 
+ static tree
+ get_single_def_stmt (tree stmt)
+ {
+   tree def_stmt = NULL_TREE;
+   use_operand_p usep;
+   ssa_op_iter iter;
+ 
+   FOR_EACH_SSA_USE_OPERAND (usep, stmt, iter, SSA_OP_VIRTUAL_USES)
+     {
+       tree def = USE_FROM_PTR (usep);
+       tree tmp = SSA_NAME_DEF_STMT (def);
+ 
+       /* ???  This is too simplistic for multiple virtual operands
+ 	 reaching different PHI nodes of the same basic blocks or for
+ 	 reaching all default definitions.  */
+       if (def_stmt
+ 	  && def_stmt != tmp)
+ 	return NULL_TREE;
+ 
+       def_stmt = tmp;
+     }
+ 
+   return def_stmt;
+ }
+ 
+ /* Given a PHI node of virtual operands, tries to eliminate cyclic
+    reached definitions if they do not alias REF and returns the
+    defining statement of the single virtual operand that flows in
+    from a non-backedge.  Returns NULL_TREE if such statement within
+    the above conditions cannot be found.  */
+ 
+ static tree
+ get_single_def_stmt_from_phi (tree ref, tree phi)
+ {
+   tree def_arg = NULL_TREE;
+   int i;
+ 
+   /* Find the single PHI argument that is not flowing in from a
+      back edge and verify that the loop-carried definitions do
+      not alias the reference we look for.  */
+   for (i = 0; i < PHI_NUM_ARGS (phi); ++i)
+     {
+       tree arg = PHI_ARG_DEF (phi, i);
+       tree def_stmt;
+ 
+       if (!(PHI_ARG_EDGE (phi, i)->flags & EDGE_DFS_BACK))
+ 	{
+ 	  /* Multiple non-back edges?  Do not try to handle this.  */
+ 	  if (def_arg)
+ 	    return NULL_TREE;
+ 	  def_arg = arg;
+ 	  continue;
+ 	}
+ 
+       def_stmt = SSA_NAME_DEF_STMT (arg);
+       do
+ 	{
+ 	  if (TREE_CODE (def_stmt) != GIMPLE_MODIFY_STMT
+ 	      || refs_may_alias_p (ref, GIMPLE_STMT_OPERAND (def_stmt, 0)))
+ 	    return NULL_TREE;
+ 	  /* ???  This will only work, reaching the PHI node again if
+ 	     there is a single virtual operand on def_stmt.  */
+ 	  def_stmt = get_single_def_stmt (def_stmt);
+ 	  if (!def_stmt)
+ 	    return NULL_TREE;
+ 	}
+       while (def_stmt != phi);
+     }
+ 
+   return SSA_NAME_DEF_STMT (def_arg);
+ }
+ 
+ /* Return the single reference statement defining all virtual uses
+    in VUSES or NULL_TREE, if there are multiple defining statements.
+    Take into account only definitions that alias REF if following
+    back-edges.  */
+ 
+ static tree
+ get_def_ref_stmt (tree ref, tree stmt)
+ {
+   tree vuse, def_stmt = NULL_TREE;
+   ssa_op_iter i;
+ 
+   switch (NUM_SSA_OPERANDS (stmt, SSA_OP_VIRTUAL_USES))
+     {
+     case 0:
+       gcc_unreachable ();
+ 
+     case 1:
+       def_stmt = SSA_NAME_DEF_STMT (SINGLE_SSA_TREE_OPERAND (stmt, SSA_OP_VIRTUAL_USES));
+       /* We can only handle lookups over PHI nodes for a single
+ 	 virtual operand.  */
+       if (TREE_CODE (def_stmt) == PHI_NODE)
+ 	return get_single_def_stmt_from_phi (ref, def_stmt);
+       return def_stmt;
+ 
+     default:;
+     }
+ 
+   FOR_EACH_SSA_TREE_OPERAND (vuse, stmt, i, SSA_OP_VIRTUAL_USES)
+     {
+       tree tmp = SSA_NAME_DEF_STMT (vuse);
+       if (def_stmt
+ 	  && tmp != def_stmt)
+ 	return NULL_TREE;
+       def_stmt = tmp;
+     }
+ 
+   return def_stmt;
+ }
+ 
+ /* Return the single reference statement defining all virtual uses
+    in VUSES or NULL_TREE, if there are multiple defining statements.
+    Take into account only definitions that alias REF if following
+    back-edges.  */
+ 
+ static tree
+ get_def_ref_stmt_vuses (tree ref, VEC (tree, gc) *vuses)
+ {
+   tree def_stmt, vuse;
+   unsigned int i;
+ 
+   gcc_assert (VEC_length (tree, vuses) >= 1);
+ 
+   def_stmt = SSA_NAME_DEF_STMT (VEC_index (tree, vuses, 0));
+   if (TREE_CODE (def_stmt) == PHI_NODE)
+     {
+       /* We can only handle lookups over PHI nodes for a single
+ 	 virtual operand.  */
+       if (VEC_length (tree, vuses) == 1)
+ 	{
+ 	  def_stmt = get_single_def_stmt_from_phi (ref, def_stmt);
+ 	  goto cont;
+ 	}
+       else
+ 	return NULL_TREE;
+     }
+ 
+   /* Verify each VUSE reaches the same defining stmt.  */
+   for (i = 1; VEC_iterate (tree, vuses, i, vuse); ++i)
+     {
+       tree tmp = SSA_NAME_DEF_STMT (vuse);
+       if (tmp != def_stmt)
+ 	return NULL_TREE;
+     }
+ 
+   /* Now see if the definition aliases ref, and loop until it does.  */
+ cont:
+   while (def_stmt
+ 	 && TREE_CODE (def_stmt) == GIMPLE_MODIFY_STMT
+ 	 && !get_call_expr_in (def_stmt)
+ 	 && !refs_may_alias_p (ref, GIMPLE_STMT_OPERAND (def_stmt, 0)))
+     def_stmt = get_def_ref_stmt (ref, def_stmt);
+ 
+   return def_stmt;
+ }
+ 
  /* Lookup OP in the current hash table, and return the resulting
     value number if it exists in the hash table.  Return NULL_TREE if
     it does not exist in the hash table. */
*************** vn_reference_lookup (tree op, VEC (tree,
*** 674,679 ****
--- 839,845 ----
  {
    void **slot;
    struct vn_reference_s vr1;
+   tree def_stmt;
  
    vr1.vuses = valueize_vuses (vuses);
    vr1.operands = valueize_refs (shared_reference_ops_from_ref (op));
*************** vn_reference_lookup (tree op, VEC (tree,
*** 683,692 ****
    if (!slot && current_info == optimistic_info)
      slot = htab_find_slot_with_hash (valid_info->references, &vr1, vr1.hashcode,
  				     NO_INSERT);
!   if (!slot)
!     return NULL_TREE;
  
!   return ((vn_reference_t)*slot)->result;
  }
  
  /* Insert OP into the current hash table with a value number of
--- 849,882 ----
    if (!slot && current_info == optimistic_info)
      slot = htab_find_slot_with_hash (valid_info->references, &vr1, vr1.hashcode,
  				     NO_INSERT);
!   if (slot)
!     return ((vn_reference_t)*slot)->result;
! 
!   /* If there is a single defining statement for all virtual uses, we can
!      use that, following virtual use-def chains.  */
!   if (vr1.vuses
!       && VEC_length (tree, vr1.vuses) >= 1
!       && (def_stmt = get_def_ref_stmt_vuses (op, vr1.vuses))
!       && TREE_CODE (def_stmt) == GIMPLE_MODIFY_STMT
!       /* If there is a call involved, op must be assumed to
! 	 be clobbered.  */
!       && !get_call_expr_in (def_stmt))
!     {
!       /* We are now at an aliasing definition for the vuses we want to
! 	 look up.  Re-do the lookup with the vdefs for this stmt.  */
!       vdefs_to_vec (def_stmt, &vuses);
!       vr1.vuses = valueize_vuses (vuses);
!       vr1.hashcode = vn_reference_compute_hash (&vr1);
!       slot = htab_find_slot_with_hash (current_info->references, &vr1, vr1.hashcode,
! 				       NO_INSERT);
!       if (!slot && current_info == optimistic_info)
!         slot = htab_find_slot_with_hash (valid_info->references, &vr1, vr1.hashcode,
! 				         NO_INSERT);
!       if (slot)
! 	return ((vn_reference_t)*slot)->result;
!     }
  
!   return NULL_TREE;
  }
  
  /* Insert OP into the current hash table with a value number of
Index: trunk/gcc/tree-ssa-structalias.c
===================================================================
*** trunk.orig/gcc/tree-ssa-structalias.c	2008-03-03 14:59:40.000000000 +0100
--- trunk/gcc/tree-ssa-structalias.c	2008-03-03 15:05:56.000000000 +0100
*************** bitpos_of_field (const tree fdecl)
*** 2630,2654 ****
  }
  
  
- /* Return true if an access to [ACCESSPOS, ACCESSSIZE]
-    overlaps with a field at [FIELDPOS, FIELDSIZE] */
- 
- static bool
- offset_overlaps_with_access (const unsigned HOST_WIDE_INT fieldpos,
- 			     const unsigned HOST_WIDE_INT fieldsize,
- 			     const unsigned HOST_WIDE_INT accesspos,
- 			     const unsigned HOST_WIDE_INT accesssize)
- {
-   if (fieldpos == accesspos && fieldsize == accesssize)
-     return true;
-   if (accesspos >= fieldpos && accesspos < (fieldpos + fieldsize))
-     return true;
-   if (accesspos < fieldpos && (accesspos + accesssize > fieldpos))
-     return true;
- 
-   return false;
- }
- 
  /* Given a COMPONENT_REF T, return the constraint_expr for it.  */
  
  static void
--- 2630,2635 ----
*************** get_constraint_for_component_ref (tree t
*** 2713,2720 ****
  	  varinfo_t curr;
  	  for (curr = get_varinfo (result->var); curr; curr = curr->next)
  	    {
! 	      if (offset_overlaps_with_access (curr->offset, curr->size,
! 					       result->offset, bitmaxsize))
  		{
  		  result->var = curr->id;
  		  break;
--- 2694,2701 ----
  	  varinfo_t curr;
  	  for (curr = get_varinfo (result->var); curr; curr = curr->next)
  	    {
! 	      if (ranges_overlap_p (curr->offset, curr->size,
! 				    result->offset, bitmaxsize))
  		{
  		  result->var = curr->id;
  		  break;
Index: trunk/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-7.c
===================================================================
*** /dev/null	1970-01-01 00:00:00.000000000 +0000
--- trunk/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-7.c	2008-03-03 15:05:56.000000000 +0100
***************
*** 0 ****
--- 1,26 ----
+ /* { dg-do compile } */
+ /* { dg-options "-O -fdump-tree-fre-details" } */
+ 
+ struct
+ {
+   int x;
+   int y;
+ } S[100];
+ 
+ int z[100];
+ 
+ int
+ foo (int y)
+ {
+   int x;
+ 
+   S[5].x = 4;
+   S[5].y = 0;
+ 
+   x = S[5].x;
+ 
+   return (x);
+ }
+ 
+ /* { dg-final { scan-tree-dump "Replaced S\\\[5\\\].x with 4" "fre" } } */
+ /* { dg-final { cleanup-tree-dump "fre" } } */
Index: trunk/gcc/testsuite/gcc.dg/tree-ssa/20031106-4.c
===================================================================
*** trunk.orig/gcc/testsuite/gcc.dg/tree-ssa/20031106-4.c	2008-01-29 11:43:26.000000000 +0100
--- trunk/gcc/testsuite/gcc.dg/tree-ssa/20031106-4.c	2008-03-03 15:05:56.000000000 +0100
*************** void foo (struct s*  r)
*** 26,30 ****
  }
  
  /* There should be no link_error calls.  */
! /* { dg-final { scan-tree-dump-times "link_error" 0 "optimized" { xfail *-*-* } } } */
  /* { dg-final { cleanup-tree-dump "optimized" } } */
--- 26,30 ----
  }
  
  /* There should be no link_error calls.  */
! /* { dg-final { scan-tree-dump-times "link_error" 0 "optimized" } } */
  /* { dg-final { cleanup-tree-dump "optimized" } } */
Index: trunk/gcc/tree.h
===================================================================
*** trunk.orig/gcc/tree.h	2008-03-03 14:59:40.000000000 +0100
--- trunk/gcc/tree.h	2008-03-03 15:12:51.000000000 +0100
*************** extern tree get_unwidened (tree, tree);
*** 4564,4572 ****
  
  extern tree get_narrower (tree, int *);
  
! /* Given an expression EXP that may be a COMPONENT_REF or an ARRAY_REF,
!    look for nested component-refs or array-refs at constant positions
!    and find the ultimate containing object, which is returned.  */
  
  extern tree get_inner_reference (tree, HOST_WIDE_INT *, HOST_WIDE_INT *,
  				 tree *, enum machine_mode *, int *, int *,
--- 4564,4576 ----
  
  extern tree get_narrower (tree, int *);
  
! /* Return true if T is an expression that get_inner_reference handles.  */
! 
! extern int handled_component_p (const_tree);
! 
! /* Given an expression EXP that is a handled_component_p,
!    look for the ultimate containing object, which is returned and specify
!    the access position and size.  */
  
  extern tree get_inner_reference (tree, HOST_WIDE_INT *, HOST_WIDE_INT *,
  				 tree *, enum machine_mode *, int *, int *,
*************** extern tree get_inner_reference (tree, H
*** 4578,4587 ****
  
  extern bool contains_packed_reference (const_tree exp);
  
- /* Return 1 if T is an expression that get_inner_reference handles.  */
- 
- extern int handled_component_p (const_tree);
- 
  /* Return a tree of sizetype representing the size, in bytes, of the element
     of EXP, an ARRAY_REF.  */
  
--- 4582,4587 ----
*************** extern int get_pointer_alignment (tree, 
*** 4875,4887 ****
  /* In convert.c */
  extern tree strip_float_extensions (tree);
  
- /* In alias.c */
- extern void record_component_aliases (tree);
- extern alias_set_type get_alias_set (tree);
- extern int alias_sets_conflict_p (alias_set_type, alias_set_type);
- extern int alias_sets_must_conflict_p (alias_set_type, alias_set_type);
- extern int objects_must_conflict_p (tree, tree);
- 
  /* In tree.c */
  extern int really_constant_p (const_tree);
  extern int int_fits_type_p (const_tree, const_tree);
--- 4875,4880 ----
Index: trunk/gcc/alias.h
===================================================================
*** trunk.orig/gcc/alias.h	2008-02-26 10:52:21.000000000 +0100
--- trunk/gcc/alias.h	2008-03-03 15:06:58.000000000 +0100
*************** along with GCC; see the file COPYING3.  
*** 20,33 ****
--- 20,40 ----
  #ifndef GCC_ALIAS_H
  #define GCC_ALIAS_H
  
+ #include "coretypes.h"
+ 
  /* The type of an alias set.  */
  typedef HOST_WIDE_INT alias_set_type;
  
  extern alias_set_type new_alias_set (void);
+ extern alias_set_type get_alias_set (tree);
  extern alias_set_type get_varargs_alias_set (void);
  extern alias_set_type get_frame_alias_set (void);
  extern bool component_uses_parent_alias_set (const_tree);
  extern bool alias_set_subset_of (alias_set_type, alias_set_type);
+ extern void record_component_aliases (tree);
+ extern int alias_sets_conflict_p (alias_set_type, alias_set_type);
+ extern int alias_sets_must_conflict_p (alias_set_type, alias_set_type);
+ extern int objects_must_conflict_p (tree, tree);
  extern int nonoverlapping_memrefs_p (const_rtx, const_rtx);
  
  /* This alias set can be used to force a memory to conflict with all
Index: trunk/gcc/tree-ssa-alias.c
===================================================================
*** trunk.orig/gcc/tree-ssa-alias.c	2008-03-03 14:59:40.000000000 +0100
--- trunk/gcc/tree-ssa-alias.c	2008-03-03 15:05:56.000000000 +0100
*************** may_alias_p (tree ptr, alias_set_type me
*** 2938,2943 ****
--- 2938,3007 ----
  }
  
  
+ /* Return true, if the two memory references REF1 and REF2 may alias.  */
+ 
+ bool
+ refs_may_alias_p (tree ref1, tree ref2)
+ {
+   tree base1, base2;
+   HOST_WIDE_INT offset1 = 0, offset2 = 0;
+   HOST_WIDE_INT size1 = -1, size2 = -1;
+   HOST_WIDE_INT max_size1 = -1, max_size2 = -1;
+ 
+   /* Defer to TBAA if possible.  */
+   if (flag_strict_aliasing
+       && !alias_sets_conflict_p (get_alias_set (ref1), get_alias_set (ref2)))
+     return false;
+ 
+   /* Decompose the references into their base objects and the access.  */
+   base1 = ref1;
+   if (handled_component_p (ref1))
+     base1 = get_ref_base_and_extent (ref1, &offset1, &size1, &max_size1);
+   base2 = ref2;
+   if (handled_component_p (ref2))
+     base2 = get_ref_base_and_extent (ref2, &offset2, &size2, &max_size2);
+ 
+   /* If both references are based on different variables, they cannot alias.
+      If both references are based on the same variable, they cannot alias if
+      if the accesses do not overlap.  */
+   if (SSA_VAR_P (base1)
+       && SSA_VAR_P (base2)
+       && (!operand_equal_p (base1, base2, 0)
+ 	  || !ranges_overlap_p (offset1, max_size1, offset2, max_size2)))
+     return false;
+ 
+   /* If both references are through pointers and both pointers are equal
+      then they do not alias if the accesses do not overlap.  */
+   if (TREE_CODE (base1) == INDIRECT_REF
+       && TREE_CODE (base2) == INDIRECT_REF
+       && operand_equal_p (TREE_OPERAND (base1, 0),
+ 			  TREE_OPERAND (base2, 0), 0)
+       && !ranges_overlap_p (offset1, max_size1, offset2, max_size2))
+     return false;
+ 
+   return true;
+ }
+ 
+ /* Return true, if the two memory references REF1 and REF2 must alias.  */
+ 
+ bool
+ refs_must_alias_p (tree ref1, tree ref2)
+ {
+   return operand_equal_p (ref1, ref2, 0);
+ }
+ 
+ /* Return true, if the memory reference REF is killed by the memory
+    definition DEF.  */
+ 
+ bool
+ ref_killed_by_def_p (tree ref, tree def)
+ {
+   /* While kill relationship is non-symmetric, must-alias relationship
+      is a conservative approximation to it.  */
+   return refs_must_alias_p (ref, def);
+ }
+ 
+ 
  /* Add ALIAS to the set of variables that may alias VAR.  */
  
  static void
Index: trunk/gcc/tree-ssa-structalias.h
===================================================================
*** trunk.orig/gcc/tree-ssa-structalias.h	2008-01-29 11:43:26.000000000 +0100
--- trunk/gcc/tree-ssa-structalias.h	2008-03-03 15:05:56.000000000 +0100
*************** struct alias_info
*** 65,70 ****
--- 65,73 ----
  /* In tree-ssa-alias.c.  */
  enum escape_type is_escape_site (tree);
  void update_mem_sym_stats_from_stmt (tree, tree, long, long);
+ bool refs_may_alias_p (tree, tree);
+ bool refs_must_alias_p (tree, tree);
+ bool ref_killed_by_def_p (tree, tree);
  
  /* In tree-ssa-structalias.c.  */
  extern void compute_points_to_sets (struct alias_info *);
Index: trunk/gcc/tree-ssa-dse.c
===================================================================
*** trunk.orig/gcc/tree-ssa-dse.c	2008-01-29 11:43:26.000000000 +0100
--- trunk/gcc/tree-ssa-dse.c	2008-03-03 15:05:56.000000000 +0100
*************** along with GCC; see the file COPYING3.  
*** 33,38 ****
--- 33,39 ----
  #include "tree-dump.h"
  #include "domwalk.h"
  #include "flags.h"
+ #include "tree-ssa-structalias.h"
  
  /* This file implements dead store elimination.
  
*************** get_kill_of_stmt_lhs (tree stmt,
*** 259,265 ****
        /* If the use stmts lhs matches the original lhs we have
  	 found the kill, otherwise continue walking.  */
        use_lhs = GIMPLE_STMT_OPERAND (stmt, 0);
!       if (operand_equal_p (use_lhs, lhs, 0))
  	{
  	  *use_stmt = stmt;
  	  return true;
--- 260,266 ----
        /* If the use stmts lhs matches the original lhs we have
  	 found the kill, otherwise continue walking.  */
        use_lhs = GIMPLE_STMT_OPERAND (stmt, 0);
!       if (ref_killed_by_def_p (lhs, use_lhs))
  	{
  	  *use_stmt = stmt;
  	  return true;
Index: trunk/gcc/Makefile.in
===================================================================
*** trunk.orig/gcc/Makefile.in	2008-03-03 11:28:17.000000000 +0100
--- trunk/gcc/Makefile.in	2008-03-03 15:12:34.000000000 +0100
*************** GCOV_IO_H = gcov-io.h gcov-iov.h auto-ho
*** 790,796 ****
  COVERAGE_H = coverage.h $(GCOV_IO_H)
  DEMANGLE_H = $(srcdir)/../include/demangle.h
  RECOG_H = recog.h
! ALIAS_H = alias.h
  EMIT_RTL_H = emit-rtl.h
  FLAGS_H = flags.h options.h
  FUNCTION_H = function.h $(TREE_H) $(HASHTAB_H)
--- 790,796 ----
  COVERAGE_H = coverage.h $(GCOV_IO_H)
  DEMANGLE_H = $(srcdir)/../include/demangle.h
  RECOG_H = recog.h
! ALIAS_H = alias.h coretypes.h
  EMIT_RTL_H = emit-rtl.h
  FLAGS_H = flags.h options.h
  FUNCTION_H = function.h $(TREE_H) $(HASHTAB_H)
*************** tree-outof-ssa.o : tree-outof-ssa.c $(TR
*** 2012,2018 ****
  tree-ssa-dse.o : tree-ssa-dse.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
     $(TM_H) $(GGC_H) $(TREE_H) $(RTL_H) $(TM_P_H) $(BASIC_BLOCK_H) \
     $(TREE_FLOW_H) tree-pass.h $(TREE_DUMP_H) domwalk.h $(FLAGS_H) \
!    $(DIAGNOSTIC_H) $(TIMEVAR_H)
  tree-ssa-forwprop.o : tree-ssa-forwprop.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
     $(TM_H) $(GGC_H) $(TREE_H) $(RTL_H) $(TM_P_H) $(BASIC_BLOCK_H) \
     $(TREE_FLOW_H) tree-pass.h $(TREE_DUMP_H) $(DIAGNOSTIC_H) $(TIMEVAR_H) \
--- 2012,2018 ----
  tree-ssa-dse.o : tree-ssa-dse.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
     $(TM_H) $(GGC_H) $(TREE_H) $(RTL_H) $(TM_P_H) $(BASIC_BLOCK_H) \
     $(TREE_FLOW_H) tree-pass.h $(TREE_DUMP_H) domwalk.h $(FLAGS_H) \
!    $(DIAGNOSTIC_H) $(TIMEVAR_H) tree-ssa-structalias.h
  tree-ssa-forwprop.o : tree-ssa-forwprop.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
     $(TM_H) $(GGC_H) $(TREE_H) $(RTL_H) $(TM_P_H) $(BASIC_BLOCK_H) \
     $(TREE_FLOW_H) tree-pass.h $(TREE_DUMP_H) $(DIAGNOSTIC_H) $(TIMEVAR_H) \
*************** tree-ssa-sccvn.o : tree-ssa-sccvn.c $(TR
*** 2080,2086 ****
     $(TM_H) coretypes.h $(TREE_DUMP_H) tree-pass.h $(FLAGS_H) $(CFGLOOP_H) \
     alloc-pool.h $(BASIC_BLOCK_H) bitmap.h $(HASHTAB_H) $(TREE_GIMPLE_H) \
     $(TREE_INLINE_H) tree-iterator.h tree-ssa-propagate.h tree-ssa-sccvn.h \
!    $(PARAMS_H)
  tree-vn.o : tree-vn.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(GGC_H) \
     $(TREE_H) $(TREE_FLOW_H) $(HASHTAB_H) langhooks.h tree-pass.h \
     $(TREE_DUMP_H) $(DIAGNOSTIC_H) tree-ssa-sccvn.h
--- 2080,2086 ----
     $(TM_H) coretypes.h $(TREE_DUMP_H) tree-pass.h $(FLAGS_H) $(CFGLOOP_H) \
     alloc-pool.h $(BASIC_BLOCK_H) bitmap.h $(HASHTAB_H) $(TREE_GIMPLE_H) \
     $(TREE_INLINE_H) tree-iterator.h tree-ssa-propagate.h tree-ssa-sccvn.h \
!    $(PARAMS_H) tree-ssa-structalias.h
  tree-vn.o : tree-vn.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(GGC_H) \
     $(TREE_H) $(TREE_FLOW_H) $(HASHTAB_H) langhooks.h tree-pass.h \
     $(TREE_DUMP_H) $(DIAGNOSTIC_H) tree-ssa-sccvn.h
Index: trunk/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-8.c
===================================================================
*** /dev/null	1970-01-01 00:00:00.000000000 +0000
--- trunk/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-8.c	2008-03-03 15:05:56.000000000 +0100
***************
*** 0 ****
--- 1,26 ----
+ /* { dg-do compile } */
+ /* { dg-options "-O -fdump-tree-fre-details" } */
+ 
+ struct
+ {
+   int x;
+   int y;
+ } S[100];
+ 
+ int z[100];
+ 
+ int
+ foo (int y)
+ {
+   int x;
+ 
+   S[5].x = 4;
+   S[5].y = 0;
+ 
+   x = S[5].x;
+ 
+   return (x);
+ }
+ 
+ /* { dg-final { scan-tree-dump "Replaced S\\\[5\\\].x with 4" "fre" } } */
+ /* { dg-final { cleanup-tree-dump "fre" } } */
Index: trunk/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-10.c
===================================================================
*** /dev/null	1970-01-01 00:00:00.000000000 +0000
--- trunk/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-10.c	2008-03-03 15:05:56.000000000 +0100
***************
*** 0 ****
--- 1,29 ----
+ /* { dg-do compile } */
+ /* { dg-options "-O -fstrict-aliasing -fno-tree-sra --param max-aliased-vops=0 --param max-fields-for-field-sensitive=0 -fdump-tree-fre-details" } */
+ 
+ /* Should be optimized, propagating &a into (*p)[i] with parameters
+      --param max-aliased-vops=0 --param max-fields-for-field-sensitive=0
+    which means max 1 VOP per stmt and no SFTs.  */
+ 
+ /* For this testcase we need TBAA to work.  */
+ 
+ struct Foo
+ {
+   void *data;
+   int size;
+ };
+ void foo(double (*q)[4], struct Foo *tmp1)
+ {
+   double a[4];
+   int i;
+   tmp1->data = &a;
+   tmp1->size = 4;
+   for (i=0; i<4; ++i)
+     {
+       double (*p)[4] = tmp1->data;
+       (*p)[i] = (*q)[i];
+     }
+ }
+ 
+ /* { dg-final { scan-tree-dump "Replaced .* with &a" "fre" } } */
+ /* { dg-final { cleanup-tree-dump "fre" } } */
Index: trunk/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-9.c
===================================================================
*** /dev/null	1970-01-01 00:00:00.000000000 +0000
--- trunk/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-9.c	2008-03-03 15:05:56.000000000 +0100
***************
*** 0 ****
--- 1,31 ----
+ /* { dg-do compile } */
+ /* { dg-options "-O -fno-tree-sra --param max-aliased-vops=0 --param max-fields-for-field-sensitive=0 -fdump-tree-fre-details" } */
+ 
+ /* Should be optimized, propagating &a into (*p)[i] with parameters
+      --param max-aliased-vops=0 --param max-fields-for-field-sensitive=0
+    which means max 1 VOP per stmt and no SFTs.  */
+ 
+ struct Foo
+ {
+   void *data;
+   double size;
+ };
+ void foo(double (*q)[4])
+ {
+   struct Foo tmp1;
+   double a[4];
+   int i;
+   tmp1.data = &a;
+   tmp1.size = 4;
+   for (i=0; i<4; ++i)
+     {
+       double (*p)[4] = tmp1.data;
+       (*p)[i] = (*q)[i];
+       /* We want a PHI for the VOP for accessing tmp1.data, so place
+  	 this store to tmp1 here.  */
+       tmp1.size -= 1.0;
+     }
+ }
+ 
+ /* { dg-final { scan-tree-dump "Replaced .* with &a" "fre" } } */
+ /* { dg-final { cleanup-tree-dump "fre" } } */
Index: trunk/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-11.c
===================================================================
*** /dev/null	1970-01-01 00:00:00.000000000 +0000
--- trunk/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-11.c	2008-03-03 15:05:56.000000000 +0100
***************
*** 0 ****
--- 1,30 ----
+ /* { dg-do compile } */
+ /* { dg-options "-O -fno-tree-sra --param max-aliased-vops=0 --param max-fields-for-field-sensitive=0 -fdump-tree-fre-details" } */
+ 
+ /* Should be optimized, propagating &a into (*p)[i] with parameters
+      --param max-aliased-vops=0 --param max-fields-for-field-sensitive=0
+    which means max 1 VOP per stmt and no SFTs.  */
+ 
+ struct Foo
+ {
+   void *data;
+   double size;
+ };
+ void foo(double (*q)[4])
+ {
+   struct Foo tmp1;
+   double a[4];
+   int i;
+   tmp1.data = &a;
+   for (i=0; i<4; ++i)
+     {
+       double (*p)[4] = tmp1.data;
+       (*p)[i] = (*q)[i];
+       /* We want a PHI for the VOP for accessing tmp1.data, so place
+  	 this store to tmp1 here.  */
+       tmp1.size -= 1.0;
+     }
+ }
+ 
+ /* { dg-final { scan-tree-dump "Replaced" "fre" } } */
+ /* { dg-final { cleanup-tree-dump "fre" } } */



More information about the Gcc-patches mailing list