def_info *def = defs[0];
if (auto set = safe_dyn_cast<set_info *> (def->prev_def ()))
- for (auto use : set->debug_insn_uses ())
+ for (auto use : iterate_safely (set->debug_insn_uses ()))
if (*use->insn () > *pair_dst)
// DEF is getting re-ordered above USE, fix up USE accordingly.
fixup_debug_use (attempt, use, def, base, wb_offset);
auto def = memory_access (insns[0]->defs ());
auto last_def = memory_access (insns[1]->defs ());
for (; def != last_def; def = def->next_def ())
- for (auto use : as_a<set_info *> (def)->debug_insn_uses ())
- {
- if (dump_file)
- fprintf (dump_file, " i%d: resetting debug use of mem\n",
- use->insn ()->uid ());
- reset_debug_use (use);
- }
+ {
+ auto set = as_a<set_info *> (def);
+ for (auto use : iterate_safely (set->debug_insn_uses ()))
+ {
+ if (dump_file)
+ fprintf (dump_file, " i%d: resetting debug use of mem\n",
+ use->insn ()->uid ());
+ reset_debug_use (use);
+ }
+ }
}
// Now let's take care of register uses, starting with debug uses
// Now that we've characterized the defs involved, go through the
// debug uses and determine how to update them (if needed).
- for (auto use : set->debug_insn_uses ())
+ for (auto use : iterate_safely (set->debug_insn_uses ()))
{
if (*pair_dst < *use->insn () && defs[1])
// We're re-ordering defs[1] above a previous use of the
// We have a def in insns[1] which isn't def'd by the first insn.
// Look to the previous def and see if it has any debug uses.
- for (auto use : prev_set->debug_insn_uses ())
+ for (auto use : iterate_safely (prev_set->debug_insn_uses ()))
if (*pair_dst < *use->insn ())
// We're ordering DEF above a previous use of the same register.
update_debug_use (use, def, writeback_pat);
// second writeback def which need re-parenting: do that.
auto def = find_access (insns[1]->defs (), base_regno);
gcc_assert (def);
- for (auto use : as_a<set_info *> (def)->debug_insn_uses ())
+ auto set = as_a<set_info *> (def);
+ for (auto use : iterate_safely (set->debug_insn_uses ()))
{
insn_change change (use->insn ());
change.new_uses = check_remove_regno_access (attempt,
if (!m_emitted_tombstone)
return;
- insn_info *insn = m_bb->head_insn ();
- while (insn)
+ for (auto insn : iterate_safely (m_bb->nondebug_insns ()))
{
- insn_info *next = insn->next_nondebug_insn ();
if (!insn->is_real ()
|| !bitmap_bit_p (&m_tombstone_bitmap, insn->uid ()))
- {
- insn = next;
- continue;
- }
+ continue;
- auto def = memory_access (insn->defs ());
- auto set = dyn_cast<set_info *> (def);
- if (set && set->has_any_uses ())
+ auto set = as_a<set_info *> (memory_access (insn->defs ()));
+ if (set->has_any_uses ())
{
- def_info *prev_def = def->prev_def ();
- auto prev_set = dyn_cast<set_info *> (prev_def);
- if (!prev_set)
- gcc_unreachable ();
-
+ auto prev_set = as_a<set_info *> (set->prev_def ());
while (set->first_use ())
crtl->ssa->reparent_use (set->first_use (), prev_set);
}
// Now set has no uses, we can delete it.
insn_change change (insn, insn_change::DELETE);
crtl->ssa->change_insn (change);
- insn = next;
}
}
return ret;
}
+// An iterator that pre-computes the next value if we haven't already got to the
+// end. This is useful in cases where a standard iterator would get invalidated
+// (e.g. elements getting removed from a container) during the body of a loop.
+template<typename T>
+class safe_iterator
+{
+ T m_current;
+ const T m_end;
+ T m_next;
+
+ T get_next ()
+ {
+ if (m_current != m_end)
+ {
+ // FIXME: we should use std::next here but that would mean having
+ // #include <iterator> everywhere that iterator-utils.h is included.
+ //
+ // For now we just implement it directly.
+ T iter = m_current;
+ return ++iter;
+ }
+ return m_end;
+ }
+
+ void advance ()
+ {
+ m_current = m_next;
+ if (m_next != m_end)
+ ++m_next;
+ }
+
+public:
+ bool operator== (const safe_iterator &other) const
+ {
+ return m_current == other.m_current;
+ }
+
+ bool operator!= (const safe_iterator &other) const
+ {
+ return m_current != other.m_current;
+ }
+
+ typename T::value_type operator*() const { return *m_current; }
+
+ safe_iterator &operator++ ()
+ {
+ advance ();
+ return *this;
+ }
+
+ safe_iterator operator++ (int)
+ {
+ auto ret = *this;
+ advance ();
+ return ret;
+ }
+
+ safe_iterator (T iter, T end)
+ : m_current (iter), m_end (end), m_next (get_next ()) {}
+};
+
+// Convert a container RANGE into a container of safe_iterators.
+template<typename Container>
+inline
+iterator_range<safe_iterator<typename Container::const_iterator>>
+iterate_safely (Container range)
+{
+ return {
+ { range.begin (), range.end () },
+ { range.end (), range.end () }
+ };
+}
+
#endif