/* Optimize jump instructions, for GNU compiler.
Copyright (C) 1987, 1988, 1989, 1991, 1992, 1993, 1994, 1995, 1996, 1997
- 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007
+ 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009
Free Software Foundation, Inc.
This file is part of GCC.
if (BARRIER_P (insn))
{
prev = prev_nonnote_insn (insn);
+ if (!prev)
+ continue;
if (BARRIER_P (prev))
delete_insn (insn);
else if (prev != PREV_INSN (insn))
NULL, /* sub */
NULL, /* next */
0, /* static_pass_number */
- 0, /* tv_id */
+ TV_NONE, /* tv_id */
0, /* properties_required */
0, /* properties_provided */
0, /* properties_destroyed */
{
rtx x = *loc;
- return x && (GET_CODE (x) == RETURN
- || (GET_CODE (x) == SET && SET_IS_RETURN_P (x)));
+ if (x == NULL)
+ return false;
+
+ switch (GET_CODE (x))
+ {
+ case RETURN:
+ case EH_RETURN:
+ return true;
+
+ case SET:
+ return SET_IS_RETURN_P (x);
+
+ default:
+ return false;
+ }
}
+/* Return TRUE if INSN is a return jump. */
+
int
returnjump_p (rtx insn)
{
+ /* Handle delayed branches. */
+ if (NONJUMP_INSN_P (insn) && GET_CODE (PATTERN (insn)) == SEQUENCE)
+ insn = XVECEXP (PATTERN (insn), 0, 0);
+
if (!JUMP_P (insn))
return 0;
+
return for_each_rtx (&PATTERN (insn), returnjump_p_1, NULL);
}
+/* Return true if INSN is a (possibly conditional) return insn. */
+
+static int
+eh_returnjump_p_1 (rtx *loc, void *data ATTRIBUTE_UNUSED)
+{
+ return *loc && GET_CODE (*loc) == EH_RETURN;
+}
+
+int
+eh_returnjump_p (rtx insn)
+{
+ if (!JUMP_P (insn))
+ return 0;
+ return for_each_rtx (&PATTERN (insn), eh_returnjump_p_1, NULL);
+}
+
/* Return true if INSN is a jump that only transfers control and
nothing more. */
{
int reg_x = -1, reg_y = -1;
int byte_x = 0, byte_y = 0;
+ struct subreg_info info;
if (GET_MODE (x) != GET_MODE (y))
return 0;
if (reg_renumber[reg_x] >= 0)
{
- if (!subreg_offset_representable_p (reg_renumber[reg_x],
- GET_MODE (SUBREG_REG (x)),
- byte_x,
- GET_MODE (x)))
+ subreg_get_info (reg_renumber[reg_x],
+ GET_MODE (SUBREG_REG (x)), byte_x,
+ GET_MODE (x), &info);
+ if (!info.representable_p)
return 0;
- reg_x = subreg_regno_offset (reg_renumber[reg_x],
- GET_MODE (SUBREG_REG (x)),
- byte_x,
- GET_MODE (x));
+ reg_x = info.offset;
byte_x = 0;
}
- else if (!subreg_offset_representable_p (reg_x,
- GET_MODE (SUBREG_REG (x)),
- byte_x,
- GET_MODE (x)))
- return 0;
}
else
{
if (reg_renumber[reg_y] >= 0)
{
- if (!subreg_offset_representable_p (reg_renumber[reg_y],
- GET_MODE (SUBREG_REG (y)),
- byte_y,
- GET_MODE (y)))
+ subreg_get_info (reg_renumber[reg_y],
+ GET_MODE (SUBREG_REG (y)), byte_y,
+ GET_MODE (y), &info);
+ if (!info.representable_p)
return 0;
- reg_y = subreg_regno_offset (reg_renumber[reg_y],
- GET_MODE (SUBREG_REG (y)),
- byte_y,
- GET_MODE (y));
+ reg_y = info.offset;
byte_y = 0;
}
- else if (!subreg_offset_representable_p (reg_y,
- GET_MODE (SUBREG_REG (y)),
- byte_y,
- GET_MODE (y)))
- return 0;
}
else
{
{
int base = true_regnum (SUBREG_REG (x));
if (base >= 0
- && base < FIRST_PSEUDO_REGISTER
- && subreg_offset_representable_p (REGNO (SUBREG_REG (x)),
- GET_MODE (SUBREG_REG (x)),
- SUBREG_BYTE (x), GET_MODE (x)))
- return base + subreg_regno_offset (REGNO (SUBREG_REG (x)),
- GET_MODE (SUBREG_REG (x)),
- SUBREG_BYTE (x), GET_MODE (x));
+ && base < FIRST_PSEUDO_REGISTER)
+ {
+ struct subreg_info info;
+
+ subreg_get_info (REGNO (SUBREG_REG (x)),
+ GET_MODE (SUBREG_REG (x)),
+ SUBREG_BYTE (x), GET_MODE (x), &info);
+
+ if (info.representable_p)
+ return base + info.offset;
+ }
}
return -1;
}