On Thu, Nov 23, 2017 at 4:32 PM, Martin Jambor <mjam...@suse.cz> wrote:
> Hi,
>
> On Mon, Nov 13 2017, Richard Biener wrote:
>> The main concern here is that GIMPLE is not very well defined for
>> aggregate copies and that gimple-fold.c happily optimizes
>> memcpy (&a, &b, sizeof (a)) into a = b;
>>
>> struct A { short s; long i; long j; };
>> struct A a, b;
>> void foo ()
>> {
>>   __builtin_memcpy (&a, &b, sizeof (struct A));
>> }
>>
>> gets folded to
>>
>>   MEM[(char * {ref-all})&a] = MEM[(char * {ref-all})&b];
>>   return;
>>
>> you see we're careful about TBAA but (don't see that above but
>> can be verified by for example debugging expand_assignment)
>> TREE_TYPE (MEM[...]) is actually 'struct A'.
>>
>> And yes, I've been worried about SRA as well here...  it _does_
>> have some early outs when seeing VIEW_CONVERT_EXPR but
>> appearantly not for the above.  Testcase that aborts with SRA but
>> not without:
>>
>> struct A { short s; long i; long j; };
>> struct A a, b;
>> void foo ()
>> {
>>   struct A c;
>>   __builtin_memcpy (&c, &b, sizeof (struct A));
>>   __builtin_memcpy (&a, &c, sizeof (struct A));
>> }
>> int main()
>> {
>>   __builtin_memset (&b, 0, sizeof (struct A));
>>   b.s = 1;
>>   __builtin_memcpy ((char *)&b+2, &b, 2);
>>   foo ();
>>   __builtin_memcpy (&a, (char *)&a+2, 2);
>>   if (a.s != 1)
>>     __builtin_abort ();
>>   return 0;
>> }
>
> Thanks for the testcase, I agree that is a fairly big problem.  Do you
> think that the following (untested) patch is an appropriate way of
> fixing it and generally of extending gimple to capture that a statement
> is a bit-copy?

I think the place to fix is the memcpy folding.  That is, we'd say that
aggregate assignments are not bit-copies but do element-wise assignments.
For memcpy folding we'd then need to use a type that doesn't contain
padding.  Which effectively means char[].

Of course we need to stop SRA from decomposing that copy to
individual characters then ;)

So iff we decide that all aggregate copies are element copies,
maybe only those where TYPE_MAIN_VARIANT of lhs and rhs match
(currently we allow TYPE_CANONICAL compatibility and thus there
might be some mismatches), then we have to fix nothign but
the memcpy folding.

> If so, I'll add the testcase, bootstrap it and formally propose it.
> Subsequently I will of course make sure that any element-wise copying
> patch would test the predicate.

I don't think the alias-set should determine whether a copy is
bit-wise or not.

Richard.

> Thanks,
>
> Martin
>
>
> 2017-11-23  Martin Jambor  <mjam...@suse.cz>
>
>         * gimple.c (gimple_bit_copy_p): New function.
>         * gimple.h (gimple_bit_copy_p): Declare it.
>         * tree-sra.c (sra_modify_assign): Use it.
> ---
>  gcc/gimple.c   | 20 ++++++++++++++++++++
>  gcc/gimple.h   |  1 +
>  gcc/tree-sra.c |  1 +
>  3 files changed, 22 insertions(+)
>
> diff --git a/gcc/gimple.c b/gcc/gimple.c
> index c986a732004..e1b428d91bb 100644
> --- a/gcc/gimple.c
> +++ b/gcc/gimple.c
> @@ -3087,6 +3087,26 @@ gimple_inexpensive_call_p (gcall *stmt)
>    return false;
>  }
>
> +/* Return true if STMT is an assignment performing bit copy and so is also
> +   expected to copy any padding.  */
> +
> +bool
> +gimple_bit_copy_p (gassign *stmt)
> +{
> +  if (!gimple_assign_single_p (stmt))
> +    return false;
> +
> +  tree lhs = gimple_assign_lhs (stmt);
> +  if (TREE_CODE (lhs) == MEM_REF
> +      && TYPE_REF_CAN_ALIAS_ALL (reference_alias_ptr_type (lhs)))
> +    return true;
> +  tree rhs = gimple_assign_rhs1 (stmt);
> +  if (TREE_CODE (rhs) == MEM_REF
> +      && TYPE_REF_CAN_ALIAS_ALL (reference_alias_ptr_type (rhs)))
> +    return true;
> +  return false;
> +}
> +
>  #if CHECKING_P
>
>  namespace selftest {
> diff --git a/gcc/gimple.h b/gcc/gimple.h
> index 334def89398..60929473361 100644
> --- a/gcc/gimple.h
> +++ b/gcc/gimple.h
> @@ -1531,6 +1531,7 @@ extern void gimple_seq_discard (gimple_seq);
>  extern void maybe_remove_unused_call_args (struct function *, gimple *);
>  extern bool gimple_inexpensive_call_p (gcall *);
>  extern bool stmt_can_terminate_bb_p (gimple *);
> +extern bool gimple_bit_copy_p (gassign *);
>
>  /* Formal (expression) temporary table handling: multiple occurrences of
>     the same scalar expression are evaluated into the same temporary.  */
> diff --git a/gcc/tree-sra.c b/gcc/tree-sra.c
> index db490b20c3e..fc0a8fe60bf 100644
> --- a/gcc/tree-sra.c
> +++ b/gcc/tree-sra.c
> @@ -3591,6 +3591,7 @@ sra_modify_assign (gimple *stmt, gimple_stmt_iterator 
> *gsi)
>        || gimple_has_volatile_ops (stmt)
>        || contains_vce_or_bfcref_p (rhs)
>        || contains_vce_or_bfcref_p (lhs)
> +      || gimple_bit_copy_p (as_a <gassign *> (stmt))
>        || stmt_ends_bb_p (stmt))
>      {
>        /* No need to copy into a constant-pool, it comes pre-initialized.  */
> --
> 2.15.0
>

Reply via email to