/* 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.
{
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. */
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
- && GET_CODE (SUBREG_REG (tmp)) == REG
+ && REG_P (SUBREG_REG (tmp))
&& REGNO (SUBREG_REG (tmp)) < FIRST_PSEUDO_REGISTER)
return pc_rtx;
- found = (GET_CODE (tmp) == REG && REGNO (tmp) < FIRST_PSEUDO_REGISTER);
+ found = (REG_P (tmp) && REGNO (tmp) < FIRST_PSEUDO_REGISTER);
return (found ? tmp : NULL_RTX);
}
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);
int src_regno;
/* Bad if this isn't a register at all. */
- if (GET_CODE (reg) != REG)
+ if (!REG_P (reg))
return 0;
/* If this register is not meant to get a hard register,
very conservative. */
if (nonlocal_goto_handler_labels)
return 1;
- /* FALLTHRU */
+ /* Fall through. */
default:
return can_throw_internal (insn);
}
|| (sregno < FIRST_PSEUDO_REGISTER
&& asm_noperands (PATTERN (p)) >= 0
&& reg_overlap_mentioned_p (src, PATTERN (p)))
+ /* Don't change hard registers used by a call. */
+ || (CALL_P (p) && sregno < FIRST_PSEUDO_REGISTER
+ && find_reg_fusage (p, USE, src))
/* Don't change a USE of a register. */
|| (GET_CODE (PATTERN (p)) == USE
&& reg_overlap_mentioned_p (src, XEXP (PATTERN (p), 0))))
/* If the insn in which SRC dies is a CALL_INSN, don't count it
as a call that has been crossed. Otherwise, count it. */
- if (q != p && GET_CODE (q) == CALL_INSN)
+ if (q != p && CALL_P (q))
{
/* Similarly, total calls for SREGNO, total calls beyond
the death note for DREGNO. */
PATTERN (q) = replace_rtx (PATTERN (q), dest, src);
- if (GET_CODE (q) == CALL_INSN)
+ if (CALL_P (q))
{
REG_N_CALLS_CROSSED (dregno)--;
REG_N_CALLS_CROSSED (sregno)++;
if (reg_set_p (src, p)
|| find_reg_note (p, REG_DEAD, dest)
- || (GET_CODE (p) == CALL_INSN && REG_N_CALLS_CROSSED (sregno) == 0))
+ || (CALL_P (p) && REG_N_CALLS_CROSSED (sregno) == 0))
break;
}
}
rtx src_reg = XEXP (src, 0);
int src_no = REGNO (src_reg);
int dst_no = REGNO (dest);
- rtx p, set, subreg;
+ rtx p, set;
enum machine_mode old_mode;
if (src_no < FIRST_PSEUDO_REGISTER
return;
if (! (set = single_set (p))
- || GET_CODE (SET_SRC (set)) != MEM
+ || !MEM_P (SET_SRC (set))
/* If there's a REG_EQUIV note, this must be an insn that loads an
argument. Prefer keeping the note over doing this optimization. */
|| find_reg_note (p, REG_EQUIV, NULL_RTX)
/* Now walk forward making additional replacements. We want to be able
to undo all the changes if a later substitution fails. */
- subreg = gen_lowpart_SUBREG (old_mode, src_reg);
while (p = NEXT_INSN (p), p != insn)
{
if (! INSN_P (p))
continue;
- /* Make a tenative change. */
- validate_replace_rtx_group (src_reg, subreg, p);
+ /* Make a tentative change. */
+ validate_replace_rtx_group (src_reg,
+ gen_lowpart_SUBREG (old_mode, src_reg),
+ p);
}
validate_replace_rtx_group (src, src_reg, insn);
parameter when there is no frame pointer that is not allocated a register.
For now, we just reject them, rather than incrementing the live length. */
- if (GET_CODE (src) == REG
+ if (REG_P (src)
&& REG_LIVE_LENGTH (REGNO (src)) > 0
- && GET_CODE (dest) == REG
- && !RTX_UNCHANGING_P (dest)
+ && REG_P (dest)
&& REG_LIVE_LENGTH (REGNO (dest)) > 0
&& (set = single_set (insn)) != NULL_RTX
&& !reg_mentioned_p (dest, SET_SRC (set))
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;
}
}
if (REGNO_LAST_UID (src_regno) == insn_uid)
REGNO_LAST_UID (src_regno) = move_uid;
-
- if (REGNO_LAST_NOTE_UID (src_regno) == insn_uid)
- REGNO_LAST_NOTE_UID (src_regno) = move_uid;
}
}
continue;
s = single_set (XEXP (p, 0));
if (s != 0
- && GET_CODE (SET_DEST (s)) == REG
+ && REG_P (SET_DEST (s))
&& REGNO (SET_DEST (s)) == REGNO (reg))
{
/* The register is set in the same basic block. */
continue;
s = single_set (p);
if (s != 0
- && GET_CODE (SET_DEST (s)) == REG
+ && REG_P (SET_DEST (s))
&& REGNO (SET_DEST (s)) == REGNO (reg))
{
/* This is the instruction which sets REG. If there is a
#ifdef AUTO_INC_DEC
for (p = PREV_INSN (insn); p; p = PREV_INSN (p))
{
- if (GET_CODE (p) == CODE_LABEL
- || GET_CODE (p) == JUMP_INSN)
+ if (LABEL_P (p)
+ || JUMP_P (p))
break;
if (! INSN_P (p))
continue;
}
for (p = NEXT_INSN (insn); p; p = NEXT_INSN (p))
{
- if (GET_CODE (p) == CODE_LABEL
- || GET_CODE (p) == JUMP_INSN)
+ if (LABEL_P (p)
+ || JUMP_P (p))
break;
if (! INSN_P (p))
continue;
/* reg_set_p is overly conservative for CALL_INSNS, thinks that all
hard regs are clobbered. Thus, we only use it for src for
non-call insns. */
- if (GET_CODE (p) == CALL_INSN)
+ if (CALL_P (p))
{
if (! dst_death)
num_calls++;
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. */
if (flag_expensive_optimizations && ! pass
&& (GET_CODE (SET_SRC (set)) == SIGN_EXTEND
|| GET_CODE (SET_SRC (set)) == ZERO_EXTEND)
- && GET_CODE (XEXP (SET_SRC (set), 0)) == REG
- && GET_CODE (SET_DEST (set)) == REG)
+ && REG_P (XEXP (SET_SRC (set), 0))
+ && REG_P (SET_DEST (set)))
optimize_reg_copy_3 (insn, SET_DEST (set), SET_SRC (set));
if (flag_expensive_optimizations && ! pass
- && GET_CODE (SET_SRC (set)) == REG
- && GET_CODE (SET_DEST (set)) == REG)
+ && REG_P (SET_SRC (set))
+ && REG_P (SET_DEST (set)))
{
/* If this is a register-register copy where SRC is not dead,
see if we can optimize it. If this optimization succeeds,
src = recog_data.operand[op_no];
dst = recog_data.operand[match_no];
- if (GET_CODE (src) != REG)
+ if (!REG_P (src))
continue;
src_subreg = src;
&& GET_MODE_SIZE (GET_MODE (dst))
>= GET_MODE_SIZE (GET_MODE (SUBREG_REG (dst))))
{
- src_subreg
- = gen_rtx_SUBREG (GET_MODE (SUBREG_REG (dst)),
- src, SUBREG_BYTE (dst));
dst = SUBREG_REG (dst);
+ src_subreg = lowpart_subreg (GET_MODE (dst),
+ src, GET_MODE (src));
+ if (!src_subreg)
+ continue;
}
- if (GET_CODE (dst) != REG
+ if (!REG_P (dst)
|| REGNO (dst) < FIRST_PSEUDO_REGISTER)
continue;
dst = recog_data.operand[match_no];
src = recog_data.operand[op_no];
- if (GET_CODE (src) != REG)
+ if (!REG_P (src))
continue;
- if (GET_CODE (dst) != REG
+ if (!REG_P (dst)
|| REGNO (dst) < FIRST_PSEUDO_REGISTER
|| REG_LIVE_LENGTH (REGNO (dst)) < 0
- || RTX_UNCHANGING_P (dst)
|| GET_MODE (src) != GET_MODE (dst))
continue;
/* If we have passed a call instruction, and the
pseudo-reg DST is not already live across a call,
then don't perform the optimization. */
- if (GET_CODE (p) == CALL_INSN)
+ if (CALL_P (p))
{
num_calls++;
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:
rtx src_note = find_reg_note (insn, REG_DEAD, src), dst_note = NULL_RTX;
int length, s_length;
- /* If SRC is marked as unchanging, we may not change it.
- ??? Maybe we could get better code by removing the unchanging bit
- instead, and changing it back if we don't succeed? */
- if (RTX_UNCHANGING_P (src))
- return 0;
-
if (! src_note)
{
/* Look for (set (regX) (op regA constX))
for (length = s_length = 0, p = NEXT_INSN (insn); p; p = NEXT_INSN (p))
{
- if (GET_CODE (p) == CALL_INSN)
+ if (CALL_P (p))
replace_in_call_usage (& CALL_INSN_FUNCTION_USAGE (p),
REGNO (dst), src, p);
hard register. */
&& ! (dst_note && ! REG_N_CALLS_CROSSED (REGNO (dst))
&& single_set (p)
- && GET_CODE (SET_DEST (single_set (p))) == REG
+ && REG_P (SET_DEST (single_set (p)))
&& (REGNO (SET_DEST (single_set (p)))
< FIRST_PSEUDO_REGISTER))
/* We may only emit an insn directly after P if we
/* If we have passed a call instruction, and the pseudo-reg SRC is not
already live across a call, then don't perform the optimization. */
- if (GET_CODE (p) == CALL_INSN)
+ if (CALL_P (p))
{
if (REG_N_CALLS_CROSSED (REGNO (src)) == 0)
break;
q = 0;
break;
}
- if (GET_CODE (p) == CALL_INSN)
+ if (CALL_P (p))
num_calls2++;
}
if (q && set2 && SET_DEST (set2) == src && CONSTANT_P (SET_SRC (set2))
}
-/* return nonzero if X is stable and mentions no registers 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
- while just paying attention to SRC and DST. A register is considered
- stable if it has the RTX_UNCHANGING_P bit set, but that would still
- leave the burden to update REG_DEAD / REG_UNUSED notes, so we don't
- want any registers but SRC and DST. */
+ while just paying attention to SRC and DST. */
static int
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);
}
static int
stack_memref_p (rtx x)
{
- if (GET_CODE (x) != MEM)
+ if (!MEM_P (x))
return 0;
x = XEXP (x, 0);
if (tmp)
return tmp;
- if (GET_CODE (insn) != INSN
+ if (!NONJUMP_INSN_P (insn)
|| GET_CODE (PATTERN (insn)) != PARALLEL)
return 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))
turn it into a direct store. Obviously we can't do this if
there were any intervening uses of the stack pointer. */
if (memlist == NULL
- && GET_CODE (dest) == MEM
+ && MEM_P (dest)
&& ((GET_CODE (XEXP (dest, 0)) == PRE_DEC
&& (last_sp_adjust
== (HOST_WIDE_INT) GET_MODE_SIZE (GET_MODE (dest))))
data.insn = insn;
data.memlist = memlist;
- if (GET_CODE (insn) != CALL_INSN && last_sp_set
+ if (!CALL_P (insn) && last_sp_set
&& !for_each_rtx (&PATTERN (insn), record_stack_memrefs, &data))
{
memlist = data.memlist;
/* Otherwise, we were not able to process the instruction.
Do not continue collecting data across such a one. */
if (last_sp_set
- && (GET_CODE (insn) == CALL_INSN
+ && (CALL_P (insn)
|| reg_mentioned_p (stack_pointer_rtx, PATTERN (insn))))
{
if (last_sp_set && last_sp_adjust == 0)