+ if (DEBUG_INSN_P (insn))
+ DEBUG_INSN_SCHED_P (insn) = TRUE;
+
+ /* ??? 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. */
+
+ if (DEBUG_INSN_P (insn))
+ {
+ gcc_assert (DEBUG_INSN_SCHED_P (insn));
+ DEBUG_INSN_SCHED_P (insn) = FALSE;
+ }
+
+ 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 (sched_deps_info->generate_spec_deps)
+ /* 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);
+}
+
+/* Convert a dependence pointed to by SD_IT to be non-speculative. */
+static void
+change_spec_dep_to_hard (sd_iterator_def sd_it)
+{
+ dep_node_t node = DEP_LINK_NODE (*sd_it.linkp);
+ dep_link_t link = DEP_NODE_BACK (node);
+ dep_t dep = DEP_NODE_DEP (node);
+ rtx elem = DEP_PRO (dep);
+ rtx insn = DEP_CON (dep);
+
+ move_dep_link (link, INSN_SPEC_BACK_DEPS (insn), INSN_HARD_BACK_DEPS (insn));
+
+ DEP_STATUS (dep) &= ~SPECULATIVE;
+
+ if (true_dependency_cache != NULL)
+ /* Clear the cache entry. */
+ bitmap_clear_bit (&spec_dependency_cache[INSN_LUID (insn)],
+ INSN_LUID (elem));
+}
+
+/* Update DEP to incorporate information from NEW_DEP.
+ SD_IT points to DEP in case it should be moved to another list.
+ MEM1 and MEM2, if nonnull, correspond to memory locations in case if
+ data-speculative dependence should be updated. */
+static enum DEPS_ADJUST_RESULT
+update_dep (dep_t dep, dep_t new_dep,
+ sd_iterator_def sd_it ATTRIBUTE_UNUSED,
+ rtx mem1 ATTRIBUTE_UNUSED,
+ rtx mem2 ATTRIBUTE_UNUSED)
+{
+ enum DEPS_ADJUST_RESULT res = DEP_PRESENT;
+ enum reg_note old_type = DEP_TYPE (dep);
+
+ /* If this is a more restrictive type of dependence than the
+ existing one, then change the existing dependence to this
+ type. */
+ if ((int) DEP_TYPE (new_dep) < (int) old_type)
+ {
+ DEP_TYPE (dep) = DEP_TYPE (new_dep);
+ res = DEP_CHANGED;
+ }
+
+ if (current_sched_info->flags & USE_DEPS_LIST)
+ /* Update DEP_STATUS. */
+ {
+ ds_t dep_status = DEP_STATUS (dep);
+ ds_t ds = DEP_STATUS (new_dep);
+ ds_t new_status = ds | dep_status;
+
+ if (new_status & SPECULATIVE)
+ /* Either existing dep or a dep we're adding or both are
+ speculative. */
+ {
+ if (!(ds & SPECULATIVE)
+ || !(dep_status & SPECULATIVE))
+ /* The new dep can't be speculative. */
+ {
+ new_status &= ~SPECULATIVE;
+
+ if (dep_status & SPECULATIVE)
+ /* The old dep was speculative, but now it
+ isn't. */
+ change_spec_dep_to_hard (sd_it);
+ }
+ else
+ {
+ /* Both are speculative. Merge probabilities. */
+ if (mem1 != NULL)
+ {
+ dw_t dw;
+
+ dw = estimate_dep_weak (mem1, mem2);
+ ds = set_dep_weak (ds, BEGIN_DATA, dw);
+ }
+
+ new_status = ds_merge (dep_status, ds);
+ }
+ }
+
+ ds = new_status;
+
+ if (dep_status != ds)
+ {
+ DEP_STATUS (dep) = ds;
+ res = DEP_CHANGED;
+ }
+ }
+
+ if (true_dependency_cache != NULL
+ && res == DEP_CHANGED)
+ update_dependency_caches (dep, old_type);
+
+ return res;
+}
+
+/* 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 or nothing has
+ been updated at all. */
+static enum DEPS_ADJUST_RESULT
+add_or_update_dep_1 (dep_t new_dep, bool resolved_p,
+ rtx mem1 ATTRIBUTE_UNUSED, rtx mem2 ATTRIBUTE_UNUSED)
+{
+ bool maybe_present_p = true;
+ bool present_p = false;
+
+ gcc_assert (INSN_P (DEP_PRO (new_dep)) && INSN_P (DEP_CON (new_dep))
+ && DEP_PRO (new_dep) != DEP_CON (new_dep));
+
+#ifdef ENABLE_CHECKING
+ check_dep (new_dep, mem1 != NULL);
+#endif
+
+ if (true_dependency_cache != NULL)
+ {
+ switch (ask_dependency_caches (new_dep))
+ {
+ case DEP_PRESENT:
+ return DEP_PRESENT;
+
+ case DEP_CHANGED:
+ maybe_present_p = true;
+ present_p = true;
+ break;
+
+ case DEP_CREATED:
+ maybe_present_p = false;
+ present_p = false;
+ break;
+
+ default:
+ gcc_unreachable ();
+ break;
+ }
+ }
+
+ /* Check that we don't already have this dependence. */
+ if (maybe_present_p)
+ {
+ dep_t present_dep;
+ sd_iterator_def sd_it;
+
+ gcc_assert (true_dependency_cache == NULL || present_p);
+
+ present_dep = sd_find_dep_between_no_cache (DEP_PRO (new_dep),
+ DEP_CON (new_dep),
+ resolved_p, &sd_it);
+
+ if (present_dep != NULL)
+ /* We found an existing dependency between ELEM and INSN. */
+ return update_dep (present_dep, new_dep, sd_it, mem1, mem2);
+ else
+ /* We didn't find a dep, it shouldn't present in the cache. */
+ gcc_assert (!present_p);
+ }
+
+ /* Might want to check one level of transitivity to save conses.
+ This check should be done in maybe_add_or_update_dep_1.
+ Since we made it to add_or_update_dep_1, we must create
+ (or update) a link. */
+
+ if (mem1 != NULL_RTX)
+ {
+ gcc_assert (sched_deps_info->generate_spec_deps);
+ DEP_STATUS (new_dep) = set_dep_weak (DEP_STATUS (new_dep), BEGIN_DATA,
+ estimate_dep_weak (mem1, mem2));
+ }
+
+ sd_add_dep (new_dep, resolved_p);
+
+ return DEP_CREATED;
+}
+
+/* Initialize BACK_LIST_PTR with consumer's backward list and
+ FORW_LIST_PTR with producer's forward list. If RESOLVED_P is true
+ initialize with lists that hold resolved deps. */
+static void
+get_back_and_forw_lists (dep_t dep, bool resolved_p,
+ deps_list_t *back_list_ptr,
+ deps_list_t *forw_list_ptr)
+{
+ rtx con = DEP_CON (dep);
+
+ if (!resolved_p)
+ {
+ if ((current_sched_info->flags & DO_SPECULATION)
+ && (DEP_STATUS (dep) & SPECULATIVE))
+ *back_list_ptr = INSN_SPEC_BACK_DEPS (con);
+ else
+ *back_list_ptr = INSN_HARD_BACK_DEPS (con);
+
+ *forw_list_ptr = INSN_FORW_DEPS (DEP_PRO (dep));
+ }
+ else
+ {
+ *back_list_ptr = INSN_RESOLVED_BACK_DEPS (con);
+ *forw_list_ptr = INSN_RESOLVED_FORW_DEPS (DEP_PRO (dep));
+ }
+}
+
+/* Add dependence described by DEP.
+ If RESOLVED_P is true treat the dependence as a resolved one. */
+void
+sd_add_dep (dep_t dep, bool resolved_p)
+{
+ dep_node_t n = create_dep_node ();
+ deps_list_t con_back_deps;
+ deps_list_t pro_forw_deps;
+ rtx elem = DEP_PRO (dep);
+ rtx insn = DEP_CON (dep);
+
+ gcc_assert (INSN_P (insn) && INSN_P (elem) && insn != elem);
+
+ if ((current_sched_info->flags & DO_SPECULATION)
+ && !sched_insn_is_legitimate_for_speculation_p (insn, DEP_STATUS (dep)))
+ DEP_STATUS (dep) &= ~SPECULATIVE;
+
+ copy_dep (DEP_NODE_DEP (n), dep);
+
+ get_back_and_forw_lists (dep, resolved_p, &con_back_deps, &pro_forw_deps);
+
+ add_to_deps_list (DEP_NODE_BACK (n), con_back_deps);
+
+#ifdef ENABLE_CHECKING
+ check_dep (dep, false);
+#endif
+
+ add_to_deps_list (DEP_NODE_FORW (n), pro_forw_deps);
+
+ /* If we are adding a dependency to INSN's LOG_LINKs, then note that
+ in the bitmap caches of dependency information. */
+ if (true_dependency_cache != NULL)
+ set_dependency_caches (dep);
+}
+
+/* Add or update backward dependence between INSN and ELEM
+ with given type DEP_TYPE and dep_status DS.
+ This function is a convenience wrapper. */
+enum DEPS_ADJUST_RESULT
+sd_add_or_update_dep (dep_t dep, bool resolved_p)
+{
+ return add_or_update_dep_1 (dep, resolved_p, NULL_RTX, NULL_RTX);
+}
+
+/* Resolved dependence pointed to by SD_IT.
+ SD_IT will advance to the next element. */
+void
+sd_resolve_dep (sd_iterator_def sd_it)
+{
+ dep_node_t node = DEP_LINK_NODE (*sd_it.linkp);
+ dep_t dep = DEP_NODE_DEP (node);
+ rtx pro = DEP_PRO (dep);
+ rtx con = DEP_CON (dep);
+
+ if ((current_sched_info->flags & DO_SPECULATION)
+ && (DEP_STATUS (dep) & SPECULATIVE))
+ move_dep_link (DEP_NODE_BACK (node), INSN_SPEC_BACK_DEPS (con),
+ INSN_RESOLVED_BACK_DEPS (con));
+ else
+ move_dep_link (DEP_NODE_BACK (node), INSN_HARD_BACK_DEPS (con),
+ INSN_RESOLVED_BACK_DEPS (con));
+
+ move_dep_link (DEP_NODE_FORW (node), INSN_FORW_DEPS (pro),
+ INSN_RESOLVED_FORW_DEPS (pro));
+}
+
+/* Make TO depend on all the FROM's producers.
+ If RESOLVED_P is true add dependencies to the resolved lists. */
+void
+sd_copy_back_deps (rtx to, rtx from, bool resolved_p)
+{
+ sd_list_types_def list_type;
+ sd_iterator_def sd_it;
+ dep_t dep;
+
+ list_type = resolved_p ? SD_LIST_RES_BACK : SD_LIST_BACK;
+
+ FOR_EACH_DEP (from, list_type, sd_it, dep)
+ {
+ dep_def _new_dep, *new_dep = &_new_dep;
+
+ copy_dep (new_dep, dep);
+ DEP_CON (new_dep) = to;
+ sd_add_dep (new_dep, resolved_p);
+ }
+}
+
+/* Remove a dependency referred to by SD_IT.
+ SD_IT will point to the next dependence after removal. */
+void
+sd_delete_dep (sd_iterator_def sd_it)
+{
+ dep_node_t n = DEP_LINK_NODE (*sd_it.linkp);
+ dep_t dep = DEP_NODE_DEP (n);
+ rtx pro = DEP_PRO (dep);
+ rtx con = DEP_CON (dep);
+ deps_list_t con_back_deps;
+ deps_list_t pro_forw_deps;
+
+ if (true_dependency_cache != NULL)
+ {
+ int elem_luid = INSN_LUID (pro);
+ int insn_luid = INSN_LUID (con);
+
+ bitmap_clear_bit (&true_dependency_cache[insn_luid], elem_luid);
+ bitmap_clear_bit (&anti_dependency_cache[insn_luid], elem_luid);
+ bitmap_clear_bit (&output_dependency_cache[insn_luid], elem_luid);
+
+ if (current_sched_info->flags & DO_SPECULATION)
+ bitmap_clear_bit (&spec_dependency_cache[insn_luid], elem_luid);
+ }
+
+ get_back_and_forw_lists (dep, sd_it.resolved_p,
+ &con_back_deps, &pro_forw_deps);
+
+ remove_from_deps_list (DEP_NODE_BACK (n), con_back_deps);
+ remove_from_deps_list (DEP_NODE_FORW (n), pro_forw_deps);
+
+ delete_dep_node (n);
+}
+
+/* Dump size of the lists. */
+#define DUMP_LISTS_SIZE (2)
+
+/* Dump dependencies of the lists. */
+#define DUMP_LISTS_DEPS (4)
+
+/* Dump all information about the lists. */
+#define DUMP_LISTS_ALL (DUMP_LISTS_SIZE | DUMP_LISTS_DEPS)
+
+/* Dump deps_lists of INSN specified by TYPES to DUMP.
+ FLAGS is a bit mask specifying what information about the lists needs
+ to be printed.
+ If FLAGS has the very first bit set, then dump all information about
+ the lists and propagate this bit into the callee dump functions. */
+static void
+dump_lists (FILE *dump, rtx insn, sd_list_types_def types, int flags)
+{
+ sd_iterator_def sd_it;
+ dep_t dep;
+ int all;
+
+ all = (flags & 1);
+
+ if (all)
+ flags |= DUMP_LISTS_ALL;
+
+ fprintf (dump, "[");
+
+ if (flags & DUMP_LISTS_SIZE)
+ fprintf (dump, "%d; ", sd_lists_size (insn, types));
+
+ if (flags & DUMP_LISTS_DEPS)
+ {
+ FOR_EACH_DEP (insn, types, sd_it, dep)
+ {
+ dump_dep (dump, dep, dump_dep_flags | all);
+ fprintf (dump, " ");
+ }
+ }
+}
+
+/* Dump all information about deps_lists of INSN specified by TYPES
+ to STDERR. */
+void
+sd_debug_lists (rtx insn, sd_list_types_def types)
+{
+ dump_lists (stderr, insn, types, 1);
+ fprintf (stderr, "\n");
+}
+
+/* A convenience wrapper to operate on an entire list. */
+
+static void
+add_dependence_list (rtx insn, rtx list, int uncond, enum reg_note dep_type)
+{
+ for (; list; list = XEXP (list, 1))
+ {
+ if (uncond || ! sched_insns_conditions_mutex_p (insn, XEXP (list, 0)))
+ add_dependence (insn, XEXP (list, 0), dep_type);
+ }
+}
+
+/* Similar, but free *LISTP at the same time, when the context
+ is not readonly. */
+
+static void
+add_dependence_list_and_free (struct deps *deps, rtx insn, rtx *listp,
+ int uncond, enum reg_note dep_type)
+{
+ rtx list, next;
+
+ if (deps->readonly)
+ {
+ add_dependence_list (insn, *listp, uncond, dep_type);
+ return;
+ }
+
+ for (list = *listp, *listp = NULL; list ; list = next)
+ {
+ next = XEXP (list, 1);
+ if (uncond || ! sched_insns_conditions_mutex_p (insn, XEXP (list, 0)))
+ add_dependence (insn, XEXP (list, 0), dep_type);
+ free_INSN_LIST_node (list);
+ }
+}
+
+/* Remove all occurences of INSN from LIST. Return the number of
+ occurences removed. */
+
+static int
+remove_from_dependence_list (rtx insn, rtx* listp)
+{
+ int removed = 0;
+
+ while (*listp)
+ {
+ if (XEXP (*listp, 0) == insn)
+ {
+ remove_free_INSN_LIST_node (listp);
+ removed++;
+ continue;
+ }
+
+ listp = &XEXP (*listp, 1);
+ }
+
+ return removed;
+}
+
+/* Same as above, but process two lists at once. */
+static int
+remove_from_both_dependence_lists (rtx insn, rtx *listp, rtx *exprp)
+{
+ int removed = 0;
+
+ while (*listp)
+ {
+ if (XEXP (*listp, 0) == insn)
+ {
+ remove_free_INSN_LIST_node (listp);
+ remove_free_EXPR_LIST_node (exprp);
+ removed++;
+ continue;
+ }
+
+ listp = &XEXP (*listp, 1);
+ exprp = &XEXP (*exprp, 1);
+ }
+
+ return removed;
+}
+
+/* Clear all dependencies for an insn. */
+static void