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 Fri, 19 Oct 2007, Daniel Berlin wrote:

> On 10/19/07, Richard Guenther <rguenther@suse.de> wrote:
> > On Fri, 19 Oct 2007, Ian Lance Taylor wrote:
> >
> > > Richard Guenther <rguenther@suse.de> writes:
> > >
> > > > But then the killer issue comes along.  The way we designed
> > > > CHANGE_DYNAMIC_TYPE_EXPR makes it impossible to do TBAA pruning on
> > > > memory accesses.  For g++.dg/init/new16.C we have
> > > >
> > > >     int *l = (int *)p;
> > > >     *l = 0;
> > > >     f = new (p) long;
> > > >     *f = -1;
> > > >
> > > >   l_7 = (int *) p_6(D);
> > > >   *l_7 ={v} 0;
> > > >   <<<change_dynamic_type (long int *) p_6(D))>>>
> > > >   D.2035_15 = p_6(D);
> > > >   f_10 = (long int *) D.2035_15;
> > > >   *f_10 ={v} -1;
> > > >
> > > > but we do not have a connection of the CHANGE_DYNAMIC_TYPE_EXPR to
> > > > the memory reference site.  So we happily prune SMT.17 from f_10s
> > > > alias set.
> > > >
> > > >   l_7 = (int *) p_6(D);
> > > >   # SMT.17_20 = VDEF <SMT.17_17>
> > > >   *l_7 = 0;
> > > >   D.2035_15 = p_6(D);
> > > >   f_10 = (long int *) D.2035_15;
> > > >   # SMT.16_21 = VDEF <SMT.16_16>
> > > >   *f_10 = -1;
> > > >
> > > > Because out IL doesn't really tell the truth.  Which even makes me
> > > > uncomfortable to just enable TBAA pruning for SFTs and bare DECLs.
> > > > But I guess that should work.
> > >
> > > The connection we need is supposed to be built by
> > > compute_tbaa_pruning--specifically, it should mark the reference with
> > > no_tbaa_pruning.  Why isn't that working for you?
> >
> > Because I didn't know of it.  But it also looks like it is local
> > to tree-ssa-structalias.c and not available at operand scanning time
> > (where we call access_can_touch_variable).
> 
> This was a mistake. Move it to var_ann.

It looks like we have the global DECL_NO_TBAA_P.  This works for new16.C
if I do:

  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)

we then get

  l_7 = (int *) p_6(D);
  # SMT.17_20 = VDEF <SMT.17_17>
  *l_7 = 0;
  D.2035_15 = p_6(D);
  f_10 = (long int *) D.2035_15;
  # SMT.16_21 = VDEF <SMT.16_16>
  # SMT.17_22 = VDEF <SMT.17_20>
  *f_10 = -1; 
...
  # VUSE <SMT.16_16>
  D.2036_12 = *f_1;
  return D.2036_12;

so we prune on the read, which is allowed.

> > But maybe Danny didn't look
> > closely enough at my patch and access_can_touch_variable is the compeltely
> > wrong place to do TBAA pruning.
> 
> It's a fine place but i wouldn't try *too* hard.
> At some point we just need to start moving our optimizers to the model
> of using memory dependence analysis, and using the memory def-use
> chains as a starting point, not the end-all be-all of aliasing.
> 
> I'm happy to try to get as much as we can out of vdef/vuse directly,
> but there is some limit to precision you will hit where anything more
> will explode time and memory, and we are fairly close to that limit
> already.

Well, pruning virtual operands _saves_ memory ;)  (Which is why I also
look at not generating subvariables for unions - we don't seem to make
use of them in optimizers and they certainly consume memory)

So, the following is the current state of the patch.  It still breaks
the hell out of Ada - I suppose I need to check TYPE_REF_CAN_ALIAS_ALL
on the pointers the same as DECL_NO_TBAA_P maybe, though I thought this
might be taken care by get_alias_set ().

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 129490)
--- 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,1249 ----
    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
+       /* If the inner reference has alias set zero, we cannot use the
+ 	 type of the access for TBAA purposes.  This happens with
+ 	 the use of attribute may_alias.  */
+       && (!base || get_alias_set (TREE_TYPE (base)) != 0)
+       && !alias_sets_conflict_p (get_alias_set (TREE_TYPE (alias)),
+ 				 get_alias_set (TREE_TYPE (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
--- 1342,1348 ----
       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))
--- 1376,1382 ----
    /* 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)
--- 1439,1445 ----
        || (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)
--- 1459,1465 ----
  	      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)
--- 1483,1489 ----
  	      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]