https://gcc.gnu.org/g:b07f8a301158e53717b8688cc8ea430b6f02574c
commit r15-3087-gb07f8a301158e53717b8688cc8ea430b6f02574c Author: Andrew Pinski <quic_apin...@quicinc.com> Date: Wed Aug 21 17:41:38 2024 -0700 fold: Fix `a * 1j` if a has side effects [PR116454] 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. PR middle-end/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> Diff: --- 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(-) diff --git a/gcc/fold-const.cc b/gcc/fold-const.cc index 8908e7381e72..ccc499af6617 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 000000000000..6210dcce4a42 --- /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 000000000000..a1e1604e6169 --- /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 (); +}