From patchwork Wed Oct 6 14:25:54 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: Fix PR rtl-optimization/45394 From: Eric Botcazou X-Patchwork-Id: 66932 Message-Id: <201010061625.54111.ebotcazou@adacore.com> To: gcc-patches@gcc.gnu.org Date: Wed, 6 Oct 2010 16:25:54 +0200 This is an ICE building the Ada run time library on s390-linux, a problem in the handling of debug insns in the combiner. The pass generally combines insns downwards, i.e with 2 insns + 1 debug insn: insn i2 debug_insn insn i3 is turned into: INSN_DELETED adjusted debug_insn insn i2 combined into i3 There is one special case where i3 is first combined into i2 (or rather, i2 is partially combined into i3 and the result is combined into the rest of i2) and then i3 replaced with the result. In this case, the debug insn is adjusted backwards and moved past i3: INSN_DELETED insn i3 combined into i2 backwards adjusted debug_insn This breaks when i3 must end a basic block, e.g. when it contains a mem store and -fnon-call-exceptions is in effect. I don't think there is a real need for this backwards adjustment + move of the debug insn in this special case. The kind of i2 insns involved (PARALLEL with multiple sets/clobbers) won't very likely generate debug insns for anything but the main set and it will be taken care of by regular adjustment; moreover this special case of combining only occurs if i2 and i3 are adjacent. Therefore the patch gets rid of the special treatment for debug insns in this special case, i.e. they are now adjusted and not moved like in all the other cases, thus simplifying a little the code. This in turn exposes the need for the small adjustment in eliminate_regs_1. Tested on i586-suse-linux and ia64-suse-linux, applied on the mainline. 2010-10-06 Eric Botcazou PR rtl-optimization/45394 * combine.c (cleanup_auto_inc_dec): Remove AFTER parameter and adjust. (struct rtx_subst_pair): Remove AFTER field. (propagate_for_debug_subst): Adjust call to cleanup_auto_inc_dec. (propagate_for_debug): Remove MOVE parameter and adjust. (try_combine): In the special case where I2 is a PARALLEL, combine only destinations of SETs and set I2SRC to the I2 source. Adjust calls to propagate_for_debug throughout. * reload1.c (eliminate_regs_1) : Do not abort for debug insns. 2010-10-06 Eric Botcazou * gnat.dg/opt6.ad[sb]: New test. Index: combine.c =================================================================== --- combine.c (revision 164827) +++ combine.c (working copy) @@ -2292,13 +2292,11 @@ reg_subword_p (rtx x, rtx reg) } #ifdef AUTO_INC_DEC -/* Replace auto-increment addressing modes with explicit operations to - access the same addresses without modifying the corresponding - registers. If AFTER holds, SRC is meant to be reused after the - side effect, otherwise it is to be reused before that. */ +/* Replace auto-increment addressing modes with explicit operations to access + the same addresses without modifying the corresponding registers. */ static rtx -cleanup_auto_inc_dec (rtx src, bool after, enum machine_mode mem_mode) +cleanup_auto_inc_dec (rtx src, enum machine_mode mem_mode) { rtx x = src; const RTX_CODE code = GET_CODE (x); @@ -2335,26 +2333,20 @@ cleanup_auto_inc_dec (rtx src, bool afte case PRE_INC: case PRE_DEC: - case POST_INC: - case POST_DEC: gcc_assert (mem_mode != VOIDmode && mem_mode != BLKmode); - if (after == (code == PRE_INC || code == PRE_DEC)) - x = cleanup_auto_inc_dec (XEXP (x, 0), after, mem_mode); - else - x = gen_rtx_PLUS (GET_MODE (x), - cleanup_auto_inc_dec (XEXP (x, 0), after, mem_mode), - GEN_INT ((code == PRE_INC || code == POST_INC) - ? GET_MODE_SIZE (mem_mode) - : -GET_MODE_SIZE (mem_mode))); - return x; + return gen_rtx_PLUS (GET_MODE (x), + cleanup_auto_inc_dec (XEXP (x, 0), mem_mode), + GEN_INT (code == PRE_INC + ? GET_MODE_SIZE (mem_mode) + : -GET_MODE_SIZE (mem_mode))); + case POST_INC: + case POST_DEC: case PRE_MODIFY: case POST_MODIFY: - if (after == (code == PRE_MODIFY)) - x = XEXP (x, 0); - else - x = XEXP (x, 1); - return cleanup_auto_inc_dec (x, after, mem_mode); + return cleanup_auto_inc_dec (code == PRE_MODIFY + ? XEXP (x, 1) : XEXP (x, 0), + mem_mode); default: break; @@ -2377,14 +2369,14 @@ cleanup_auto_inc_dec (rtx src, bool afte fmt = GET_RTX_FORMAT (code); for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--) if (fmt[i] == 'e') - XEXP (x, i) = cleanup_auto_inc_dec (XEXP (x, i), after, mem_mode); + XEXP (x, i) = cleanup_auto_inc_dec (XEXP (x, i), mem_mode); else if (fmt[i] == 'E' || fmt[i] == 'V') { int j; XVEC (x, i) = rtvec_alloc (XVECLEN (x, i)); for (j = 0; j < XVECLEN (x, i); j++) XVECEXP (x, i, j) - = cleanup_auto_inc_dec (XVECEXP (src, i, j), after, mem_mode); + = cleanup_auto_inc_dec (XVECEXP (src, i, j), mem_mode); } return x; @@ -2397,7 +2389,6 @@ struct rtx_subst_pair { rtx to; bool adjusted; - bool after; }; /* DATA points to an rtx_subst_pair. Return the value that should be @@ -2414,7 +2405,7 @@ propagate_for_debug_subst (rtx from, con { pair->adjusted = true; #ifdef AUTO_INC_DEC - pair->to = cleanup_auto_inc_dec (pair->to, pair->after, VOIDmode); + pair->to = cleanup_auto_inc_dec (pair->to, VOIDmode); #else pair->to = copy_rtx (pair->to); #endif @@ -2424,19 +2415,17 @@ propagate_for_debug_subst (rtx from, con return copy_rtx (pair->to); } -/* Replace occurrences of DEST with SRC in DEBUG_INSNs between INSN - and LAST. If MOVE holds, debug insns must also be moved past - LAST. */ +/* Replace all the occurrences of DEST with SRC in DEBUG_INSNs between INSN + and LAST. */ static void -propagate_for_debug (rtx insn, rtx last, rtx dest, rtx src, bool move) +propagate_for_debug (rtx insn, rtx last, rtx dest, rtx src) { - rtx next, move_pos = move ? last : NULL_RTX, loc; + rtx next, loc; struct rtx_subst_pair p; p.to = src; p.adjusted = false; - p.after = move; next = NEXT_INSN (insn); while (next != last) @@ -2450,14 +2439,7 @@ propagate_for_debug (rtx insn, rtx last, if (loc == INSN_VAR_LOCATION_LOC (insn)) continue; INSN_VAR_LOCATION_LOC (insn) = loc; - if (move_pos) - { - remove_insn (insn); - PREV_INSN (insn) = NEXT_INSN (insn) = NULL_RTX; - move_pos = emit_debug_insn_after (insn, move_pos); - } - else - df_insn_rescan (insn); + df_insn_rescan (insn); } } } @@ -2619,7 +2601,7 @@ try_combine (rtx i3, rtx i2, rtx i1, rtx added_links_insn = 0; - /* First check for one important special-case that the code below will + /* First check for one important special case that the code below will not handle. Namely, the case where I1 is zero, I2 is a PARALLEL and I3 is a SET whose SET_SRC is a SET_DEST in I2. In that case, we may be able to replace that destination with the destination of I3. @@ -2627,8 +2609,8 @@ try_combine (rtx i3, rtx i2, rtx i1, rtx remainder into a structure, in which case we want to do the computation directly into the structure to avoid register-register copies. - Note that this case handles both multiple sets in I2 and also - cases where I2 has a number of CLOBBER or PARALLELs. + Note that this case handles both multiple sets in I2 and also cases + where I2 has a number of CLOBBERs inside the PARALLEL. We make very conservative checks below and only try to handle the most common cases of this. For example, we only handle the case @@ -2672,8 +2654,7 @@ try_combine (rtx i3, rtx i2, rtx i1, rtx if (i == XVECLEN (p2, 0)) for (i = 0; i < XVECLEN (p2, 0); i++) - if ((GET_CODE (XVECEXP (p2, 0, i)) == SET - || GET_CODE (XVECEXP (p2, 0, i)) == CLOBBER) + if (GET_CODE (XVECEXP (p2, 0, i)) == SET && SET_DEST (XVECEXP (p2, 0, i)) == SET_SRC (PATTERN (i3))) { combine_merges++; @@ -2682,16 +2663,14 @@ try_combine (rtx i3, rtx i2, rtx i1, rtx subst_low_luid = DF_INSN_LUID (i2); added_sets_2 = added_sets_1 = added_sets_0 = 0; - i2src = SET_DEST (PATTERN (i3)); - i2dest = SET_SRC (PATTERN (i3)); + i2src = SET_SRC (XVECEXP (p2, 0, i)); + i2dest = SET_DEST (XVECEXP (p2, 0, i)); i2dest_killed = dead_or_set_p (i2, i2dest); /* Replace the dest in I2 with our dest and make the resulting - insn the new pattern for I3. Then skip to where we - validate the pattern. Everything was set up above. */ - SUBST (SET_DEST (XVECEXP (p2, 0, i)), - SET_DEST (PATTERN (i3))); - + insn the new pattern for I3. Then skip to where we validate + the pattern. Everything was set up above. */ + SUBST (SET_DEST (XVECEXP (p2, 0, i)), SET_DEST (PATTERN (i3))); newpat = p2; i3_subst_into_i2 = 1; goto validate_replacement; @@ -3820,7 +3799,7 @@ try_combine (rtx i3, rtx i2, rtx i1, rtx i2src while its original mode is temporarily restored, and then clear i2scratch so that we don't do it again later. */ - propagate_for_debug (i2, i3, reg, i2src, false); + propagate_for_debug (i2, i3, reg, i2src); i2scratch = false; /* Put back the new mode. */ adjust_reg_mode (reg, new_mode); @@ -3851,11 +3830,10 @@ try_combine (rtx i3, rtx i2, rtx i1, rtx with this copy we have created; then, replace the copy with the SUBREG of the original shared reg, once again changed to the new mode. */ - propagate_for_debug (first, last, reg, tempreg, false); + propagate_for_debug (first, last, reg, tempreg); adjust_reg_mode (reg, new_mode); propagate_for_debug (first, last, tempreg, - lowpart_subreg (old_mode, reg, new_mode), - false); + lowpart_subreg (old_mode, reg, new_mode)); } } } @@ -4069,14 +4047,14 @@ try_combine (rtx i3, rtx i2, rtx i1, rtx if (newi2pat) { if (MAY_HAVE_DEBUG_INSNS && i2scratch) - propagate_for_debug (i2, i3, i2dest, i2src, false); + propagate_for_debug (i2, i3, i2dest, i2src); INSN_CODE (i2) = i2_code_number; PATTERN (i2) = newi2pat; } else { if (MAY_HAVE_DEBUG_INSNS && i2src) - propagate_for_debug (i2, i3, i2dest, i2src, i3_subst_into_i2); + propagate_for_debug (i2, i3, i2dest, i2src); SET_INSN_DELETED (i2); } @@ -4085,7 +4063,7 @@ try_combine (rtx i3, rtx i2, rtx i1, rtx LOG_LINKS (i1) = 0; REG_NOTES (i1) = 0; if (MAY_HAVE_DEBUG_INSNS) - propagate_for_debug (i1, i3, i1dest, i1src, false); + propagate_for_debug (i1, i3, i1dest, i1src); SET_INSN_DELETED (i1); } @@ -4094,7 +4072,7 @@ try_combine (rtx i3, rtx i2, rtx i1, rtx LOG_LINKS (i0) = 0; REG_NOTES (i0) = 0; if (MAY_HAVE_DEBUG_INSNS) - propagate_for_debug (i0, i3, i0dest, i0src, false); + propagate_for_debug (i0, i3, i0dest, i0src); SET_INSN_DELETED (i0); } Index: reload1.c =================================================================== --- reload1.c (revision 164827) +++ reload1.c (working copy) @@ -2882,10 +2882,10 @@ eliminate_regs_1 (rtx x, enum machine_mo return x; case CLOBBER: + case ASM_OPERANDS: gcc_assert (insn && DEBUG_INSN_P (insn)); break; - case ASM_OPERANDS: case SET: gcc_unreachable ();