Hi!

The following testcase ICEs on aarch64.  The problem is that
op0 is (subreg:HI (reg:HF ...) 0) and because we can't create a SUBREG of a
SUBREG and aarch64 doesn't have HImode insv, only SImode insv,
store_bit_field_using_insv tries to create (subreg:SI (reg:HF ...) 0)
which is not valid for the target and so gen_rtx_SUBREG ICEs.

The following patch fixes it by punting if the to be created SUBREG
doesn't validate, callers of store_bit_field_using_insv can handle
the fallback.

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

2021-03-03  Jakub Jelinek  <ja...@redhat.com>

        PR middle-end/93235
        * expmed.c (store_bit_field_using_insv): Return false of xop0 is a
        SUBREG and a SUBREG to op_mode can't be created.

        * gcc.target/aarch64/pr93235.c: New test.

--- gcc/expmed.c.jj     2021-01-04 10:25:39.761223316 +0100
+++ gcc/expmed.c        2021-03-03 19:22:41.249301351 +0100
@@ -629,9 +629,16 @@ store_bit_field_using_insv (const extrac
       /* If xop0 is a register, we need it in OP_MODE
         to make it acceptable to the format of insv.  */
       if (GET_CODE (xop0) == SUBREG)
-       /* We can't just change the mode, because this might clobber op0,
-          and we will need the original value of op0 if insv fails.  */
-       xop0 = gen_rtx_SUBREG (op_mode, SUBREG_REG (xop0), SUBREG_BYTE (xop0));
+       {
+         /* If such a SUBREG can't be created, give up.  */
+         if (!validate_subreg (op_mode, GET_MODE (SUBREG_REG (xop0)),
+                               SUBREG_REG (xop0), SUBREG_BYTE (xop0)))
+           return false;
+         /* We can't just change the mode, because this might clobber op0,
+            and we will need the original value of op0 if insv fails.  */
+         xop0 = gen_rtx_SUBREG (op_mode, SUBREG_REG (xop0),
+                                SUBREG_BYTE (xop0));
+       }
       if (REG_P (xop0) && GET_MODE (xop0) != op_mode)
        xop0 = gen_lowpart_SUBREG (op_mode, xop0);
     }
--- gcc/testsuite/gcc.target/aarch64/pr93235.c.jj       2021-03-03 
19:28:47.743300618 +0100
+++ gcc/testsuite/gcc.target/aarch64/pr93235.c  2021-03-03 19:28:27.247524328 
+0100
@@ -0,0 +1,12 @@
+/* PR middle-end/93235 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -fno-strict-aliasing" } */
+
+struct sfp16 { __fp16 f; };
+struct sfp16
+foo (short x)
+{
+  struct sfp16 a;
+  *(short*)&a.f = x;
+  return a;
+}

        Jakub

Reply via email to