1 /* Tree based Andersen points-to analysis
2 Copyright (C) 2002, 2003 Free Software Foundation, Inc.
3 Contributed by Daniel Berlin <dberlin@dberlin.org>
5 This file is part of GCC.
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 2 of the License, or
10 (at your option) any later version.
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.
17 You should have received a copy of the GNU General Public License
18 along with GCC; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 #include "coretypes.h"
29 #include "tree-alias-type.h"
30 #include "tree-alias-ander.h"
34 #include "hard-reg-set.h"
35 #include "basic-block.h"
39 #include "diagnostic.h"
41 #include "tree-flow.h"
42 #include "tree-inline.h"
44 #include "tree-gimple.h"
45 #include "splay-tree.h"
46 #include "engine/util.h"
47 #include "libcompat/regions.h"
48 #include "andersen_terms.h"
50 #include "tree-pass.h"
53 /* Andersen's interprocedural points-to analysis.
54 This is a flow-insensitive, context insensitive algorithm.
56 This file is an implementation of the alias_ops structure used by
57 tree-alias-common.c to drive PTA analysis.
59 All these functions do is generate constraints for and through
60 libbanshee. When we query for a points-to set, we ask libbanshee
61 to solve the constraints and give us the answer. The terms of the
62 constraints are the aterms, which are an opaque data structure
63 that stores libbanshee specific data for the constraints.
65 The constraints to be generated come from andersen's paper. By
66 constraint, we mean something like "the points-to set of A must be
67 a subset or equal to the points-to set of B" or "the points-to set
68 of A must include Q". In order to avoid having to write all the
69 constraints directly in the code, we use helper functions such as
70 pta_assignment, pta_rvalue, etc, that generate the necessary
71 constraint terms for us, making for much more readable code.
73 One could replace libbanshee with some other constraint solving
74 engine, and you'd simply have to replace the implementation of the
75 pta_* functions, and provide replacements for the aterm specific
76 functions (like making a list of aterms, printing the label of an
77 aterm). However, libbanshee is extremely fast, and extremely low
78 memory usage, so one would be hard pressed to do better than it
81 Understanding how constraint solving and what each constraint means is
82 beyond the scope of this documentation. See the libbanshee
83 documentation, and references therein for more enlightenment.
85 That said, our constraints inclusion constraints of set
86 expressions. Given the helper functions, the various inference
87 functions we implement should *look* relatively straightforward.
89 In order to save time during queries, we cache the resulting
90 points-to sets of each variable, rather than recalculate them
91 again and again. (libbanshee actually has it's own internal
92 caching, but the function call overhead for calling the solver is
93 non-trivial, given the number of queries).
95 Todo: Don't pass alias ops as first argument, just have a global
96 "current_alias_ops". */
98 static unsigned int id_num
= 1;
99 static region andersen_rgn
;
100 static void andersen_simple_assign (struct tree_alias_ops
*,
101 alias_var
, alias_var
);
102 static void andersen_addr_assign (struct tree_alias_ops
*,
103 alias_var
, alias_var
);
104 static void andersen_ptr_assign (struct tree_alias_ops
*,
105 alias_var
, alias_var
);
106 static void andersen_op_assign (struct tree_alias_ops
*,
107 alias_var
, varray_type
, tree
, bitmap
);
108 static void andersen_heap_assign (struct tree_alias_ops
*, alias_var
);
109 static void andersen_assign_ptr (struct tree_alias_ops
*,
110 alias_var
, alias_var
);
111 static void andersen_function_def (struct tree_alias_ops
*, alias_var
,
112 varray_type
, alias_var
);
113 static int andersen_function_call (struct tree_alias_ops
*, alias_var
,
114 alias_var
, varray_type
, bitmap
);
115 static void andersen_init (struct tree_alias_ops
*);
116 static int print_out_result (splay_tree_node
, void *);
117 static void andersen_cleanup (struct tree_alias_ops
*);
118 static bool andersen_may_alias (struct tree_alias_ops
*, alias_var
,
120 static bool andersen_same_points_to_set (struct tree_alias_ops
*,
121 alias_var
, alias_var
);
122 static bool andersen_empty_points_to_set (struct tree_alias_ops
*,
124 static alias_var
andersen_add_var (struct tree_alias_ops
*, tree
);
125 static alias_var
andersen_add_var_same (struct tree_alias_ops
*,
127 static bool pointer_destroying_op (tree
);
128 static aterm_list
get_ptset (alias_var
);
129 static splay_tree ptamap
;
132 static struct tree_alias_ops andersen_ops
= {
136 andersen_add_var_same
,
137 andersen_simple_assign
,
138 andersen_addr_assign
,
141 andersen_heap_assign
,
143 andersen_function_def
,
144 andersen_function_call
,
146 andersen_same_points_to_set
,
147 andersen_empty_points_to_set
,
149 0, /* Currently non-interprocedural */
150 1 /* Can do IP on all statics without help. */
152 struct tree_alias_ops
*andersen_alias_ops
= &andersen_ops
;
154 static void term_inclusion (aterm
, aterm
);
155 static void pta_init (void);
156 static void pta_reset (void);
157 static aterm
get_ref (aterm
);
158 static argterm
fun_rec_aterm (aterm_list
);
159 static aterm
pta_make_lam (const char *, aterm
, aterm_list
);
160 static aterm
pta_make_ref (const char *);
161 static aterm
pta_bottom (void);
162 static aterm
pta_join (aterm
, aterm
);
163 static aterm
pta_deref (aterm
);
164 static aterm
pta_rvalue (aterm
);
165 static aterm
pta_address (aterm
);
166 static void pta_assignment (aterm
, aterm
);
167 static aterm
pta_make_fun (const char *, aterm
, aterm_list
);
168 static aterm
pta_application (aterm
, aterm_list
);
170 typedef aterm contents_type
;
171 static contents_type
pta_get_contents (aterm
);
172 static void pr_ptset_aterm_elem (aterm
);
173 static void pta_pr_ptset (contents_type
);
175 /* Hook for debugging. This function is called instead of
176 aterm_inclusion, and lets us print the actual constraints as they
180 term_inclusion (aterm t1
, aterm t2
)
184 fprintf (dump_file
, "Constraint: ");
185 aterm_print (dump_file
, t1
);
186 fprintf (dump_file
, " <= ");
187 aterm_print (dump_file
, t2
);
188 fprintf (dump_file
, "\n");
191 aterm_inclusion (t1
, t2
);
194 /* Initialize libbanshee's constraint engine. */
199 andersen_terms_init ();
202 /* Reset libbanshee's constraint engine. We do this when we are done
203 using it, as it releases the memory libbanshee is using. */
208 andersen_terms_reset ();
214 struct ref_decon r_decon
;
215 r_decon
= ref_decon (t
);
222 /* Make a function record out of the arguments. */
225 fun_rec_aterm (aterm_list args
)
229 argterm rest
, result
;
230 aterm_list_scanner scan
;
232 char field_name
[512];
235 scratch
= newregion ();
236 map
= new_argterm_map (scratch
);
237 aterm_list_scan (args
, &scan
);
238 while (aterm_list_next (&scan
, &temp
))
240 snprintf (field_name
, 512, "%d", counter
++);
241 argterm_map_cons (argterm_make_field (field_name
, temp
), map
);
244 rest
= argterm_wild ();
245 /* rest = argterm_fresh(); */
247 /* safe since field_add makes a copy of the string*/
248 result
= argterm_row (map
, rest
);
250 deleteregion (scratch
);
257 pta_make_lam (const char *id
, aterm ret
, aterm_list args
)
259 return lam (label_term_constant (id
), fun_rec_aterm (args
), ret
);
262 /* Make a label reference to the given id. */
265 pta_make_ref (const char *id
)
268 aterm var
= aterm_fresh (id
);
270 label_term tag
= label_term_constant (id
);
272 return ref (tag
, var
, var
);
275 /* Return the empty set. */
280 return aterm_zero ();
283 /* Join two terms, such that anything in set t1 will also be in set
284 t2, and vice versa. */
287 pta_join (aterm t1
, aterm t2
)
290 region scratch_rgn
= newregion ();
291 aterm_list list
= new_aterm_list (scratch_rgn
);
293 aterm_list_cons (t1
, list
);
294 aterm_list_cons (t2
, list
);
297 result
= aterm_union (list
);
298 deleteregion (scratch_rgn
);
303 /* Generate the constraint for a dereference of term t1. */
308 return ref_proj2 (t1
);
311 /* Generate the constraint for t1 being an rvalue. */
314 pta_rvalue (aterm t1
)
316 return pta_deref (t1
);
319 /* Generate the constraint for taking the address of t1. */
322 pta_address (aterm t1
)
324 return ref (label_term_one (), aterm_one (), t1
);
327 /* Generate the constraint for assigning t2 to t1. */
330 pta_assignment (aterm t1
, aterm t2
)
332 term_inclusion (t1
, ref_pat1 (t2
));
335 /* Make a function from the given name, return value, and arguments. */
338 pta_make_fun (const char *name
, aterm ret
, aterm_list args
)
341 aterm_list_scanner scan
;
342 region scratch_rgn
= newregion ();
343 aterm_list arg_list
= new_aterm_list (scratch_rgn
);
345 aterm_list_scan (args
, &scan
);
347 while (aterm_list_next (&scan
, &temp
))
349 aterm_list_cons (get_ref (temp
), arg_list
);
352 return pta_make_lam (name
, get_ref (ret
), arg_list
);
355 /* Return the constraint for calling function T with arguments
359 pta_application (aterm t
, aterm_list actuals
)
361 argterm args
= fun_rec_aterm (actuals
);
363 term_inclusion (t
, lam_pat1 (args
));
364 return pta_address (lam_proj2 (t
));
367 /* Return the contents of set expression T. */
370 pta_get_contents (aterm t
)
372 struct ref_decon t_decon
;
373 t_decon
= ref_decon (t
);
378 /* Print out a points-to set element. */
381 pr_ptset_aterm_elem (aterm t
)
383 struct ref_decon ref
;
384 struct lam_decon lam
;
389 fprintf (dump_file
, ",");
391 label_term_print (dump_file
, ref
.f0
);
393 label_term_print (dump_file
, lam
.f0
);
397 /* Print out a points-to set. */
400 pta_pr_ptset (contents_type t
)
405 scratch_rgn
= newregion ();
406 ptset
= aterm_list_copy (scratch_rgn
, aterm_tlb (t
));
408 size
= aterm_list_length (ptset
);
410 fprintf (dump_file
, "{");
411 if (!aterm_list_empty (ptset
))
413 struct ref_decon ref
;
414 struct lam_decon lam
;
415 ref
= ref_decon (aterm_list_head (ptset
));
416 lam
= lam_decon (aterm_list_head (ptset
));
418 label_term_print (dump_file
, ref
.f0
);
420 label_term_print (dump_file
, lam
.f0
);
422 /* aterm_pr(stdout,aterm_hd(ptset)); */
423 ptset
= aterm_list_tail (ptset
);
425 aterm_list_app (ptset
, pr_ptset_aterm_elem
);
426 fprintf (dump_file
, "}(%d)\n", size
);
427 deleteregion (scratch_rgn
);
430 /* Initialize Andersen alias analysis. */
431 static int initted
= 0;
434 andersen_init (struct tree_alias_ops
*ops ATTRIBUTE_UNUSED
)
437 /* Don't claim we can do ip partial unless we have unit_at_a_time on. */
438 if (!flag_unit_at_a_time
)
440 andersen_ops
.ip_partial
= 0;
441 if (!initted
|| (!andersen_ops
.ip_partial
&& !andersen_ops
.ip
))
444 andersen_rgn
= newregion ();
448 ptamap
= splay_tree_new (splay_tree_compare_pointers
, NULL
, NULL
);
453 print_out_result (splay_tree_node node
, void *data ATTRIBUTE_UNUSED
)
455 fprintf (dump_file
, "%s :=",
456 alias_get_name (ALIAS_VAR_DECL (((alias_var
) node
->value
))));
457 pta_pr_ptset (pta_get_contents ((aterm
) node
->key
));
461 /* Cleanup after Andersen alias analysis. */
464 andersen_cleanup (struct tree_alias_ops
*ops ATTRIBUTE_UNUSED
)
468 if (dump_flags
& TDF_STATS
)
470 fprintf (dump_file
, "\nPoints-to stats:\n");
471 andersen_terms_stats (dump_file
);
474 fprintf (dump_file
, "\nPoints-to sets:\n");
475 splay_tree_foreach (ptamap
, print_out_result
, NULL
);
478 splay_tree_delete (ptamap
);
480 if (!andersen_ops
.ip_partial
&& !andersen_ops
.ip
)
483 deleteregion (andersen_rgn
);
488 /* Add decl to the analyzer, and return a var for it. For
489 Andersen, we create a new alias var for the declaration, and
493 andersen_add_var (struct tree_alias_ops
*ops ATTRIBUTE_UNUSED
, tree decl
)
496 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
497 fprintf (dump_file
, "Adding variable %s\n",
498 alias_get_name (decl
));
500 if (alias_get_name (decl
) != NULL
)
502 ret
= alias_var_new_with_aterm (decl
,
503 pta_make_ref (alias_get_name (decl
)));
508 ASM_FORMAT_PRIVATE_NAME (tmp_name
, "unnamed var", id_num
++);
509 ret
= alias_var_new_with_aterm (decl
, pta_make_ref (tmp_name
));
511 splay_tree_insert (ptamap
, (splay_tree_key
) ALIAS_VAR_ATERM (ret
),
512 (splay_tree_value
) ret
);
513 ALIAS_VAR_PTSET (ret
) = NULL
;
518 /* Add a variable to the analyzer that is equivalent (as far as
519 aliases go) to some existing alias variable.
520 For Andersen, we just call a function that does this for us. */
523 andersen_add_var_same (struct tree_alias_ops
*ops ATTRIBUTE_UNUSED
, tree decl
,
528 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
529 fprintf (dump_file
, "Adding variable %s same as %s\n",
530 alias_get_name (decl
), alias_get_name (ALIAS_VAR_DECL (tv
)));
532 if (alias_get_name (decl
) != NULL
)
533 ret
= alias_var_new_with_aterm (decl
,
534 pta_make_ref (alias_get_name (decl
)));
538 ASM_FORMAT_PRIVATE_NAME (tmp_name
, "unnamed var", id_num
++);
539 ret
= alias_var_new_with_aterm (decl
, pta_make_ref (tmp_name
));
542 pta_join (ALIAS_VAR_ATERM (tv
), ALIAS_VAR_ATERM (ret
));
543 splay_tree_insert (ptamap
, (splay_tree_key
) ALIAS_VAR_ATERM (ret
),
544 (splay_tree_value
) ret
);
545 ALIAS_VAR_PTSET (tv
) = NULL
;
546 ALIAS_VAR_PTSET (ret
) = NULL
;
551 /* Inference for simple assignment (lhs = rhs) */
554 andersen_simple_assign (struct tree_alias_ops
*ops ATTRIBUTE_UNUSED
,
555 alias_var lhs
, alias_var rhs
)
557 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
558 fprintf (dump_file
, "Simple assignment %s = %s\n",
559 alias_get_name (ALIAS_VAR_DECL (lhs
)),
560 alias_get_name (ALIAS_VAR_DECL (rhs
)));
564 /* The rvalue is just the term itself, and we generate a constraint
565 for assigning it to the lhs. */
566 pta_assignment (ALIAS_VAR_ATERM (lhs
),
567 pta_rvalue (ALIAS_VAR_ATERM (rhs
)));
570 /* Inference for address assignment (lhs = &addr) */
573 andersen_addr_assign (struct tree_alias_ops
*ops ATTRIBUTE_UNUSED
,
574 alias_var lhs
, alias_var addr
)
578 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
579 fprintf (dump_file
, "Address assignment %s = &%s\n",
580 alias_get_name (ALIAS_VAR_DECL (lhs
)),
581 alias_get_name (ALIAS_VAR_DECL (addr
)));
583 /* The rvalue here is the address of a term, and we generate a
584 constraint to assign this address to the lhs. */
585 pta_assignment (ALIAS_VAR_ATERM (lhs
),
586 pta_rvalue (pta_address (ALIAS_VAR_ATERM (addr
))));
590 /* Inference for pointer assignment (lhs = *ptr) */
593 andersen_ptr_assign (struct tree_alias_ops
*ops ATTRIBUTE_UNUSED
,
594 alias_var lhs
, alias_var ptr
)
599 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
600 fprintf (dump_file
, "Pointer assignment %s = *%s\n",
601 alias_get_name (ALIAS_VAR_DECL (lhs
)),
602 alias_get_name (ALIAS_VAR_DECL (ptr
)));
604 pta_assignment (ALIAS_VAR_ATERM (lhs
),
605 pta_rvalue (pta_deref (ALIAS_VAR_ATERM (ptr
))));
609 /* Determine if OP destroys the current assumed to be valid pointer
610 (whether it generates a new valid pointer is not relevant). */
613 pointer_destroying_op (tree op
)
615 switch (TREE_CODE (op
))
639 /* Inference rule for operations (lhs = operation(operands)). */
642 andersen_op_assign (struct tree_alias_ops
*ops ATTRIBUTE_UNUSED
,
643 alias_var lhs
, varray_type operands
, tree operation
,
648 if (VARRAY_ACTIVE_SIZE (operands
) == 0)
651 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
653 fprintf (dump_file
, "Op assignment %s = ",
654 alias_get_name (ALIAS_VAR_DECL (lhs
)));
655 print_generic_stmt (dump_file
, operation
, dump_flags
);
656 fprintf (dump_file
, "\n");
660 /* Pointer destroying operations do not give us the same valid pointer
661 back, and thus, are assignment to pta_bottom. */
662 if (pointer_destroying_op (operation
))
664 pta_assignment (ALIAS_VAR_ATERM (lhs
), pta_rvalue (pta_bottom ()));
668 /* Operations in general we can't track the exact effect of. Thus,
669 we conservatively assume that it could make the LHS point to
670 *anything* the RHS points to. To signify this, we join the RHS
671 variables together and assign it to the LHS. */
672 /* The >2 case occurs when we are dealing with constructors. */
673 if (VARRAY_ACTIVE_SIZE (operands
) > 2)
676 alias_var tv1
= VARRAY_GENERIC_PTR (operands
, 0);
677 newvar
= ALIAS_VAR_ATERM (tv1
);
678 for (i
= 1; i
< VARRAY_ACTIVE_SIZE (operands
); i
++)
680 alias_var tempvar
= VARRAY_GENERIC_PTR (operands
, i
);
681 aterm t2
= ALIAS_VAR_ATERM (tempvar
);
682 if (bitmap_bit_p (addrargs
, i
))
683 newvar
= pta_join (newvar
, pta_address (t2
));
685 newvar
= pta_join (newvar
, t2
);
688 else if (VARRAY_ACTIVE_SIZE (operands
) == 2)
690 alias_var tv1
= VARRAY_GENERIC_PTR (operands
, 0);
691 alias_var tv2
= VARRAY_GENERIC_PTR (operands
, 1);
692 aterm t1
= ALIAS_VAR_ATERM (tv1
);
693 aterm t2
= ALIAS_VAR_ATERM (tv2
);
694 if (bitmap_bit_p (addrargs
, 0) && bitmap_bit_p (addrargs
, 1))
695 newvar
= pta_join (pta_address (t1
), pta_address (t2
));
696 else if (bitmap_bit_p (addrargs
, 0))
697 newvar
= pta_join (pta_address (t1
), t2
);
698 else if (bitmap_bit_p (addrargs
, 1))
699 newvar
= pta_join (t1
, pta_address (t2
));
701 newvar
= pta_join (t1
, t2
);
703 else if (VARRAY_ACTIVE_SIZE (operands
) == 1)
705 alias_var tv1
= VARRAY_GENERIC_PTR (operands
, 0);
706 aterm t1
= ALIAS_VAR_ATERM (tv1
);
707 if (bitmap_bit_p (addrargs
, 0))
708 newvar
= pta_address (t1
);
712 pta_assignment (ALIAS_VAR_ATERM (lhs
), pta_rvalue (newvar
));
715 /* Inference for heap assignment (lhs = alloc). */
718 andersen_heap_assign (struct tree_alias_ops
*ops ATTRIBUTE_UNUSED
,
719 alias_var lhs ATTRIBUTE_UNUSED
)
724 type1
= ECR_get_type (alias_var_get_ECR (lhs
));
725 tau
= alias_ltype_loc (type1
);
727 if (ECR_get_type (tau
) == alias_bottom
)
728 ECR_set_type (tau
, alias_ltype_new ());
732 /* Inference for assignment to a pointer (*ptr = rhs). */
735 andersen_assign_ptr (struct tree_alias_ops
*ops ATTRIBUTE_UNUSED
,
736 alias_var ptr
, alias_var rhs
)
741 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
742 fprintf (dump_file
, "Assignment to pointer *%s = %s\n",
743 alias_get_name (ALIAS_VAR_DECL (ptr
)),
744 alias_get_name (ALIAS_VAR_DECL (rhs
)));
745 /* The RHS is a standard rvalue, and the LHS is a pointer
747 pta_assignment (pta_deref (ALIAS_VAR_ATERM (ptr
)),
748 pta_rvalue (ALIAS_VAR_ATERM (rhs
)));
751 /* Inference for a function definition. */
754 andersen_function_def (struct tree_alias_ops
*ops ATTRIBUTE_UNUSED
,
755 alias_var func
, varray_type params
,
758 aterm_list args
= new_aterm_list (andersen_rgn
);
761 size_t l
= VARRAY_ACTIVE_SIZE (params
);
764 /* Set up the arguments for the new function type. */
765 for (i
= 0; i
< l
; i
++)
767 alias_var tv
= VARRAY_GENERIC_PTR (params
, i
);
768 aterm_list_cons (ALIAS_VAR_ATERM (tv
), args
);
770 /* Create the function type. */
771 fun_type
= pta_make_fun (alias_get_name (ALIAS_VAR_DECL (func
)),
772 ALIAS_VAR_ATERM (retval
), args
);
774 /* Assign the function type itself to the function. */
775 pta_assignment (ALIAS_VAR_ATERM (func
), fun_type
);
778 /* Inference for a function call assignment. */
781 andersen_function_call (struct tree_alias_ops
*ops
,
782 alias_var lhs
, alias_var func
,
783 varray_type args
, bitmap addrargs
)
785 aterm_list actuals
= new_aterm_list (andersen_rgn
);
786 aterm ftype
= ALIAS_VAR_ATERM (func
);
789 tree decl
= ALIAS_VAR_DECL (func
);
794 ret
= ALIAS_VAR_ATERM (lhs
);
795 for (i
= 0; i
< VARRAY_ACTIVE_SIZE (args
); i
++)
797 alias_var argtv
= VARRAY_GENERIC_PTR (args
, i
);
798 aterm arg
= ALIAS_VAR_ATERM (argtv
);
799 if (bitmap_bit_p (addrargs
, i
))
800 aterm_list_cons (pta_rvalue (pta_address (arg
)), actuals
);
802 aterm_list_cons (pta_rvalue (arg
), actuals
);
804 aterm_list_reverse (actuals
);
806 /* Generate the constraint that calls the function with it's
807 arguments, and gives us the result. This in turn applies
808 whatever constraints are in that function. */
809 res
= pta_application (pta_rvalue (ftype
), actuals
);
810 /* We only need care about the result if we have an LHS. If we do,
811 assign the result of function application back to the LHS. */
813 pta_assignment (ret
, pta_rvalue (res
));
815 /* We can handle functions we've got trees for. non-statics will
816 just have incoming parameters assigned to global_var if
818 if (TREE_CODE (decl
) == FUNCTION_DECL
819 && DECL_PTA_ALIASVAR (decl
)
821 && (cgraph_local_info (decl
)->local
))
829 /* Simple pointer comparison function for list sorting. */
832 simple_cmp (const aterm a
, const aterm b
)
834 return (int *)a
- (int *)b
;
838 /* Get the points-to set for TV, caching if it we had to compute it. */
841 get_ptset (alias_var tv
)
844 ptset
= ALIAS_VAR_PTSET (tv
);
847 ptset
= aterm_tlb (pta_get_contents (ALIAS_VAR_ATERM (tv
)));
848 ALIAS_VAR_PTSET (tv
) = ptset
;
853 /* Determine if two aterm's have the same points-to set. */
856 andersen_same_points_to_set (struct tree_alias_ops
*ops ATTRIBUTE_UNUSED
,
857 alias_var ptrtv
, alias_var vartv
)
859 aterm_list ptset1
, ptset2
;
860 aterm_list_scanner scan1
, scan2
;
862 region scratch_rgn
= newregion ();
864 ptset1
= get_ptset (ptrtv
);
865 ptset2
= get_ptset (vartv
);
867 if (aterm_list_length (ptset1
) != aterm_list_length (ptset2
))
869 deleteregion (scratch_rgn
);
873 if (ptset1
== ptset2
)
875 deleteregion (scratch_rgn
);
879 ptset1
= aterm_list_copy (scratch_rgn
, ptset1
);
880 ptset2
= aterm_list_copy (scratch_rgn
, ptset2
);
882 if (aterm_list_length (ptset1
) != aterm_list_length (ptset2
))
884 deleteregion (scratch_rgn
);
888 ptset1
= aterm_list_sort (ptset1
, simple_cmp
);
889 ptset2
= aterm_list_sort (ptset2
, simple_cmp
);
891 aterm_list_scan (ptset1
, &scan1
);
892 aterm_list_scan (ptset2
, &scan2
);
893 while (aterm_list_next (&scan1
, &data1
))
895 aterm_list_next (&scan2
, &data2
);
898 deleteregion(scratch_rgn
);
902 deleteregion(scratch_rgn
);
907 /* Determine if two variables may alias. In our case, this means
908 whether the decl represented by PTRTV can point to VARTV. */
911 andersen_may_alias (struct tree_alias_ops
*ops ATTRIBUTE_UNUSED
,
912 alias_var ptrtv
, alias_var vartv
)
915 ptset
= get_ptset (ptrtv
);
917 if (aterm_list_empty (ptset
))
920 return aterm_list_member (ptset
, ALIAS_VAR_ATERM (vartv
));
923 /* Determine whether PTRTV has an empty points-to set. IE it may not
924 point to anything. */
927 andersen_empty_points_to_set (struct tree_alias_ops
*ops ATTRIBUTE_UNUSED
,
931 ptset
= get_ptset (ptrtv
);
932 return aterm_list_empty (ptset
);