Commit abcb0cdc by Ian Lance Taylor Committed by Kenneth Zadeck

combine.c (struct undo): Remove is_int.

2006-01-11  Ian Lance Taylor <ian@airs.com>

	* combine.c (struct undo): Remove is_int.  Enumify types of undos.
	Allow undoing set of machine mode.
	(do_SUBST): Use enums instead of is_int.
	(do_SUBST_MODE): New function.
	(SUBST_MODE): New macro.
	(try_combine): Use SUBST_MODE/PUT_MODE instead of generating a new
	reg and trying to replace reg_regno_rtx with a new register.
	(undo_all): Use new enums, handle undoing a PUT_MODE change.
	(simplify_set): Use SUBST_MODE.
	(distribute_notes): Remove code that tried to update reg notes
	for regno_reg_rtx changes.

From-SVN: r109579
parent bc23502b
2006-01-11 Ian Lance Taylor <ian@airs.com>
* combine.c (struct undo): Remove is_int. Enumify types of undos.
Allow undoing set of machine mode.
(do_SUBST): Use enums instead of is_int.
(do_SUBST_MODE): New function.
(SUBST_MODE): New macro.
(try_combine): Use SUBST_MODE/PUT_MODE instead of generating a new
reg and trying to replace reg_regno_rtx with a new register.
(undo_all): Use new enums, handle undoing a PUT_MODE change.
(simplify_set): Use SUBST_MODE.
(distribute_notes): Remove code that tried to update reg notes
for regno_reg_rtx changes.
2006-01-11 Paolo Bonzini <bonzini@gnu.org> 2006-01-11 Paolo Bonzini <bonzini@gnu.org>
PR tree-optimization/23109 PR tree-optimization/23109
......
...@@ -321,15 +321,14 @@ static int nonzero_sign_valid; ...@@ -321,15 +321,14 @@ static int nonzero_sign_valid;
/* Record one modification to rtl structure /* Record one modification to rtl structure
to be undone by storing old_contents into *where. to be undone by storing old_contents into *where. */
is_int is 1 if the contents are an int. */
struct undo struct undo
{ {
struct undo *next; struct undo *next;
int is_int; enum { UNDO_RTX, UNDO_INT, UNDO_MODE } kind;
union {rtx r; int i;} old_contents; union { rtx r; int i; enum machine_mode m; } old_contents;
union {rtx *r; int *i;} where; union { rtx *r; int *i; } where;
}; };
/* Record a bunch of changes to be undone, up to MAX_UNDO of them. /* Record a bunch of changes to be undone, up to MAX_UNDO of them.
...@@ -490,7 +489,7 @@ do_SUBST (rtx *into, rtx newval) ...@@ -490,7 +489,7 @@ do_SUBST (rtx *into, rtx newval)
else else
buf = xmalloc (sizeof (struct undo)); buf = xmalloc (sizeof (struct undo));
buf->is_int = 0; buf->kind = UNDO_RTX;
buf->where.r = into; buf->where.r = into;
buf->old_contents.r = oldval; buf->old_contents.r = oldval;
*into = newval; *into = newval;
...@@ -518,7 +517,7 @@ do_SUBST_INT (int *into, int newval) ...@@ -518,7 +517,7 @@ do_SUBST_INT (int *into, int newval)
else else
buf = xmalloc (sizeof (struct undo)); buf = xmalloc (sizeof (struct undo));
buf->is_int = 1; buf->kind = UNDO_INT;
buf->where.i = into; buf->where.i = into;
buf->old_contents.i = oldval; buf->old_contents.i = oldval;
*into = newval; *into = newval;
...@@ -527,6 +526,35 @@ do_SUBST_INT (int *into, int newval) ...@@ -527,6 +526,35 @@ do_SUBST_INT (int *into, int newval)
} }
#define SUBST_INT(INTO, NEWVAL) do_SUBST_INT(&(INTO), (NEWVAL)) #define SUBST_INT(INTO, NEWVAL) do_SUBST_INT(&(INTO), (NEWVAL))
/* Similar to SUBST, but just substitute the mode. This is used when
changing the mode of a pseudo-register, so that any other
references to the entry in the regno_reg_rtx array will change as
well. */
static void
do_SUBST_MODE (rtx *into, enum machine_mode newval)
{
struct undo *buf;
enum machine_mode oldval = GET_MODE (*into);
if (oldval == newval)
return;
if (undobuf.frees)
buf = undobuf.frees, undobuf.frees = buf->next;
else
buf = xmalloc (sizeof (struct undo));
buf->kind = UNDO_MODE;
buf->where.r = into;
buf->old_contents.m = oldval;
PUT_MODE (*into, newval);
buf->next = undobuf.undos, undobuf.undos = buf;
}
#define SUBST_MODE(INTO, NEWVAL) do_SUBST_MODE(&(INTO), (NEWVAL))
/* Subroutine of try_combine. Determine whether the combine replacement /* Subroutine of try_combine. Determine whether the combine replacement
patterns NEWPAT and NEWI2PAT are cheaper according to insn_rtx_cost patterns NEWPAT and NEWI2PAT are cheaper according to insn_rtx_cost
...@@ -2224,10 +2252,15 @@ try_combine (rtx i3, rtx i2, rtx i1, int *new_direct_jump_p) ...@@ -2224,10 +2252,15 @@ try_combine (rtx i3, rtx i2, rtx i1, int *new_direct_jump_p)
compare_mode)) compare_mode))
{ {
unsigned int regno = REGNO (SET_DEST (newpat)); unsigned int regno = REGNO (SET_DEST (newpat));
rtx new_dest = gen_rtx_REG (compare_mode, regno); rtx new_dest;
if (regno >= FIRST_PSEUDO_REGISTER) if (regno < FIRST_PSEUDO_REGISTER)
SUBST (regno_reg_rtx[regno], new_dest); new_dest = gen_rtx_REG (compare_mode, regno);
else
{
SUBST_MODE (regno_reg_rtx[regno], compare_mode);
new_dest = regno_reg_rtx[regno];
}
SUBST (SET_DEST (newpat), new_dest); SUBST (SET_DEST (newpat), new_dest);
SUBST (XEXP (*cc_use, 0), new_dest); SUBST (XEXP (*cc_use, 0), new_dest);
...@@ -2476,7 +2509,6 @@ try_combine (rtx i3, rtx i2, rtx i1, int *new_direct_jump_p) ...@@ -2476,7 +2509,6 @@ try_combine (rtx i3, rtx i2, rtx i1, int *new_direct_jump_p)
&& asm_noperands (newpat) < 0) && asm_noperands (newpat) < 0)
{ {
rtx m_split, *split; rtx m_split, *split;
rtx ni2dest = i2dest;
/* See if the MD file can split NEWPAT. If it can't, see if letting it /* See if the MD file can split NEWPAT. If it can't, see if letting it
use I2DEST as a scratch register will help. In the latter case, use I2DEST as a scratch register will help. In the latter case,
...@@ -2491,34 +2523,55 @@ try_combine (rtx i3, rtx i2, rtx i1, int *new_direct_jump_p) ...@@ -2491,34 +2523,55 @@ try_combine (rtx i3, rtx i2, rtx i1, int *new_direct_jump_p)
possible to try that as a scratch reg. This would require adding possible to try that as a scratch reg. This would require adding
more code to make it work though. */ more code to make it work though. */
if (m_split == 0 && ! reg_overlap_mentioned_p (ni2dest, newpat)) if (m_split == 0 && ! reg_overlap_mentioned_p (i2dest, newpat))
{ {
enum machine_mode new_mode = GET_MODE (SET_DEST (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 (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));
/* First try to split using the original register as a
scratch register. */
m_split = split_insns (gen_rtx_PARALLEL m_split = split_insns (gen_rtx_PARALLEL
(VOIDmode, (VOIDmode,
gen_rtvec (2, newpat, gen_rtvec (2, newpat,
gen_rtx_CLOBBER (VOIDmode, gen_rtx_CLOBBER (VOIDmode,
ni2dest))), i2dest))),
i3); i3);
/* If the split with the mode-changed register didn't work, try
the original register. */ /* If that didn't work, try changing the mode of I2DEST if
if (! m_split && ni2dest != i2dest) we can. */
if (m_split == 0
&& new_mode != GET_MODE (i2dest)
&& new_mode != VOIDmode
&& can_change_dest_mode (i2dest, added_sets_2, new_mode))
{ {
ni2dest = i2dest; enum machine_mode old_mode = GET_MODE (i2dest);
rtx ni2dest;
if (REGNO (i2dest) < FIRST_PSEUDO_REGISTER)
ni2dest = gen_rtx_REG (new_mode, REGNO (i2dest));
else
{
SUBST_MODE (regno_reg_rtx[REGNO (i2dest)], new_mode);
ni2dest = regno_reg_rtx[REGNO (i2dest)];
}
m_split = split_insns (gen_rtx_PARALLEL m_split = split_insns (gen_rtx_PARALLEL
(VOIDmode, (VOIDmode,
gen_rtvec (2, newpat, gen_rtvec (2, newpat,
gen_rtx_CLOBBER (VOIDmode, gen_rtx_CLOBBER (VOIDmode,
i2dest))), ni2dest))),
i3); i3);
if (m_split == 0
&& REGNO (i2dest) >= FIRST_PSEUDO_REGISTER)
{
struct undo *buf;
PUT_MODE (regno_reg_rtx[REGNO (i2dest)], old_mode);
buf = undobuf.undos;
undobuf.undos = buf->next;
buf->next = undobuf.frees;
undobuf.frees = buf;
}
} }
} }
...@@ -2547,13 +2600,6 @@ try_combine (rtx i3, rtx i2, rtx i1, int *new_direct_jump_p) ...@@ -2547,13 +2600,6 @@ try_combine (rtx i3, rtx i2, rtx i1, int *new_direct_jump_p)
i3set = single_set (NEXT_INSN (m_split)); i3set = single_set (NEXT_INSN (m_split));
i2set = single_set (m_split); i2set = single_set (m_split);
/* In case we changed the mode of I2DEST, replace it in the
pseudo-register table here. We can't do it above in case this
code doesn't get executed and we do a split the other way. */
if (REGNO (i2dest) >= FIRST_PSEUDO_REGISTER)
SUBST (regno_reg_rtx[REGNO (i2dest)], ni2dest);
i2_code_number = recog_for_combine (&newi2pat, i2, &new_i2_notes); i2_code_number = recog_for_combine (&newi2pat, i2, &new_i2_notes);
/* If I2 or I3 has multiple SETs, we won't know how to track /* If I2 or I3 has multiple SETs, we won't know how to track
...@@ -2624,10 +2670,13 @@ try_combine (rtx i3, rtx i2, rtx i1, int *new_direct_jump_p) ...@@ -2624,10 +2670,13 @@ try_combine (rtx i3, rtx i2, rtx i1, int *new_direct_jump_p)
validated that we can do this. */ validated that we can do this. */
if (GET_MODE (i2dest) != split_mode && split_mode != VOIDmode) if (GET_MODE (i2dest) != split_mode && split_mode != VOIDmode)
{ {
newdest = gen_rtx_REG (split_mode, REGNO (i2dest)); if (REGNO (i2dest) < FIRST_PSEUDO_REGISTER)
newdest = gen_rtx_REG (split_mode, REGNO (i2dest));
if (REGNO (i2dest) >= FIRST_PSEUDO_REGISTER) else
SUBST (regno_reg_rtx[REGNO (i2dest)], newdest); {
SUBST_MODE (regno_reg_rtx[REGNO (i2dest)], split_mode);
newdest = regno_reg_rtx[REGNO (i2dest)];
}
} }
/* If *SPLIT is a (mult FOO (const_int pow2)), convert it to /* If *SPLIT is a (mult FOO (const_int pow2)), convert it to
...@@ -3328,10 +3377,20 @@ undo_all (void) ...@@ -3328,10 +3377,20 @@ undo_all (void)
for (undo = undobuf.undos; undo; undo = next) for (undo = undobuf.undos; undo; undo = next)
{ {
next = undo->next; next = undo->next;
if (undo->is_int) switch (undo->kind)
*undo->where.i = undo->old_contents.i; {
else case UNDO_RTX:
*undo->where.r = undo->old_contents.r; *undo->where.r = undo->old_contents.r;
break;
case UNDO_INT:
*undo->where.i = undo->old_contents.i;
break;
case UNDO_MODE:
PUT_MODE (*undo->where.r, undo->old_contents.m);
break;
default:
gcc_unreachable ();
}
undo->next = undobuf.frees; undo->next = undobuf.frees;
undobuf.frees = undo; undobuf.frees = undo;
...@@ -5160,10 +5219,15 @@ simplify_set (rtx x) ...@@ -5160,10 +5219,15 @@ simplify_set (rtx x)
if (can_change_dest_mode (dest, 0, compare_mode)) if (can_change_dest_mode (dest, 0, compare_mode))
{ {
unsigned int regno = REGNO (dest); unsigned int regno = REGNO (dest);
rtx new_dest = gen_rtx_REG (compare_mode, regno); rtx new_dest;
if (regno >= FIRST_PSEUDO_REGISTER) if (regno < FIRST_PSEUDO_REGISTER)
SUBST (regno_reg_rtx[regno], new_dest); new_dest = gen_rtx_REG (compare_mode, regno);
else
{
SUBST_MODE (regno_reg_rtx[regno], compare_mode);
new_dest = regno_reg_rtx[regno];
}
SUBST (SET_DEST (x), new_dest); SUBST (SET_DEST (x), new_dest);
SUBST (XEXP (*cc_use, 0), new_dest); SUBST (XEXP (*cc_use, 0), new_dest);
...@@ -11709,12 +11773,6 @@ distribute_notes (rtx notes, rtx from_insn, rtx i3, rtx i2, rtx elim_i2, ...@@ -11709,12 +11773,6 @@ distribute_notes (rtx notes, rtx from_insn, rtx i3, rtx i2, rtx elim_i2,
{ {
rtx place = 0, place2 = 0; rtx place = 0, place2 = 0;
/* If this NOTE references a pseudo register, ensure it references
the latest copy of that register. */
if (XEXP (note, 0) && REG_P (XEXP (note, 0))
&& REGNO (XEXP (note, 0)) >= FIRST_PSEUDO_REGISTER)
XEXP (note, 0) = regno_reg_rtx[REGNO (XEXP (note, 0))];
next_note = XEXP (note, 1); next_note = XEXP (note, 1);
switch (REG_NOTE_KIND (note)) switch (REG_NOTE_KIND (note))
{ {
......
/* This test exposed a bug in combine where it was improperly changing
the mode of a register. The bug appeared to be latent until web
was moved after combine. This is the reduced test that fails
by crashing in reload. */
typedef struct cpp_reader cpp_reader;
typedef struct cpp_string cpp_string;
struct cpp_string
{
unsigned int len;
const unsigned char *text;
};
struct cpp_callbacks
{
void (*ident) (cpp_reader *, unsigned int, const cpp_string *);
};
static void cb_ident (cpp_reader *, unsigned int, const cpp_string *);
init_c_lex (void)
{
struct cpp_callbacks *cb;
cb->ident = cb_ident;
}
cb_ident (cpp_reader * pfile __attribute__ ((__unused__)), unsigned int
line
__attribute__ ((__unused__)), const cpp_string * str
__attribute__ ((__unused__)))
{
{
cpp_string cstr = {
};
if (cpp_interpret_string (pfile, str, 1, &cstr, 0))
{
}
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment