Line data Source code
1 : /* Andersen-style solver for tree based points-to analysis
2 : Copyright (C) 2005-2026 Free Software Foundation, Inc.
3 : Contributed by Daniel Berlin <dberlin@dberlin.org>
4 :
5 : This file is part of GCC.
6 :
7 : GCC is free software; you can redistribute it and/or modify
8 : under the terms of the GNU General Public License as published by
9 : the Free Software Foundation; either version 3 of the License, or
10 : (at your option) any later version.
11 :
12 : GCC is distributed in the hope that it will be useful,
13 : but WITHOUT ANY WARRANTY; without even the implied warranty of
14 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 : GNU General Public License for more details.
16 :
17 : You should have received a copy of the GNU General Public License
18 : along with GCC; see the file COPYING3. If not see
19 : <http://www.gnu.org/licenses/>. */
20 :
21 : #include "config.h"
22 : #include "system.h"
23 : #include "coretypes.h"
24 : #include "backend.h"
25 :
26 : #include "tree-ssa-structalias.h"
27 : #include "pta-andersen.h"
28 :
29 : /* During variable substitution and the offline version of indirect
30 : cycle finding, we create nodes to represent dereferences and
31 : address taken constraints. These represent where these start and
32 : end. */
33 : #define FIRST_REF_NODE (varmap).length ()
34 : #define LAST_REF_NODE (FIRST_REF_NODE + (FIRST_REF_NODE - 1))
35 :
36 : #define EXECUTE_IF_IN_NONNULL_BITMAP(a, b, c, d) \
37 : if (a) \
38 : EXECUTE_IF_SET_IN_BITMAP (a, b, c, d)
39 :
40 : using namespace pointer_analysis;
41 :
42 : /* Used for predecessor bitmaps. */
43 : static bitmap_obstack predbitmap_obstack;
44 :
45 : /* Used for per-solver-iteration bitmaps. */
46 : static bitmap_obstack iteration_obstack;
47 :
48 : typedef struct constraint_graph *constraint_graph_t;
49 :
50 : /* The constraint graph is represented as an array of bitmaps
51 : containing successor nodes. */
52 :
53 : struct constraint_graph
54 : {
55 : /* Size of this graph, which may be different than the number of
56 : nodes in the variable map. */
57 : unsigned int size;
58 :
59 : /* Explicit successors of each node. */
60 : bitmap *succs;
61 :
62 : /* Implicit predecessors of each node (Used for variable
63 : substitution). */
64 : bitmap *implicit_preds;
65 :
66 : /* Explicit predecessors of each node (Used for variable substitution). */
67 : bitmap *preds;
68 :
69 : /* Indirect cycle representatives, or -1 if the node has no indirect
70 : cycles. */
71 : int *indirect_cycles;
72 :
73 : /* Representative node for a node. rep[a] == a unless the node has
74 : been unified. */
75 : unsigned int *rep;
76 :
77 : /* Equivalence class representative for a label. This is used for
78 : variable substitution. */
79 : int *eq_rep;
80 :
81 : /* Pointer equivalence label for a node. All nodes with the same
82 : pointer equivalence label can be unified together at some point
83 : (either during constraint optimization or after the constraint
84 : graph is built). */
85 : unsigned int *pe;
86 :
87 : /* Pointer equivalence representative for a label. This is used to
88 : handle nodes that are pointer equivalent but not location
89 : equivalent. We can unite these once the addressof constraints
90 : are transformed into initial points-to sets. */
91 : int *pe_rep;
92 :
93 : /* Pointer equivalence label for each node, used during variable
94 : substitution. */
95 : unsigned int *pointer_label;
96 :
97 : /* Location equivalence label for each node, used during location
98 : equivalence finding. */
99 : unsigned int *loc_label;
100 :
101 : /* Pointed-by set for each node, used during location equivalence
102 : finding. This is pointed-by rather than pointed-to, because it
103 : is constructed using the predecessor graph. */
104 : bitmap *pointed_by;
105 :
106 : /* Points to sets for pointer equivalence. This is *not* the actual
107 : points-to sets for nodes. */
108 : bitmap *points_to;
109 :
110 : /* Bitmap of nodes where the bit is set if the node is a direct
111 : node. Used for variable substitution. */
112 : sbitmap direct_nodes;
113 :
114 : /* Bitmap of nodes where the bit is set if the node is address
115 : taken. Used for variable substitution. */
116 : bitmap address_taken;
117 :
118 : /* Vector of complex constraints for each graph node. Complex
119 : constraints are those involving dereferences or offsets that are
120 : not 0. */
121 : vec<constraint_t> *complex;
122 : };
123 :
124 : static constraint_graph_t graph;
125 :
126 : static void unify_nodes (constraint_graph_t, unsigned int, unsigned int, bool);
127 :
128 :
129 : /* Return the representative node for NODE, if NODE has been unioned
130 : with another NODE.
131 : This function performs path compression along the way to finding
132 : the representative. */
133 :
134 : static unsigned int
135 8793153692 : find (unsigned int node)
136 : {
137 8793153692 : gcc_checking_assert (node < graph->size);
138 8793153692 : if (graph->rep[node] != node)
139 431051465 : return graph->rep[node] = find (graph->rep[node]);
140 : return node;
141 : }
142 :
143 : /* Union the TO and FROM nodes to the TO nodes.
144 : Note that at some point in the future, we may want to do
145 : union-by-rank, in which case we are going to have to return the
146 : node we unified to. */
147 :
148 : static bool
149 620562618 : unite (unsigned int to, unsigned int from)
150 : {
151 620562618 : gcc_checking_assert (to < graph->size && from < graph->size);
152 620562618 : if (to != from
153 121148910 : && graph->rep[from] != to
154 : /* Do not merge an artificial variable into another, this will
155 : explode solution sets unnecessarily. */
156 862736907 : && (from >= FIRST_REF_NODE || !get_varinfo (from)->is_artificial_var))
157 : {
158 44102250 : graph->rep[from] = to;
159 44102250 : return true;
160 : }
161 : return false;
162 : }
163 :
164 : /* Perform path compression for all nodes in the node representatives
165 : union-find structure. */
166 :
167 : static void
168 4624489 : union_find_compress_all (void)
169 : {
170 4624489 : unsigned int i;
171 240185108 : for (i = 0; i < graph->size; i++)
172 235560619 : find (i);
173 4624489 : }
174 :
175 : /* Print the constraint graph in dot format. */
176 :
177 : static void
178 6 : dump_constraint_graph (FILE *file)
179 : {
180 6 : unsigned int i;
181 :
182 : /* Only print the graph if it has already been initialized: */
183 6 : if (!graph)
184 : return;
185 :
186 : /* Prints the header of the dot file: */
187 6 : fprintf (file, "strict digraph {\n");
188 6 : fprintf (file, " node [\n shape = box\n ]\n");
189 6 : fprintf (file, " edge [\n fontsize = \"12\"\n ]\n");
190 6 : fprintf (file, "\n // List of nodes and complex constraints in "
191 : "the constraint graph:\n");
192 :
193 : /* The next lines print the nodes in the graph together with the
194 : complex constraints attached to them. */
195 86 : for (i = 1; i < graph->size; i++)
196 : {
197 148 : if (i == FIRST_REF_NODE)
198 0 : continue;
199 74 : if (find (i) != i)
200 2 : continue;
201 72 : if (i < FIRST_REF_NODE)
202 72 : fprintf (file, "\"%s\"", get_varinfo (i)->name);
203 : else
204 0 : fprintf (file, "\"*%s\"", get_varinfo (i - FIRST_REF_NODE)->name);
205 72 : if (graph->complex[i].exists ())
206 : {
207 16 : unsigned j;
208 16 : constraint_t c;
209 16 : fprintf (file, " [label=\"\\N\\n");
210 70 : for (j = 0; graph->complex[i].iterate (j, &c); ++j)
211 : {
212 38 : dump_constraint (file, c);
213 38 : fprintf (file, "\\l");
214 : }
215 16 : fprintf (file, "\"]");
216 : }
217 72 : fprintf (file, ";\n");
218 : }
219 :
220 : /* Go over the edges. */
221 6 : fprintf (file, "\n // Edges in the constraint graph:\n");
222 86 : for (i = 1; i < graph->size; i++)
223 : {
224 74 : unsigned j;
225 74 : bitmap_iterator bi;
226 74 : if (find (i) != i)
227 2 : continue;
228 102 : EXECUTE_IF_IN_NONNULL_BITMAP (graph->succs[i], 0, j, bi)
229 : {
230 30 : unsigned to = find (j);
231 30 : if (i == to)
232 0 : continue;
233 30 : if (i < FIRST_REF_NODE)
234 30 : fprintf (file, "\"%s\"", get_varinfo (i)->name);
235 : else
236 0 : fprintf (file, "\"*%s\"", get_varinfo (i - FIRST_REF_NODE)->name);
237 30 : fprintf (file, " -> ");
238 30 : if (to < FIRST_REF_NODE)
239 30 : fprintf (file, "\"%s\"", get_varinfo (to)->name);
240 : else
241 0 : fprintf (file, "\"*%s\"", get_varinfo (to - FIRST_REF_NODE)->name);
242 30 : fprintf (file, ";\n");
243 : }
244 : }
245 :
246 : /* Prints the tail of the dot file. */
247 6 : fprintf (file, "}\n");
248 : }
249 :
250 : /* Print out the constraint graph to stderr. */
251 :
252 : DEBUG_FUNCTION void
253 0 : debug_constraint_graph (void)
254 : {
255 0 : dump_constraint_graph (stderr);
256 0 : }
257 :
258 :
259 : /* SOLVER FUNCTIONS
260 :
261 : The solver is a simple worklist solver, that works on the following
262 : algorithm:
263 :
264 : sbitmap changed_nodes = all zeroes;
265 : changed_count = 0;
266 : For each node that is not already collapsed:
267 : changed_count++;
268 : set bit in changed nodes
269 :
270 : while (changed_count > 0)
271 : {
272 : compute topological ordering for constraint graph
273 :
274 : find and collapse cycles in the constraint graph (updating
275 : changed if necessary)
276 :
277 : for each node (n) in the graph in topological order:
278 : changed_count--;
279 :
280 : Process each complex constraint associated with the node,
281 : updating changed if necessary.
282 :
283 : For each outgoing edge from n, propagate the solution from n to
284 : the destination of the edge, updating changed as necessary.
285 :
286 : } */
287 :
288 : /* Return true if two constraint expressions A and B are equal. */
289 :
290 : static bool
291 18322641 : constraint_expr_equal (struct constraint_expr a, struct constraint_expr b)
292 : {
293 11050274 : return a.type == b.type && a.var == b.var && a.offset == b.offset;
294 : }
295 :
296 : /* Return true if constraint expression A is less than constraint expression
297 : B. This is just arbitrary, but consistent, in order to give them an
298 : ordering. */
299 :
300 : static bool
301 455523185 : constraint_expr_less (struct constraint_expr a, struct constraint_expr b)
302 : {
303 0 : if (a.type == b.type)
304 : {
305 271091158 : if (a.var == b.var)
306 204264662 : return a.offset < b.offset;
307 : else
308 66826496 : return a.var < b.var;
309 : }
310 : else
311 184432027 : return a.type < b.type;
312 : }
313 :
314 : /* Return true if constraint A is less than constraint B. This is just
315 : arbitrary, but consistent, in order to give them an ordering. */
316 :
317 : static bool
318 251021043 : constraint_less (const constraint_t &a, const constraint_t &b)
319 : {
320 502042086 : if (constraint_expr_less (a->lhs, b->lhs))
321 : return true;
322 215851684 : else if (constraint_expr_less (b->lhs, a->lhs))
323 : return false;
324 : else
325 96576300 : return constraint_expr_less (a->rhs, b->rhs);
326 : }
327 :
328 : /* Return true if two constraints A and B are equal. */
329 :
330 : static bool
331 12063652 : constraint_equal (const constraint &a, const constraint &b)
332 : {
333 18322641 : return constraint_expr_equal (a.lhs, b.lhs)
334 12063652 : && constraint_expr_equal (a.rhs, b.rhs);
335 : }
336 :
337 : /* Find a constraint LOOKFOR in the sorted constraint vector VEC. */
338 :
339 : static constraint_t
340 12349 : constraint_vec_find (vec<constraint_t> vec,
341 : constraint &lookfor)
342 : {
343 12349 : unsigned int place;
344 12349 : constraint_t found;
345 :
346 12349 : if (!vec.exists ())
347 : return NULL;
348 :
349 10090 : place = vec.lower_bound (&lookfor, constraint_less);
350 10090 : if (place >= vec.length ())
351 : return NULL;
352 4331 : found = vec[place];
353 4331 : if (!constraint_equal (*found, lookfor))
354 4244 : return NULL;
355 : return found;
356 : }
357 :
358 : /* Union two constraint vectors, TO and FROM. Put the result in TO.
359 : Returns true of TO set is changed. */
360 :
361 : static bool
362 43979015 : constraint_set_union (vec<constraint_t> *to,
363 : vec<constraint_t> *from)
364 : {
365 43979015 : int i;
366 43979015 : constraint_t c;
367 43979015 : bool any_change = false;
368 :
369 43991364 : FOR_EACH_VEC_ELT (*from, i, c)
370 : {
371 12349 : if (constraint_vec_find (*to, *c) == NULL)
372 : {
373 12262 : unsigned int place = to->lower_bound (c, constraint_less);
374 12262 : to->safe_insert (place, c);
375 12262 : any_change = true;
376 : }
377 : }
378 43979015 : return any_change;
379 : }
380 :
381 : /* Expands the solution in SET to all sub-fields of variables included. */
382 :
383 : static bitmap
384 137686097 : solution_set_expand (bitmap set, bitmap *expanded)
385 : {
386 137686097 : bitmap_iterator bi;
387 137686097 : unsigned j;
388 :
389 137686097 : if (*expanded)
390 : return *expanded;
391 :
392 76966660 : *expanded = BITMAP_ALLOC (&iteration_obstack);
393 :
394 : /* In a first pass expand variables, once for each head to avoid
395 : quadratic behavior, to include all sub-fields. */
396 76966660 : unsigned prev_head = 0;
397 263512993 : EXECUTE_IF_SET_IN_BITMAP (set, 0, j, bi)
398 : {
399 186546333 : varinfo_t v = get_varinfo (j);
400 186546333 : if (v->is_artificial_var
401 92474151 : || v->is_full_var)
402 110686772 : continue;
403 75859561 : if (v->head != prev_head)
404 : {
405 19346431 : varinfo_t head = get_varinfo (v->head);
406 19346431 : unsigned num = 1;
407 114016460 : for (varinfo_t n = vi_next (head); n != NULL; n = vi_next (n))
408 : {
409 94670029 : if (n->id != head->id + num)
410 : {
411 : /* Usually sub variables are adjacent but since we
412 : create pointed-to restrict representatives there
413 : can be gaps as well. */
414 15061 : bitmap_set_range (*expanded, head->id, num);
415 15061 : head = n;
416 15061 : num = 1;
417 : }
418 : else
419 94654968 : num++;
420 : }
421 :
422 19346431 : bitmap_set_range (*expanded, head->id, num);
423 19346431 : prev_head = v->head;
424 : }
425 : }
426 :
427 : /* And finally set the rest of the bits from SET in an efficient way. */
428 76966660 : bitmap_ior_into (*expanded, set);
429 :
430 76966660 : return *expanded;
431 : }
432 :
433 : /* Union solution sets TO and DELTA, and add INC to each member of DELTA in the
434 : process. */
435 :
436 : static bool
437 86561521 : set_union_with_increment (bitmap to, bitmap delta, HOST_WIDE_INT inc,
438 : bitmap *expanded_delta)
439 : {
440 86561521 : bool changed = false;
441 86561521 : bitmap_iterator bi;
442 86561521 : unsigned int i;
443 :
444 : /* If the solution of DELTA contains anything it is good enough to transfer
445 : this to TO. */
446 86561521 : if (bitmap_bit_p (delta, anything_id))
447 1186052 : return bitmap_set_bit (to, anything_id);
448 :
449 : /* If the offset is unknown we have to expand the solution to
450 : all subfields. */
451 85375469 : if (inc == UNKNOWN_OFFSET)
452 : {
453 84388893 : delta = solution_set_expand (delta, expanded_delta);
454 84388893 : changed |= bitmap_ior_into (to, delta);
455 84388893 : return changed;
456 : }
457 :
458 : /* For non-zero offset union the offsetted solution into the destination. */
459 3469544 : EXECUTE_IF_SET_IN_BITMAP (delta, 0, i, bi)
460 : {
461 2482968 : varinfo_t vi = get_varinfo (i);
462 :
463 : /* If this is a variable with just one field just set its bit
464 : in the result. */
465 2482968 : if (vi->is_artificial_var
466 1175234 : || vi->is_unknown_size_var
467 1029742 : || vi->is_full_var)
468 1644825 : changed |= bitmap_set_bit (to, i);
469 : else
470 : {
471 838143 : HOST_WIDE_INT fieldoffset = vi->offset + inc;
472 838143 : unsigned HOST_WIDE_INT size = vi->size;
473 :
474 : /* If the offset makes the pointer point to before the
475 : variable use offset zero for the field lookup. */
476 838143 : if (fieldoffset < 0)
477 71220 : vi = get_varinfo (vi->head);
478 : else
479 766923 : vi = first_or_preceding_vi_for_offset (vi, fieldoffset);
480 :
481 1855121 : do
482 : {
483 1855121 : changed |= bitmap_set_bit (to, vi->id);
484 1855121 : if (vi->is_full_var
485 1855081 : || vi->next == 0)
486 : break;
487 :
488 : /* We have to include all fields that overlap the current field
489 : shifted by inc. */
490 1306652 : vi = vi_next (vi);
491 : }
492 1306652 : while (vi->offset < fieldoffset + size);
493 : }
494 : }
495 :
496 : return changed;
497 : }
498 :
499 : /* Insert constraint C into the list of complex constraints for graph
500 : node VAR. */
501 :
502 : static void
503 150825843 : insert_into_complex (constraint_graph_t graph,
504 : unsigned int var, constraint_t c)
505 : {
506 150825843 : vec<constraint_t> complex = graph->complex[var];
507 150825843 : unsigned int place = complex.lower_bound (c, constraint_less);
508 :
509 : /* Only insert constraints that do not already exist. */
510 150825843 : if (place >= complex.length ()
511 102777106 : || !constraint_equal (*c, *complex[place]))
512 149330546 : graph->complex[var].safe_insert (place, c);
513 150825843 : }
514 :
515 :
516 : /* Condense two variable nodes into a single variable node, by moving
517 : all associated info from FROM to TO. Returns true if TO node's
518 : constraint set changes after the merge. */
519 :
520 : static bool
521 43979015 : merge_node_constraints (constraint_graph_t graph, unsigned int to,
522 : unsigned int from)
523 : {
524 43979015 : unsigned int i;
525 43979015 : constraint_t c;
526 43979015 : bool any_change = false;
527 :
528 43979015 : gcc_checking_assert (find (from) == to);
529 :
530 : /* Move all complex constraints from src node into to node. */
531 43991364 : FOR_EACH_VEC_ELT (graph->complex[from], i, c)
532 : {
533 : /* In complex constraints for node FROM, we may have either
534 : a = *FROM, and *FROM = a, or an offsetted constraint which are
535 : always added to the rhs node's constraints. */
536 :
537 12349 : if (c->rhs.type == DEREF)
538 2989 : c->rhs.var = to;
539 9360 : else if (c->lhs.type == DEREF)
540 4630 : c->lhs.var = to;
541 : else
542 4730 : c->rhs.var = to;
543 :
544 : }
545 43979015 : any_change = constraint_set_union (&graph->complex[to],
546 : &graph->complex[from]);
547 43979015 : graph->complex[from].release ();
548 43979015 : return any_change;
549 : }
550 :
551 : /* Remove edges involving NODE from GRAPH. */
552 :
553 : static void
554 64468718 : clear_edges_for_node (constraint_graph_t graph, unsigned int node)
555 : {
556 64468718 : if (graph->succs[node])
557 818547 : BITMAP_FREE (graph->succs[node]);
558 64468718 : }
559 :
560 : /* Merge GRAPH nodes FROM and TO into node TO. */
561 :
562 : static void
563 43979015 : merge_graph_nodes (constraint_graph_t graph, unsigned int to,
564 : unsigned int from)
565 : {
566 43979015 : if (graph->indirect_cycles[from] != -1)
567 : {
568 : /* If we have indirect cycles with the from node, and we have
569 : none on the to node, the to node has indirect cycles from the
570 : from node now that they are unified.
571 : If indirect cycles exist on both, unify the nodes that they
572 : are in a cycle with, since we know they are in a cycle with
573 : each other. */
574 108 : if (graph->indirect_cycles[to] == -1)
575 83 : graph->indirect_cycles[to] = graph->indirect_cycles[from];
576 : }
577 :
578 : /* Merge all the successor edges. */
579 43979015 : if (graph->succs[from])
580 : {
581 818547 : if (!graph->succs[to])
582 427279 : graph->succs[to] = BITMAP_ALLOC (&pta_obstack);
583 818547 : bitmap_ior_into (graph->succs[to],
584 818547 : graph->succs[from]);
585 : }
586 :
587 43979015 : clear_edges_for_node (graph, from);
588 43979015 : }
589 :
590 :
591 : /* Add an indirect graph edge to GRAPH, going from TO to FROM if
592 : it doesn't exist in the graph already. */
593 :
594 : static void
595 303703445 : add_implicit_graph_edge (constraint_graph_t graph, unsigned int to,
596 : unsigned int from)
597 : {
598 303703445 : if (to == from)
599 : return;
600 :
601 303703445 : if (!graph->implicit_preds[to])
602 170235003 : graph->implicit_preds[to] = BITMAP_ALLOC (&predbitmap_obstack);
603 :
604 303703445 : if (bitmap_set_bit (graph->implicit_preds[to], from))
605 285547571 : stats.num_implicit_edges++;
606 : }
607 :
608 : /* Add a predecessor graph edge to GRAPH, going from TO to FROM if
609 : it doesn't exist in the graph already.
610 : Return false if the edge already existed, true otherwise. */
611 :
612 : static void
613 256849911 : add_pred_graph_edge (constraint_graph_t graph, unsigned int to,
614 : unsigned int from)
615 : {
616 256849911 : if (!graph->preds[to])
617 151533543 : graph->preds[to] = BITMAP_ALLOC (&predbitmap_obstack);
618 256849911 : bitmap_set_bit (graph->preds[to], from);
619 256849911 : }
620 :
621 : /* Add a graph edge to GRAPH, going from FROM to TO if
622 : it doesn't exist in the graph already.
623 : Return false if the edge already existed, true otherwise. */
624 :
625 : static bool
626 708138766 : add_graph_edge (constraint_graph_t graph, unsigned int to,
627 : unsigned int from)
628 : {
629 708138766 : if (to == from)
630 : {
631 : return false;
632 : }
633 : else
634 : {
635 707878587 : bool r = false;
636 :
637 707878587 : if (!graph->succs[from])
638 104445035 : graph->succs[from] = BITMAP_ALLOC (&pta_obstack);
639 :
640 : /* The graph solving process does not avoid "triangles", thus
641 : there can be multiple paths from a node to another involving
642 : intermediate other nodes. That causes extra copying which is
643 : most difficult to avoid when the intermediate node is ESCAPED
644 : because there are no edges added from ESCAPED. Avoid
645 : adding the direct edge FROM -> TO when we have FROM -> ESCAPED
646 : and TO contains ESCAPED.
647 : ??? Note this is only a heuristic, it does not prevent the
648 : situation from occurring. The heuristic helps PR38474 and
649 : PR99912 significantly. */
650 707878587 : if (to < FIRST_REF_NODE
651 674941026 : && bitmap_bit_p (graph->succs[from], find (escaped_id))
652 948416992 : && bitmap_bit_p (get_varinfo (find (to))->solution, escaped_id))
653 : {
654 207138396 : stats.num_avoided_edges++;
655 207138396 : return false;
656 : }
657 :
658 500740191 : if (bitmap_set_bit (graph->succs[from], to))
659 : {
660 418647947 : r = true;
661 418647947 : if (to < FIRST_REF_NODE && from < FIRST_REF_NODE)
662 372977802 : stats.num_edges++;
663 : }
664 : return r;
665 : }
666 : }
667 :
668 : /* Initialize the constraint graph structure to contain SIZE nodes. */
669 :
670 : static void
671 4624489 : init_graph (unsigned int size)
672 : {
673 4624489 : unsigned int j;
674 :
675 4624489 : bitmap_obstack_initialize (&predbitmap_obstack);
676 :
677 4624489 : graph = XCNEW (struct constraint_graph);
678 4624489 : graph->size = size;
679 4624489 : graph->succs = XCNEWVEC (bitmap, graph->size);
680 4624489 : graph->indirect_cycles = XNEWVEC (int, graph->size);
681 4624489 : graph->rep = XNEWVEC (unsigned int, graph->size);
682 : /* ??? Macros do not support template types with multiple arguments,
683 : so we use a typedef to work around it. */
684 4624489 : typedef vec<constraint_t> vec_constraint_t_heap;
685 4624489 : graph->complex = XCNEWVEC (vec_constraint_t_heap, size);
686 4624489 : graph->pe = XCNEWVEC (unsigned int, graph->size);
687 4624489 : graph->pe_rep = XNEWVEC (int, graph->size);
688 :
689 475745727 : for (j = 0; j < graph->size; j++)
690 : {
691 471121238 : graph->rep[j] = j;
692 471121238 : graph->pe_rep[j] = -1;
693 471121238 : graph->indirect_cycles[j] = -1;
694 : }
695 4624489 : }
696 :
697 : /* Build the constraint graph, adding only predecessor edges right now. */
698 :
699 : static void
700 4624489 : build_pred_graph (void)
701 : {
702 4624489 : int i;
703 4624489 : constraint_t c;
704 4624489 : unsigned int j;
705 :
706 4624489 : graph->implicit_preds = XCNEWVEC (bitmap, graph->size);
707 4624489 : graph->preds = XCNEWVEC (bitmap, graph->size);
708 4624489 : graph->pointer_label = XCNEWVEC (unsigned int, graph->size);
709 4624489 : graph->loc_label = XCNEWVEC (unsigned int, graph->size);
710 4624489 : graph->pointed_by = XCNEWVEC (bitmap, graph->size);
711 4624489 : graph->points_to = XCNEWVEC (bitmap, graph->size);
712 4624489 : graph->eq_rep = XNEWVEC (int, graph->size);
713 4624489 : graph->direct_nodes = sbitmap_alloc (graph->size);
714 4624489 : graph->address_taken = BITMAP_ALLOC (&predbitmap_obstack);
715 4624489 : bitmap_clear (graph->direct_nodes);
716 :
717 475745727 : for (j = 1; j < FIRST_REF_NODE; j++)
718 : {
719 230936130 : if (!get_varinfo (j)->is_special_var)
720 207813685 : bitmap_set_bit (graph->direct_nodes, j);
721 : }
722 :
723 475745727 : for (j = 0; j < graph->size; j++)
724 471121238 : graph->eq_rep[j] = -1;
725 :
726 480370216 : for (j = 0; j < varmap.length (); j++)
727 235560619 : graph->indirect_cycles[j] = -1;
728 :
729 460410906 : FOR_EACH_VEC_ELT (constraints, i, c)
730 : {
731 455786417 : struct constraint_expr lhs = c->lhs;
732 455786417 : struct constraint_expr rhs = c->rhs;
733 455786417 : unsigned int lhsvar = lhs.var;
734 455786417 : unsigned int rhsvar = rhs.var;
735 :
736 455786417 : if (lhs.type == DEREF)
737 : {
738 : /* *x = y. */
739 37503374 : if (rhs.offset == 0 && lhs.offset == 0 && rhs.type == SCALAR)
740 : {
741 32957595 : if (lhs.var == anything_id)
742 0 : add_pred_graph_edge (graph, storedanything_id, rhsvar);
743 : else
744 65915190 : add_pred_graph_edge (graph, FIRST_REF_NODE + lhsvar, rhsvar);
745 : }
746 : }
747 418283043 : else if (rhs.type == DEREF)
748 : {
749 : /* x = *y */
750 50710733 : if (rhs.offset == 0 && lhs.offset == 0 && lhs.type == SCALAR)
751 27255084 : add_pred_graph_edge (graph, lhsvar, FIRST_REF_NODE + rhsvar);
752 : else
753 37083191 : bitmap_clear_bit (graph->direct_nodes, lhsvar);
754 : }
755 367572310 : else if (rhs.type == ADDRESSOF)
756 : {
757 93438671 : varinfo_t v;
758 :
759 : /* x = &y */
760 93438671 : if (graph->points_to[lhsvar] == NULL)
761 69330283 : graph->points_to[lhsvar] = BITMAP_ALLOC (&predbitmap_obstack);
762 93438671 : bitmap_set_bit (graph->points_to[lhsvar], rhsvar);
763 :
764 93438671 : if (graph->pointed_by[rhsvar] == NULL)
765 22525138 : graph->pointed_by[rhsvar] = BITMAP_ALLOC (&predbitmap_obstack);
766 93438671 : bitmap_set_bit (graph->pointed_by[rhsvar], lhsvar);
767 :
768 : /* Implicitly, *x = y */
769 186877342 : add_implicit_graph_edge (graph, FIRST_REF_NODE + lhsvar, rhsvar);
770 :
771 : /* All related variables are no longer direct nodes. */
772 93438671 : bitmap_clear_bit (graph->direct_nodes, rhsvar);
773 93438671 : v = get_varinfo (rhsvar);
774 93438671 : if (!v->is_full_var)
775 : {
776 7943117 : v = get_varinfo (v->head);
777 51589748 : do
778 : {
779 51589748 : bitmap_clear_bit (graph->direct_nodes, v->id);
780 51589748 : v = vi_next (v);
781 : }
782 51589748 : while (v != NULL);
783 : }
784 93438671 : bitmap_set_bit (graph->address_taken, rhsvar);
785 : }
786 274133639 : else if (lhsvar > anything_id
787 274133639 : && lhsvar != rhsvar && lhs.offset == 0 && rhs.offset == 0)
788 : {
789 : /* x = y */
790 210264774 : add_pred_graph_edge (graph, lhsvar, rhsvar);
791 : /* Implicitly, *x = *y */
792 210264774 : add_implicit_graph_edge (graph, FIRST_REF_NODE + lhsvar,
793 210264774 : FIRST_REF_NODE + rhsvar);
794 : }
795 63868865 : else if (lhs.offset != 0 || rhs.offset != 0)
796 : {
797 63672506 : if (rhs.offset != 0)
798 63672506 : bitmap_clear_bit (graph->direct_nodes, lhs.var);
799 0 : else if (lhs.offset != 0)
800 0 : bitmap_clear_bit (graph->direct_nodes, rhs.var);
801 : }
802 : }
803 4624489 : }
804 :
805 : /* Build the constraint graph, adding successor edges. */
806 :
807 : static void
808 4624489 : build_succ_graph (void)
809 : {
810 4624489 : unsigned i, t;
811 4624489 : constraint_t c;
812 :
813 460410906 : FOR_EACH_VEC_ELT (constraints, i, c)
814 : {
815 455786417 : struct constraint_expr lhs;
816 455786417 : struct constraint_expr rhs;
817 455786417 : unsigned int lhsvar;
818 455786417 : unsigned int rhsvar;
819 :
820 455786417 : if (!c)
821 2554388 : continue;
822 :
823 453232029 : lhs = c->lhs;
824 453232029 : rhs = c->rhs;
825 453232029 : lhsvar = find (lhs.var);
826 453232029 : rhsvar = find (rhs.var);
827 :
828 453232029 : if (lhs.type == DEREF)
829 : {
830 37462554 : if (rhs.offset == 0 && lhs.offset == 0 && rhs.type == SCALAR)
831 : {
832 32937561 : if (lhs.var == anything_id)
833 0 : add_graph_edge (graph, storedanything_id, rhsvar);
834 : else
835 65875122 : add_graph_edge (graph, FIRST_REF_NODE + lhsvar, rhsvar);
836 : }
837 : }
838 415769475 : else if (rhs.type == DEREF)
839 : {
840 50709803 : if (rhs.offset == 0 && lhs.offset == 0 && lhs.type == SCALAR)
841 27253610 : add_graph_edge (graph, lhsvar, FIRST_REF_NODE + rhsvar);
842 : }
843 365059672 : else if (rhs.type == ADDRESSOF)
844 : {
845 : /* x = &y */
846 93438671 : gcc_checking_assert (find (rhs.var) == rhs.var);
847 93438671 : bitmap_set_bit (get_varinfo (lhsvar)->solution, rhsvar);
848 : }
849 271621001 : else if (lhsvar > anything_id
850 271621001 : && lhsvar != rhsvar && lhs.offset == 0 && rhs.offset == 0)
851 : {
852 180420000 : add_graph_edge (graph, lhsvar, rhsvar);
853 : }
854 : }
855 :
856 : /* Add edges from STOREDANYTHING to all nodes that can receive pointers. */
857 4624489 : t = find (storedanything_id);
858 203189196 : for (i = integer_id + 1; i < FIRST_REF_NODE; ++i)
859 : {
860 193940218 : if (get_varinfo (i)->may_have_pointers)
861 193916333 : add_graph_edge (graph, find (i), t);
862 : }
863 :
864 : /* Everything stored to ANYTHING also potentially escapes. */
865 4624489 : add_graph_edge (graph, find (escaped_id), t);
866 4624489 : }
867 :
868 :
869 : /* Changed variables on the last iteration. */
870 : static bitmap changed;
871 :
872 : /* Strongly Connected Component visitation info. */
873 :
874 : class scc_info
875 : {
876 : public:
877 : scc_info (size_t size);
878 : ~scc_info ();
879 :
880 : auto_sbitmap visited;
881 : auto_sbitmap deleted;
882 : unsigned int *dfs;
883 : unsigned int *node_mapping;
884 : int current_index;
885 : auto_vec<unsigned> scc_stack;
886 : };
887 :
888 :
889 : /* Recursive routine to find strongly connected components in GRAPH.
890 : SI is the SCC info to store the information in, and N is the id of current
891 : graph node we are processing.
892 :
893 : This is Tarjan's strongly connected component finding algorithm, as
894 : modified by Nuutila to keep only non-root nodes on the stack.
895 : The algorithm can be found in "On finding the strongly connected
896 : connected components in a directed graph" by Esko Nuutila and Eljas
897 : Soisalon-Soininen, in Information Processing Letters volume 49,
898 : number 1, pages 9-14. */
899 :
900 : static void
901 423569458 : scc_visit (constraint_graph_t graph, class scc_info *si, unsigned int n)
902 : {
903 423569458 : unsigned int i;
904 423569458 : bitmap_iterator bi;
905 423569458 : unsigned int my_dfs;
906 :
907 423569458 : bitmap_set_bit (si->visited, n);
908 423569458 : si->dfs[n] = si->current_index ++;
909 423569458 : my_dfs = si->dfs[n];
910 :
911 : /* Visit all the successors. */
912 781884509 : EXECUTE_IF_IN_NONNULL_BITMAP (graph->succs[n], 0, i, bi)
913 : {
914 358315051 : unsigned int w;
915 :
916 716630102 : if (i > LAST_REF_NODE)
917 : break;
918 :
919 358315051 : w = find (i);
920 358315051 : if (bitmap_bit_p (si->deleted, w))
921 174164986 : continue;
922 :
923 184150065 : if (!bitmap_bit_p (si->visited, w))
924 183206675 : scc_visit (graph, si, w);
925 :
926 184150065 : unsigned int t = find (w);
927 184150065 : gcc_checking_assert (find (n) == n);
928 184150065 : if (si->dfs[t] < si->dfs[n])
929 638696 : si->dfs[n] = si->dfs[t];
930 : }
931 :
932 : /* See if any components have been identified. */
933 423569458 : if (si->dfs[n] == my_dfs)
934 : {
935 422932952 : if (si->scc_stack.length () > 0
936 422932952 : && si->dfs[si->scc_stack.last ()] >= my_dfs)
937 : {
938 191071 : bitmap scc = BITMAP_ALLOC (NULL);
939 191071 : unsigned int lowest_node;
940 191071 : bitmap_iterator bi;
941 :
942 191071 : bitmap_set_bit (scc, n);
943 :
944 191071 : while (si->scc_stack.length () != 0
945 599023 : && si->dfs[si->scc_stack.last ()] >= my_dfs)
946 : {
947 407952 : unsigned int w = si->scc_stack.pop ();
948 :
949 407952 : bitmap_set_bit (scc, w);
950 : }
951 :
952 191071 : lowest_node = bitmap_first_set_bit (scc);
953 191071 : gcc_assert (lowest_node < FIRST_REF_NODE);
954 :
955 : /* Collapse the SCC nodes into a single node, and mark the
956 : indirect cycles. */
957 790094 : EXECUTE_IF_SET_IN_BITMAP (scc, 0, i, bi)
958 : {
959 599023 : if (i < FIRST_REF_NODE)
960 : {
961 475788 : if (unite (lowest_node, i))
962 14387 : unify_nodes (graph, lowest_node, i, false);
963 : }
964 : else
965 : {
966 123235 : if (unite (lowest_node, i))
967 246470 : graph->indirect_cycles[i - FIRST_REF_NODE] = lowest_node;
968 : }
969 : }
970 191071 : bitmap_set_bit (si->deleted, lowest_node);
971 : }
972 : else
973 422741881 : bitmap_set_bit (si->deleted, n);
974 : }
975 : else
976 636506 : si->scc_stack.safe_push (n);
977 423569458 : }
978 :
979 : /* Unify node FROM into node TO, updating the changed count if
980 : necessary when UPDATE_CHANGED is true. */
981 :
982 : static void
983 43979015 : unify_nodes (constraint_graph_t graph, unsigned int to, unsigned int from,
984 : bool update_changed)
985 : {
986 43979015 : gcc_checking_assert (to != from && find (to) == to);
987 :
988 43979015 : if (dump_file && (dump_flags & TDF_DETAILS))
989 573 : fprintf (dump_file, "Unifying %s to %s\n",
990 573 : get_varinfo (from)->name,
991 573 : get_varinfo (to)->name);
992 :
993 43979015 : if (update_changed)
994 60324 : stats.unified_vars_dynamic++;
995 : else
996 43918691 : stats.unified_vars_static++;
997 :
998 43979015 : merge_graph_nodes (graph, to, from);
999 43979015 : if (merge_node_constraints (graph, to, from))
1000 : {
1001 3914 : if (update_changed)
1002 1288 : bitmap_set_bit (changed, to);
1003 : }
1004 :
1005 : /* Mark TO as changed if FROM was changed. If TO was already marked
1006 : as changed, decrease the changed count. */
1007 :
1008 43976389 : if (update_changed
1009 43976389 : && bitmap_clear_bit (changed, from))
1010 22782 : bitmap_set_bit (changed, to);
1011 43979015 : varinfo_t fromvi = get_varinfo (from);
1012 43979015 : if (fromvi->solution)
1013 : {
1014 : /* If the solution changes because of the merging, we need to mark
1015 : the variable as changed. */
1016 43979015 : varinfo_t tovi = get_varinfo (to);
1017 43979015 : if (bitmap_ior_into (tovi->solution, fromvi->solution))
1018 : {
1019 388824 : if (update_changed)
1020 9378 : bitmap_set_bit (changed, to);
1021 : }
1022 :
1023 43979015 : BITMAP_FREE (fromvi->solution);
1024 43979015 : if (fromvi->oldsolution)
1025 40236 : BITMAP_FREE (fromvi->oldsolution);
1026 :
1027 43979015 : if (stats.iterations > 0
1028 60324 : && tovi->oldsolution)
1029 4988 : BITMAP_FREE (tovi->oldsolution);
1030 : }
1031 43979015 : if (graph->succs[to])
1032 884106 : bitmap_clear_bit (graph->succs[to], to);
1033 43979015 : }
1034 :
1035 : /* Add a copy edge FROM -> TO, optimizing special cases. Returns TRUE
1036 : if the solution of TO changed. */
1037 :
1038 : static bool
1039 332839853 : solve_add_graph_edge (constraint_graph_t graph, unsigned int to,
1040 : unsigned int from)
1041 : {
1042 : /* Adding edges from the special vars is pointless.
1043 : They don't have sets that can change. */
1044 332839853 : if (get_varinfo (from)->is_special_var)
1045 63766327 : return bitmap_ior_into (get_varinfo (to)->solution,
1046 127532654 : get_varinfo (from)->solution);
1047 : /* Merging the solution from ESCAPED needlessly increases
1048 : the set. Use ESCAPED as representative instead. */
1049 269073526 : else if (from == find (escaped_id))
1050 30965548 : return bitmap_set_bit (get_varinfo (to)->solution, escaped_id);
1051 238107978 : else if (get_varinfo (from)->may_have_pointers
1052 238107978 : && add_graph_edge (graph, to, from))
1053 86148886 : return bitmap_ior_into (get_varinfo (to)->solution,
1054 86148886 : get_varinfo (from)->solution);
1055 : return false;
1056 : }
1057 :
1058 : /* Process a constraint C that represents x = *(y + off), using DELTA as the
1059 : starting solution for y. */
1060 :
1061 : static void
1062 70652694 : do_sd_constraint (constraint_graph_t graph, constraint_t c,
1063 : bitmap delta, bitmap *expanded_delta)
1064 : {
1065 70652694 : unsigned int lhs = c->lhs.var;
1066 70652694 : bool flag = false;
1067 70652694 : bitmap sol = get_varinfo (lhs)->solution;
1068 70652694 : unsigned int j;
1069 70652694 : bitmap_iterator bi;
1070 70652694 : HOST_WIDE_INT roffset = c->rhs.offset;
1071 :
1072 : /* Our IL does not allow this. */
1073 70652694 : gcc_checking_assert (c->lhs.offset == 0);
1074 :
1075 : /* If the solution of Y contains anything it is good enough to transfer
1076 : this to the LHS. */
1077 70652694 : if (bitmap_bit_p (delta, anything_id))
1078 : {
1079 562970 : flag |= bitmap_set_bit (sol, anything_id);
1080 562970 : goto done;
1081 : }
1082 :
1083 : /* If we do not know at with offset the rhs is dereferenced compute
1084 : the reachability set of DELTA, conservatively assuming it is
1085 : dereferenced at all valid offsets. */
1086 70089724 : if (roffset == UNKNOWN_OFFSET)
1087 : {
1088 51592767 : delta = solution_set_expand (delta, expanded_delta);
1089 : /* No further offset processing is necessary. */
1090 51592767 : roffset = 0;
1091 : }
1092 :
1093 : /* For each variable j in delta (Sol(y)), add
1094 : an edge in the graph from j to x, and union Sol(j) into Sol(x). */
1095 278817602 : EXECUTE_IF_SET_IN_BITMAP (delta, 0, j, bi)
1096 : {
1097 208727878 : varinfo_t v = get_varinfo (j);
1098 208727878 : HOST_WIDE_INT fieldoffset = v->offset + roffset;
1099 208727878 : unsigned HOST_WIDE_INT size = v->size;
1100 208727878 : unsigned int t;
1101 :
1102 208727878 : if (v->is_full_var)
1103 : ;
1104 111856823 : else if (roffset != 0)
1105 : {
1106 3873863 : if (fieldoffset < 0)
1107 32069 : v = get_varinfo (v->head);
1108 : else
1109 3841794 : v = first_or_preceding_vi_for_offset (v, fieldoffset);
1110 : }
1111 :
1112 : /* We have to include all fields that overlap the current field
1113 : shifted by roffset. */
1114 209464557 : do
1115 : {
1116 209464557 : t = find (v->id);
1117 :
1118 209464557 : flag |= solve_add_graph_edge (graph, lhs, t);
1119 :
1120 209464557 : if (v->is_full_var
1121 112593307 : || v->next == 0)
1122 : break;
1123 :
1124 91957988 : v = vi_next (v);
1125 : }
1126 91957988 : while (v->offset < fieldoffset + size);
1127 : }
1128 :
1129 70089724 : done:
1130 : /* If the LHS solution changed, mark the var as changed. */
1131 70652694 : if (flag)
1132 29748972 : bitmap_set_bit (changed, lhs);
1133 70652694 : }
1134 :
1135 : /* Process a constraint C that represents *(x + off) = y using DELTA
1136 : as the starting solution for x. */
1137 :
1138 : static void
1139 56340183 : do_ds_constraint (constraint_t c, bitmap delta, bitmap *expanded_delta)
1140 : {
1141 56340183 : unsigned int rhs = c->rhs.var;
1142 56340183 : bitmap sol = get_varinfo (rhs)->solution;
1143 56340183 : unsigned int j;
1144 56340183 : bitmap_iterator bi;
1145 56340183 : HOST_WIDE_INT loff = c->lhs.offset;
1146 56340183 : bool escaped_p = false;
1147 :
1148 : /* Our IL does not allow this. */
1149 56340183 : gcc_checking_assert (c->rhs.offset == 0);
1150 :
1151 : /* If the solution of y contains ANYTHING simply use the ANYTHING
1152 : solution. This avoids needlessly increasing the points-to sets. */
1153 56340183 : if (bitmap_bit_p (sol, anything_id))
1154 394748 : sol = get_varinfo (find (anything_id))->solution;
1155 :
1156 : /* If the solution for x contains ANYTHING we have to merge the
1157 : solution of y into all pointer variables which we do via
1158 : STOREDANYTHING. */
1159 56340183 : if (bitmap_bit_p (delta, anything_id))
1160 : {
1161 444922 : unsigned t = find (storedanything_id);
1162 444922 : if (solve_add_graph_edge (graph, t, rhs))
1163 35677 : bitmap_set_bit (changed, t);
1164 444922 : return;
1165 : }
1166 :
1167 : /* If we do not know at with offset the rhs is dereferenced compute
1168 : the reachability set of DELTA, conservatively assuming it is
1169 : dereferenced at all valid offsets. */
1170 55895261 : if (loff == UNKNOWN_OFFSET)
1171 : {
1172 1704437 : delta = solution_set_expand (delta, expanded_delta);
1173 1704437 : loff = 0;
1174 : }
1175 :
1176 : /* For each member j of delta (Sol(x)), add an edge from y to j and
1177 : union Sol(y) into Sol(j) */
1178 216688222 : EXECUTE_IF_SET_IN_BITMAP (delta, 0, j, bi)
1179 : {
1180 160792961 : varinfo_t v = get_varinfo (j);
1181 160792961 : unsigned int t;
1182 160792961 : HOST_WIDE_INT fieldoffset = v->offset + loff;
1183 160792961 : unsigned HOST_WIDE_INT size = v->size;
1184 :
1185 160792961 : if (v->is_full_var)
1186 : ;
1187 80951356 : else if (loff != 0)
1188 : {
1189 5256127 : if (fieldoffset < 0)
1190 6308 : v = get_varinfo (v->head);
1191 : else
1192 5249819 : v = first_or_preceding_vi_for_offset (v, fieldoffset);
1193 : }
1194 :
1195 : /* We have to include all fields that overlap the current field
1196 : shifted by loff. */
1197 162696790 : do
1198 : {
1199 162696790 : if (v->may_have_pointers)
1200 : {
1201 : /* If v is a global variable then this is an escape point. */
1202 151210250 : if (v->is_global_var
1203 116140997 : && !escaped_p)
1204 : {
1205 44506001 : t = find (escaped_id);
1206 44506001 : if (add_graph_edge (graph, t, rhs)
1207 61000886 : && bitmap_ior_into (get_varinfo (t)->solution, sol))
1208 1334575 : bitmap_set_bit (changed, t);
1209 : /* Enough to let rhs escape once. */
1210 : escaped_p = true;
1211 : }
1212 :
1213 151210250 : if (v->is_special_var)
1214 : break;
1215 :
1216 122930374 : t = find (v->id);
1217 :
1218 122930374 : if (solve_add_graph_edge (graph, t, rhs))
1219 12720194 : bitmap_set_bit (changed, t);
1220 : }
1221 :
1222 134416914 : if (v->is_full_var
1223 82855040 : || v->next == 0)
1224 : break;
1225 :
1226 67364681 : v = vi_next (v);
1227 : }
1228 67364681 : while (v->offset < fieldoffset + size);
1229 : }
1230 : }
1231 :
1232 : /* Handle a non-simple (simple meaning requires no iteration),
1233 : constraint (IE *x = &y, x = *y, *x = y, and x = y with offsets involved). */
1234 :
1235 : static void
1236 213554453 : do_complex_constraint (constraint_graph_t graph, constraint_t c, bitmap delta,
1237 : bitmap *expanded_delta)
1238 : {
1239 213554453 : if (c->lhs.type == DEREF)
1240 : {
1241 56340183 : if (c->rhs.type == ADDRESSOF)
1242 : {
1243 0 : gcc_unreachable ();
1244 : }
1245 : else
1246 : {
1247 : /* *x = y */
1248 56340183 : do_ds_constraint (c, delta, expanded_delta);
1249 : }
1250 : }
1251 157214270 : else if (c->rhs.type == DEREF)
1252 : {
1253 : /* x = *y */
1254 70652749 : if (!(get_varinfo (c->lhs.var)->is_special_var))
1255 70652694 : do_sd_constraint (graph, c, delta, expanded_delta);
1256 : }
1257 : else
1258 : {
1259 86561521 : bitmap tmp;
1260 86561521 : bool flag = false;
1261 :
1262 86561521 : gcc_checking_assert (c->rhs.type == SCALAR && c->lhs.type == SCALAR
1263 : && c->rhs.offset != 0 && c->lhs.offset == 0);
1264 86561521 : tmp = get_varinfo (c->lhs.var)->solution;
1265 :
1266 86561521 : flag = set_union_with_increment (tmp, delta, c->rhs.offset,
1267 : expanded_delta);
1268 :
1269 86561521 : if (flag)
1270 21962127 : bitmap_set_bit (changed, c->lhs.var);
1271 : }
1272 213554453 : }
1273 :
1274 : /* Initialize and return a new SCC info structure. */
1275 :
1276 9248978 : scc_info::scc_info (size_t size) :
1277 9248978 : visited (size), deleted (size), current_index (0), scc_stack (1)
1278 : {
1279 9248978 : bitmap_clear (visited);
1280 9248978 : bitmap_clear (deleted);
1281 9248978 : node_mapping = XNEWVEC (unsigned int, size);
1282 9248978 : dfs = XCNEWVEC (unsigned int, size);
1283 :
1284 951491454 : for (size_t i = 0; i < size; i++)
1285 942242476 : node_mapping[i] = i;
1286 9248978 : }
1287 :
1288 : /* Free an SCC info structure pointed to by SI. */
1289 :
1290 9248978 : scc_info::~scc_info ()
1291 : {
1292 9248978 : free (node_mapping);
1293 9248978 : free (dfs);
1294 9248978 : }
1295 :
1296 :
1297 : /* Find indirect cycles in GRAPH that occur, using strongly connected
1298 : components, and note them in the indirect cycles map.
1299 :
1300 : This technique comes from Ben Hardekopf and Calvin Lin,
1301 : "It Pays to be Lazy: Fast and Accurate Pointer Analysis for Millions of
1302 : Lines of Code", submitted to PLDI 2007. */
1303 :
1304 : static void
1305 4624489 : find_indirect_cycles (constraint_graph_t graph)
1306 : {
1307 4624489 : unsigned int i;
1308 4624489 : unsigned int size = graph->size;
1309 4624489 : scc_info si (size);
1310 :
1311 946866965 : for (i = 0; i < MIN (LAST_REF_NODE, size); i++)
1312 466496749 : if (!bitmap_bit_p (si.visited, i) && find (i) == i)
1313 240362783 : scc_visit (graph, &si, i);
1314 4624489 : }
1315 :
1316 : /* Visit the graph in topological order starting at node N, and store the
1317 : order in TOPO_ORDER using VISITED to indicate visited nodes. */
1318 :
1319 : static void
1320 466914259 : topo_visit (constraint_graph_t graph, vec<unsigned> &topo_order,
1321 : sbitmap visited, unsigned int n)
1322 : {
1323 466914259 : bitmap_iterator bi;
1324 466914259 : unsigned int j;
1325 :
1326 466914259 : bitmap_set_bit (visited, n);
1327 :
1328 466914259 : if (graph->succs[n])
1329 1133108648 : EXECUTE_IF_SET_IN_BITMAP (graph->succs[n], 0, j, bi)
1330 : {
1331 915000045 : unsigned k = find (j);
1332 915000045 : if (!bitmap_bit_p (visited, k))
1333 355045990 : topo_visit (graph, topo_order, visited, k);
1334 : }
1335 :
1336 : /* Also consider copy with offset complex constraints as implicit edges. */
1337 917792843 : for (auto c : graph->complex[n])
1338 : {
1339 : /* Constraints are ordered so that SCALAR = SCALAR appear first. */
1340 261292008 : if (c->lhs.type != SCALAR || c->rhs.type != SCALAR)
1341 : break;
1342 146403506 : gcc_checking_assert (c->rhs.var == n);
1343 146403506 : unsigned k = find (c->lhs.var);
1344 146403506 : if (!bitmap_bit_p (visited, k))
1345 38971118 : topo_visit (graph, topo_order, visited, k);
1346 : }
1347 :
1348 466914259 : topo_order.quick_push (n);
1349 466914259 : }
1350 :
1351 : /* Compute a topological ordering for GRAPH, and return the result. */
1352 :
1353 : static auto_vec<unsigned>
1354 8234835 : compute_topo_order (constraint_graph_t graph)
1355 : {
1356 8234835 : unsigned int i;
1357 8234835 : unsigned int size = graph->size;
1358 :
1359 8234835 : auto_sbitmap visited (size);
1360 8234835 : bitmap_clear (visited);
1361 :
1362 : /* For the heuristic in add_graph_edge to work optimally make sure to
1363 : first visit the connected component of the graph containing
1364 : ESCAPED. Do this by extracting the connected component
1365 : with ESCAPED and append that to all other components as solve_graph
1366 : pops from the order. */
1367 8234835 : auto_vec<unsigned> tail (size);
1368 8234835 : topo_visit (graph, tail, visited, find (escaped_id));
1369 :
1370 8234835 : auto_vec<unsigned> topo_order (size);
1371 :
1372 595260422 : for (i = 0; i != size; ++i)
1373 578790752 : if (!bitmap_bit_p (visited, i) && find (i) == i)
1374 64662316 : topo_visit (graph, topo_order, visited, i);
1375 :
1376 8234835 : topo_order.splice (tail);
1377 8234835 : return topo_order;
1378 8234835 : }
1379 :
1380 : /* Structure used to for hash value numbering of pointer equivalence
1381 : classes. */
1382 :
1383 : typedef struct equiv_class_label
1384 : {
1385 : hashval_t hashcode;
1386 : unsigned int equivalence_class;
1387 : bitmap labels;
1388 : } *equiv_class_label_t;
1389 : typedef const struct equiv_class_label *const_equiv_class_label_t;
1390 :
1391 : /* Equiv_class_label hashtable helpers. */
1392 :
1393 : struct equiv_class_hasher : nofree_ptr_hash <equiv_class_label>
1394 : {
1395 : static inline hashval_t hash (const equiv_class_label *);
1396 : static inline bool equal (const equiv_class_label *,
1397 : const equiv_class_label *);
1398 : };
1399 :
1400 : /* A hashtable for mapping a bitmap of labels->pointer equivalence
1401 : classes. */
1402 : static hash_table<equiv_class_hasher> *pointer_equiv_class_table;
1403 :
1404 : /* A hashtable for mapping a bitmap of labels->location equivalence
1405 : classes. */
1406 : static hash_table<equiv_class_hasher> *location_equiv_class_table;
1407 :
1408 : /* Hash function for a equiv_class_label_t. */
1409 :
1410 : inline hashval_t
1411 196851321 : equiv_class_hasher::hash (const equiv_class_label *ecl)
1412 : {
1413 196851321 : return ecl->hashcode;
1414 : }
1415 :
1416 : /* Equality function for two equiv_class_label_t's. */
1417 :
1418 : inline bool
1419 254548341 : equiv_class_hasher::equal (const equiv_class_label *eql1,
1420 : const equiv_class_label *eql2)
1421 : {
1422 254548341 : return (eql1->hashcode == eql2->hashcode
1423 254548341 : && bitmap_equal_p (eql1->labels, eql2->labels));
1424 : }
1425 :
1426 : struct obstack equiv_class_obstack;
1427 :
1428 : /* Lookup a equivalence class in TABLE by the bitmap of LABELS with
1429 : hash HAS it contains. Sets *REF_LABELS to the bitmap LABELS
1430 : is equivalent to. */
1431 :
1432 : static equiv_class_label *
1433 201514761 : equiv_class_lookup_or_add (hash_table<equiv_class_hasher> *table,
1434 : bitmap labels)
1435 : {
1436 201514761 : equiv_class_label **slot;
1437 201514761 : equiv_class_label ecl;
1438 :
1439 201514761 : ecl.labels = labels;
1440 201514761 : ecl.hashcode = bitmap_hash (labels);
1441 201514761 : slot = table->find_slot (&ecl, INSERT);
1442 201514761 : if (!*slot)
1443 : {
1444 168779941 : *slot = XOBNEW (&equiv_class_obstack, struct equiv_class_label);
1445 168779941 : (*slot)->labels = labels;
1446 168779941 : (*slot)->hashcode = ecl.hashcode;
1447 168779941 : (*slot)->equivalence_class = 0;
1448 : }
1449 :
1450 201514761 : return *slot;
1451 : }
1452 :
1453 :
1454 : /* Perform offline variable substitution.
1455 :
1456 : This is a worst case quadratic time way of identifying variables
1457 : that must have equivalent points-to sets, including those caused by
1458 : static cycles, and single entry subgraphs, in the constraint graph.
1459 :
1460 : The technique is described in "Exploiting Pointer and Location
1461 : Equivalence to Optimize Pointer Analysis. In the 14th International
1462 : Static Analysis Symposium (SAS), August 2007." It is known as the
1463 : "HU" algorithm, and is equivalent to value numbering the collapsed
1464 : constraint graph including evaluating unions.
1465 :
1466 : The general method of finding equivalence classes is as follows:
1467 : Add fake nodes (REF nodes) and edges for *a = b and a = *b constraints.
1468 : Initialize all non-REF nodes to be direct nodes.
1469 : For each constraint a = a U {b}, we set pts(a) = pts(a) u {fresh
1470 : variable}
1471 : For each constraint containing the dereference, we also do the same
1472 : thing.
1473 :
1474 : We then compute SCC's in the graph and unify nodes in the same SCC,
1475 : including pts sets.
1476 :
1477 : For each non-collapsed node x:
1478 : Visit all unvisited explicit incoming edges.
1479 : Ignoring all non-pointers, set pts(x) = Union of pts(a) for y
1480 : where y->x.
1481 : Lookup the equivalence class for pts(x).
1482 : If we found one, equivalence_class(x) = found class.
1483 : Otherwise, equivalence_class(x) = new class, and new_class is
1484 : added to the lookup table.
1485 :
1486 : All direct nodes with the same equivalence class can be replaced
1487 : with a single representative node.
1488 : All unlabeled nodes (label == 0) are not pointers and all edges
1489 : involving them can be eliminated.
1490 : We perform these optimizations during rewrite_constraints
1491 :
1492 : In addition to pointer equivalence class finding, we also perform
1493 : location equivalence class finding. This is the set of variables
1494 : that always appear together in points-to sets. We use this to
1495 : compress the size of the points-to sets. */
1496 :
1497 : /* Current maximum pointer equivalence class id. */
1498 : static int pointer_equiv_class;
1499 :
1500 : /* Current maximum location equivalence class id. */
1501 : static int location_equiv_class;
1502 :
1503 : /* Recursive routine to find strongly connected components in GRAPH,
1504 : and label it's nodes with DFS numbers. */
1505 :
1506 : static void
1507 275260860 : condense_visit (constraint_graph_t graph, class scc_info *si, unsigned int n)
1508 : {
1509 275260860 : unsigned int i;
1510 275260860 : bitmap_iterator bi;
1511 275260860 : unsigned int my_dfs;
1512 :
1513 275260860 : gcc_checking_assert (si->node_mapping[n] == n);
1514 275260860 : bitmap_set_bit (si->visited, n);
1515 275260860 : si->dfs[n] = si->current_index ++;
1516 275260860 : my_dfs = si->dfs[n];
1517 :
1518 : /* Visit all the successors. */
1519 505843631 : EXECUTE_IF_IN_NONNULL_BITMAP (graph->preds[n], 0, i, bi)
1520 : {
1521 230582771 : unsigned int w = si->node_mapping[i];
1522 :
1523 230582771 : if (bitmap_bit_p (si->deleted, w))
1524 146448565 : continue;
1525 :
1526 84134206 : if (!bitmap_bit_p (si->visited, w))
1527 82649972 : condense_visit (graph, si, w);
1528 :
1529 84134206 : unsigned int t = si->node_mapping[w];
1530 84134206 : gcc_checking_assert (si->node_mapping[n] == n);
1531 84134206 : if (si->dfs[t] < si->dfs[n])
1532 2636235 : si->dfs[n] = si->dfs[t];
1533 : }
1534 :
1535 : /* Visit all the implicit predecessors. */
1536 335271396 : EXECUTE_IF_IN_NONNULL_BITMAP (graph->implicit_preds[n], 0, i, bi)
1537 : {
1538 60010536 : unsigned int w = si->node_mapping[i];
1539 :
1540 60010536 : if (bitmap_bit_p (si->deleted, w))
1541 19826667 : continue;
1542 :
1543 40183869 : if (!bitmap_bit_p (si->visited, w))
1544 35200617 : condense_visit (graph, si, w);
1545 :
1546 40183869 : unsigned int t = si->node_mapping[w];
1547 40183869 : gcc_assert (si->node_mapping[n] == n);
1548 40183869 : if (si->dfs[t] < si->dfs[n])
1549 8473355 : si->dfs[n] = si->dfs[t];
1550 : }
1551 :
1552 : /* See if any components have been identified. */
1553 275260860 : if (si->dfs[n] == my_dfs)
1554 : {
1555 264322719 : if (si->scc_stack.length () != 0
1556 264322719 : && si->dfs[si->scc_stack.last ()] >= my_dfs)
1557 : {
1558 : /* Find the first node of the SCC and do non-bitmap work. */
1559 10938141 : bool direct_p = true;
1560 10938141 : unsigned first = si->scc_stack.length ();
1561 10938141 : do
1562 : {
1563 10938141 : --first;
1564 10938141 : unsigned int w = si->scc_stack[first];
1565 10938141 : si->node_mapping[w] = n;
1566 10938141 : if (!bitmap_bit_p (graph->direct_nodes, w))
1567 8831080 : direct_p = false;
1568 : }
1569 : while (first > 0
1570 12314835 : && si->dfs[si->scc_stack[first - 1]] >= my_dfs);
1571 1376694 : if (!direct_p)
1572 874398 : bitmap_clear_bit (graph->direct_nodes, n);
1573 :
1574 : /* Want to reduce to node n, push that first. */
1575 1376694 : si->scc_stack.reserve (1);
1576 1376694 : si->scc_stack.quick_push (si->scc_stack[first]);
1577 1376694 : si->scc_stack[first] = n;
1578 :
1579 1376694 : unsigned scc_size = si->scc_stack.length () - first;
1580 1376694 : unsigned split = scc_size / 2;
1581 1376694 : unsigned carry = scc_size - split * 2;
1582 4829191 : while (split > 0)
1583 : {
1584 14390638 : for (unsigned i = 0; i < split; ++i)
1585 : {
1586 10938141 : unsigned a = si->scc_stack[first + i];
1587 10938141 : unsigned b = si->scc_stack[first + split + carry + i];
1588 :
1589 : /* Unify our nodes. */
1590 10938141 : if (graph->preds[b])
1591 : {
1592 4799466 : if (!graph->preds[a])
1593 1003602 : std::swap (graph->preds[a], graph->preds[b]);
1594 : else
1595 3795864 : bitmap_ior_into_and_free (graph->preds[a],
1596 : &graph->preds[b]);
1597 : }
1598 10938141 : if (graph->implicit_preds[b])
1599 : {
1600 8729968 : if (!graph->implicit_preds[a])
1601 880040 : std::swap (graph->implicit_preds[a],
1602 : graph->implicit_preds[b]);
1603 : else
1604 7849928 : bitmap_ior_into_and_free (graph->implicit_preds[a],
1605 : &graph->implicit_preds[b]);
1606 : }
1607 10938141 : if (graph->points_to[b])
1608 : {
1609 530329 : if (!graph->points_to[a])
1610 234929 : std::swap (graph->points_to[a], graph->points_to[b]);
1611 : else
1612 295400 : bitmap_ior_into_and_free (graph->points_to[a],
1613 : &graph->points_to[b]);
1614 : }
1615 : }
1616 3452497 : unsigned remain = split + carry;
1617 3452497 : split = remain / 2;
1618 3452497 : carry = remain - split * 2;
1619 : }
1620 : /* Actually pop the SCC. */
1621 1376694 : si->scc_stack.truncate (first);
1622 : }
1623 264322719 : bitmap_set_bit (si->deleted, n);
1624 : }
1625 : else
1626 10938141 : si->scc_stack.safe_push (n);
1627 275260860 : }
1628 :
1629 : /* Label pointer equivalences.
1630 :
1631 : This performs a value numbering of the constraint graph to
1632 : discover which variables will always have the same points-to sets
1633 : under the current set of constraints.
1634 :
1635 : The way it value numbers is to store the set of points-to bits
1636 : generated by the constraints and graph edges. This is just used as a
1637 : hash and equality comparison. The *actual set of points-to bits* is
1638 : completely irrelevant, in that we don't care about being able to
1639 : extract them later.
1640 :
1641 : The equality values (currently bitmaps) just have to satisfy a few
1642 : constraints, the main ones being:
1643 : 1. The combining operation must be order independent.
1644 : 2. The end result of a given set of operations must be unique iff the
1645 : combination of input values is unique
1646 : 3. Hashable. */
1647 :
1648 : static void
1649 240533084 : label_visit (constraint_graph_t graph, class scc_info *si, unsigned int n)
1650 : {
1651 240533084 : unsigned int i, first_pred;
1652 240533084 : bitmap_iterator bi;
1653 :
1654 240533084 : bitmap_set_bit (si->visited, n);
1655 :
1656 : /* Label and union our incoming edges's points to sets. */
1657 240533084 : first_pred = -1U;
1658 465735680 : EXECUTE_IF_IN_NONNULL_BITMAP (graph->preds[n], 0, i, bi)
1659 : {
1660 225202596 : unsigned int w = si->node_mapping[i];
1661 225202596 : if (!bitmap_bit_p (si->visited, w))
1662 77920509 : label_visit (graph, si, w);
1663 :
1664 : /* Skip unused edges. */
1665 225202596 : if (w == n || graph->pointer_label[w] == 0)
1666 5252642 : continue;
1667 :
1668 219949954 : if (graph->points_to[w])
1669 : {
1670 219949954 : if (!graph->points_to[n])
1671 : {
1672 153564800 : if (first_pred == -1U)
1673 : first_pred = w;
1674 : else
1675 : {
1676 42628179 : graph->points_to[n] = BITMAP_ALLOC (&predbitmap_obstack);
1677 42628179 : bitmap_ior (graph->points_to[n],
1678 42628179 : graph->points_to[first_pred],
1679 42628179 : graph->points_to[w]);
1680 : }
1681 : }
1682 : else
1683 66385154 : bitmap_ior_into (graph->points_to[n], graph->points_to[w]);
1684 : }
1685 : }
1686 :
1687 : /* Indirect nodes get fresh variables and a new pointer equiv class. */
1688 240533084 : if (!bitmap_bit_p (graph->direct_nodes, n))
1689 : {
1690 116632725 : if (!graph->points_to[n])
1691 : {
1692 67326561 : graph->points_to[n] = BITMAP_ALLOC (&predbitmap_obstack);
1693 67326561 : if (first_pred != -1U)
1694 27253200 : bitmap_copy (graph->points_to[n], graph->points_to[first_pred]);
1695 : }
1696 233265450 : bitmap_set_bit (graph->points_to[n], FIRST_REF_NODE + n);
1697 116632725 : graph->pointer_label[n] = pointer_equiv_class++;
1698 116632725 : equiv_class_label_t ecl;
1699 233265450 : ecl = equiv_class_lookup_or_add (pointer_equiv_class_table,
1700 116632725 : graph->points_to[n]);
1701 116632725 : ecl->equivalence_class = graph->pointer_label[n];
1702 178176186 : return;
1703 : }
1704 :
1705 : /* If there was only a single non-empty predecessor the pointer equiv
1706 : class is the same. */
1707 123900359 : if (!graph->points_to[n])
1708 : {
1709 61543461 : if (first_pred != -1U)
1710 : {
1711 41055242 : graph->pointer_label[n] = graph->pointer_label[first_pred];
1712 41055242 : graph->points_to[n] = graph->points_to[first_pred];
1713 : }
1714 : return;
1715 : }
1716 :
1717 62356898 : if (!bitmap_empty_p (graph->points_to[n]))
1718 : {
1719 62356898 : equiv_class_label_t ecl;
1720 62356898 : ecl = equiv_class_lookup_or_add (pointer_equiv_class_table,
1721 : graph->points_to[n]);
1722 62356898 : if (ecl->equivalence_class == 0)
1723 30081572 : ecl->equivalence_class = pointer_equiv_class++;
1724 : else
1725 : {
1726 32275326 : BITMAP_FREE (graph->points_to[n]);
1727 32275326 : graph->points_to[n] = ecl->labels;
1728 : }
1729 62356898 : graph->pointer_label[n] = ecl->equivalence_class;
1730 : }
1731 : }
1732 :
1733 : /* Print the pred graph in dot format. */
1734 :
1735 : static void
1736 3 : dump_pred_graph (class scc_info *si, FILE *file)
1737 : {
1738 3 : unsigned int i;
1739 :
1740 : /* Only print the graph if it has already been initialized: */
1741 3 : if (!graph)
1742 : return;
1743 :
1744 : /* Prints the header of the dot file: */
1745 3 : fprintf (file, "strict digraph {\n");
1746 3 : fprintf (file, " node [\n shape = box\n ]\n");
1747 3 : fprintf (file, " edge [\n fontsize = \"12\"\n ]\n");
1748 3 : fprintf (file, "\n // List of nodes and complex constraints in "
1749 : "the constraint graph:\n");
1750 :
1751 : /* The next lines print the nodes in the graph together with the
1752 : complex constraints attached to them. */
1753 83 : for (i = 1; i < graph->size; i++)
1754 : {
1755 154 : if (i == FIRST_REF_NODE)
1756 3 : continue;
1757 74 : if (si->node_mapping[i] != i)
1758 0 : continue;
1759 74 : if (i < FIRST_REF_NODE)
1760 37 : fprintf (file, "\"%s\"", get_varinfo (i)->name);
1761 : else
1762 37 : fprintf (file, "\"*%s\"", get_varinfo (i - FIRST_REF_NODE)->name);
1763 74 : if (graph->points_to[i]
1764 74 : && !bitmap_empty_p (graph->points_to[i]))
1765 : {
1766 11 : if (i < FIRST_REF_NODE)
1767 11 : fprintf (file, "[label=\"%s = {", get_varinfo (i)->name);
1768 : else
1769 0 : fprintf (file, "[label=\"*%s = {",
1770 0 : get_varinfo (i - FIRST_REF_NODE)->name);
1771 11 : unsigned j;
1772 11 : bitmap_iterator bi;
1773 25 : EXECUTE_IF_SET_IN_BITMAP (graph->points_to[i], 0, j, bi)
1774 14 : fprintf (file, " %d", j);
1775 11 : fprintf (file, " }\"]");
1776 : }
1777 74 : fprintf (file, ";\n");
1778 : }
1779 :
1780 : /* Go over the edges. */
1781 3 : fprintf (file, "\n // Edges in the constraint graph:\n");
1782 83 : for (i = 1; i < graph->size; i++)
1783 : {
1784 77 : unsigned j;
1785 77 : bitmap_iterator bi;
1786 77 : if (si->node_mapping[i] != i)
1787 0 : continue;
1788 92 : EXECUTE_IF_IN_NONNULL_BITMAP (graph->preds[i], 0, j, bi)
1789 : {
1790 15 : unsigned from = si->node_mapping[j];
1791 15 : if (from < FIRST_REF_NODE)
1792 7 : fprintf (file, "\"%s\"", get_varinfo (from)->name);
1793 : else
1794 8 : fprintf (file, "\"*%s\"",
1795 8 : get_varinfo (from - FIRST_REF_NODE)->name);
1796 15 : fprintf (file, " -> ");
1797 15 : if (i < FIRST_REF_NODE)
1798 11 : fprintf (file, "\"%s\"", get_varinfo (i)->name);
1799 : else
1800 8 : fprintf (file, "\"*%s\"", get_varinfo (i - FIRST_REF_NODE)->name);
1801 15 : fprintf (file, ";\n");
1802 : }
1803 : }
1804 :
1805 : /* Prints the tail of the dot file. */
1806 3 : fprintf (file, "}\n");
1807 : }
1808 :
1809 : /* Perform offline variable substitution, discovering equivalence
1810 : classes, and eliminating non-pointer variables. */
1811 :
1812 : static class scc_info *
1813 4624489 : perform_var_substitution (constraint_graph_t graph)
1814 : {
1815 4624489 : unsigned int i;
1816 4624489 : unsigned int size = graph->size;
1817 4624489 : scc_info *si = new scc_info (size);
1818 :
1819 4624489 : bitmap_obstack_initialize (&iteration_obstack);
1820 4624489 : gcc_obstack_init (&equiv_class_obstack);
1821 4624489 : pointer_equiv_class_table = new hash_table<equiv_class_hasher> (511);
1822 4624489 : location_equiv_class_table
1823 4624489 : = new hash_table<equiv_class_hasher> (511);
1824 4624489 : pointer_equiv_class = 1;
1825 4624489 : location_equiv_class = 1;
1826 :
1827 : /* Condense the nodes, which means to find SCC's, count incoming
1828 : predecessors, and unite nodes in SCC's. */
1829 235560619 : for (i = 1; i < FIRST_REF_NODE; i++)
1830 230936130 : if (!bitmap_bit_p (si->visited, si->node_mapping[i]))
1831 157410271 : condense_visit (graph, si, si->node_mapping[i]);
1832 :
1833 4624489 : if (dump_file && (dump_flags & TDF_GRAPH))
1834 : {
1835 3 : fprintf (dump_file, "\n\n// The constraint graph before var-substitution "
1836 : "in dot format:\n");
1837 3 : dump_pred_graph (si, dump_file);
1838 3 : fprintf (dump_file, "\n\n");
1839 : }
1840 :
1841 4624489 : bitmap_clear (si->visited);
1842 : /* Actually the label the nodes for pointer equivalences. */
1843 475745727 : for (i = 1; i < FIRST_REF_NODE; i++)
1844 230936130 : if (!bitmap_bit_p (si->visited, si->node_mapping[i]))
1845 162612575 : label_visit (graph, si, si->node_mapping[i]);
1846 :
1847 : /* Calculate location equivalence labels. */
1848 235560619 : for (i = 1; i < FIRST_REF_NODE; i++)
1849 : {
1850 230936130 : bitmap pointed_by;
1851 230936130 : bitmap_iterator bi;
1852 230936130 : unsigned int j;
1853 :
1854 230936130 : if (!graph->pointed_by[i])
1855 208410992 : continue;
1856 22525138 : pointed_by = BITMAP_ALLOC (&iteration_obstack);
1857 :
1858 : /* Translate the pointed-by mapping for pointer equivalence
1859 : labels. */
1860 101146300 : EXECUTE_IF_SET_IN_BITMAP (graph->pointed_by[i], 0, j, bi)
1861 : {
1862 78621162 : bitmap_set_bit (pointed_by,
1863 78621162 : graph->pointer_label[si->node_mapping[j]]);
1864 : }
1865 : /* The original pointed_by is now dead. */
1866 22525138 : BITMAP_FREE (graph->pointed_by[i]);
1867 :
1868 : /* Look up the location equivalence label if one exists, or make
1869 : one otherwise. */
1870 22525138 : equiv_class_label_t ecl;
1871 22525138 : ecl = equiv_class_lookup_or_add (location_equiv_class_table, pointed_by);
1872 22525138 : if (ecl->equivalence_class == 0)
1873 22065644 : ecl->equivalence_class = location_equiv_class++;
1874 : else
1875 : {
1876 459494 : if (dump_file && (dump_flags & TDF_DETAILS))
1877 55 : fprintf (dump_file, "Found location equivalence for node %s\n",
1878 55 : get_varinfo (i)->name);
1879 459494 : BITMAP_FREE (pointed_by);
1880 : }
1881 22525138 : graph->loc_label[i] = ecl->equivalence_class;
1882 :
1883 : }
1884 :
1885 4624489 : if (dump_file && (dump_flags & TDF_DETAILS))
1886 6830 : for (i = 1; i < FIRST_REF_NODE; i++)
1887 : {
1888 6529 : unsigned j = si->node_mapping[i];
1889 6529 : if (j != i)
1890 : {
1891 21 : fprintf (dump_file, "%s node id %d ",
1892 21 : bitmap_bit_p (graph->direct_nodes, i)
1893 : ? "Direct" : "Indirect", i);
1894 21 : if (i < FIRST_REF_NODE)
1895 21 : fprintf (dump_file, "\"%s\"", get_varinfo (i)->name);
1896 : else
1897 0 : fprintf (dump_file, "\"*%s\"",
1898 0 : get_varinfo (i - FIRST_REF_NODE)->name);
1899 21 : fprintf (dump_file, " mapped to SCC leader node id %d ", j);
1900 21 : if (j < FIRST_REF_NODE)
1901 21 : fprintf (dump_file, "\"%s\"\n", get_varinfo (j)->name);
1902 : else
1903 0 : fprintf (dump_file, "\"*%s\"\n",
1904 0 : get_varinfo (j - FIRST_REF_NODE)->name);
1905 : }
1906 : else
1907 : {
1908 10023 : fprintf (dump_file,
1909 : "Equivalence classes for %s node id %d ",
1910 6508 : bitmap_bit_p (graph->direct_nodes, i)
1911 : ? "direct" : "indirect", i);
1912 6508 : if (i < FIRST_REF_NODE)
1913 6508 : fprintf (dump_file, "\"%s\"", get_varinfo (i)->name);
1914 : else
1915 0 : fprintf (dump_file, "\"*%s\"",
1916 0 : get_varinfo (i - FIRST_REF_NODE)->name);
1917 6508 : fprintf (dump_file,
1918 : ": pointer %d, location %d\n",
1919 6508 : graph->pointer_label[i], graph->loc_label[i]);
1920 : }
1921 : }
1922 :
1923 : /* Quickly eliminate our non-pointer variables. */
1924 :
1925 235560619 : for (i = 1; i < FIRST_REF_NODE; i++)
1926 : {
1927 230936130 : unsigned int node = si->node_mapping[i];
1928 :
1929 230936130 : if (graph->pointer_label[node] == 0)
1930 : {
1931 20489703 : if (dump_file && (dump_flags & TDF_DETAILS))
1932 926 : fprintf (dump_file,
1933 : "%s is a non-pointer variable, eliminating edges.\n",
1934 926 : get_varinfo (node)->name);
1935 20489703 : stats.nonpointer_vars++;
1936 20489703 : clear_edges_for_node (graph, node);
1937 : }
1938 : }
1939 :
1940 4624489 : return si;
1941 : }
1942 :
1943 : /* Free information that was only necessary for variable
1944 : substitution. */
1945 :
1946 : static void
1947 4624489 : free_var_substitution_info (class scc_info *si)
1948 : {
1949 4624489 : delete si;
1950 4624489 : free (graph->pointer_label);
1951 4624489 : free (graph->loc_label);
1952 4624489 : free (graph->pointed_by);
1953 4624489 : free (graph->points_to);
1954 4624489 : free (graph->eq_rep);
1955 4624489 : sbitmap_free (graph->direct_nodes);
1956 4624489 : delete pointer_equiv_class_table;
1957 4624489 : pointer_equiv_class_table = NULL;
1958 4624489 : delete location_equiv_class_table;
1959 4624489 : location_equiv_class_table = NULL;
1960 4624489 : obstack_free (&equiv_class_obstack, NULL);
1961 4624489 : bitmap_obstack_release (&iteration_obstack);
1962 4624489 : }
1963 :
1964 : /* Return an existing node that is equivalent to NODE, which has
1965 : equivalence class LABEL, if one exists. Return NODE otherwise. */
1966 :
1967 : static unsigned int
1968 906464058 : find_equivalent_node (constraint_graph_t graph,
1969 : unsigned int node, unsigned int label)
1970 : {
1971 : /* If the address version of this variable is unused, we can
1972 : substitute it for anything else with the same label.
1973 : Otherwise, we know the pointers are equivalent, but not the
1974 : locations, and we can unite them later. */
1975 :
1976 906464058 : if (!bitmap_bit_p (graph->address_taken, node))
1977 : {
1978 705325014 : gcc_checking_assert (label < graph->size);
1979 :
1980 705325014 : if (graph->eq_rep[label] != -1)
1981 : {
1982 : /* Unify the two variables since we know they are equivalent. */
1983 596911156 : if (unite (graph->eq_rep[label], node))
1984 : {
1985 43094901 : unify_nodes (graph, graph->eq_rep[label], node, false);
1986 43094901 : return graph->eq_rep[label];
1987 : }
1988 : }
1989 : else
1990 : {
1991 108413858 : graph->eq_rep[label] = node;
1992 108413858 : graph->pe_rep[label] = node;
1993 : }
1994 : }
1995 : else
1996 : {
1997 201139044 : gcc_checking_assert (label < graph->size);
1998 201139044 : graph->pe[node] = label;
1999 201139044 : if (graph->pe_rep[label] == -1)
2000 22434718 : graph->pe_rep[label] = node;
2001 : }
2002 :
2003 : return node;
2004 : }
2005 :
2006 : /* Unite pointer equivalent but not location equivalent nodes in
2007 : GRAPH. This may only be performed once variable substitution is
2008 : finished. */
2009 :
2010 : static void
2011 4624489 : unite_pointer_equivalences (constraint_graph_t graph)
2012 : {
2013 4624489 : unsigned int i;
2014 :
2015 : /* Go through the pointer equivalences and unite them to their
2016 : representative, if they aren't already. */
2017 235560619 : for (i = 1; i < FIRST_REF_NODE; i++)
2018 : {
2019 230936130 : unsigned int label = graph->pe[i];
2020 230936130 : if (label)
2021 : {
2022 22525138 : int label_rep = graph->pe_rep[label];
2023 :
2024 22525138 : if (label_rep == -1)
2025 0 : continue;
2026 :
2027 22525138 : label_rep = find (label_rep);
2028 22525138 : if (label_rep >= 0 && unite (label_rep, find (i)))
2029 809403 : unify_nodes (graph, label_rep, i, false);
2030 : }
2031 : }
2032 4624489 : }
2033 :
2034 : /* Move complex constraints to the GRAPH nodes they belong to. */
2035 :
2036 : static void
2037 4624489 : move_complex_constraints (constraint_graph_t graph)
2038 : {
2039 4624489 : int i;
2040 4624489 : constraint_t c;
2041 :
2042 460410906 : FOR_EACH_VEC_ELT (constraints, i, c)
2043 : {
2044 455786417 : if (c)
2045 : {
2046 453232029 : struct constraint_expr lhs = c->lhs;
2047 453232029 : struct constraint_expr rhs = c->rhs;
2048 :
2049 453232029 : if (lhs.type == DEREF)
2050 : {
2051 37462554 : insert_into_complex (graph, lhs.var, c);
2052 : }
2053 415769475 : else if (rhs.type == DEREF)
2054 : {
2055 50709803 : if (!(get_varinfo (lhs.var)->is_special_var))
2056 50709800 : insert_into_complex (graph, rhs.var, c);
2057 : }
2058 365059672 : else if (rhs.type != ADDRESSOF && lhs.var > anything_id
2059 271459978 : && (lhs.offset != 0 || rhs.offset != 0))
2060 : {
2061 62653489 : insert_into_complex (graph, rhs.var, c);
2062 : }
2063 : }
2064 : }
2065 4624489 : }
2066 :
2067 : /* Optimize and rewrite complex constraints while performing
2068 : collapsing of equivalent nodes. SI is the SCC_INFO that is the
2069 : result of perform_variable_substitution. */
2070 :
2071 : static void
2072 4624489 : rewrite_constraints (constraint_graph_t graph,
2073 : class scc_info *si)
2074 : {
2075 4624489 : int i;
2076 4624489 : constraint_t c;
2077 :
2078 4624489 : if (flag_checking)
2079 : {
2080 475742579 : for (unsigned int j = 0; j < graph->size; j++)
2081 471118150 : gcc_assert (find (j) == j);
2082 : }
2083 :
2084 460410906 : FOR_EACH_VEC_ELT (constraints, i, c)
2085 : {
2086 455786417 : struct constraint_expr lhs = c->lhs;
2087 455786417 : struct constraint_expr rhs = c->rhs;
2088 455786417 : unsigned int lhsvar = find (lhs.var);
2089 455786417 : unsigned int rhsvar = find (rhs.var);
2090 455786417 : unsigned int lhsnode, rhsnode;
2091 455786417 : unsigned int lhslabel, rhslabel;
2092 :
2093 455786417 : lhsnode = si->node_mapping[lhsvar];
2094 455786417 : rhsnode = si->node_mapping[rhsvar];
2095 455786417 : lhslabel = graph->pointer_label[lhsnode];
2096 455786417 : rhslabel = graph->pointer_label[rhsnode];
2097 :
2098 : /* See if it is really a non-pointer variable, and if so, ignore
2099 : the constraint. */
2100 455786417 : if (lhslabel == 0)
2101 : {
2102 804511 : if (dump_file && (dump_flags & TDF_DETAILS))
2103 : {
2104 :
2105 44 : fprintf (dump_file, "%s is a non-pointer variable, "
2106 : "ignoring constraint:",
2107 22 : get_varinfo (lhs.var)->name);
2108 22 : dump_constraint (dump_file, c);
2109 22 : fprintf (dump_file, "\n");
2110 : }
2111 804511 : constraints[i] = NULL;
2112 455786417 : continue;
2113 : }
2114 :
2115 454981906 : if (rhslabel == 0)
2116 : {
2117 1749877 : if (dump_file && (dump_flags & TDF_DETAILS))
2118 : {
2119 :
2120 90 : fprintf (dump_file, "%s is a non-pointer variable, "
2121 : "ignoring constraint:",
2122 45 : get_varinfo (rhs.var)->name);
2123 45 : dump_constraint (dump_file, c);
2124 45 : fprintf (dump_file, "\n");
2125 : }
2126 1749877 : constraints[i] = NULL;
2127 1749877 : continue;
2128 : }
2129 :
2130 453232029 : lhsvar = find_equivalent_node (graph, lhsvar, lhslabel);
2131 453232029 : rhsvar = find_equivalent_node (graph, rhsvar, rhslabel);
2132 453232029 : c->lhs.var = lhsvar;
2133 453232029 : c->rhs.var = rhsvar;
2134 : }
2135 4624489 : }
2136 :
2137 : /* Eliminate indirect cycles involving NODE. Return true if NODE was
2138 : part of an SCC, false otherwise. */
2139 :
2140 : static bool
2141 466894007 : eliminate_indirect_cycles (unsigned int node)
2142 : {
2143 466894007 : if (graph->indirect_cycles[node] != -1
2144 467233478 : && !bitmap_empty_p (get_varinfo (node)->solution))
2145 : {
2146 305302 : unsigned int i;
2147 305302 : auto_vec<unsigned> queue;
2148 305302 : int queuepos;
2149 305302 : unsigned int to = find (graph->indirect_cycles[node]);
2150 305302 : bitmap_iterator bi;
2151 :
2152 : /* We can't touch the solution set and call unify_nodes
2153 : at the same time, because unify_nodes is going to do
2154 : bitmap unions into it. */
2155 :
2156 1151327 : EXECUTE_IF_SET_IN_BITMAP (get_varinfo (node)->solution, 0, i, bi)
2157 : {
2158 846025 : if (find (i) == i && i != to)
2159 : {
2160 527301 : if (unite (to, i))
2161 60324 : queue.safe_push (i);
2162 : }
2163 : }
2164 :
2165 60324 : for (queuepos = 0;
2166 380473 : queue.iterate (queuepos, &i);
2167 : queuepos++)
2168 : {
2169 60324 : unify_nodes (graph, to, i, true);
2170 : }
2171 305302 : return true;
2172 305302 : }
2173 : return false;
2174 : }
2175 :
2176 : /* Solve the constraint graph GRAPH using our worklist solver.
2177 : This is based on the PW* family of solvers from the "Efficient Field
2178 : Sensitive Pointer Analysis for C" paper.
2179 : It works by iterating over all the graph nodes, processing the complex
2180 : constraints and propagating the copy constraints, until everything stops
2181 : changed. This corresponds to steps 6-8 in the solving list given above. */
2182 :
2183 : static void
2184 4624489 : solve_graph (constraint_graph_t graph)
2185 : {
2186 4624489 : unsigned int size = graph->size;
2187 4624489 : unsigned int i;
2188 4624489 : bitmap pts;
2189 :
2190 4624489 : changed = BITMAP_ALLOC (NULL);
2191 :
2192 : /* Mark all initial non-collapsed nodes as changed. */
2193 235560619 : for (i = 1; i < size; i++)
2194 : {
2195 230936130 : varinfo_t ivi = get_varinfo (i);
2196 417953569 : if (find (i) == i && !bitmap_empty_p (ivi->solution)
2197 289420856 : && ((graph->succs[i] && !bitmap_empty_p (graph->succs[i]))
2198 238871414 : || graph->complex[i].length () > 0))
2199 37310156 : bitmap_set_bit (changed, i);
2200 : }
2201 :
2202 : /* Allocate a bitmap to be used to store the changed bits. */
2203 4624489 : pts = BITMAP_ALLOC (&pta_obstack);
2204 :
2205 17483813 : while (!bitmap_empty_p (changed))
2206 : {
2207 8234835 : unsigned int i;
2208 8234835 : stats.iterations++;
2209 :
2210 8234835 : bitmap_obstack_initialize (&iteration_obstack);
2211 :
2212 8234835 : auto_vec<unsigned> topo_order = compute_topo_order (graph);
2213 483383929 : while (topo_order.length () != 0)
2214 : {
2215 466914259 : i = topo_order.pop ();
2216 :
2217 : /* If this variable is not a representative, skip it. */
2218 466914259 : if (find (i) != i)
2219 20252 : continue;
2220 :
2221 : /* In certain indirect cycle cases, we may merge this
2222 : variable to another. */
2223 466894007 : if (eliminate_indirect_cycles (i) && find (i) != i)
2224 93 : continue;
2225 :
2226 : /* If the node has changed, we need to process the
2227 : complex constraints and outgoing edges again. For complex
2228 : constraints that modify i itself, like the common group of
2229 : callarg = callarg + UNKNOWN;
2230 : callarg = *callarg + UNKNOWN;
2231 : *callarg = callescape;
2232 : make sure to iterate immediately because that maximizes
2233 : cache reuse and expands the graph quickest, leading to
2234 : better visitation order in the next iteration. */
2235 641117864 : while (bitmap_clear_bit (changed, i))
2236 : {
2237 174480287 : bitmap solution;
2238 174480287 : vec<constraint_t> &complex = graph->complex[i];
2239 174480287 : varinfo_t vi = get_varinfo (i);
2240 174480287 : bool solution_empty;
2241 :
2242 : /* Compute the changed set of solution bits. If anything
2243 : is in the solution just propagate that. */
2244 174480287 : if (bitmap_bit_p (vi->solution, anything_id))
2245 : {
2246 : /* If anything is also in the old solution there is
2247 : nothing to do.
2248 : ??? But we shouldn't ended up with "changed" set ... */
2249 2712618 : if (vi->oldsolution
2250 2712618 : && bitmap_bit_p (vi->oldsolution, anything_id))
2251 : break;
2252 2456281 : bitmap_copy (pts, get_varinfo (find (anything_id))->solution);
2253 : }
2254 171767669 : else if (vi->oldsolution)
2255 36354925 : bitmap_and_compl (pts, vi->solution, vi->oldsolution);
2256 : else
2257 135412744 : bitmap_copy (pts, vi->solution);
2258 :
2259 174223950 : if (bitmap_empty_p (pts))
2260 : break;
2261 :
2262 174223950 : if (vi->oldsolution)
2263 37573596 : bitmap_ior_into (vi->oldsolution, pts);
2264 : else
2265 : {
2266 136650354 : vi->oldsolution = BITMAP_ALLOC (&oldpta_obstack);
2267 136650354 : bitmap_copy (vi->oldsolution, pts);
2268 : }
2269 :
2270 174223950 : solution = vi->solution;
2271 174223950 : solution_empty = bitmap_empty_p (solution);
2272 :
2273 : /* Process the complex constraints. */
2274 174223950 : hash_set<constraint_t> *cvisited = nullptr;
2275 174223950 : if (flag_checking)
2276 174223101 : cvisited = new hash_set<constraint_t>;
2277 174223950 : bitmap expanded_pts = NULL;
2278 387819642 : for (unsigned j = 0; j < complex.length (); ++j)
2279 : {
2280 213595692 : constraint_t c = complex[j];
2281 : /* At unification time only the directly involved nodes
2282 : will get their complex constraints updated. Update
2283 : our complex constraints now but keep the constraint
2284 : vector sorted and clear of duplicates. Also make
2285 : sure to evaluate each prevailing constraint only once. */
2286 213595692 : unsigned int new_lhs = find (c->lhs.var);
2287 213595692 : unsigned int new_rhs = find (c->rhs.var);
2288 213595692 : if (c->lhs.var != new_lhs || c->rhs.var != new_rhs)
2289 : {
2290 94701 : constraint tem = *c;
2291 94701 : tem.lhs.var = new_lhs;
2292 94701 : tem.rhs.var = new_rhs;
2293 94701 : unsigned int place
2294 94701 : = complex.lower_bound (&tem, constraint_less);
2295 94701 : c->lhs.var = new_lhs;
2296 94701 : c->rhs.var = new_rhs;
2297 94701 : if (place != j)
2298 : {
2299 85659 : complex.ordered_remove (j);
2300 85659 : if (j < place)
2301 72989 : --place;
2302 85659 : if (place < complex.length ())
2303 : {
2304 31039 : if (constraint_equal (*complex[place], *c))
2305 : {
2306 12489 : j--;
2307 41239 : continue;
2308 : }
2309 : else
2310 18550 : complex.safe_insert (place, c);
2311 : }
2312 : else
2313 54620 : complex.quick_push (c);
2314 73170 : if (place > j)
2315 : {
2316 28750 : j--;
2317 28750 : continue;
2318 : }
2319 : }
2320 : }
2321 :
2322 : /* The only complex constraint that can change our
2323 : solution to non-empty, given an empty solution,
2324 : is a constraint where the lhs side is receiving
2325 : some set from elsewhere. */
2326 213554453 : if (cvisited && cvisited->add (c))
2327 0 : gcc_unreachable ();
2328 213554453 : if (!solution_empty || c->lhs.type != DEREF)
2329 213554453 : do_complex_constraint (graph, c, pts, &expanded_pts);
2330 : }
2331 174223950 : if (cvisited)
2332 : {
2333 : /* When checking, verify the order of constraints is
2334 : maintained and each constraint is evaluated exactly
2335 : once. */
2336 304907923 : for (unsigned j = 1; j < complex.length (); ++j)
2337 130684822 : gcc_assert (constraint_less (complex[j-1], complex[j]));
2338 257091672 : gcc_assert (cvisited->elements () == complex.length ());
2339 174223101 : delete cvisited;
2340 : }
2341 174223950 : BITMAP_FREE (expanded_pts);
2342 :
2343 174223950 : solution_empty = bitmap_empty_p (solution);
2344 :
2345 174223950 : if (!solution_empty)
2346 : {
2347 174223950 : bitmap_iterator bi;
2348 174223950 : unsigned eff_escaped_id = find (escaped_id);
2349 174223950 : unsigned j;
2350 :
2351 : /* Propagate solution to all successors. */
2352 174223950 : unsigned to_remove = ~0U;
2353 459466395 : EXECUTE_IF_IN_NONNULL_BITMAP (graph->succs[i],
2354 : 0, j, bi)
2355 : {
2356 285242445 : if (to_remove != ~0U)
2357 : {
2358 780776 : bitmap_clear_bit (graph->succs[i], to_remove);
2359 780776 : to_remove = ~0U;
2360 : }
2361 285242445 : unsigned int to = find (j);
2362 285242445 : if (to != j)
2363 : {
2364 : /* Update the succ graph, avoiding duplicate
2365 : work. */
2366 842384 : to_remove = j;
2367 842384 : if (! bitmap_set_bit (graph->succs[i], to))
2368 126999 : continue;
2369 : /* We eventually end up processing 'to' twice
2370 : as it is undefined whether bitmap iteration
2371 : iterates over bits set during iteration.
2372 : Play safe instead of doing tricks. */
2373 : }
2374 : /* Don't try to propagate to ourselves. */
2375 285115446 : if (to == i)
2376 : {
2377 118347 : to_remove = j;
2378 118347 : continue;
2379 : }
2380 : /* Early node unification can lead to edges from
2381 : escaped - remove them. */
2382 284997099 : if (i == eff_escaped_id)
2383 : {
2384 20122 : to_remove = j;
2385 20122 : if (bitmap_set_bit (get_varinfo (to)->solution,
2386 : escaped_id))
2387 19340 : bitmap_set_bit (changed, to);
2388 20122 : continue;
2389 : }
2390 :
2391 284976977 : if (bitmap_ior_into (get_varinfo (to)->solution, pts))
2392 142065947 : bitmap_set_bit (changed, to);
2393 : }
2394 108086037 : if (to_remove != ~0U)
2395 133861 : bitmap_clear_bit (graph->succs[i], to_remove);
2396 : }
2397 : }
2398 : }
2399 8234835 : bitmap_obstack_release (&iteration_obstack);
2400 8234835 : }
2401 :
2402 4624489 : BITMAP_FREE (pts);
2403 4624489 : BITMAP_FREE (changed);
2404 4624489 : bitmap_obstack_release (&oldpta_obstack);
2405 4624489 : }
2406 :
2407 : void
2408 4624489 : delete_graph (void)
2409 : {
2410 4624489 : unsigned int i;
2411 240185108 : for (i = 0; i < graph->size; i++)
2412 235560619 : graph->complex[i].release ();
2413 4624489 : free (graph->complex);
2414 :
2415 4624489 : free (graph->succs);
2416 4624489 : free (graph->pe);
2417 4624489 : free (graph->pe_rep);
2418 4624489 : free (graph->indirect_cycles);
2419 : /* We are not doing free (graph->rep) since the representatives mapping is
2420 : needed outside of the solver too. */
2421 4624489 : free (graph);
2422 4624489 : }
2423 :
2424 : /* Remove the REF and ADDRESS edges from GRAPH, as well as all the
2425 : predecessor edges. */
2426 :
2427 : static void
2428 4624489 : remove_preds_and_fake_succs (constraint_graph_t graph)
2429 : {
2430 4624489 : unsigned int i;
2431 :
2432 : /* Clear the implicit ref and address nodes from the successor
2433 : lists. */
2434 235560619 : for (i = 1; i < FIRST_REF_NODE; i++)
2435 : {
2436 230936130 : if (graph->succs[i])
2437 75183016 : bitmap_clear_range (graph->succs[i], FIRST_REF_NODE,
2438 75183016 : FIRST_REF_NODE * 2);
2439 : }
2440 :
2441 : /* Free the successor list for the non-ref nodes. */
2442 240185108 : for (i = FIRST_REF_NODE + 1; i < graph->size; i++)
2443 : {
2444 230936130 : if (graph->succs[i])
2445 12307552 : BITMAP_FREE (graph->succs[i]);
2446 : }
2447 :
2448 : /* Now reallocate the size of the successor list as, and blow away
2449 : the predecessor bitmaps. */
2450 4624489 : graph->size = varmap.length ();
2451 4624489 : graph->succs = XRESIZEVEC (bitmap, graph->succs, graph->size);
2452 :
2453 4624489 : free (graph->implicit_preds);
2454 4624489 : graph->implicit_preds = NULL;
2455 4624489 : free (graph->preds);
2456 4624489 : graph->preds = NULL;
2457 4624489 : bitmap_obstack_release (&predbitmap_obstack);
2458 4624489 : }
2459 :
2460 : namespace pointer_analysis {
2461 :
2462 : /* Solve the constraint set. The entry function of the solver. */
2463 :
2464 : void
2465 4624489 : solve_constraints (void)
2466 : {
2467 4624489 : class scc_info *si;
2468 :
2469 : /* Sort varinfos so that ones that cannot be pointed to are last.
2470 : This makes bitmaps more efficient. */
2471 4624489 : unsigned int *map = XNEWVEC (unsigned int, varmap.length ());
2472 50869379 : for (unsigned i = 0; i < integer_id + 1; ++i)
2473 41620401 : map[i] = i;
2474 : /* Start with address-taken vars, followed by not address-taken vars
2475 : to move vars never appearing in the points-to solution bitmaps last. */
2476 : unsigned j = integer_id + 1;
2477 397129414 : for (unsigned i = integer_id + 1; i < varmap.length (); ++i)
2478 193940218 : if (varmap[varmap[i]->head]->address_taken)
2479 15915438 : map[i] = j++;
2480 198564707 : for (unsigned i = integer_id + 1; i < varmap.length (); ++i)
2481 193940218 : if (! varmap[varmap[i]->head]->address_taken)
2482 178024780 : map[i] = j++;
2483 : /* Shuffle varmap according to map. */
2484 198564707 : for (unsigned i = integer_id + 1; i < varmap.length (); ++i)
2485 : {
2486 288883118 : while (map[varmap[i]->id] != i)
2487 94942900 : std::swap (varmap[i], varmap[map[varmap[i]->id]]);
2488 193940218 : gcc_assert (bitmap_empty_p (varmap[i]->solution));
2489 193940218 : varmap[i]->id = i;
2490 193940218 : varmap[i]->next = map[varmap[i]->next];
2491 193940218 : varmap[i]->head = map[varmap[i]->head];
2492 : }
2493 : /* Finally rewrite constraints. */
2494 460410906 : for (unsigned i = 0; i < constraints.length (); ++i)
2495 : {
2496 455786417 : constraints[i]->lhs.var = map[constraints[i]->lhs.var];
2497 455786417 : constraints[i]->rhs.var = map[constraints[i]->rhs.var];
2498 : }
2499 4624489 : free (map);
2500 :
2501 4624489 : if (dump_file)
2502 489 : fprintf (dump_file,
2503 : "\nCollapsing static cycles and doing variable "
2504 : "substitution\n");
2505 :
2506 9248978 : init_graph (varmap.length () * 2);
2507 :
2508 4624489 : if (dump_file)
2509 489 : fprintf (dump_file, "Building predecessor graph\n");
2510 4624489 : build_pred_graph ();
2511 :
2512 4624489 : if (dump_file)
2513 489 : fprintf (dump_file, "Detecting pointer and location "
2514 : "equivalences\n");
2515 4624489 : si = perform_var_substitution (graph);
2516 :
2517 4624489 : if (dump_file)
2518 489 : fprintf (dump_file, "Rewriting constraints and unifying "
2519 : "variables\n");
2520 4624489 : rewrite_constraints (graph, si);
2521 :
2522 4624489 : build_succ_graph ();
2523 :
2524 4624489 : free_var_substitution_info (si);
2525 :
2526 : /* Attach complex constraints to graph nodes. */
2527 4624489 : move_complex_constraints (graph);
2528 :
2529 4624489 : if (dump_file)
2530 489 : fprintf (dump_file, "Uniting pointer but not location equivalent "
2531 : "variables\n");
2532 4624489 : unite_pointer_equivalences (graph);
2533 :
2534 4624489 : if (dump_file)
2535 489 : fprintf (dump_file, "Finding indirect cycles\n");
2536 4624489 : find_indirect_cycles (graph);
2537 :
2538 : /* Implicit nodes and predecessors are no longer necessary at this
2539 : point. */
2540 4624489 : remove_preds_and_fake_succs (graph);
2541 :
2542 4624489 : if (dump_file && (dump_flags & TDF_GRAPH))
2543 : {
2544 3 : fprintf (dump_file, "\n\n// The constraint graph before solve-graph "
2545 : "in dot format:\n");
2546 3 : dump_constraint_graph (dump_file);
2547 3 : fprintf (dump_file, "\n\n");
2548 : }
2549 :
2550 4624489 : if (dump_file)
2551 489 : fprintf (dump_file, "Solving graph\n");
2552 :
2553 4624489 : solve_graph (graph);
2554 :
2555 4624489 : if (dump_file && (dump_flags & TDF_GRAPH))
2556 : {
2557 3 : fprintf (dump_file, "\n\n// The constraint graph after solve-graph "
2558 : "in dot format:\n");
2559 3 : dump_constraint_graph (dump_file);
2560 3 : fprintf (dump_file, "\n\n");
2561 : }
2562 :
2563 : /* The mapping node -> representative is one of the outputs of the
2564 : solver. */
2565 4624489 : union_find_compress_all ();
2566 4624489 : var_rep = graph->rep;
2567 :
2568 4624489 : delete_graph ();
2569 4624489 : }
2570 :
2571 : } // namespace pointer_analysis
|