This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH][RFC][rtlanal] Fix rtl-optimization/71295


Hi all,

The ICE in this PR occurs when initialising the reginfo for the ira_costs for an instruction of the form:
(insn 6 15 16 2 (set (subreg:V2DI (reg/v:EI 111 [ b ]) 0)
        (const_vector:V2DI [
                (const_int 1 [0x1])
                (const_int 1 [0x1])
            ])) mycrash.c:10 861 {*neon_movv2di}
     (nil))

we're talking about (subreg:V2DI (reg/v:EI 111 [ b ]) 0).
EImode is a 24 byte arm-specific integer mode used to represent 3 D-registers.

record_subregs_of_mode in reginfo.c analyses not just the subreg at offset 0 as requested
but also the adjacent V2DI subreg i.e. at offset 16. However, there cannot be a second V2DI 16-byte
subreg because EImode is only 24 bytes wide, so we get an ICE in subreg_get_info to that effect.

I'm not familiar with the processes in that part of the code but my suspicion is that we should be
rejecting that invalid subreg somewhere and this patch does that in subreg_get_info a few lines before
the triggering assert. It rejects the subreg by setting info->representable_p to false.

This fixes the ICE for me on ARM (reproducible at -O3) and doesn't show any regressions on aarch64 and x86_64.

Is this the right way to go around fixing this?

Thanks,
Kyrill

2016-05-31  Kyrylo Tkachov  <kyrylo.tkachov@arm.com>

    PR rtl-optimization/71295
    * rtlanal.c (subreg_get_info): If taking a subreg at the requested
    offset would go over the size of the inner mode reject it.

2016-05-31  Kyrylo Tkachov  <kyrylo.tkachov@arm.com>

    PR rtl-optimization/71295
    * gcc.c-torture/compile/pr71295.c: New test.
diff --git a/gcc/rtlanal.c b/gcc/rtlanal.c
index bfefd968b47c530c77c50d72ce42f4a6d4955ea4..6ab96889408bc09815f5490532657ffcecf5c52e 100644
--- a/gcc/rtlanal.c
+++ b/gcc/rtlanal.c
@@ -3657,6 +3657,16 @@ subreg_get_info (unsigned int xregno, machine_mode xmode,
 	  info->offset = offset / regsize_xmode;
 	  return;
 	}
+      /* It's not valid to extract a subreg of mode YMODE at OFFSET that
+	 would go outside of XMODE.  */
+      if (!rknown
+	  && GET_MODE_SIZE (ymode) + offset > GET_MODE_SIZE (xmode))
+	{
+	  info->representable_p = false;
+	  info->nregs = nregs_ymode;
+	  info->offset = offset / regsize_xmode;
+	  return;
+	}
       /* Quick exit for the simple and common case of extracting whole
 	 subregisters from a multiregister value.  */
       /* ??? It would be better to integrate this into the code below,
diff --git a/gcc/testsuite/gcc.c-torture/compile/pr71295.c b/gcc/testsuite/gcc.c-torture/compile/pr71295.c
new file mode 100644
index 0000000000000000000000000000000000000000..d2ec852fd08b307da50bfd993a6c43d42f303037
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/compile/pr71295.c
@@ -0,0 +1,12 @@
+extern void fn2 (long long);
+int a;
+
+void
+fn1 ()
+{
+  long long b[3];
+  a = 0;
+  for (; a < 3; a++)
+    b[a] = 1;
+  fn2 (b[1]);
+}

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]