[PATCH] tree-ssa-math-opts: Pattern recognize some further hand written forms of signed __builtin_mul_overflow{, _p} [PR105776]
Richard Biener
rguenther@suse.de
Fri May 19 10:43:50 GMT 2023
> 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
>
More information about the Gcc-patches
mailing list