Hi! On the following testcase, we have: (debug_insn 45 20 22 2 (var_location:DI D#4 (const_int 0 [0])) -1 (nil)) (debug_insn 22 45 26 2 (debug_marker) "pr90733.c":16:3 -1 (nil)) (debug_insn 26 22 27 2 (var_location:CSI D#3 (subreg:CSI (debug_expr:DI D#4) 0)) "pr90733.c":16:10 -1 (nil)) (debug_insn 27 26 28 2 (var_location:SI D#2 (subreg:SI (debug_expr:CSI D#3) 0)) -1 (nil)) (debug_insn 28 27 29 2 (var_location:SI D#1 (clobber (const_int 0 [0]))) -1 (nil)) (debug_insn 29 28 30 2 (var_location:CSI y$c (concat:CSI (debug_expr:SI D#2) (debug_expr:SI D#1))) -1 (nil)) During var-tracking, we first propagate D#4 into the D#3 definition and want to simplify_subreg (CSImode, const0_rtx, DImode, 0), unfortunately that fails due to simplify_immed_subreg having: /* We have no way to represent a complex constant at the rtl level. */ if (COMPLEX_MODE_P (outermode)) return NULL_RTX; and later on the following vt_expand_loc_callback hunk forces the creation of SUBREG, as in debug insns/notes we generally can handle even invalid SUBREGs. We can't handle SUBREGs where the inner mode is VOIDmode though, we don't really know what to do that. On this testcase, after creating such a subreg we simplify another subreg, the SImode lowpart subreg of that and that is where we ICE, because subreg of a subreg is invalid, we try harder to simplify it and don't know what to do with the VOIDmode in there.
The following patch fixes the ICE by refusing to create raw SUBREGs with VOIDmode inner mode. Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? Incrementally, we could into vt_expand_loc_callback add some special case for complex modes, if simplify_subreg fails, for complex mode try to simplify a lowpart and highpart subregs for the scalar halves and if both succeed, create a CONCAT of those, which is what we use in debug insns (as debug_insn 29 above shows). Another option might be to use CONST_VECTORs even with complex modes, but I guess that would be a far bigger change. 2019-06-05 Jakub Jelinek <ja...@redhat.com> PR debug/90733 * var-tracking.c (vt_expand_loc_callback): Don't create raw subregs with VOIDmode inner operands. * gcc.dg/pr90733.c: New test. --- gcc/var-tracking.c.jj 2019-05-03 15:22:07.000000000 +0200 +++ gcc/var-tracking.c 2019-06-04 16:32:35.014561614 +0200 @@ -8491,7 +8491,7 @@ vt_expand_loc_callback (rtx x, bitmap re /* Invalid SUBREGs are ok in debug info. ??? We could try alternate expansions for the VALUE as well. */ - if (!result) + if (!result && GET_MODE (subreg) != VOIDmode) result = gen_rtx_raw_SUBREG (GET_MODE (x), subreg, SUBREG_BYTE (x)); return result; --- gcc/testsuite/gcc.dg/pr90733.c.jj 2019-06-04 16:43:21.749638839 +0200 +++ gcc/testsuite/gcc.dg/pr90733.c 2019-06-04 16:42:53.181083748 +0200 @@ -0,0 +1,22 @@ +/* PR debug/90733 */ +/* { dg-do compile } */ +/* { dg-options "-g -O2 -w" } */ + +struct S { unsigned a : 1; }; +union U { struct S b; _Complex unsigned c; }; + +union U +foo (union U d) +{ + union U e = d; + return e; +} + +int +bar (void) +{ + union U x, y; + x.c = x.b.a; + y = foo (x); + return x.c != y.c; +} Jakub