re PR tree-optimization/83609 (ICE in read_complex_part at gcc/expr.c:3202)
authorJakub Jelinek <jakub@redhat.com>
Sun, 31 Dec 2017 23:51:14 +0000 (00:51 +0100)
committerJakub Jelinek <jakub@gcc.gnu.org>
Sun, 31 Dec 2017 23:51:14 +0000 (00:51 +0100)
PR middle-end/83609
* expr.c (expand_assignment): Fix up a typo in simplify_gen_subreg
last argument when extracting from CONCAT.  If either from_real or
from_imag is NULL, use expansion through memory.  If result is not
a CONCAT and simplify_gen_subreg fails, try to simplify_gen_subreg
the parts directly to inner mode, if even that fails, use expansion
through memory.

* gcc.dg/pr83609.c: New test.
* g++.dg/opt/pr83609.C: New test.

From-SVN: r256052

gcc/ChangeLog
gcc/expr.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/opt/pr83609.C [new file with mode: 0644]
gcc/testsuite/gcc.dg/pr83609.c [new file with mode: 0644]

index 548bb17c10c57bde4fae005e10287f2f8c81c6c1..98073e8f9427382001a339ea5c142e125c6e1a35 100644 (file)
@@ -1,5 +1,13 @@
 2018-01-01  Jakub Jelinek  <jakub@redhat.com>
 
+       PR middle-end/83609
+       * expr.c (expand_assignment): Fix up a typo in simplify_gen_subreg
+       last argument when extracting from CONCAT.  If either from_real or
+       from_imag is NULL, use expansion through memory.  If result is not
+       a CONCAT and simplify_gen_subreg fails, try to simplify_gen_subreg
+       the parts directly to inner mode, if even that fails, use expansion
+       through memory.
+
        PR middle-end/83623
        * expmed.c (expand_shift_1): For 2-byte rotates by BITS_PER_UNIT,
        check for bswap in mode rather than HImode and use that in expand_unop
index 4e7349e649488dcf3f763e230996663afd0d0b21..0a735762e51da8e873e03f337d3090a56bb171ce 100644 (file)
@@ -5158,7 +5158,9 @@ expand_assignment (tree to, tree from, bool nontemporal)
                                           from_mode, 0);
                  rtx from_imag
                    = simplify_gen_subreg (to_mode, XEXP (result, 1),
-                                          from_mode, 1);
+                                          from_mode, 0);
+                 if (!from_real || !from_imag)
+                   goto concat_store_slow;
                  emit_move_insn (XEXP (to_rtx, 0), from_real);
                  emit_move_insn (XEXP (to_rtx, 1), from_imag);
                }
@@ -5167,14 +5169,35 @@ expand_assignment (tree to, tree from, bool nontemporal)
                  rtx from_rtx
                    = simplify_gen_subreg (GET_MODE (to_rtx), result,
                                           TYPE_MODE (TREE_TYPE (from)), 0);
-                 emit_move_insn (XEXP (to_rtx, 0),
-                                 read_complex_part (from_rtx, false));
-                 emit_move_insn (XEXP (to_rtx, 1),
-                                 read_complex_part (from_rtx, true));
+                 if (from_rtx)
+                   {
+                     emit_move_insn (XEXP (to_rtx, 0),
+                                     read_complex_part (from_rtx, false));
+                     emit_move_insn (XEXP (to_rtx, 1),
+                                     read_complex_part (from_rtx, true));
+                   }
+                 else
+                   {
+                     machine_mode to_mode
+                       = GET_MODE_INNER (GET_MODE (to_rtx));
+                     rtx from_real
+                       = simplify_gen_subreg (to_mode, result,
+                                              TYPE_MODE (TREE_TYPE (from)),
+                                              0);
+                     rtx from_imag
+                       = simplify_gen_subreg (to_mode, result,
+                                              TYPE_MODE (TREE_TYPE (from)),
+                                              GET_MODE_SIZE (to_mode));
+                     if (!from_real || !from_imag)
+                       goto concat_store_slow;
+                     emit_move_insn (XEXP (to_rtx, 0), from_real);
+                     emit_move_insn (XEXP (to_rtx, 1), from_imag);
+                   }
                }
            }
          else
            {
+           concat_store_slow:;
              rtx temp = assign_stack_temp (GET_MODE (to_rtx),
                                            GET_MODE_SIZE (GET_MODE (to_rtx)));
              write_complex_part (temp, XEXP (to_rtx, 0), false);
index f89ae2e549673d595f21a4f5f574c58442112322..59c9543de5fa26a822e7e647381d3cbcfd372fbf 100644 (file)
@@ -1,5 +1,9 @@
 2018-01-01  Jakub Jelinek  <jakub@redhat.com>
 
+       PR middle-end/83609
+       * gcc.dg/pr83609.c: New test.
+       * g++.dg/opt/pr83609.C: New test.
+
        PR middle-end/83623
        * gcc.dg/pr83623.c: New test.
 
diff --git a/gcc/testsuite/g++.dg/opt/pr83609.C b/gcc/testsuite/g++.dg/opt/pr83609.C
new file mode 100644 (file)
index 0000000..a43d291
--- /dev/null
@@ -0,0 +1,28 @@
+// PR middle-end/83609
+// { dg-do compile }
+// { dg-options "-O2 -fno-tree-forwprop" }
+
+template <typename> class B;
+template <> struct B<float>
+{
+  float foo () { return __real__ b; }
+  _Complex float b;
+};
+
+void bar (int);
+
+template <class T>
+void
+baz ()
+{
+  B<T> h;
+  T *a = (T *) &h;
+  a[0] = a[1] = 6;
+  h.foo () ? void () : bar (7);
+}
+
+int
+main ()
+{
+  baz<float> ();
+}
diff --git a/gcc/testsuite/gcc.dg/pr83609.c b/gcc/testsuite/gcc.dg/pr83609.c
new file mode 100644 (file)
index 0000000..eac11fc
--- /dev/null
@@ -0,0 +1,29 @@
+/* PR middle-end/83609 */
+/* { dg-do run } */
+/* { dg-options "-O2 -fno-tree-forwprop -fno-tree-ccp -fno-tree-fre -fno-tree-pre -fno-code-hoisting" } */
+
+#if __SIZEOF_LONG_LONG__ == 2 * __SIZEOF_FLOAT__
+_Complex float
+foo (void)
+{
+  _Complex float c;
+  *((unsigned long long *)&c) = 0x123456789abcdef0ULL;
+  return c;
+}
+
+int
+main ()
+{
+  union { _Complex float c; unsigned long long l; } u;
+  u.c = foo ();
+  if (u.l != 0x123456789abcdef0ULL)
+    __builtin_abort ();
+  return 0;
+}
+#else
+int
+main ()
+{
+  return 0;
+}
+#endif