/* Move registers around to reduce number of move instructions needed.
Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
- 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+ 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
This file is part of GCC.
#define STACK_GROWS_DOWNWARD 0
#endif
-static int perhaps_ends_bb_p PARAMS ((rtx));
-static int optimize_reg_copy_1 PARAMS ((rtx, rtx, rtx));
-static void optimize_reg_copy_2 PARAMS ((rtx, rtx, rtx));
-static void optimize_reg_copy_3 PARAMS ((rtx, rtx, rtx));
-static void copy_src_to_dest PARAMS ((rtx, rtx, rtx, int));
+static int perhaps_ends_bb_p (rtx);
+static int optimize_reg_copy_1 (rtx, rtx, rtx);
+static void optimize_reg_copy_2 (rtx, rtx, rtx);
+static void optimize_reg_copy_3 (rtx, rtx, rtx);
+static void copy_src_to_dest (rtx, rtx, rtx, int);
static int *regmove_bb_head;
struct match {
int early_clobber[MAX_RECOG_OPERANDS];
};
-static rtx discover_flags_reg PARAMS ((void));
-static void mark_flags_life_zones PARAMS ((rtx));
-static void flags_set_1 PARAMS ((rtx, rtx, void *));
-
-static int try_auto_increment PARAMS ((rtx, rtx, rtx, rtx, HOST_WIDE_INT, int));
-static int find_matches PARAMS ((rtx, struct match *));
-static void replace_in_call_usage PARAMS ((rtx *, unsigned int, rtx, rtx));
-static int fixup_match_1 PARAMS ((rtx, rtx, rtx, rtx, rtx, int, int, int, FILE *))
-;
-static int reg_is_remote_constant_p PARAMS ((rtx, rtx, rtx));
-static int stable_and_no_regs_but_for_p PARAMS ((rtx, rtx, rtx));
-static int regclass_compatible_p PARAMS ((int, int));
-static int replacement_quality PARAMS ((rtx));
-static int fixup_match_2 PARAMS ((rtx, rtx, rtx, rtx, FILE *));
+static rtx discover_flags_reg (void);
+static void mark_flags_life_zones (rtx);
+static void flags_set_1 (rtx, rtx, void *);
+
+static int try_auto_increment (rtx, rtx, rtx, rtx, HOST_WIDE_INT, int);
+static int find_matches (rtx, struct match *);
+static void replace_in_call_usage (rtx *, unsigned int, rtx, rtx);
+static int fixup_match_1 (rtx, rtx, rtx, rtx, rtx, int, int, int, FILE *);
+static int reg_is_remote_constant_p (rtx, rtx, rtx);
+static int stable_and_no_regs_but_for_p (rtx, rtx, rtx);
+static int regclass_compatible_p (int, int);
+static int replacement_quality (rtx);
+static int fixup_match_2 (rtx, rtx, rtx, rtx, FILE *);
/* Return nonzero if registers with CLASS1 and CLASS2 can be merged without
causing too much register allocation problems. */
static int
-regclass_compatible_p (class0, class1)
- int class0, class1;
+regclass_compatible_p (int class0, int class1)
{
return (class0 == class1
|| (reg_class_subset_p (class0, class1)
Iff INC_INSN_SET is nonzero, inc_insn has a destination different from src.
Return nonzero for success. */
static int
-try_auto_increment (insn, inc_insn, inc_insn_set, reg, increment, pre)
- rtx reg, insn, inc_insn ,inc_insn_set;
- HOST_WIDE_INT increment;
- int pre;
+try_auto_increment (rtx insn, rtx inc_insn, rtx inc_insn_set, rtx reg,
+ HOST_WIDE_INT increment, int pre)
{
enum rtx_code inc_code;
if no flags were found. Return pc_rtx if we got confused. */
static rtx
-discover_flags_reg ()
+discover_flags_reg (void)
{
rtx tmp;
tmp = gen_rtx_REG (word_mode, 10000);
- tmp = gen_add3_insn (tmp, tmp, GEN_INT (2));
+ 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. */
static int flags_set_1_set;
static void
-mark_flags_life_zones (flags)
- rtx flags;
+mark_flags_life_zones (rtx flags)
{
int flags_regno;
int flags_nregs;
flags_nregs = 1;
#else
flags_regno = REGNO (flags);
- flags_nregs = HARD_REGNO_NREGS (flags_regno, GET_MODE (flags));
+ flags_nregs = hard_regno_nregs[flags_regno][GET_MODE (flags)];
#endif
flags_set_1_rtx = flags;
rtx insn, end;
int live;
- insn = block->head;
- end = block->end;
+ insn = BB_HEAD (block);
+ end = BB_END (block);
/* Look out for the (unlikely) case of flags being live across
basic block boundaries. */
#endif
PUT_MODE (insn, (live ? HImode : VOIDmode));
- /* In either case, birth is denoted simply by it's presence
+ /* 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);
/* A subroutine of mark_flags_life_zones, called through note_stores. */
static void
-flags_set_1 (x, pat, data)
- rtx x, pat;
- void *data ATTRIBUTE_UNUSED;
+flags_set_1 (rtx x, rtx pat, void *data ATTRIBUTE_UNUSED)
{
if (GET_CODE (pat) == SET
&& reg_overlap_mentioned_p (x, flags_set_1_rtx))
a candidate for tying to a hard register, since the output might in
turn be a candidate to be tied to a different hard register. */
static int
-replacement_quality (reg)
- rtx reg;
+replacement_quality (rtx reg)
{
int src_regno;
\f
/* Return 1 if INSN might end a basic block. */
-static int perhaps_ends_bb_p (insn)
- rtx insn;
+static int perhaps_ends_bb_p (rtx insn)
{
switch (GET_CODE (insn))
{
very conservative. */
if (nonlocal_goto_handler_labels)
return 1;
- /* FALLTHRU */
+ /* Fall through. */
default:
return can_throw_internal (insn);
}
register-register copy. */
static int
-optimize_reg_copy_1 (insn, dest, src)
- rtx insn;
- rtx dest;
- rtx src;
+optimize_reg_copy_1 (rtx insn, rtx dest, rtx src)
{
rtx p, q;
rtx note;
this for hard registers since the substitutions we may make might fail. */
static void
-optimize_reg_copy_2 (insn, dest, src)
- rtx insn;
- rtx dest;
- rtx src;
+optimize_reg_copy_2 (rtx insn, rtx dest, rtx src)
{
rtx p, q;
rtx set;
the remaining accesses to use the appropriate SUBREG. This allows
SRC and DEST to be tied later. */
static void
-optimize_reg_copy_3 (insn, dest, src)
- rtx insn;
- rtx dest;
- rtx src;
+optimize_reg_copy_3 (rtx insn, rtx dest, rtx src)
{
rtx src_reg = XEXP (src, 0);
int src_no = REGNO (src_reg);
if (! INSN_P (p))
continue;
- /* Make a tenative change. */
+ /* Make a tentative change. */
validate_replace_rtx_group (src_reg, subreg, p);
}
instead moving the value to dest directly before the operation. */
static void
-copy_src_to_dest (insn, src, dest, old_max_uid)
- rtx insn;
- rtx src;
- rtx dest;
- int old_max_uid;
+copy_src_to_dest (rtx insn, rtx src, rtx dest, int old_max_uid)
{
rtx seq;
rtx link;
bb = regmove_bb_head[insn_uid];
if (bb >= 0)
{
- BLOCK_HEAD (bb) = move_insn;
+ BB_HEAD (BASIC_BLOCK (bb)) = move_insn;
regmove_bb_head[insn_uid] = -1;
}
}
the first insn in the function. */
static int
-reg_is_remote_constant_p (reg, insn, first)
- rtx reg;
- rtx insn;
- rtx first;
+reg_is_remote_constant_p (rtx reg, rtx insn, rtx first)
{
rtx p;
hard register as ultimate source, like the frame pointer. */
static int
-fixup_match_2 (insn, dst, src, offset, regmove_dump_file)
- rtx insn, dst, src, offset;
- FILE *regmove_dump_file;
+fixup_match_2 (rtx insn, rtx dst, rtx src, rtx offset, FILE *regmove_dump_file)
{
rtx p, dst_death = 0;
int length, num_calls = 0;
(or 0 if none should be output). */
void
-regmove_optimize (f, nregs, regmove_dump_file)
- rtx f;
- int nregs;
- FILE *regmove_dump_file;
+regmove_optimize (rtx f, int nregs, FILE *regmove_dump_file)
{
int old_max_uid = get_max_uid ();
rtx insn;
can suppress some optimizations in those zones. */
mark_flags_life_zones (discover_flags_reg ());
- regno_src_regno = (int *) xmalloc (sizeof *regno_src_regno * nregs);
+ regno_src_regno = xmalloc (sizeof *regno_src_regno * nregs);
for (i = nregs; --i >= 0; ) regno_src_regno[i] = -1;
- regmove_bb_head = (int *) xmalloc (sizeof (int) * (old_max_uid + 1));
+ regmove_bb_head = xmalloc (sizeof (int) * (old_max_uid + 1));
for (i = old_max_uid; i >= 0; i--) regmove_bb_head[i] = -1;
FOR_EACH_BB (bb)
- regmove_bb_head[INSN_UID (bb->head)] = bb->index;
+ regmove_bb_head[INSN_UID (BB_HEAD (bb))] = bb->index;
/* A forward/backward pass. Replace output operands with input operands. */
ends. Fix that here. */
FOR_EACH_BB (bb)
{
- rtx end = bb->end;
+ rtx end = BB_END (bb);
rtx new = end;
rtx next = NEXT_INSN (new);
while (next != 0 && INSN_UID (next) >= old_max_uid
- && (bb->next_bb == EXIT_BLOCK_PTR || bb->next_bb->head != next))
+ && (bb->next_bb == EXIT_BLOCK_PTR || BB_HEAD (bb->next_bb) != next))
new = next, next = NEXT_INSN (new);
- bb->end = new;
+ BB_END (bb) = new;
}
done:
Initialize the info in MATCHP based on the constraints. */
static int
-find_matches (insn, matchp)
- rtx insn;
- struct match *matchp;
+find_matches (rtx insn, struct match *matchp)
{
int likely_spilled[MAX_RECOG_OPERANDS];
int op_no;
assumed to be in INSN. */
static void
-replace_in_call_usage (loc, dst_reg, src, insn)
- rtx *loc;
- unsigned int dst_reg;
- rtx src;
- rtx insn;
+replace_in_call_usage (rtx *loc, unsigned int dst_reg, rtx src, rtx insn)
{
rtx x = *loc;
enum rtx_code code;
Return nonzero for success. */
static int
-fixup_match_1 (insn, set, src, src_subreg, dst, backward, operand_number,
- match_number, regmove_dump_file)
- rtx insn, set, src, src_subreg, dst;
- int backward, operand_number, match_number;
- FILE *regmove_dump_file;
+fixup_match_1 (rtx insn, rtx set, rtx src, rtx src_subreg, rtx dst,
+ int backward, int operand_number, int match_number,
+ FILE *regmove_dump_file)
{
rtx p;
rtx post_inc = 0, post_inc_set = 0, search_end = 0;
}
-/* return nonzero if X is stable and mentions no regsiters but for
+/* Return nonzero if X is stable and mentions no registers but for
mentioning SRC or mentioning / changing DST . If in doubt, presume
it is unstable.
The rationale is that we want to check if we can move an insn easily
leave the burden to update REG_DEAD / REG_UNUSED notes, so we don't
want any registers but SRC and DST. */
static int
-stable_and_no_regs_but_for_p (x, src, dst)
- rtx x, src, dst;
+stable_and_no_regs_but_for_p (rtx x, rtx src, rtx dst)
{
RTX_CODE code = GET_CODE (x);
switch (GET_RTX_CLASS (code))
{
- case '<': case '1': case 'c': case '2': case 'b': case '3':
+ case RTX_UNARY:
+ case RTX_BIN_ARITH:
+ case RTX_COMM_ARITH:
+ case RTX_COMPARE:
+ case RTX_COMM_COMPARE:
+ case RTX_TERNARY:
+ case RTX_BITFIELD_OPS:
{
int i;
const char *fmt = GET_RTX_FORMAT (code);
return 0;
return 1;
}
- case 'o':
+ case RTX_OBJ:
if (code == REG)
return x == src || x == dst;
/* If this is a MEM, look inside - there might be a register hidden in
if (code == MEM
&& ! stable_and_no_regs_but_for_p (XEXP (x, 0), src, dst))
return 0;
- /* fall through */
+ /* Fall through. */
default:
return ! rtx_unstable_p (x);
}
struct csa_memlist *next;
};
-static int stack_memref_p PARAMS ((rtx));
-static rtx single_set_for_csa PARAMS ((rtx));
-static void free_csa_memlist PARAMS ((struct csa_memlist *));
-static struct csa_memlist *record_one_stack_memref
- PARAMS ((rtx, rtx *, struct csa_memlist *));
-static int try_apply_stack_adjustment
- PARAMS ((rtx, struct csa_memlist *, HOST_WIDE_INT, HOST_WIDE_INT));
-static void combine_stack_adjustments_for_block PARAMS ((basic_block));
-static int record_stack_memrefs PARAMS ((rtx *, void *));
+static int stack_memref_p (rtx);
+static rtx single_set_for_csa (rtx);
+static void free_csa_memlist (struct csa_memlist *);
+static struct csa_memlist *record_one_stack_memref (rtx, rtx *,
+ struct csa_memlist *);
+static int try_apply_stack_adjustment (rtx, struct csa_memlist *,
+ HOST_WIDE_INT, HOST_WIDE_INT);
+static void combine_stack_adjustments_for_block (basic_block);
+static int record_stack_memrefs (rtx *, void *);
/* Main entry point for stack adjustment combination. */
void
-combine_stack_adjustments ()
+combine_stack_adjustments (void)
{
basic_block bb;
/* Recognize a MEM of the form (sp) or (plus sp const). */
static int
-stack_memref_p (x)
- rtx x;
+stack_memref_p (rtx x)
{
if (GET_CODE (x) != MEM)
return 0;
tying fp and sp adjustments. */
static rtx
-single_set_for_csa (insn)
- rtx insn;
+single_set_for_csa (rtx insn)
{
int i;
rtx tmp = single_set (insn);
/* Free the list of csa_memlist nodes. */
static void
-free_csa_memlist (memlist)
- struct csa_memlist *memlist;
+free_csa_memlist (struct csa_memlist *memlist)
{
struct csa_memlist *next;
for (; memlist ; memlist = next)
It is already known that the memory is stack_memref_p. */
static struct csa_memlist *
-record_one_stack_memref (insn, mem, next_memlist)
- rtx insn, *mem;
- struct csa_memlist *next_memlist;
+record_one_stack_memref (rtx insn, rtx *mem, struct csa_memlist *next_memlist)
{
struct csa_memlist *ml;
- ml = (struct csa_memlist *) xmalloc (sizeof (*ml));
+ ml = xmalloc (sizeof (*ml));
if (XEXP (*mem, 0) == stack_pointer_rtx)
ml->sp_offset = 0;
as each of the memories in MEMLIST. Return true on success. */
static int
-try_apply_stack_adjustment (insn, memlist, new_adjust, delta)
- rtx insn;
- struct csa_memlist *memlist;
- HOST_WIDE_INT new_adjust, delta;
+try_apply_stack_adjustment (rtx insn, struct csa_memlist *memlist, HOST_WIDE_INT new_adjust,
+ HOST_WIDE_INT delta)
{
struct csa_memlist *ml;
rtx set;
};
static int
-record_stack_memrefs (xp, data)
- rtx *xp;
- void *data;
+record_stack_memrefs (rtx *xp, void *data)
{
rtx x = *xp;
struct record_stack_memrefs_data *d =
return 1;
case REG:
/* ??? We want be able to handle non-memory stack pointer
- references later. For now just discard all insns refering to
+ references later. For now just discard all insns referring to
stack pointer outside mem expressions. We would probably
want to teach validate_replace to simplify expressions first.
We can't just compare with STACK_POINTER_RTX because the
reference to the stack pointer might be in some other mode.
In particular, an explicit clobber in an asm statement will
- result in a QImode clober. */
+ result in a QImode clobber. */
if (REGNO (x) == STACK_POINTER_REGNUM)
return 1;
break;
/* Subroutine of combine_stack_adjustments, called for each basic block. */
static void
-combine_stack_adjustments_for_block (bb)
- basic_block bb;
+combine_stack_adjustments_for_block (basic_block bb)
{
HOST_WIDE_INT last_sp_adjust = 0;
rtx last_sp_set = NULL_RTX;
struct record_stack_memrefs_data data;
bool end_of_block = false;
- for (insn = bb->head; !end_of_block ; insn = next)
+ for (insn = BB_HEAD (bb); !end_of_block ; insn = next)
{
- end_of_block = insn == bb->end;
+ end_of_block = insn == BB_END (bb);
next = NEXT_INSN (insn);
if (! INSN_P (insn))