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.tkac...@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.tkac...@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]); +}