#include "system.h"
#include "coretypes.h"
#include "tm.h"
-#include "toplev.h"
+#include "diagnostic-core.h"
#include "rtl.h"
#include "tm_p.h"
#include "hard-reg-set.h"
#include "insn-config.h"
#include "insn-attr.h"
#include "except.h"
-#include "toplev.h"
#include "recog.h"
#include "sched-int.h"
#include "params.h"
#define CHECK (false)
#endif
+/* In deps->last_pending_memory_flush marks JUMP_INSNs that weren't
+ added to the list because of flush_pending_lists, stands just
+ for itself and not for any other pending memory reads/writes. */
+#define NON_FLUSH_JUMP_KIND REG_DEP_ANTI
+#define NON_FLUSH_JUMP_P(x) (REG_NOTE_KIND (x) == NON_FLUSH_JUMP_KIND)
+
/* Holds current parameters for the dependency analyzer. */
struct sched_deps_info_def *sched_deps_info;
static int deps_may_trap_p (const_rtx);
static void add_dependence_list (rtx, rtx, int, enum reg_note);
-static void add_dependence_list_and_free (struct deps *, rtx,
+static void add_dependence_list_and_free (struct deps_desc *, rtx,
rtx *, int, enum reg_note);
static void delete_all_dependences (rtx);
static void fixup_sched_groups (rtx);
-static void flush_pending_lists (struct deps *, rtx, int, int);
-static void sched_analyze_1 (struct deps *, rtx, rtx);
-static void sched_analyze_2 (struct deps *, rtx, rtx);
-static void sched_analyze_insn (struct deps *, rtx, rtx);
+static void flush_pending_lists (struct deps_desc *, rtx, int, int);
+static void sched_analyze_1 (struct deps_desc *, rtx, rtx);
+static void sched_analyze_2 (struct deps_desc *, rtx, rtx);
+static void sched_analyze_insn (struct deps_desc *, rtx, rtx);
static bool sched_has_condition_p (const_rtx);
static int conditions_mutex_p (const_rtx, const_rtx, bool, bool);
/* The following instructions, which depend on a speculatively scheduled
instruction, cannot be speculatively scheduled along. */
{
- if (may_trap_p (PATTERN (insn)))
- /* If instruction might trap, it cannot be speculatively scheduled.
+ if (may_trap_or_fault_p (PATTERN (insn)))
+ /* If instruction might fault, it cannot be speculatively scheduled.
For control speculation it's obvious why and for data speculation
it's because the insn might get wrong input if speculation
wasn't successful. */
is not readonly. */
static void
-add_dependence_list_and_free (struct deps *deps, rtx insn, rtx *listp,
+add_dependence_list_and_free (struct deps_desc *deps, rtx insn, rtx *listp,
int uncond, enum reg_note dep_type)
{
rtx list, next;
- if (deps->readonly)
+ /* We don't want to short-circuit dependencies involving debug
+ insns, because they may cause actual dependencies to be
+ disregarded. */
+ if (deps->readonly || DEBUG_INSN_P (insn))
{
add_dependence_list (insn, *listp, uncond, dep_type);
return;
delete_all_dependences (insn);
- prev_nonnote = prev_nonnote_insn (insn);
- while (DEBUG_INSN_P (prev_nonnote))
- prev_nonnote = prev_nonnote_insn (prev_nonnote);
+ prev_nonnote = prev_nonnote_nondebug_insn (insn);
if (BLOCK_FOR_INSN (insn) == BLOCK_FOR_INSN (prev_nonnote)
&& ! sched_insns_conditions_mutex_p (insn, prev_nonnote))
add_dependence (insn, prev_nonnote, REG_DEP_ANTI);
so that we can do memory aliasing on it. */
static void
-add_insn_mem_dependence (struct deps *deps, bool read_p,
+add_insn_mem_dependence (struct deps_desc *deps, bool read_p,
rtx insn, rtx mem)
{
rtx *insn_list;
dependencies for a read operation, similarly with FOR_WRITE. */
static void
-flush_pending_lists (struct deps *deps, rtx insn, int for_read,
+flush_pending_lists (struct deps_desc *deps, rtx insn, int for_read,
int for_write)
{
if (for_write)
/* Set up insn register uses for INSN and dependency context DEPS. */
static void
-setup_insn_reg_uses (struct deps *deps, rtx insn)
+setup_insn_reg_uses (struct deps_desc *deps, rtx insn)
{
unsigned i;
reg_set_iterator rsi;
/* Extend reg info for the deps context DEPS given that
we have just generated a register numbered REGNO. */
static void
-extend_deps_reg_info (struct deps *deps, int regno)
+extend_deps_reg_info (struct deps_desc *deps, int regno)
{
int max_regno = regno + 1;
CLOBBER, PRE_DEC, POST_DEC, PRE_INC, POST_INC or USE. */
static void
-sched_analyze_reg (struct deps *deps, int regno, enum machine_mode mode,
+sched_analyze_reg (struct deps_desc *deps, int regno, enum machine_mode mode,
enum rtx_code ref, rtx insn)
{
/* We could emit new pseudos in renaming. Extend the reg structures. */
destination of X, and reads of everything mentioned. */
static void
-sched_analyze_1 (struct deps *deps, rtx x, rtx insn)
+sched_analyze_1 (struct deps_desc *deps, rtx x, rtx insn)
{
rtx dest = XEXP (x, 0);
enum rtx_code code = GET_CODE (x);
/* Analyze the uses of memory and registers in rtx X in INSN. */
static void
-sched_analyze_2 (struct deps *deps, rtx x, rtx insn)
+sched_analyze_2 (struct deps_desc *deps, rtx x, rtx insn)
{
int i;
int j;
for (u = deps->last_pending_memory_flush; u; u = XEXP (u, 1))
{
- if (! JUMP_P (XEXP (u, 0)))
+ if (! NON_FLUSH_JUMP_P (u))
add_dependence (insn, XEXP (u, 0), REG_DEP_ANTI);
else if (deps_may_trap_p (x))
{
/* Analyze an INSN with pattern X to find all dependencies. */
static void
-sched_analyze_insn (struct deps *deps, rtx x, rtx insn)
+sched_analyze_insn (struct deps_desc *deps, rtx x, rtx insn)
{
RTX_CODE code = GET_CODE (x);
rtx link;
if (JUMP_P (insn))
{
rtx next;
- next = next_nonnote_insn (insn);
- while (next && DEBUG_INSN_P (next))
- next = next_nonnote_insn (next);
+ next = next_nonnote_nondebug_insn (insn);
if (next && BARRIER_P (next))
reg_pending_barrier = MOVE_BARRIER;
else
REG_DEP_ANTI);
for (u = deps->last_pending_memory_flush; u; u = XEXP (u, 1))
- if (! JUMP_P (XEXP (u, 0))
- || !sel_sched_p ())
+ if (! NON_FLUSH_JUMP_P (u) || !sel_sched_p ())
add_dependence (insn, XEXP (u, 0), REG_DEP_ANTI);
EXECUTE_IF_SET_IN_REG_SET (reg_pending_uses, 0, i, rsi)
This insn must be a simple move of a hard reg to a pseudo or
vice-versa.
- We must avoid moving these insns for correctness on
- SMALL_REGISTER_CLASS machines, and for special registers like
+ We must avoid moving these insns for correctness on targets
+ with small register classes, and for special registers like
PIC_OFFSET_TABLE_REGNUM. For simplicity, extend this to all
hard regs for all targets. */
/* Analyze INSN with DEPS as a context. */
void
-deps_analyze_insn (struct deps *deps, rtx insn)
+deps_analyze_insn (struct deps_desc *deps, rtx insn)
{
if (sched_deps_info->start_insn)
sched_deps_info->start_insn (insn);
if (deps->pending_flush_length++ > MAX_PENDING_LIST_LENGTH)
flush_pending_lists (deps, insn, true, true);
else
- deps->last_pending_memory_flush
- = alloc_INSN_LIST (insn, deps->last_pending_memory_flush);
+ {
+ deps->last_pending_memory_flush
+ = alloc_INSN_LIST (insn, deps->last_pending_memory_flush);
+ /* Signal to sched_analyze_insn that this jump stands
+ just for its own, not any other pending memory
+ reads/writes flush_pending_lists had to flush. */
+ PUT_REG_NOTE_KIND (deps->last_pending_memory_flush,
+ NON_FLUSH_JUMP_KIND);
+ }
}
sched_analyze_insn (deps, PATTERN (insn), insn);
/* Initialize DEPS for the new block beginning with HEAD. */
void
-deps_start_bb (struct deps *deps, rtx head)
+deps_start_bb (struct deps_desc *deps, rtx head)
{
gcc_assert (!deps->readonly);
hard registers correct. */
if (! reload_completed && !LABEL_P (head))
{
- rtx insn = prev_nonnote_insn (head);
+ rtx insn = prev_nonnote_nondebug_insn (head);
- while (insn && DEBUG_INSN_P (insn))
- insn = prev_nonnote_insn (insn);
if (insn && CALL_P (insn))
deps->in_post_call_group_p = post_call_initial;
}
/* Analyze every insn between HEAD and TAIL inclusive, creating backward
dependencies for each insn. */
void
-sched_analyze (struct deps *deps, rtx head, rtx tail)
+sched_analyze (struct deps_desc *deps, rtx head, rtx tail)
{
rtx insn;
\f
/* Initialize variables for region data dependence analysis.
When LAZY_REG_LAST is true, do not allocate reg_last array
- of struct deps immediately. */
+ of struct deps_desc immediately. */
void
-init_deps (struct deps *deps, bool lazy_reg_last)
+init_deps (struct deps_desc *deps, bool lazy_reg_last)
{
int max_reg = (reload_completed ? FIRST_PSEUDO_REGISTER : max_reg_num ());
/* Init only reg_last field of DEPS, which was not allocated before as
we inited DEPS lazily. */
void
-init_deps_reg_last (struct deps *deps)
+init_deps_reg_last (struct deps_desc *deps)
{
gcc_assert (deps && deps->max_reg > 0);
gcc_assert (deps->reg_last == NULL);
/* Free insn lists found in DEPS. */
void
-free_deps (struct deps *deps)
+free_deps (struct deps_desc *deps)
{
unsigned i;
reg_set_iterator rsi;
/* Remove INSN from dependence contexts DEPS. Caution: reg_conditional_sets
is not handled. */
void
-remove_from_deps (struct deps *deps, rtx insn)
+remove_from_deps (struct deps_desc *deps, rtx insn)
{
int removed;
unsigned i;
fprintf (f, "}");
}
-void
+DEBUG_FUNCTION void
debug_ds (ds_t s)
{
dump_ds (stderr, s);