/* 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 */
return UNKNOWN;
/* These CONST_CAST's are okay because prev_nonnote_insn just
- returns it's argument and we assign it to a const_rtx
+ returns its argument and we assign it to a const_rtx
variable. */
for (prev = prev_nonnote_insn (CONST_CAST_RTX(insn));
prev != 0 && !LABEL_P (prev);
/* Test for an integer condition, or a floating-point comparison
in which NaNs can be ignored. */
- if (GET_CODE (arg0) == CONST_INT
+ if (CONST_INT_P (arg0)
|| (GET_MODE (arg0) != VOIDmode
&& GET_MODE_CLASS (mode) != MODE_CC
&& !HONOR_NANS (mode)))
{
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)
{
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. */
a label, except for the primary target of a jump,
must have such a note. */
if (! find_reg_note (insn, kind, label))
- REG_NOTES (insn)
- = gen_rtx_INSN_LIST (kind, label, REG_NOTES (insn));
+ add_reg_note (insn, kind, label);
}
}
return;
/* Likewise if we're deleting a dispatch table. */
- if (JUMP_P (insn)
- && (GET_CODE (PATTERN (insn)) == ADDR_VEC
- || GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC))
+ if (JUMP_TABLE_DATA_P (insn))
{
rtx pat = PATTERN (insn);
int i, diff_vec_p = GET_CODE (pat) == ADDR_DIFF_VEC;
if (was_code_label
&& NEXT_INSN (insn) != 0
- && JUMP_P (NEXT_INSN (insn))
- && (GET_CODE (PATTERN (NEXT_INSN (insn))) == ADDR_VEC
- || GET_CODE (PATTERN (NEXT_INSN (insn))) == ADDR_DIFF_VEC))
+ && JUMP_TABLE_DATA_P (NEXT_INSN (insn)))
next = delete_related_insns (NEXT_INSN (insn));
/* If INSN was a label, delete insns following it if now unreachable. */
return;
}
+ if (code == IF_THEN_ELSE)
+ {
+ /* Skip the condition of an IF_THEN_ELSE. We only want to
+ change jump destinations, not eventual label comparisons. */
+ redirect_exp_1 (&XEXP (x, 1), olabel, nlabel, insn);
+ redirect_exp_1 (&XEXP (x, 2), olabel, nlabel, insn);
+ return;
+ }
+
fmt = GET_RTX_FORMAT (code);
for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
{
{
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)
{
- reg_x = subreg_regno_offset (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 = info.offset;
byte_x = 0;
}
}
if (reg_renumber[reg_y] >= 0)
{
- reg_y = subreg_regno_offset (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 = info.offset;
byte_y = 0;
}
}
{
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;
}