/* Prefer the new address if it is less expensive. */
bool speed = optimize_bb_for_speed_p (BLOCK_FOR_INSN (insn));
- temporarily_undo_changes (old_num_changes);
- gain = address_cost (XEXP (mem, 0), GET_MODE (mem),
- MEM_ADDR_SPACE (mem), speed);
- redo_changes (old_num_changes);
+ {
+ undo_recog_changes undo (old_num_changes);
+ gain = address_cost (XEXP (mem, 0), GET_MODE (mem),
+ MEM_ADDR_SPACE (mem), speed);
+ }
gain -= address_cost (XEXP (mem, 0), GET_MODE (mem),
MEM_ADDR_SPACE (mem), speed);
if (gain == 0)
{
gain = set_src_cost (XEXP (mem, 0), VOIDmode, speed);
- temporarily_undo_changes (old_num_changes);
+ undo_recog_changes undo (old_num_changes);
gain -= set_src_cost (XEXP (mem, 0), VOIDmode, speed);
- redo_changes (old_num_changes);
}
return (gain > 0);
return false;
}
- temporarily_undo_changes (old_num_changes);
- bool can_simplify = can_simplify_addr (XEXP (mem, 0));
- redo_changes (old_num_changes);
+ bool can_simplify = [&]()
+ {
+ undo_recog_changes undo (old_num_changes);
+ return can_simplify_addr (XEXP (mem, 0));
+ } ();
if (!can_simplify)
{
failure_reason = "would replace a frame address";
{
fprintf (dump_file, "\nin notes of insn %d, replacing:\n ",
INSN_UID (use_rtl));
- temporarily_undo_changes (0);
- print_inline_rtx (dump_file, note, 2);
- redo_changes (0);
+ {
+ undo_recog_changes undo (0);
+ print_inline_rtx (dump_file, note, 2);
+ }
fprintf (dump_file, "\n with:\n ");
print_inline_rtx (dump_file, note, 2);
fprintf (dump_file, "\n");
{
fprintf (dump_file, "\npropagating insn %d into insn %d, replacing:\n",
def_insn->uid (), use_insn->uid ());
- temporarily_undo_changes (0);
+ undo_recog_changes undo (0);
print_rtl_single (dump_file, PATTERN (use_rtl));
- redo_changes (0);
}
bool ok = recog (attempt, use_change);
static int changes_allocated;
static int num_changes = 0;
-static int temporarily_undone_changes = 0;
+int undo_recog_changes::s_num_changes = 0;
/* Validate a proposed change to OBJECT. LOC is the location in the rtl
at which NEW_RTX will be placed. If NEW_LEN is >= 0, XVECLEN (NEW_RTX, 0)
validate_change_1 (rtx object, rtx *loc, rtx new_rtx, bool in_group,
bool unshare, int new_len = -1)
{
- gcc_assert (temporarily_undone_changes == 0);
+ gcc_assert (!undo_recog_changes::is_active ());
rtx old = *loc;
/* Single-element parallels aren't valid and won't match anything.
int i;
rtx last_object = NULL;
- gcc_assert (temporarily_undone_changes == 0);
+ gcc_assert (!undo_recog_changes::is_active ());
for (i = 0; i < num_changes; i++)
{
rtx object = changes[i].object;
void
cancel_changes (int num)
{
- gcc_assert (temporarily_undone_changes == 0);
+ gcc_assert (!undo_recog_changes::is_active ());
int i;
/* Back out all the changes. Do this in the opposite order in which
}
}
-/* Temporarily undo all the changes numbered NUM and up, with a view
- to reapplying them later. The next call to the changes machinery
- must be:
-
- redo_changes (NUM)
-
- otherwise things will end up in an invalid state. */
-
-void
-temporarily_undo_changes (int num)
+undo_recog_changes::undo_recog_changes (int num)
+ : m_old_num_changes (s_num_changes)
{
- gcc_assert (temporarily_undone_changes == 0 && num <= num_changes);
- for (int i = num_changes - 1; i >= num; i--)
+ gcc_assert (num <= num_changes - s_num_changes);
+ for (int i = num_changes - s_num_changes - 1; i >= num; i--)
swap_change (i);
- temporarily_undone_changes = num_changes - num;
+ s_num_changes = num_changes - num;
}
-/* Redo the changes that were temporarily undone by:
-
- temporarily_undo_changes (NUM). */
-
-void
-redo_changes (int num)
+undo_recog_changes::~undo_recog_changes ()
{
- gcc_assert (temporarily_undone_changes == num_changes - num);
- for (int i = num; i < num_changes; ++i)
+ for (int i = num_changes - s_num_changes;
+ i < num_changes - m_old_num_changes; ++i)
swap_change (i);
- temporarily_undone_changes = 0;
+ s_num_changes = m_old_num_changes;
}
/* Reduce conditional compilation elsewhere. */
{
}
+/* An RAII class that temporarily undoes part of the current change group.
+ The sequence:
+
+ {
+ ...;
+ undo_recog_changes undo (NUM);
+ STMTS;
+ }
+
+ executes STMTS with all the changes numbered NUM and up temporarily
+ reverted. STMTS must not try to add to the current change group.
+
+ Nested uses are supported, but each nested NUM must be no greater than
+ outer NUMs. */
+
+class undo_recog_changes
+{
+public:
+ undo_recog_changes (int);
+ ~undo_recog_changes ();
+
+ static bool is_active () { return s_num_changes != 0; }
+
+private:
+ int m_old_num_changes;
+
+ static int s_num_changes;
+};
+
extern void init_recog (void);
extern void init_recog_no_volatile (void);
extern bool check_asm_operands (rtx);
extern bool apply_change_group (void);
extern int num_validated_changes (void);
extern void cancel_changes (int);
-extern void temporarily_undo_changes (int);
-extern void redo_changes (int);
extern bool constrain_operands (int, alternative_mask);
extern bool constrain_operands_cached (rtx_insn *, int);
extern bool memory_address_addr_space_p (machine_mode, rtx, addr_space_t,
bool strict_p)
{
unsigned int old_cost = 0;
- unsigned int new_cost = 0;
sreal weighted_old_cost = 0;
- sreal weighted_new_cost = 0;
auto entry_count = ENTRY_BLOCK_PTR_FOR_FN (cfun)->count;
+ {
+ undo_recog_changes undo (0);
+ for (insn_change *change : changes)
+ {
+ // Count zero for the old cost if the old instruction was a no-op
+ // move or had an unknown cost. This should reduce the chances of
+ // making an unprofitable change.
+ old_cost += change->old_cost ();
+ basic_block cfg_bb = change->bb ()->cfg_bb ();
+ if (optimize_bb_for_speed_p (cfg_bb))
+ weighted_old_cost += (cfg_bb->count.to_sreal_scale (entry_count)
+ * change->old_cost ());
+
+ }
+ }
+ unsigned int new_cost = 0;
+ sreal weighted_new_cost = 0;
for (insn_change *change : changes)
{
- // Count zero for the old cost if the old instruction was a no-op
- // move or had an unknown cost. This should reduce the chances of
- // making an unprofitable change.
- old_cost += change->old_cost ();
basic_block cfg_bb = change->bb ()->cfg_bb ();
bool for_speed = optimize_bb_for_speed_p (cfg_bb);
- if (for_speed)
- weighted_old_cost += (cfg_bb->count.to_sreal_scale (entry_count)
- * change->old_cost ());
if (!change->is_deletion ()
&& INSN_CODE (change->rtl ()) != NOOP_MOVE_INSN_CODE)
{
insn_info::calculate_cost () const
{
basic_block cfg_bb = BLOCK_FOR_INSN (m_rtl);
- temporarily_undo_changes (0);
+ undo_recog_changes (0);
if (INSN_CODE (m_rtl) == NOOP_MOVE_INSN_CODE)
// insn_cost also uses 0 to mean "don't know". Callers that
// want to distinguish the cases will need to check INSN_CODE.
m_cost_or_uid = 0;
else
m_cost_or_uid = insn_cost (m_rtl, optimize_bb_for_speed_p (cfg_bb));
- redo_changes (0);
}
// Add NOTE to the instruction's notes.