On Thu, Aug 22, 2024 at 1:47 PM Andrew Pinski <quic_apin...@quicinc.com> wrote:
>
> The problem here was a missing save_expr around arg0 since
> it is used twice, once in REALPART_EXPR and once in IMAGPART_EXPR.
> Thia adds the save_expr and reformats the code slightly so it is a
> little easier to understand.  It excludes the case when arg0 is
> a COMPLEX_EXPR since in that case we'll end up with the distinct
> real and imaginary parts.  This is important to retain early
> optimization in some testcases.
>
> Bootstapped and tested on x86_64-linux-gnu with no regressions, pushed.

Eh, it was me who sent this mail after 'git am' of a patch from bugzilla,
editing and testing it and then using git format-patch ...

Richard.

>         PR 116454
>
> gcc/ChangeLog:
>
>         * fold-const.cc (fold_binary_loc): Fix `a * +-1i`
>         by wrapping arg0 with save_expr when it is not COMPLEX_EXPR.
>
> gcc/testsuite/ChangeLog:
>
>         * gcc.dg/torture/pr116454-1.c: New test.
>         * gcc.dg/torture/pr116454-2.c: New test.
>
> Signed-off-by: Andrew Pinski <quic_apin...@quicinc.com>
> Co-Authored-By: Richard Biener  <rguent...@suse.de>
> ---
>  gcc/fold-const.cc                         | 32 ++++++++++++++++-------
>  gcc/testsuite/gcc.dg/torture/pr116454-1.c | 16 ++++++++++++
>  gcc/testsuite/gcc.dg/torture/pr116454-2.c | 12 +++++++++
>  3 files changed, 50 insertions(+), 10 deletions(-)
>  create mode 100644 gcc/testsuite/gcc.dg/torture/pr116454-1.c
>  create mode 100644 gcc/testsuite/gcc.dg/torture/pr116454-2.c
>
> diff --git a/gcc/fold-const.cc b/gcc/fold-const.cc
> index eeadc8db9f6..35402a59768 100644
> --- a/gcc/fold-const.cc
> +++ b/gcc/fold-const.cc
> @@ -12093,17 +12093,29 @@ fold_binary_loc (location_t loc, enum tree_code 
> code, tree type,
>             {
>               tree rtype = TREE_TYPE (TREE_TYPE (arg0));
>               if (real_onep (TREE_IMAGPART (arg1)))
> -               return
> -                 fold_build2_loc (loc, COMPLEX_EXPR, type,
> -                              negate_expr (fold_build1_loc (loc, 
> IMAGPART_EXPR,
> -                                                            rtype, arg0)),
> -                              fold_build1_loc (loc, REALPART_EXPR, rtype, 
> arg0));
> +               {
> +                 if (TREE_CODE (arg0) != COMPLEX_EXPR)
> +                   arg0 = save_expr (arg0);
> +                 tree iarg0 = fold_build1_loc (loc, IMAGPART_EXPR,
> +                                               rtype, arg0);
> +                 tree rarg0 = fold_build1_loc (loc, REALPART_EXPR,
> +                                               rtype, arg0);
> +                 return fold_build2_loc (loc, COMPLEX_EXPR, type,
> +                                         negate_expr (iarg0),
> +                                         rarg0);
> +               }
>               else if (real_minus_onep (TREE_IMAGPART (arg1)))
> -               return
> -                 fold_build2_loc (loc, COMPLEX_EXPR, type,
> -                              fold_build1_loc (loc, IMAGPART_EXPR, rtype, 
> arg0),
> -                              negate_expr (fold_build1_loc (loc, 
> REALPART_EXPR,
> -                                                            rtype, arg0)));
> +               {
> +                 if (TREE_CODE (arg0) != COMPLEX_EXPR)
> +                   arg0 = save_expr (arg0);
> +                 tree iarg0 = fold_build1_loc (loc, IMAGPART_EXPR,
> +                                               rtype, arg0);
> +                 tree rarg0 = fold_build1_loc (loc, REALPART_EXPR,
> +                                               rtype, arg0);
> +                 return fold_build2_loc (loc, COMPLEX_EXPR, type,
> +                                         iarg0,
> +                                         negate_expr (rarg0));
> +               }
>             }
>
>           /* Optimize z * conj(z) for floating point complex numbers.
> diff --git a/gcc/testsuite/gcc.dg/torture/pr116454-1.c 
> b/gcc/testsuite/gcc.dg/torture/pr116454-1.c
> new file mode 100644
> index 00000000000..6210dcce4a4
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/torture/pr116454-1.c
> @@ -0,0 +1,16 @@
> +/* { dg-do run } */
> +/* { dg-additional-options "-ffast-math" } */
> +
> +static int t = 0;
> +_Complex float f()
> +{
> +        t++;
> +        return 0;
> +}
> +int main() {
> +       t = 0;
> +       /* Would cause f() to be incorrectly invoked twice. */
> +       f() * 1j;
> +       if (t != 1)
> +          __builtin_abort();
> +}
> diff --git a/gcc/testsuite/gcc.dg/torture/pr116454-2.c 
> b/gcc/testsuite/gcc.dg/torture/pr116454-2.c
> new file mode 100644
> index 00000000000..a1e1604e616
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/torture/pr116454-2.c
> @@ -0,0 +1,12 @@
> +/* { dg-do run } */
> +/* { dg-additional-options "-ffast-math" } */
> +_Complex float arr[2];
> +
> +int main() {
> +  _Complex float *ptr;
> +  ptr = arr;
> +  *++ptr * 1j;
> +  /* ptr should only increment once, not twice. */
> +  if (ptr != arr + 1)
> +    __builtin_abort ();
> +}
> --
> 2.43.0

Reply via email to