/* Optimize jump instructions, for GNU compiler.
- Copyright (C) 1987-2015 Free Software Foundation, Inc.
+ Copyright (C) 1987-2020 Free Software Foundation, Inc.
This file is part of GCC.
#include "config.h"
#include "system.h"
#include "coretypes.h"
-#include "tm.h"
+#include "backend.h"
+#include "target.h"
#include "rtl.h"
+#include "tree.h"
+#include "cfghooks.h"
+#include "tree-pass.h"
+#include "memmodel.h"
#include "tm_p.h"
-#include "flags.h"
-#include "hard-reg-set.h"
-#include "regs.h"
#include "insn-config.h"
-#include "insn-attr.h"
+#include "regs.h"
+#include "emit-rtl.h"
#include "recog.h"
-#include "hashtab.h"
-#include "hash-set.h"
-#include "vec.h"
-#include "input.h"
-#include "function.h"
-#include "predict.h"
-#include "dominance.h"
-#include "cfg.h"
#include "cfgrtl.h"
-#include "basic-block.h"
-#include "symtab.h"
-#include "statistics.h"
-#include "alias.h"
-#include "inchash.h"
-#include "tree.h"
-#include "expmed.h"
-#include "dojump.h"
-#include "explow.h"
-#include "calls.h"
-#include "emit-rtl.h"
-#include "varasm.h"
-#include "stmt.h"
-#include "expr.h"
-#include "except.h"
-#include "diagnostic-core.h"
-#include "reload.h"
-#include "tree-pass.h"
-#include "target.h"
#include "rtl-iter.h"
/* Optimize jump y; x: ... y: jumpif... x?
static void mark_all_labels (rtx_insn *);
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);
+static void redirect_exp_1 (rtx *, rtx, rtx, rtx_insn *);
+static int invert_exp_1 (rtx, rtx_insn *);
\f
/* Worker for rebuild_jump_labels and rebuild_jump_labels_chain. */
static void
rebuild_jump_labels_1 (rtx_insn *f, bool count_forced)
{
- rtx_insn_list *insn;
-
timevar_push (TV_REBUILD_JUMP);
init_label_info (f);
mark_all_labels (f);
count doesn't drop to zero. */
if (count_forced)
- for (insn = forced_labels; insn; insn = insn->next ())
- if (LABEL_P (insn->insn ()))
- LABEL_NUSES (insn->insn ())++;
+ {
+ rtx_insn *insn;
+ unsigned int i;
+ FOR_EACH_VEC_SAFE_ELT (forced_labels, i, insn)
+ if (LABEL_P (insn))
+ LABEL_NUSES (insn)++;
+ }
timevar_pop (TV_REBUILD_JUMP);
}
{
if (BARRIER_P (insn))
{
- rtx_insn *prev = prev_nonnote_insn (insn);
+ rtx_insn *prev = prev_nonnote_nondebug_insn (insn);
if (!prev)
continue;
- if (CALL_P (prev))
- {
- /* Make sure we do not split a call and its corresponding
- CALL_ARG_LOCATION note. */
- rtx_insn *next = NEXT_INSN (prev);
-
- if (NOTE_P (next)
- && NOTE_KIND (next) == NOTE_INSN_CALL_ARG_LOCATION)
- prev = next;
- }
-
if (BARRIER_P (prev))
delete_insn (insn);
else if (prev != PREV_INSN (insn))
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) == LABEL_REF_LABEL (SET_SRC (label_set)));
+ gcc_assert (XEXP (label_note, 0) == label_ref_label (SET_SRC (label_set)));
mark_jump_label_1 (label_set, jump_insn, false, true);
to help this function avoid overhead in these cases. */
enum rtx_code
reversed_comparison_code_parts (enum rtx_code code, const_rtx arg0,
- const_rtx arg1, const_rtx insn)
+ const_rtx arg1, const rtx_insn *insn)
{
machine_mode mode;
machine description to do tricks. */
if (GET_MODE_CLASS (mode) == MODE_CC
&& REVERSIBLE_CC_MODE (mode))
- {
-#ifdef REVERSE_CONDITION
- return REVERSE_CONDITION (code, mode);
-#else
- return reverse_condition (code);
-#endif
- }
+ return REVERSE_CONDITION (code, mode);
/* Try a few special cases based on the comparison code. */
switch (code)
if (GET_MODE_CLASS (mode) == MODE_CC || CC0_P (arg0))
{
- const_rtx prev;
/* Try to search for the comparison to determine the real mode.
This code is expensive, but with sane machine description it
will be never used, since REVERSIBLE_CC_MODE will return true
/* These CONST_CAST's are okay because prev_nonnote_insn just
returns its argument and we assign it to a const_rtx
variable. */
- for (prev = prev_nonnote_insn (CONST_CAST_RTX (insn));
+ for (rtx_insn *prev = prev_nonnote_insn (const_cast<rtx_insn *> (insn));
prev != 0 && !LABEL_P (prev);
- prev = prev_nonnote_insn (CONST_CAST_RTX (prev)))
+ prev = prev_nonnote_insn (prev))
{
const_rtx set = set_of (arg0, prev);
if (set && GET_CODE (set) == SET
/* A wrapper around the previous function to take COMPARISON as rtx
expression. This simplifies many callers. */
enum rtx_code
-reversed_comparison_code (const_rtx comparison, const_rtx insn)
+reversed_comparison_code (const_rtx comparison, const rtx_insn *insn)
{
if (!COMPARISON_P (comparison))
return UNKNOWN;
rtx
reversed_comparison (const_rtx exp, machine_mode mode)
{
- enum rtx_code reversed_code = reversed_comparison_code (exp, NULL_RTX);
+ enum rtx_code reversed_code = reversed_comparison_code (exp, NULL);
if (reversed_code == UNKNOWN)
return NULL_RTX;
else
case LABEL_REF:
{
- rtx label = LABEL_REF_LABEL (x);
+ rtx_insn *label = label_ref_label (x);
/* Ignore remaining references to unreachable labels that
have been deleted. */
if (LABEL_REF_NONLOCAL_P (x))
break;
- LABEL_REF_LABEL (x) = label;
+ set_label_ref_label (x, label);
if (! insn || ! insn->deleted ())
++LABEL_NUSES (label);
if (next != 0 && BARRIER_P (next))
delete_insn (next);
- /* If this is a call, then we have to remove the var tracking note
- for the call arguments. */
-
- if (CALL_P (insn)
- || (NONJUMP_INSN_P (insn)
- && GET_CODE (PATTERN (insn)) == SEQUENCE
- && CALL_P (XVECEXP (PATTERN (insn), 0, 0))))
- {
- rtx_insn *p;
-
- 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)
- {
- remove_insn (p);
- break;
- }
- }
-
/* If deleting a jump, decrement the count of the label,
and delete the label if it is now unused. */
NLABEL as a return. Accrue modifications into the change group. */
static void
-redirect_exp_1 (rtx *loc, rtx olabel, rtx nlabel, rtx insn)
+redirect_exp_1 (rtx *loc, rtx olabel, rtx nlabel, rtx_insn *insn)
{
rtx x = *loc;
RTX_CODE code = GET_CODE (x);
int i;
const char *fmt;
- if ((code == LABEL_REF && LABEL_REF_LABEL (x) == 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
- && LABEL_REF_LABEL (SET_SRC (x)) == olabel)
+ && label_ref_label (SET_SRC (x)) == olabel)
{
validate_change (insn, loc, nlabel, 1);
return;
/* Invert the jump condition X contained in jump insn INSN. Accrue the
modifications into the change group. Return nonzero for success. */
static int
-invert_exp_1 (rtx x, rtx insn)
+invert_exp_1 (rtx x, rtx_insn *insn)
{
RTX_CODE code = GET_CODE (x);
&& REG_P (SUBREG_REG (y)))))
{
int reg_x = -1, reg_y = -1;
- int byte_x = 0, byte_y = 0;
+ poly_int64 byte_x = 0, byte_y = 0;
struct subreg_info info;
if (GET_MODE (x) != GET_MODE (y))
reg_y = reg_renumber[reg_y];
}
- return reg_x >= 0 && reg_x == reg_y && byte_x == byte_y;
+ return reg_x >= 0 && reg_x == reg_y && known_eq (byte_x, byte_y);
}
/* Now we have disposed of all the cases
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 LABEL_REF_LABEL (x) == LABEL_REF_LABEL (y);
+ 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 (LABEL_REF_LABEL (x))
- == next_real_insn (LABEL_REF_LABEL (y)));
+ else
+ {
+ rtx_insn *xi = next_nonnote_nondebug_insn (label_ref_label (x));
+ rtx_insn *yi = next_nonnote_nondebug_insn (label_ref_label (y));
+ while (xi && LABEL_P (xi))
+ xi = next_nonnote_nondebug_insn (xi);
+ while (yi && LABEL_P (yi))
+ yi = next_nonnote_nondebug_insn (yi);
+ return xi == yi;
+ }
case SYMBOL_REF:
return XSTR (x, 0) == XSTR (y, 0);
}
break;
+ case 'p':
+ if (maybe_ne (SUBREG_BYTE (x), SUBREG_BYTE (y)))
+ return 0;
+ break;
+
case 't':
if (XTREE (x, i) != XTREE (y, i))
return 0;