]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
fold: Fix `a * 1j` if a has side effects [PR116454]
authorAndrew Pinski <quic_apinski@quicinc.com>
Thu, 22 Aug 2024 00:41:38 +0000 (17:41 -0700)
committerRichard Biener <rguenth@gcc.gnu.org>
Thu, 22 Aug 2024 11:51:32 +0000 (13:51 +0200)
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_apinski@quicinc.com>
Co-Authored-By: Richard Biener <rguenther@suse.de>
gcc/fold-const.cc
gcc/testsuite/gcc.dg/torture/pr116454-1.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/torture/pr116454-2.c [new file with mode: 0644]

index 8908e7381e72cbbf4a8fd96f18cbf4436aba8441..ccc499af6617749a4b13055c85a65241e58566b9 100644 (file)
@@ -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 (file)
index 0000000..6210dcc
--- /dev/null
@@ -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 (file)
index 0000000..a1e1604
--- /dev/null
@@ -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 ();
+}