summaryrefslogtreecommitdiff
path: root/gcc/tree-ssa-structalias.c
diff options
context:
space:
mode:
authordberlin <dberlin@138bc75d-0d04-0410-961f-82ee72b054a4>2006-11-23 02:19:39 +0000
committerdberlin <dberlin@138bc75d-0d04-0410-961f-82ee72b054a4>2006-11-23 02:19:39 +0000
commit6395bf5bc92194b0cf802b87cd74182749763d66 (patch)
treef8a9128f5bf19f445a21b025ab8217021f7fc145 /gcc/tree-ssa-structalias.c
parentf70f9c9c8054771f76673067203c638138f85e4a (diff)
downloadgcc-6395bf5bc92194b0cf802b87cd74182749763d66.tar.gz
Revert accidental commit (patch coming for this :P)
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@119113 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/tree-ssa-structalias.c')
-rw-r--r--gcc/tree-ssa-structalias.c658
1 files changed, 544 insertions, 114 deletions
diff --git a/gcc/tree-ssa-structalias.c b/gcc/tree-ssa-structalias.c
index 828481c5680..42099ddedd4 100644
--- a/gcc/tree-ssa-structalias.c
+++ b/gcc/tree-ssa-structalias.c
@@ -434,14 +434,53 @@ struct constraint
static VEC(constraint_t,heap) *constraints;
static alloc_pool constraint_pool;
+/* An edge in the weighted constraint graph. The edges are weighted,
+ with a bit set in weights meaning their is an edge with that
+ weight.
+ We don't keep the src in the edge, because we always know what it
+ is. */
-/* The constraint graph is represented as an array of bitmaps
- containing successor nodes. */
+struct constraint_edge
+{
+ unsigned int dest;
+ bitmap weights;
+};
+
+typedef struct constraint_edge *constraint_edge_t;
+static alloc_pool constraint_edge_pool;
+
+/* Return a new constraint edge from SRC to DEST. */
+
+static constraint_edge_t
+new_constraint_edge (unsigned int dest)
+{
+ constraint_edge_t ret = pool_alloc (constraint_edge_pool);
+ ret->dest = dest;
+ ret->weights = NULL;
+ return ret;
+}
+
+DEF_VEC_P(constraint_edge_t);
+DEF_VEC_ALLOC_P(constraint_edge_t,heap);
+
+
+/* The constraint graph is represented internally in two different
+ ways. The overwhelming majority of edges in the constraint graph
+ are zero weigh edges, and thus, using a vector of contrainst_edge_t
+ is a waste of time and memory, since they have no weights. We
+ simply use a bitmap to store the preds and succs for each node.
+ The weighted edges are stored as a set of adjacency vectors, one
+ per variable. succs[x] is the vector of successors for variable x,
+ and preds[x] is the vector of predecessors for variable x. IOW,
+ all edges are "forward" edges, which is not like our CFG. So
+ remember that preds[x]->src == x, and succs[x]->src == x. */
struct constraint_graph
{
- bitmap *succs;
- bitmap *preds;
+ bitmap *zero_weight_succs;
+ bitmap *zero_weight_preds;
+ VEC(constraint_edge_t,heap) **succs;
+ VEC(constraint_edge_t,heap) **preds;
};
typedef struct constraint_graph *constraint_graph_t;
@@ -700,6 +739,44 @@ insert_into_complex (unsigned int var, constraint_t c)
}
+/* Compare two constraint edges A and B, return true if they are equal. */
+
+static bool
+constraint_edge_equal (struct constraint_edge a, struct constraint_edge b)
+{
+ return a.dest == b.dest;
+}
+
+/* Compare two constraint edges, return true if A is less than B */
+
+static bool
+constraint_edge_less (const constraint_edge_t a, const constraint_edge_t b)
+{
+ if (a->dest < b->dest)
+ return true;
+ return false;
+}
+
+/* Find the constraint edge that matches LOOKFOR, in VEC.
+ Return the edge, if found, NULL otherwise. */
+
+static constraint_edge_t
+constraint_edge_vec_find (VEC(constraint_edge_t,heap) *vec,
+ struct constraint_edge lookfor)
+{
+ unsigned int place;
+ constraint_edge_t edge = NULL;
+
+ place = VEC_lower_bound (constraint_edge_t, vec, &lookfor,
+ constraint_edge_less);
+ if (place >= VEC_length (constraint_edge_t, vec))
+ return NULL;
+ edge = VEC_index (constraint_edge_t, vec, place);
+ if (!constraint_edge_equal (*edge, lookfor))
+ return NULL;
+ return edge;
+}
+
/* Condense two variable nodes into a single variable node, by moving
all associated info from SRC to TO. */
@@ -738,43 +815,206 @@ condense_varmap_nodes (unsigned int to, unsigned int src)
srcvi->complex = NULL;
}
+/* Erase an edge from SRC to SRC from GRAPH. This routine only
+ handles self-edges (e.g. an edge from a to a). */
+
+static void
+erase_graph_self_edge (constraint_graph_t graph, unsigned int src)
+{
+ VEC(constraint_edge_t,heap) *predvec = graph->preds[src];
+ VEC(constraint_edge_t,heap) *succvec = graph->succs[src];
+ struct constraint_edge edge;
+ unsigned int place;
+
+ edge.dest = src;
+
+ /* Remove from the successors. */
+ place = VEC_lower_bound (constraint_edge_t, succvec, &edge,
+ constraint_edge_less);
+
+ /* Make sure we found the edge. */
+#ifdef ENABLE_CHECKING
+ {
+ constraint_edge_t tmp = VEC_index (constraint_edge_t, succvec, place);
+ gcc_assert (constraint_edge_equal (*tmp, edge));
+ }
+#endif
+ VEC_ordered_remove (constraint_edge_t, succvec, place);
+
+ /* Remove from the predecessors. */
+ place = VEC_lower_bound (constraint_edge_t, predvec, &edge,
+ constraint_edge_less);
+
+ /* Make sure we found the edge. */
+#ifdef ENABLE_CHECKING
+ {
+ constraint_edge_t tmp = VEC_index (constraint_edge_t, predvec, place);
+ gcc_assert (constraint_edge_equal (*tmp, edge));
+ }
+#endif
+ VEC_ordered_remove (constraint_edge_t, predvec, place);
+}
/* Remove edges involving NODE from GRAPH. */
static void
clear_edges_for_node (constraint_graph_t graph, unsigned int node)
{
+ VEC(constraint_edge_t,heap) *succvec = graph->succs[node];
+ VEC(constraint_edge_t,heap) *predvec = graph->preds[node];
bitmap_iterator bi;
unsigned int j;
+ constraint_edge_t c = NULL;
+ int i;
/* Walk the successors, erase the associated preds. */
- EXECUTE_IF_IN_NONNULL_BITMAP (graph->succs[node], 0, j, bi)
+ EXECUTE_IF_IN_NONNULL_BITMAP (graph->zero_weight_succs[node], 0, j, bi)
if (j != node)
- bitmap_clear_bit (graph->preds[j], node);
+ bitmap_clear_bit (graph->zero_weight_preds[j], node);
+ for (i = 0; VEC_iterate (constraint_edge_t, succvec, i, c); i++)
+ if (c->dest != node)
+ {
+ unsigned int place;
+ struct constraint_edge lookfor;
+ constraint_edge_t result;
+
+ lookfor.dest = node;
+ place = VEC_lower_bound (constraint_edge_t, graph->preds[c->dest],
+ &lookfor, constraint_edge_less);
+ result = VEC_ordered_remove (constraint_edge_t,
+ graph->preds[c->dest], place);
+ pool_free (constraint_edge_pool, result);
+ }
/* Walk the preds, erase the associated succs. */
- EXECUTE_IF_IN_NONNULL_BITMAP (graph->preds[node], 0, j, bi)
+ EXECUTE_IF_IN_NONNULL_BITMAP (graph->zero_weight_preds[node], 0, j, bi)
if (j != node)
- bitmap_clear_bit (graph->succs[j], node);
+ bitmap_clear_bit (graph->zero_weight_succs[j], node);
+ for (i =0; VEC_iterate (constraint_edge_t, predvec, i, c); i++)
+ if (c->dest != node)
+ {
+ unsigned int place;
+ struct constraint_edge lookfor;
+ constraint_edge_t result;
+
+ lookfor.dest = node;
+ place = VEC_lower_bound (constraint_edge_t, graph->succs[c->dest],
+ &lookfor, constraint_edge_less);
+ result = VEC_ordered_remove (constraint_edge_t,
+ graph->succs[c->dest], place);
+ pool_free (constraint_edge_pool, result);
- if (graph->preds[node])
+ }
+
+ if (graph->zero_weight_preds[node])
{
- BITMAP_FREE (graph->preds[node]);
- graph->preds[node] = NULL;
+ BITMAP_FREE (graph->zero_weight_preds[node]);
+ graph->zero_weight_preds[node] = NULL;
}
- if (graph->succs[node])
+ if (graph->zero_weight_succs[node])
{
- BITMAP_FREE (graph->succs[node]);
- graph->succs[node] = NULL;
- }
+ BITMAP_FREE (graph->zero_weight_succs[node]);
+ graph->zero_weight_succs[node] = NULL;
+ }
+
+ VEC_free (constraint_edge_t, heap, graph->preds[node]);
+ VEC_free (constraint_edge_t, heap, graph->succs[node]);
+ graph->preds[node] = NULL;
+ graph->succs[node] = NULL;
}
static bool edge_added = false;
+
+/* Add edge (src, dest) to the graph. */
+
+static bool
+add_graph_edge (constraint_graph_t graph, unsigned int src, unsigned int dest)
+{
+ unsigned int place;
+ VEC(constraint_edge_t,heap) *vec;
+ struct constraint_edge newe;
+ newe.dest = dest;
+
+ vec = graph->preds[src];
+ place = VEC_lower_bound (constraint_edge_t, vec, &newe,
+ constraint_edge_less);
+ if (place == VEC_length (constraint_edge_t, vec)
+ || VEC_index (constraint_edge_t, vec, place)->dest != dest)
+ {
+ constraint_edge_t edge = new_constraint_edge (dest);
+
+ VEC_safe_insert (constraint_edge_t, heap, graph->preds[src],
+ place, edge);
+ edge = new_constraint_edge (src);
+
+ place = VEC_lower_bound (constraint_edge_t, graph->succs[dest],
+ edge, constraint_edge_less);
+ VEC_safe_insert (constraint_edge_t, heap, graph->succs[dest],
+ place, edge);
+ edge_added = true;
+ stats.num_edges++;
+ return true;
+ }
+ else
+ return false;
+}
+
+
+/* Return the bitmap representing the weights of edge (SRC, DEST). */
+
+static bitmap *
+get_graph_weights (constraint_graph_t graph, unsigned int src,
+ unsigned int dest)
+{
+ constraint_edge_t edge;
+ VEC(constraint_edge_t,heap) *vec;
+ struct constraint_edge lookfor;
+
+ lookfor.dest = dest;
+
+ vec = graph->preds[src];
+ edge = constraint_edge_vec_find (vec, lookfor);
+ gcc_assert (edge != NULL);
+ return &edge->weights;
+}
+
+/* Allocate graph weight bitmap for the edges associated with SRC and
+ DEST in GRAPH. Both the pred and the succ edges share a single
+ bitmap, so we need to set both edges to that bitmap. */
+
+static bitmap
+allocate_graph_weights (constraint_graph_t graph, unsigned int src,
+ unsigned int dest)
+{
+ bitmap result;
+ constraint_edge_t edge;
+ VEC(constraint_edge_t,heap) *vec;
+ struct constraint_edge lookfor;
+
+ result = BITMAP_ALLOC (&ptabitmap_obstack);
+
+ /* Set the pred weight. */
+ lookfor.dest = dest;
+ vec = graph->preds[src];
+ edge = constraint_edge_vec_find (vec, lookfor);
+ gcc_assert (edge != NULL);
+ edge->weights = result;
+
+ /* Set the succ weight. */
+ lookfor.dest = src;
+ vec = graph->succs[dest];
+ edge = constraint_edge_vec_find (vec, lookfor);
+ gcc_assert (edge != NULL);
+ edge->weights = result;
+
+ return result;
+}
+
/* Merge GRAPH nodes FROM and TO into node TO. */
@@ -782,72 +1022,144 @@ static void
merge_graph_nodes (constraint_graph_t graph, unsigned int to,
unsigned int from)
{
+ VEC(constraint_edge_t,heap) *succvec = graph->succs[from];
+ VEC(constraint_edge_t,heap) *predvec = graph->preds[from];
+ int i;
+ constraint_edge_t c;
unsigned int j;
bitmap_iterator bi;
- /* Merge all the predecessor edges. */
- if (graph->preds[from])
+ /* Merge all the zero weighted predecessor edges. */
+ if (graph->zero_weight_preds[from])
{
- if (!graph->preds[to])
- graph->preds[to] = BITMAP_ALLOC (&predbitmap_obstack);
+ if (!graph->zero_weight_preds[to])
+ graph->zero_weight_preds[to] = BITMAP_ALLOC (&predbitmap_obstack);
- EXECUTE_IF_SET_IN_BITMAP (graph->preds[from], 0, j, bi)
+ EXECUTE_IF_SET_IN_BITMAP (graph->zero_weight_preds[from], 0, j, bi)
{
if (j != to)
{
- bitmap_clear_bit (graph->succs[j], from);
- bitmap_set_bit (graph->succs[j], to);
+ bitmap_clear_bit (graph->zero_weight_succs[j], from);
+ bitmap_set_bit (graph->zero_weight_succs[j], to);
}
}
- bitmap_ior_into (graph->preds[to],
- graph->preds[from]);
+ bitmap_ior_into (graph->zero_weight_preds[to],
+ graph->zero_weight_preds[from]);
}
- /* Merge all the successor edges. */
- if (graph->succs[from])
+ /* Merge all the zero weighted successor edges. */
+ if (graph->zero_weight_succs[from])
{
- if (!graph->succs[to])
- graph->succs[to] = BITMAP_ALLOC (&ptabitmap_obstack);
- EXECUTE_IF_SET_IN_BITMAP (graph->succs[from], 0, j, bi)
+ if (!graph->zero_weight_succs[to])
+ graph->zero_weight_succs[to] = BITMAP_ALLOC (&ptabitmap_obstack);
+ EXECUTE_IF_SET_IN_BITMAP (graph->zero_weight_succs[from], 0, j, bi)
+ {
+ bitmap_clear_bit (graph->zero_weight_preds[j], from);
+ bitmap_set_bit (graph->zero_weight_preds[j], to);
+ }
+ bitmap_ior_into (graph->zero_weight_succs[to],
+ graph->zero_weight_succs[from]);
+ }
+
+ /* Merge all the nonzero weighted predecessor edges. */
+ for (i = 0; VEC_iterate (constraint_edge_t, predvec, i, c); i++)
+ {
+ unsigned int d = c->dest;
+ bitmap temp;
+ bitmap *weights;
+
+ if (c->dest == from)
+ d = to;
+
+ add_graph_edge (graph, to, d);
+
+ temp = *(get_graph_weights (graph, from, c->dest));
+ if (temp)
{
- bitmap_clear_bit (graph->preds[j], from);
- bitmap_set_bit (graph->preds[j], to);
+ weights = get_graph_weights (graph, to, d);
+ if (!*weights)
+ *weights = allocate_graph_weights (graph, to, d);
+
+ bitmap_ior_into (*weights, temp);
}
- bitmap_ior_into (graph->succs[to],
- graph->succs[from]);
+
}
+
+ /* Merge all the nonzero weighted successor edges. */
+ for (i = 0; VEC_iterate (constraint_edge_t, succvec, i, c); i++)
+ {
+ unsigned int d = c->dest;
+ bitmap temp;
+ bitmap *weights;
+
+ if (c->dest == from)
+ d = to;
+ add_graph_edge (graph, d, to);
+
+ temp = *(get_graph_weights (graph, c->dest, from));
+ if (temp)
+ {
+ weights = get_graph_weights (graph, d, to);
+ if (!*weights)
+ *weights = allocate_graph_weights (graph, d, to);
+ bitmap_ior_into (*weights, temp);
+ }
+ }
clear_edges_for_node (graph, from);
}
-/* Add a graph edge to GRAPH, going from TO to FROM if
+/* Add a graph edge to GRAPH, going from TO to FROM, with WEIGHT, if
it doesn't exist in the graph already.
Return false if the edge already existed, true otherwise. */
static bool
-add_graph_edge (constraint_graph_t graph, unsigned int to,
- unsigned int from)
+int_add_graph_edge (constraint_graph_t graph, unsigned int to,
+ unsigned int from, unsigned HOST_WIDE_INT weight)
{
- if (to == from)
+ if (to == from && weight == 0)
{
return false;
}
else
{
bool r = false;
-
- if (!graph->preds[to])
- graph->preds[to] = BITMAP_ALLOC (&predbitmap_obstack);
- if (!graph->succs[from])
- graph->succs[from] = BITMAP_ALLOC (&ptabitmap_obstack);
- if (!bitmap_bit_p (graph->succs[from], to))
+
+ if (weight == 0)
{
- edge_added = true;
- r = true;
- stats.num_edges++;
- bitmap_set_bit (graph->preds[to], from);
- bitmap_set_bit (graph->succs[from], to);
+ if (!graph->zero_weight_preds[to])
+ graph->zero_weight_preds[to] = BITMAP_ALLOC (&predbitmap_obstack);
+ if (!graph->zero_weight_succs[from])
+ graph->zero_weight_succs[from] = BITMAP_ALLOC (&ptabitmap_obstack);
+ if (!bitmap_bit_p (graph->zero_weight_succs[from], to))
+ {
+ edge_added = true;
+ r = true;
+ stats.num_edges++;
+ bitmap_set_bit (graph->zero_weight_preds[to], from);
+ bitmap_set_bit (graph->zero_weight_succs[from], to);
+ }
}
+ else
+ {
+ bitmap *weights;
+
+ r = add_graph_edge (graph, to, from);
+ weights = get_graph_weights (graph, to, from);
+
+ if (!*weights)
+ {
+ r = true;
+ *weights = allocate_graph_weights (graph, to, from);
+ bitmap_set_bit (*weights, weight);
+ }
+ else
+ {
+ r |= !bitmap_bit_p (*weights, weight);
+ bitmap_set_bit (*weights, weight);
+ }
+ }
+
return r;
}
}
@@ -859,10 +1171,28 @@ static bool
valid_graph_edge (constraint_graph_t graph, unsigned int src,
unsigned int dest)
{
- return (graph->succs[dest]
- && bitmap_bit_p (graph->succs[dest], src));
+ struct constraint_edge lookfor;
+ lookfor.dest = src;
+
+ return (graph->zero_weight_succs[dest]
+ && bitmap_bit_p (graph->zero_weight_succs[dest], src))
+ || constraint_edge_vec_find (graph->succs[dest], lookfor) != NULL;
}
+/* Return true if {DEST, SRC} is an existing weighted graph edge (IE has
+ a weight other than 0) in GRAPH. */
+static bool
+valid_weighted_graph_edge (constraint_graph_t graph, unsigned int src,
+ unsigned int dest)
+{
+ struct constraint_edge lookfor;
+ lookfor.dest = src;
+
+ return graph->preds[src]
+ && constraint_edge_vec_find (graph->succs[dest], lookfor) != NULL;
+}
+
+
/* Build the constraint graph. */
static void
@@ -873,8 +1203,10 @@ build_constraint_graph (void)
graph = XNEW (struct constraint_graph);
graph_size = VEC_length (varinfo_t, varmap) + 1;
- graph->succs = XCNEWVEC (bitmap, graph_size);
- graph->preds = XCNEWVEC (bitmap, graph_size);
+ graph->succs = XCNEWVEC (VEC(constraint_edge_t,heap) *, graph_size);
+ graph->preds = XCNEWVEC (VEC(constraint_edge_t,heap) *, graph_size);
+ graph->zero_weight_succs = XCNEWVEC (bitmap, graph_size);
+ graph->zero_weight_preds = XCNEWVEC (bitmap, graph_size);
for (i = 0; VEC_iterate (constraint_t, constraints, i, c); i++)
{
@@ -902,14 +1234,12 @@ build_constraint_graph (void)
}
else if (lhsvar > anything_id)
{
- /* Ignore self edges, as they can't possibly contribute
+ /* Ignore 0 weighted self edges, as they can't possibly contribute
anything */
if (lhsvar != rhsvar || rhs.offset != 0 || lhs.offset != 0)
{
- if (rhs.offset != 0 || lhs.offset != 0)
- insert_into_complex (lhsvar, c);
- else
- add_graph_edge (graph, lhs.var, rhs.var);
+ /* x = y (simple) */
+ int_add_graph_edge (graph, lhs.var, rhs.var, rhs.offset);
}
}
@@ -961,7 +1291,7 @@ scc_visit (constraint_graph_t graph, struct scc_info *si, unsigned int n)
si->visited_index[n] = si->current_index ++;
/* Visit all the successors. */
- EXECUTE_IF_IN_NONNULL_BITMAP (graph->succs[n], 0, i, bi)
+ EXECUTE_IF_IN_NONNULL_BITMAP (graph->zero_weight_succs[n], 0, i, bi)
{
unsigned int w = i;
if (!TEST_BIT (si->visited, w))
@@ -1010,10 +1340,16 @@ collapse_nodes (constraint_graph_t graph, unsigned int to, unsigned int from)
if (valid_graph_edge (graph, to, to))
{
- if (graph->preds[to])
+ if (graph->zero_weight_preds[to])
+ {
+ bitmap_clear_bit (graph->zero_weight_preds[to], to);
+ bitmap_clear_bit (graph->zero_weight_succs[to], to);
+ }
+ if (valid_weighted_graph_edge (graph, to, to))
{
- bitmap_clear_bit (graph->preds[to], to);
- bitmap_clear_bit (graph->succs[to], to);
+ bitmap weights = *(get_graph_weights (graph, to, to));
+ if (!weights || bitmap_empty_p (weights))
+ erase_graph_self_edge (graph, to);
}
}
BITMAP_FREE (fromsol);
@@ -1058,7 +1394,7 @@ process_unification_queue (constraint_graph_t graph, struct scc_info *si,
Merge tmp into solution for rep, marking rep changed if this
changed rep's solution.
- Delete any self-edges we now have for rep. */
+ Delete any 0 weighted self-edges we now have for rep. */
while (i != VEC_length (unsigned, si->unification_queue))
{
unsigned int tounify = VEC_index (unsigned, si->unification_queue, i);
@@ -1111,11 +1447,17 @@ process_unification_queue (constraint_graph_t graph, struct scc_info *si,
if (valid_graph_edge (graph, n, n))
{
- if (graph->succs[n])
+ if (graph->zero_weight_succs[n])
{
- if (graph->preds[n])
- bitmap_clear_bit (graph->preds[n], n);
- bitmap_clear_bit (graph->succs[n], n);
+ if (graph->zero_weight_preds[n])
+ bitmap_clear_bit (graph->zero_weight_preds[n], n);
+ bitmap_clear_bit (graph->zero_weight_succs[n], n);
+ }
+ if (valid_weighted_graph_edge (graph, n, n))
+ {
+ bitmap weights = *(get_graph_weights (graph, n, n));
+ if (!weights || bitmap_empty_p (weights))
+ erase_graph_self_edge (graph, n);
}
}
}
@@ -1167,12 +1509,24 @@ static void
topo_visit (constraint_graph_t graph, struct topo_info *ti,
unsigned int n)
{
+ VEC(constraint_edge_t,heap) *succs = graph->succs[n];
bitmap temp;
bitmap_iterator bi;
+ constraint_edge_t c;
+ int i;
unsigned int j;
SET_BIT (ti->visited, n);
- temp = graph->succs[n];
+ if (VEC_length (constraint_edge_t, succs) != 0)
+ {
+ temp = BITMAP_ALLOC (&iteration_obstack);
+ if (graph->zero_weight_succs[n])
+ bitmap_ior_into (temp, graph->zero_weight_succs[n]);
+ for (i = 0; VEC_iterate (constraint_edge_t, succs, i, c); i++)
+ bitmap_set_bit (temp, c->dest);
+ }
+ else
+ temp = graph->zero_weight_succs[n];
if (temp)
EXECUTE_IF_SET_IN_BITMAP (temp, 0, j, bi)
@@ -1286,7 +1640,7 @@ do_sd_constraint (constraint_graph_t graph, constraint_t c,
They don't have sets that can change. */
if (get_varinfo (t) ->is_special_var)
flag |= bitmap_ior_into (sol, get_varinfo (t)->solution);
- else if (add_graph_edge (graph, lhs, t))
+ else if (int_add_graph_edge (graph, lhs, t, 0))
flag |= bitmap_ior_into (sol, get_varinfo (t)->solution);
}
else if (0 && dump_file && !(get_varinfo (j)->is_special_var))
@@ -1310,7 +1664,7 @@ done:
/* Process a constraint C that represents *x = y. */
static void
-do_ds_constraint (constraint_t c, bitmap delta)
+do_ds_constraint (constraint_graph_t graph, constraint_t c, bitmap delta)
{
unsigned int rhs = get_varinfo (c->rhs.var)->node;
unsigned HOST_WIDE_INT roff = c->rhs.offset;
@@ -1356,26 +1710,27 @@ do_ds_constraint (constraint_t c, bitmap delta)
varinfo_t v;
unsigned int t;
unsigned HOST_WIDE_INT fieldoffset = get_varinfo (j)->offset + loff;
- bitmap tmp;
-
+
v = first_vi_for_offset (get_varinfo (j), fieldoffset);
if (!v)
continue;
t = v->node;
- tmp = get_varinfo (t)->solution;
-
- if (set_union_with_increment (tmp, sol, roff))
+ if (int_add_graph_edge (graph, t, rhs, roff))
{
- get_varinfo (t)->solution = tmp;
- if (t == rhs)
- sol = get_varinfo (rhs)->solution;
- if (!TEST_BIT (changed, t))
+ bitmap tmp = get_varinfo (t)->solution;
+ if (set_union_with_increment (tmp, sol, roff))
{
- SET_BIT (changed, t);
- changed_count++;
+ get_varinfo (t)->solution = tmp;
+ if (t == rhs)
+ sol = get_varinfo (rhs)->solution;
+ if (!TEST_BIT (changed, t))
+ {
+ SET_BIT (changed, t);
+ changed_count++;
+ }
}
}
- }
+ }
else if (0 && dump_file && !(get_varinfo (j)->is_special_var))
fprintf (dump_file, "Untypesafe usage in do_ds_constraint\n");
}
@@ -1397,40 +1752,15 @@ do_complex_constraint (constraint_graph_t graph, constraint_t c, bitmap delta)
else
{
/* *x = y */
- do_ds_constraint (c, delta);
+ do_ds_constraint (graph, c, delta);
}
}
- else if (c->rhs.type == DEREF)
+ else
{
/* x = *y */
if (!(get_varinfo (c->lhs.var)->is_special_var))
do_sd_constraint (graph, c, delta);
}
- else
- {
- bitmap tmp;
- bitmap solution;
- bool flag = false;
- unsigned int t;
-
- gcc_assert(c->rhs.type == SCALAR && c->lhs.type == SCALAR);
- t = get_varinfo (c->rhs.var)->node;
- solution = get_varinfo (t)->solution;
- t = get_varinfo (c->lhs.var)->node;
- tmp = get_varinfo (t)->solution;
-
- flag = set_union_with_increment (tmp, solution, c->rhs.offset);
-
- if (flag)
- {
- get_varinfo (t)->solution = tmp;
- if (!TEST_BIT (changed, c->lhs.var))
- {
- SET_BIT (changed, c->lhs.var);
- changed_count++;
- }
- }
- }
}
/* Initialize and return a new SCC info structure. */
@@ -1501,6 +1831,21 @@ compute_topo_order (constraint_graph_t graph,
topo_visit (graph, ti, i);
}
+/* Return true if bitmap B is empty, or a bitmap other than bit 0 is set. */
+
+static bool
+bitmap_other_than_zero_bit_set (bitmap b)
+{
+ unsigned int i;
+ bitmap_iterator bi;
+
+ if (bitmap_empty_p (b))
+ return false;
+ EXECUTE_IF_SET_IN_BITMAP (b, 1, i, bi)
+ return true;
+ return false;
+}
+
/* Perform offline variable substitution.
This is a linear time way of identifying variables that must have
@@ -1524,9 +1869,12 @@ perform_var_substitution (constraint_graph_t graph)
while (VEC_length (unsigned, ti->topo_order) != 0)
{
unsigned int i = VEC_pop (unsigned, ti->topo_order);
+ unsigned int pred;
varinfo_t vi = get_varinfo (i);
bool okay_to_elim = false;
unsigned int root = VEC_length (varinfo_t, varmap);
+ VEC(constraint_edge_t,heap) *predvec = graph->preds[i];
+ constraint_edge_t ce = NULL;
bitmap tmp;
unsigned int k;
bitmap_iterator bi;
@@ -1537,7 +1885,7 @@ perform_var_substitution (constraint_graph_t graph)
continue;
/* See if all predecessors of I are ripe for elimination */
- EXECUTE_IF_IN_NONNULL_BITMAP (graph->preds[i], 0, k, bi)
+ EXECUTE_IF_IN_NONNULL_BITMAP (graph->zero_weight_preds[i], 0, k, bi)
{
unsigned int w;
w = get_varinfo (k)->node;
@@ -1573,6 +1921,55 @@ perform_var_substitution (constraint_graph_t graph)
BITMAP_FREE (tmp);
}
+ if (okay_to_elim)
+ for (pred = 0;
+ VEC_iterate (constraint_edge_t, predvec, pred, ce);
+ pred++)
+ {
+ bitmap weight;
+ unsigned int w;
+ weight = *(get_graph_weights (graph, i, ce->dest));
+
+ /* We can't eliminate variables that have nonzero weighted
+ edges between them. */
+ if (weight && bitmap_other_than_zero_bit_set (weight))
+ {
+ okay_to_elim = false;
+ break;
+ }
+ w = get_varinfo (ce->dest)->node;
+
+ /* We can't eliminate the node if one of the predecessors is
+ part of a different strongly connected component. */
+ if (!okay_to_elim)
+ {
+ root = w;
+ okay_to_elim = true;
+ }
+ else if (w != root)
+ {
+ okay_to_elim = false;
+ break;
+ }
+
+ /* Theorem 4 in Rountev and Chandra: If i is a direct node,
+ then Solution(i) is a subset of Solution (w), where w is a
+ predecessor in the graph.
+ Corollary: If all predecessors of i have the same
+ points-to set, then i has that same points-to set as
+ those predecessors. */
+ tmp = BITMAP_ALLOC (NULL);
+ bitmap_and_compl (tmp, get_varinfo (i)->solution,
+ get_varinfo (w)->solution);
+ if (!bitmap_empty_p (tmp))
+ {
+ okay_to_elim = false;
+ BITMAP_FREE (tmp);
+ break;
+ }
+ BITMAP_FREE (tmp);
+ }
+
/* See if the root is different than the original node.
If so, we've found an equivalence. */
if (root != get_varinfo (i)->node && okay_to_elim)
@@ -1647,9 +2044,11 @@ solve_graph (constraint_graph_t graph)
{
unsigned int j;
constraint_t c;
+ constraint_edge_t e = NULL;
bitmap solution;
bitmap_iterator bi;
VEC(constraint_t,heap) *complex = get_varinfo (i)->complex;
+ VEC(constraint_edge_t,heap) *succs;
bool solution_empty;
RESET_BIT (changed, i);
@@ -1674,14 +2073,14 @@ solve_graph (constraint_graph_t graph)
if (!solution_empty)
{
/* Propagate solution to all successors. */
- EXECUTE_IF_IN_NONNULL_BITMAP (graph->succs[i],
+ succs = graph->succs[i];
+
+ EXECUTE_IF_IN_NONNULL_BITMAP (graph->zero_weight_succs[i],
0, j, bi)
{
bitmap tmp = get_varinfo (j)->solution;
bool flag = false;
- gcc_assert (get_varinfo (j)->node == j);
-
flag = set_union_with_increment (tmp, solution, 0);
if (flag)
@@ -1694,13 +2093,35 @@ solve_graph (constraint_graph_t graph)
}
}
}
+ for (j = 0; VEC_iterate (constraint_edge_t, succs, j, e); j++)
+ {
+ bitmap tmp = get_varinfo (e->dest)->solution;
+ bool flag = false;
+ unsigned int k;
+ bitmap weights = e->weights;
+ bitmap_iterator bi;
+
+ gcc_assert (weights && !bitmap_empty_p (weights));
+ EXECUTE_IF_SET_IN_BITMAP (weights, 0, k, bi)
+ flag |= set_union_with_increment (tmp, solution, k);
+
+ if (flag)
+ {
+ get_varinfo (e->dest)->solution = tmp;
+ if (!TEST_BIT (changed, e->dest))
+ {
+ SET_BIT (changed, e->dest);
+ changed_count++;
+ }
+ }
+ }
}
}
}
free_topo_info (ti);
bitmap_obstack_release (&iteration_obstack);
}
-
+
sbitmap_free (changed);
}
@@ -4246,6 +4667,9 @@ init_alias_vars (void)
sizeof (struct constraint), 30);
variable_info_pool = create_alloc_pool ("Variable info pool",
sizeof (struct variable_info), 30);
+ constraint_edge_pool = create_alloc_pool ("Constraint edges",
+ sizeof (struct constraint_edge), 30);
+
constraints = VEC_alloc (constraint_t, heap, 8);
varmap = VEC_alloc (varinfo_t, heap, 8);
id_for_tree = htab_create (10, tree_id_hash, tree_id_eq, free);
@@ -4449,15 +4873,21 @@ delete_points_to_sets (void)
if (i >= graph_size)
break;
+ VEC_free (constraint_edge_t, heap, graph->succs[i]);
+ VEC_free (constraint_edge_t, heap, graph->preds[i]);
VEC_free (constraint_t, heap, v->complex);
}
- free (graph->preds);
+ free (graph->zero_weight_preds);
+ free (graph->zero_weight_succs);
free (graph->succs);
+ free (graph->preds);
free (graph);
VEC_free (varinfo_t, heap, varmap);
free_alloc_pool (variable_info_pool);
free_alloc_pool (constraint_pool);
+ free_alloc_pool (constraint_edge_pool);
+
have_alias_info = false;
}