On Wed, Nov 6, 2013 at 1:19 PM, Marc Glisse <[email protected]> wrote:
> [Discussion started in
> http://gcc.gnu.org/ml/gcc-patches/2013-10/msg02472.html ]
>
>
> On Wed, 30 Oct 2013, Marc Glisse wrote:
>
>> On Wed, 30 Oct 2013, Richard Biener wrote:
>>
>>> Btw, get_addr_base_and_unit_offset may also return an offsetted
>>> MEM_REF (from &MEM [p_3, 17] for example). As we are interested in
>>> pointers this could be handled by not requiring a memory reference
>>> but extracting the base address and offset, covering more cases.
>>
>>
>> I tried the attached patch, and it almost worked, except for one fortran
>> testcase (widechar_intrinsics_10.f90):
>
>
> Now that ao_ref_init_from_ptr_and_size has been fixed, the following patch
> passes bootstrap+testsuite (default languages) on x86_64-unknown-linux-gnu.
>
> 2013-11-06 Marc Glisse <[email protected]>
> Jeff Law <[email protected]>
>
> gcc/
> * tree-ssa-alias.c (stmt_kills_ref_p_1): Use
> ao_ref_init_from_ptr_and_size for builtins.
>
> gcc/testsuite/
> * gcc.dg/tree-ssa/alias-27.c: New testcase.
>
> --
> Marc Glisse
> Index: gcc/testsuite/gcc.dg/tree-ssa/alias-27.c
> ===================================================================
> --- gcc/testsuite/gcc.dg/tree-ssa/alias-27.c (revision 0)
> +++ gcc/testsuite/gcc.dg/tree-ssa/alias-27.c (working copy)
> @@ -0,0 +1,11 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O1 -fdump-tree-optimized" } */
> +
> +void f (long *p) {
> + *p = 42;
> + p[4] = 42;
> + __builtin_memset (p, 0, 100);
> +}
> +
> +/* { dg-final { scan-tree-dump-not "= 42" "optimized" } } */
> +/* { dg-final { cleanup-tree-dump "optimized" } } */
>
> Property changes on: gcc/testsuite/gcc.dg/tree-ssa/alias-27.c
> ___________________________________________________________________
> Added: svn:keywords
> ## -0,0 +1 ##
> +Author Date Id Revision URL
> \ No newline at end of property
> Added: svn:eol-style
> ## -0,0 +1 ##
> +native
> \ No newline at end of property
> Index: gcc/tree-ssa-alias.c
> ===================================================================
> --- gcc/tree-ssa-alias.c (revision 204453)
> +++ gcc/tree-ssa-alias.c (working copy)
> @@ -2001,23 +2001,24 @@ stmt_may_clobber_ref_p (gimple stmt, tre
> return stmt_may_clobber_ref_p_1 (stmt, &r);
> }
>
> /* If STMT kills the memory reference REF return true, otherwise
> return false. */
>
> static bool
> stmt_kills_ref_p_1 (gimple stmt, ao_ref *ref)
> {
> /* For a must-alias check we need to be able to constrain
> - the access properly. */
> - ao_ref_base (ref);
> - if (ref->max_size == -1)
> + the access properly.
> + FIXME: except for BUILTIN_FREE. */
> + if (!ao_ref_base (ref)
> + || ref->max_size == -1)
> return false;
>
> if (gimple_has_lhs (stmt)
> && TREE_CODE (gimple_get_lhs (stmt)) != SSA_NAME
> /* The assignment is not necessarily carried out if it can throw
> and we can catch it in the current function where we could inspect
> the previous value.
> ??? We only need to care about the RHS throwing. For aggregate
> assignments or similar calls and non-call exceptions the LHS
> might throw as well. */
> @@ -2090,37 +2091,47 @@ stmt_kills_ref_p_1 (gimple stmt, ao_ref
> case BUILT_IN_MEMPCPY:
> case BUILT_IN_MEMMOVE:
> case BUILT_IN_MEMSET:
> case BUILT_IN_MEMCPY_CHK:
> case BUILT_IN_MEMPCPY_CHK:
> case BUILT_IN_MEMMOVE_CHK:
> case BUILT_IN_MEMSET_CHK:
> {
> tree dest = gimple_call_arg (stmt, 0);
> tree len = gimple_call_arg (stmt, 2);
> - tree base = NULL_TREE;
> - HOST_WIDE_INT offset = 0;
> + tree rbase = ref->base;
> + HOST_WIDE_INT roffset = ref->offset;
> if (!host_integerp (len, 0))
> return false;
> - if (TREE_CODE (dest) == ADDR_EXPR)
> - base = get_addr_base_and_unit_offset (TREE_OPERAND (dest,
> 0),
> - &offset);
> - else if (TREE_CODE (dest) == SSA_NAME)
> - base = dest;
> - if (base
> - && base == ao_ref_base (ref))
> + ao_ref dref;
> + ao_ref_init_from_ptr_and_size (&dref, dest, len);
What I dislike about this is that it can end up building a new tree node.
Not sure if that should block the patch though as it clearly allows to
simplify the code ...
> + tree base = ao_ref_base (&dref);
> + HOST_WIDE_INT offset = dref.offset;
> + if (!base || dref.size == -1)
> + return false;
> + if (TREE_CODE (base) == MEM_REF)
> + {
> + if (TREE_CODE (rbase) != MEM_REF)
why's that? I think that just processing both bases separately
would work as well.
> + return false;
> + // Compare pointers.
> + offset += BITS_PER_UNIT
> + * TREE_INT_CST_LOW (TREE_OPERAND (base, 1));
Use mem_ref_offset (base).
> + roffset += BITS_PER_UNIT
> + * TREE_INT_CST_LOW (TREE_OPERAND (rbase, 1));
Likewise.
> + base = TREE_OPERAND (base, 0);
> + rbase = TREE_OPERAND (rbase, 0);
Both could be &decl here, so you want
if (TREE_CODE (base) == ADDR_EXPR)
base = TREE_OPERAND (base, 0);
Thanks,
Richard.
> + }
> + if (base == rbase)
> {
> - HOST_WIDE_INT size = TREE_INT_CST_LOW (len);
> - if (offset <= ref->offset / BITS_PER_UNIT
> - && (offset + size
> - >= ((ref->offset + ref->max_size + BITS_PER_UNIT -
> 1)
> - / BITS_PER_UNIT)))
> + HOST_WIDE_INT size = BITS_PER_UNIT * TREE_INT_CST_LOW
> (len);
> + if (offset <= roffset
> + && offset + size >= (roffset + ref->max_size))
> return true;
> }
> break;
> }
>
> case BUILT_IN_VA_END:
> {
> tree ptr = gimple_call_arg (stmt, 0);
> if (TREE_CODE (ptr) == ADDR_EXPR)
> {
>