[PATCH 2/2] Optimize alias subset recording
Richard Biener
rguenther@suse.de
Wed Jan 15 10:54:00 GMT 2020
On Tue, 14 Jan 2020, Richard Biener wrote:
> On Tue, 14 Jan 2020, Richard Biener wrote:
>
> > On Tue, 14 Jan 2020, Richard Biener wrote:
> >
> > > When an alias-set is an already existing subset there is no need
> > > to re-record its children as childs of the parent.
> > >
> > > I noticed this when doing 1/2 as trivial opportunity to squeeze
> > > back some performance for the non-caching recursion I added. The
> > > whole thing is still quadratic in the depth of the structure, of course.
> > >
> > > Bootstrapped and tested on x86_64-unknown-linux-gnu.
> > >
> > > Since I'm curious I'll test a variant which checks the children
> > > are actually recorded before pushing this ... (OK, maybe I shouldn't
> > > do this...)
> >
> > So I did it. It works but for
> >
> > FAIL: gnat.dg/interface2.adb 3 blank line(s) in output
> > FAIL: gnat.dg/interface2.adb (test for excess errors)
> > UNRESOLVED: gnat.dg/interface2.adb compilation failed to produce
> > executable
> > FAIL: gnat.dg/predicate2_main.adb 3 blank line(s) in output
> > FAIL: gnat.dg/predicate2_main.adb (test for excess errors)
> >
> > which ICE with the adjusted patch below. Ada calls
> > record_component_aliases itself and eventually too early when
> > some types are not yet complete? Which would also mean that
> > subsets could be failed to recorded properly.
> >
> > So I'm still inclined to go with the original non-checking patch
> > unless Eric tells me I'm completely wrong and there isn't a
> > latent issue in the Ada frontend.
>
> Btw, all the dance the Ada FE performs in relate_alias_sets isn't
> going to work with LTO unless it is no longer necessary anyways.
>
> Oh, and we miss libbacktrace support for GNAT bug boxes, for the
> above I'd like to know whether its from record_component_aliases
> calls or calls of record_alias_subset.
And if I delay checking until we actually look for subsets
(alias_sets_conflict or alias_set_subset_of), verifying we collected
all subsets that fails when building the RTS, for example when
building g-awk.adb. The patch below does that verification,
it doesn't actually look for a case where the final answer of
those predicates is wrong though.
It seems that Ada is the only frontend affected by this "bug" so
I pushed the original change.
Richard.
diff --git a/gcc/alias.c b/gcc/alias.c
index 9629b5a9f48..ffb2af9b34f 100644
--- a/gcc/alias.c
+++ b/gcc/alias.c
@@ -154,7 +154,7 @@ static int base_alias_check (rtx, rtx, rtx, rtx, machine_mode,
machine_mode);
static rtx find_base_value (rtx);
static int mems_in_disjoint_alias_sets_p (const_rtx, const_rtx);
-static alias_set_entry *get_alias_set_entry (alias_set_type);
+static alias_set_entry *get_alias_set_entry (alias_set_type, bool = false);
static tree decl_for_component_ref (tree);
static int write_dependence_p (const_rtx,
const_rtx, machine_mode, rtx,
@@ -372,9 +372,37 @@ rtx_refs_may_alias_p (const_rtx x, const_rtx mem, bool tbaa_p)
such an entry, or NULL otherwise. */
static inline alias_set_entry *
-get_alias_set_entry (alias_set_type alias_set)
+get_alias_set_entry (alias_set_type alias_set, bool check)
{
- return (*alias_sets)[alias_set];
+ alias_set_entry *e = (*alias_sets)[alias_set];
+ if (check && e && e->children)
+ {
+ bitmap_obstack_initialize (NULL);
+ auto_vec<alias_set_type> worklist;
+ auto_bitmap visited;
+ hash_map<alias_set_hash, int>::iterator iter
+ = e->children->begin ();
+ for (; iter != e->children->end (); ++iter)
+ worklist.safe_push ((*iter).first);
+ while (!worklist.is_empty ())
+ {
+ alias_set_type subset = worklist.pop ();
+ if (!bitmap_set_bit (visited, subset))
+ continue;
+ alias_set_entry *se = (*alias_sets)[subset];
+ if (se && se->children)
+ for (iter = se->children->begin ();
+ iter != se->children->end (); ++iter)
+ {
+ if ((*iter).first == alias_set)
+ continue;
+ gcc_assert (e->children->get ((*iter).first) != NULL);
+ worklist.safe_push ((*iter).first);
+ }
+ }
+ bitmap_obstack_release (NULL);
+ }
+ return e;
}
/* Returns nonzero if the alias sets for MEM1 and MEM2 are such that
@@ -404,7 +432,7 @@ alias_set_subset_of (alias_set_type set1, alias_set_type set2)
return true;
/* Check if set1 is a subset of set2. */
- ase2 = get_alias_set_entry (set2);
+ ase2 = get_alias_set_entry (set2, true);
if (ase2 != 0
&& (ase2->has_zero_child
|| (ase2->children && ase2->children->get (set1))))
@@ -433,7 +461,7 @@ alias_set_subset_of (alias_set_type set1, alias_set_type set2)
get_alias_set for more details. */
if (ase2 && ase2->has_pointer)
{
- alias_set_entry *ase1 = get_alias_set_entry (set1);
+ alias_set_entry *ase1 = get_alias_set_entry (set1, true);
if (ase1 && ase1->is_pointer)
{
@@ -465,7 +493,7 @@ alias_sets_conflict_p (alias_set_type set1, alias_set_type set2)
return 1;
/* See if the first alias set is a subset of the second. */
- ase1 = get_alias_set_entry (set1);
+ ase1 = get_alias_set_entry (set1, true);
if (ase1 != 0
&& ase1->children && ase1->children->get (set2))
{
@@ -474,7 +502,7 @@ alias_sets_conflict_p (alias_set_type set1, alias_set_type set2)
}
/* Now do the same, but with the alias sets reversed. */
- ase2 = get_alias_set_entry (set2);
+ ase2 = get_alias_set_entry (set2, true);
if (ase2 != 0
&& ase2->children && ase2->children->get (set1))
{
@@ -1164,10 +1192,16 @@ record_alias_subset (alias_set_type superset, alias_set_type subset)
superset_entry->has_zero_child = 1;
else
{
- subset_entry = get_alias_set_entry (subset);
if (!superset_entry->children)
superset_entry->children
= hash_map<alias_set_hash, int>::create_ggc (64);
+
+ /* Enter the SUBSET itself as a child of the SUPERSET. If it was
+ already there we're done. */
+ if (superset_entry->children->put (subset, 0))
+ return;
+
+ subset_entry = get_alias_set_entry (subset);
/* If there is an entry for the subset, enter all of its children
(if they are not already present) as children of the SUPERSET. */
if (subset_entry)
@@ -1182,12 +1216,13 @@ record_alias_subset (alias_set_type superset, alias_set_type subset)
hash_map<alias_set_hash, int>::iterator iter
= subset_entry->children->begin ();
for (; iter != subset_entry->children->end (); ++iter)
- superset_entry->children->put ((*iter).first, (*iter).second);
+ /* It is possible in complex type situations for both sets
+ to be the same, in which case we can ignore this
+ operation. */
+ if ((*iter).first != superset)
+ superset_entry->children->put ((*iter).first, (*iter).second);
}
}
-
- /* Enter the SUBSET itself as a child of the SUPERSET. */
- superset_entry->children->put (subset, 0);
}
}
More information about the Gcc-patches
mailing list