+#ifdef INSN_SCHEDULING
+
+#ifdef ENABLE_CHECKING
+#define CHECK (true)
+#else
+#define CHECK (false)
+#endif
+
+/* Return the major type present in the DS. */
+enum reg_note
+ds_to_dk (ds_t ds)
+{
+ if (ds & DEP_TRUE)
+ return REG_DEP_TRUE;
+
+ if (ds & DEP_OUTPUT)
+ return REG_DEP_OUTPUT;
+
+ gcc_assert (ds & DEP_ANTI);
+
+ return REG_DEP_ANTI;
+}
+
+/* Return equivalent dep_status. */
+ds_t
+dk_to_ds (enum reg_note dk)
+{
+ switch (dk)
+ {
+ case REG_DEP_TRUE:
+ return DEP_TRUE;
+
+ case REG_DEP_OUTPUT:
+ return DEP_OUTPUT;
+
+ default:
+ gcc_assert (dk == REG_DEP_ANTI);
+ return DEP_ANTI;
+ }
+}
+
+/* Functions to operate with dependence information container - dep_t. */
+
+/* Init DEP with the arguments. */
+void
+init_dep_1 (dep_t dep, rtx pro, rtx con, enum reg_note type, ds_t ds)
+{
+ DEP_PRO (dep) = pro;
+ DEP_CON (dep) = con;
+ DEP_TYPE (dep) = type;
+ DEP_STATUS (dep) = ds;
+}
+
+/* Init DEP with the arguments.
+ While most of the scheduler (including targets) only need the major type
+ of the dependency, it is convenient to hide full dep_status from them. */
+void
+init_dep (dep_t dep, rtx pro, rtx con, enum reg_note kind)
+{
+ ds_t ds;
+
+ if ((current_sched_info->flags & USE_DEPS_LIST))
+ ds = dk_to_ds (kind);
+ else
+ ds = -1;
+
+ init_dep_1 (dep, pro, con, kind, ds);
+}
+
+/* Make a copy of FROM in TO. */
+static void
+copy_dep (dep_t to, dep_t from)
+{
+ memcpy (to, from, sizeof (*to));
+}
+
+static void dump_ds (FILE *, ds_t);
+
+/* Define flags for dump_dep (). */
+
+/* Dump producer of the dependence. */
+#define DUMP_DEP_PRO (2)
+
+/* Dump consumer of the dependence. */
+#define DUMP_DEP_CON (4)
+
+/* Dump type of the dependence. */
+#define DUMP_DEP_TYPE (8)
+
+/* Dump status of the dependence. */
+#define DUMP_DEP_STATUS (16)
+
+/* Dump all information about the dependence. */
+#define DUMP_DEP_ALL (DUMP_DEP_PRO | DUMP_DEP_CON | DUMP_DEP_TYPE \
+ |DUMP_DEP_STATUS)
+
+/* Dump DEP to DUMP.
+ FLAGS is a bit mask specifying what information about DEP needs
+ to be printed.
+ If FLAGS has the very first bit set, then dump all information about DEP
+ and propagate this bit into the callee dump functions. */
+static void
+dump_dep (FILE *dump, dep_t dep, int flags)
+{
+ if (flags & 1)
+ flags |= DUMP_DEP_ALL;
+
+ fprintf (dump, "<");
+
+ if (flags & DUMP_DEP_PRO)
+ fprintf (dump, "%d; ", INSN_UID (DEP_PRO (dep)));
+
+ if (flags & DUMP_DEP_CON)
+ fprintf (dump, "%d; ", INSN_UID (DEP_CON (dep)));
+
+ if (flags & DUMP_DEP_TYPE)
+ {
+ char t;
+ enum reg_note type = DEP_TYPE (dep);
+
+ switch (type)
+ {
+ case REG_DEP_TRUE:
+ t = 't';
+ break;
+
+ case REG_DEP_OUTPUT:
+ t = 'o';
+ break;
+
+ case REG_DEP_ANTI:
+ t = 'a';
+ break;
+
+ default:
+ gcc_unreachable ();
+ break;
+ }
+
+ fprintf (dump, "%c; ", t);
+ }
+
+ if (flags & DUMP_DEP_STATUS)
+ {
+ if (current_sched_info->flags & USE_DEPS_LIST)
+ dump_ds (dump, DEP_STATUS (dep));
+ }
+
+ fprintf (dump, ">");
+}
+
+/* Default flags for dump_dep (). */
+static int dump_dep_flags = (DUMP_DEP_PRO | DUMP_DEP_CON);
+
+/* Dump all fields of DEP to STDERR. */
+void
+sd_debug_dep (dep_t dep)
+{
+ dump_dep (stderr, dep, 1);
+ fprintf (stderr, "\n");
+}
+
+/* Functions to operate with a single link from the dependencies lists -
+ dep_link_t. */
+
+/* Attach L to appear after link X whose &DEP_LINK_NEXT (X) is given by
+ PREV_NEXT_P. */
+static void
+attach_dep_link (dep_link_t l, dep_link_t *prev_nextp)
+{
+ dep_link_t next = *prev_nextp;
+
+ gcc_assert (DEP_LINK_PREV_NEXTP (l) == NULL
+ && DEP_LINK_NEXT (l) == NULL);
+
+ /* Init node being inserted. */
+ DEP_LINK_PREV_NEXTP (l) = prev_nextp;
+ DEP_LINK_NEXT (l) = next;
+
+ /* Fix next node. */
+ if (next != NULL)
+ {
+ gcc_assert (DEP_LINK_PREV_NEXTP (next) == prev_nextp);
+
+ DEP_LINK_PREV_NEXTP (next) = &DEP_LINK_NEXT (l);
+ }
+
+ /* Fix prev node. */
+ *prev_nextp = l;
+}
+
+/* Add dep_link LINK to deps_list L. */
+static void
+add_to_deps_list (dep_link_t link, deps_list_t l)
+{
+ attach_dep_link (link, &DEPS_LIST_FIRST (l));
+
+ ++DEPS_LIST_N_LINKS (l);
+}
+
+/* Detach dep_link L from the list. */
+static void
+detach_dep_link (dep_link_t l)
+{
+ dep_link_t *prev_nextp = DEP_LINK_PREV_NEXTP (l);
+ dep_link_t next = DEP_LINK_NEXT (l);
+
+ *prev_nextp = next;
+
+ if (next != NULL)
+ DEP_LINK_PREV_NEXTP (next) = prev_nextp;
+
+ DEP_LINK_PREV_NEXTP (l) = NULL;
+ DEP_LINK_NEXT (l) = NULL;
+}
+
+/* Remove link LINK from list LIST. */
+static void
+remove_from_deps_list (dep_link_t link, deps_list_t list)
+{
+ detach_dep_link (link);
+
+ --DEPS_LIST_N_LINKS (list);
+}
+
+/* Move link LINK from list FROM to list TO. */
+static void
+move_dep_link (dep_link_t link, deps_list_t from, deps_list_t to)
+{
+ remove_from_deps_list (link, from);
+ add_to_deps_list (link, to);
+}
+
+/* Return true of LINK is not attached to any list. */
+static bool
+dep_link_is_detached_p (dep_link_t link)
+{
+ return DEP_LINK_PREV_NEXTP (link) == NULL;
+}
+
+/* Pool to hold all dependency nodes (dep_node_t). */
+static alloc_pool dn_pool;
+
+/* Number of dep_nodes out there. */
+static int dn_pool_diff = 0;
+
+/* Create a dep_node. */
+static dep_node_t
+create_dep_node (void)
+{
+ dep_node_t n = (dep_node_t) pool_alloc (dn_pool);
+ dep_link_t back = DEP_NODE_BACK (n);
+ dep_link_t forw = DEP_NODE_FORW (n);
+
+ DEP_LINK_NODE (back) = n;
+ DEP_LINK_NEXT (back) = NULL;
+ DEP_LINK_PREV_NEXTP (back) = NULL;
+
+ DEP_LINK_NODE (forw) = n;
+ DEP_LINK_NEXT (forw) = NULL;
+ DEP_LINK_PREV_NEXTP (forw) = NULL;
+
+ ++dn_pool_diff;
+
+ return n;
+}
+
+/* Delete dep_node N. N must not be connected to any deps_list. */
+static void
+delete_dep_node (dep_node_t n)
+{
+ gcc_assert (dep_link_is_detached_p (DEP_NODE_BACK (n))
+ && dep_link_is_detached_p (DEP_NODE_FORW (n)));
+
+ --dn_pool_diff;
+
+ pool_free (dn_pool, n);
+}
+
+/* Pool to hold dependencies lists (deps_list_t). */
+static alloc_pool dl_pool;
+
+/* Number of deps_lists out there. */
+static int dl_pool_diff = 0;
+
+/* Functions to operate with dependences lists - deps_list_t. */
+
+/* Return true if list L is empty. */
+static bool
+deps_list_empty_p (deps_list_t l)
+{
+ return DEPS_LIST_N_LINKS (l) == 0;
+}
+
+/* Create a new deps_list. */
+static deps_list_t
+create_deps_list (void)
+{
+ deps_list_t l = (deps_list_t) pool_alloc (dl_pool);
+
+ DEPS_LIST_FIRST (l) = NULL;
+ DEPS_LIST_N_LINKS (l) = 0;
+
+ ++dl_pool_diff;
+ return l;
+}
+
+/* Free deps_list L. */
+static void
+free_deps_list (deps_list_t l)
+{
+ gcc_assert (deps_list_empty_p (l));
+
+ --dl_pool_diff;
+
+ pool_free (dl_pool, l);
+}
+
+/* Return true if there is no dep_nodes and deps_lists out there.
+ After the region is scheduled all the dependency nodes and lists
+ should [generally] be returned to pool. */
+bool
+deps_pools_are_empty_p (void)
+{
+ return dn_pool_diff == 0 && dl_pool_diff == 0;
+}
+
+/* Remove all elements from L. */
+static void
+clear_deps_list (deps_list_t l)
+{
+ do
+ {
+ dep_link_t link = DEPS_LIST_FIRST (l);
+
+ if (link == NULL)
+ break;
+
+ remove_from_deps_list (link, l);
+ }
+ while (1);
+}
+
+static regset reg_pending_sets;
+static regset reg_pending_clobbers;
+static regset reg_pending_uses;
+
+/* The following enumeration values tell us what dependencies we
+ should use to implement the barrier. We use true-dependencies for
+ TRUE_BARRIER and anti-dependencies for MOVE_BARRIER. */
+enum reg_pending_barrier_mode
+{
+ NOT_A_BARRIER = 0,
+ MOVE_BARRIER,
+ TRUE_BARRIER
+};
+
+static enum reg_pending_barrier_mode reg_pending_barrier;
+
+/* To speed up the test for duplicate dependency links we keep a
+ record of dependencies created by add_dependence when the average
+ number of instructions in a basic block is very large.
+
+ Studies have shown that there is typically around 5 instructions between
+ branches for typical C code. So we can make a guess that the average
+ basic block is approximately 5 instructions long; we will choose 100X
+ the average size as a very large basic block.
+
+ Each insn has associated bitmaps for its dependencies. Each bitmap
+ has enough entries to represent a dependency on any other insn in
+ the insn chain. All bitmap for true dependencies cache is
+ allocated then the rest two ones are also allocated. */
+static bitmap_head *true_dependency_cache;
+static bitmap_head *output_dependency_cache;
+static bitmap_head *anti_dependency_cache;
+static bitmap_head *spec_dependency_cache;
+static int cache_size;
+
+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 (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 rtx sched_get_condition (const_rtx);
+static int conditions_mutex_p (const_rtx, const_rtx);
+
+static enum DEPS_ADJUST_RESULT maybe_add_or_update_dep_1 (dep_t, bool,
+ rtx, rtx);
+static enum DEPS_ADJUST_RESULT add_or_update_dep_1 (dep_t, bool, rtx, rtx);
+
+static dw_t estimate_dep_weak (rtx, rtx);
+#ifdef ENABLE_CHECKING
+static void check_dep (dep_t, bool);
+#endif
+\f
+/* Return nonzero if a load of the memory reference MEM can cause a trap. */
+
+static int
+deps_may_trap_p (const_rtx mem)
+{
+ const_rtx addr = XEXP (mem, 0);
+
+ if (REG_P (addr) && REGNO (addr) >= FIRST_PSEUDO_REGISTER)
+ {
+ const_rtx t = get_reg_known_value (REGNO (addr));
+ if (t)
+ addr = t;
+ }
+ return rtx_addr_can_trap_p (addr);
+}
+\f
+/* Find the condition under which INSN is executed. */
+
+static rtx
+sched_get_condition (const_rtx insn)
+{
+ rtx pat = PATTERN (insn);
+ rtx src;
+
+ if (pat == 0)
+ return 0;
+
+ if (GET_CODE (pat) == COND_EXEC)
+ return COND_EXEC_TEST (pat);
+
+ if (!any_condjump_p (insn) || !onlyjump_p (insn))
+ return 0;
+
+ src = SET_SRC (pc_set (insn));
+
+ if (XEXP (src, 2) == pc_rtx)
+ return XEXP (src, 0);
+ else if (XEXP (src, 1) == pc_rtx)
+ {
+ rtx cond = XEXP (src, 0);
+ enum rtx_code revcode = reversed_comparison_code (cond, insn);
+
+ if (revcode == UNKNOWN)
+ return 0;
+ return gen_rtx_fmt_ee (revcode, GET_MODE (cond), XEXP (cond, 0),
+ XEXP (cond, 1));
+ }
+
+ return 0;
+}
+
+\f
+/* Return nonzero if conditions COND1 and COND2 can never be both true. */
+
+static int
+conditions_mutex_p (const_rtx cond1, const_rtx cond2)
+{
+ if (COMPARISON_P (cond1)
+ && COMPARISON_P (cond2)
+ && GET_CODE (cond1) == reversed_comparison_code (cond2, NULL)
+ && XEXP (cond1, 0) == XEXP (cond2, 0)
+ && XEXP (cond1, 1) == XEXP (cond2, 1))
+ return 1;
+ return 0;
+}
+
+/* Return true if insn1 and insn2 can never depend on one another because
+ the conditions under which they are executed are mutually exclusive. */
+bool
+sched_insns_conditions_mutex_p (const_rtx insn1, const_rtx insn2)
+{
+ rtx cond1, cond2;
+
+ /* df doesn't handle conditional lifetimes entirely correctly;
+ calls mess up the conditional lifetimes. */
+ if (!CALL_P (insn1) && !CALL_P (insn2))
+ {
+ cond1 = sched_get_condition (insn1);
+ cond2 = sched_get_condition (insn2);
+ if (cond1 && cond2
+ && conditions_mutex_p (cond1, cond2)
+ /* Make sure first instruction doesn't affect condition of second
+ instruction if switched. */
+ && !modified_in_p (cond1, insn2)
+ /* Make sure second instruction doesn't affect condition of first
+ instruction if switched. */
+ && !modified_in_p (cond2, insn1))
+ return true;
+ }
+ return false;
+}
+\f
+
+/* Initialize LIST_PTR to point to one of the lists present in TYPES_PTR,
+ initialize RESOLVED_P_PTR with true if that list consists of resolved deps,
+ and remove the type of returned [through LIST_PTR] list from TYPES_PTR.
+ This function is used to switch sd_iterator to the next list.
+ !!! For internal use only. Might consider moving it to sched-int.h. */
+void
+sd_next_list (const_rtx insn, sd_list_types_def *types_ptr,
+ deps_list_t *list_ptr, bool *resolved_p_ptr)
+{
+ sd_list_types_def types = *types_ptr;
+
+ if (types & SD_LIST_HARD_BACK)
+ {
+ *list_ptr = INSN_HARD_BACK_DEPS (insn);
+ *resolved_p_ptr = false;
+ *types_ptr = types & ~SD_LIST_HARD_BACK;
+ }
+ else if (types & SD_LIST_SPEC_BACK)
+ {
+ *list_ptr = INSN_SPEC_BACK_DEPS (insn);
+ *resolved_p_ptr = false;
+ *types_ptr = types & ~SD_LIST_SPEC_BACK;
+ }
+ else if (types & SD_LIST_FORW)
+ {
+ *list_ptr = INSN_FORW_DEPS (insn);
+ *resolved_p_ptr = false;
+ *types_ptr = types & ~SD_LIST_FORW;
+ }
+ else if (types & SD_LIST_RES_BACK)
+ {
+ *list_ptr = INSN_RESOLVED_BACK_DEPS (insn);
+ *resolved_p_ptr = true;
+ *types_ptr = types & ~SD_LIST_RES_BACK;
+ }
+ else if (types & SD_LIST_RES_FORW)
+ {
+ *list_ptr = INSN_RESOLVED_FORW_DEPS (insn);
+ *resolved_p_ptr = true;
+ *types_ptr = types & ~SD_LIST_RES_FORW;
+ }
+ else
+ {
+ *list_ptr = NULL;
+ *resolved_p_ptr = false;
+ *types_ptr = SD_LIST_NONE;
+ }
+}
+
+/* Return the summary size of INSN's lists defined by LIST_TYPES. */
+int
+sd_lists_size (const_rtx insn, sd_list_types_def list_types)
+{
+ int size = 0;
+
+ while (list_types != SD_LIST_NONE)
+ {
+ deps_list_t list;
+ bool resolved_p;
+
+ sd_next_list (insn, &list_types, &list, &resolved_p);
+ size += DEPS_LIST_N_LINKS (list);
+ }
+
+ return size;
+}
+
+/* Return true if INSN's lists defined by LIST_TYPES are all empty. */
+bool
+sd_lists_empty_p (const_rtx insn, sd_list_types_def list_types)
+{
+ return sd_lists_size (insn, list_types) == 0;
+}
+
+/* Initialize data for INSN. */
+void
+sd_init_insn (rtx insn)
+{
+ INSN_HARD_BACK_DEPS (insn) = create_deps_list ();
+ INSN_SPEC_BACK_DEPS (insn) = create_deps_list ();
+ INSN_RESOLVED_BACK_DEPS (insn) = create_deps_list ();
+ INSN_FORW_DEPS (insn) = create_deps_list ();
+ INSN_RESOLVED_FORW_DEPS (insn) = create_deps_list ();
+
+ /* ??? It would be nice to allocate dependency caches here. */
+}
+
+/* Free data for INSN. */
+void
+sd_finish_insn (rtx insn)
+{
+ /* ??? It would be nice to deallocate dependency caches here. */
+
+ free_deps_list (INSN_HARD_BACK_DEPS (insn));
+ INSN_HARD_BACK_DEPS (insn) = NULL;
+
+ free_deps_list (INSN_SPEC_BACK_DEPS (insn));
+ INSN_SPEC_BACK_DEPS (insn) = NULL;
+
+ free_deps_list (INSN_RESOLVED_BACK_DEPS (insn));
+ INSN_RESOLVED_BACK_DEPS (insn) = NULL;
+
+ free_deps_list (INSN_FORW_DEPS (insn));
+ INSN_FORW_DEPS (insn) = NULL;
+
+ free_deps_list (INSN_RESOLVED_FORW_DEPS (insn));
+ INSN_RESOLVED_FORW_DEPS (insn) = NULL;
+}
+
+/* Find a dependency between producer PRO and consumer CON.
+ Search through resolved dependency lists if RESOLVED_P is true.
+ If no such dependency is found return NULL,
+ otherwise return the dependency and initialize SD_IT_PTR [if it is nonnull]
+ with an iterator pointing to it. */
+static dep_t
+sd_find_dep_between_no_cache (rtx pro, rtx con, bool resolved_p,
+ sd_iterator_def *sd_it_ptr)
+{
+ sd_list_types_def pro_list_type;
+ sd_list_types_def con_list_type;
+ sd_iterator_def sd_it;
+ dep_t dep;
+ bool found_p = false;
+
+ if (resolved_p)
+ {
+ pro_list_type = SD_LIST_RES_FORW;
+ con_list_type = SD_LIST_RES_BACK;
+ }
+ else
+ {
+ pro_list_type = SD_LIST_FORW;
+ con_list_type = SD_LIST_BACK;
+ }
+
+ /* Walk through either back list of INSN or forw list of ELEM
+ depending on which one is shorter. */
+ if (sd_lists_size (con, con_list_type) < sd_lists_size (pro, pro_list_type))
+ {
+ /* Find the dep_link with producer PRO in consumer's back_deps. */
+ FOR_EACH_DEP (con, con_list_type, sd_it, dep)
+ if (DEP_PRO (dep) == pro)
+ {
+ found_p = true;
+ break;
+ }
+ }
+ else
+ {
+ /* Find the dep_link with consumer CON in producer's forw_deps. */
+ FOR_EACH_DEP (pro, pro_list_type, sd_it, dep)
+ if (DEP_CON (dep) == con)
+ {
+ found_p = true;
+ break;
+ }
+ }
+
+ if (found_p)
+ {
+ if (sd_it_ptr != NULL)
+ *sd_it_ptr = sd_it;
+
+ return dep;
+ }
+
+ return NULL;
+}
+
+/* Find a dependency between producer PRO and consumer CON.
+ Use dependency [if available] to check if dependency is present at all.
+ Search through resolved dependency lists if RESOLVED_P is true.
+ If the dependency or NULL if none found. */
+dep_t
+sd_find_dep_between (rtx pro, rtx con, bool resolved_p)
+{
+ if (true_dependency_cache != NULL)
+ /* Avoiding the list walk below can cut compile times dramatically
+ for some code. */
+ {
+ int elem_luid = INSN_LUID (pro);
+ int insn_luid = INSN_LUID (con);
+
+ gcc_assert (output_dependency_cache != NULL
+ && anti_dependency_cache != NULL);
+
+ if (!bitmap_bit_p (&true_dependency_cache[insn_luid], elem_luid)
+ && !bitmap_bit_p (&output_dependency_cache[insn_luid], elem_luid)
+ && !bitmap_bit_p (&anti_dependency_cache[insn_luid], elem_luid))
+ return NULL;
+ }
+
+ return sd_find_dep_between_no_cache (pro, con, resolved_p, NULL);
+}
+
+/* Add or update a dependence described by DEP.
+ MEM1 and MEM2, if non-null, correspond to memory locations in case of
+ data speculation.
+
+ The function returns a value indicating if an old entry has been changed
+ or a new entry has been added to insn's backward deps.
+
+ This function merely checks if producer and consumer is the same insn
+ and doesn't create a dep in this case. Actual manipulation of
+ dependence data structures is performed in add_or_update_dep_1. */
+static enum DEPS_ADJUST_RESULT
+maybe_add_or_update_dep_1 (dep_t dep, bool resolved_p, rtx mem1, rtx mem2)
+{
+ rtx elem = DEP_PRO (dep);
+ rtx insn = DEP_CON (dep);
+
+ gcc_assert (INSN_P (insn) && INSN_P (elem));
+
+ /* Don't depend an insn on itself. */
+ if (insn == elem)
+ {
+ if (current_sched_info->flags & DO_SPECULATION)
+ /* INSN has an internal dependence, which we can't overcome. */
+ HAS_INTERNAL_DEP (insn) = 1;
+
+ return DEP_NODEP;
+ }
+
+ return add_or_update_dep_1 (dep, resolved_p, mem1, mem2);
+}
+
+/* Ask dependency caches what needs to be done for dependence DEP.
+ Return DEP_CREATED if new dependence should be created and there is no
+ need to try to find one searching the dependencies lists.
+ Return DEP_PRESENT if there already is a dependence described by DEP and
+ hence nothing is to be done.
+ Return DEP_CHANGED if there already is a dependence, but it should be
+ updated to incorporate additional information from DEP. */
+static enum DEPS_ADJUST_RESULT
+ask_dependency_caches (dep_t dep)
+{
+ int elem_luid = INSN_LUID (DEP_PRO (dep));
+ int insn_luid = INSN_LUID (DEP_CON (dep));
+
+ gcc_assert (true_dependency_cache != NULL
+ && output_dependency_cache != NULL
+ && anti_dependency_cache != NULL);
+
+ if (!(current_sched_info->flags & USE_DEPS_LIST))
+ {
+ enum reg_note present_dep_type;
+
+ if (bitmap_bit_p (&true_dependency_cache[insn_luid], elem_luid))
+ present_dep_type = REG_DEP_TRUE;
+ else if (bitmap_bit_p (&output_dependency_cache[insn_luid], elem_luid))
+ present_dep_type = REG_DEP_OUTPUT;
+ else if (bitmap_bit_p (&anti_dependency_cache[insn_luid], elem_luid))
+ present_dep_type = REG_DEP_ANTI;
+ else
+ /* There is no existing dep so it should be created. */
+ return DEP_CREATED;
+
+ if ((int) DEP_TYPE (dep) >= (int) present_dep_type)
+ /* DEP does not add anything to the existing dependence. */
+ return DEP_PRESENT;
+ }
+ else
+ {
+ ds_t present_dep_types = 0;
+
+ if (bitmap_bit_p (&true_dependency_cache[insn_luid], elem_luid))
+ present_dep_types |= DEP_TRUE;
+ if (bitmap_bit_p (&output_dependency_cache[insn_luid], elem_luid))
+ present_dep_types |= DEP_OUTPUT;
+ if (bitmap_bit_p (&anti_dependency_cache[insn_luid], elem_luid))
+ present_dep_types |= DEP_ANTI;
+
+ if (present_dep_types == 0)
+ /* There is no existing dep so it should be created. */
+ return DEP_CREATED;
+
+ if (!(current_sched_info->flags & DO_SPECULATION)
+ || !bitmap_bit_p (&spec_dependency_cache[insn_luid], elem_luid))
+ {
+ if ((present_dep_types | (DEP_STATUS (dep) & DEP_TYPES))
+ == present_dep_types)
+ /* DEP does not add anything to the existing dependence. */
+ return DEP_PRESENT;
+ }
+ else
+ {
+ /* Only true dependencies can be data speculative and
+ only anti dependencies can be control speculative. */
+ gcc_assert ((present_dep_types & (DEP_TRUE | DEP_ANTI))
+ == present_dep_types);
+
+ /* if (DEP is SPECULATIVE) then
+ ..we should update DEP_STATUS
+ else
+ ..we should reset existing dep to non-speculative. */
+ }
+ }
+
+ return DEP_CHANGED;
+}
+
+/* Set dependency caches according to DEP. */
+static void
+set_dependency_caches (dep_t dep)
+{
+ int elem_luid = INSN_LUID (DEP_PRO (dep));
+ int insn_luid = INSN_LUID (DEP_CON (dep));
+
+ if (!(current_sched_info->flags & USE_DEPS_LIST))
+ {
+ switch (DEP_TYPE (dep))
+ {
+ case REG_DEP_TRUE:
+ bitmap_set_bit (&true_dependency_cache[insn_luid], elem_luid);
+ break;
+
+ case REG_DEP_OUTPUT:
+ bitmap_set_bit (&output_dependency_cache[insn_luid], elem_luid);
+ break;
+
+ case REG_DEP_ANTI:
+ bitmap_set_bit (&anti_dependency_cache[insn_luid], elem_luid);
+ break;
+
+ default:
+ gcc_unreachable ();
+ }
+ }
+ else
+ {
+ ds_t ds = DEP_STATUS (dep);
+
+ if (ds & DEP_TRUE)
+ bitmap_set_bit (&true_dependency_cache[insn_luid], elem_luid);
+ if (ds & DEP_OUTPUT)
+ bitmap_set_bit (&output_dependency_cache[insn_luid], elem_luid);
+ if (ds & DEP_ANTI)
+ bitmap_set_bit (&anti_dependency_cache[insn_luid], elem_luid);
+
+ if (ds & SPECULATIVE)
+ {
+ gcc_assert (current_sched_info->flags & DO_SPECULATION);
+ bitmap_set_bit (&spec_dependency_cache[insn_luid], elem_luid);
+ }
+ }
+}
+
+/* Type of dependence DEP have changed from OLD_TYPE. Update dependency
+ caches accordingly. */
+static void
+update_dependency_caches (dep_t dep, enum reg_note old_type)
+{
+ int elem_luid = INSN_LUID (DEP_PRO (dep));
+ int insn_luid = INSN_LUID (DEP_CON (dep));
+
+ /* Clear corresponding cache entry because type of the link
+ may have changed. Keep them if we use_deps_list. */
+ if (!(current_sched_info->flags & USE_DEPS_LIST))
+ {
+ switch (old_type)
+ {
+ case REG_DEP_OUTPUT:
+ bitmap_clear_bit (&output_dependency_cache[insn_luid], elem_luid);
+ break;
+
+ case REG_DEP_ANTI:
+ bitmap_clear_bit (&anti_dependency_cache[insn_luid], elem_luid);
+ break;
+
+ default:
+ gcc_unreachable ();
+ }
+ }
+
+ set_dependency_caches (dep);
+}