From 4164b2fb1628493c3b529b1e9ee045a504f44a0e Mon Sep 17 00:00:00 2001 From: Paul Brook Date: Wed, 3 Aug 2005 13:07:31 +0000 Subject: [PATCH] combine.c (can_change_dest_mode): New function. 2005-08-03 Paul Brook * combine.c (can_change_dest_mode): New function. (try_combine, simplify_set): Use it. From-SVN: r102686 --- gcc/ChangeLog | 5 +++++ gcc/combine.c | 62 +++++++++++++++++++++++++++++++-------------------- 2 files changed, 43 insertions(+), 24 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 6656cad3a86..fb1cf3fd7cc 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,8 @@ +2005-08-03 Paul Brook + + * combine.c (can_change_dest_mode): New function. + (try_combine, simplify_set): Use it. + 2005-08-03 Eric Botcazou * config/ia64/hpux.h (MEMBER_TYPE_FORCES_BLK): Only force diff --git a/gcc/combine.c b/gcc/combine.c index bbd6c0953c3..d5be605751a 100644 --- a/gcc/combine.c +++ b/gcc/combine.c @@ -1666,6 +1666,29 @@ adjust_for_new_dest (rtx insn) distribute_links (gen_rtx_INSN_LIST (VOIDmode, insn, NULL_RTX)); } +/* Return TRUE if combine can reuse reg X in mode MODE. + ADDED_SETS is nonzero if the original set is still required. */ +static bool +can_change_dest_mode (rtx x, int added_sets, enum machine_mode mode) +{ + unsigned int regno; + + if (!REG_P(x)) + return false; + + regno = REGNO (x); + /* Allow hard registers if the new mode is legal, and occupies no more + registers than the old mode. */ + if (regno < FIRST_PSEUDO_REGISTER) + return (HARD_REGNO_MODE_OK (regno, mode) + && (hard_regno_nregs[regno][GET_MODE (x)] + >= hard_regno_nregs[regno][mode])); + + /* Or a pseudo that is only used once. */ + return (REG_N_SETS (regno) == 1 && !added_sets + && !REG_USERVAR_P (x)); +} + /* Try to combine the insns I1 and I2 into I3. Here I1 and I2 appear earlier than I3. I1 can be zero; then we combine just I2 into I3. @@ -2117,13 +2140,12 @@ try_combine (rtx i3, rtx i2, rtx i1, int *new_direct_jump_p) i2src, const0_rtx)) != GET_MODE (SET_DEST (newpat)))) { - unsigned int regno = REGNO (SET_DEST (newpat)); - rtx new_dest = gen_rtx_REG (compare_mode, regno); - - if (regno < FIRST_PSEUDO_REGISTER - || (REG_N_SETS (regno) == 1 && ! added_sets_2 - && ! REG_USERVAR_P (SET_DEST (newpat)))) + if (can_change_dest_mode(SET_DEST (newpat), added_sets_2, + compare_mode)) { + unsigned int regno = REGNO (SET_DEST (newpat)); + rtx new_dest = gen_rtx_REG (compare_mode, regno); + if (regno >= FIRST_PSEUDO_REGISTER) SUBST (regno_reg_rtx[regno], new_dest); @@ -2356,14 +2378,12 @@ try_combine (rtx i3, rtx i2, rtx i1, int *new_direct_jump_p) if (m_split == 0 && ! reg_overlap_mentioned_p (ni2dest, newpat)) { + enum machine_mode new_mode = GET_MODE (SET_DEST (newpat)); /* If I2DEST is a hard register or the only use of a pseudo, we can change its mode. */ - if (GET_MODE (SET_DEST (newpat)) != GET_MODE (i2dest) - && GET_MODE (SET_DEST (newpat)) != VOIDmode - && REG_P (i2dest) - && (REGNO (i2dest) < FIRST_PSEUDO_REGISTER - || (REG_N_SETS (REGNO (i2dest)) == 1 && ! added_sets_2 - && ! REG_USERVAR_P (i2dest)))) + if (new_mode != GET_MODE (i2dest) + && new_mode != VOIDmode + && can_change_dest_mode (i2dest, added_sets_2, new_mode)) ni2dest = gen_rtx_REG (GET_MODE (SET_DEST (newpat)), REGNO (i2dest)); @@ -2471,13 +2491,8 @@ try_combine (rtx i3, rtx i2, rtx i1, int *new_direct_jump_p) isn't valid for it, or change the number of registers. */ && (GET_MODE (*split) == GET_MODE (i2dest) || GET_MODE (*split) == VOIDmode - || (REGNO (i2dest) < FIRST_PSEUDO_REGISTER - && HARD_REGNO_MODE_OK (REGNO (i2dest), GET_MODE (*split)) - && (hard_regno_nregs[REGNO (i2dest)][GET_MODE (i2dest)] - == hard_regno_nregs[REGNO (i2dest)][GET_MODE (*split)])) - || (REGNO (i2dest) >= FIRST_PSEUDO_REGISTER - && REG_N_SETS (REGNO (i2dest)) == 1 && ! added_sets_2 - && ! REG_USERVAR_P (i2dest))) + || can_change_dest_mode (i2dest, added_sets_2, + GET_MODE (*split))) && (next_real_insn (i2) == i3 || ! use_crosses_set_p (*split, INSN_CUID (i2))) /* We can't overwrite I2DEST if its value is still used by @@ -5282,12 +5297,11 @@ simplify_set (rtx x) which case we can safely change its mode. */ if (compare_mode != GET_MODE (dest)) { - unsigned int regno = REGNO (dest); - rtx new_dest = gen_rtx_REG (compare_mode, regno); - - if (regno < FIRST_PSEUDO_REGISTER - || (REG_N_SETS (regno) == 1 && ! REG_USERVAR_P (dest))) + if (can_change_dest_mode (dest, 0, compare_mode)) { + unsigned int regno = REGNO (dest); + rtx new_dest = gen_rtx_REG (compare_mode, regno); + if (regno >= FIRST_PSEUDO_REGISTER) SUBST (regno_reg_rtx[regno], new_dest); -- 2.30.2