regmove.c (discover_flags_reg, [...]): Delete.
2009-02-25 Paolo Bonzini <bonzini@gnu.org> * regmove.c (discover_flags_reg, flags_set_1, mark_flags_life_zones, flags_set_1_rtx, flags_set_1_set): Delete. (regmove_optimize): Do not call mark_flags_life_zones. From-SVN: r144425
This commit is contained in:
parent
6d2538f5f9
commit
c8a05f7c57
@ -1,3 +1,9 @@
|
||||
2009-02-25 Paolo Bonzini <bonzini@gnu.org>
|
||||
|
||||
* regmove.c (discover_flags_reg, flags_set_1, mark_flags_life_zones,
|
||||
flags_set_1_rtx, flags_set_1_set): Delete.
|
||||
(regmove_optimize): Do not call mark_flags_life_zones.
|
||||
|
||||
2009-02-24 Julian Brown <julian@codesourcery.com>
|
||||
|
||||
PR target/35965
|
||||
|
173
gcc/regmove.c
173
gcc/regmove.c
@ -58,10 +58,6 @@ struct match {
|
||||
int early_clobber[MAX_RECOG_OPERANDS];
|
||||
};
|
||||
|
||||
static rtx discover_flags_reg (void);
|
||||
static void mark_flags_life_zones (rtx);
|
||||
static void flags_set_1 (rtx, const_rtx, void *);
|
||||
|
||||
static int find_matches (rtx, struct match *);
|
||||
static int regclass_compatible_p (int, int);
|
||||
static int fixup_match_2 (rtx, rtx, rtx, rtx);
|
||||
@ -79,171 +75,6 @@ regclass_compatible_p (int class0, int class1)
|
||||
}
|
||||
|
||||
|
||||
/* Determine if the pattern generated by add_optab has a clobber,
|
||||
such as might be issued for a flags hard register. To make the
|
||||
code elsewhere simpler, we handle cc0 in this same framework.
|
||||
|
||||
Return the register if one was discovered. Return NULL_RTX if
|
||||
if no flags were found. Return pc_rtx if we got confused. */
|
||||
|
||||
static rtx
|
||||
discover_flags_reg (void)
|
||||
{
|
||||
rtx tmp;
|
||||
tmp = gen_rtx_REG (word_mode, 10000);
|
||||
tmp = gen_add3_insn (tmp, tmp, const2_rtx);
|
||||
|
||||
/* If we get something that isn't a simple set, or a
|
||||
[(set ..) (clobber ..)], this whole function will go wrong. */
|
||||
if (GET_CODE (tmp) == SET)
|
||||
return NULL_RTX;
|
||||
else if (GET_CODE (tmp) == PARALLEL)
|
||||
{
|
||||
int found;
|
||||
|
||||
if (XVECLEN (tmp, 0) != 2)
|
||||
return pc_rtx;
|
||||
tmp = XVECEXP (tmp, 0, 1);
|
||||
if (GET_CODE (tmp) != CLOBBER)
|
||||
return pc_rtx;
|
||||
tmp = XEXP (tmp, 0);
|
||||
|
||||
/* Don't do anything foolish if the md wanted to clobber a
|
||||
scratch or something. We only care about hard regs.
|
||||
Moreover we don't like the notion of subregs of hard regs. */
|
||||
if (GET_CODE (tmp) == SUBREG
|
||||
&& REG_P (SUBREG_REG (tmp))
|
||||
&& REGNO (SUBREG_REG (tmp)) < FIRST_PSEUDO_REGISTER)
|
||||
return pc_rtx;
|
||||
found = (REG_P (tmp) && REGNO (tmp) < FIRST_PSEUDO_REGISTER);
|
||||
|
||||
return (found ? tmp : NULL_RTX);
|
||||
}
|
||||
|
||||
return pc_rtx;
|
||||
}
|
||||
|
||||
/* It is a tedious task identifying when the flags register is live and
|
||||
when it is safe to optimize. Since we process the instruction stream
|
||||
multiple times, locate and record these live zones by marking the
|
||||
mode of the instructions --
|
||||
|
||||
QImode is used on the instruction at which the flags becomes live.
|
||||
|
||||
HImode is used within the range (exclusive) that the flags are
|
||||
live. Thus the user of the flags is not marked.
|
||||
|
||||
All other instructions are cleared to VOIDmode. */
|
||||
|
||||
/* Used to communicate with flags_set_1. */
|
||||
static rtx flags_set_1_rtx;
|
||||
static int flags_set_1_set;
|
||||
|
||||
static void
|
||||
mark_flags_life_zones (rtx flags)
|
||||
{
|
||||
int flags_regno;
|
||||
int flags_nregs;
|
||||
basic_block block;
|
||||
|
||||
#ifdef HAVE_cc0
|
||||
/* If we found a flags register on a cc0 host, bail. */
|
||||
if (flags == NULL_RTX)
|
||||
flags = cc0_rtx;
|
||||
else if (flags != cc0_rtx)
|
||||
flags = pc_rtx;
|
||||
#endif
|
||||
|
||||
/* Simple cases first: if no flags, clear all modes. If confusing,
|
||||
mark the entire function as being in a flags shadow. */
|
||||
if (flags == NULL_RTX || flags == pc_rtx)
|
||||
{
|
||||
enum machine_mode mode = (flags ? HImode : VOIDmode);
|
||||
rtx insn;
|
||||
for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
|
||||
PUT_MODE (insn, mode);
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef HAVE_cc0
|
||||
flags_regno = -1;
|
||||
flags_nregs = 1;
|
||||
#else
|
||||
flags_regno = REGNO (flags);
|
||||
flags_nregs = hard_regno_nregs[flags_regno][GET_MODE (flags)];
|
||||
#endif
|
||||
flags_set_1_rtx = flags;
|
||||
|
||||
/* Process each basic block. */
|
||||
FOR_EACH_BB_REVERSE (block)
|
||||
{
|
||||
rtx insn, end;
|
||||
int live;
|
||||
|
||||
insn = BB_HEAD (block);
|
||||
end = BB_END (block);
|
||||
|
||||
/* Look out for the (unlikely) case of flags being live across
|
||||
basic block boundaries. */
|
||||
live = 0;
|
||||
#ifndef HAVE_cc0
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < flags_nregs; ++i)
|
||||
live |= REGNO_REG_SET_P (df_get_live_in (block), flags_regno + i);
|
||||
}
|
||||
#endif
|
||||
|
||||
while (1)
|
||||
{
|
||||
/* Process liveness in reverse order of importance --
|
||||
alive, death, birth. This lets more important info
|
||||
overwrite the mode of lesser info. */
|
||||
|
||||
if (INSN_P (insn))
|
||||
{
|
||||
#ifdef HAVE_cc0
|
||||
/* In the cc0 case, death is not marked in reg notes,
|
||||
but is instead the mere use of cc0 when it is alive. */
|
||||
if (live && reg_mentioned_p (cc0_rtx, PATTERN (insn)))
|
||||
live = 0;
|
||||
#else
|
||||
/* In the hard reg case, we watch death notes. */
|
||||
if (live && find_regno_note (insn, REG_DEAD, flags_regno))
|
||||
live = 0;
|
||||
#endif
|
||||
PUT_MODE (insn, (live ? HImode : VOIDmode));
|
||||
|
||||
/* In either case, birth is denoted simply by its presence
|
||||
as the destination of a set. */
|
||||
flags_set_1_set = 0;
|
||||
note_stores (PATTERN (insn), flags_set_1, NULL);
|
||||
if (flags_set_1_set)
|
||||
{
|
||||
live = 1;
|
||||
PUT_MODE (insn, QImode);
|
||||
}
|
||||
}
|
||||
else
|
||||
PUT_MODE (insn, (live ? HImode : VOIDmode));
|
||||
|
||||
if (insn == end)
|
||||
break;
|
||||
insn = NEXT_INSN (insn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* A subroutine of mark_flags_life_zones, called through note_stores. */
|
||||
|
||||
static void
|
||||
flags_set_1 (rtx x, const_rtx pat, void *data ATTRIBUTE_UNUSED)
|
||||
{
|
||||
if (GET_CODE (pat) == SET
|
||||
&& reg_overlap_mentioned_p (x, flags_set_1_rtx))
|
||||
flags_set_1_set = 1;
|
||||
}
|
||||
|
||||
#ifdef AUTO_INC_DEC
|
||||
|
||||
/* Find the place in the rtx X where REG is used as a memory address.
|
||||
@ -1077,10 +908,6 @@ regmove_optimize (rtx f, int nregs)
|
||||
regstat_init_n_sets_and_refs ();
|
||||
regstat_compute_ri ();
|
||||
|
||||
/* Find out where a potential flags register is live, and so that we
|
||||
can suppress some optimizations in those zones. */
|
||||
mark_flags_life_zones (discover_flags_reg ());
|
||||
|
||||
regno_src_regno = XNEWVEC (int, nregs);
|
||||
for (i = nregs; --i >= 0; )
|
||||
regno_src_regno[i] = -1;
|
||||
|
Loading…
Reference in New Issue
Block a user