// At the moment we don't support moving instructions between EBBs,
// but this would be worth adding if it's useful.
insn_info *insn = change.insn ();
- gcc_assert (after->ebb () == insn->ebb ());
+
bb_info *bb = after->bb ();
basic_block cfg_bb = bb->cfg_bb ();
- if (insn->bb () != bb)
- // Force DF to mark the old block as dirty.
- df_insn_delete (rtl);
- ::remove_insn (rtl);
+ if (!insn->is_temporary ())
+ {
+ gcc_assert (after->ebb () == insn->ebb ());
+
+ if (insn->bb () != bb)
+ // Force DF to mark the old block as dirty.
+ df_insn_delete (rtl);
+ ::remove_insn (rtl);
+ }
+
::add_insn_after (rtl, after_rtl, cfg_bb);
}
{
def_info *def = find_access (change.new_defs, ref.regno);
gcc_assert (def);
+
+ if (def->m_is_temp && is_a<set_info *> (def) && def->last_def ())
+ {
+ // For temporary sets being added with this change, we keep track of
+ // the corresponding permanent def using the last_def link.
+ //
+ // So if we have one of these, follow it to get the permanent def.
+ def = def->last_def ();
+ gcc_assert (!def->m_is_temp && !def->m_has_been_superceded);
+ }
+
if (def->m_is_temp)
{
- // At present, the only temporary instruction definitions we
- // create are clobbers, such as those added during recog.
- gcc_assert (is_a<clobber_info *> (def));
- def = allocate<clobber_info> (change.insn (), ref.regno);
+ if (is_a<clobber_info *> (def))
+ def = allocate<clobber_info> (change.insn (), ref.regno);
+ else if (is_a<set_info *> (def))
+ {
+ // Install the permanent set in the last_def link of the
+ // temporary def. This allows us to find the permanent def
+ // later in case we see a second write to the same resource.
+ def_info *perm_def = allocate<set_info> (change.insn (),
+ def->resource ());
+ def->set_last_def (perm_def);
+ def = perm_def;
+ }
+ else
+ gcc_unreachable ();
}
else if (!def->m_has_been_superceded)
{
insn->set_accesses (builder.finish ().begin (), num_defs, num_uses);
}
+
+ insn->m_is_temp = false;
}
// Add a temporary placeholder instruction after AFTER.
if (!change->is_deletion ())
{
// Remove any notes that are no longer relevant.
- update_notes (change->rtl ());
+ if (!change->insn ()->m_is_temp)
+ update_notes (change->rtl ());
// Make sure that the placement of this instruction would still
// leave room for previous instructions.
// verify_insn_changes is supposed to make sure that this holds.
gcc_unreachable ();
min_insn = later_insn (min_insn, change->move_range.first);
+
+ if (change->insn ()->m_is_temp)
+ {
+ change->m_insn = allocate<insn_info> (change->insn ()->bb (),
+ change->rtl (),
+ change->insn_uid ());
+
+ // Set the flag again so subsequent logic is aware.
+ // It will be cleared later on.
+ change->m_insn->m_is_temp = true;
+ }
}
}
// Remove the placeholder first so that we have a wider range of
// program points when inserting INSN.
insn_info *after = placeholder->prev_any_insn ();
- remove_insn (insn);
+ if (!insn->is_temporary ())
+ remove_insn (insn);
remove_insn (placeholder);
insn->set_bb (after->bb ());
add_insn_after (insn, after);
return changed_cfg;
}
+insn_info *
+function_info::create_insn (obstack_watermark &watermark,
+ rtx_code insn_code,
+ rtx pat)
+{
+ rtx_insn *rti = nullptr;
+
+ // TODO: extend, move in to emit-rtl.cc.
+ switch (insn_code)
+ {
+ case INSN:
+ rti = make_insn_raw (pat);
+ break;
+ default:
+ gcc_unreachable ();
+ }
+
+ auto insn = change_alloc<insn_info> (watermark, nullptr, rti, INSN_UID (rti));
+ insn->m_is_temp = true;
+ return insn;
+}
+
// Print a description of CHANGE to PP.
void
rtl_ssa::pp_insn_change (pretty_printer *pp, const insn_change &change)
// Return the SSA information for CFG_BB.
bb_info *bb (basic_block cfg_bb) const { return m_bbs[cfg_bb->index]; }
+ // Create a temporary def.
+ set_info *create_set (obstack_watermark &watermark,
+ insn_info *insn,
+ resource_info resource);
+
+ // Create a temporary insn with code INSN_CODE and pattern PAT.
+ insn_info *create_insn (obstack_watermark &watermark,
+ rtx_code insn_code,
+ rtx pat);
+
// Return a list of all the instructions in the function, in reverse
// postorder. The list includes both real and artificial instructions.
//
// Print the contents of the function to PP.
void print (pretty_printer *pp) const;
+ // Allocate an object of type T above the obstack watermark WM.
+ template<typename T, typename... Ts>
+ T *change_alloc (obstack_watermark &wm, Ts... args);
+
private:
class bb_phi_info;
class build_info;