aboutsummaryrefslogtreecommitdiff
path: root/gcc/rtl-ssa
diff options
context:
space:
mode:
authorRichard Sandiford <richard.sandiford@arm.com>2024-11-19 10:19:24 +0000
committerRichard Sandiford <richard.sandiford@arm.com>2024-11-19 10:19:24 +0000
commit387dba05e4207fc3f9a2f2bcb09a343a999c76fc (patch)
tree6c93e63c5d1f6e48066ffbe8a0cf652b3114689e /gcc/rtl-ssa
parent694613a7f9adfa9c87e733adc63839c8801f2b5c (diff)
downloadgcc-387dba05e4207fc3f9a2f2bcb09a343a999c76fc.zip
gcc-387dba05e4207fc3f9a2f2bcb09a343a999c76fc.tar.gz
gcc-387dba05e4207fc3f9a2f2bcb09a343a999c76fc.tar.bz2
Avoid repeated calls to temporarily_undo_changes [PR117297]
In an attempt to reduce compile time, rtl-ssa computes the cost of existing instructions lazily rather than eagerly. However, this means that it might need to calculate the cost of an existing instruction while a change group is already in progress for the instruction. rtl_ssa::insn_info::calculate_cost therefore temporarily undoes any in-progress changes in order to get back the original pattern and insn code. rtl-ssa's main use of insn costs is in rtl_ssa::changes_are_worthwhile, which calculates the cost of a change involving an arbitrary number of instructions. Summing up the original cost of N instructions while those N instructions have in-progress changes could lead to O(N*N) rtl changes, since each lazy calculation might have to temporarily undo the changes to all N instructions. We can avoid that by converting the current temporarily_undo_changes/ redo_changes pair into an RAII class and extending it to allow nested uses. rtl_ssa::changes_are_worthwhile can then undo the in-progress changes once, before computing the original cost of all the instructions. gcc/ PR rtl-optimization/117297 * recog.h (temporarily_undo_changes, redo_changes): Delete in favor of... (undo_recog_changes): ...this new RAII class. * fwprop.cc (should_replace_address): Update accordingly. (fwprop_propagation::check_mem): Likewise. (try_fwprop_subst_note): Likewise. (try_fwprop_subst_pattern): Likewise. * rtl-ssa/insns.cc (insn_info::calculate_cost): Likewise. * rtl-ssa/changes.cc (rtl_ssa::changes_are_worthwhile): Temporarily undo all in-progress changes while computing the cost of the original sequence. * recog.cc (temporarily_undone_changes): Replace with... (undo_recog_changes::s_num_changes): ...this static member variable. (validate_change_1): Update check accordingly. (confirm_change_group): Likewise. (num_validated_changes): Likewise. (temporarily_undo_changes): Replace with... (undo_recog_changes::undo_recog_changes): ...this constructor. (redo_changes): Replace with... (undo_recog_changes::~undo_recog_changes): ...this destructor.
Diffstat (limited to 'gcc/rtl-ssa')
-rw-r--r--gcc/rtl-ssa/changes.cc26
-rw-r--r--gcc/rtl-ssa/insns.cc3
2 files changed, 18 insertions, 11 deletions
diff --git a/gcc/rtl-ssa/changes.cc b/gcc/rtl-ssa/changes.cc
index f2be119..5f3a0f0 100644
--- a/gcc/rtl-ssa/changes.cc
+++ b/gcc/rtl-ssa/changes.cc
@@ -173,21 +173,29 @@ rtl_ssa::changes_are_worthwhile (array_slice<insn_change *const> changes,
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)
{
diff --git a/gcc/rtl-ssa/insns.cc b/gcc/rtl-ssa/insns.cc
index bfc6683..4af79be 100644
--- a/gcc/rtl-ssa/insns.cc
+++ b/gcc/rtl-ssa/insns.cc
@@ -49,14 +49,13 @@ void
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.