From 40a8fb89a30c6b1ec9d4f541cac4318f46a581e2 Mon Sep 17 00:00:00 2001 From: ian Date: Tue, 11 Oct 2005 23:45:54 +0000 Subject: [PATCH] PR rtl-optimization/13931 * combine.c: Revert patch of 2003-05-14, and: (try_combine): Only set elim_i1 and elim_i2 if the destination is completely killed in the appropriate insn. (distribute_notes): Don't skip multiple hard register test for elim_i1 and elim_i2. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@105275 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog | 9 +++++++ gcc/combine.c | 75 +++++++++++++++++++++++++++++++++++++++++++++-------------- 2 files changed, 66 insertions(+), 18 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 9d7fc4e7a8c..8fa4b88a3af 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2005-10-11 Ian Lance Taylor + + PR rtl-optimization/13931 + * combine.c: Revert patch of 2003-05-14, and: + (try_combine): Only set elim_i1 and elim_i2 if the destination is + completely killed in the appropriate insn. + (distribute_notes): Don't skip multiple hard register test for + elim_i1 and elim_i2. + 2005-10-11 Richard Henderson PR c/24255 diff --git a/gcc/combine.c b/gcc/combine.c index 4ab0f18097e..3be34e4b44d 100644 --- a/gcc/combine.c +++ b/gcc/combine.c @@ -53,6 +53,10 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA flow.c aren't completely updated: - reg_live_length is not updated + - reg_n_refs is not adjusted in the rare case when a register is + no longer required in a computation + - there are extremely rare cases (see distribute_regnotes) when a + REG_DEAD note is lost - a LOG_LINKS entry that refers to an insn with multiple SETs may be removed because there is no way to know which register it was linking @@ -410,7 +414,7 @@ static void reg_dead_at_p_1 (rtx, rtx, void *); static int reg_dead_at_p (rtx, rtx); static void move_deaths (rtx, rtx, int, rtx, rtx *); static int reg_bitfield_target_p (rtx, rtx); -static void distribute_notes (rtx, rtx, rtx, rtx); +static void distribute_notes (rtx, rtx, rtx, rtx, rtx, rtx); static void distribute_links (rtx); static void mark_used_regs_combine (rtx); static int insn_cuid (rtx); @@ -1730,6 +1734,7 @@ try_combine (rtx i3, rtx i2, rtx i1, int *new_direct_jump_p) rtx i2pat; /* Indicates if I2DEST or I1DEST is in I2SRC or I1_SRC. */ int i2dest_in_i2src = 0, i1dest_in_i1src = 0, i2dest_in_i1src = 0; + int i2dest_killed = 0, i1dest_killed = 0; int i1_feeds_i3 = 0; /* Notes that must be added to REG_NOTES in I3 and I2. */ rtx new_i3_notes, new_i2_notes; @@ -1838,6 +1843,7 @@ try_combine (rtx i3, rtx i2, rtx i1, int *new_direct_jump_p) added_sets_2 = added_sets_1 = 0; i2dest = SET_SRC (PATTERN (i3)); + 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 @@ -1912,6 +1918,7 @@ try_combine (rtx i3, rtx i2, rtx i1, int *new_direct_jump_p) subst_low_cuid = INSN_CUID (i2); added_sets_2 = added_sets_1 = 0; i2dest = SET_DEST (temp); + i2dest_killed = dead_or_set_p (i2, i2dest); SUBST (SET_SRC (temp), immed_double_const (lo, hi, GET_MODE (SET_DEST (temp)))); @@ -1982,6 +1989,8 @@ try_combine (rtx i3, rtx i2, rtx i1, int *new_direct_jump_p) i2dest_in_i2src = reg_overlap_mentioned_p (i2dest, i2src); i1dest_in_i1src = i1 && reg_overlap_mentioned_p (i1dest, i1src); i2dest_in_i1src = i1 && reg_overlap_mentioned_p (i2dest, i1src); + i2dest_killed = dead_or_set_p (i2, i2dest); + i1dest_killed = i1 && dead_or_set_p (i1, i1dest); /* See if I1 directly feeds into I3. It does if I1DEST is not used in I2SRC. */ @@ -2737,7 +2746,7 @@ try_combine (rtx i3, rtx i2, rtx i1, int *new_direct_jump_p) REG_N_DEATHS (REGNO (XEXP (note, 0)))++; distribute_notes (new_other_notes, undobuf.other_insn, - undobuf.other_insn, NULL_RTX); + undobuf.other_insn, NULL_RTX, NULL_RTX, NULL_RTX); } #ifdef HAVE_cc0 /* If I2 is the CC0 setter and I3 is the CC0 user then check whether @@ -2812,6 +2821,17 @@ try_combine (rtx i3, rtx i2, rtx i1, int *new_direct_jump_p) rtx i3links, i2links, i1links = 0; rtx midnotes = 0; unsigned int regno; + /* Compute which registers we expect to eliminate. newi2pat may be setting + either i3dest or i2dest, so we must check it. Also, i1dest may be the + same as i3dest, in which case newi2pat may be setting i1dest. */ + rtx elim_i2 = ((newi2pat && reg_set_p (i2dest, newi2pat)) + || i2dest_in_i2src || i2dest_in_i1src + || !i2dest_killed + ? 0 : i2dest); + rtx elim_i1 = (i1 == 0 || i1dest_in_i1src + || (newi2pat && reg_set_p (i1dest, newi2pat)) + || !i1dest_killed + ? 0 : i1dest); /* Get the old REG_NOTES and LOG_LINKS from all our insns and clear them. */ @@ -2936,13 +2956,17 @@ try_combine (rtx i3, rtx i2, rtx i1, int *new_direct_jump_p) /* Distribute all the LOG_LINKS and REG_NOTES from I1, I2, and I3. */ if (i3notes) - distribute_notes (i3notes, i3, i3, newi2pat ? i2 : NULL_RTX); + distribute_notes (i3notes, i3, i3, newi2pat ? i2 : NULL_RTX, + elim_i2, elim_i1); if (i2notes) - distribute_notes (i2notes, i2, i3, newi2pat ? i2 : NULL_RTX); + distribute_notes (i2notes, i2, i3, newi2pat ? i2 : NULL_RTX, + elim_i2, elim_i1); if (i1notes) - distribute_notes (i1notes, i1, i3, newi2pat ? i2 : NULL_RTX); + distribute_notes (i1notes, i1, i3, newi2pat ? i2 : NULL_RTX, + elim_i2, elim_i1); if (midnotes) - distribute_notes (midnotes, NULL_RTX, i3, newi2pat ? i2 : NULL_RTX); + distribute_notes (midnotes, NULL_RTX, i3, newi2pat ? i2 : NULL_RTX, + elim_i2, elim_i1); /* Distribute any notes added to I2 or I3 by recog_for_combine. We know these are REG_UNUSED and want them to go to the desired insn, @@ -2955,7 +2979,7 @@ try_combine (rtx i3, rtx i2, rtx i1, int *new_direct_jump_p) if (REG_P (XEXP (temp, 0))) REG_N_DEATHS (REGNO (XEXP (temp, 0)))++; - distribute_notes (new_i2_notes, i2, i2, NULL_RTX); + distribute_notes (new_i2_notes, i2, i2, NULL_RTX, NULL_RTX, NULL_RTX); } if (new_i3_notes) @@ -2964,7 +2988,7 @@ try_combine (rtx i3, rtx i2, rtx i1, int *new_direct_jump_p) if (REG_P (XEXP (temp, 0))) REG_N_DEATHS (REGNO (XEXP (temp, 0)))++; - distribute_notes (new_i3_notes, i3, i3, NULL_RTX); + distribute_notes (new_i3_notes, i3, i3, NULL_RTX, NULL_RTX, NULL_RTX); } /* If I3DEST was used in I3SRC, it really died in I3. We may need to @@ -2982,11 +3006,12 @@ try_combine (rtx i3, rtx i2, rtx i1, int *new_direct_jump_p) if (newi2pat && reg_set_p (i3dest_killed, newi2pat)) distribute_notes (gen_rtx_EXPR_LIST (REG_DEAD, i3dest_killed, NULL_RTX), - NULL_RTX, i2, NULL_RTX); + NULL_RTX, i2, NULL_RTX, elim_i2, elim_i1); else distribute_notes (gen_rtx_EXPR_LIST (REG_DEAD, i3dest_killed, NULL_RTX), - NULL_RTX, i3, newi2pat ? i2 : NULL_RTX); + NULL_RTX, i3, newi2pat ? i2 : NULL_RTX, + elim_i2, elim_i1); } if (i2dest_in_i2src) @@ -2996,10 +3021,11 @@ try_combine (rtx i3, rtx i2, rtx i1, int *new_direct_jump_p) if (newi2pat && reg_set_p (i2dest, newi2pat)) distribute_notes (gen_rtx_EXPR_LIST (REG_DEAD, i2dest, NULL_RTX), - NULL_RTX, i2, NULL_RTX); + NULL_RTX, i2, NULL_RTX, NULL_RTX, NULL_RTX); else distribute_notes (gen_rtx_EXPR_LIST (REG_DEAD, i2dest, NULL_RTX), - NULL_RTX, i3, newi2pat ? i2 : NULL_RTX); + NULL_RTX, i3, newi2pat ? i2 : NULL_RTX, + NULL_RTX, NULL_RTX); } if (i1dest_in_i1src) @@ -3009,10 +3035,11 @@ try_combine (rtx i3, rtx i2, rtx i1, int *new_direct_jump_p) if (newi2pat && reg_set_p (i1dest, newi2pat)) distribute_notes (gen_rtx_EXPR_LIST (REG_DEAD, i1dest, NULL_RTX), - NULL_RTX, i2, NULL_RTX); + NULL_RTX, i2, NULL_RTX, NULL_RTX, NULL_RTX); else distribute_notes (gen_rtx_EXPR_LIST (REG_DEAD, i1dest, NULL_RTX), - NULL_RTX, i3, newi2pat ? i2 : NULL_RTX); + NULL_RTX, i3, newi2pat ? i2 : NULL_RTX, + NULL_RTX, NULL_RTX); } distribute_links (i3links); @@ -11906,11 +11933,16 @@ reg_bitfield_target_p (rtx x, rtx body) as appropriate. I3 and I2 are the insns resulting from the combination insns including FROM (I2 may be zero). + ELIM_I2 and ELIM_I1 are either zero or registers that we know will + not need REG_DEAD notes because they are being substituted for. This + saves searching in the most common cases. + Each note in the list is either ignored or placed on some insns, depending on the type of note. */ static void -distribute_notes (rtx notes, rtx from_insn, rtx i3, rtx i2) +distribute_notes (rtx notes, rtx from_insn, rtx i3, rtx i2, rtx elim_i2, + rtx elim_i1) { rtx note, next_note; rtx tem; @@ -12188,6 +12220,11 @@ distribute_notes (rtx notes, rtx from_insn, rtx i3, rtx i2) && reg_referenced_p (XEXP (note, 0), PATTERN (i2))) place = i2; + if (place == 0 + && (rtx_equal_p (XEXP (note, 0), elim_i2) + || rtx_equal_p (XEXP (note, 0), elim_i1))) + break; + if (place == 0) { basic_block bb = this_basic_block; @@ -12249,7 +12286,8 @@ distribute_notes (rtx notes, rtx from_insn, rtx i3, rtx i2) PATTERN (tem) = pc_rtx; REG_NOTES (tem) = NULL; - distribute_notes (old_notes, tem, tem, NULL_RTX); + distribute_notes (old_notes, tem, tem, NULL_RTX, + NULL_RTX, NULL_RTX); distribute_links (LOG_LINKS (tem)); SET_INSN_DELETED (tem); @@ -12263,7 +12301,8 @@ distribute_notes (rtx notes, rtx from_insn, rtx i3, rtx i2) REG_NOTES (cc0_setter) = NULL; distribute_notes (old_notes, cc0_setter, - cc0_setter, NULL_RTX); + cc0_setter, NULL_RTX, + NULL_RTX, NULL_RTX); distribute_links (LOG_LINKS (cc0_setter)); SET_INSN_DELETED (cc0_setter); @@ -12398,7 +12437,7 @@ distribute_notes (rtx notes, rtx from_insn, rtx i3, rtx i2) = gen_rtx_EXPR_LIST (REG_DEAD, piece, NULL_RTX); distribute_notes (new_note, place, place, - NULL_RTX); + NULL_RTX, NULL_RTX, NULL_RTX); } else if (! refers_to_regno_p (i, i + 1, PATTERN (place), 0) -- 2.11.4.GIT