aboutsummaryrefslogtreecommitdiff
path: root/gcc/tree-ssa-structalias.cc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/tree-ssa-structalias.cc')
-rw-r--r--gcc/tree-ssa-structalias.cc38
1 files changed, 25 insertions, 13 deletions
diff --git a/gcc/tree-ssa-structalias.cc b/gcc/tree-ssa-structalias.cc
index 8db99a4..ee9313c 100644
--- a/gcc/tree-ssa-structalias.cc
+++ b/gcc/tree-ssa-structalias.cc
@@ -966,28 +966,40 @@ solution_set_expand (bitmap set, bitmap *expanded)
*expanded = BITMAP_ALLOC (&iteration_obstack);
- /* In a first pass expand to the head of the variables we need to
- add all sub-fields off. This avoids quadratic behavior. */
+ /* In a first pass expand variables, once for each head to avoid
+ quadratic behavior, to include all sub-fields. */
+ unsigned prev_head = 0;
EXECUTE_IF_SET_IN_BITMAP (set, 0, j, bi)
{
varinfo_t v = get_varinfo (j);
if (v->is_artificial_var
|| v->is_full_var)
continue;
- bitmap_set_bit (*expanded, v->head);
- }
+ if (v->head != prev_head)
+ {
+ varinfo_t head = get_varinfo (v->head);
+ unsigned num = 1;
+ for (varinfo_t n = vi_next (head); n != NULL; n = vi_next (n))
+ {
+ if (n->id != head->id + num)
+ {
+ /* Usually sub variables are adjacent but since we
+ create pointed-to restrict representatives there
+ can be gaps as well. */
+ bitmap_set_range (*expanded, head->id, num);
+ head = n;
+ num = 1;
+ }
+ else
+ num++;
+ }
- /* In the second pass now expand all head variables with subfields. */
- EXECUTE_IF_SET_IN_BITMAP (*expanded, 0, j, bi)
- {
- varinfo_t v = get_varinfo (j);
- if (v->head != j)
- continue;
- for (v = vi_next (v); v != NULL; v = vi_next (v))
- bitmap_set_bit (*expanded, v->id);
+ bitmap_set_range (*expanded, head->id, num);
+ prev_head = v->head;
+ }
}
- /* And finally set the rest of the bits from SET. */
+ /* And finally set the rest of the bits from SET in an efficient way. */
bitmap_ior_into (*expanded, set);
return *expanded;