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

Richard Guenther rguenther@suse.de
Thu Oct 18 16:18:00 GMT 2007


On Thu, 18 Oct 2007, Richard Guenther wrote:

> 
> Now, I was totally suprised to see that while we prune virtual operands
> (in the case of PR32921 a bunch of SFTs) based on the offset of the access
> but not based on TBAA.  Duh.  Fixed with the following patch that will
> do so for all alias symbols (apart from MPTs, those would need more
> special treatment).  I also took the liberty to re-shuffle things a bit
> in access_can_touch_variable.
> 
> Maybe I'm missing something obvious here, but a slightly less invasive
> patch (just pruning SFTs) bootstrapped & tested fine.
> 
> This patch is currently bootstrapping and testing on 
> x86_64-unknown-linux-gnu for all languages including Ada.
> 
> Danny?  Am I just crazy this day?

Of course things are never that easy.  As for now we only miscompiled
the fortran frontend I at least found a new alias stressing testcase ;)
(HEAP variables do not have a type meaningful for TBAA)

I expect maybe similar fallout for NMTs, but I'm sure SMTs and SFTs
are correct in this respect.

So the following is bootstrapping & testing now.

Richard.

2007-10-18  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.

	* gfortran.dg/pr32921.f: New testcase.
	* gcc.c-torture/execute/20071018-1.c: Likewise.

Index: testsuite/gfortran.dg/pr32921.f
===================================================================
--- testsuite/gfortran.dg/pr32921.f	(revision 0)
+++ testsuite/gfortran.dg/pr32921.f	(revision 0)
@@ -0,0 +1,49 @@
+! { dg-do compile }
+! { dg-options "-O2 -fdump-tree-lim" }
+! gfortran -c -m32 -O2 -S junk.f
+!
+      MODULE LES3D_DATA
+
+      IMPLICIT REAL*8 (A-H,O-Z)
+
+      PARAMETER ( NSPECI = 1, ND = 7 + NSPECI )
+
+      INTEGER IMAX
+
+      DOUBLE PRECISION,ALLOCATABLE,DIMENSION(:,:,:) ::
+     >         UAV,QAV
+
+
+      END MODULE LES3D_DATA
+!---------------------------------------------------------------------
+!------------------------------------------------------------------------
+      SUBROUTINE FLUXI()
+
+      USE LES3D_DATA
+      IMPLICIT REAL*8(A-H,O-Z)
+
+      ALLOCATABLE QS(:)
+
+      ALLOCATE( QS(0:IMAX))
+      QS=0D0
+
+      RETURN
+      END
+!------------------------------------------------------------------------
+!------------------------------------------------------------------------
+      SUBROUTINE EXTRAPI()
+
+      USE LES3D_DATA
+      IMPLICIT REAL*8(A-H,O-Z)
+
+      I1 = 0
+      I2 = IMAX - 1
+
+            DO I = I1, I2
+               UAV(I,1,2) = QAV(I,1,2)
+            END DO
+
+      RETURN
+      END
+! { dg-final { scan-tree-dump-times "stride" 6 "lim" } }
+! { dg-final { cleanup-tree-dump "lim" } }
Index: tree-ssa-operands.c
===================================================================
*** tree-ssa-operands.c	(revision 129439)
--- tree-ssa-operands.c	(working copy)
*************** access_can_touch_variable (tree ref, tre
*** 1198,1204 ****
  {
    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
--- 1198,1208 ----
  {
    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
--- 1210,1247 ----
    if (alias == gimple_global_var (cfun))
      return true;
  
+   /* If the alias sets of the single primitive type in an alias does
+      not conflict with that of the memory reference then the access does
+      not touch the alias.  Both MPTs and HEAP vars we cannot handle here.  */
+   if (flag_strict_aliasing
+       && TREE_CODE (alias) != MEMORY_PARTITION_TAG
+       && !var_ann (alias)->is_heapvar
+       && !AGGREGATE_TYPE_P (TREE_TYPE (ref))
+       && !AGGREGATE_TYPE_P (TREE_TYPE (alias)))
+     {
+       tree alias_type = TREE_TYPE (alias);
+       tree ref_type = TREE_TYPE (ref);
+ 
+       if (TREE_CODE (alias_type) == COMPLEX_TYPE
+ 	  || TREE_CODE (alias_type) == VECTOR_TYPE)
+ 	alias_type = TREE_TYPE (alias_type);
+ 
+       if (TREE_CODE (ref_type) == COMPLEX_TYPE
+ 	  || TREE_CODE (ref_type) == VECTOR_TYPE)
+ 	ref_type = TREE_TYPE (ref_type);
+ 
+       if (!alias_sets_conflict_p (get_alias_set (alias_type),
+ 				  get_alias_set (ref_type)))
+ 	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;
!  
!   base = get_base_address (ref);
! 
    /* 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
--- 1340,1346 ----
       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))
--- 1374,1380 ----
    /* 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))
Index: testsuite/gcc.c-torture/execute/20071018-1.c
===================================================================
*** testsuite/gcc.c-torture/execute/20071018-1.c	(revision 0)
--- testsuite/gcc.c-torture/execute/20071018-1.c	(revision 0)
***************
*** 0 ****
--- 1,31 ----
+ extern void abort(void);
+ 
+ struct foo {
+   int rank;
+   char *name;
+ };
+ 
+ struct mem {
+   struct foo *x[4];
+ };
+ 
+ void __attribute__((noinline)) bar(struct foo **f)
+ {
+   *f = __builtin_malloc(sizeof(struct foo));
+ }
+ struct foo * foo(int rank)
+ {
+   void *x = __builtin_malloc(sizeof(struct mem));
+   struct mem *as = x;
+   struct foo **upper = &as->x[rank * 8 - 1];
+   *upper = 0;
+   bar(upper);
+   return *upper;
+ }
+ 
+ int main()
+ {
+   if (foo(0) == 0)
+     abort ();
+   return 0;
+ }



More information about the Gcc-patches mailing list