#include "insn-config.h"
#include "insn-attr.h"
#include "recog.h"
+#include "hashtab.h"
+#include "hash-set.h"
+#include "vec.h"
+#include "machmode.h"
+#include "input.h"
#include "function.h"
+#include "predict.h"
+#include "dominance.h"
+#include "cfg.h"
+#include "cfgrtl.h"
#include "basic-block.h"
#include "expr.h"
#include "except.h"
#include "diagnostic-core.h"
#include "reload.h"
-#include "predict.h"
#include "tree-pass.h"
#include "target.h"
#include "rtl-iter.h"
static void init_label_info (rtx_insn *);
static void mark_all_labels (rtx_insn *);
-static void mark_jump_label_1 (rtx, rtx, bool, bool);
-static void mark_jump_label_asm (rtx, rtx);
+static void mark_jump_label_1 (rtx, rtx_insn *, bool, bool);
+static void mark_jump_label_asm (rtx, rtx_insn *);
static void redirect_exp_1 (rtx *, rtx, rtx, rtx);
static int invert_exp_1 (rtx, rtx);
\f
static void
rebuild_jump_labels_1 (rtx_insn *f, bool count_forced)
{
- rtx_expr_list *insn;
+ rtx_insn_list *insn;
timevar_push (TV_REBUILD_JUMP);
init_label_info (f);
if (count_forced)
for (insn = forced_labels; insn; insn = insn->next ())
- if (LABEL_P (insn->element ()))
- LABEL_NUSES (insn->element ())++;
+ if (LABEL_P (insn->insn ()))
+ LABEL_NUSES (insn->insn ())++;
timevar_pop (TV_REBUILD_JUMP);
}
CODE_LABEL in the LABEL_REF of the "set". We can
conveniently use it for the marker function, which
requires a LABEL_REF wrapping. */
- gcc_assert (XEXP (label_note, 0) == XEXP (SET_SRC (label_set), 0));
+ gcc_assert (XEXP (label_note, 0) == LABEL_REF_LABEL (SET_SRC (label_set)));
mark_jump_label_1 (label_set, jump_insn, false, true);
handled by other optimizers using better algorithms. */
FOR_BB_INSNS (bb, insn)
{
- gcc_assert (! INSN_DELETED_P (insn));
+ gcc_assert (! insn->deleted ());
if (NONDEBUG_INSN_P (insn))
mark_jump_label (PATTERN (insn), insn, 0);
}
rtx_insn *prev_nonjump_insn = NULL;
for (insn = f; insn; insn = NEXT_INSN (insn))
{
- if (INSN_DELETED_P (insn))
+ if (insn->deleted ())
;
else if (LABEL_P (insn))
prev_nonjump_insn = NULL;
reversed_comparison_code_parts (enum rtx_code code, const_rtx arg0,
const_rtx arg1, const_rtx insn)
{
- enum machine_mode mode;
+ machine_mode mode;
/* If this is not actually a comparison, we can't reverse it. */
if (GET_RTX_CLASS (code) != RTX_COMPARE
/* Return comparison with reversed code of EXP.
Return NULL_RTX in case we fail to do the reversal. */
rtx
-reversed_comparison (const_rtx exp, enum machine_mode mode)
+reversed_comparison (const_rtx exp, machine_mode mode)
{
enum rtx_code reversed_code = reversed_comparison_code (exp, NULL_RTX);
if (reversed_code == UNKNOWN)
/* Return 1 if INSN is an unconditional jump and nothing else. */
int
-simplejump_p (const_rtx insn)
+simplejump_p (const rtx_insn *insn)
{
return (JUMP_P (insn)
&& GET_CODE (PATTERN (insn)) == SET
branch and compare insns. Use any_condjump_p instead whenever possible. */
int
-condjump_p (const_rtx insn)
+condjump_p (const rtx_insn *insn)
{
const_rtx x = PATTERN (insn);
branch and compare insns. Use any_condjump_p instead whenever possible. */
int
-condjump_in_parallel_p (const_rtx insn)
+condjump_in_parallel_p (const rtx_insn *insn)
{
const_rtx x = PATTERN (insn);
/* Return set of PC, otherwise NULL. */
rtx
-pc_set (const_rtx insn)
+pc_set (const rtx_insn *insn)
{
rtx pat;
if (!JUMP_P (insn))
possibly bundled inside a PARALLEL. */
int
-any_uncondjump_p (const_rtx insn)
+any_uncondjump_p (const rtx_insn *insn)
{
const_rtx x = pc_set (insn);
if (!x)
Note that unlike condjump_p it returns false for unconditional jumps. */
int
-any_condjump_p (const_rtx insn)
+any_condjump_p (const rtx_insn *insn)
{
const_rtx x = pc_set (insn);
enum rtx_code a, b;
/* Return the label of a conditional jump. */
rtx
-condjump_label (const_rtx insn)
+condjump_label (const rtx_insn *insn)
{
rtx x = pc_set (insn);
/* Return TRUE if INSN is a return jump. */
int
-returnjump_p (rtx insn)
+returnjump_p (const rtx_insn *insn)
{
if (JUMP_P (insn))
{
/* Return true if INSN is a (possibly conditional) return insn. */
int
-eh_returnjump_p (rtx insn)
+eh_returnjump_p (rtx_insn *insn)
{
if (JUMP_P (insn))
{
nothing more. */
int
-onlyjump_p (const_rtx insn)
+onlyjump_p (const rtx_insn *insn)
{
rtx set;
/* Return true iff INSN is a jump and its JUMP_LABEL is a label, not
NULL or a return. */
bool
-jump_to_label_p (rtx insn)
+jump_to_label_p (const rtx_insn *insn)
{
return (JUMP_P (insn)
&& JUMP_LABEL (insn) != NULL && !ANY_RETURN_P (JUMP_LABEL (insn)));
that loop-optimization is done with. */
void
-mark_jump_label (rtx x, rtx insn, int in_mem)
+mark_jump_label (rtx x, rtx_insn *insn, int in_mem)
{
rtx asmop = extract_asm_operands (x);
if (asmop)
note. */
static void
-mark_jump_label_1 (rtx x, rtx insn, bool in_mem, bool is_target)
+mark_jump_label_1 (rtx x, rtx_insn *insn, bool in_mem, bool is_target)
{
RTX_CODE code = GET_CODE (x);
int i;
case LABEL_REF:
{
- rtx label = XEXP (x, 0);
+ rtx label = LABEL_REF_LABEL (x);
/* Ignore remaining references to unreachable labels that
have been deleted. */
if (LABEL_REF_NONLOCAL_P (x))
break;
- XEXP (x, 0) = label;
- if (! insn || ! INSN_DELETED_P (insn))
+ LABEL_REF_LABEL (x) = label;
+ if (! insn || ! insn->deleted ())
++LABEL_NUSES (label);
if (insn)
ADDR_DIFF_VEC. Don't set the JUMP_LABEL of a vector. */
case ADDR_VEC:
case ADDR_DIFF_VEC:
- if (! INSN_DELETED_P (insn))
+ if (! insn->deleted ())
{
int eltnum = code == ADDR_DIFF_VEC ? 1 : 0;
for (i = 0; i < XVECLEN (x, eltnum); i++)
- mark_jump_label_1 (XVECEXP (x, eltnum, i), NULL_RTX, in_mem,
+ mark_jump_label_1 (XVECEXP (x, eltnum, i), NULL, in_mem,
is_target);
}
return;
need to be considered targets. */
static void
-mark_jump_label_asm (rtx asmop, rtx insn)
+mark_jump_label_asm (rtx asmop, rtx_insn *insn)
{
int i;
subsequent cfg_cleanup pass to delete unreachable code if needed. */
rtx_insn *
-delete_related_insns (rtx insn)
+delete_related_insns (rtx uncast_insn)
{
+ rtx_insn *insn = as_a <rtx_insn *> (uncast_insn);
int was_code_label = (LABEL_P (insn));
rtx note;
rtx_insn *next = NEXT_INSN (insn), *prev = PREV_INSN (insn);
- while (next && INSN_DELETED_P (next))
+ while (next && next->deleted ())
next = NEXT_INSN (next);
/* This insn is already deleted => return first following nondeleted. */
- if (INSN_DELETED_P (insn))
+ if (insn->deleted ())
return next;
delete_insn (insn);
&& GET_CODE (PATTERN (insn)) == SEQUENCE
&& CALL_P (XVECEXP (PATTERN (insn), 0, 0))))
{
- rtx p;
+ rtx_insn *p;
- for (p = next && INSN_DELETED_P (next) ? NEXT_INSN (next) : next;
+ for (p = next && next->deleted () ? NEXT_INSN (next) : next;
p && NOTE_P (p);
p = NEXT_INSN (p))
if (NOTE_KIND (p) == NOTE_INSN_CALL_ARG_LOCATION)
/* Likewise if we're deleting a dispatch table. */
- if (JUMP_TABLE_DATA_P (insn))
+ if (rtx_jump_table_data *table = dyn_cast <rtx_jump_table_data *> (insn))
{
- rtx pat = PATTERN (insn);
- int i, diff_vec_p = GET_CODE (pat) == ADDR_DIFF_VEC;
- int len = XVECLEN (pat, diff_vec_p);
+ rtvec labels = table->get_labels ();
+ int i;
+ int len = GET_NUM_ELEM (labels);
for (i = 0; i < len; i++)
- if (LABEL_NUSES (XEXP (XVECEXP (pat, diff_vec_p, i), 0)) == 0)
- delete_related_insns (XEXP (XVECEXP (pat, diff_vec_p, i), 0));
- while (next && INSN_DELETED_P (next))
+ if (LABEL_NUSES (XEXP (RTVEC_ELT (labels, i), 0)) == 0)
+ delete_related_insns (XEXP (RTVEC_ELT (labels, i), 0));
+ while (next && next->deleted ())
next = NEXT_INSN (next);
return next;
}
if (LABEL_NUSES (XEXP (note, 0)) == 0)
delete_related_insns (XEXP (note, 0));
- while (prev && (INSN_DELETED_P (prev) || NOTE_P (prev)))
+ while (prev && (prev->deleted () || NOTE_P (prev)))
prev = PREV_INSN (prev);
/* If INSN was a label and a dispatch table follows it,
if (code == NOTE)
next = NEXT_INSN (next);
/* Keep going past other deleted labels to delete what follows. */
- else if (code == CODE_LABEL && INSN_DELETED_P (next))
+ else if (code == CODE_LABEL && next->deleted ())
next = NEXT_INSN (next);
/* Keep the (use (insn))s created by dbr_schedule, which needs
them in order to track liveness relative to a previous
but I see no clean and sure alternative way
to find the first insn after INSN that is not now deleted.
I hope this works. */
- while (next && INSN_DELETED_P (next))
+ while (next && next->deleted ())
next = NEXT_INSN (next);
return next;
}
if (!NOTE_P (insn))
{
- INSN_DELETED_P (insn) = 1;
+ insn->set_deleted();
/* Patch this insn out of the chain. */
/* We don't do this all at once, because we
int i;
const char *fmt;
- if ((code == LABEL_REF && XEXP (x, 0) == olabel)
+ if ((code == LABEL_REF && LABEL_REF_LABEL (x) == olabel)
|| x == olabel)
{
x = redirect_target (nlabel);
if (code == SET && SET_DEST (x) == pc_rtx
&& ANY_RETURN_P (nlabel)
&& GET_CODE (SET_SRC (x)) == LABEL_REF
- && XEXP (SET_SRC (x), 0) == olabel)
+ && LABEL_REF_LABEL (SET_SRC (x)) == olabel)
{
validate_change (insn, loc, nlabel, 1);
return;
inversion and redirection. */
int
-invert_jump_1 (rtx jump, rtx nlabel)
+invert_jump_1 (rtx_insn *jump, rtx nlabel)
{
rtx x = pc_set (jump);
int ochanges;
NLABEL instead of where it jumps now. Return true if successful. */
int
-invert_jump (rtx jump, rtx nlabel, int delete_unused)
+invert_jump (rtx_insn *jump, rtx nlabel, int delete_unused)
{
rtx olabel = JUMP_LABEL (jump);
case LABEL_REF:
/* We can't assume nonlocal labels have their following insns yet. */
if (LABEL_REF_NONLOCAL_P (x) || LABEL_REF_NONLOCAL_P (y))
- return XEXP (x, 0) == XEXP (y, 0);
+ return LABEL_REF_LABEL (x) == LABEL_REF_LABEL (y);
/* Two label-refs are equivalent if they point at labels
in the same position in the instruction stream. */
- return (next_real_insn (XEXP (x, 0))
- == next_real_insn (XEXP (y, 0)));
+ return (next_real_insn (LABEL_REF_LABEL (x))
+ == next_real_insn (LABEL_REF_LABEL (y)));
case SYMBOL_REF:
return XSTR (x, 0) == XSTR (y, 0);