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


I have fixed most of the issues that came up sofar (And for PR32921
I committed a different fix).  Now if we still want to do TBAA pruning
at access sites then there is one issue left that I don't see where
to fix this best.  With the patch below we ICE in i386 specific
vectorization testcases, for example gcc.target/i386/pr33524.c:

pr33524.c:18: error: missing definition
for SSA_NAME: SFT.2_18 in statement:
SFT.2_26 = PHI <SFT.2_18(4), SFT.2_12(D)(2)>
PHI argument
SFT.2_18
for PHI node
SFT.2_26 = PHI <SFT.2_18(4), SFT.2_12(D)(2)>

because the vectorizer replaces a memory access that happens through
a union

typedef long long __m128i  __attribute__ ((__vector_size__ (16), 
__may_alias__));

#define SIZE 10240
union {
  signed   int   si[SIZE];
  signed   long  sl[SIZE];
  __m128i        align;
} a, b;


  # SFT.1_17 = VDEF <SFT.1_25>
  # SFT.2_18 = VDEF <SFT.2_26>
  # SFT.3_19 = VDEF <SFT.3_27>
  a.sl[i_24] = D.1799_6;

with two stores that happen through pointer types

  # SFT.1_36 = VDEF <SFT.1_25>
  # SFT.3_37 = VDEF <SFT.3_27>
  *ivtmp.34_31 = vect_var_.27_20;
  # SFT.1_38 = VDEF <SFT.1_36>
  # SFT.3_39 = VDEF <SFT.3_37>
  *ivtmp.34_33 = vect_var_.27_28; 

where we can prune the virtual operands for the integer array.
But nobody removes the now dead PHI node for the virtual operand SFT.2.

Of course I believe we didn't create SFTs for union members at some point?
Which is what the hunk to tree-flow-inline.h would restore.

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-ssa-operands.c
===================================================================
*** tree-ssa-operands.c	(revision 129483)
--- 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;
! 
!   /* 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,1243 ----
    if (alias == gimple_global_var (cfun))
      return true;
  
+   base = get_base_address (ref);
+ 
+   /* 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.  */
+       && (!is_write || TREE_CODE (alias) != SYMBOL_MEMORY_TAG)
+       /* 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
--- 1336,1342 ----
       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))
--- 1370,1376 ----
    /* 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)
--- 1433,1439 ----
        || (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)
--- 1453,1459 ----
  	      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)
--- 1477,1483 ----
  	      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: 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 Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]