https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80125
Jakub Jelinek <jakub at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |jakub at gcc dot gnu.org --- Comment #1 from Jakub Jelinek <jakub at gcc dot gnu.org> --- We trigger: /* If I2 is a PARALLEL of two SETs of REGs (and perhaps some CLOBBERs), make those two SETs separate I1 and I2 insns, and make an I0 that is the original I1. */ if (!HAVE_cc0 && i0 == 0 && is_parallel_of_n_reg_sets (PATTERN (i2), 2) && can_split_parallel_of_n_reg_sets (i2, 2) && !reg_used_between_p (SET_DEST (XVECEXP (PATTERN (i2), 0, 0)), i2, i3) && !reg_used_between_p (SET_DEST (XVECEXP (PATTERN (i2), 0, 1)), i2, i3)) { /* If there is no I1, there is no I0 either. */ i0 = i1; /* We make I1 with the same INSN_UID as I2. This gives it the same DF_INSN_LUID for value tracking. Our fake I1 will never appear in the insn stream so giving it the same INSN_UID as I2 will not cause a problem. */ i1 = gen_rtx_INSN (VOIDmode, NULL, i2, BLOCK_FOR_INSN (i2), XVECEXP (PATTERN (i2), 0, 0), INSN_LOCATION (i2), -1, NULL_RTX); INSN_UID (i1) = INSN_UID (i2); SUBST (PATTERN (i2), XVECEXP (PATTERN (i2), 0, 1)); } and thus i1 really isn't in the insn stream, it only has NEXT_INSN set to i2 (so in the only case where this is passed to can_combine_p succ is that i1 and succ2 is the i2 right after it). --- combine.c.jj 2017-03-21 07:57:01.000000000 +0100 +++ combine.c 2017-03-21 09:52:50.564214916 +0100 @@ -1955,7 +1955,7 @@ can_combine_p (rtx_insn *insn, rtx_insn || (JUMP_P (i3) && find_reg_note (i3, REG_NON_LOCAL_GOTO, NULL_RTX)) /* Make sure that DEST is not used after INSN but before SUCC, or between SUCC and SUCC2. */ - || (succ && reg_used_between_p (dest, insn, succ)) + || (succ && PREV_INSN (succ) && reg_used_between_p (dest, insn, succ)) || (succ2 && reg_used_between_p (dest, succ, succ2)) /* Make sure that DEST is not used after SUCC but before I3. */ || (!all_adjacent fixes the ICE but isn't the right thing.