Branch data Line data Source code
1 : : /* Andersen-style solver for tree based points-to analysis
2 : : Copyright (C) 2005-2025 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 : 9439653215 : find (unsigned int node)
136 : : {
137 : 9439653215 : gcc_checking_assert (node < graph->size);
138 : 9439653215 : if (graph->rep[node] != node)
139 : 1071167786 : 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 : 603935130 : unite (unsigned int to, unsigned int from)
150 : : {
151 : 603935130 : gcc_checking_assert (to < graph->size && from < graph->size);
152 : 603935130 : if (to != from && graph->rep[from] != to)
153 : : {
154 : 71031078 : graph->rep[from] = to;
155 : 71031078 : return true;
156 : : }
157 : : return false;
158 : : }
159 : :
160 : : /* Perform path compression for all nodes in the node representatives
161 : : union-find structure. */
162 : :
163 : : static void
164 : 4518845 : union_find_compress_all (void)
165 : : {
166 : 4518845 : unsigned int i;
167 : 233241293 : for (i = 0; i < graph->size; i++)
168 : 228722448 : find (i);
169 : 4518845 : }
170 : :
171 : : /* Print the constraint graph in dot format. */
172 : :
173 : : static void
174 : 6 : dump_constraint_graph (FILE *file)
175 : : {
176 : 6 : unsigned int i;
177 : :
178 : : /* Only print the graph if it has already been initialized: */
179 : 6 : if (!graph)
180 : : return;
181 : :
182 : : /* Prints the header of the dot file: */
183 : 6 : fprintf (file, "strict digraph {\n");
184 : 6 : fprintf (file, " node [\n shape = box\n ]\n");
185 : 6 : fprintf (file, " edge [\n fontsize = \"12\"\n ]\n");
186 : 6 : fprintf (file, "\n // List of nodes and complex constraints in "
187 : : "the constraint graph:\n");
188 : :
189 : : /* The next lines print the nodes in the graph together with the
190 : : complex constraints attached to them. */
191 : 80 : for (i = 1; i < graph->size; i++)
192 : : {
193 : 148 : if (i == FIRST_REF_NODE)
194 : 0 : continue;
195 : 74 : if (find (i) != i)
196 : 2 : continue;
197 : 72 : if (i < FIRST_REF_NODE)
198 : 72 : fprintf (file, "\"%s\"", get_varinfo (i)->name);
199 : : else
200 : 0 : fprintf (file, "\"*%s\"", get_varinfo (i - FIRST_REF_NODE)->name);
201 : 72 : if (graph->complex[i].exists ())
202 : : {
203 : 16 : unsigned j;
204 : 16 : constraint_t c;
205 : 16 : fprintf (file, " [label=\"\\N\\n");
206 : 70 : for (j = 0; graph->complex[i].iterate (j, &c); ++j)
207 : : {
208 : 38 : dump_constraint (file, c);
209 : 38 : fprintf (file, "\\l");
210 : : }
211 : 16 : fprintf (file, "\"]");
212 : : }
213 : 72 : fprintf (file, ";\n");
214 : : }
215 : :
216 : : /* Go over the edges. */
217 : 6 : fprintf (file, "\n // Edges in the constraint graph:\n");
218 : 80 : for (i = 1; i < graph->size; i++)
219 : : {
220 : 74 : unsigned j;
221 : 74 : bitmap_iterator bi;
222 : 74 : if (find (i) != i)
223 : 2 : continue;
224 : 102 : EXECUTE_IF_IN_NONNULL_BITMAP (graph->succs[i], 0, j, bi)
225 : : {
226 : 30 : unsigned to = find (j);
227 : 30 : if (i == to)
228 : 0 : continue;
229 : 30 : if (i < FIRST_REF_NODE)
230 : 30 : fprintf (file, "\"%s\"", get_varinfo (i)->name);
231 : : else
232 : 0 : fprintf (file, "\"*%s\"", get_varinfo (i - FIRST_REF_NODE)->name);
233 : 30 : fprintf (file, " -> ");
234 : 30 : if (to < FIRST_REF_NODE)
235 : 30 : fprintf (file, "\"%s\"", get_varinfo (to)->name);
236 : : else
237 : 0 : fprintf (file, "\"*%s\"", get_varinfo (to - FIRST_REF_NODE)->name);
238 : 30 : fprintf (file, ";\n");
239 : : }
240 : : }
241 : :
242 : : /* Prints the tail of the dot file. */
243 : 6 : fprintf (file, "}\n");
244 : : }
245 : :
246 : : /* Print out the constraint graph to stderr. */
247 : :
248 : : DEBUG_FUNCTION void
249 : 0 : debug_constraint_graph (void)
250 : : {
251 : 0 : dump_constraint_graph (stderr);
252 : 0 : }
253 : :
254 : :
255 : : /* SOLVER FUNCTIONS
256 : :
257 : : The solver is a simple worklist solver, that works on the following
258 : : algorithm:
259 : :
260 : : sbitmap changed_nodes = all zeroes;
261 : : changed_count = 0;
262 : : For each node that is not already collapsed:
263 : : changed_count++;
264 : : set bit in changed nodes
265 : :
266 : : while (changed_count > 0)
267 : : {
268 : : compute topological ordering for constraint graph
269 : :
270 : : find and collapse cycles in the constraint graph (updating
271 : : changed if necessary)
272 : :
273 : : for each node (n) in the graph in topological order:
274 : : changed_count--;
275 : :
276 : : Process each complex constraint associated with the node,
277 : : updating changed if necessary.
278 : :
279 : : For each outgoing edge from n, propagate the solution from n to
280 : : the destination of the edge, updating changed as necessary.
281 : :
282 : : } */
283 : :
284 : : /* Return true if two constraint expressions A and B are equal. */
285 : :
286 : : static bool
287 : 19480273 : constraint_expr_equal (struct constraint_expr a, struct constraint_expr b)
288 : : {
289 : 12068018 : return a.type == b.type && a.var == b.var && a.offset == b.offset;
290 : : }
291 : :
292 : : /* Return true if constraint expression A is less than constraint expression
293 : : B. This is just arbitrary, but consistent, in order to give them an
294 : : ordering. */
295 : :
296 : : static bool
297 : 458856466 : constraint_expr_less (struct constraint_expr a, struct constraint_expr b)
298 : : {
299 : 0 : if (a.type == b.type)
300 : : {
301 : 273556140 : if (a.var == b.var)
302 : 206048129 : return a.offset < b.offset;
303 : : else
304 : 67508011 : return a.var < b.var;
305 : : }
306 : : else
307 : 185300326 : return a.type < b.type;
308 : : }
309 : :
310 : : /* Return true if constraint A is less than constraint B. This is just
311 : : arbitrary, but consistent, in order to give them an ordering. */
312 : :
313 : : static bool
314 : 252127564 : constraint_less (const constraint_t &a, const constraint_t &b)
315 : : {
316 : 504255128 : if (constraint_expr_less (a->lhs, b->lhs))
317 : : return true;
318 : 218587354 : else if (constraint_expr_less (b->lhs, a->lhs))
319 : : return false;
320 : : else
321 : 97435225 : return constraint_expr_less (a->rhs, b->rhs);
322 : : }
323 : :
324 : : /* Return true if two constraints A and B are equal. */
325 : :
326 : : static bool
327 : 12802442 : constraint_equal (const constraint &a, const constraint &b)
328 : : {
329 : 19480273 : return constraint_expr_equal (a.lhs, b.lhs)
330 : 12802442 : && constraint_expr_equal (a.rhs, b.rhs);
331 : : }
332 : :
333 : : /* Find a constraint LOOKFOR in the sorted constraint vector VEC. */
334 : :
335 : : static constraint_t
336 : 278787 : constraint_vec_find (vec<constraint_t> vec,
337 : : constraint &lookfor)
338 : : {
339 : 278787 : unsigned int place;
340 : 278787 : constraint_t found;
341 : :
342 : 278787 : if (!vec.exists ())
343 : : return NULL;
344 : :
345 : 223349 : place = vec.lower_bound (&lookfor, constraint_less);
346 : 223349 : if (place >= vec.length ())
347 : : return NULL;
348 : 87911 : found = vec[place];
349 : 87911 : if (!constraint_equal (*found, lookfor))
350 : : return NULL;
351 : : return found;
352 : : }
353 : :
354 : : /* Union two constraint vectors, TO and FROM. Put the result in TO.
355 : : Returns true of TO set is changed. */
356 : :
357 : : static bool
358 : 70906212 : constraint_set_union (vec<constraint_t> *to,
359 : : vec<constraint_t> *from)
360 : : {
361 : 70906212 : int i;
362 : 70906212 : constraint_t c;
363 : 70906212 : bool any_change = false;
364 : :
365 : 71184999 : FOR_EACH_VEC_ELT (*from, i, c)
366 : : {
367 : 278787 : if (constraint_vec_find (*to, *c) == NULL)
368 : : {
369 : 278120 : unsigned int place = to->lower_bound (c, constraint_less);
370 : 278120 : to->safe_insert (place, c);
371 : 278120 : any_change = true;
372 : : }
373 : : }
374 : 70906212 : return any_change;
375 : : }
376 : :
377 : : /* Expands the solution in SET to all sub-fields of variables included. */
378 : :
379 : : static bitmap
380 : 136395678 : solution_set_expand (bitmap set, bitmap *expanded)
381 : : {
382 : 136395678 : bitmap_iterator bi;
383 : 136395678 : unsigned j;
384 : :
385 : 136395678 : if (*expanded)
386 : : return *expanded;
387 : :
388 : 76033384 : *expanded = BITMAP_ALLOC (&iteration_obstack);
389 : :
390 : : /* In a first pass expand variables, once for each head to avoid
391 : : quadratic behavior, to include all sub-fields. */
392 : 76033384 : unsigned prev_head = 0;
393 : 297906749 : EXECUTE_IF_SET_IN_BITMAP (set, 0, j, bi)
394 : : {
395 : 221873365 : varinfo_t v = get_varinfo (j);
396 : 221873365 : if (v->is_artificial_var
397 : 131623494 : || v->is_full_var)
398 : 111205404 : continue;
399 : 110667961 : if (v->head != prev_head)
400 : : {
401 : 25264367 : varinfo_t head = get_varinfo (v->head);
402 : 25264367 : unsigned num = 1;
403 : 147719836 : for (varinfo_t n = vi_next (head); n != NULL; n = vi_next (n))
404 : : {
405 : 122455469 : if (n->id != head->id + num)
406 : : {
407 : : /* Usually sub variables are adjacent but since we
408 : : create pointed-to restrict representatives there
409 : : can be gaps as well. */
410 : 15086 : bitmap_set_range (*expanded, head->id, num);
411 : 15086 : head = n;
412 : 15086 : num = 1;
413 : : }
414 : : else
415 : 122440383 : num++;
416 : : }
417 : :
418 : 25264367 : bitmap_set_range (*expanded, head->id, num);
419 : 25264367 : prev_head = v->head;
420 : : }
421 : : }
422 : :
423 : : /* And finally set the rest of the bits from SET in an efficient way. */
424 : 76033384 : bitmap_ior_into (*expanded, set);
425 : :
426 : 76033384 : return *expanded;
427 : : }
428 : :
429 : : /* Union solution sets TO and DELTA, and add INC to each member of DELTA in the
430 : : process. */
431 : :
432 : : static bool
433 : 85173922 : set_union_with_increment (bitmap to, bitmap delta, HOST_WIDE_INT inc,
434 : : bitmap *expanded_delta)
435 : : {
436 : 85173922 : bool changed = false;
437 : 85173922 : bitmap_iterator bi;
438 : 85173922 : unsigned int i;
439 : :
440 : : /* If the solution of DELTA contains anything it is good enough to transfer
441 : : this to TO. */
442 : 85173922 : if (bitmap_bit_p (delta, anything_id))
443 : 1306330 : return bitmap_set_bit (to, anything_id);
444 : :
445 : : /* If the offset is unknown we have to expand the solution to
446 : : all subfields. */
447 : 83867592 : if (inc == UNKNOWN_OFFSET)
448 : : {
449 : 82866885 : delta = solution_set_expand (delta, expanded_delta);
450 : 82866885 : changed |= bitmap_ior_into (to, delta);
451 : 82866885 : return changed;
452 : : }
453 : :
454 : : /* For non-zero offset union the offsetted solution into the destination. */
455 : 4310036 : EXECUTE_IF_SET_IN_BITMAP (delta, 0, i, bi)
456 : : {
457 : 3309329 : varinfo_t vi = get_varinfo (i);
458 : :
459 : : /* If this is a variable with just one field just set its bit
460 : : in the result. */
461 : 3309329 : if (vi->is_artificial_var
462 : 1970066 : || vi->is_unknown_size_var
463 : 1828806 : || vi->is_full_var)
464 : 1728000 : changed |= bitmap_set_bit (to, i);
465 : : else
466 : : {
467 : 1581329 : HOST_WIDE_INT fieldoffset = vi->offset + inc;
468 : 1581329 : unsigned HOST_WIDE_INT size = vi->size;
469 : :
470 : : /* If the offset makes the pointer point to before the
471 : : variable use offset zero for the field lookup. */
472 : 1581329 : if (fieldoffset < 0)
473 : 33072 : vi = get_varinfo (vi->head);
474 : : else
475 : 1548257 : vi = first_or_preceding_vi_for_offset (vi, fieldoffset);
476 : :
477 : 1908422 : do
478 : : {
479 : 1908422 : changed |= bitmap_set_bit (to, vi->id);
480 : 1908422 : if (vi->is_full_var
481 : 1908382 : || vi->next == 0)
482 : : break;
483 : :
484 : : /* We have to include all fields that overlap the current field
485 : : shifted by inc. */
486 : 899149 : vi = vi_next (vi);
487 : : }
488 : 899149 : while (vi->offset < fieldoffset + size);
489 : : }
490 : : }
491 : :
492 : : return changed;
493 : : }
494 : :
495 : : /* Insert constraint C into the list of complex constraints for graph
496 : : node VAR. */
497 : :
498 : : static void
499 : 146491302 : insert_into_complex (constraint_graph_t graph,
500 : : unsigned int var, constraint_t c)
501 : : {
502 : 146491302 : vec<constraint_t> complex = graph->complex[var];
503 : 146491302 : unsigned int place = complex.lower_bound (c, constraint_less);
504 : :
505 : : /* Only insert constraints that do not already exist. */
506 : 146491302 : if (place >= complex.length ()
507 : 100766600 : || !constraint_equal (*c, *complex[place]))
508 : 144545682 : graph->complex[var].safe_insert (place, c);
509 : 146491302 : }
510 : :
511 : :
512 : : /* Condense two variable nodes into a single variable node, by moving
513 : : all associated info from FROM to TO. Returns true if TO node's
514 : : constraint set changes after the merge. */
515 : :
516 : : static bool
517 : 70906212 : merge_node_constraints (constraint_graph_t graph, unsigned int to,
518 : : unsigned int from)
519 : : {
520 : 70906212 : unsigned int i;
521 : 70906212 : constraint_t c;
522 : 70906212 : bool any_change = false;
523 : :
524 : 70906212 : gcc_checking_assert (find (from) == to);
525 : :
526 : : /* Move all complex constraints from src node into to node. */
527 : 71184999 : FOR_EACH_VEC_ELT (graph->complex[from], i, c)
528 : : {
529 : : /* In complex constraints for node FROM, we may have either
530 : : a = *FROM, and *FROM = a, or an offseted constraint which are
531 : : always added to the rhs node's constraints. */
532 : :
533 : 278787 : if (c->rhs.type == DEREF)
534 : 91140 : c->rhs.var = to;
535 : 187647 : else if (c->lhs.type == DEREF)
536 : 92065 : c->lhs.var = to;
537 : : else
538 : 95582 : c->rhs.var = to;
539 : :
540 : : }
541 : 70906212 : any_change = constraint_set_union (&graph->complex[to],
542 : : &graph->complex[from]);
543 : 70906212 : graph->complex[from].release ();
544 : 70906212 : return any_change;
545 : : }
546 : :
547 : : /* Remove edges involving NODE from GRAPH. */
548 : :
549 : : static void
550 : 90761464 : clear_edges_for_node (constraint_graph_t graph, unsigned int node)
551 : : {
552 : 90761464 : if (graph->succs[node])
553 : 2511668 : BITMAP_FREE (graph->succs[node]);
554 : 90761464 : }
555 : :
556 : : /* Merge GRAPH nodes FROM and TO into node TO. */
557 : :
558 : : static void
559 : 70906212 : merge_graph_nodes (constraint_graph_t graph, unsigned int to,
560 : : unsigned int from)
561 : : {
562 : 70906212 : if (graph->indirect_cycles[from] != -1)
563 : : {
564 : : /* If we have indirect cycles with the from node, and we have
565 : : none on the to node, the to node has indirect cycles from the
566 : : from node now that they are unified.
567 : : If indirect cycles exist on both, unify the nodes that they
568 : : are in a cycle with, since we know they are in a cycle with
569 : : each other. */
570 : 73 : if (graph->indirect_cycles[to] == -1)
571 : 53 : graph->indirect_cycles[to] = graph->indirect_cycles[from];
572 : : }
573 : :
574 : : /* Merge all the successor edges. */
575 : 70906212 : if (graph->succs[from])
576 : : {
577 : 2511668 : if (!graph->succs[to])
578 : 1264946 : graph->succs[to] = BITMAP_ALLOC (&pta_obstack);
579 : 2511668 : bitmap_ior_into (graph->succs[to],
580 : 2511668 : graph->succs[from]);
581 : : }
582 : :
583 : 70906212 : clear_edges_for_node (graph, from);
584 : 70906212 : }
585 : :
586 : :
587 : : /* Add an indirect graph edge to GRAPH, going from TO to FROM if
588 : : it doesn't exist in the graph already. */
589 : :
590 : : static void
591 : 296156673 : add_implicit_graph_edge (constraint_graph_t graph, unsigned int to,
592 : : unsigned int from)
593 : : {
594 : 296156673 : if (to == from)
595 : : return;
596 : :
597 : 296156673 : if (!graph->implicit_preds[to])
598 : 165315784 : graph->implicit_preds[to] = BITMAP_ALLOC (&predbitmap_obstack);
599 : :
600 : 296156673 : if (bitmap_set_bit (graph->implicit_preds[to], from))
601 : 278622627 : stats.num_implicit_edges++;
602 : : }
603 : :
604 : : /* Add a predecessor graph edge to GRAPH, going from TO to FROM if
605 : : it doesn't exist in the graph already.
606 : : Return false if the edge already existed, true otherwise. */
607 : :
608 : : static void
609 : 250950538 : add_pred_graph_edge (constraint_graph_t graph, unsigned int to,
610 : : unsigned int from)
611 : : {
612 : 250950538 : if (!graph->preds[to])
613 : 147472064 : graph->preds[to] = BITMAP_ALLOC (&predbitmap_obstack);
614 : 250950538 : bitmap_set_bit (graph->preds[to], from);
615 : 250950538 : }
616 : :
617 : : /* Add a graph edge to GRAPH, going from FROM to TO if
618 : : it doesn't exist in the graph already.
619 : : Return false if the edge already existed, true otherwise. */
620 : :
621 : : static bool
622 : 800587152 : add_graph_edge (constraint_graph_t graph, unsigned int to,
623 : : unsigned int from)
624 : : {
625 : 800587152 : if (to == from)
626 : : {
627 : : return false;
628 : : }
629 : : else
630 : : {
631 : 799844154 : bool r = false;
632 : :
633 : 799844154 : if (!graph->succs[from])
634 : 93369012 : graph->succs[from] = BITMAP_ALLOC (&pta_obstack);
635 : :
636 : : /* The graph solving process does not avoid "triangles", thus
637 : : there can be multiple paths from a node to another involving
638 : : intermediate other nodes. That causes extra copying which is
639 : : most difficult to avoid when the intermediate node is ESCAPED
640 : : because there are no edges added from ESCAPED. Avoid
641 : : adding the direct edge FROM -> TO when we have FROM -> ESCAPED
642 : : and TO contains ESCAPED.
643 : : ??? Note this is only a heuristic, it does not prevent the
644 : : situation from occuring. The heuristic helps PR38474 and
645 : : PR99912 significantly. */
646 : 799844154 : if (to < FIRST_REF_NODE
647 : 767716373 : && bitmap_bit_p (graph->succs[from], find (escaped_id))
648 : 1166946648 : && bitmap_bit_p (get_varinfo (find (to))->solution, escaped_id))
649 : : {
650 : 308740894 : stats.num_avoided_edges++;
651 : 308740894 : return false;
652 : : }
653 : :
654 : 491103260 : if (bitmap_set_bit (graph->succs[from], to))
655 : : {
656 : 343451218 : r = true;
657 : 343451218 : if (to < FIRST_REF_NODE && from < FIRST_REF_NODE)
658 : 299053344 : stats.num_edges++;
659 : : }
660 : 491103260 : return r;
661 : : }
662 : : }
663 : :
664 : : /* Initialize the constraint graph structure to contain SIZE nodes. */
665 : :
666 : : static void
667 : 4518845 : init_graph (unsigned int size)
668 : : {
669 : 4518845 : unsigned int j;
670 : :
671 : 4518845 : bitmap_obstack_initialize (&predbitmap_obstack);
672 : :
673 : 4518845 : graph = XCNEW (struct constraint_graph);
674 : 4518845 : graph->size = size;
675 : 4518845 : graph->succs = XCNEWVEC (bitmap, graph->size);
676 : 4518845 : graph->indirect_cycles = XNEWVEC (int, graph->size);
677 : 4518845 : graph->rep = XNEWVEC (unsigned int, graph->size);
678 : : /* ??? Macros do not support template types with multiple arguments,
679 : : so we use a typedef to work around it. */
680 : 4518845 : typedef vec<constraint_t> vec_constraint_t_heap;
681 : 4518845 : graph->complex = XCNEWVEC (vec_constraint_t_heap, size);
682 : 4518845 : graph->pe = XCNEWVEC (unsigned int, graph->size);
683 : 4518845 : graph->pe_rep = XNEWVEC (int, graph->size);
684 : :
685 : 461963741 : for (j = 0; j < graph->size; j++)
686 : : {
687 : 457444896 : graph->rep[j] = j;
688 : 457444896 : graph->pe_rep[j] = -1;
689 : 457444896 : graph->indirect_cycles[j] = -1;
690 : : }
691 : 4518845 : }
692 : :
693 : : /* Build the constraint graph, adding only predecessor edges right now. */
694 : :
695 : : static void
696 : 4518845 : build_pred_graph (void)
697 : : {
698 : 4518845 : int i;
699 : 4518845 : constraint_t c;
700 : 4518845 : unsigned int j;
701 : :
702 : 4518845 : graph->implicit_preds = XCNEWVEC (bitmap, graph->size);
703 : 4518845 : graph->preds = XCNEWVEC (bitmap, graph->size);
704 : 4518845 : graph->pointer_label = XCNEWVEC (unsigned int, graph->size);
705 : 4518845 : graph->loc_label = XCNEWVEC (unsigned int, graph->size);
706 : 4518845 : graph->pointed_by = XCNEWVEC (bitmap, graph->size);
707 : 4518845 : graph->points_to = XCNEWVEC (bitmap, graph->size);
708 : 4518845 : graph->eq_rep = XNEWVEC (int, graph->size);
709 : 4518845 : graph->direct_nodes = sbitmap_alloc (graph->size);
710 : 4518845 : graph->address_taken = BITMAP_ALLOC (&predbitmap_obstack);
711 : 4518845 : bitmap_clear (graph->direct_nodes);
712 : :
713 : 461963741 : for (j = 1; j < FIRST_REF_NODE; j++)
714 : : {
715 : 224203603 : if (!get_varinfo (j)->is_special_var)
716 : 201609378 : bitmap_set_bit (graph->direct_nodes, j);
717 : : }
718 : :
719 : 461963741 : for (j = 0; j < graph->size; j++)
720 : 457444896 : graph->eq_rep[j] = -1;
721 : :
722 : 466482586 : for (j = 0; j < varmap.length (); j++)
723 : 228722448 : graph->indirect_cycles[j] = -1;
724 : :
725 : 448403212 : FOR_EACH_VEC_ELT (constraints, i, c)
726 : : {
727 : 443884367 : struct constraint_expr lhs = c->lhs;
728 : 443884367 : struct constraint_expr rhs = c->rhs;
729 : 443884367 : unsigned int lhsvar = lhs.var;
730 : 443884367 : unsigned int rhsvar = rhs.var;
731 : :
732 : 443884367 : if (lhs.type == DEREF)
733 : : {
734 : : /* *x = y. */
735 : 36536270 : if (rhs.offset == 0 && lhs.offset == 0 && rhs.type == SCALAR)
736 : : {
737 : 32155842 : if (lhs.var == anything_id)
738 : 0 : add_pred_graph_edge (graph, storedanything_id, rhsvar);
739 : : else
740 : 64311684 : add_pred_graph_edge (graph, FIRST_REF_NODE + lhsvar, rhsvar);
741 : : }
742 : : }
743 : 407348097 : else if (rhs.type == DEREF)
744 : : {
745 : : /* x = *y */
746 : 49292052 : if (rhs.offset == 0 && lhs.offset == 0 && lhs.type == SCALAR)
747 : 26560142 : add_pred_graph_edge (graph, lhsvar, FIRST_REF_NODE + rhsvar);
748 : : else
749 : 36011981 : bitmap_clear_bit (graph->direct_nodes, lhsvar);
750 : : }
751 : 358056045 : else if (rhs.type == ADDRESSOF)
752 : : {
753 : 90642048 : varinfo_t v;
754 : :
755 : : /* x = &y */
756 : 90642048 : if (graph->points_to[lhsvar] == NULL)
757 : 67179880 : graph->points_to[lhsvar] = BITMAP_ALLOC (&predbitmap_obstack);
758 : 90642048 : bitmap_set_bit (graph->points_to[lhsvar], rhsvar);
759 : :
760 : 90642048 : if (graph->pointed_by[rhsvar] == NULL)
761 : 21826662 : graph->pointed_by[rhsvar] = BITMAP_ALLOC (&predbitmap_obstack);
762 : 90642048 : bitmap_set_bit (graph->pointed_by[rhsvar], lhsvar);
763 : :
764 : : /* Implicitly, *x = y */
765 : 181284096 : add_implicit_graph_edge (graph, FIRST_REF_NODE + lhsvar, rhsvar);
766 : :
767 : : /* All related variables are no longer direct nodes. */
768 : 90642048 : bitmap_clear_bit (graph->direct_nodes, rhsvar);
769 : 90642048 : v = get_varinfo (rhsvar);
770 : 90642048 : if (!v->is_full_var)
771 : : {
772 : 7523404 : v = get_varinfo (v->head);
773 : 47885818 : do
774 : : {
775 : 47885818 : bitmap_clear_bit (graph->direct_nodes, v->id);
776 : 47885818 : v = vi_next (v);
777 : : }
778 : 47885818 : while (v != NULL);
779 : : }
780 : 90642048 : bitmap_set_bit (graph->address_taken, rhsvar);
781 : : }
782 : 267413997 : else if (lhsvar > anything_id
783 : 267413997 : && lhsvar != rhsvar && lhs.offset == 0 && rhs.offset == 0)
784 : : {
785 : : /* x = y */
786 : 205514625 : add_pred_graph_edge (graph, lhsvar, rhsvar);
787 : : /* Implicitly, *x = *y */
788 : 205514625 : add_implicit_graph_edge (graph, FIRST_REF_NODE + lhsvar,
789 : 205514625 : FIRST_REF_NODE + rhsvar);
790 : : }
791 : 61899372 : else if (lhs.offset != 0 || rhs.offset != 0)
792 : : {
793 : 61707897 : if (rhs.offset != 0)
794 : 61707897 : bitmap_clear_bit (graph->direct_nodes, lhs.var);
795 : 0 : else if (lhs.offset != 0)
796 : 0 : bitmap_clear_bit (graph->direct_nodes, rhs.var);
797 : : }
798 : : }
799 : 4518845 : }
800 : :
801 : : /* Build the constraint graph, adding successor edges. */
802 : :
803 : : static void
804 : 4518845 : build_succ_graph (void)
805 : : {
806 : 4518845 : unsigned i, t;
807 : 4518845 : constraint_t c;
808 : :
809 : 448403212 : FOR_EACH_VEC_ELT (constraints, i, c)
810 : : {
811 : 443884367 : struct constraint_expr lhs;
812 : 443884367 : struct constraint_expr rhs;
813 : 443884367 : unsigned int lhsvar;
814 : 443884367 : unsigned int rhsvar;
815 : :
816 : 443884367 : if (!c)
817 : 2546102 : continue;
818 : :
819 : 441338265 : lhs = c->lhs;
820 : 441338265 : rhs = c->rhs;
821 : 441338265 : lhsvar = find (lhs.var);
822 : 441338265 : rhsvar = find (rhs.var);
823 : :
824 : 441338265 : if (lhs.type == DEREF)
825 : : {
826 : 36489050 : if (rhs.offset == 0 && lhs.offset == 0 && rhs.type == SCALAR)
827 : : {
828 : 32127781 : if (lhs.var == anything_id)
829 : 0 : add_graph_edge (graph, storedanything_id, rhsvar);
830 : : else
831 : 64255562 : add_graph_edge (graph, FIRST_REF_NODE + lhsvar, rhsvar);
832 : : }
833 : : }
834 : 404849215 : else if (rhs.type == DEREF)
835 : : {
836 : 49291085 : if (rhs.offset == 0 && lhs.offset == 0 && lhs.type == SCALAR)
837 : 26558572 : add_graph_edge (graph, lhsvar, FIRST_REF_NODE + rhsvar);
838 : : }
839 : 355558130 : else if (rhs.type == ADDRESSOF)
840 : : {
841 : : /* x = &y */
842 : 90642048 : gcc_checking_assert (find (rhs.var) == rhs.var);
843 : 90642048 : bitmap_set_bit (get_varinfo (lhsvar)->solution, rhsvar);
844 : : }
845 : 264916082 : else if (lhsvar > anything_id
846 : 264916082 : && lhsvar != rhsvar && lhs.offset == 0 && rhs.offset == 0)
847 : : {
848 : 154795737 : add_graph_edge (graph, lhsvar, rhsvar);
849 : : }
850 : : }
851 : :
852 : : /* Add edges from STOREDANYTHING to all nodes that can receive pointers. */
853 : 4518845 : t = find (storedanything_id);
854 : 197090533 : for (i = integer_id + 1; i < FIRST_REF_NODE; ++i)
855 : : {
856 : 188052843 : if (get_varinfo (i)->may_have_pointers)
857 : 188029391 : add_graph_edge (graph, find (i), t);
858 : : }
859 : :
860 : : /* Everything stored to ANYTHING also potentially escapes. */
861 : 4518845 : add_graph_edge (graph, find (escaped_id), t);
862 : 4518845 : }
863 : :
864 : :
865 : : /* Changed variables on the last iteration. */
866 : : static bitmap changed;
867 : :
868 : : /* Strongly Connected Component visitation info. */
869 : :
870 : : class scc_info
871 : : {
872 : : public:
873 : : scc_info (size_t size);
874 : : ~scc_info ();
875 : :
876 : : auto_sbitmap visited;
877 : : auto_sbitmap deleted;
878 : : unsigned int *dfs;
879 : : unsigned int *node_mapping;
880 : : int current_index;
881 : : auto_vec<unsigned> scc_stack;
882 : : };
883 : :
884 : :
885 : : /* Recursive routine to find strongly connected components in GRAPH.
886 : : SI is the SCC info to store the information in, and N is the id of current
887 : : graph node we are processing.
888 : :
889 : : This is Tarjan's strongly connected component finding algorithm, as
890 : : modified by Nuutila to keep only non-root nodes on the stack.
891 : : The algorithm can be found in "On finding the strongly connected
892 : : connected components in a directed graph" by Esko Nuutila and Eljas
893 : : Soisalon-Soininen, in Information Processing Letters volume 49,
894 : : number 1, pages 9-14. */
895 : :
896 : : static void
897 : 383222692 : scc_visit (constraint_graph_t graph, class scc_info *si, unsigned int n)
898 : : {
899 : 383222692 : unsigned int i;
900 : 383222692 : bitmap_iterator bi;
901 : 383222692 : unsigned int my_dfs;
902 : :
903 : 383222692 : bitmap_set_bit (si->visited, n);
904 : 383222692 : si->dfs[n] = si->current_index ++;
905 : 383222692 : my_dfs = si->dfs[n];
906 : :
907 : : /* Visit all the successors. */
908 : 651405159 : EXECUTE_IF_IN_NONNULL_BITMAP (graph->succs[n], 0, i, bi)
909 : : {
910 : 268182467 : unsigned int w;
911 : :
912 : 536364934 : if (i > LAST_REF_NODE)
913 : : break;
914 : :
915 : 268182467 : w = find (i);
916 : 268182467 : if (bitmap_bit_p (si->deleted, w))
917 : 116863801 : continue;
918 : :
919 : 151318666 : if (!bitmap_bit_p (si->visited, w))
920 : 151045221 : scc_visit (graph, si, w);
921 : :
922 : 151318666 : unsigned int t = find (w);
923 : 151318666 : gcc_checking_assert (find (n) == n);
924 : 151318666 : if (si->dfs[t] < si->dfs[n])
925 : 143948 : si->dfs[n] = si->dfs[t];
926 : : }
927 : :
928 : : /* See if any components have been identified. */
929 : 383222692 : if (si->dfs[n] == my_dfs)
930 : : {
931 : 383078810 : if (si->scc_stack.length () > 0
932 : 383078810 : && si->dfs[si->scc_stack.last ()] >= my_dfs)
933 : : {
934 : 110030 : bitmap scc = BITMAP_ALLOC (NULL);
935 : 110030 : unsigned int lowest_node;
936 : 110030 : bitmap_iterator bi;
937 : :
938 : 110030 : bitmap_set_bit (scc, n);
939 : :
940 : 110030 : while (si->scc_stack.length () != 0
941 : 253912 : && si->dfs[si->scc_stack.last ()] >= my_dfs)
942 : : {
943 : 143882 : unsigned int w = si->scc_stack.pop ();
944 : :
945 : 143882 : bitmap_set_bit (scc, w);
946 : : }
947 : :
948 : 110030 : lowest_node = bitmap_first_set_bit (scc);
949 : 110030 : gcc_assert (lowest_node < FIRST_REF_NODE);
950 : :
951 : : /* Collapse the SCC nodes into a single node, and mark the
952 : : indirect cycles. */
953 : 363942 : EXECUTE_IF_SET_IN_BITMAP (scc, 0, i, bi)
954 : : {
955 : 253912 : if (i < FIRST_REF_NODE)
956 : : {
957 : 129046 : if (unite (lowest_node, i))
958 : 19016 : unify_nodes (graph, lowest_node, i, false);
959 : : }
960 : : else
961 : : {
962 : 124866 : unite (lowest_node, i);
963 : 249732 : graph->indirect_cycles[i - FIRST_REF_NODE] = lowest_node;
964 : : }
965 : : }
966 : 110030 : bitmap_set_bit (si->deleted, lowest_node);
967 : : }
968 : : else
969 : 382968780 : bitmap_set_bit (si->deleted, n);
970 : : }
971 : : else
972 : 143882 : si->scc_stack.safe_push (n);
973 : 383222692 : }
974 : :
975 : : /* Unify node FROM into node TO, updating the changed count if
976 : : necessary when UPDATE_CHANGED is true. */
977 : :
978 : : static void
979 : 70906212 : unify_nodes (constraint_graph_t graph, unsigned int to, unsigned int from,
980 : : bool update_changed)
981 : : {
982 : 70906212 : gcc_checking_assert (to != from && find (to) == to);
983 : :
984 : 70906212 : if (dump_file && (dump_flags & TDF_DETAILS))
985 : 1224 : fprintf (dump_file, "Unifying %s to %s\n",
986 : 1224 : get_varinfo (from)->name,
987 : 1224 : get_varinfo (to)->name);
988 : :
989 : 70906212 : if (update_changed)
990 : 345470 : stats.unified_vars_dynamic++;
991 : : else
992 : 70560742 : stats.unified_vars_static++;
993 : :
994 : 70906212 : merge_graph_nodes (graph, to, from);
995 : 70906212 : if (merge_node_constraints (graph, to, from))
996 : : {
997 : 94802 : if (update_changed)
998 : 12362 : bitmap_set_bit (changed, to);
999 : : }
1000 : :
1001 : : /* Mark TO as changed if FROM was changed. If TO was already marked
1002 : : as changed, decrease the changed count. */
1003 : :
1004 : 70823772 : if (update_changed
1005 : 70823772 : && bitmap_clear_bit (changed, from))
1006 : 37238 : bitmap_set_bit (changed, to);
1007 : 70906212 : varinfo_t fromvi = get_varinfo (from);
1008 : 70906212 : if (fromvi->solution)
1009 : : {
1010 : : /* If the solution changes because of the merging, we need to mark
1011 : : the variable as changed. */
1012 : 70906212 : varinfo_t tovi = get_varinfo (to);
1013 : 70906212 : if (bitmap_ior_into (tovi->solution, fromvi->solution))
1014 : : {
1015 : 1973126 : if (update_changed)
1016 : 69248 : bitmap_set_bit (changed, to);
1017 : : }
1018 : :
1019 : 70906212 : BITMAP_FREE (fromvi->solution);
1020 : 70906212 : if (fromvi->oldsolution)
1021 : 215108 : BITMAP_FREE (fromvi->oldsolution);
1022 : :
1023 : 70906212 : if (stats.iterations > 0
1024 : 345470 : && tovi->oldsolution)
1025 : 19965 : BITMAP_FREE (tovi->oldsolution);
1026 : : }
1027 : 70906212 : if (graph->succs[to])
1028 : 2699824 : bitmap_clear_bit (graph->succs[to], to);
1029 : 70906212 : }
1030 : :
1031 : : /* Add a copy edge FROM -> TO, optimizing special cases. Returns TRUE
1032 : : if the solution of TO changed. */
1033 : :
1034 : : static bool
1035 : 429674935 : solve_add_graph_edge (constraint_graph_t graph, unsigned int to,
1036 : : unsigned int from)
1037 : : {
1038 : : /* Adding edges from the special vars is pointless.
1039 : : They don't have sets that can change. */
1040 : 429674935 : if (get_varinfo (from)->is_special_var)
1041 : 31090740 : return bitmap_ior_into (get_varinfo (to)->solution,
1042 : 62181480 : get_varinfo (from)->solution);
1043 : : /* Merging the solution from ESCAPED needlessly increases
1044 : : the set. Use ESCAPED as representative instead. */
1045 : 398584195 : else if (from == find (escaped_id))
1046 : 35650592 : return bitmap_set_bit (get_varinfo (to)->solution, escaped_id);
1047 : 362933603 : else if (get_varinfo (from)->may_have_pointers
1048 : 362933603 : && add_graph_edge (graph, to, from))
1049 : 117735516 : return bitmap_ior_into (get_varinfo (to)->solution,
1050 : 117735516 : get_varinfo (from)->solution);
1051 : : return false;
1052 : : }
1053 : :
1054 : : /* Process a constraint C that represents x = *(y + off), using DELTA as the
1055 : : starting solution for y. */
1056 : :
1057 : : static void
1058 : 70216060 : do_sd_constraint (constraint_graph_t graph, constraint_t c,
1059 : : bitmap delta, bitmap *expanded_delta)
1060 : : {
1061 : 70216060 : unsigned int lhs = c->lhs.var;
1062 : 70216060 : bool flag = false;
1063 : 70216060 : bitmap sol = get_varinfo (lhs)->solution;
1064 : 70216060 : unsigned int j;
1065 : 70216060 : bitmap_iterator bi;
1066 : 70216060 : HOST_WIDE_INT roffset = c->rhs.offset;
1067 : :
1068 : : /* Our IL does not allow this. */
1069 : 70216060 : gcc_checking_assert (c->lhs.offset == 0);
1070 : :
1071 : : /* If the solution of Y contains anything it is good enough to transfer
1072 : : this to the LHS. */
1073 : 70216060 : if (bitmap_bit_p (delta, anything_id))
1074 : : {
1075 : 679086 : flag |= bitmap_set_bit (sol, anything_id);
1076 : 679086 : goto done;
1077 : : }
1078 : :
1079 : : /* If we do not know at with offset the rhs is dereferenced compute
1080 : : the reachability set of DELTA, conservatively assuming it is
1081 : : dereferenced at all valid offsets. */
1082 : 69536974 : if (roffset == UNKNOWN_OFFSET)
1083 : : {
1084 : 51472637 : delta = solution_set_expand (delta, expanded_delta);
1085 : : /* No further offset processing is necessary. */
1086 : 51472637 : roffset = 0;
1087 : : }
1088 : :
1089 : : /* For each variable j in delta (Sol(y)), add
1090 : : an edge in the graph from j to x, and union Sol(j) into Sol(x). */
1091 : 314599276 : EXECUTE_IF_SET_IN_BITMAP (delta, 0, j, bi)
1092 : : {
1093 : 245062302 : varinfo_t v = get_varinfo (j);
1094 : 245062302 : HOST_WIDE_INT fieldoffset = v->offset + roffset;
1095 : 245062302 : unsigned HOST_WIDE_INT size = v->size;
1096 : 245062302 : unsigned int t;
1097 : :
1098 : 245062302 : if (v->is_full_var)
1099 : : ;
1100 : 146257362 : else if (roffset != 0)
1101 : : {
1102 : 5643690 : if (fieldoffset < 0)
1103 : 186863 : v = get_varinfo (v->head);
1104 : : else
1105 : 5456827 : v = first_or_preceding_vi_for_offset (v, fieldoffset);
1106 : : }
1107 : :
1108 : : /* We have to include all fields that overlap the current field
1109 : : shifted by roffset. */
1110 : 247152192 : do
1111 : : {
1112 : 247152192 : t = find (v->id);
1113 : :
1114 : 247152192 : flag |= solve_add_graph_edge (graph, lhs, t);
1115 : :
1116 : 247152192 : if (v->is_full_var
1117 : 148347060 : || v->next == 0)
1118 : : break;
1119 : :
1120 : 120956314 : v = vi_next (v);
1121 : : }
1122 : 120956314 : while (v->offset < fieldoffset + size);
1123 : : }
1124 : :
1125 : 69536974 : done:
1126 : : /* If the LHS solution changed, mark the var as changed. */
1127 : 70216060 : if (flag)
1128 : 28196250 : bitmap_set_bit (changed, lhs);
1129 : 70216060 : }
1130 : :
1131 : : /* Process a constraint C that represents *(x + off) = y using DELTA
1132 : : as the starting solution for x. */
1133 : :
1134 : : static void
1135 : 56811491 : do_ds_constraint (constraint_t c, bitmap delta, bitmap *expanded_delta)
1136 : : {
1137 : 56811491 : unsigned int rhs = c->rhs.var;
1138 : 56811491 : bitmap sol = get_varinfo (rhs)->solution;
1139 : 56811491 : unsigned int j;
1140 : 56811491 : bitmap_iterator bi;
1141 : 56811491 : HOST_WIDE_INT loff = c->lhs.offset;
1142 : 56811491 : bool escaped_p = false;
1143 : :
1144 : : /* Our IL does not allow this. */
1145 : 56811491 : gcc_checking_assert (c->rhs.offset == 0);
1146 : :
1147 : : /* If the solution of y contains ANYTHING simply use the ANYTHING
1148 : : solution. This avoids needlessly increasing the points-to sets. */
1149 : 56811491 : if (bitmap_bit_p (sol, anything_id))
1150 : 468089 : sol = get_varinfo (find (anything_id))->solution;
1151 : :
1152 : : /* If the solution for x contains ANYTHING we have to merge the
1153 : : solution of y into all pointer variables which we do via
1154 : : STOREDANYTHING. */
1155 : 56811491 : if (bitmap_bit_p (delta, anything_id))
1156 : : {
1157 : 513824 : unsigned t = find (storedanything_id);
1158 : 513824 : if (solve_add_graph_edge (graph, t, rhs))
1159 : 36155 : bitmap_set_bit (changed, t);
1160 : 513824 : return;
1161 : : }
1162 : :
1163 : : /* If we do not know at with offset the rhs is dereferenced compute
1164 : : the reachability set of DELTA, conservatively assuming it is
1165 : : dereferenced at all valid offsets. */
1166 : 56297667 : if (loff == UNKNOWN_OFFSET)
1167 : : {
1168 : 2056156 : delta = solution_set_expand (delta, expanded_delta);
1169 : 2056156 : loff = 0;
1170 : : }
1171 : :
1172 : : /* For each member j of delta (Sol(x)), add an edge from y to j and
1173 : : union Sol(y) into Sol(j) */
1174 : 275047637 : EXECUTE_IF_SET_IN_BITMAP (delta, 0, j, bi)
1175 : : {
1176 : 218749970 : varinfo_t v = get_varinfo (j);
1177 : 218749970 : unsigned int t;
1178 : 218749970 : HOST_WIDE_INT fieldoffset = v->offset + loff;
1179 : 218749970 : unsigned HOST_WIDE_INT size = v->size;
1180 : :
1181 : 218749970 : if (v->is_full_var)
1182 : : ;
1183 : 133968998 : else if (loff != 0)
1184 : : {
1185 : 8152201 : if (fieldoffset < 0)
1186 : 4971 : v = get_varinfo (v->head);
1187 : : else
1188 : 8147230 : v = first_or_preceding_vi_for_offset (v, fieldoffset);
1189 : : }
1190 : :
1191 : : /* We have to include all fields that overlap the current field
1192 : : shifted by loff. */
1193 : 221185511 : do
1194 : : {
1195 : 221185511 : if (v->may_have_pointers)
1196 : : {
1197 : : /* If v is a global variable then this is an escape point. */
1198 : 208399949 : if (v->is_global_var
1199 : 156066572 : && !escaped_p)
1200 : : {
1201 : 44902914 : t = find (escaped_id);
1202 : 44902914 : if (add_graph_edge (graph, t, rhs)
1203 : 58675795 : && bitmap_ior_into (get_varinfo (t)->solution, sol))
1204 : 1348628 : bitmap_set_bit (changed, t);
1205 : : /* Enough to let rhs escape once. */
1206 : : escaped_p = true;
1207 : : }
1208 : :
1209 : 208399949 : if (v->is_special_var)
1210 : : break;
1211 : :
1212 : 182008919 : t = find (v->id);
1213 : :
1214 : 182008919 : if (solve_add_graph_edge (graph, t, rhs))
1215 : 12329266 : bitmap_set_bit (changed, t);
1216 : : }
1217 : :
1218 : 194794481 : if (v->is_full_var
1219 : 136404397 : || v->next == 0)
1220 : : break;
1221 : :
1222 : 111256874 : v = vi_next (v);
1223 : : }
1224 : 111256874 : while (v->offset < fieldoffset + size);
1225 : : }
1226 : : }
1227 : :
1228 : : /* Handle a non-simple (simple meaning requires no iteration),
1229 : : constraint (IE *x = &y, x = *y, *x = y, and x = y with offsets involved). */
1230 : :
1231 : : static void
1232 : 212201473 : do_complex_constraint (constraint_graph_t graph, constraint_t c, bitmap delta,
1233 : : bitmap *expanded_delta)
1234 : : {
1235 : 212201473 : if (c->lhs.type == DEREF)
1236 : : {
1237 : 56811491 : if (c->rhs.type == ADDRESSOF)
1238 : : {
1239 : 0 : gcc_unreachable ();
1240 : : }
1241 : : else
1242 : : {
1243 : : /* *x = y */
1244 : 56811491 : do_ds_constraint (c, delta, expanded_delta);
1245 : : }
1246 : : }
1247 : 155389982 : else if (c->rhs.type == DEREF)
1248 : : {
1249 : : /* x = *y */
1250 : 70216060 : if (!(get_varinfo (c->lhs.var)->is_special_var))
1251 : 70216060 : do_sd_constraint (graph, c, delta, expanded_delta);
1252 : : }
1253 : : else
1254 : : {
1255 : 85173922 : bitmap tmp;
1256 : 85173922 : bool flag = false;
1257 : :
1258 : 85173922 : gcc_checking_assert (c->rhs.type == SCALAR && c->lhs.type == SCALAR
1259 : : && c->rhs.offset != 0 && c->lhs.offset == 0);
1260 : 85173922 : tmp = get_varinfo (c->lhs.var)->solution;
1261 : :
1262 : 85173922 : flag = set_union_with_increment (tmp, delta, c->rhs.offset,
1263 : : expanded_delta);
1264 : :
1265 : 85173922 : if (flag)
1266 : 20926780 : bitmap_set_bit (changed, c->lhs.var);
1267 : : }
1268 : 212201473 : }
1269 : :
1270 : : /* Initialize and return a new SCC info structure. */
1271 : :
1272 : 9037690 : scc_info::scc_info (size_t size) :
1273 : 9037690 : visited (size), deleted (size), current_index (0), scc_stack (1)
1274 : : {
1275 : 9037690 : bitmap_clear (visited);
1276 : 9037690 : bitmap_clear (deleted);
1277 : 9037690 : node_mapping = XNEWVEC (unsigned int, size);
1278 : 9037690 : dfs = XCNEWVEC (unsigned int, size);
1279 : :
1280 : 923927482 : for (size_t i = 0; i < size; i++)
1281 : 914889792 : node_mapping[i] = i;
1282 : 9037690 : }
1283 : :
1284 : : /* Free an SCC info structure pointed to by SI. */
1285 : :
1286 : 9037690 : scc_info::~scc_info ()
1287 : : {
1288 : 9037690 : free (node_mapping);
1289 : 9037690 : free (dfs);
1290 : 9037690 : }
1291 : :
1292 : :
1293 : : /* Find indirect cycles in GRAPH that occur, using strongly connected
1294 : : components, and note them in the indirect cycles map.
1295 : :
1296 : : This technique comes from Ben Hardekopf and Calvin Lin,
1297 : : "It Pays to be Lazy: Fast and Accurate Pointer Analysis for Millions of
1298 : : Lines of Code", submitted to PLDI 2007. */
1299 : :
1300 : : static void
1301 : 4518845 : find_indirect_cycles (constraint_graph_t graph)
1302 : : {
1303 : 4518845 : unsigned int i;
1304 : 4518845 : unsigned int size = graph->size;
1305 : 4518845 : scc_info si (size);
1306 : :
1307 : 919408637 : for (i = 0; i < MIN (LAST_REF_NODE, size); i++)
1308 : 452926051 : if (!bitmap_bit_p (si.visited, i) && find (i) == i)
1309 : 232177471 : scc_visit (graph, &si, i);
1310 : 4518845 : }
1311 : :
1312 : : /* Visit the graph in topological order starting at node N, and store the
1313 : : order in TOPO_ORDER using VISITED to indicate visited nodes. */
1314 : :
1315 : : static void
1316 : 389817226 : topo_visit (constraint_graph_t graph, vec<unsigned> &topo_order,
1317 : : sbitmap visited, unsigned int n)
1318 : : {
1319 : 389817226 : bitmap_iterator bi;
1320 : 389817226 : unsigned int j;
1321 : :
1322 : 389817226 : bitmap_set_bit (visited, n);
1323 : :
1324 : 389817226 : if (graph->succs[n])
1325 : 950702159 : EXECUTE_IF_SET_IN_BITMAP (graph->succs[n], 0, j, bi)
1326 : : {
1327 : 749917971 : unsigned k = find (j);
1328 : 749917971 : if (!bitmap_bit_p (visited, k))
1329 : 284874530 : topo_visit (graph, topo_order, visited, k);
1330 : : }
1331 : :
1332 : : /* Also consider copy with offset complex constraints as implicit edges. */
1333 : 833609460 : for (auto c : graph->complex[n])
1334 : : {
1335 : : /* Constraints are ordered so that SCALAR = SCALAR appear first. */
1336 : 258494248 : if (c->lhs.type != SCALAR || c->rhs.type != SCALAR)
1337 : : break;
1338 : 143553348 : gcc_checking_assert (c->rhs.var == n);
1339 : 143553348 : unsigned k = find (c->lhs.var);
1340 : 143553348 : if (!bitmap_bit_p (visited, k))
1341 : 36570117 : topo_visit (graph, topo_order, visited, k);
1342 : : }
1343 : :
1344 : 389817226 : topo_order.quick_push (n);
1345 : 389817226 : }
1346 : :
1347 : : /* Compute a topological ordering for GRAPH, and return the result. */
1348 : :
1349 : : static auto_vec<unsigned>
1350 : 7994696 : compute_topo_order (constraint_graph_t graph)
1351 : : {
1352 : 7994696 : unsigned int i;
1353 : 7994696 : unsigned int size = graph->size;
1354 : :
1355 : 7994696 : auto_sbitmap visited (size);
1356 : 7994696 : bitmap_clear (visited);
1357 : :
1358 : : /* For the heuristic in add_graph_edge to work optimally make sure to
1359 : : first visit the connected component of the graph containing
1360 : : ESCAPED. Do this by extracting the connected component
1361 : : with ESCAPED and append that to all other components as solve_graph
1362 : : pops from the order. */
1363 : 7994696 : auto_vec<unsigned> tail (size);
1364 : 7994696 : topo_visit (graph, tail, visited, find (escaped_id));
1365 : :
1366 : 7994696 : auto_vec<unsigned> topo_order (size);
1367 : :
1368 : 593097156 : for (i = 0; i != size; ++i)
1369 : 577107764 : if (!bitmap_bit_p (visited, i) && find (i) == i)
1370 : 60377883 : topo_visit (graph, topo_order, visited, i);
1371 : :
1372 : 7994696 : topo_order.splice (tail);
1373 : 7994696 : return topo_order;
1374 : 7994696 : }
1375 : :
1376 : : /* Structure used to for hash value numbering of pointer equivalence
1377 : : classes. */
1378 : :
1379 : : typedef struct equiv_class_label
1380 : : {
1381 : : hashval_t hashcode;
1382 : : unsigned int equivalence_class;
1383 : : bitmap labels;
1384 : : } *equiv_class_label_t;
1385 : : typedef const struct equiv_class_label *const_equiv_class_label_t;
1386 : :
1387 : : /* Equiv_class_label hashtable helpers. */
1388 : :
1389 : : struct equiv_class_hasher : nofree_ptr_hash <equiv_class_label>
1390 : : {
1391 : : static inline hashval_t hash (const equiv_class_label *);
1392 : : static inline bool equal (const equiv_class_label *,
1393 : : const equiv_class_label *);
1394 : : };
1395 : :
1396 : : /* A hashtable for mapping a bitmap of labels->pointer equivalence
1397 : : classes. */
1398 : : static hash_table<equiv_class_hasher> *pointer_equiv_class_table;
1399 : :
1400 : : /* A hashtable for mapping a bitmap of labels->location equivalence
1401 : : classes. */
1402 : : static hash_table<equiv_class_hasher> *location_equiv_class_table;
1403 : :
1404 : : /* Hash function for a equiv_class_label_t. */
1405 : :
1406 : : inline hashval_t
1407 : 187713683 : equiv_class_hasher::hash (const equiv_class_label *ecl)
1408 : : {
1409 : 187713683 : return ecl->hashcode;
1410 : : }
1411 : :
1412 : : /* Equality function for two equiv_class_label_t's. */
1413 : :
1414 : : inline bool
1415 : 243732888 : equiv_class_hasher::equal (const equiv_class_label *eql1,
1416 : : const equiv_class_label *eql2)
1417 : : {
1418 : 243732888 : return (eql1->hashcode == eql2->hashcode
1419 : 243732888 : && bitmap_equal_p (eql1->labels, eql2->labels));
1420 : : }
1421 : :
1422 : : struct obstack equiv_class_obstack;
1423 : :
1424 : : /* Lookup a equivalence class in TABLE by the bitmap of LABELS with
1425 : : hash HAS it contains. Sets *REF_LABELS to the bitmap LABELS
1426 : : is equivalent to. */
1427 : :
1428 : : static equiv_class_label *
1429 : 195767941 : equiv_class_lookup_or_add (hash_table<equiv_class_hasher> *table,
1430 : : bitmap labels)
1431 : : {
1432 : 195767941 : equiv_class_label **slot;
1433 : 195767941 : equiv_class_label ecl;
1434 : :
1435 : 195767941 : ecl.labels = labels;
1436 : 195767941 : ecl.hashcode = bitmap_hash (labels);
1437 : 195767941 : slot = table->find_slot (&ecl, INSERT);
1438 : 195767941 : if (!*slot)
1439 : : {
1440 : 163632231 : *slot = XOBNEW (&equiv_class_obstack, struct equiv_class_label);
1441 : 163632231 : (*slot)->labels = labels;
1442 : 163632231 : (*slot)->hashcode = ecl.hashcode;
1443 : 163632231 : (*slot)->equivalence_class = 0;
1444 : : }
1445 : :
1446 : 195767941 : return *slot;
1447 : : }
1448 : :
1449 : :
1450 : : /* Perform offline variable substitution.
1451 : :
1452 : : This is a worst case quadratic time way of identifying variables
1453 : : that must have equivalent points-to sets, including those caused by
1454 : : static cycles, and single entry subgraphs, in the constraint graph.
1455 : :
1456 : : The technique is described in "Exploiting Pointer and Location
1457 : : Equivalence to Optimize Pointer Analysis. In the 14th International
1458 : : Static Analysis Symposium (SAS), August 2007." It is known as the
1459 : : "HU" algorithm, and is equivalent to value numbering the collapsed
1460 : : constraint graph including evaluating unions.
1461 : :
1462 : : The general method of finding equivalence classes is as follows:
1463 : : Add fake nodes (REF nodes) and edges for *a = b and a = *b constraints.
1464 : : Initialize all non-REF nodes to be direct nodes.
1465 : : For each constraint a = a U {b}, we set pts(a) = pts(a) u {fresh
1466 : : variable}
1467 : : For each constraint containing the dereference, we also do the same
1468 : : thing.
1469 : :
1470 : : We then compute SCC's in the graph and unify nodes in the same SCC,
1471 : : including pts sets.
1472 : :
1473 : : For each non-collapsed node x:
1474 : : Visit all unvisited explicit incoming edges.
1475 : : Ignoring all non-pointers, set pts(x) = Union of pts(a) for y
1476 : : where y->x.
1477 : : Lookup the equivalence class for pts(x).
1478 : : If we found one, equivalence_class(x) = found class.
1479 : : Otherwise, equivalence_class(x) = new class, and new_class is
1480 : : added to the lookup table.
1481 : :
1482 : : All direct nodes with the same equivalence class can be replaced
1483 : : with a single representative node.
1484 : : All unlabeled nodes (label == 0) are not pointers and all edges
1485 : : involving them can be eliminated.
1486 : : We perform these optimizations during rewrite_constraints
1487 : :
1488 : : In addition to pointer equivalence class finding, we also perform
1489 : : location equivalence class finding. This is the set of variables
1490 : : that always appear together in points-to sets. We use this to
1491 : : compress the size of the points-to sets. */
1492 : :
1493 : : /* Current maximum pointer equivalence class id. */
1494 : : static int pointer_equiv_class;
1495 : :
1496 : : /* Current maximum location equivalence class id. */
1497 : : static int location_equiv_class;
1498 : :
1499 : : /* Recursive routine to find strongly connected components in GRAPH,
1500 : : and label it's nodes with DFS numbers. */
1501 : :
1502 : : static void
1503 : 267952786 : condense_visit (constraint_graph_t graph, class scc_info *si, unsigned int n)
1504 : : {
1505 : 267952786 : unsigned int i;
1506 : 267952786 : bitmap_iterator bi;
1507 : 267952786 : unsigned int my_dfs;
1508 : :
1509 : 267952786 : gcc_checking_assert (si->node_mapping[n] == n);
1510 : 267952786 : bitmap_set_bit (si->visited, n);
1511 : 267952786 : si->dfs[n] = si->current_index ++;
1512 : 267952786 : my_dfs = si->dfs[n];
1513 : :
1514 : : /* Visit all the successors. */
1515 : 493424575 : EXECUTE_IF_IN_NONNULL_BITMAP (graph->preds[n], 0, i, bi)
1516 : : {
1517 : 225471789 : unsigned int w = si->node_mapping[i];
1518 : :
1519 : 225471789 : if (bitmap_bit_p (si->deleted, w))
1520 : 143259861 : continue;
1521 : :
1522 : 82211928 : if (!bitmap_bit_p (si->visited, w))
1523 : 80739010 : condense_visit (graph, si, w);
1524 : :
1525 : 82211928 : unsigned int t = si->node_mapping[w];
1526 : 82211928 : gcc_checking_assert (si->node_mapping[n] == n);
1527 : 82211928 : if (si->dfs[t] < si->dfs[n])
1528 : 2661778 : si->dfs[n] = si->dfs[t];
1529 : : }
1530 : :
1531 : : /* Visit all the implicit predecessors. */
1532 : 327293036 : EXECUTE_IF_IN_NONNULL_BITMAP (graph->implicit_preds[n], 0, i, bi)
1533 : : {
1534 : 59340250 : unsigned int w = si->node_mapping[i];
1535 : :
1536 : 59340250 : if (bitmap_bit_p (si->deleted, w))
1537 : 19650822 : continue;
1538 : :
1539 : 39689428 : if (!bitmap_bit_p (si->visited, w))
1540 : 34818845 : condense_visit (graph, si, w);
1541 : :
1542 : 39689428 : unsigned int t = si->node_mapping[w];
1543 : 39689428 : gcc_assert (si->node_mapping[n] == n);
1544 : 39689428 : if (si->dfs[t] < si->dfs[n])
1545 : 8352133 : si->dfs[n] = si->dfs[t];
1546 : : }
1547 : :
1548 : : /* See if any components have been identified. */
1549 : 267952786 : if (si->dfs[n] == my_dfs)
1550 : : {
1551 : 257106001 : if (si->scc_stack.length () != 0
1552 : 257106001 : && si->dfs[si->scc_stack.last ()] >= my_dfs)
1553 : : {
1554 : : /* Find the first node of the SCC and do non-bitmap work. */
1555 : : bool direct_p = true;
1556 : : unsigned first = si->scc_stack.length ();
1557 : 10846785 : do
1558 : : {
1559 : 10846785 : --first;
1560 : 10846785 : unsigned int w = si->scc_stack[first];
1561 : 10846785 : si->node_mapping[w] = n;
1562 : 10846785 : if (!bitmap_bit_p (graph->direct_nodes, w))
1563 : 8722558 : direct_p = false;
1564 : : }
1565 : : while (first > 0
1566 : 12205199 : && si->dfs[si->scc_stack[first - 1]] >= my_dfs);
1567 : 1358414 : if (!direct_p)
1568 : 871838 : bitmap_clear_bit (graph->direct_nodes, n);
1569 : :
1570 : : /* Want to reduce to node n, push that first. */
1571 : 1358414 : si->scc_stack.reserve (1);
1572 : 1358414 : si->scc_stack.quick_push (si->scc_stack[first]);
1573 : 1358414 : si->scc_stack[first] = n;
1574 : :
1575 : 1358414 : unsigned scc_size = si->scc_stack.length () - first;
1576 : 1358414 : unsigned split = scc_size / 2;
1577 : 1358414 : unsigned carry = scc_size - split * 2;
1578 : 4792071 : while (split > 0)
1579 : : {
1580 : 14280442 : for (unsigned i = 0; i < split; ++i)
1581 : : {
1582 : 10846785 : unsigned a = si->scc_stack[first + i];
1583 : 10846785 : unsigned b = si->scc_stack[first + split + carry + i];
1584 : :
1585 : : /* Unify our nodes. */
1586 : 10846785 : if (graph->preds[b])
1587 : : {
1588 : 4759546 : if (!graph->preds[a])
1589 : 976852 : std::swap (graph->preds[a], graph->preds[b]);
1590 : : else
1591 : 3782694 : bitmap_ior_into_and_free (graph->preds[a],
1592 : : &graph->preds[b]);
1593 : : }
1594 : 10846785 : if (graph->implicit_preds[b])
1595 : : {
1596 : 8619409 : if (!graph->implicit_preds[a])
1597 : 888996 : std::swap (graph->implicit_preds[a],
1598 : : graph->implicit_preds[b]);
1599 : : else
1600 : 7730413 : bitmap_ior_into_and_free (graph->implicit_preds[a],
1601 : : &graph->implicit_preds[b]);
1602 : : }
1603 : 10846785 : if (graph->points_to[b])
1604 : : {
1605 : 523841 : if (!graph->points_to[a])
1606 : 231352 : std::swap (graph->points_to[a], graph->points_to[b]);
1607 : : else
1608 : 292489 : bitmap_ior_into_and_free (graph->points_to[a],
1609 : : &graph->points_to[b]);
1610 : : }
1611 : : }
1612 : 3433657 : unsigned remain = split + carry;
1613 : 3433657 : split = remain / 2;
1614 : 3433657 : carry = remain - split * 2;
1615 : : }
1616 : : /* Actually pop the SCC. */
1617 : 1358414 : si->scc_stack.truncate (first);
1618 : : }
1619 : 257106001 : bitmap_set_bit (si->deleted, n);
1620 : : }
1621 : : else
1622 : 10846785 : si->scc_stack.safe_push (n);
1623 : 267952786 : }
1624 : :
1625 : : /* Label pointer equivalences.
1626 : :
1627 : : This performs a value numbering of the constraint graph to
1628 : : discover which variables will always have the same points-to sets
1629 : : under the current set of constraints.
1630 : :
1631 : : The way it value numbers is to store the set of points-to bits
1632 : : generated by the constraints and graph edges. This is just used as a
1633 : : hash and equality comparison. The *actual set of points-to bits* is
1634 : : completely irrelevant, in that we don't care about being able to
1635 : : extract them later.
1636 : :
1637 : : The equality values (currently bitmaps) just have to satisfy a few
1638 : : constraints, the main ones being:
1639 : : 1. The combining operation must be order independent.
1640 : : 2. The end result of a given set of operations must be unique iff the
1641 : : combination of input values is unique
1642 : : 3. Hashable. */
1643 : :
1644 : : static void
1645 : 233474385 : label_visit (constraint_graph_t graph, class scc_info *si, unsigned int n)
1646 : : {
1647 : 233474385 : unsigned int i, first_pred;
1648 : 233474385 : bitmap_iterator bi;
1649 : :
1650 : 233474385 : bitmap_set_bit (si->visited, n);
1651 : :
1652 : : /* Label and union our incoming edges's points to sets. */
1653 : 233474385 : first_pred = -1U;
1654 : 453609889 : EXECUTE_IF_IN_NONNULL_BITMAP (graph->preds[n], 0, i, bi)
1655 : : {
1656 : 220135504 : unsigned int w = si->node_mapping[i];
1657 : 220135504 : if (!bitmap_bit_p (si->visited, w))
1658 : 76035904 : label_visit (graph, si, w);
1659 : :
1660 : : /* Skip unused edges. */
1661 : 220135504 : if (w == n || graph->pointer_label[w] == 0)
1662 : 5279705 : continue;
1663 : :
1664 : 214855799 : if (graph->points_to[w])
1665 : : {
1666 : 214855799 : if (!graph->points_to[n])
1667 : : {
1668 : 149425235 : if (first_pred == -1U)
1669 : : first_pred = w;
1670 : : else
1671 : : {
1672 : 41627619 : graph->points_to[n] = BITMAP_ALLOC (&predbitmap_obstack);
1673 : 41627619 : bitmap_ior (graph->points_to[n],
1674 : 41627619 : graph->points_to[first_pred],
1675 : 41627619 : graph->points_to[w]);
1676 : : }
1677 : : }
1678 : : else
1679 : 65430564 : bitmap_ior_into (graph->points_to[n], graph->points_to[w]);
1680 : : }
1681 : : }
1682 : :
1683 : : /* Indirect nodes get fresh variables and a new pointer equiv class. */
1684 : 233474385 : if (!bitmap_bit_p (graph->direct_nodes, n))
1685 : : {
1686 : 113183451 : if (!graph->points_to[n])
1687 : : {
1688 : 65426269 : graph->points_to[n] = BITMAP_ALLOC (&predbitmap_obstack);
1689 : 65426269 : if (first_pred != -1U)
1690 : 26490698 : bitmap_copy (graph->points_to[n], graph->points_to[first_pred]);
1691 : : }
1692 : 226366902 : bitmap_set_bit (graph->points_to[n], FIRST_REF_NODE + n);
1693 : 113183451 : graph->pointer_label[n] = pointer_equiv_class++;
1694 : 113183451 : equiv_class_label_t ecl;
1695 : 226366902 : ecl = equiv_class_lookup_or_add (pointer_equiv_class_table,
1696 : 113183451 : graph->points_to[n]);
1697 : 113183451 : ecl->equivalence_class = graph->pointer_label[n];
1698 : 172716557 : return;
1699 : : }
1700 : :
1701 : : /* If there was only a single non-empty predecessor the pointer equiv
1702 : : class is the same. */
1703 : 120290934 : if (!graph->points_to[n])
1704 : : {
1705 : 59533106 : if (first_pred != -1U)
1706 : : {
1707 : 39679299 : graph->pointer_label[n] = graph->pointer_label[first_pred];
1708 : 39679299 : graph->points_to[n] = graph->points_to[first_pred];
1709 : : }
1710 : 59533106 : return;
1711 : : }
1712 : :
1713 : 60757828 : if (!bitmap_empty_p (graph->points_to[n]))
1714 : : {
1715 : 60757828 : equiv_class_label_t ecl;
1716 : 60757828 : ecl = equiv_class_lookup_or_add (pointer_equiv_class_table,
1717 : : graph->points_to[n]);
1718 : 60757828 : if (ecl->equivalence_class == 0)
1719 : 29070689 : ecl->equivalence_class = pointer_equiv_class++;
1720 : : else
1721 : : {
1722 : 31687139 : BITMAP_FREE (graph->points_to[n]);
1723 : 31687139 : graph->points_to[n] = ecl->labels;
1724 : : }
1725 : 60757828 : graph->pointer_label[n] = ecl->equivalence_class;
1726 : : }
1727 : : }
1728 : :
1729 : : /* Print the pred graph in dot format. */
1730 : :
1731 : : static void
1732 : 3 : dump_pred_graph (class scc_info *si, FILE *file)
1733 : : {
1734 : 3 : unsigned int i;
1735 : :
1736 : : /* Only print the graph if it has already been initialized: */
1737 : 3 : if (!graph)
1738 : : return;
1739 : :
1740 : : /* Prints the header of the dot file: */
1741 : 3 : fprintf (file, "strict digraph {\n");
1742 : 3 : fprintf (file, " node [\n shape = box\n ]\n");
1743 : 3 : fprintf (file, " edge [\n fontsize = \"12\"\n ]\n");
1744 : 3 : fprintf (file, "\n // List of nodes and complex constraints in "
1745 : : "the constraint graph:\n");
1746 : :
1747 : : /* The next lines print the nodes in the graph together with the
1748 : : complex constraints attached to them. */
1749 : 80 : for (i = 1; i < graph->size; i++)
1750 : : {
1751 : 154 : if (i == FIRST_REF_NODE)
1752 : 3 : continue;
1753 : 74 : if (si->node_mapping[i] != i)
1754 : 0 : continue;
1755 : 74 : if (i < FIRST_REF_NODE)
1756 : 37 : fprintf (file, "\"%s\"", get_varinfo (i)->name);
1757 : : else
1758 : 37 : fprintf (file, "\"*%s\"", get_varinfo (i - FIRST_REF_NODE)->name);
1759 : 74 : if (graph->points_to[i]
1760 : 74 : && !bitmap_empty_p (graph->points_to[i]))
1761 : : {
1762 : 11 : if (i < FIRST_REF_NODE)
1763 : 11 : fprintf (file, "[label=\"%s = {", get_varinfo (i)->name);
1764 : : else
1765 : 0 : fprintf (file, "[label=\"*%s = {",
1766 : 0 : get_varinfo (i - FIRST_REF_NODE)->name);
1767 : 11 : unsigned j;
1768 : 11 : bitmap_iterator bi;
1769 : 25 : EXECUTE_IF_SET_IN_BITMAP (graph->points_to[i], 0, j, bi)
1770 : 14 : fprintf (file, " %d", j);
1771 : 11 : fprintf (file, " }\"]");
1772 : : }
1773 : 74 : fprintf (file, ";\n");
1774 : : }
1775 : :
1776 : : /* Go over the edges. */
1777 : 3 : fprintf (file, "\n // Edges in the constraint graph:\n");
1778 : 80 : for (i = 1; i < graph->size; i++)
1779 : : {
1780 : 77 : unsigned j;
1781 : 77 : bitmap_iterator bi;
1782 : 77 : if (si->node_mapping[i] != i)
1783 : 0 : continue;
1784 : 92 : EXECUTE_IF_IN_NONNULL_BITMAP (graph->preds[i], 0, j, bi)
1785 : : {
1786 : 15 : unsigned from = si->node_mapping[j];
1787 : 15 : if (from < FIRST_REF_NODE)
1788 : 7 : fprintf (file, "\"%s\"", get_varinfo (from)->name);
1789 : : else
1790 : 8 : fprintf (file, "\"*%s\"",
1791 : 8 : get_varinfo (from - FIRST_REF_NODE)->name);
1792 : 15 : fprintf (file, " -> ");
1793 : 15 : if (i < FIRST_REF_NODE)
1794 : 11 : fprintf (file, "\"%s\"", get_varinfo (i)->name);
1795 : : else
1796 : 8 : fprintf (file, "\"*%s\"", get_varinfo (i - FIRST_REF_NODE)->name);
1797 : 15 : fprintf (file, ";\n");
1798 : : }
1799 : : }
1800 : :
1801 : : /* Prints the tail of the dot file. */
1802 : 3 : fprintf (file, "}\n");
1803 : : }
1804 : :
1805 : : /* Perform offline variable substitution, discovering equivalence
1806 : : classes, and eliminating non-pointer variables. */
1807 : :
1808 : : static class scc_info *
1809 : 4518845 : perform_var_substitution (constraint_graph_t graph)
1810 : : {
1811 : 4518845 : unsigned int i;
1812 : 4518845 : unsigned int size = graph->size;
1813 : 4518845 : scc_info *si = new scc_info (size);
1814 : :
1815 : 4518845 : bitmap_obstack_initialize (&iteration_obstack);
1816 : 4518845 : gcc_obstack_init (&equiv_class_obstack);
1817 : 4518845 : pointer_equiv_class_table = new hash_table<equiv_class_hasher> (511);
1818 : 4518845 : location_equiv_class_table
1819 : 4518845 : = new hash_table<equiv_class_hasher> (511);
1820 : 4518845 : pointer_equiv_class = 1;
1821 : 4518845 : location_equiv_class = 1;
1822 : :
1823 : : /* Condense the nodes, which means to find SCC's, count incoming
1824 : : predecessors, and unite nodes in SCC's. */
1825 : 228722448 : for (i = 1; i < FIRST_REF_NODE; i++)
1826 : 224203603 : if (!bitmap_bit_p (si->visited, si->node_mapping[i]))
1827 : 152394931 : condense_visit (graph, si, si->node_mapping[i]);
1828 : :
1829 : 4518845 : if (dump_file && (dump_flags & TDF_GRAPH))
1830 : : {
1831 : 3 : fprintf (dump_file, "\n\n// The constraint graph before var-substitution "
1832 : : "in dot format:\n");
1833 : 3 : dump_pred_graph (si, dump_file);
1834 : 3 : fprintf (dump_file, "\n\n");
1835 : : }
1836 : :
1837 : 4518845 : bitmap_clear (si->visited);
1838 : : /* Actually the label the nodes for pointer equivalences. */
1839 : 461963741 : for (i = 1; i < FIRST_REF_NODE; i++)
1840 : 224203603 : if (!bitmap_bit_p (si->visited, si->node_mapping[i]))
1841 : 157438481 : label_visit (graph, si, si->node_mapping[i]);
1842 : :
1843 : : /* Calculate location equivalence labels. */
1844 : 228722448 : for (i = 1; i < FIRST_REF_NODE; i++)
1845 : : {
1846 : 224203603 : bitmap pointed_by;
1847 : 224203603 : bitmap_iterator bi;
1848 : 224203603 : unsigned int j;
1849 : :
1850 : 224203603 : if (!graph->pointed_by[i])
1851 : 202376941 : continue;
1852 : 21826662 : pointed_by = BITMAP_ALLOC (&iteration_obstack);
1853 : :
1854 : : /* Translate the pointed-by mapping for pointer equivalence
1855 : : labels. */
1856 : 98073487 : EXECUTE_IF_SET_IN_BITMAP (graph->pointed_by[i], 0, j, bi)
1857 : : {
1858 : 76246825 : bitmap_set_bit (pointed_by,
1859 : 76246825 : graph->pointer_label[si->node_mapping[j]]);
1860 : : }
1861 : : /* The original pointed_by is now dead. */
1862 : 21826662 : BITMAP_FREE (graph->pointed_by[i]);
1863 : :
1864 : : /* Look up the location equivalence label if one exists, or make
1865 : : one otherwise. */
1866 : 21826662 : equiv_class_label_t ecl;
1867 : 21826662 : ecl = equiv_class_lookup_or_add (location_equiv_class_table, pointed_by);
1868 : 21826662 : if (ecl->equivalence_class == 0)
1869 : 21378091 : ecl->equivalence_class = location_equiv_class++;
1870 : : else
1871 : : {
1872 : 448571 : if (dump_file && (dump_flags & TDF_DETAILS))
1873 : 53 : fprintf (dump_file, "Found location equivalence for node %s\n",
1874 : 53 : get_varinfo (i)->name);
1875 : 448571 : BITMAP_FREE (pointed_by);
1876 : : }
1877 : 21826662 : graph->loc_label[i] = ecl->equivalence_class;
1878 : :
1879 : : }
1880 : :
1881 : 4518845 : if (dump_file && (dump_flags & TDF_DETAILS))
1882 : 6763 : for (i = 1; i < FIRST_REF_NODE; i++)
1883 : : {
1884 : 6464 : unsigned j = si->node_mapping[i];
1885 : 6464 : if (j != i)
1886 : : {
1887 : 21 : fprintf (dump_file, "%s node id %d ",
1888 : 21 : bitmap_bit_p (graph->direct_nodes, i)
1889 : : ? "Direct" : "Indirect", i);
1890 : 21 : if (i < FIRST_REF_NODE)
1891 : 21 : fprintf (dump_file, "\"%s\"", get_varinfo (i)->name);
1892 : : else
1893 : 0 : fprintf (dump_file, "\"*%s\"",
1894 : 0 : get_varinfo (i - FIRST_REF_NODE)->name);
1895 : 21 : fprintf (dump_file, " mapped to SCC leader node id %d ", j);
1896 : 21 : if (j < FIRST_REF_NODE)
1897 : 21 : fprintf (dump_file, "\"%s\"\n", get_varinfo (j)->name);
1898 : : else
1899 : 0 : fprintf (dump_file, "\"*%s\"\n",
1900 : 0 : get_varinfo (j - FIRST_REF_NODE)->name);
1901 : : }
1902 : : else
1903 : : {
1904 : 9933 : fprintf (dump_file,
1905 : : "Equivalence classes for %s node id %d ",
1906 : 6443 : bitmap_bit_p (graph->direct_nodes, i)
1907 : : ? "direct" : "indirect", i);
1908 : 6443 : if (i < FIRST_REF_NODE)
1909 : 6443 : fprintf (dump_file, "\"%s\"", get_varinfo (i)->name);
1910 : : else
1911 : 0 : fprintf (dump_file, "\"*%s\"",
1912 : 0 : get_varinfo (i - FIRST_REF_NODE)->name);
1913 : 6443 : fprintf (dump_file,
1914 : : ": pointer %d, location %d\n",
1915 : 6443 : graph->pointer_label[i], graph->loc_label[i]);
1916 : : }
1917 : : }
1918 : :
1919 : : /* Quickly eliminate our non-pointer variables. */
1920 : :
1921 : 228722448 : for (i = 1; i < FIRST_REF_NODE; i++)
1922 : : {
1923 : 224203603 : unsigned int node = si->node_mapping[i];
1924 : :
1925 : 224203603 : if (graph->pointer_label[node] == 0)
1926 : : {
1927 : 19855252 : if (dump_file && (dump_flags & TDF_DETAILS))
1928 : 913 : fprintf (dump_file,
1929 : : "%s is a non-pointer variable, eliminating edges.\n",
1930 : 913 : get_varinfo (node)->name);
1931 : 19855252 : stats.nonpointer_vars++;
1932 : 19855252 : clear_edges_for_node (graph, node);
1933 : : }
1934 : : }
1935 : :
1936 : 4518845 : return si;
1937 : : }
1938 : :
1939 : : /* Free information that was only necessary for variable
1940 : : substitution. */
1941 : :
1942 : : static void
1943 : 4518845 : free_var_substitution_info (class scc_info *si)
1944 : : {
1945 : 4518845 : delete si;
1946 : 4518845 : free (graph->pointer_label);
1947 : 4518845 : free (graph->loc_label);
1948 : 4518845 : free (graph->pointed_by);
1949 : 4518845 : free (graph->points_to);
1950 : 4518845 : free (graph->eq_rep);
1951 : 4518845 : sbitmap_free (graph->direct_nodes);
1952 : 4518845 : delete pointer_equiv_class_table;
1953 : 4518845 : pointer_equiv_class_table = NULL;
1954 : 4518845 : delete location_equiv_class_table;
1955 : 4518845 : location_equiv_class_table = NULL;
1956 : 4518845 : obstack_free (&equiv_class_obstack, NULL);
1957 : 4518845 : bitmap_obstack_release (&iteration_obstack);
1958 : 4518845 : }
1959 : :
1960 : : /* Return an existing node that is equivalent to NODE, which has
1961 : : equivalence class LABEL, if one exists. Return NODE otherwise. */
1962 : :
1963 : : static unsigned int
1964 : 882676530 : find_equivalent_node (constraint_graph_t graph,
1965 : : unsigned int node, unsigned int label)
1966 : : {
1967 : : /* If the address version of this variable is unused, we can
1968 : : substitute it for anything else with the same label.
1969 : : Otherwise, we know the pointers are equivalent, but not the
1970 : : locations, and we can unite them later. */
1971 : :
1972 : 882676530 : if (!bitmap_bit_p (graph->address_taken, node))
1973 : : {
1974 : 686637727 : gcc_checking_assert (label < graph->size);
1975 : :
1976 : 686637727 : if (graph->eq_rep[label] != -1)
1977 : : {
1978 : : /* Unify the two variables since we know they are equivalent. */
1979 : 581509086 : if (unite (graph->eq_rep[label], node))
1980 : 68184091 : unify_nodes (graph, graph->eq_rep[label], node, false);
1981 : 581509086 : return graph->eq_rep[label];
1982 : : }
1983 : : else
1984 : : {
1985 : 105128641 : graph->eq_rep[label] = node;
1986 : 105128641 : graph->pe_rep[label] = node;
1987 : : }
1988 : : }
1989 : : else
1990 : : {
1991 : 196038803 : gcc_checking_assert (label < graph->size);
1992 : 196038803 : graph->pe[node] = label;
1993 : 196038803 : if (graph->pe_rep[label] == -1)
1994 : 21730347 : graph->pe_rep[label] = node;
1995 : : }
1996 : :
1997 : : return node;
1998 : : }
1999 : :
2000 : : /* Unite pointer equivalent but not location equivalent nodes in
2001 : : GRAPH. This may only be performed once variable substitution is
2002 : : finished. */
2003 : :
2004 : : static void
2005 : 4518845 : unite_pointer_equivalences (constraint_graph_t graph)
2006 : : {
2007 : 4518845 : unsigned int i;
2008 : :
2009 : : /* Go through the pointer equivalences and unite them to their
2010 : : representative, if they aren't already. */
2011 : 228722448 : for (i = 1; i < FIRST_REF_NODE; i++)
2012 : : {
2013 : 224203603 : unsigned int label = graph->pe[i];
2014 : 224203603 : if (label)
2015 : : {
2016 : 21826662 : int label_rep = graph->pe_rep[label];
2017 : :
2018 : 21826662 : if (label_rep == -1)
2019 : 0 : continue;
2020 : :
2021 : 21826662 : label_rep = find (label_rep);
2022 : 21826662 : if (label_rep >= 0 && unite (label_rep, find (i)))
2023 : 2357635 : unify_nodes (graph, label_rep, i, false);
2024 : : }
2025 : : }
2026 : 4518845 : }
2027 : :
2028 : : /* Move complex constraints to the GRAPH nodes they belong to. */
2029 : :
2030 : : static void
2031 : 4518845 : move_complex_constraints (constraint_graph_t graph)
2032 : : {
2033 : 4518845 : int i;
2034 : 4518845 : constraint_t c;
2035 : :
2036 : 448403212 : FOR_EACH_VEC_ELT (constraints, i, c)
2037 : : {
2038 : 443884367 : if (c)
2039 : : {
2040 : 441338265 : struct constraint_expr lhs = c->lhs;
2041 : 441338265 : struct constraint_expr rhs = c->rhs;
2042 : :
2043 : 441338265 : if (lhs.type == DEREF)
2044 : : {
2045 : 36489050 : insert_into_complex (graph, lhs.var, c);
2046 : : }
2047 : 404849215 : else if (rhs.type == DEREF)
2048 : : {
2049 : 49291085 : if (!(get_varinfo (lhs.var)->is_special_var))
2050 : 49291079 : insert_into_complex (graph, rhs.var, c);
2051 : : }
2052 : 355558130 : else if (rhs.type != ADDRESSOF && lhs.var > anything_id
2053 : 264760549 : && (lhs.offset != 0 || rhs.offset != 0))
2054 : : {
2055 : 60711173 : insert_into_complex (graph, rhs.var, c);
2056 : : }
2057 : : }
2058 : : }
2059 : 4518845 : }
2060 : :
2061 : : /* Optimize and rewrite complex constraints while performing
2062 : : collapsing of equivalent nodes. SI is the SCC_INFO that is the
2063 : : result of perform_variable_substitution. */
2064 : :
2065 : : static void
2066 : 4518845 : rewrite_constraints (constraint_graph_t graph,
2067 : : class scc_info *si)
2068 : : {
2069 : 4518845 : int i;
2070 : 4518845 : constraint_t c;
2071 : :
2072 : 4518845 : if (flag_checking)
2073 : : {
2074 : 461960599 : for (unsigned int j = 0; j < graph->size; j++)
2075 : 457441814 : gcc_assert (find (j) == j);
2076 : : }
2077 : :
2078 : 448403212 : FOR_EACH_VEC_ELT (constraints, i, c)
2079 : : {
2080 : 443884367 : struct constraint_expr lhs = c->lhs;
2081 : 443884367 : struct constraint_expr rhs = c->rhs;
2082 : 443884367 : unsigned int lhsvar = find (lhs.var);
2083 : 443884367 : unsigned int rhsvar = find (rhs.var);
2084 : 443884367 : unsigned int lhsnode, rhsnode;
2085 : 443884367 : unsigned int lhslabel, rhslabel;
2086 : :
2087 : 443884367 : lhsnode = si->node_mapping[lhsvar];
2088 : 443884367 : rhsnode = si->node_mapping[rhsvar];
2089 : 443884367 : lhslabel = graph->pointer_label[lhsnode];
2090 : 443884367 : rhslabel = graph->pointer_label[rhsnode];
2091 : :
2092 : : /* See if it is really a non-pointer variable, and if so, ignore
2093 : : the constraint. */
2094 : 443884367 : if (lhslabel == 0)
2095 : : {
2096 : 783903 : if (dump_file && (dump_flags & TDF_DETAILS))
2097 : : {
2098 : :
2099 : 44 : fprintf (dump_file, "%s is a non-pointer variable, "
2100 : : "ignoring constraint:",
2101 : 22 : get_varinfo (lhs.var)->name);
2102 : 22 : dump_constraint (dump_file, c);
2103 : 22 : fprintf (dump_file, "\n");
2104 : : }
2105 : 783903 : constraints[i] = NULL;
2106 : 2546102 : continue;
2107 : : }
2108 : :
2109 : 443100464 : if (rhslabel == 0)
2110 : : {
2111 : 1762199 : if (dump_file && (dump_flags & TDF_DETAILS))
2112 : : {
2113 : :
2114 : 72 : fprintf (dump_file, "%s is a non-pointer variable, "
2115 : : "ignoring constraint:",
2116 : 36 : get_varinfo (rhs.var)->name);
2117 : 36 : dump_constraint (dump_file, c);
2118 : 36 : fprintf (dump_file, "\n");
2119 : : }
2120 : 1762199 : constraints[i] = NULL;
2121 : 1762199 : continue;
2122 : : }
2123 : :
2124 : 441338265 : lhsvar = find_equivalent_node (graph, lhsvar, lhslabel);
2125 : 441338265 : rhsvar = find_equivalent_node (graph, rhsvar, rhslabel);
2126 : 441338265 : c->lhs.var = lhsvar;
2127 : 441338265 : c->rhs.var = rhsvar;
2128 : : }
2129 : 4518845 : }
2130 : :
2131 : : /* Eliminate indirect cycles involving NODE. Return true if NODE was
2132 : : part of an SCC, false otherwise. */
2133 : :
2134 : : static bool
2135 : 389502469 : eliminate_indirect_cycles (unsigned int node)
2136 : : {
2137 : 389502469 : if (graph->indirect_cycles[node] != -1
2138 : 389839030 : && !bitmap_empty_p (get_varinfo (node)->solution))
2139 : : {
2140 : 303547 : unsigned int i;
2141 : 303547 : auto_vec<unsigned> queue;
2142 : 303547 : int queuepos;
2143 : 303547 : unsigned int to = find (graph->indirect_cycles[node]);
2144 : 303547 : bitmap_iterator bi;
2145 : :
2146 : : /* We can't touch the solution set and call unify_nodes
2147 : : at the same time, because unify_nodes is going to do
2148 : : bitmap unions into it. */
2149 : :
2150 : 1620090 : EXECUTE_IF_SET_IN_BITMAP (get_varinfo (node)->solution, 0, i, bi)
2151 : : {
2152 : 1316543 : if (find (i) == i && i != to)
2153 : : {
2154 : 345470 : if (unite (to, i))
2155 : 345470 : queue.safe_push (i);
2156 : : }
2157 : : }
2158 : :
2159 : 345470 : for (queuepos = 0;
2160 : 649017 : queue.iterate (queuepos, &i);
2161 : : queuepos++)
2162 : : {
2163 : 345470 : unify_nodes (graph, to, i, true);
2164 : : }
2165 : 303547 : return true;
2166 : 303547 : }
2167 : : return false;
2168 : : }
2169 : :
2170 : : /* Solve the constraint graph GRAPH using our worklist solver.
2171 : : This is based on the PW* family of solvers from the "Efficient Field
2172 : : Sensitive Pointer Analysis for C" paper.
2173 : : It works by iterating over all the graph nodes, processing the complex
2174 : : constraints and propagating the copy constraints, until everything stops
2175 : : changed. This corresponds to steps 6-8 in the solving list given above. */
2176 : :
2177 : : static void
2178 : 4518845 : solve_graph (constraint_graph_t graph)
2179 : : {
2180 : 4518845 : unsigned int size = graph->size;
2181 : 4518845 : unsigned int i;
2182 : 4518845 : bitmap pts;
2183 : :
2184 : 4518845 : changed = BITMAP_ALLOC (NULL);
2185 : :
2186 : : /* Mark all initial non-collapsed nodes as changed. */
2187 : 228722448 : for (i = 1; i < size; i++)
2188 : : {
2189 : 224203603 : varinfo_t ivi = get_varinfo (i);
2190 : 377846464 : if (find (i) == i && !bitmap_empty_p (ivi->solution)
2191 : 277441519 : && ((graph->succs[i] && !bitmap_empty_p (graph->succs[i]))
2192 : 232026913 : || graph->complex[i].length () > 0))
2193 : 33841647 : bitmap_set_bit (changed, i);
2194 : : }
2195 : :
2196 : : /* Allocate a bitmap to be used to store the changed bits. */
2197 : 4518845 : pts = BITMAP_ALLOC (&pta_obstack);
2198 : :
2199 : 17032386 : while (!bitmap_empty_p (changed))
2200 : : {
2201 : 7994696 : unsigned int i;
2202 : 7994696 : stats.iterations++;
2203 : :
2204 : 7994696 : bitmap_obstack_initialize (&iteration_obstack);
2205 : :
2206 : 7994696 : auto_vec<unsigned> topo_order = compute_topo_order (graph);
2207 : 405806618 : while (topo_order.length () != 0)
2208 : : {
2209 : 389817226 : i = topo_order.pop ();
2210 : :
2211 : : /* If this variable is not a representative, skip it. */
2212 : 389817226 : if (find (i) != i)
2213 : 314757 : continue;
2214 : :
2215 : : /* In certain indirect cycle cases, we may merge this
2216 : : variable to another. */
2217 : 389502469 : if (eliminate_indirect_cycles (i) && find (i) != i)
2218 : 50 : continue;
2219 : :
2220 : : /* If the node has changed, we need to process the
2221 : : complex constraints and outgoing edges again. For complex
2222 : : constraints that modify i itself, like the common group of
2223 : : callarg = callarg + UNKNOWN;
2224 : : callarg = *callarg + UNKNOWN;
2225 : : *callarg = callescape;
2226 : : make sure to iterate immediately because that maximizes
2227 : : cache reuse and expands the graph quickest, leading to
2228 : : better visitation order in the next iteration. */
2229 : 533340099 : while (bitmap_clear_bit (changed, i))
2230 : : {
2231 : 144142494 : bitmap solution;
2232 : 144142494 : vec<constraint_t> &complex = graph->complex[i];
2233 : 144142494 : varinfo_t vi = get_varinfo (i);
2234 : 144142494 : bool solution_empty;
2235 : :
2236 : : /* Compute the changed set of solution bits. If anything
2237 : : is in the solution just propagate that. */
2238 : 144142494 : if (bitmap_bit_p (vi->solution, anything_id))
2239 : : {
2240 : : /* If anything is also in the old solution there is
2241 : : nothing to do.
2242 : : ??? But we shouldn't ended up with "changed" set ... */
2243 : 2746856 : if (vi->oldsolution
2244 : 2746856 : && bitmap_bit_p (vi->oldsolution, anything_id))
2245 : : break;
2246 : 2442042 : bitmap_copy (pts, get_varinfo (find (anything_id))->solution);
2247 : : }
2248 : 141395638 : else if (vi->oldsolution)
2249 : 36786143 : bitmap_and_compl (pts, vi->solution, vi->oldsolution);
2250 : : else
2251 : 104609495 : bitmap_copy (pts, vi->solution);
2252 : :
2253 : 143837680 : if (bitmap_empty_p (pts))
2254 : : break;
2255 : :
2256 : 143837680 : if (vi->oldsolution)
2257 : 37985489 : bitmap_ior_into (vi->oldsolution, pts);
2258 : : else
2259 : : {
2260 : 105852191 : vi->oldsolution = BITMAP_ALLOC (&oldpta_obstack);
2261 : 105852191 : bitmap_copy (vi->oldsolution, pts);
2262 : : }
2263 : :
2264 : 143837680 : solution = vi->solution;
2265 : 143837680 : solution_empty = bitmap_empty_p (solution);
2266 : :
2267 : : /* Process the complex constraints. */
2268 : 143837680 : hash_set<constraint_t> *cvisited = nullptr;
2269 : 143837680 : if (flag_checking)
2270 : 143836995 : cvisited = new hash_set<constraint_t>;
2271 : 143837680 : bitmap expanded_pts = NULL;
2272 : 356343239 : for (unsigned j = 0; j < complex.length (); ++j)
2273 : : {
2274 : 212505559 : constraint_t c = complex[j];
2275 : : /* At unification time only the directly involved nodes
2276 : : will get their complex constraints updated. Update
2277 : : our complex constraints now but keep the constraint
2278 : : vector sorted and clear of duplicates. Also make
2279 : : sure to evaluate each prevailing constraint only once. */
2280 : 212505559 : unsigned int new_lhs = find (c->lhs.var);
2281 : 212505559 : unsigned int new_rhs = find (c->rhs.var);
2282 : 212505559 : if (c->lhs.var != new_lhs || c->rhs.var != new_rhs)
2283 : : {
2284 : 1626005 : constraint tem = *c;
2285 : 1626005 : tem.lhs.var = new_lhs;
2286 : 1626005 : tem.rhs.var = new_rhs;
2287 : 1626005 : unsigned int place
2288 : 1626005 : = complex.lower_bound (&tem, constraint_less);
2289 : 1626005 : c->lhs.var = new_lhs;
2290 : 1626005 : c->rhs.var = new_rhs;
2291 : 1626005 : if (place != j)
2292 : : {
2293 : 1613585 : complex.ordered_remove (j);
2294 : 1613585 : if (j < place)
2295 : 1595399 : --place;
2296 : 1613585 : if (place < complex.length ())
2297 : : {
2298 : 399625 : if (constraint_equal (*complex[place], *c))
2299 : : {
2300 : 36560 : j--;
2301 : 304086 : continue;
2302 : : }
2303 : : else
2304 : 363065 : complex.safe_insert (place, c);
2305 : : }
2306 : : else
2307 : 1213960 : complex.quick_push (c);
2308 : 1577025 : if (place > j)
2309 : : {
2310 : 267526 : j--;
2311 : 267526 : continue;
2312 : : }
2313 : : }
2314 : : }
2315 : :
2316 : : /* The only complex constraint that can change our
2317 : : solution to non-empty, given an empty solution,
2318 : : is a constraint where the lhs side is receiving
2319 : : some set from elsewhere. */
2320 : 212201473 : if (cvisited && cvisited->add (c))
2321 : 0 : gcc_unreachable ();
2322 : 212201473 : if (!solution_empty || c->lhs.type != DEREF)
2323 : 212201473 : do_complex_constraint (graph, c, pts, &expanded_pts);
2324 : : }
2325 : 143837680 : if (cvisited)
2326 : : {
2327 : : /* When checking, verify the order of constraints is
2328 : : maintained and each constraint is evaluated exactly
2329 : : once. */
2330 : 274139900 : for (unsigned j = 1; j < complex.length (); ++j)
2331 : 130302905 : gcc_assert (constraint_less (complex[j-1], complex[j]));
2332 : 225734503 : gcc_assert (cvisited->elements () == complex.length ());
2333 : 143836995 : delete cvisited;
2334 : : }
2335 : 143837680 : BITMAP_FREE (expanded_pts);
2336 : :
2337 : 143837680 : solution_empty = bitmap_empty_p (solution);
2338 : :
2339 : 143837680 : if (!solution_empty)
2340 : : {
2341 : 143837680 : bitmap_iterator bi;
2342 : 143837680 : unsigned eff_escaped_id = find (escaped_id);
2343 : 143837680 : unsigned j;
2344 : :
2345 : : /* Propagate solution to all successors. */
2346 : 143837680 : unsigned to_remove = ~0U;
2347 : 364180790 : EXECUTE_IF_IN_NONNULL_BITMAP (graph->succs[i],
2348 : : 0, j, bi)
2349 : : {
2350 : 220343110 : if (to_remove != ~0U)
2351 : : {
2352 : 2314805 : bitmap_clear_bit (graph->succs[i], to_remove);
2353 : 2314805 : to_remove = ~0U;
2354 : : }
2355 : 220343110 : unsigned int to = find (j);
2356 : 220343110 : if (to != j)
2357 : : {
2358 : : /* Update the succ graph, avoiding duplicate
2359 : : work. */
2360 : 2282393 : to_remove = j;
2361 : 2282393 : if (! bitmap_set_bit (graph->succs[i], to))
2362 : 917927 : continue;
2363 : : /* We eventually end up processing 'to' twice
2364 : : as it is undefined whether bitmap iteration
2365 : : iterates over bits set during iteration.
2366 : : Play safe instead of doing tricks. */
2367 : : }
2368 : : /* Don't try to propagate to ourselves. */
2369 : 219425183 : if (to == i)
2370 : : {
2371 : 175475 : to_remove = j;
2372 : 175475 : continue;
2373 : : }
2374 : : /* Early node unification can lead to edges from
2375 : : escaped - remove them. */
2376 : 219249708 : if (i == eff_escaped_id)
2377 : : {
2378 : 175575 : to_remove = j;
2379 : 175575 : if (bitmap_set_bit (get_varinfo (to)->solution,
2380 : : escaped_id))
2381 : 96741 : bitmap_set_bit (changed, to);
2382 : 175575 : continue;
2383 : : }
2384 : :
2385 : 219074133 : if (bitmap_ior_into (get_varinfo (to)->solution, pts))
2386 : 97476369 : bitmap_set_bit (changed, to);
2387 : : }
2388 : 100987698 : if (to_remove != ~0U)
2389 : 217302 : bitmap_clear_bit (graph->succs[i], to_remove);
2390 : : }
2391 : : }
2392 : : }
2393 : 7994696 : bitmap_obstack_release (&iteration_obstack);
2394 : 7994696 : }
2395 : :
2396 : 4518845 : BITMAP_FREE (pts);
2397 : 4518845 : BITMAP_FREE (changed);
2398 : 4518845 : bitmap_obstack_release (&oldpta_obstack);
2399 : 4518845 : }
2400 : :
2401 : : void
2402 : 4518845 : delete_graph (void)
2403 : : {
2404 : 4518845 : unsigned int i;
2405 : 233241293 : for (i = 0; i < graph->size; i++)
2406 : 228722448 : graph->complex[i].release ();
2407 : 4518845 : free (graph->complex);
2408 : :
2409 : 4518845 : free (graph->succs);
2410 : 4518845 : free (graph->pe);
2411 : 4518845 : free (graph->pe_rep);
2412 : 4518845 : free (graph->indirect_cycles);
2413 : : /* We are not doing free (graph->rep) since the representatives mapping is
2414 : : needed outside of the solver too. */
2415 : 4518845 : free (graph);
2416 : 4518845 : }
2417 : :
2418 : : /* Remove the REF and ADDRESS edges from GRAPH, as well as all the
2419 : : predecessor edges. */
2420 : :
2421 : : static void
2422 : 4518845 : remove_preds_and_fake_succs (constraint_graph_t graph)
2423 : : {
2424 : 4518845 : unsigned int i;
2425 : :
2426 : : /* Clear the implicit ref and address nodes from the successor
2427 : : lists. */
2428 : 228722448 : for (i = 1; i < FIRST_REF_NODE; i++)
2429 : : {
2430 : 224203603 : if (graph->succs[i])
2431 : 65771113 : bitmap_clear_range (graph->succs[i], FIRST_REF_NODE,
2432 : 65771113 : FIRST_REF_NODE * 2);
2433 : : }
2434 : :
2435 : : /* Free the successor list for the non-ref nodes. */
2436 : 233241293 : for (i = FIRST_REF_NODE + 1; i < graph->size; i++)
2437 : : {
2438 : 224203603 : if (graph->succs[i])
2439 : 12022098 : BITMAP_FREE (graph->succs[i]);
2440 : : }
2441 : :
2442 : : /* Now reallocate the size of the successor list as, and blow away
2443 : : the predecessor bitmaps. */
2444 : 4518845 : graph->size = varmap.length ();
2445 : 4518845 : graph->succs = XRESIZEVEC (bitmap, graph->succs, graph->size);
2446 : :
2447 : 4518845 : free (graph->implicit_preds);
2448 : 4518845 : graph->implicit_preds = NULL;
2449 : 4518845 : free (graph->preds);
2450 : 4518845 : graph->preds = NULL;
2451 : 4518845 : bitmap_obstack_release (&predbitmap_obstack);
2452 : 4518845 : }
2453 : :
2454 : : namespace pointer_analysis {
2455 : :
2456 : : /* Solve the constraint set. The entry function of the solver. */
2457 : :
2458 : : void
2459 : 4518845 : solve_constraints (void)
2460 : : {
2461 : 4518845 : class scc_info *si;
2462 : :
2463 : : /* Sort varinfos so that ones that cannot be pointed to are last.
2464 : : This makes bitmaps more efficient. */
2465 : 4518845 : unsigned int *map = XNEWVEC (unsigned int, varmap.length ());
2466 : 45188450 : for (unsigned i = 0; i < integer_id + 1; ++i)
2467 : 40669605 : map[i] = i;
2468 : : /* Start with address-taken vars, followed by not address-taken vars
2469 : : to move vars never appearing in the points-to solution bitmaps last. */
2470 : : unsigned j = integer_id + 1;
2471 : 385143376 : for (unsigned i = integer_id + 1; i < varmap.length (); ++i)
2472 : 188052843 : if (varmap[varmap[i]->head]->address_taken)
2473 : 15269660 : map[i] = j++;
2474 : 192571688 : for (unsigned i = integer_id + 1; i < varmap.length (); ++i)
2475 : 188052843 : if (! varmap[varmap[i]->head]->address_taken)
2476 : 172783183 : map[i] = j++;
2477 : : /* Shuffle varmap according to map. */
2478 : 192571688 : for (unsigned i = integer_id + 1; i < varmap.length (); ++i)
2479 : : {
2480 : 278189822 : while (map[varmap[i]->id] != i)
2481 : 90136979 : std::swap (varmap[i], varmap[map[varmap[i]->id]]);
2482 : 188052843 : gcc_assert (bitmap_empty_p (varmap[i]->solution));
2483 : 188052843 : varmap[i]->id = i;
2484 : 188052843 : varmap[i]->next = map[varmap[i]->next];
2485 : 188052843 : varmap[i]->head = map[varmap[i]->head];
2486 : : }
2487 : : /* Finally rewrite constraints. */
2488 : 448403212 : for (unsigned i = 0; i < constraints.length (); ++i)
2489 : : {
2490 : 443884367 : constraints[i]->lhs.var = map[constraints[i]->lhs.var];
2491 : 443884367 : constraints[i]->rhs.var = map[constraints[i]->rhs.var];
2492 : : }
2493 : 4518845 : free (map);
2494 : :
2495 : 4518845 : if (dump_file)
2496 : 480 : fprintf (dump_file,
2497 : : "\nCollapsing static cycles and doing variable "
2498 : : "substitution\n");
2499 : :
2500 : 9037690 : init_graph (varmap.length () * 2);
2501 : :
2502 : 4518845 : if (dump_file)
2503 : 480 : fprintf (dump_file, "Building predecessor graph\n");
2504 : 4518845 : build_pred_graph ();
2505 : :
2506 : 4518845 : if (dump_file)
2507 : 480 : fprintf (dump_file, "Detecting pointer and location "
2508 : : "equivalences\n");
2509 : 4518845 : si = perform_var_substitution (graph);
2510 : :
2511 : 4518845 : if (dump_file)
2512 : 480 : fprintf (dump_file, "Rewriting constraints and unifying "
2513 : : "variables\n");
2514 : 4518845 : rewrite_constraints (graph, si);
2515 : :
2516 : 4518845 : build_succ_graph ();
2517 : :
2518 : 4518845 : free_var_substitution_info (si);
2519 : :
2520 : : /* Attach complex constraints to graph nodes. */
2521 : 4518845 : move_complex_constraints (graph);
2522 : :
2523 : 4518845 : if (dump_file)
2524 : 480 : fprintf (dump_file, "Uniting pointer but not location equivalent "
2525 : : "variables\n");
2526 : 4518845 : unite_pointer_equivalences (graph);
2527 : :
2528 : 4518845 : if (dump_file)
2529 : 480 : fprintf (dump_file, "Finding indirect cycles\n");
2530 : 4518845 : find_indirect_cycles (graph);
2531 : :
2532 : : /* Implicit nodes and predecessors are no longer necessary at this
2533 : : point. */
2534 : 4518845 : remove_preds_and_fake_succs (graph);
2535 : :
2536 : 4518845 : if (dump_file && (dump_flags & TDF_GRAPH))
2537 : : {
2538 : 3 : fprintf (dump_file, "\n\n// The constraint graph before solve-graph "
2539 : : "in dot format:\n");
2540 : 3 : dump_constraint_graph (dump_file);
2541 : 3 : fprintf (dump_file, "\n\n");
2542 : : }
2543 : :
2544 : 4518845 : if (dump_file)
2545 : 480 : fprintf (dump_file, "Solving graph\n");
2546 : :
2547 : 4518845 : solve_graph (graph);
2548 : :
2549 : 4518845 : if (dump_file && (dump_flags & TDF_GRAPH))
2550 : : {
2551 : 3 : fprintf (dump_file, "\n\n// The constraint graph after solve-graph "
2552 : : "in dot format:\n");
2553 : 3 : dump_constraint_graph (dump_file);
2554 : 3 : fprintf (dump_file, "\n\n");
2555 : : }
2556 : :
2557 : : /* The mapping node -> representative is one of the outputs of the
2558 : : solver. */
2559 : 4518845 : union_find_compress_all ();
2560 : 4518845 : var_rep = graph->rep;
2561 : :
2562 : 4518845 : delete_graph ();
2563 : 4518845 : }
2564 : :
2565 : : } // namespace pointer_analysis
|