{
public:
pass_store_merging (gcc::context *ctxt)
- : gimple_opt_pass (pass_data_tree_store_merging, ctxt), m_stores_head ()
+ : gimple_opt_pass (pass_data_tree_store_merging, ctxt), m_stores_head (),
+ m_n_chains (0), m_n_stores (0)
{
}
decisions when going out of SSA). */
imm_store_chain_info *m_stores_head;
+ /* The number of store chains currently tracked. */
+ unsigned m_n_chains;
+ /* The number of stores currently tracked. */
+ unsigned m_n_stores;
+
bool process_store (gimple *);
bool terminate_and_process_chain (imm_store_chain_info *);
bool terminate_all_aliasing_chains (imm_store_chain_info **, gimple *);
bool
pass_store_merging::terminate_and_process_chain (imm_store_chain_info *chain_info)
{
+ m_n_stores -= chain_info->m_store_info.length ();
+ m_n_chains--;
bool ret = chain_info->terminate_and_process_chain ();
m_stores.remove (chain_info->base_addr);
delete chain_info;
bool
imm_store_chain_info::terminate_and_process_chain ()
{
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file, "Terminating chain with %u stores\n",
+ m_store_info.length ());
/* Process store chain. */
bool ret = false;
if (m_store_info.length () > 1)
print_gimple_stmt (dump_file, stmt, 0);
}
(*chain_info)->m_store_info.safe_push (info);
+ m_n_stores++;
ret |= terminate_all_aliasing_chains (chain_info, stmt);
/* If we reach the limit of stores to merge in a chain terminate and
process the chain now. */
"Reached maximum number of statements to merge:\n");
ret |= terminate_and_process_chain (*chain_info);
}
- return ret;
}
+ else
+ {
+ /* Store aliases any existing chain? */
+ ret |= terminate_all_aliasing_chains (NULL, stmt);
- /* Store aliases any existing chain? */
- ret |= terminate_all_aliasing_chains (NULL, stmt);
- /* Start a new chain. */
- class imm_store_chain_info *new_chain
- = new imm_store_chain_info (m_stores_head, base_addr);
- info = new store_immediate_info (const_bitsize, const_bitpos,
- const_bitregion_start,
- const_bitregion_end,
- stmt, 0, rhs_code, n, ins_stmt,
- bit_not_p, lp_nr_for_store (stmt),
- ops[0], ops[1]);
- new_chain->m_store_info.safe_push (info);
- m_stores.put (base_addr, new_chain);
- if (dump_file && (dump_flags & TDF_DETAILS))
+ /* Start a new chain. */
+ class imm_store_chain_info *new_chain
+ = new imm_store_chain_info (m_stores_head, base_addr);
+ info = new store_immediate_info (const_bitsize, const_bitpos,
+ const_bitregion_start,
+ const_bitregion_end,
+ stmt, 0, rhs_code, n, ins_stmt,
+ bit_not_p, lp_nr_for_store (stmt),
+ ops[0], ops[1]);
+ new_chain->m_store_info.safe_push (info);
+ m_n_stores++;
+ m_stores.put (base_addr, new_chain);
+ m_n_chains++;
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ {
+ fprintf (dump_file, "Starting active chain number %u with statement:\n",
+ m_n_chains);
+ print_gimple_stmt (dump_file, stmt, 0);
+ fprintf (dump_file, "The base object is:\n");
+ print_generic_expr (dump_file, base_addr);
+ fprintf (dump_file, "\n");
+ }
+ }
+
+ /* Prune oldest chains so that after adding the chain or store above
+ we're again within the limits set by the params. */
+ if (m_n_chains > (unsigned)param_max_store_chains_to_track
+ || m_n_stores > (unsigned)param_max_stores_to_track)
{
- fprintf (dump_file, "Starting new chain with statement:\n");
- print_gimple_stmt (dump_file, stmt, 0);
- fprintf (dump_file, "The base object is:\n");
- print_generic_expr (dump_file, base_addr);
- fprintf (dump_file, "\n");
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file, "Too many chains (%u > %d) or stores (%u > %d), "
+ "terminating oldest chain(s).\n", m_n_chains,
+ param_max_store_chains_to_track, m_n_stores,
+ param_max_stores_to_track);
+ imm_store_chain_info **e = &m_stores_head;
+ unsigned idx = 0;
+ unsigned n_stores = 0;
+ while (*e)
+ {
+ if (idx >= (unsigned)param_max_store_chains_to_track
+ || (n_stores + (*e)->m_store_info.length ()
+ > (unsigned)param_max_stores_to_track))
+ terminate_and_process_chain (*e);
+ else
+ {
+ n_stores += (*e)->m_store_info.length ();
+ e = &(*e)->next;
+ ++idx;
+ }
+ }
}
+
return ret;
}