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][alias-improvements] Re-implement the SCCVN reference walker / alias oracle


This re-implements the SCCVN oracle by properly walking all
value-equivalent VUSEs for a given memory reference and doing hashtable
lookups for them.  On the trunk we only do this for the final aliasing
def - which means we catch store-forwarding reliably but not really
doing CSE of loads properly.  This is more visible on the 
alias-improvements branch but it also fixes for example PR38207 which
is seen on the trunk.

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

This fixes a bunch of testsuite failures and exposes some which
I have reduced to a PRE issue (that is not easy to fix, I have
added tree-ssa/ssa-pre-24.c for that which fails now) but which
is fixable with a copyprop patch as well (PR38458).

I will install the copyprop patch as a separate revision though.

Additional fails are

+FAIL: gcc.dg/vect/pr25413a.c scan-tree-dump-times vect "vectorized 1 
loops" 1
+FAIL: gcc.dg/vect/vect-64.c scan-tree-dump-times vect "vectorized 3 
loops" 1
+FAIL: gcc.dg/vect/vect-align-2.c scan-tree-dump-times vect "Alignment of 
access
 forced using versioning" 1
+FAIL: gcc.dg/vect/vect-align-2.c scan-tree-dump-times vect "vectorized 1 
loops"
 1
+FAIL: gcc.dg/vect/no-section-anchors-vect-64.c scan-tree-dump-times vect 
"vecto
rized 3 loops" 1
+FAIL: gcc.dg/vect/no-section-anchors-vect-64.c scan-tree-dump-times vect 
"Align
ment of access forced using peeling" 2

we also accumulated one more XPASS on the branch,

+XPASS: gcc.dg/tree-ssa/20070302-1.c (test for excess errors)

Richard.

2008-12-09  Richard Guenther  <rguenther@suse.de>

	PR tree-optimization/38207
	* tree-flow.h: Include tree-ssa-alias.h.
	(get_single_def_stmt, get_single_def_stmt_from_phi,
	get_single_def_stmt_with_phi): Remove.
	(refs_may_alias_p): Move ...
	* tree-ssa-alias.h: ... here.  New file.
	* tree-dfa.c (refs_may_alias_p): Handle non-aliased locals.
	(get_single_def_stmt, get_single_def_stmt_from_phi,
	get_single_def_stmt_with_phi): Remove.
	* tree-ssa-alias.c: Include tree-ssa-alias.h.
	(call_may_clobber_ref_p): New function.
	(stmt_may_clobber_ref_p): Likewise.
	(get_single_incoming_phi_arg_for_maybe_loop_invariant_ref): Likewise.
	(walk_non_aliased_vuses): Likewise.
	* Makefile.in (TREE_FLOW_H): Add tree-ssa-alias.h.
	* tree-ssa-sccvn.c (SSA_VAL): Revert handling NULL arguments.
	(get_def_ref_stmt_vuse): Remove.
	(vn_reference_lookup_2): New function.
	(vn_reference_lookup_pieces): Use walk_non_aliased_vuses for
	walking equivalent vuses.
	(vn_reference_lookup): Likewise.

	* gcc.dg/tree-ssa/ssa-fre-18.c: New testcase.
	* gcc.dg/tree-ssa/ssa-fre-19.c: Likewise.
	* gcc.dg/tree-ssa/ssa-lim-3.c: Run at -O to disable PRE.
	* gcc.dg/tree-ssa/ssa-pre-23.c: New testcase.
	* gcc.dg/tree-ssa/ssa-pre-24.c: Likewise.

Index: gcc/tree-ssa-alias.h
===================================================================
*** /dev/null	1970-01-01 00:00:00.000000000 +0000
--- gcc/tree-ssa-alias.h	2008-12-10 16:06:54.000000000 +0100
***************
*** 0 ****
--- 1,33 ----
+ /* Tree based alias analysis and alias oracle.
+    Copyright (C) 2008 Free Software Foundation, Inc.
+    Contributed by Richard Guenther  <rguenther@suse.de>
+ 
+    This file is part of GCC.
+ 
+    GCC is free software; you can redistribute it and/or modify
+    under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 3 of the License, or
+    (at your option) any later version.
+ 
+    GCC is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+ 
+    You should have received a copy of the GNU General Public License
+    along with GCC; see the file COPYING3.  If not see
+    <http://www.gnu.org/licenses/>.  */
+ 
+ #ifndef TREE_SSA_ALIAS_H
+ #define TREE_SSA_ALIAS_H
+ 
+ #include "coretypes.h"
+ 
+ /* In tree-ssa-alias.c  */
+ void *walk_non_aliased_vuses (tree, tree,
+ 			      void *(*)(tree, tree, void *), void *);
+ 
+ /* In tree-dfa.c  */
+ extern bool refs_may_alias_p (tree, tree);
+ 
+ #endif /* TREE_SSA_ALIAS_H  */
Index: gcc/tree-flow.h
===================================================================
*** gcc/tree-flow.h.orig	2008-12-10 16:00:59.000000000 +0100
--- gcc/tree-flow.h	2008-12-10 16:06:54.000000000 +0100
*************** along with GCC; see the file COPYING3.  
*** 30,35 ****
--- 30,36 ----
  #include "tree-ssa-operands.h"
  #include "cgraph.h"
  #include "ipa-reference.h"
+ #include "tree-ssa-alias.h"
  
  /* Forward declare structures for the garbage collector GTY markers.  */
  #ifndef GCC_BASIC_BLOCK_H
*************** extern tree make_rename_temp (tree, cons
*** 669,678 ****
  extern void set_default_def (tree, tree);
  extern tree gimple_default_def (struct function *, tree);
  extern bool stmt_references_abnormal_ssa_name (gimple);
- extern bool refs_may_alias_p (tree, tree);
- extern gimple get_single_def_stmt (gimple);
- extern gimple get_single_def_stmt_from_phi (tree, gimple);
- extern gimple get_single_def_stmt_with_phi (tree, gimple);
  
  /* In tree-phinodes.c  */
  extern void reserve_phi_args_for_new_edge (basic_block);
--- 670,675 ----
Index: gcc/tree-dfa.c
===================================================================
*** gcc/tree-dfa.c.orig	2008-12-10 16:01:51.000000000 +0100
--- gcc/tree-dfa.c	2008-12-10 16:07:37.000000000 +0100
*************** refs_may_alias_p (tree ref1, tree ref2)
*** 975,980 ****
--- 975,992 ----
        return ranges_overlap_p (offset1, max_size1, offset2, max_size2);
      }
  
+   /* If one reference is based on a pointer and one is based on a local
+      variable that does not have its address taken, they cannot alias.  */
+   if ((SSA_VAR_P (base1)
+        && !TREE_ADDRESSABLE (base1)
+        && !is_global_var (base1)
+        && INDIRECT_REF_P (base2))
+       || (SSA_VAR_P (base2)
+ 	  && !TREE_ADDRESSABLE (base2)
+ 	  && !is_global_var (base2)
+ 	  && INDIRECT_REF_P (base1)))
+     return false;
+ 
    /* If one base is a ref-all pointer or a TARGET_MEM_REF weird things
       are allowed.  */
    strict_aliasing_applies = (flag_strict_aliasing
*************** refs_may_alias_p (tree ref1, tree ref2)
*** 1062,1138 ****
    return true;
  }
  
- /* Given a stmt STMT that references memory, return the single stmt
-    that is reached by following the VUSE -> VDEF link.
-    Note that this may return a PHI node as well.
-    Note that if the VUSE is a default definition this function will
-    return an empty statement.  */
- 
- gimple
- get_single_def_stmt (gimple stmt)
- {
-   return SSA_NAME_DEF_STMT (gimple_vuse (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.  */
- 
- gimple
- get_single_def_stmt_from_phi (tree ref, gimple phi)
- {
-   tree def_arg = NULL_TREE;
-   unsigned 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 < gimple_phi_num_args (phi); ++i)
-     {
-       tree arg = PHI_ARG_DEF (phi, i);
-       gimple def_stmt;
- 
-       if (!(gimple_phi_arg_edge (phi, i)->flags & EDGE_DFS_BACK))
- 	{
- 	  /* Multiple non-back edges?  Do not try to handle this.  */
- 	  if (def_arg)
- 	    return NULL;
- 	  def_arg = arg;
- 	  continue;
- 	}
- 
-       /* Follow the definitions back to the original PHI node.  Bail
- 	 out once a definition is found that may alias REF.  */
-       def_stmt = SSA_NAME_DEF_STMT (arg);
-       do
- 	{
- 	  if (!is_gimple_assign (def_stmt)
- 	      || refs_may_alias_p (ref, gimple_assign_lhs (def_stmt)))
- 	    return NULL;
- 	  def_stmt = get_single_def_stmt (def_stmt);
- 	  if (!def_stmt)
- 	    return NULL;
- 	}
-       while (def_stmt != phi);
-     }
- 
-   return SSA_NAME_DEF_STMT (def_arg);
- }
- 
- /* Return the single reference statement defining all virtual uses
-    on STMT or NULL_TREE, if there are multiple defining statements.
-    Take into account only definitions that alias REF if following
-    back-edges when looking through a loop PHI node.  */
- 
- gimple
- get_single_def_stmt_with_phi (tree ref, gimple stmt)
- {
-   gimple def_stmt = SSA_NAME_DEF_STMT (gimple_vuse (stmt));
- 
-   if (gimple_code (def_stmt) == GIMPLE_PHI)
-     return get_single_def_stmt_from_phi (ref, def_stmt);
- 
-   return def_stmt;
- }
--- 1074,1076 ----
Index: gcc/tree-ssa-alias.c
===================================================================
*** gcc/tree-ssa-alias.c.orig	2008-12-10 16:00:59.000000000 +0100
--- gcc/tree-ssa-alias.c	2008-12-10 16:08:00.000000000 +0100
*************** along with GCC; see the file COPYING3.  
*** 48,53 ****
--- 48,54 ----
  #include "vecprim.h"
  #include "pointer-set.h"
  #include "alloc-pool.h"
+ #include "tree-ssa-alias.h"
  
  /* Broad overview of how aliasing works:
     
*************** struct gimple_opt_pass pass_build_alias 
*** 1107,1109 ****
--- 1108,1239 ----
    TODO_rebuild_alias | TODO_dump_func  /* todo_flags_finish */
   }
  };
+ 
+ 
+ 
+ /* If the call in statement CALL may clobber the memory reference REF
+    return true, otherwise return false.  */
+ 
+ static bool
+ call_may_clobber_ref_p (gimple call, tree ref)
+ {
+   tree base;
+ 
+   /* If the call is pure or const it cannot clobber anything.  */
+   if (gimple_call_flags (call)
+       & (ECF_PURE|ECF_CONST|ECF_LOOPING_CONST_OR_PURE|ECF_NOVOPS))
+     return false;
+ 
+   base = get_base_address (ref);
+   if (SSA_VAR_P (base))
+     return is_call_clobbered (base);
+ 
+   return true;
+ }
+ 
+ /* If the statement STMT may clobber the memory reference REF return true,
+    otherwise return false.  */
+ 
+ static 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;
+ }
+ 
+ /* For a phi-node PHI for the virtual operand get the argument that
+    represents the single incoming edge into a loop if REF is invariant
+    in that loop.  */
+ 
+ static tree
+ get_single_incoming_phi_arg_for_maybe_loop_invariant_ref (gimple phi, tree ref)
+ {
+   tree def_arg = NULL_TREE;
+   unsigned i;
+ 
+   for (i = 0; i < gimple_phi_num_args (phi); ++i)
+     {
+       tree arg = PHI_ARG_DEF (phi, i);
+       gimple def_stmt;
+ 
+       if (!(gimple_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;
+ 	}
+ 
+       /* Follow the definitions back to the original PHI node.  Bail
+ 	 out once a definition is found that may clobber REF.  */
+       def_stmt = SSA_NAME_DEF_STMT (arg);
+       do
+ 	{
+ 	  if (gimple_code (def_stmt) == GIMPLE_PHI
+ 	      || gimple_nop_p (def_stmt)
+ 	      || stmt_may_clobber_ref_p (def_stmt, ref))
+ 	    return NULL;
+ 	  def_stmt = SSA_NAME_DEF_STMT (gimple_vuse (def_stmt));
+ 	}
+       while (def_stmt != phi);
+     }
+ 
+   return def_arg;
+ }
+ 
+ /* Based on the memory reference REF and its virtual use VUSE call
+    WALKER for each virtual use that is equivalent to VUSE, including VUSE
+    itself.  That is, for each virtual use for which its defining statement
+    does not clobber REF.
+ 
+    WALKER is called with REF, the current virtual use and DATA.  If
+    WALKER returns non-NULL the walk stops and its result is returned.
+    At the end of a non-successful walk NULL is returned.
+ 
+    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 *data)
+ {
+   do
+     {
+       gimple def_stmt;
+       void *res;
+ 
+       res = (*walker) (ref, vuse, data);
+       if (res)
+ 	return res;
+ 
+       def_stmt = SSA_NAME_DEF_STMT (vuse);
+       if (gimple_nop_p (def_stmt))
+ 	return NULL;
+       else if (gimple_code (def_stmt) == GIMPLE_PHI)
+ 	vuse = get_single_incoming_phi_arg_for_maybe_loop_invariant_ref
+ 	         (def_stmt, ref);
+       else
+ 	{
+ 	  if (stmt_may_clobber_ref_p (def_stmt, ref))
+ 	    return NULL;
+ 	  vuse = gimple_vuse (def_stmt);
+ 	}
+     }
+   while (vuse);
+ 
+   return NULL;
+ }
Index: gcc/Makefile.in
===================================================================
*** gcc/Makefile.in.orig	2008-12-10 16:00:59.000000000 +0100
--- gcc/Makefile.in	2008-12-10 16:06:54.000000000 +0100
*************** CPP_INTERNAL_H = $(srcdir)/../libcpp/int
*** 870,876 ****
  TREE_DUMP_H = tree-dump.h $(SPLAY_TREE_H) tree-pass.h
  TREE_FLOW_H = tree-flow.h tree-flow-inline.h tree-ssa-operands.h \
  		$(BITMAP_H) $(BASIC_BLOCK_H) hard-reg-set.h $(GIMPLE_H) \
! 		$(HASHTAB_H) $(CGRAPH_H) $(IPA_REFERENCE_H)
  TREE_SSA_LIVE_H = tree-ssa-live.h $(PARTITION_H) vecprim.h
  PRETTY_PRINT_H = pretty-print.h $(INPUT_H) $(OBSTACK_H)
  DIAGNOSTIC_H = diagnostic.h diagnostic.def $(PRETTY_PRINT_H) options.h
--- 870,877 ----
  TREE_DUMP_H = tree-dump.h $(SPLAY_TREE_H) tree-pass.h
  TREE_FLOW_H = tree-flow.h tree-flow-inline.h tree-ssa-operands.h \
  		$(BITMAP_H) $(BASIC_BLOCK_H) hard-reg-set.h $(GIMPLE_H) \
! 		$(HASHTAB_H) $(CGRAPH_H) $(IPA_REFERENCE_H) \
! 		tree-ssa-alias.h
  TREE_SSA_LIVE_H = tree-ssa-live.h $(PARTITION_H) vecprim.h
  PRETTY_PRINT_H = pretty-print.h $(INPUT_H) $(OBSTACK_H)
  DIAGNOSTIC_H = diagnostic.h diagnostic.def $(PRETTY_PRINT_H) options.h
Index: gcc/tree-ssa-sccvn.c
===================================================================
*** gcc/tree-ssa-sccvn.c.orig	2008-12-10 16:00:59.000000000 +0100
--- gcc/tree-ssa-sccvn.c	2008-12-10 16:06:54.000000000 +0100
*************** static vn_tables_t current_info;
*** 140,146 ****
  
  static int *rpo_numbers;
  
! #define SSA_VAL(x) (x ? VN_INFO ((x))->valnum : NULL_TREE)
  
  /* This represents the top of the VN lattice, which is the universal
     value.  */
--- 140,146 ----
  
  static int *rpo_numbers;
  
! #define SSA_VAL(x) (VN_INFO ((x))->valnum)
  
  /* This represents the top of the VN lattice, which is the universal
     value.  */
*************** valueize_refs (VEC (vn_reference_op_s, h
*** 793,823 ****
    return orig;
  }
  
- /* 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 gimple
- get_def_ref_stmt_vuse (tree ref, tree vuse)
- {
-   gimple def_stmt;
- 
-   gcc_assert (vuse != NULL_TREE);
- 
-   def_stmt = SSA_NAME_DEF_STMT (vuse);
-   if (gimple_code (def_stmt) == GIMPLE_PHI)
-     def_stmt = get_single_def_stmt_from_phi (ref, def_stmt);
- 
-   /* Now see if the definition aliases ref, and loop until it does.  */
-   while (def_stmt
- 	 && is_gimple_assign (def_stmt)
- 	 && !refs_may_alias_p (ref, gimple_get_lhs (def_stmt)))
-     def_stmt = get_single_def_stmt_with_phi (ref, def_stmt);
- 
-   return def_stmt;
- }
- 
  /* Lookup a SCCVN reference operation VR in the current hash table.
     Returns the resulting value number if it exists in the hash table,
     NULL_TREE otherwise.  VNRESULT will be filled in with the actual
--- 793,798 ----
*************** vn_reference_lookup_1 (vn_reference_t vr
*** 845,850 ****
--- 820,851 ----
    return NULL_TREE;
  }
  
+ /* Callback for walk_non_aliased_vuses.  Adjusts the vn_reference_t VR_
+    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;
+   hashval_t hash;
+ 
+   /* Fixup vuse and hash.  */
+   vr->hashcode = vr->hashcode - iterative_hash_expr (vr->vuse, 0);
+   vr->vuse = SSA_VAL (vuse);
+   vr->hashcode = vr->hashcode + iterative_hash_expr (vr->vuse, 0);
+ 
+   hash = vr->hashcode;
+   slot = htab_find_slot_with_hash (current_info->references, vr,
+ 				   hash, NO_INSERT);
+   if (!slot && current_info == optimistic_info)
+     slot = htab_find_slot_with_hash (valid_info->references, vr,
+ 				     hash, NO_INSERT);
+   if (slot)
+     return *slot;
+   
+   return NULL;
+ }
  
  /* Lookup a reference operation by it's parts, in the current hash table.
     Returns the resulting value number if it exists in the hash table,
*************** vn_reference_lookup_pieces (tree vuse,
*** 858,889 ****
  {
    struct vn_reference_s vr1;
    tree result;
    if (vnresult)
      *vnresult = NULL;
    
!   vr1.vuse = SSA_VAL (vuse);
    vr1.operands = valueize_refs (operands);
    vr1.hashcode = vn_reference_compute_hash (&vr1);
    result = vn_reference_lookup_1 (&vr1, vnresult);
  
-   /* If there is a single defining statement for all virtual uses, we can
-      use that, following virtual use-def chains.  */
    if (!result
        && maywalk
        && vr1.vuse)
      {
        tree ref = get_ref_from_reference_ops (operands);
!       gimple def_stmt;
!       if (ref
! 	  && (def_stmt = get_def_ref_stmt_vuse (ref, vr1.vuse))
! 	  && is_gimple_assign (def_stmt))
! 	{
! 	  /* We are now at an aliasing definition for the vuse we want to
! 	     look up.  Re-do the lookup with the vdef for this stmt.  */
! 	  vr1.vuse = SSA_VAL (gimple_vdef (def_stmt));
! 	  vr1.hashcode = vn_reference_compute_hash (&vr1);
! 	  result = vn_reference_lookup_1 (&vr1, vnresult);
  	}
      }
  
    return result;
--- 859,892 ----
  {
    struct vn_reference_s vr1;
    tree result;
+ 
    if (vnresult)
      *vnresult = NULL;
    
!   vr1.vuse = vuse ? SSA_VAL (vuse) : NULL_TREE;
    vr1.operands = valueize_refs (operands);
    vr1.hashcode = vn_reference_compute_hash (&vr1);
    result = vn_reference_lookup_1 (&vr1, vnresult);
  
    if (!result
        && maywalk
        && vr1.vuse)
      {
+       vn_reference_t wvnresult;
        tree ref = get_ref_from_reference_ops (operands);
!       if (!ref)
! 	return NULL_TREE;
!       wvnresult =
! 	(vn_reference_t)walk_non_aliased_vuses (ref, vr1.vuse,
! 						vn_reference_lookup_2, &vr1);
!       if (wvnresult)
! 	{
! 	  if (vnresult)
! 	    *vnresult = wvnresult;
! 	  return wvnresult->result;
  	}
+ 
+       return NULL_TREE;
      }
  
    return result;
*************** vn_reference_lookup (tree op, tree vuse,
*** 900,931 ****
  		     vn_reference_t *vnresult)
  {
    struct vn_reference_s vr1;
!   tree result;
!   gimple def_stmt;
    if (vnresult)
      *vnresult = NULL;
  
!   vr1.vuse = SSA_VAL (vuse);
    vr1.operands = valueize_refs (shared_reference_ops_from_ref (op));
    vr1.hashcode = vn_reference_compute_hash (&vr1);
-   result = vn_reference_lookup_1 (&vr1, vnresult);
  
!   /* If there is a single defining statement for all virtual uses, we can
!      use that, following virtual use-def chains.  */
!   if (!result
!       && maywalk
!       && vr1.vuse
!       && (def_stmt = get_def_ref_stmt_vuse (op, vr1.vuse))
!       && is_gimple_assign (def_stmt))
!     {
!       /* We are now at an aliasing definition for the vuse we want to
! 	 look up.  Re-do the lookup with the vdef for this stmt.  */
!       vr1.vuse = SSA_VAL (gimple_vdef (def_stmt));
!       vr1.hashcode = vn_reference_compute_hash (&vr1);
!       result = vn_reference_lookup_1 (&vr1, vnresult);
      }
  
!   return result;
  }
  
  
--- 903,934 ----
  		     vn_reference_t *vnresult)
  {
    struct vn_reference_s vr1;
! 
    if (vnresult)
      *vnresult = NULL;
  
!   vr1.vuse = vuse ? SSA_VAL (vuse) : NULL_TREE;
    vr1.operands = valueize_refs (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, &vr1);
!       if (wvnresult)
! 	{
! 	  if (vnresult)
! 	    *vnresult = wvnresult;
! 	  return wvnresult->result;
! 	}
! 
!       return NULL_TREE;
      }
  
!   return vn_reference_lookup_1 (&vr1, vnresult);
  }
  
  
*************** vn_reference_insert (tree op, tree resul
*** 943,949 ****
      vr1->value_id = VN_INFO (result)->value_id;
    else
      vr1->value_id = get_or_alloc_constant_value_id (result);
!   vr1->vuse = SSA_VAL (vuse);
    vr1->operands = valueize_refs (create_reference_ops_from_ref (op));
    vr1->hashcode = vn_reference_compute_hash (vr1);
    vr1->result = TREE_CODE (result) == SSA_NAME ? SSA_VAL (result) : result;
--- 946,952 ----
      vr1->value_id = VN_INFO (result)->value_id;
    else
      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->hashcode = vn_reference_compute_hash (vr1);
    vr1->result = TREE_CODE (result) == SSA_NAME ? SSA_VAL (result) : result;
*************** vn_reference_insert_pieces (tree vuse,
*** 981,988 ****
    vn_reference_t vr1;
  
    vr1 = (vn_reference_t) pool_alloc (current_info->references_pool);
!   vr1->value_id =  value_id;
!   vr1->vuse = SSA_VAL (vuse);
    vr1->operands = valueize_refs (operands);
    vr1->hashcode = vn_reference_compute_hash (vr1);
    if (result && TREE_CODE (result) == SSA_NAME)
--- 984,991 ----
    vn_reference_t vr1;
  
    vr1 = (vn_reference_t) pool_alloc (current_info->references_pool);
!   vr1->value_id = value_id;
!   vr1->vuse = vuse ? SSA_VAL (vuse) : NULL_TREE;
    vr1->operands = valueize_refs (operands);
    vr1->hashcode = vn_reference_compute_hash (vr1);
    if (result && TREE_CODE (result) == SSA_NAME)
*************** visit_reference_op_call (tree lhs, gimpl
*** 1575,1582 ****
    bool changed = false;
    struct vn_reference_s vr1;
    tree result;
  
!   vr1.vuse = SSA_VAL (gimple_vuse (stmt));
    vr1.operands = valueize_refs (shared_reference_ops_from_call (stmt));
    vr1.hashcode = vn_reference_compute_hash (&vr1);
    result = vn_reference_lookup_1 (&vr1, NULL);
--- 1578,1586 ----
    bool changed = false;
    struct vn_reference_s vr1;
    tree result;
+   tree vuse = gimple_vuse (stmt);
  
!   vr1.vuse = vuse ? SSA_VAL (vuse) : NULL_TREE;
    vr1.operands = valueize_refs (shared_reference_ops_from_call (stmt));
    vr1.hashcode = vn_reference_compute_hash (&vr1);
    result = vn_reference_lookup_1 (&vr1, NULL);
*************** visit_reference_op_call (tree lhs, gimpl
*** 1593,1599 ****
        vn_reference_t vr2;
        changed = set_ssa_val_to (lhs, lhs);
        vr2 = (vn_reference_t) pool_alloc (current_info->references_pool);
!       vr2->vuse = SSA_VAL (gimple_vuse (stmt));
        vr2->operands = valueize_refs (create_reference_ops_from_call (stmt));
        vr2->hashcode = vr1.hashcode;
        vr2->result = lhs;
--- 1597,1603 ----
        vn_reference_t vr2;
        changed = set_ssa_val_to (lhs, lhs);
        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->hashcode = vr1.hashcode;
        vr2->result = lhs;
Index: gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-18.c
===================================================================
*** /dev/null	1970-01-01 00:00:00.000000000 +0000
--- gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-18.c	2008-12-10 16:06:54.000000000 +0100
***************
*** 0 ****
--- 1,28 ----
+ /* { dg-do compile } */
+ /* { dg-options "-O -fdump-tree-fre" } */
+ 
+ struct a
+ {
+   union
+   {
+     int a;
+     int b;
+   };
+   union
+   {
+     int c;
+     int d;
+   };
+ };
+ 
+ int f(struct a *c)
+ {
+   int d = c->a;
+   c->c = 1;
+   return c->a + d;
+ }
+ 
+ /* We should have CSEd the load from c->a.  */
+ 
+ /* { dg-final { scan-tree-dump-times "c_.*\\\.a" 1 "fre" } } */
+ /* { dg-final { cleanup-tree-dump "fre" } } */
Index: gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-19.c
===================================================================
*** /dev/null	1970-01-01 00:00:00.000000000 +0000
--- gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-19.c	2008-12-10 16:06:54.000000000 +0100
***************
*** 0 ****
--- 1,31 ----
+ /* { dg-do compile } */
+ /* { dg-options "-O -fdump-tree-fre" } */
+ 
+ struct a
+ {
+   union
+   {
+     int a;
+     int b;
+   };
+   union
+   {
+     int c;
+     int d;
+   };
+   int e;
+ };
+ 
+ int f(struct a *c)
+ {
+   int d;
+   c->e = 2;
+   d = c->a;
+   c->c = 1;
+   return c->a + d;
+ }
+ 
+ /* We should have CSEd the load from c->a.  */
+ 
+ /* { dg-final { scan-tree-dump-times "c_.*\\\.a" 1 "fre" } } */
+ /* { dg-final { cleanup-tree-dump "fre" } } */
Index: gcc/testsuite/gcc.dg/tree-ssa/ssa-lim-3.c
===================================================================
*** gcc/testsuite/gcc.dg/tree-ssa/ssa-lim-3.c.orig	2008-12-10 16:00:59.000000000 +0100
--- gcc/testsuite/gcc.dg/tree-ssa/ssa-lim-3.c	2008-12-10 16:06:54.000000000 +0100
***************
*** 1,5 ****
  /* { dg-do compile } */
! /* { dg-options "-O2 -fdump-tree-lim-details" } */
  
  struct { int x; int y; } global;
  void foo(int n)
--- 1,5 ----
  /* { dg-do compile } */
! /* { dg-options "-O -fdump-tree-lim-details" } */
  
  struct { int x; int y; } global;
  void foo(int n)
Index: gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-23.c
===================================================================
*** /dev/null	1970-01-01 00:00:00.000000000 +0000
--- gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-23.c	2008-12-10 16:06:54.000000000 +0100
***************
*** 0 ****
--- 1,13 ----
+ /* { dg-do compile } */
+ /* { dg-options "-O2 -fdump-tree-pre-stats" } */
+ 
+ struct { int x; int y; } global;
+ void foo(int n)
+ {
+   int i;
+   for ( i=0; i<n; i++)
+     global.y += global.x*global.x;
+ }
+ 
+ /* { dg-final { scan-tree-dump "Eliminated: 2" "pre" } } */
+ /* { dg-final { cleanup-tree-dump "pre" } } */
Index: gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-24.c
===================================================================
*** /dev/null	1970-01-01 00:00:00.000000000 +0000
--- gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-24.c	2008-12-10 16:06:54.000000000 +0100
***************
*** 0 ****
--- 1,15 ----
+ /* { dg-do compile } */
+ /* { dg-options "-O2 -fdump-tree-pre" } */
+ 
+ void foo(int *p, double *x, int n)
+ {
+   int i;
+   for (i = 0; i < n; ++i)
+     *(x + *p * i) = 0.0;
+ }
+ 
+ /* We should remove the unnecessary insertion of a phi-node and
+    _not_ end up using the phi result for replacement *p.  */
+ 
+ /* { dg-final { scan-tree-dump-not "prephitmp" "pre" } } */
+ /* { dg-final { cleanup-tree-dump "pre" } } */


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