This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[patch] Invalid register modes in combine
- From: Paul Brook <paul at codesourcery dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Wed, 3 Aug 2005 04:44:03 +0100
- Subject: [patch] Invalid register modes in combine
When backporting the combine patch mentioned below to csl-arm-branch I noticed
that there are a few other places in combine.c where we do the same
transformation, but do not do all the validity checks.
http://gcc.gnu.org/ml/gcc-patches/2005-03/msg01842.html
2005-03-19 Bernd Schmidt <bernd.schmidt@analog.com>
* combine.c (try_combine): When changing the mode of a hard reg, make
sure that doing so is valid.
The attached patch moves this logic into a common function.
Tested with cross to arm-none-eabi bootstrapped i686-linux.
Ok?
Paul
2005-08-03 Paul Brook <paul@codesourcery.com>
* combine.c (can_change_dest_mode): New function.
(try_combine, simplify_set): Use it.
:ADDPATCH middle-end (combine):
Index: gcc/combine.c
===================================================================
RCS file: /var/cvsroot/gcc-cvs/gcc/gcc/combine.c,v
retrieving revision 1.499
diff -u -p -r1.499 combine.c
--- gcc/combine.c 22 Jul 2005 11:55:42 -0000 1.499
+++ gcc/combine.c 3 Aug 2005 02:30:41 -0000
@@ -1663,6 +1663,27 @@ 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;
+
+ /* The mode can be changed for hard registers and single use pseudos. */
+ if (!REG_P(x))
+ return false;
+
+ regno = REGNO (x);
+ if (regno < FIRST_PSEUDO_REGISTER)
+ return (HARD_REGNO_MODE_OK (regno, mode)
+ && (hard_regno_nregs[regno][GET_MODE (x)]
+ == hard_regno_nregs[regno][mode]));
+
+ 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,9 +2138,8 @@ try_combine (rtx i3, rtx i2, rtx i1, int
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))
{
if (regno >= FIRST_PSEUDO_REGISTER)
SUBST (regno_reg_rtx[regno], new_dest);
@@ -2353,14 +2373,12 @@ try_combine (rtx i3, rtx i2, rtx i1, int
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));
@@ -2468,13 +2486,8 @@ try_combine (rtx i3, rtx i2, rtx i1, int
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,8 +5295,7 @@ simplify_set (rtx x)
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))
{
if (regno >= FIRST_PSEUDO_REGISTER)
SUBST (regno_reg_rtx[regno], new_dest);