On December 30, 2017 8:31:59 PM GMT+01:00, Jakub Jelinek <ja...@redhat.com> 
wrote:
>Hi!
>
>The first hunk before the if (!from...) part shows a typo I've made in
>a
>recent change, the last argument of simplify_gen_subreg is byte offset,
>and
>the subreg has same bitsize outer and inner modes, so using byte offset
>1
>makes no sense at all.
>Another issue that the testcase suffers from is that the
>simplify_gen_rtx
>(preexisting issue) can fail, and in that case trying to
>read_complex_part
>from that NULL will ICE.  The patch tries harder by trying to simplify
>the
>2 halves separately, and for all cases when simplify_gen_subreg fails
>which
>can happen because of various reasons, there is the fallback to go
>through
>memory.
>
>Bootstrapped/regtested on x86_64-linux and i686-linux, ok for
>trunk/7.3?

OK. 

Richard. 

>2017-12-30  Jakub Jelinek  <ja...@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.
>
>       * gcc.dg/pr83609.c: New test.
>       * g++.dg/opt/pr83609.C: New test.
>
>--- gcc/expr.c.jj      2017-12-21 09:43:19.797042465 +0100
>+++ gcc/expr.c 2017-12-30 13:49:19.634057445 +0100
>@@ -5158,7 +5158,9 @@ expand_assignment (tree to, tree from, b
>                                          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, b
>                 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);
>--- gcc/testsuite/gcc.dg/pr83609.c.jj  2017-12-30 13:47:49.350044674
>+0100
>+++ gcc/testsuite/gcc.dg/pr83609.c     2017-12-30 13:42:52.227002619 +0100
>@@ -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
>--- gcc/testsuite/g++.dg/opt/pr83609.C.jj      2017-12-30 13:48:18.937048860
>+0100
>+++ gcc/testsuite/g++.dg/opt/pr83609.C 2017-12-30 13:46:25.968032868
>+0100
>@@ -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> ();
>+}
>
>       Jakub

Reply via email to