diff options
author | Paul Brook <paul@codesourcery.com> | 2005-08-03 13:07:31 +0000 |
---|---|---|
committer | Paul Brook <pbrook@gcc.gnu.org> | 2005-08-03 13:07:31 +0000 |
commit | 4164b2fb1628493c3b529b1e9ee045a504f44a0e (patch) | |
tree | d1aef2b428dd98d35f2e112642326ee2c613aac1 /gcc | |
parent | 4e2b3c877d1882f2df53f6c467628e4887564467 (diff) | |
download | gcc-4164b2fb1628493c3b529b1e9ee045a504f44a0e.zip gcc-4164b2fb1628493c3b529b1e9ee045a504f44a0e.tar.gz gcc-4164b2fb1628493c3b529b1e9ee045a504f44a0e.tar.bz2 |
combine.c (can_change_dest_mode): New function.
2005-08-03 Paul Brook <paul@codesourcery.com>
* combine.c (can_change_dest_mode): New function.
(try_combine, simplify_set): Use it.
From-SVN: r102686
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/combine.c | 62 |
2 files changed, 43 insertions, 24 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 6656cad..fb1cf3f 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,8 @@ +2005-08-03 Paul Brook <paul@codesourcery.com> + + * combine.c (can_change_dest_mode): New function. + (try_combine, simplify_set): Use it. + 2005-08-03 Eric Botcazou <ebotcazou@adacore.com> * config/ia64/hpux.h (MEMBER_TYPE_FORCES_BLK): Only force diff --git a/gcc/combine.c b/gcc/combine.c index bbd6c09..d5be605 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); |