public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH] tree-ssa-math-opts: Pattern recognize some further hand written forms of signed __builtin_mul_overflow{,_p} [PR105776]
@ 2023-05-19  8:06 Jakub Jelinek
  2023-05-19 10:43 ` Richard Biener
  0 siblings, 1 reply; 2+ messages in thread
From: Jakub Jelinek @ 2023-05-19  8:06 UTC (permalink / raw)
  To: Richard Biener; +Cc: gcc-patches

Hi!

In the pattern recognition of signed __builtin_mul_overflow{,_p} we
check for result of unsigned division (which follows unsigned
multiplication) being equality compared against one of the multiplication's
argument (the one not used in the division) and check for the comparison
to be done against same precision cast of the argument (because
division's result is unsigned and the argument is signed).
But as shown in this PR, one can write it equally as comparison done in
the signed type, i.e. compare division's result cast to corresponding
signed type against the argument.

The following patch handles even those cases.

Bootstrapped/regtested on x86_64-linux, i686-linux, aarch64-linux and
powerpc64le-linux, ok for trunk?

2023-05-19  Jakub Jelinek  <jakub@redhat.com>

	PR tree-optimization/105776
	* tree-ssa-math-opts.cc (arith_overflow_check_p): If cast_stmt is
	non-NULL, allow division statement to have a cast as single imm use
	rather than comparison/condition.
	(match_arith_overflow): In that case remove the cast stmt in addition
	to the division statement.

	* gcc.target/i386/pr105776.c: New test.

--- gcc/tree-ssa-math-opts.cc.jj	2023-05-18 14:57:13.216409685 +0200
+++ gcc/tree-ssa-math-opts.cc	2023-05-18 15:45:34.077177053 +0200
@@ -3802,6 +3802,21 @@ arith_overflow_check_p (gimple *stmt, gi
       use_operand_p use;
       if (!single_imm_use (divlhs, &use, &cur_use_stmt))
 	return 0;
+      if (cast_stmt && gimple_assign_cast_p (cur_use_stmt))
+	{
+	  tree cast_lhs = gimple_assign_lhs (cur_use_stmt);
+	  if (INTEGRAL_TYPE_P (TREE_TYPE (cast_lhs))
+	      && TYPE_UNSIGNED (TREE_TYPE (cast_lhs))
+	      && (TYPE_PRECISION (TREE_TYPE (cast_lhs))
+		  == TYPE_PRECISION (TREE_TYPE (divlhs)))
+	      && single_imm_use (cast_lhs, &use, &cur_use_stmt))
+	    {
+	      cast_stmt = NULL;
+	      divlhs = cast_lhs;
+	    }
+	  else
+	    return 0;
+	}
     }
   if (gimple_code (cur_use_stmt) == GIMPLE_COND)
     {
@@ -4390,6 +4405,16 @@ match_arith_overflow (gimple_stmt_iterat
 	  gimple_stmt_iterator gsi2 = gsi_for_stmt (orig_use_stmt);
 	  maybe_optimize_guarding_check (mul_stmts, use_stmt, orig_use_stmt,
 					 cfg_changed);
+	  use_operand_p use;
+	  gimple *cast_stmt;
+	  if (single_imm_use (gimple_assign_lhs (orig_use_stmt), &use,
+			      &cast_stmt)
+	      && gimple_assign_cast_p (cast_stmt))
+	    {
+	      gimple_stmt_iterator gsi3 = gsi_for_stmt (cast_stmt);
+	      gsi_remove (&gsi3, true);
+	      release_ssa_name (gimple_assign_lhs (cast_stmt));
+	    }
 	  gsi_remove (&gsi2, true);
 	  release_ssa_name (gimple_assign_lhs (orig_use_stmt));
 	}
--- gcc/testsuite/gcc.target/i386/pr105776.c.jj	2023-05-18 15:57:15.570218802 +0200
+++ gcc/testsuite/gcc.target/i386/pr105776.c	2023-05-18 15:56:55.273506918 +0200
@@ -0,0 +1,43 @@
+/* PR tree-optimization/105776 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized -masm=att" } */
+/* { dg-final { scan-tree-dump-times " = \.MUL_OVERFLOW " 5 "optimized" } } */
+/* { dg-final { scan-assembler-times "\timull\t" 5 } } */
+/* { dg-final { scan-assembler-times "\tsetno\t" 5 } } */
+
+int
+foo (unsigned x, unsigned y)
+{
+  unsigned int r = x * y;
+  return !x || ((int) r / (int) x) == (int) y;
+}
+
+int
+bar (unsigned x, unsigned y)
+{
+  return !x || ((int) (x * y) / (int) x) == (int) y;
+}
+
+int
+baz (unsigned x, unsigned y)
+{
+  if (x == 0)
+    return 1;
+  return ((int) (x * y) / (int) x) == y;
+}
+
+int
+qux (unsigned x, unsigned y, unsigned *z)
+{
+  unsigned int r = x * y;
+  *z = r;
+  return !x || ((int) r / (int) x) == (int) y;
+}
+
+int
+corge (unsigned x, unsigned y, unsigned *z)
+{
+  unsigned int r = x * y;
+  *z = r;
+  return !x || ((int) r / (int) x) == y;
+}

	Jakub


^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: [PATCH] tree-ssa-math-opts: Pattern recognize some further hand written forms of signed __builtin_mul_overflow{,_p} [PR105776]
  2023-05-19  8:06 [PATCH] tree-ssa-math-opts: Pattern recognize some further hand written forms of signed __builtin_mul_overflow{,_p} [PR105776] Jakub Jelinek
@ 2023-05-19 10:43 ` Richard Biener
  0 siblings, 0 replies; 2+ messages in thread
From: Richard Biener @ 2023-05-19 10:43 UTC (permalink / raw)
  To: Jakub Jelinek; +Cc: gcc-patches



> Am 19.05.2023 um 10:06 schrieb Jakub Jelinek <jakub@redhat.com>:
> 
> Hi!
> 
> In the pattern recognition of signed __builtin_mul_overflow{,_p} we
> check for result of unsigned division (which follows unsigned
> multiplication) being equality compared against one of the multiplication's
> argument (the one not used in the division) and check for the comparison
> to be done against same precision cast of the argument (because
> division's result is unsigned and the argument is signed).
> But as shown in this PR, one can write it equally as comparison done in
> the signed type, i.e. compare division's result cast to corresponding
> signed type against the argument.
> 
> The following patch handles even those cases.
> 
> Bootstrapped/regtested on x86_64-linux, i686-linux, aarch64-linux and
> powerpc64le-linux, ok for trunk?

Ok.

Richard 

> 2023-05-19  Jakub Jelinek  <jakub@redhat.com>
> 
>    PR tree-optimization/105776
>    * tree-ssa-math-opts.cc (arith_overflow_check_p): If cast_stmt is
>    non-NULL, allow division statement to have a cast as single imm use
>    rather than comparison/condition.
>    (match_arith_overflow): In that case remove the cast stmt in addition
>    to the division statement.
> 
>    * gcc.target/i386/pr105776.c: New test.
> 
> --- gcc/tree-ssa-math-opts.cc.jj    2023-05-18 14:57:13.216409685 +0200
> +++ gcc/tree-ssa-math-opts.cc    2023-05-18 15:45:34.077177053 +0200
> @@ -3802,6 +3802,21 @@ arith_overflow_check_p (gimple *stmt, gi
>       use_operand_p use;
>       if (!single_imm_use (divlhs, &use, &cur_use_stmt))
>    return 0;
> +      if (cast_stmt && gimple_assign_cast_p (cur_use_stmt))
> +    {
> +      tree cast_lhs = gimple_assign_lhs (cur_use_stmt);
> +      if (INTEGRAL_TYPE_P (TREE_TYPE (cast_lhs))
> +          && TYPE_UNSIGNED (TREE_TYPE (cast_lhs))
> +          && (TYPE_PRECISION (TREE_TYPE (cast_lhs))
> +          == TYPE_PRECISION (TREE_TYPE (divlhs)))
> +          && single_imm_use (cast_lhs, &use, &cur_use_stmt))
> +        {
> +          cast_stmt = NULL;
> +          divlhs = cast_lhs;
> +        }
> +      else
> +        return 0;
> +    }
>     }
>   if (gimple_code (cur_use_stmt) == GIMPLE_COND)
>     {
> @@ -4390,6 +4405,16 @@ match_arith_overflow (gimple_stmt_iterat
>      gimple_stmt_iterator gsi2 = gsi_for_stmt (orig_use_stmt);
>      maybe_optimize_guarding_check (mul_stmts, use_stmt, orig_use_stmt,
>                     cfg_changed);
> +      use_operand_p use;
> +      gimple *cast_stmt;
> +      if (single_imm_use (gimple_assign_lhs (orig_use_stmt), &use,
> +                  &cast_stmt)
> +          && gimple_assign_cast_p (cast_stmt))
> +        {
> +          gimple_stmt_iterator gsi3 = gsi_for_stmt (cast_stmt);
> +          gsi_remove (&gsi3, true);
> +          release_ssa_name (gimple_assign_lhs (cast_stmt));
> +        }
>      gsi_remove (&gsi2, true);
>      release_ssa_name (gimple_assign_lhs (orig_use_stmt));
>    }
> --- gcc/testsuite/gcc.target/i386/pr105776.c.jj    2023-05-18 15:57:15.570218802 +0200
> +++ gcc/testsuite/gcc.target/i386/pr105776.c    2023-05-18 15:56:55.273506918 +0200
> @@ -0,0 +1,43 @@
> +/* PR tree-optimization/105776 */
> +/* { dg-do compile } */
> +/* { dg-options "-O2 -fdump-tree-optimized -masm=att" } */
> +/* { dg-final { scan-tree-dump-times " = \.MUL_OVERFLOW " 5 "optimized" } } */
> +/* { dg-final { scan-assembler-times "\timull\t" 5 } } */
> +/* { dg-final { scan-assembler-times "\tsetno\t" 5 } } */
> +
> +int
> +foo (unsigned x, unsigned y)
> +{
> +  unsigned int r = x * y;
> +  return !x || ((int) r / (int) x) == (int) y;
> +}
> +
> +int
> +bar (unsigned x, unsigned y)
> +{
> +  return !x || ((int) (x * y) / (int) x) == (int) y;
> +}
> +
> +int
> +baz (unsigned x, unsigned y)
> +{
> +  if (x == 0)
> +    return 1;
> +  return ((int) (x * y) / (int) x) == y;
> +}
> +
> +int
> +qux (unsigned x, unsigned y, unsigned *z)
> +{
> +  unsigned int r = x * y;
> +  *z = r;
> +  return !x || ((int) r / (int) x) == (int) y;
> +}
> +
> +int
> +corge (unsigned x, unsigned y, unsigned *z)
> +{
> +  unsigned int r = x * y;
> +  *z = r;
> +  return !x || ((int) r / (int) x) == y;
> +}
> 
>    Jakub
> 

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2023-05-19 10:44 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-05-19  8:06 [PATCH] tree-ssa-math-opts: Pattern recognize some further hand written forms of signed __builtin_mul_overflow{,_p} [PR105776] Jakub Jelinek
2023-05-19 10:43 ` Richard Biener

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).