along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
+#define INCLUDE_ALGORITHM
#include "config.h"
#include "system.h"
#include "coretypes.h"
psr.dummy = NULL_TREE;
psr.unit_offset = unit_offset;
m_replacements.safe_push (psr);
+ m_sorted_replacements_p = false;
}
/* Register that REPLACEMENT should replace parameter described in APM. */
replacement);
}
+/* Comparator for sorting and searching
+ ipa_param_body_adjustments::m_replacements. */
+
+static int
+compare_param_body_replacement (const void *va, const void *vb)
+{
+ const ipa_param_body_replacement *a = (const ipa_param_body_replacement *) va;
+ const ipa_param_body_replacement *b = (const ipa_param_body_replacement *) vb;
+
+ if (DECL_UID (a->base) < DECL_UID (b->base))
+ return -1;
+ if (DECL_UID (a->base) > DECL_UID (b->base))
+ return 1;
+ if (a->unit_offset < b->unit_offset)
+ return -1;
+ if (a->unit_offset > b->unit_offset)
+ return 1;
+ return 0;
+}
+
+/* Sort m_replacements and set m_sorted_replacements_p to true. */
+
+void
+ipa_param_body_adjustments::sort_replacements ()
+{
+ if (m_sorted_replacements_p)
+ return;
+ m_replacements.qsort (compare_param_body_replacement);
+ m_sorted_replacements_p = true;
+}
+
/* Copy or not, as appropriate given m_id and decl context, a pre-existing
PARM_DECL T so that it can be included in the parameters of the modified
function. */
}
}
}
+ sort_replacements ();
if (tree_map)
{
m_dead_stmt_debug_equiv (), m_fndecl (fndecl), m_id (NULL), m_oparms (),
m_new_decls (), m_new_types (), m_replacements (),
m_split_agg_csts_inits (), m_removed_decls (), m_removed_map (),
- m_method2func (false)
+ m_method2func (false), m_sorted_replacements_p (true)
{
common_initialization (fndecl, NULL, NULL);
}
m_dead_ssa_debug_equiv (), m_dead_stmt_debug_equiv (), m_fndecl (fndecl),
m_id (NULL), m_oparms (), m_new_decls (), m_new_types (), m_replacements (),
m_split_agg_csts_inits (), m_removed_decls (), m_removed_map (),
- m_method2func (false)
+ m_method2func (false), m_sorted_replacements_p (true)
{
common_initialization (fndecl, NULL, NULL);
}
m_dead_ssa_debug_equiv (), m_dead_stmt_debug_equiv (), m_fndecl (fndecl),
m_id (id), m_oparms (), m_new_decls (), m_new_types (), m_replacements (),
m_split_agg_csts_inits (), m_removed_decls (), m_removed_map (),
- m_method2func (false)
+ m_method2func (false), m_sorted_replacements_p (true)
{
common_initialization (old_fndecl, vars, tree_map);
}
ipa_param_body_adjustments::lookup_replacement_1 (tree base,
unsigned unit_offset)
{
- unsigned int len = m_replacements.length ();
- for (unsigned i = 0; i < len; i++)
- {
- ipa_param_body_replacement *pbr = &m_replacements[i];
+ gcc_assert (m_sorted_replacements_p);
+ ipa_param_body_replacement key;
+ key.base = base;
+ key.unit_offset = unit_offset;
+ ipa_param_body_replacement *res
+ = std::lower_bound (m_replacements.begin (), m_replacements.end (), key,
+ [] (const ipa_param_body_replacement &elt,
+ const ipa_param_body_replacement &val)
+ {
+ return (compare_param_body_replacement (&elt, &val)
+ < 0);
+ });
+
+ if (res == m_replacements.end ()
+ || res->base != base
+ || res->unit_offset != unit_offset)
+ return NULL;
+ return res;
+}
- if (pbr->base == base
- && (pbr->unit_offset == unit_offset))
- return pbr;
- }
- return NULL;
+/* Find the first replacement for BASE among m_replacements and return pointer
+ to it, or NULL if there is none. */
+
+ipa_param_body_replacement *
+ipa_param_body_adjustments::lookup_first_base_replacement (tree base)
+{
+ gcc_assert (m_sorted_replacements_p);
+ ipa_param_body_replacement key;
+ key.base = base;
+ ipa_param_body_replacement *res
+ = std::lower_bound (m_replacements.begin (), m_replacements.end (), key,
+ [] (const ipa_param_body_replacement &elt,
+ const ipa_param_body_replacement &val)
+ {
+ if (DECL_UID (elt.base) < DECL_UID (val.base))
+ return true;
+ return false;
+ });
+
+ if (res == m_replacements.end ()
+ || res->base != base)
+ return NULL;
+ return res;
}
/* Given BASE and UNIT_OFFSET, find the corresponding replacement expression
gcall *stmt = *stmt_p;
unsigned nargs = gimple_call_num_args (stmt);
bool recreate = false;
+ gcc_assert (m_sorted_replacements_p);
for (unsigned i = 0; i < gimple_call_num_args (stmt); i++)
{
if (TREE_CODE (base) != PARM_DECL)
continue;
- bool base_among_replacements = false;
- unsigned j, repl_list_len = m_replacements.length ();
- for (j = 0; j < repl_list_len; j++)
- {
- ipa_param_body_replacement *pbr = &m_replacements[j];
- if (pbr->base == base)
- {
- base_among_replacements = true;
- break;
- }
- }
- if (!base_among_replacements)
+ ipa_param_body_replacement *first_rep
+ = lookup_first_base_replacement (base);
+ if (!first_rep)
continue;
+ unsigned first_rep_index = first_rep - m_replacements.begin ();
/* We still have to distinguish between an end-use that we have to
transform now and a pass-through, which happens in the following
recreate = true;
gcc_assert (POINTER_TYPE_P (TREE_TYPE (t)));
pass_through_args.safe_push (i);
- pass_through_pbr_indices.safe_push (j);
+ pass_through_pbr_indices.safe_push (first_rep_index);
pass_through_offsets.safe_push (agg_arg_offset);
}
else if (!by_ref && AGGREGATE_TYPE_P (TREE_TYPE (t)))
{
recreate = true;
pass_through_args.safe_push (i);
- pass_through_pbr_indices.safe_push (j);
+ pass_through_pbr_indices.safe_push (first_rep_index);
pass_through_offsets.safe_push (agg_arg_offset);
}
}
void register_replacement (tree base, unsigned unit_offset, tree replacement);
/* Register a replacement decl for the transformation done in APM. */
void register_replacement (ipa_adjusted_param *apm, tree replacement);
+ /* Sort m_replacements and set m_sorted_replacements_p to true. Users that
+ call register_replacement themselves must call the method before any
+ lookup and thus also any statement or expression modification. */
+ void sort_replacements ();
/* Lookup a replacement for a given offset within a given parameter. */
tree lookup_replacement (tree base, unsigned unit_offset);
/* Lookup a replacement for an expression, if there is one. */
unsigned get_base_index (ipa_adjusted_param *apm);
ipa_param_body_replacement *lookup_replacement_1 (tree base,
unsigned unit_offset);
+ ipa_param_body_replacement *lookup_first_base_replacement (tree base);
tree replace_removed_params_ssa_names (tree old_name, gimple *stmt);
bool modify_expression (tree *expr_p, bool convert);
bool modify_assignment (gimple *stmt, gimple_seq *extra_stmts);
its this pointer and must be converted to a normal function. */
bool m_method2func;
+
+ /* True if m_replacements have ben sorted since the last insertion. */
+
+ bool m_sorted_replacements_p;
};
void push_function_arg_decls (vec<tree> *args, tree fndecl);