if (ref_node)
return ref_node;
- if (changed)
- *changed = true;
-
- /* Collapse the node if too full already. */
- if (refs && refs->length () >= max_refs)
+ /* We always allow inserting ref 0. For non-0 refs there is upper
+ limit on number of entries and if exceeded,
+ drop ref conservatively to 0. */
+ if (ref && refs && refs->length () >= max_refs)
{
if (dump_file)
- fprintf (dump_file, "--param param=modref-max-refs limit reached\n");
- collapse ();
- return NULL;
+ fprintf (dump_file, "--param param=modref-max-refs limit reached;"
+ " using 0\n");
+ ref = 0;
+ ref_node = search (ref);
+ if (ref_node)
+ return ref_node;
}
+ if (changed)
+ *changed = true;
+
ref_node = new (ggc_alloc <modref_ref_node <T> > ())modref_ref_node <T>
(ref);
vec_safe_push (refs, ref_node);
/* Insert BASE; collapse tree if there are more than MAX_REFS.
Return inserted base and if CHANGED is non-null set it to true if
- something changed. */
+ something changed.
+ If table gets full, try to insert REF instead. */
- modref_base_node <T> *insert_base (T base, bool *changed = NULL)
+ modref_base_node <T> *insert_base (T base, T ref, bool *changed = NULL)
{
modref_base_node <T> *base_node;
if (base_node)
return base_node;
- if (changed)
- *changed = true;
-
- /* Collapse the node if too full already. */
- if (bases && bases->length () >= max_bases)
+ /* We always allow inserting base 0. For non-0 base there is upper
+ limit on number of entries and if exceeded,
+ drop base conservatively to ref and if it still does not fit to 0. */
+ if (base && bases && bases->length () >= max_bases)
{
+ base_node = search (ref);
+ if (base_node)
+ {
+ if (dump_file)
+ fprintf (dump_file, "--param param=modref-max-bases"
+ " limit reached; using ref\n");
+ return base_node;
+ }
if (dump_file)
- fprintf (dump_file, "--param param=modref-max-bases limit reached\n");
- collapse ();
- return NULL;
+ fprintf (dump_file, "--param param=modref-max-bases"
+ " limit reached; using 0\n");
+ base = 0;
+ base_node = search (base);
+ if (base_node)
+ return base_node;
}
+ if (changed)
+ *changed = true;
+
base_node = new (ggc_alloc <modref_base_node <T> > ())
modref_base_node <T> (base);
vec_safe_push (bases, base_node);
return true;
}
- modref_base_node <T> *base_node = insert_base (base, &changed);
- if (!base_node || base_node->every_ref)
+ modref_base_node <T> *base_node = insert_base (base, ref, &changed);
+ base = base_node->base;
+ /* If table got full we may end up with useless base. */
+ if (!base && !ref && !a.useful_p ())
+ {
+ collapse ();
+ return true;
+ }
+ if (base_node->every_ref)
return changed;
gcc_checking_assert (search (base) != NULL);
modref_ref_node <T> *ref_node = base_node->insert_ref (ref, max_refs,
&changed);
+ ref = ref_node->ref;
- /* If we failed to insert ref, just see if there is a cleanup possible. */
- if (!ref_node)
+ if (ref_node->every_access)
+ return changed;
+ changed |= ref_node->insert_access (a, max_accesses,
+ record_adjustments);
+ /* See if we failed to add useful access. */
+ if (ref_node->every_access)
{
- /* No useful ref information and no useful base; collapse everything. */
- if (!base && base_node->every_ref)
+ /* Collapse everything if there is no useful base and ref. */
+ if (!base && !ref)
{
collapse ();
gcc_checking_assert (changed);
}
- else if (changed)
- cleanup ();
- }
- else
- {
- if (ref_node->every_access)
- return changed;
- changed |= ref_node->insert_access (a, max_accesses,
- record_adjustments);
- /* See if we failed to add useful access. */
- if (ref_node->every_access)
+ /* Collapse base if there is no useful ref. */
+ else if (!ref)
{
- /* Collapse everything if there is no useful base and ref. */
- if (!base && !ref)
- {
- collapse ();
- gcc_checking_assert (changed);
- }
- /* Collapse base if there is no useful ref. */
- else if (!ref)
- {
- base_node->collapse ();
- gcc_checking_assert (changed);
- }
+ base_node->collapse ();
+ gcc_checking_assert (changed);
}
}
return changed;
{
if (base_node->every_ref)
{
- my_base_node = insert_base (base_node->base, &changed);
+ my_base_node = insert_base (base_node->base, 0, &changed);
if (my_base_node && !my_base_node->every_ref)
{
my_base_node->collapse ();