This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [PATCH] Fix PR32921, prune virtual operands of memory accesses based on TBAA
On 10/18/07, Richard Guenther <rguenther@suse.de> wrote:
> 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.
This looks fine to me.
Yes, HEAP vars have no real type, and can't be pruned.
NMT's should always be the correct type.
>
> 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;
> + }
>