Hi!

On the following testcase we ICE in simplify_gen_subreg, when result has
BLKmode and we want to convert it to some complex mode (e.g. DCmode or
in theory XCmode or TCmode too).
Such SUBREGs are invalid, but BLKmode can only live in memory and when it
is a MEM, we don't really need to create a subreg, we can change_address
and just load it as if it is a complex MEM.

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

2019-02-20  Jakub Jelinek  <ja...@redhat.com>

        PR middle-end/89412
        * expr.c (expand_assignment): If result is a MEM, use change_address
        instead of simplify_gen_subreg.

        * gcc.c-torture/compile/pr89412.c: New test.

--- gcc/expr.c.jj       2019-02-16 12:19:37.602192262 +0100
+++ gcc/expr.c  2019-02-20 16:29:39.261497006 +0100
@@ -5211,9 +5211,13 @@ expand_assignment (tree to, tree from, b
                }
              else
                {
-                 rtx from_rtx
-                   = simplify_gen_subreg (to_mode, result,
-                                          TYPE_MODE (TREE_TYPE (from)), 0);
+                 rtx from_rtx;
+                 if (MEM_P (result))
+                   from_rtx = change_address (result, to_mode, NULL_RTX);
+                 else
+                   from_rtx
+                     = simplify_gen_subreg (to_mode, result,
+                                            TYPE_MODE (TREE_TYPE (from)), 0);
                  if (from_rtx)
                    {
                      emit_move_insn (XEXP (to_rtx, 0),
--- gcc/testsuite/gcc.c-torture/compile/pr89412.c.jj    2019-02-20 
16:30:47.722387639 +0100
+++ gcc/testsuite/gcc.c-torture/compile/pr89412.c       2019-02-20 
16:31:29.288714080 +0100
@@ -0,0 +1,16 @@
+/* PR middle-end/89412 */
+
+struct S { double a, b; } d;
+int e;
+double f;
+
+void
+foo ()
+{
+  _Complex double h;
+  while (e)
+    {
+      f = h;
+      *(struct S *) &h = d;
+    }
+}

        Jakub

Reply via email to