Re: [PATCH] handle bzero/bcopy in DSE and aliasing (PR 80933, 80934)

2017-06-16 Thread Martin Sebor

+static bool
+gimple_fold_builtin_bcmp (gimple_stmt_iterator *gsi)
+{

+  /* Transform bcmp (a, b, len) into memcmp (a, b, len).  */
+
+  gimple *stmt = gsi_stmt (*gsi);
+  tree a = gimple_call_arg (stmt, 0);
+  tree b = gimple_call_arg (stmt, 1);
+  tree len = gimple_call_arg (stmt, 2);
+
+  gimple_seq seq = NULL;
+  gimple *repl = gimple_build_call (fn, 3, a, b, len);
+  gimple_seq_add_stmt_without_update (, repl);
+  gsi_replace_with_seq_vops (gsi, seq);

given they have the same prototype you can do like gimple_fold_builtin_stpcpy:

  gimple_call_set_fndecl (stmt, fn);
  fold_stmt (gsi);

That works even with bcopy -> memmove if you swap arguments.

Ok with that changes.


I made these changes along with those mentioned downthread and
committed r249278.

Martin


Re: [PATCH] handle bzero/bcopy in DSE and aliasing (PR 80933, 80934)

2017-06-09 Thread Richard Biener
On Fri, Jun 9, 2017 at 3:04 PM, Jakub Jelinek  wrote:
> On Fri, Jun 09, 2017 at 02:35:45PM +0200, Richard Biener wrote:
>> +static bool
>> +gimple_fold_builtin_bcmp (gimple_stmt_iterator *gsi)
>> +{
>>
>> +  /* Transform bcmp (a, b, len) into memcmp (a, b, len).  */
>> +
>> +  gimple *stmt = gsi_stmt (*gsi);
>> +  tree a = gimple_call_arg (stmt, 0);
>> +  tree b = gimple_call_arg (stmt, 1);
>> +  tree len = gimple_call_arg (stmt, 2);
>> +
>> +  gimple_seq seq = NULL;
>> +  gimple *repl = gimple_build_call (fn, 3, a, b, len);
>> +  gimple_seq_add_stmt_without_update (, repl);
>> +  gsi_replace_with_seq_vops (gsi, seq);
>>
>> given they have the same prototype you can do like 
>> gimple_fold_builtin_stpcpy:
>>
>>   gimple_call_set_fndecl (stmt, fn);
>>   fold_stmt (gsi);
>>
>> That works even with bcopy -> memmove if you swap arguments.
>
> Shouldn't it also update gimple_call_fntype though, at least for memmove?
> Those differ with void const * vs. void * arguments, and also in the return
> value.  At least if the old fntype is compatible with the bcopy call.

Yes.  If the old fntype isn't compatible we don't reach the folding.

Richard.

> Jakub


Re: [PATCH] handle bzero/bcopy in DSE and aliasing (PR 80933, 80934)

2017-06-09 Thread Jakub Jelinek
On Fri, Jun 09, 2017 at 02:35:45PM +0200, Richard Biener wrote:
> +static bool
> +gimple_fold_builtin_bcmp (gimple_stmt_iterator *gsi)
> +{
> 
> +  /* Transform bcmp (a, b, len) into memcmp (a, b, len).  */
> +
> +  gimple *stmt = gsi_stmt (*gsi);
> +  tree a = gimple_call_arg (stmt, 0);
> +  tree b = gimple_call_arg (stmt, 1);
> +  tree len = gimple_call_arg (stmt, 2);
> +
> +  gimple_seq seq = NULL;
> +  gimple *repl = gimple_build_call (fn, 3, a, b, len);
> +  gimple_seq_add_stmt_without_update (, repl);
> +  gsi_replace_with_seq_vops (gsi, seq);
> 
> given they have the same prototype you can do like gimple_fold_builtin_stpcpy:
> 
>   gimple_call_set_fndecl (stmt, fn);
>   fold_stmt (gsi);
> 
> That works even with bcopy -> memmove if you swap arguments.

Shouldn't it also update gimple_call_fntype though, at least for memmove?
Those differ with void const * vs. void * arguments, and also in the return
value.  At least if the old fntype is compatible with the bcopy call.

Jakub


Re: [PATCH] handle bzero/bcopy in DSE and aliasing (PR 80933, 80934)

2017-06-09 Thread Richard Biener
On Thu, Jun 8, 2017 at 6:29 PM, Martin Sebor  wrote:
> On 06/08/2017 01:51 AM, Richard Biener wrote:
>>
>> On Thu, Jun 8, 2017 at 4:33 AM, Martin Sebor  wrote:
>>>
>>> On 06/07/2017 02:12 PM, Martin Sebor wrote:


 On 06/07/2017 02:01 PM, Marc Glisse wrote:
>
>
> On Wed, 7 Jun 2017, Bernhard Reutner-Fischer wrote:
>
>> On 7 June 2017 16:46:53 CEST, Martin Sebor  wrote:
>>>
>>>
>>> On 06/07/2017 02:23 AM, Richard Biener wrote:


 On Wed, Jun 7, 2017 at 5:26 AM, Martin Sebor 
>>>
>>>
>>> wrote:
>>
>>
>> Note I'd be _much_ more sympathetic to simply canonicalizing all
>> of
>> bzero and bcopy
>> to memset / memmove and be done with all the above complexity.
>
>
>
>
> Attached is an updated patch along these lines.  Please let me
> know if it matches your expectations.



 I think you attached the wrong patch.
>>>
>>>
>>>
>>> Yes I did, sorry.  The correct one is attached.
>>
>>
>>
>> Under POSIX.1-2008 "optimizing" bzero or bcmp is IMO plain wrong.
>>
>> It's like optimizing foo() to a random built-in but maybe that's just
>> me. If your libc provides a define to a standard function for these
>> under a compat knob then fine but otherwise you should fix that.
>> *shrug*. Joseph?
>
>
>
> The patch optimizes __builtin_bzero, which should be ok. The question
> (independent from this patch) is then under what conditions bzero
> should
> be detected as a builtin.



 Yes.  The problem is that unlike for C and C++, GCC doesn't have
 a mechanism to select the target version of POSIX.  I think it
 should.

 But there is a subtle problem with the patch that needs fixing.
 Bcopy should not be transformed to memcpy but rather memmove.
 I'll fix that before committing.
>>>
>>>
>>>
>>> Attached is an updated patch with this fix.  I also added a cast
>>> from bcopy and bzero to void to detect accidental uses of the
>>> return value.  Tested on x86_64-linux.
>>
>>
>> Please do not add foldings to builtins.c but instead add them to
>> gimple-fold.c.
>
>
> Sure.  Attached is an adjusted patch.
>
>>
>> +  /* Call memset and return the result cast to void to detect its use
>> + (bzero returns void).  */
>> +  tree call = build_call_expr_loc (loc, fn, 3, dst, integer_zero_node,
>> len);
>> +  return fold_convert (void_type_node, call);
>>
>> ???  How can the result be used if the original call result was not?
>
>
> The cast ensured GCC would continue to warn on code like:
>
>   void f (void *d, unsigned n)
>   {
> return bzero (d, n);
>   }
>
> Without the cast (as in the first patch) the above was silently
> accepted.
>
> This isn't necessary when the folding is done in gimple-fold.c.

+static bool
+gimple_fold_builtin_bcmp (gimple_stmt_iterator *gsi)
+{

+  /* Transform bcmp (a, b, len) into memcmp (a, b, len).  */
+
+  gimple *stmt = gsi_stmt (*gsi);
+  tree a = gimple_call_arg (stmt, 0);
+  tree b = gimple_call_arg (stmt, 1);
+  tree len = gimple_call_arg (stmt, 2);
+
+  gimple_seq seq = NULL;
+  gimple *repl = gimple_build_call (fn, 3, a, b, len);
+  gimple_seq_add_stmt_without_update (, repl);
+  gsi_replace_with_seq_vops (gsi, seq);

given they have the same prototype you can do like gimple_fold_builtin_stpcpy:

  gimple_call_set_fndecl (stmt, fn);
  fold_stmt (gsi);

That works even with bcopy -> memmove if you swap arguments.

Ok with that changes.

Thanks,
Richard.

> Martin


Re: [PATCH] handle bzero/bcopy in DSE and aliasing (PR 80933, 80934)

2017-06-08 Thread Martin Sebor

On 06/08/2017 01:51 AM, Richard Biener wrote:

On Thu, Jun 8, 2017 at 4:33 AM, Martin Sebor  wrote:

On 06/07/2017 02:12 PM, Martin Sebor wrote:


On 06/07/2017 02:01 PM, Marc Glisse wrote:


On Wed, 7 Jun 2017, Bernhard Reutner-Fischer wrote:


On 7 June 2017 16:46:53 CEST, Martin Sebor  wrote:


On 06/07/2017 02:23 AM, Richard Biener wrote:


On Wed, Jun 7, 2017 at 5:26 AM, Martin Sebor 


wrote:


Note I'd be _much_ more sympathetic to simply canonicalizing all of
bzero and bcopy
to memset / memmove and be done with all the above complexity.




Attached is an updated patch along these lines.  Please let me
know if it matches your expectations.



I think you attached the wrong patch.



Yes I did, sorry.  The correct one is attached.



Under POSIX.1-2008 "optimizing" bzero or bcmp is IMO plain wrong.

It's like optimizing foo() to a random built-in but maybe that's just
me. If your libc provides a define to a standard function for these
under a compat knob then fine but otherwise you should fix that.
*shrug*. Joseph?



The patch optimizes __builtin_bzero, which should be ok. The question
(independent from this patch) is then under what conditions bzero should
be detected as a builtin.



Yes.  The problem is that unlike for C and C++, GCC doesn't have
a mechanism to select the target version of POSIX.  I think it
should.

But there is a subtle problem with the patch that needs fixing.
Bcopy should not be transformed to memcpy but rather memmove.
I'll fix that before committing.



Attached is an updated patch with this fix.  I also added a cast
from bcopy and bzero to void to detect accidental uses of the
return value.  Tested on x86_64-linux.


Please do not add foldings to builtins.c but instead add them to gimple-fold.c.


Sure.  Attached is an adjusted patch.



+  /* Call memset and return the result cast to void to detect its use
+ (bzero returns void).  */
+  tree call = build_call_expr_loc (loc, fn, 3, dst, integer_zero_node, len);
+  return fold_convert (void_type_node, call);

???  How can the result be used if the original call result was not?


The cast ensured GCC would continue to warn on code like:

  void f (void *d, unsigned n)
  {
return bzero (d, n);
  }

Without the cast (as in the first patch) the above was silently
accepted.

This isn't necessary when the folding is done in gimple-fold.c.

Martin
PR tree-optimization/80934 - bzero should be assumed not to escape pointer argument
PR tree-optimization/80933 - redundant bzero/bcopy calls not eliminated

gcc/ChangeLog:

	PR tree-optimization/80933
	PR tree-optimization/80934
	* builtins.c (fold_builtin_3): Do not handle bcmp here.
	* gimple-fold.c (gimple_fold_builtin_bcmp): New function.
	(gimple_fold_builtin_bcopy, gimple_fold_builtin_bzero): Likewise.
	(gimple_fold_builtin): Call them.

gcc/testsuite/ChangeLog:

	PR tree-optimization/80933
	PR tree-optimization/80934
	* gcc.dg/fold-bcopy.c: New test.
	* gcc.dg/tree-ssa/ssa-dse-30.c: Likewise..
	* gcc.dg/tree-ssa/alias-36.c: Likewise.
	* gcc/testsuite/gcc.dg/pr79214.c: Adjust.
	* gcc.dg/tree-prof/val-prof-7.c: Likewise.
	* gcc.dg/Wsizeof-pointer-memaccess1.c: Likewise.
	* gcc.dg/builtins-nonnull.c: Likewise.

diff --git a/gcc/builtins.c b/gcc/builtins.c
index 30462ad..ce657bf 100644
--- a/gcc/builtins.c
+++ b/gcc/builtins.c
@@ -9034,7 +9034,6 @@ fold_builtin_3 (location_t loc, tree fndecl,
 	return do_mpfr_remquo (arg0, arg1, arg2);
 break;
 
-case BUILT_IN_BCMP:
 case BUILT_IN_MEMCMP:
   return fold_builtin_memcmp (loc, arg0, arg1, arg2);;
 
diff --git a/gcc/gimple-fold.c b/gcc/gimple-fold.c
index d12f9d0..159a7e6 100644
--- a/gcc/gimple-fold.c
+++ b/gcc/gimple-fold.c
@@ -1076,6 +1076,88 @@ done:
   return true;
 }
 
+/* Transform a call to built-in bcmp(a, b, len) at *GSI into one
+   to built-in memcmp (a, b, len).  */
+
+static bool
+gimple_fold_builtin_bcmp (gimple_stmt_iterator *gsi)
+{
+  tree fn = builtin_decl_implicit (BUILT_IN_MEMCMP);
+
+  if (!fn)
+return false;
+
+  /* Transform bcmp (a, b, len) into memcmp (a, b, len).  */
+
+  gimple *stmt = gsi_stmt (*gsi);
+  tree a = gimple_call_arg (stmt, 0);
+  tree b = gimple_call_arg (stmt, 1);
+  tree len = gimple_call_arg (stmt, 2);
+
+  gimple_seq seq = NULL;
+  gimple *repl = gimple_build_call (fn, 3, a, b, len);
+  gimple_seq_add_stmt_without_update (, repl);
+  gsi_replace_with_seq_vops (gsi, seq);
+  fold_stmt (gsi);
+
+  return true;
+}
+
+/* Transform a call to built-in bcopy (src, dest, len) at *GSI into one
+   to built-in memmove (dest, src, len).  */
+
+static bool
+gimple_fold_builtin_bcopy (gimple_stmt_iterator *gsi)
+{
+  tree fn = builtin_decl_implicit (BUILT_IN_MEMMOVE);
+
+  if (!fn)
+return false;
+
+  /* bcopy has been removed from POSIX in Issue 7 but Issue 6 specifies
+ it's quivalent to memmove (not memcpy).  Transform bcopy (src, dest,
+ len) into memmove (dest, src, len).  */
+
+  gimple *stmt = gsi_stmt 

Re: [PATCH] handle bzero/bcopy in DSE and aliasing (PR 80933, 80934)

2017-06-08 Thread Richard Biener
On Thu, Jun 8, 2017 at 4:33 AM, Martin Sebor  wrote:
> On 06/07/2017 02:12 PM, Martin Sebor wrote:
>>
>> On 06/07/2017 02:01 PM, Marc Glisse wrote:
>>>
>>> On Wed, 7 Jun 2017, Bernhard Reutner-Fischer wrote:
>>>
 On 7 June 2017 16:46:53 CEST, Martin Sebor  wrote:
>
> On 06/07/2017 02:23 AM, Richard Biener wrote:
>>
>> On Wed, Jun 7, 2017 at 5:26 AM, Martin Sebor 
>
> wrote:

 Note I'd be _much_ more sympathetic to simply canonicalizing all of
 bzero and bcopy
 to memset / memmove and be done with all the above complexity.
>>>
>>>
>>>
>>> Attached is an updated patch along these lines.  Please let me
>>> know if it matches your expectations.
>>
>>
>> I think you attached the wrong patch.
>
>
> Yes I did, sorry.  The correct one is attached.


 Under POSIX.1-2008 "optimizing" bzero or bcmp is IMO plain wrong.

 It's like optimizing foo() to a random built-in but maybe that's just
 me. If your libc provides a define to a standard function for these
 under a compat knob then fine but otherwise you should fix that.
 *shrug*. Joseph?
>>>
>>>
>>> The patch optimizes __builtin_bzero, which should be ok. The question
>>> (independent from this patch) is then under what conditions bzero should
>>> be detected as a builtin.
>>
>>
>> Yes.  The problem is that unlike for C and C++, GCC doesn't have
>> a mechanism to select the target version of POSIX.  I think it
>> should.
>>
>> But there is a subtle problem with the patch that needs fixing.
>> Bcopy should not be transformed to memcpy but rather memmove.
>> I'll fix that before committing.
>
>
> Attached is an updated patch with this fix.  I also added a cast
> from bcopy and bzero to void to detect accidental uses of the
> return value.  Tested on x86_64-linux.

Please do not add foldings to builtins.c but instead add them to gimple-fold.c.

+  /* Call memset and return the result cast to void to detect its use
+ (bzero returns void).  */
+  tree call = build_call_expr_loc (loc, fn, 3, dst, integer_zero_node, len);
+  return fold_convert (void_type_node, call);

???  How can the result be used if the original call result was not?

Thanks,
Richard.

> Martin


Re: [PATCH] handle bzero/bcopy in DSE and aliasing (PR 80933, 80934)

2017-06-07 Thread Martin Sebor

On 06/07/2017 02:12 PM, Martin Sebor wrote:

On 06/07/2017 02:01 PM, Marc Glisse wrote:

On Wed, 7 Jun 2017, Bernhard Reutner-Fischer wrote:


On 7 June 2017 16:46:53 CEST, Martin Sebor  wrote:

On 06/07/2017 02:23 AM, Richard Biener wrote:

On Wed, Jun 7, 2017 at 5:26 AM, Martin Sebor 

wrote:

Note I'd be _much_ more sympathetic to simply canonicalizing all of
bzero and bcopy
to memset / memmove and be done with all the above complexity.



Attached is an updated patch along these lines.  Please let me
know if it matches your expectations.


I think you attached the wrong patch.


Yes I did, sorry.  The correct one is attached.


Under POSIX.1-2008 "optimizing" bzero or bcmp is IMO plain wrong.

It's like optimizing foo() to a random built-in but maybe that's just
me. If your libc provides a define to a standard function for these
under a compat knob then fine but otherwise you should fix that.
*shrug*. Joseph?


The patch optimizes __builtin_bzero, which should be ok. The question
(independent from this patch) is then under what conditions bzero should
be detected as a builtin.


Yes.  The problem is that unlike for C and C++, GCC doesn't have
a mechanism to select the target version of POSIX.  I think it
should.

But there is a subtle problem with the patch that needs fixing.
Bcopy should not be transformed to memcpy but rather memmove.
I'll fix that before committing.


Attached is an updated patch with this fix.  I also added a cast
from bcopy and bzero to void to detect accidental uses of the
return value.  Tested on x86_64-linux.

Martin
PR tree-optimization/80934 - bzero should be assumed not to escape pointer argument
PR tree-optimization/80933 - redundant bzero/bcopy calls not eliminated

gcc/ChangeLog:

	PR tree-optimization/80933
	PR tree-optimization/80934
	* builtins.c (fold_builtin_bcmp, fold_builtin_bcopy): New functions.
	(fold_builtin_bzero): Likewise.
	(fold_builtin_2): Handle bzero.
	(fold_builtin_3): Handle bcmp and bcpy.

gcc/testsuite/ChangeLog:

	PR tree-optimization/80933
	PR tree-optimization/80934
	* gcc.dg/fold-bcopy.c: New test.
	* gcc.dg/tree-ssa/ssa-dse-30.c: Likewise..
	* gcc.dg/tree-ssa/alias-36.c: Likewise.
	* gcc/testsuite/gcc.dg/pr79214.c: Adjust.
	* gcc.dg/tree-prof/val-prof-7.c: Likewise.
	* gcc.dg/Wsizeof-pointer-memaccess1.c: Likewise.
	* gcc.dg/builtins-nonnull.c: Likewise.

diff --git a/gcc/builtins.c b/gcc/builtins.c
index 30462ad..52d42b9 100644
--- a/gcc/builtins.c
+++ b/gcc/builtins.c
@@ -145,6 +145,9 @@ static rtx expand_builtin_unop (machine_mode, tree, rtx, rtx, optab);
 static rtx expand_builtin_frame_address (tree, tree);
 static tree stabilize_va_list_loc (location_t, tree, int);
 static rtx expand_builtin_expect (tree, rtx);
+static tree fold_builtin_bcmp (location_t, tree, tree, tree);
+static tree fold_builtin_bcopy (location_t, tree, tree, tree);
+static tree fold_builtin_bzero (location_t, tree, tree);
 static tree fold_builtin_constant_p (tree);
 static tree fold_builtin_classify_type (tree);
 static tree fold_builtin_strlen (location_t, tree, tree);
@@ -7982,6 +7985,56 @@ fold_builtin_sincos (location_t loc,
 			 fold_build1_loc (loc, REALPART_EXPR, type, call)));
 }
 
+/* Fold function call to built-in bzero with arguments SRC and LEN
+   into a call to built-in memset (DST, 0, LEN).  */
+
+static tree
+fold_builtin_bzero (location_t loc, tree dst, tree len)
+{
+  if (!validate_arg (dst, POINTER_TYPE)
+  || !validate_arg (len, INTEGER_TYPE))
+return NULL_TREE;
+
+  tree fn = builtin_decl_implicit (BUILT_IN_MEMSET);
+  /* Call memset and return the result cast to void to detect its use
+ (bzero returns void).  */
+  tree call = build_call_expr_loc (loc, fn, 3, dst, integer_zero_node, len);
+  return fold_convert (void_type_node, call);
+}
+
+/* Fold function call to built-in bcmp with arguments ARG1, ARG2, and LEN
+   into a call to built-in memcmp(ARG1, ARG2, LEN).  */
+
+static tree
+fold_builtin_bcmp (location_t loc, tree arg1, tree arg2, tree len)
+{
+  if (!validate_arg (arg1, POINTER_TYPE)
+  || !validate_arg (arg2, POINTER_TYPE)
+  || !validate_arg (len, INTEGER_TYPE))
+return NULL_TREE;
+
+  tree fn = builtin_decl_implicit (BUILT_IN_MEMCMP);
+  return build_call_expr_loc (loc, fn, 3, arg1, arg2, len);
+}
+
+/* Fold function call to built-in bcopy with arguments SRC, DST, and LEN
+   into a call to built-in memmove(DST, SRC, LEN).  */
+
+static tree
+fold_builtin_bcopy (location_t loc, tree src, tree dst, tree len)
+{
+  if (!validate_arg (src, POINTER_TYPE)
+  || !validate_arg (dst, POINTER_TYPE)
+  || !validate_arg (len, INTEGER_TYPE))
+return NULL_TREE;
+
+  /* bcopy has been removed from POSIX in Issue 7 but Issue 6 specifies
+ it's quivalent to memmove (not memcpy).  Call memmove and return
+ the result cast to void to detect its use (bcopy returns void).  */
+  tree fn = builtin_decl_implicit (BUILT_IN_MEMMOVE);
+  return build_call_expr_loc (loc, fn, 3, 

Re: [PATCH] handle bzero/bcopy in DSE and aliasing (PR 80933, 80934)

2017-06-07 Thread Joseph Myers
On Wed, 7 Jun 2017, Bernhard Reutner-Fischer wrote:

> It's like optimizing foo() to a random built-in but maybe that's just 
> me. If your libc provides a define to a standard function for these 
> under a compat knob then fine but otherwise you should fix that. 
> *shrug*. Joseph?

It's the usual thing of: if the -std option enables a function as built-in 
it can be assumed to have certain semantics if called (this does *not* 
mean it's appropriate to generate calls to it from code that called other 
functions, as the library might not have it at all; that's for the 
libc_has_function hook to specify).  Otherwise (-std=c11 etc. options) 
semantics cannot be assumed based on the name (they still can for 
__builtin_*) - but in principle it may be OK to assume semantics for a 
function whose name is reserved in the relevant C standard version, or if 
an explicit declaration came from a system header (which would generally 
be the case for e.g. -std=c99 -D_POSIX_C_SOURCE=whatever).

-- 
Joseph S. Myers
jos...@codesourcery.com


Re: [PATCH] handle bzero/bcopy in DSE and aliasing (PR 80933, 80934)

2017-06-07 Thread Martin Sebor

On 06/07/2017 02:01 PM, Marc Glisse wrote:

On Wed, 7 Jun 2017, Bernhard Reutner-Fischer wrote:


On 7 June 2017 16:46:53 CEST, Martin Sebor  wrote:

On 06/07/2017 02:23 AM, Richard Biener wrote:

On Wed, Jun 7, 2017 at 5:26 AM, Martin Sebor 

wrote:

Note I'd be _much_ more sympathetic to simply canonicalizing all of
bzero and bcopy
to memset / memmove and be done with all the above complexity.



Attached is an updated patch along these lines.  Please let me
know if it matches your expectations.


I think you attached the wrong patch.


Yes I did, sorry.  The correct one is attached.


Under POSIX.1-2008 "optimizing" bzero or bcmp is IMO plain wrong.

It's like optimizing foo() to a random built-in but maybe that's just
me. If your libc provides a define to a standard function for these
under a compat knob then fine but otherwise you should fix that.
*shrug*. Joseph?


The patch optimizes __builtin_bzero, which should be ok. The question
(independent from this patch) is then under what conditions bzero should
be detected as a builtin.


Yes.  The problem is that unlike for C and C++, GCC doesn't have
a mechanism to select the target version of POSIX.  I think it
should.

But there is a subtle problem with the patch that needs fixing.
Bcopy should not be transformed to memcpy but rather memmove.
I'll fix that before committing.

Martin


Re: [PATCH] handle bzero/bcopy in DSE and aliasing (PR 80933, 80934)

2017-06-07 Thread Marc Glisse

On Wed, 7 Jun 2017, Bernhard Reutner-Fischer wrote:


On 7 June 2017 16:46:53 CEST, Martin Sebor  wrote:

On 06/07/2017 02:23 AM, Richard Biener wrote:

On Wed, Jun 7, 2017 at 5:26 AM, Martin Sebor 

wrote:

Note I'd be _much_ more sympathetic to simply canonicalizing all of
bzero and bcopy
to memset / memmove and be done with all the above complexity.



Attached is an updated patch along these lines.  Please let me
know if it matches your expectations.


I think you attached the wrong patch.


Yes I did, sorry.  The correct one is attached.


Under POSIX.1-2008 "optimizing" bzero or bcmp is IMO plain wrong.

It's like optimizing foo() to a random built-in but maybe that's just 
me. If your libc provides a define to a standard function for these 
under a compat knob then fine but otherwise you should fix that. 
*shrug*. Joseph?


The patch optimizes __builtin_bzero, which should be ok. The question 
(independent from this patch) is then under what conditions bzero should 
be detected as a builtin.


--
Marc Glisse


Re: [PATCH] handle bzero/bcopy in DSE and aliasing (PR 80933, 80934)

2017-06-07 Thread Bernhard Reutner-Fischer
On 7 June 2017 16:46:53 CEST, Martin Sebor  wrote:
>On 06/07/2017 02:23 AM, Richard Biener wrote:
>> On Wed, Jun 7, 2017 at 5:26 AM, Martin Sebor 
>wrote:
 Note I'd be _much_ more sympathetic to simply canonicalizing all of
 bzero and bcopy
 to memset / memmove and be done with all the above complexity.
>>>
>>>
>>> Attached is an updated patch along these lines.  Please let me
>>> know if it matches your expectations.
>>
>> I think you attached the wrong patch.
>
>Yes I did, sorry.  The correct one is attached.

Under POSIX.1-2008 "optimizing" bzero or bcmp is IMO plain wrong.

It's like optimizing foo() to a random built-in but maybe that's just me. If 
your libc provides a define to a standard function for these under a compat 
knob then fine but otherwise you should fix that. *shrug*. Joseph?

thanks,
>
>Martin
>
>>
>> Richard.
>>
>>> FWIW, although I don't feel too strongly about bzero et al. I'm
>>> not sure that this approach is the right one in general.  It might
>>> (slightly) simplify GCC itself, but other than the incidental code
>>> generation improvement, it offers no benefit to users.  In some
>>> cases, it even degrades user experience by causing GCC issue
>>> diagnostics that refer to functions that don't appear in the source
>>> code, such as for:
>>>
>>>   char d[1];
>>>
>>>   void* f (const void *p)
>>>   {
>>> bzero (d, 7);
>>>   }
>>>
>>>   warning: ‘__builtin_memset’ writing 7 bytes into a region of size
>1
>>> overflows the destination [-Wstringop-overflow=]
>>>
>>> For some functions like mempcpy it might even worse code overall
>>> (slower and bigger).
>>>
>>> In other cases (like profiling) it loses interesting information.
>>>
>>> I think these types of transformations would be justified  f they
>>> were done based on measurably improved efficiency of the generated
>>> code, but I'm uneasy about swapping calls to one function for
>another
>>> solely because it simplifies the implementation.  Not least because
>>> it doesn't seem like a viable general approach to simplifying the
>>> implementation.
>>>
>>> Martin
>>>
>>> PS I stopped short of simplifying GCC to remove the existing special
>>> handling of these three built-ins.  If the patch is approved I'm
>>> willing to do the cleanup in a subsequent pass.



Re: [PATCH] handle bzero/bcopy in DSE and aliasing (PR 80933, 80934)

2017-06-07 Thread Martin Sebor

On 06/07/2017 02:23 AM, Richard Biener wrote:

On Wed, Jun 7, 2017 at 5:26 AM, Martin Sebor  wrote:

Note I'd be _much_ more sympathetic to simply canonicalizing all of
bzero and bcopy
to memset / memmove and be done with all the above complexity.



Attached is an updated patch along these lines.  Please let me
know if it matches your expectations.


I think you attached the wrong patch.


Yes I did, sorry.  The correct one is attached.

Martin



Richard.


FWIW, although I don't feel too strongly about bzero et al. I'm
not sure that this approach is the right one in general.  It might
(slightly) simplify GCC itself, but other than the incidental code
generation improvement, it offers no benefit to users.  In some
cases, it even degrades user experience by causing GCC issue
diagnostics that refer to functions that don't appear in the source
code, such as for:

  char d[1];

  void* f (const void *p)
  {
bzero (d, 7);
  }

  warning: ‘__builtin_memset’ writing 7 bytes into a region of size 1
overflows the destination [-Wstringop-overflow=]

For some functions like mempcpy it might even worse code overall
(slower and bigger).

In other cases (like profiling) it loses interesting information.

I think these types of transformations would be justified  f they
were done based on measurably improved efficiency of the generated
code, but I'm uneasy about swapping calls to one function for another
solely because it simplifies the implementation.  Not least because
it doesn't seem like a viable general approach to simplifying the
implementation.

Martin

PS I stopped short of simplifying GCC to remove the existing special
handling of these three built-ins.  If the patch is approved I'm
willing to do the cleanup in a subsequent pass.


PR tree-optimization/80934 - bzero should be assumed not to escape pointer argument
PR tree-optimization/80933 - redundant bzero/bcopy calls not eliminated

gcc/ChangeLog:

	PR tree-optimization/80933
	PR tree-optimization/80934
	* builtins.c (fold_builtin_bcmp, fold_builtin_bcopy): New functions.
	(fold_builtin_bzero): Likewise.
	(fold_builtin_2): Handle bzero.
	(fold_builtin_3): Handle bcmp and bcpy.

gcc/testsuite/ChangeLog:

	PR tree-optimization/80933
	PR tree-optimization/80934
	* gcc.dg/fold-bcopy.c: New test.
	* gcc.dg/tree-ssa/ssa-dse-30.c: Likewise..
	* gcc.dg/tree-ssa/alias-36.c: Likewise.
	* gcc/testsuite/gcc.dg/pr79214.c: Adjust.

diff --git a/gcc/builtins.c b/gcc/builtins.c
index 30462ad..c6a2ec5 100644
--- a/gcc/builtins.c
+++ b/gcc/builtins.c
@@ -145,6 +145,9 @@ static rtx expand_builtin_unop (machine_mode, tree, rtx, rtx, optab);
 static rtx expand_builtin_frame_address (tree, tree);
 static tree stabilize_va_list_loc (location_t, tree, int);
 static rtx expand_builtin_expect (tree, rtx);
+static tree fold_builtin_bcmp (location_t, tree, tree, tree);
+static tree fold_builtin_bcopy (location_t, tree, tree, tree);
+static tree fold_builtin_bzero (location_t, tree, tree);
 static tree fold_builtin_constant_p (tree);
 static tree fold_builtin_classify_type (tree);
 static tree fold_builtin_strlen (location_t, tree, tree);
@@ -7982,6 +7985,53 @@ fold_builtin_sincos (location_t loc,
 			 fold_build1_loc (loc, REALPART_EXPR, type, call)));
 }
 
+/* Fold function call to built-in bzero with arguments SRC and LEN
+   into a call to built-in memset (DST, 0, LEN).  */
+
+static tree
+fold_builtin_bzero (location_t loc, tree dst, tree len)
+{
+  if (!validate_arg (dst, POINTER_TYPE)
+  || !validate_arg (len, INTEGER_TYPE))
+return NULL_TREE;
+
+  tree fn = builtin_decl_implicit (BUILT_IN_MEMSET);
+  return build_call_expr_loc (loc, fn, 3, dst, integer_zero_node, len);
+}
+
+/* Fold function call to built-in bcmp with arguments ARG1, ARG2, and LEN
+   into a call to built-in memcmp(ARG1, ARG2, LEN).  */
+
+static tree
+fold_builtin_bcmp (location_t loc, tree arg1, tree arg2, tree len)
+{
+  if (tree ret = fold_builtin_memcmp (loc, arg1, arg2, len))
+return ret;
+
+  if (!validate_arg (arg1, POINTER_TYPE)
+  || !validate_arg (arg2, POINTER_TYPE)
+  || !validate_arg (len, INTEGER_TYPE))
+return NULL_TREE;
+
+  tree fn = builtin_decl_implicit (BUILT_IN_MEMCMP);
+  return build_call_expr_loc (loc, fn, 3, arg1, arg2, len);
+}
+
+/* Fold function call to built-in bcopy with arguments SRC, DST, and LEN
+   into a call to built-in memcpy(DST, SRC, LEN).  */
+
+static tree
+fold_builtin_bcopy (location_t loc, tree src, tree dst, tree len)
+{
+  if (!validate_arg (src, POINTER_TYPE)
+  || !validate_arg (dst, POINTER_TYPE)
+  || !validate_arg (len, INTEGER_TYPE))
+return NULL_TREE;
+
+  tree fn = builtin_decl_implicit (BUILT_IN_MEMCPY);
+  return build_call_expr_loc (loc, fn, 3, dst, src, len);
+}
+
 /* Fold function call to builtin memcmp with arguments ARG1 and ARG2.
Return NULL_TREE if no simplification can be made.  */
 
@@ -8947,6 +8997,9 @@ fold_builtin_2 (location_t loc, tree fndecl, tree arg0, tree arg1)
 

Re: [PATCH] handle bzero/bcopy in DSE and aliasing (PR 80933, 80934)

2017-06-07 Thread Richard Biener
On Wed, Jun 7, 2017 at 5:26 AM, Martin Sebor  wrote:
>> Note I'd be _much_ more sympathetic to simply canonicalizing all of
>> bzero and bcopy
>> to memset / memmove and be done with all the above complexity.
>
>
> Attached is an updated patch along these lines.  Please let me
> know if it matches your expectations.

I think you attached the wrong patch.

Richard.

> FWIW, although I don't feel too strongly about bzero et al. I'm
> not sure that this approach is the right one in general.  It might
> (slightly) simplify GCC itself, but other than the incidental code
> generation improvement, it offers no benefit to users.  In some
> cases, it even degrades user experience by causing GCC issue
> diagnostics that refer to functions that don't appear in the source
> code, such as for:
>
>   char d[1];
>
>   void* f (const void *p)
>   {
> bzero (d, 7);
>   }
>
>   warning: ‘__builtin_memset’ writing 7 bytes into a region of size 1
> overflows the destination [-Wstringop-overflow=]
>
> For some functions like mempcpy it might even worse code overall
> (slower and bigger).
>
> In other cases (like profiling) it loses interesting information.
>
> I think these types of transformations would be justified  f they
> were done based on measurably improved efficiency of the generated
> code, but I'm uneasy about swapping calls to one function for another
> solely because it simplifies the implementation.  Not least because
> it doesn't seem like a viable general approach to simplifying the
> implementation.
>
> Martin
>
> PS I stopped short of simplifying GCC to remove the existing special
> handling of these three built-ins.  If the patch is approved I'm
> willing to do the cleanup in a subsequent pass.


Re: [PATCH] handle bzero/bcopy in DSE and aliasing (PR 80933, 80934)

2017-06-06 Thread Martin Sebor

Note I'd be _much_ more sympathetic to simply canonicalizing all of
bzero and bcopy
to memset / memmove and be done with all the above complexity.


Attached is an updated patch along these lines.  Please let me
know if it matches your expectations.

FWIW, although I don't feel too strongly about bzero et al. I'm
not sure that this approach is the right one in general.  It might
(slightly) simplify GCC itself, but other than the incidental code
generation improvement, it offers no benefit to users.  In some
cases, it even degrades user experience by causing GCC issue
diagnostics that refer to functions that don't appear in the source
code, such as for:

  char d[1];

  void* f (const void *p)
  {
bzero (d, 7);
  }

  warning: ‘__builtin_memset’ writing 7 bytes into a region of size 1 
overflows the destination [-Wstringop-overflow=]


For some functions like mempcpy it might even worse code overall
(slower and bigger).

In other cases (like profiling) it loses interesting information.

I think these types of transformations would be justified  f they
were done based on measurably improved efficiency of the generated
code, but I'm uneasy about swapping calls to one function for another
solely because it simplifies the implementation.  Not least because
it doesn't seem like a viable general approach to simplifying the
implementation.

Martin

PS I stopped short of simplifying GCC to remove the existing special
handling of these three built-ins.  If the patch is approved I'm
willing to do the cleanup in a subsequent pass.
diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt
index 37bb236..363d104 100644
--- a/gcc/c-family/c.opt
+++ b/gcc/c-family/c.opt
@@ -804,6 +804,10 @@ Wnon-template-friend
 C++ ObjC++ Var(warn_nontemplate_friend) Init(1) Warning
 Warn when non-templatized friend functions are declared within a template.
 
+Wclass-memaccess
+C++ ObjC++ Var(warn_class_memaccess) Warning LangEnabledBy(C++ ObjC++, Wall)
+Warn for unsafe raw memory writes to objects of class types.
+
 Wnon-virtual-dtor
 C++ ObjC++ Var(warn_nonvdtor) Warning LangEnabledBy(C++ ObjC++,Weffc++)
 Warn about non-virtual destructors.
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index 51260f0..6d8e77e 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -8146,6 +8146,396 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
   return call;
 }
 
+/* Return the DECL of the first non-public data member of class TYPE
+   or null if none can be found.  */
+
+static tree
+first_non_public_field (tree type)
+{
+  if (!CLASS_TYPE_P (type))
+return NULL_TREE;
+
+  for (tree field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
+{
+  if (TREE_CODE (field) != FIELD_DECL)
+	continue;
+  if (TREE_STATIC (field))
+	continue;
+  if (TREE_PRIVATE (field) || TREE_PROTECTED (field))
+	return field;
+}
+
+  int i = 0;
+
+  for (tree base_binfo, binfo = TYPE_BINFO (type);
+   BINFO_BASE_ITERATE (binfo, i, base_binfo); i++)
+{
+  tree base = TREE_TYPE (base_binfo);
+
+  if (tree field = first_non_public_field (base))
+	return field;
+}
+
+  return NULL_TREE;
+}
+
+/* Return true if all copy and move assignment operator overloads for
+   class TYPE are trivial and at least one of them is not deleted and,
+   when ACCESS is set, accessible.  Return false otherwise.  Set
+   HASASSIGN to true when the TYPE has a (not necessarily trivial)
+   copy or move assignment.  */
+
+static bool
+has_trivial_copy_assign_p (tree type, bool access, bool *hasassign)
+{
+  tree fns = cp_assignment_operator_id (NOP_EXPR);
+  fns = lookup_fnfields_slot (type, fns);
+
+  bool all_trivial = true;
+
+  /* Iterate over copy and move assignment overloads.  */
+
+  for (ovl_iterator oi (fns); oi; ++oi)
+{
+  tree f = *oi;
+
+  bool accessible = !access || !(TREE_PRIVATE (f) || TREE_PROTECTED (f));
+
+  /* Skip template assignment operators and deleted functions.  */
+  if (TREE_CODE (f) != FUNCTION_DECL || DECL_DELETED_FN (f))
+	continue;
+
+  if (accessible)
+	*hasassign = true;
+
+  if (!accessible || !trivial_fn_p (f))
+	all_trivial = false;
+
+  /* Break early when both properties have been determined.  */
+  if (*hasassign && !all_trivial)
+	break;
+}
+
+  /* Return true if they're all trivial and one of the expressions
+ TYPE() = TYPE() or TYPE() = (TYPE&)() is valid.  */
+  tree ref = cp_build_reference_type (type, false);
+  return (all_trivial
+	  && (is_trivially_xible (MODIFY_EXPR, type, type)
+	  || is_trivially_xible (MODIFY_EXPR, type, ref)));
+}
+
+/* Return true if all copy and move ctor overloads for class TYPE are
+   trivial and at least one of them is not deleted and, when ACCESS is
+   set, accessible.  Return false otherwise.  Set each element of HASCTOR[]
+   to true when the TYPE has a (not necessarily trivial) default and copy
+   (or move) ctor, respectively.  */
+
+static bool
+has_trivial_copy_p (tree type, bool access, bool 

Re: [PATCH] handle bzero/bcopy in DSE and aliasing (PR 80933, 80934)

2017-06-06 Thread Jeff Law
On 06/04/2017 09:36 AM, Bernhard Reutner-Fischer wrote:
> On 2 June 2017 13:12:41 CEST, Richard Biener  
> wrote:
> 
>> Note I'd be _much_ more sympathetic to simply canonicalizing all of
>> bzero and bcopy
>> to memset / memmove and be done with all the above complexity.
> 
> Indeed and even more so since SUSv3 marked it LEGACY and both were removed in 
> SUSv4.
> thanks,
Likewise.
jeff


Re: [PATCH] handle bzero/bcopy in DSE and aliasing (PR 80933, 80934)

2017-06-04 Thread Bernhard Reutner-Fischer
On 2 June 2017 13:12:41 CEST, Richard Biener  wrote:

>Note I'd be _much_ more sympathetic to simply canonicalizing all of
>bzero and bcopy
>to memset / memmove and be done with all the above complexity.

Indeed and even more so since SUSv3 marked it LEGACY and both were removed in 
SUSv4.
thanks,


Re: [PATCH] handle bzero/bcopy in DSE and aliasing (PR 80933, 80934)

2017-06-02 Thread Richard Biener
  On Thu, Jun 1, 2017 at 10:52 PM, Martin Sebor  wrote:
> While testing some otherwise unrelated enhancements in these areas
> I noticed that calls to bzero and bcopy are not being handled as
> efficiently as equivalent calls to memset and memcpy.  Specifically,
> redundant calls are not eliminated and the functions appear to be
> treated as if they allowed their pointer arguments to escape.  This
> turned out to be due to the missing handling of the former two built
> ins by the DSE and aliasing passes.
>
> The attached patch adds this handling so the cases I noted in the two
> PRs are now handled.

+  /* The number of the size argument to one of the built-in functions
+ below.  */
+  unsigned sizargno = 2;
   /* Handle those builtin functions explicitly that do not act as
  escape points.  See tree-ssa-structalias.c:find_func_aliases
  for the list of builtins we might need to handle here.  */
@@ -2030,8 +2034,13 @@ call_may_clobber_ref_p_1 (gcall *call, ao_ref *ref)
   && gimple_call_builtin_p (call, BUILT_IN_NORMAL))
 switch (DECL_FUNCTION_CODE (callee))
   {
-   /* All the following functions clobber memory pointed to by
-  their first argument.  */
+case BUILT_IN_BZERO:
+ sizargno = 1;
+ /* Fall through.  */
+
+ /* With the exception of the bzero function above, all of
+the following clobber memory pointed to by their first
+argument.  */
case BUILT_IN_STRCPY:
case BUILT_IN_STRNCPY:
case BUILT_IN_MEMCPY:
@@ -2062,9 +2071,9 @@ call_may_clobber_ref_p_1 (gcall *call, ao_ref *ref)
   is strlen (dest) + n + 1 instead of n, resp.
   n + 1 at dest + strlen (dest), but strlen (dest) isn't
   known.  */
-   if (gimple_call_num_args (call) == 3
+   if (gimple_call_num_args (call) > sizargno
&& DECL_FUNCTION_CODE (callee) != BUILT_IN_STRNCAT)
- size = gimple_call_arg (call, 2);
+ size = gimple_call_arg (call, sizargno);
ao_ref_init_from_ptr_and_size (,
   gimple_call_arg (call, 0),
   size);

please insted do

if (DECL_FUNCTION_CODE (callee) == BUILT_IN_BZERO)
  size = gimple_call_Arg (call, 1);
else if (gimple_call_num_args (call) == 3
...

instead of the above changes.  Likewise in stmt_kills_ref_p.

Likewise in initialize_ao_ref_for_dse I see no value in uglifying the code
but instead do

   case BUILT_IN_BCOPY:
  {
ao_ref_init_from_ptr_and_size (write, gimple_call_arg (stmt,
1), gimple_call_arg (stmt, 2));
return true;
  }

and similar for BZERO.

Similar in maybe_trim_memstar_call, for decrement_count simply pass in
the tree *
instead of the argno (and you can get rid of the stmt as well.

+ 1) Bzero and memset.  */
+  bool memset_p = false;
   if (is_gimple_reg_type (vr->type)
-  && gimple_call_builtin_p (def_stmt, BUILT_IN_MEMSET)
-  && integer_zerop (gimple_call_arg (def_stmt, 1))
-  && tree_fits_uhwi_p (gimple_call_arg (def_stmt, 2))
+  && (((memset_p = gimple_call_builtin_p (def_stmt, BUILT_IN_MEMSET))
+  && integer_zerop (gimple_call_arg (def_stmt, 1))
+  && tree_fits_uhwi_p (gimple_call_arg (def_stmt, 2)))
+ || gimple_call_builtin_p (def_stmt, BUILT_IN_BZERO))

you miss the tree_fits_uhwi_p check for bzero.

Note I'd be _much_ more sympathetic to simply canonicalizing all of
bzero and bcopy
to memset / memmove and be done with all the above complexity.

Richard.

> Tested on x86_64-linux.
>
> Martin


[PATCH] handle bzero/bcopy in DSE and aliasing (PR 80933, 80934)

2017-06-01 Thread Martin Sebor

While testing some otherwise unrelated enhancements in these areas
I noticed that calls to bzero and bcopy are not being handled as
efficiently as equivalent calls to memset and memcpy.  Specifically,
redundant calls are not eliminated and the functions appear to be
treated as if they allowed their pointer arguments to escape.  This
turned out to be due to the missing handling of the former two built
ins by the DSE and aliasing passes.

The attached patch adds this handling so the cases I noted in the two
PRs are now handled.

Tested on x86_64-linux.

Martin
PR tree-optimization/80934 - bzero should be assumed not to escape pointer argument
PR tree-optimization/80933 - redundant bzero/bcopy calls not eliminated

gcc/ChangeLog:

	PR tree-optimization/80933
	* tree-ssa-alias.c (ref_maybe_used_by_call_p_1): Handle bzero.
	(call_may_clobber_ref_p_1): Likewise.
	(stmt_kills_ref_p): Likewise.
	* tree-ssa-dse.c (initialize_ao_ref_for_dse): Handle bcopy and bzero.
	(decrement_count): Add an argument.
	(maybe_trim_memstar_call): Handle bcopy.
	(dse_dom_walker::dse_optimize_stmt): Likewise.
	* tree-ssa-sccvn.c (vn_reference_lookup_3): Handle bzero.
	* tree-ssa-structalias.c (find_func_aliases_for_builtin_call): Likewise.
	(find_func_clobbers): Likewise.

gcc/testsuite/ChangeLog:

	PR tree-optimization/80933
	* gcc.dg/tree-ssa/ssa-dse-30.c: New test.
	* gcc.dg/tree-ssa/alias-36.c: Likewise.

diff --git a/gcc/testsuite/gcc.dg/tree-ssa/alias-36.c b/gcc/testsuite/gcc.dg/tree-ssa/alias-36.c
new file mode 100644
index 000..61b601a
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/alias-36.c
@@ -0,0 +1,28 @@
+/* PR tree-optimization/80934 - bzero should be assumed not to escape
+   pointer argument
+   { dg-do compile }
+   { dg-options "-O2 -fdump-tree-alias" } */
+
+void foobar (void);
+
+void f (void);
+
+void g (void)
+{
+  char d[32];
+  __builtin_memset (d, 0, sizeof d);
+  f ();
+  if (*d != 0)
+foobar ();
+}
+
+void h (void)
+{
+  char d[32];
+  __builtin_bzero (d, sizeof d);
+  f ();
+  if (*d != 0)
+foobar ();
+}
+
+/* { dg-final { scan-tree-dump-not "memset|foobar|bzero" "alias" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-30.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-30.c
new file mode 100644
index 000..9d2c920
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-30.c
@@ -0,0 +1,30 @@
+/* PR tree-optimization/80933 - redundant bzero/bcopy calls not eliminated
+   { dg-do compile }
+   { dg-options "-O2 -fdump-tree-dse1" } */
+
+void sink (void*);
+
+void test_bcopy (const void *s)
+{
+  char d[33];
+
+  /* The bcopy calls are expanded inline in EVRP, before DSE runs,
+ so this test doesn't actually verify that DSE does its job.  */
+  __builtin_bcopy (s, d, sizeof d);
+  __builtin_bcopy (s, d, sizeof d);
+
+  sink (d);
+}
+
+void test_bzero (void)
+{
+  char d[33];
+
+  __builtin_bzero (d, sizeof d);
+  __builtin_bzero (d, sizeof d);
+
+  sink (d);
+}
+
+/* { dg-final { scan-tree-dump-times "builtin_bzero" 1 "dse1" } } */
+/* { dg-final { scan-tree-dump-not "builtin_bcopy" "dse1" } } */
diff --git a/gcc/tree-ssa-alias.c b/gcc/tree-ssa-alias.c
index 74ee2b0..8c4b289f 100644
--- a/gcc/tree-ssa-alias.c
+++ b/gcc/tree-ssa-alias.c
@@ -1783,6 +1783,7 @@ ref_maybe_used_by_call_p_1 (gcall *call, ao_ref *ref)
 	case BUILT_IN_ALLOCA_WITH_ALIGN:
 	case BUILT_IN_STACK_SAVE:
 	case BUILT_IN_STACK_RESTORE:
+	case BUILT_IN_BZERO:
 	case BUILT_IN_MEMSET:
 	case BUILT_IN_TM_MEMSET:
 	case BUILT_IN_MEMSET_CHK:
@@ -2023,6 +2024,9 @@ call_may_clobber_ref_p_1 (gcall *call, ao_ref *ref)
 
   callee = gimple_call_fndecl (call);
 
+  /* The number of the size argument to one of the built-in functions
+ below.  */
+  unsigned sizargno = 2;
   /* Handle those builtin functions explicitly that do not act as
  escape points.  See tree-ssa-structalias.c:find_func_aliases
  for the list of builtins we might need to handle here.  */
@@ -2030,8 +2034,13 @@ call_may_clobber_ref_p_1 (gcall *call, ao_ref *ref)
   && gimple_call_builtin_p (call, BUILT_IN_NORMAL))
 switch (DECL_FUNCTION_CODE (callee))
   {
-	/* All the following functions clobber memory pointed to by
-	   their first argument.  */
+case BUILT_IN_BZERO:
+	  sizargno = 1;
+	  /* Fall through.  */
+
+	  /* With the exception of the bzero function above, all of
+	 the following clobber memory pointed to by their first
+	 argument.  */
 	case BUILT_IN_STRCPY:
 	case BUILT_IN_STRNCPY:
 	case BUILT_IN_MEMCPY:
@@ -2062,9 +2071,9 @@ call_may_clobber_ref_p_1 (gcall *call, ao_ref *ref)
 	   is strlen (dest) + n + 1 instead of n, resp.
 	   n + 1 at dest + strlen (dest), but strlen (dest) isn't
 	   known.  */
-	if (gimple_call_num_args (call) == 3
+	if (gimple_call_num_args (call) > sizargno
 		&& DECL_FUNCTION_CODE (callee) != BUILT_IN_STRNCAT)
-	  size = gimple_call_arg (call, 2);
+	  size = gimple_call_arg (call, sizargno);
 	ao_ref_init_from_ptr_and_size (,