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]

Re: [PATCH] Fix PR32921, prune virtual operands of memory accesses based on TBAA


On Mon, 22 Oct 2007, Daniel Berlin wrote:

> On 10/22/07, Diego Novillo <dnovillo@google.com> wrote:
> > Daniel Berlin wrote:
> >
> > > We in fact, do this :)
> > >
> > > This is one of the things that we do when filling in the points-to
> > > bitmaps in find_what_p_points_to.
> >
> > So, this patch makes even less sense to me now.  What is really going on
> > that Richard's patch has any effect at all?  It seems to me that it
> > shouldn't.  I'm really confused about the whole thing.
> 
> I await Richard finding out :)

The patch below works now.  But I now see PRE doing appearantly new
(or different) optimization and ICE during value-numbering of inserted
storetmps (that have VOPs that are not renamed yet), so for example
g++.dg/opt/unroll1.C ICEs with

g++.dg/opt/unroll1.C: In function 'int main()':
g++.dg/opt/unroll1.C:411: internal compiler error: tree check: expected 
ssa_name, have symbol_memory_tag in VN_INFO, at tree-ssa-sccvn.c:253
Please submit a full bug report,
with preprocessed source if appropriate.
See <http://gcc.gnu.org/bugs.html> for instructions.

where the stmt it looks at during this value-numbering is

# VUSE <SMT.75> { SMT.75 }
storetmp.83_166 = *pt_211

For the same reason 22 libstd++v3 tests fail.

The tree-flow-inline.h patch is necessary to not make the vectorizer
fall over the case I mentioned earlier.  (And I think this change may
be useful on its own, to reduce the amount of appearantly useless SFTs
we create).

Not that I expect this patch does too much useful prunings anymore,
but unless I find a way around the PRE/VN issue performance-testing
this won't take me too far.

Richard.


2007-10-19  Richard Guenther  <rguenther@suse.de>

	PR middle-end/32921
	* tree-ssa-operands.c (access_can_touch_variable): Aliases
	with non-conflicting alias sets with the reference do not
	touch the access.  Re-structure function a bit.
	* tree-flow-inline.h (var_can_have_subvars): Unions cannot
	have subvars.

Index: tree-flow-inline.h
===================================================================
*** tree-flow-inline.h	(revision 129483)
--- tree-flow-inline.h	(working copy)
*************** var_can_have_subvars (const_tree v)
*** 1634,1640 ****
      return false;
  
    /* Aggregates can have subvars.  */
!   if (AGGREGATE_TYPE_P (TREE_TYPE (v)))
      return true;
  
    /* Complex types variables which are not also a gimple register can
--- 1634,1642 ----
      return false;
  
    /* Aggregates can have subvars.  */
!   if (AGGREGATE_TYPE_P (TREE_TYPE (v))
!       && TREE_CODE (TREE_TYPE (v)) != UNION_TYPE
!       && TREE_CODE (TREE_TYPE (v)) != QUAL_UNION_TYPE)
      return true;
  
    /* Complex types variables which are not also a gimple register can
Index: tree-ssa-operands.c
===================================================================
*** tree-ssa-operands.c	(revision 129547)
--- tree-ssa-operands.c	(working copy)
*************** append_vuse (tree var)
*** 1189,1204 ****
     expression, if available, or NULL otherwise.  ALIAS is the variable
     we are asking if REF can access.  OFFSET and SIZE come from the
     memory access expression that generated this virtual operand.
  
     XXX: We should handle the NO_ALIAS attributes here.  */
  
  static bool
  access_can_touch_variable (tree ref, tree alias, HOST_WIDE_INT offset,
! 			   HOST_WIDE_INT size)
  {
    bool offsetgtz = offset > 0;
    unsigned HOST_WIDE_INT uoffset = (unsigned HOST_WIDE_INT) offset;
!   tree base = ref ? get_base_address (ref) : NULL;
  
    /* If ALIAS is .GLOBAL_VAR then the memory reference REF must be
       using a call-clobbered memory tag.  By definition, call-clobbered
--- 1189,1209 ----
     expression, if available, or NULL otherwise.  ALIAS is the variable
     we are asking if REF can access.  OFFSET and SIZE come from the
     memory access expression that generated this virtual operand.
+    IS_WRITE should be true if the access is a store, otherwise false.
  
     XXX: We should handle the NO_ALIAS attributes here.  */
  
  static bool
  access_can_touch_variable (tree ref, tree alias, HOST_WIDE_INT offset,
! 			   HOST_WIDE_INT size, bool is_write)
  {
    bool offsetgtz = offset > 0;
    unsigned HOST_WIDE_INT uoffset = (unsigned HOST_WIDE_INT) offset;
!   tree base, base_var;
! 
!   /* For NULL refs we cannot prune based on the unknown access.  */
!   if (!ref)
!     return true;
  
    /* If ALIAS is .GLOBAL_VAR then the memory reference REF must be
       using a call-clobbered memory tag.  By definition, call-clobbered
*************** access_can_touch_variable (tree ref, tre
*** 1206,1216 ****
    if (alias == gimple_global_var (cfun))
      return true;
  
    /* If ref is a TARGET_MEM_REF, just return true, as we can't really
!      disambiguate them right now.  */
!   if (ref && TREE_CODE (ref) == TARGET_MEM_REF)
      return true;
!   
    /* If ALIAS is an SFT, it can't be touched if the offset     
       and size of the access is not overlapping with the SFT offset and
       size.  This is only true if we are accessing through a pointer
--- 1211,1245 ----
    if (alias == gimple_global_var (cfun))
      return true;
  
+   base = get_base_address (ref);
+   if (base
+       && INDIRECT_REF_P (base))
+     base_var = SSA_NAME_VAR (TREE_OPERAND (base, 0));
+   else
+     base_var = NULL_TREE;
+ 
+   /* If the alias sets of the alias and the ref do not conflict then
+      then the access does not touch the alias.  This is pruning based
+      on TBAA.  */
+   if (flag_strict_aliasing
+       /* Memory partitions represent multiple types and need different
+ 	 treatment for TBAA pruning.  */
+       && TREE_CODE (alias) != MEMORY_PARTITION_TAG
+       /* We cannot prune symbol memory tags for stores as this breaks
+ 	 CHANGE_DYNAMIC_TYPE_EXPR handling.  Unless the base access
+ 	 is not marked with DECL_NO_TBAA_P.  */
+       && (!base_var || !DECL_NO_TBAA_P (base_var) || !is_write)
+       /* HEAP variables do not have types that are meaningful for TBAA.  */
+       && !var_ann (alias)->is_heapvar
+       && !alias_sets_conflict_p (get_alias_set (alias),
+ 				 get_alias_set (ref)))
+     return false;
+ 
    /* If ref is a TARGET_MEM_REF, just return true, as we can't really
!      disambiguate them based on offsets right now.  */
!   if (TREE_CODE (ref) == TARGET_MEM_REF)
      return true;
!  
    /* If ALIAS is an SFT, it can't be touched if the offset     
       and size of the access is not overlapping with the SFT offset and
       size.  This is only true if we are accessing through a pointer
*************** access_can_touch_variable (tree ref, tre
*** 1309,1316 ****
       my_char_ref_1 = (char[1:1] &) &my_char;
       D.874_2 = (*my_char_ref_1)[1]{lb: 1 sz: 1};
    */
!   else if (ref 
! 	   && flag_strict_aliasing
  	   && TREE_CODE (ref) != INDIRECT_REF
  	   && !MTAG_P (alias)
  	   && base
--- 1338,1344 ----
       my_char_ref_1 = (char[1:1] &) &my_char;
       D.874_2 = (*my_char_ref_1)[1]{lb: 1 sz: 1};
    */
!   else if (flag_strict_aliasing
  	   && TREE_CODE (ref) != INDIRECT_REF
  	   && !MTAG_P (alias)
  	   && base
*************** access_can_touch_variable (tree ref, tre
*** 1344,1351 ****
    /* If the offset of the access is greater than the size of one of
       the possible aliases, it can't be touching that alias, because it
       would be past the end of the structure.  */
!   else if (ref
! 	   && flag_strict_aliasing
  	   && TREE_CODE (ref) != INDIRECT_REF
  	   && !MTAG_P (alias)
  	   && !POINTER_TYPE_P (TREE_TYPE (alias))
--- 1372,1378 ----
    /* If the offset of the access is greater than the size of one of
       the possible aliases, it can't be touching that alias, because it
       would be past the end of the structure.  */
!   else if (flag_strict_aliasing
  	   && TREE_CODE (ref) != INDIRECT_REF
  	   && !MTAG_P (alias)
  	   && !POINTER_TYPE_P (TREE_TYPE (alias))
*************** add_vars_for_offset (tree full_ref, tree
*** 1408,1414 ****
        || (TREE_CODE (var) != STRUCT_FIELD_TAG
  	  && (!var_can_have_subvars (var) || !get_subvars_for_var (var))))
      {
!       if (!access_can_touch_variable (full_ref, var, offset, size))
  	return false;
  
        if (is_def)
--- 1435,1441 ----
        || (TREE_CODE (var) != STRUCT_FIELD_TAG
  	  && (!var_can_have_subvars (var) || !get_subvars_for_var (var))))
      {
!       if (!access_can_touch_variable (full_ref, var, offset, size, is_def))
  	return false;
  
        if (is_def)
*************** add_vars_for_offset (tree full_ref, tree
*** 1428,1434 ****
  	      if (overlap_subvar (SFT_OFFSET (var) + offset, size,
  				  sv->var, NULL)
  		  && access_can_touch_variable (full_ref, sv->var,
! 						offset, size))
  		{
  		  added = true;
  		  if (is_def)
--- 1455,1461 ----
  	      if (overlap_subvar (SFT_OFFSET (var) + offset, size,
  				  sv->var, NULL)
  		  && access_can_touch_variable (full_ref, sv->var,
! 						offset, size, is_def))
  		{
  		  added = true;
  		  if (is_def)
*************** add_vars_for_offset (tree full_ref, tree
*** 1452,1458 ****
  	      if (overlap_subvar (SFT_OFFSET (var) + offset, size,
  				  sv->var, NULL)
  		  && access_can_touch_variable (full_ref, sv->var, offset, 
! 						size))
  		{
  		  added = true;
  		  if (is_def)
--- 1479,1485 ----
  	      if (overlap_subvar (SFT_OFFSET (var) + offset, size,
  				  sv->var, NULL)
  		  && access_can_touch_variable (full_ref, sv->var, offset, 
! 						size, is_def))
  		{
  		  added = true;
  		  if (is_def)


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