xref: /openbsd/gnu/gcc/gcc/tree-ssa-structalias.c (revision 404b540a)
1*404b540aSrobert /* Tree based points-to analysis
2*404b540aSrobert    Copyright (C) 2005, 2006 Free Software Foundation, Inc.
3*404b540aSrobert    Contributed by Daniel Berlin <dberlin@dberlin.org>
4*404b540aSrobert 
5*404b540aSrobert This file is part of GCC.
6*404b540aSrobert 
7*404b540aSrobert GCC is free software; you can redistribute it and/or modify
8*404b540aSrobert under the terms of the GNU General Public License as published by
9*404b540aSrobert the Free Software Foundation; either version 2 of the License, or
10*404b540aSrobert (at your option) any later version.
11*404b540aSrobert 
12*404b540aSrobert GCC is distributed in the hope that it will be useful,
13*404b540aSrobert but WITHOUT ANY WARRANTY; without even the implied warranty of
14*404b540aSrobert MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15*404b540aSrobert GNU General Public License for more details.
16*404b540aSrobert 
17*404b540aSrobert You should have received a copy of the GNU General Public License
18*404b540aSrobert along with GCC; if not, write to the Free Software
19*404b540aSrobert Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
20*404b540aSrobert */
21*404b540aSrobert 
22*404b540aSrobert #include "config.h"
23*404b540aSrobert #include "system.h"
24*404b540aSrobert #include "coretypes.h"
25*404b540aSrobert #include "tm.h"
26*404b540aSrobert #include "ggc.h"
27*404b540aSrobert #include "obstack.h"
28*404b540aSrobert #include "bitmap.h"
29*404b540aSrobert #include "flags.h"
30*404b540aSrobert #include "rtl.h"
31*404b540aSrobert #include "tm_p.h"
32*404b540aSrobert #include "hard-reg-set.h"
33*404b540aSrobert #include "basic-block.h"
34*404b540aSrobert #include "output.h"
35*404b540aSrobert #include "errors.h"
36*404b540aSrobert #include "diagnostic.h"
37*404b540aSrobert #include "tree.h"
38*404b540aSrobert #include "c-common.h"
39*404b540aSrobert #include "tree-flow.h"
40*404b540aSrobert #include "tree-inline.h"
41*404b540aSrobert #include "varray.h"
42*404b540aSrobert #include "c-tree.h"
43*404b540aSrobert #include "tree-gimple.h"
44*404b540aSrobert #include "hashtab.h"
45*404b540aSrobert #include "function.h"
46*404b540aSrobert #include "cgraph.h"
47*404b540aSrobert #include "tree-pass.h"
48*404b540aSrobert #include "timevar.h"
49*404b540aSrobert #include "alloc-pool.h"
50*404b540aSrobert #include "splay-tree.h"
51*404b540aSrobert #include "params.h"
52*404b540aSrobert #include "tree-ssa-structalias.h"
53*404b540aSrobert #include "cgraph.h"
54*404b540aSrobert #include "pointer-set.h"
55*404b540aSrobert 
56*404b540aSrobert /* The idea behind this analyzer is to generate set constraints from the
57*404b540aSrobert    program, then solve the resulting constraints in order to generate the
58*404b540aSrobert    points-to sets.
59*404b540aSrobert 
60*404b540aSrobert    Set constraints are a way of modeling program analysis problems that
61*404b540aSrobert    involve sets.  They consist of an inclusion constraint language,
62*404b540aSrobert    describing the variables (each variable is a set) and operations that
63*404b540aSrobert    are involved on the variables, and a set of rules that derive facts
64*404b540aSrobert    from these operations.  To solve a system of set constraints, you derive
65*404b540aSrobert    all possible facts under the rules, which gives you the correct sets
66*404b540aSrobert    as a consequence.
67*404b540aSrobert 
68*404b540aSrobert    See  "Efficient Field-sensitive pointer analysis for C" by "David
69*404b540aSrobert    J. Pearce and Paul H. J. Kelly and Chris Hankin, at
70*404b540aSrobert    http://citeseer.ist.psu.edu/pearce04efficient.html
71*404b540aSrobert 
72*404b540aSrobert    Also see "Ultra-fast Aliasing Analysis using CLA: A Million Lines
73*404b540aSrobert    of C Code in a Second" by ""Nevin Heintze and Olivier Tardieu" at
74*404b540aSrobert    http://citeseer.ist.psu.edu/heintze01ultrafast.html
75*404b540aSrobert 
76*404b540aSrobert    There are three types of real constraint expressions, DEREF,
77*404b540aSrobert    ADDRESSOF, and SCALAR.  Each constraint expression consists
78*404b540aSrobert    of a constraint type, a variable, and an offset.
79*404b540aSrobert 
80*404b540aSrobert    SCALAR is a constraint expression type used to represent x, whether
81*404b540aSrobert    it appears on the LHS or the RHS of a statement.
82*404b540aSrobert    DEREF is a constraint expression type used to represent *x, whether
83*404b540aSrobert    it appears on the LHS or the RHS of a statement.
84*404b540aSrobert    ADDRESSOF is a constraint expression used to represent &x, whether
85*404b540aSrobert    it appears on the LHS or the RHS of a statement.
86*404b540aSrobert 
87*404b540aSrobert    Each pointer variable in the program is assigned an integer id, and
88*404b540aSrobert    each field of a structure variable is assigned an integer id as well.
89*404b540aSrobert 
90*404b540aSrobert    Structure variables are linked to their list of fields through a "next
91*404b540aSrobert    field" in each variable that points to the next field in offset
92*404b540aSrobert    order.
93*404b540aSrobert    Each variable for a structure field has
94*404b540aSrobert 
95*404b540aSrobert    1. "size", that tells the size in bits of that field.
96*404b540aSrobert    2. "fullsize, that tells the size in bits of the entire structure.
97*404b540aSrobert    3. "offset", that tells the offset in bits from the beginning of the
98*404b540aSrobert    structure to this field.
99*404b540aSrobert 
100*404b540aSrobert    Thus,
101*404b540aSrobert    struct f
102*404b540aSrobert    {
103*404b540aSrobert      int a;
104*404b540aSrobert      int b;
105*404b540aSrobert    } foo;
106*404b540aSrobert    int *bar;
107*404b540aSrobert 
108*404b540aSrobert    looks like
109*404b540aSrobert 
110*404b540aSrobert    foo.a -> id 1, size 32, offset 0, fullsize 64, next foo.b
111*404b540aSrobert    foo.b -> id 2, size 32, offset 32, fullsize 64, next NULL
112*404b540aSrobert    bar -> id 3, size 32, offset 0, fullsize 32, next NULL
113*404b540aSrobert 
114*404b540aSrobert 
115*404b540aSrobert   In order to solve the system of set constraints, the following is
116*404b540aSrobert   done:
117*404b540aSrobert 
118*404b540aSrobert   1. Each constraint variable x has a solution set associated with it,
119*404b540aSrobert   Sol(x).
120*404b540aSrobert 
121*404b540aSrobert   2. Constraints are separated into direct, copy, and complex.
122*404b540aSrobert   Direct constraints are ADDRESSOF constraints that require no extra
123*404b540aSrobert   processing, such as P = &Q
124*404b540aSrobert   Copy constraints are those of the form P = Q.
125*404b540aSrobert   Complex constraints are all the constraints involving dereferences
126*404b540aSrobert   and offsets (including offsetted copies).
127*404b540aSrobert 
128*404b540aSrobert   3. All direct constraints of the form P = &Q are processed, such
129*404b540aSrobert   that Q is added to Sol(P)
130*404b540aSrobert 
131*404b540aSrobert   4. All complex constraints for a given constraint variable are stored in a
132*404b540aSrobert   linked list attached to that variable's node.
133*404b540aSrobert 
134*404b540aSrobert   5. A directed graph is built out of the copy constraints. Each
135*404b540aSrobert   constraint variable is a node in the graph, and an edge from
136*404b540aSrobert   Q to P is added for each copy constraint of the form P = Q
137*404b540aSrobert 
138*404b540aSrobert   6. The graph is then walked, and solution sets are
139*404b540aSrobert   propagated along the copy edges, such that an edge from Q to P
140*404b540aSrobert   causes Sol(P) <- Sol(P) union Sol(Q).
141*404b540aSrobert 
142*404b540aSrobert   7.  As we visit each node, all complex constraints associated with
143*404b540aSrobert   that node are processed by adding appropriate copy edges to the graph, or the
144*404b540aSrobert   appropriate variables to the solution set.
145*404b540aSrobert 
146*404b540aSrobert   8. The process of walking the graph is iterated until no solution
147*404b540aSrobert   sets change.
148*404b540aSrobert 
149*404b540aSrobert   Prior to walking the graph in steps 6 and 7, We perform static
150*404b540aSrobert   cycle elimination on the constraint graph, as well
151*404b540aSrobert   as off-line variable substitution.
152*404b540aSrobert 
153*404b540aSrobert   TODO: Adding offsets to pointer-to-structures can be handled (IE not punted
154*404b540aSrobert   on and turned into anything), but isn't.  You can just see what offset
155*404b540aSrobert   inside the pointed-to struct it's going to access.
156*404b540aSrobert 
157*404b540aSrobert   TODO: Constant bounded arrays can be handled as if they were structs of the
158*404b540aSrobert   same number of elements.
159*404b540aSrobert 
160*404b540aSrobert   TODO: Modeling heap and incoming pointers becomes much better if we
161*404b540aSrobert   add fields to them as we discover them, which we could do.
162*404b540aSrobert 
163*404b540aSrobert   TODO: We could handle unions, but to be honest, it's probably not
164*404b540aSrobert   worth the pain or slowdown.  */
165*404b540aSrobert 
166*404b540aSrobert static GTY ((if_marked ("tree_map_marked_p"), param_is (struct tree_map))) htab_t heapvar_for_stmt;
167*404b540aSrobert 
168*404b540aSrobert /* One variable to represent all non-local accesses.  */
169*404b540aSrobert tree nonlocal_all;
170*404b540aSrobert 
171*404b540aSrobert static bool use_field_sensitive = true;
172*404b540aSrobert static int in_ipa_mode = 0;
173*404b540aSrobert 
174*404b540aSrobert /* Used for predecessor bitmaps. */
175*404b540aSrobert static bitmap_obstack predbitmap_obstack;
176*404b540aSrobert 
177*404b540aSrobert /* Used for points-to sets.  */
178*404b540aSrobert static bitmap_obstack pta_obstack;
179*404b540aSrobert 
180*404b540aSrobert /* Used for oldsolution members of variables. */
181*404b540aSrobert static bitmap_obstack oldpta_obstack;
182*404b540aSrobert 
183*404b540aSrobert /* Used for per-solver-iteration bitmaps.  */
184*404b540aSrobert static bitmap_obstack iteration_obstack;
185*404b540aSrobert 
186*404b540aSrobert static unsigned int create_variable_info_for (tree, const char *);
187*404b540aSrobert typedef struct constraint_graph *constraint_graph_t;
188*404b540aSrobert static void unify_nodes (constraint_graph_t, unsigned int, unsigned int, bool);
189*404b540aSrobert 
190*404b540aSrobert DEF_VEC_P(constraint_t);
191*404b540aSrobert DEF_VEC_ALLOC_P(constraint_t,heap);
192*404b540aSrobert 
193*404b540aSrobert #define EXECUTE_IF_IN_NONNULL_BITMAP(a, b, c, d)	\
194*404b540aSrobert   if (a)						\
195*404b540aSrobert     EXECUTE_IF_SET_IN_BITMAP (a, b, c, d)
196*404b540aSrobert 
197*404b540aSrobert static struct constraint_stats
198*404b540aSrobert {
199*404b540aSrobert   unsigned int total_vars;
200*404b540aSrobert   unsigned int nonpointer_vars;
201*404b540aSrobert   unsigned int unified_vars_static;
202*404b540aSrobert   unsigned int unified_vars_dynamic;
203*404b540aSrobert   unsigned int iterations;
204*404b540aSrobert   unsigned int num_edges;
205*404b540aSrobert   unsigned int num_implicit_edges;
206*404b540aSrobert   unsigned int points_to_sets_created;
207*404b540aSrobert } stats;
208*404b540aSrobert 
209*404b540aSrobert struct variable_info
210*404b540aSrobert {
211*404b540aSrobert   /* ID of this variable  */
212*404b540aSrobert   unsigned int id;
213*404b540aSrobert 
214*404b540aSrobert   /* Name of this variable */
215*404b540aSrobert   const char *name;
216*404b540aSrobert 
217*404b540aSrobert   /* Tree that this variable is associated with.  */
218*404b540aSrobert   tree decl;
219*404b540aSrobert 
220*404b540aSrobert   /* Offset of this variable, in bits, from the base variable  */
221*404b540aSrobert   unsigned HOST_WIDE_INT offset;
222*404b540aSrobert 
223*404b540aSrobert   /* Size of the variable, in bits.  */
224*404b540aSrobert   unsigned HOST_WIDE_INT size;
225*404b540aSrobert 
226*404b540aSrobert   /* Full size of the base variable, in bits.  */
227*404b540aSrobert   unsigned HOST_WIDE_INT fullsize;
228*404b540aSrobert 
229*404b540aSrobert   /* A link to the variable for the next field in this structure.  */
230*404b540aSrobert   struct variable_info *next;
231*404b540aSrobert 
232*404b540aSrobert   /* True if the variable is directly the target of a dereference.
233*404b540aSrobert      This is used to track which variables are *actually* dereferenced
234*404b540aSrobert      so we can prune their points to listed. */
235*404b540aSrobert   unsigned int directly_dereferenced:1;
236*404b540aSrobert 
237*404b540aSrobert   /* True if this is a variable created by the constraint analysis, such as
238*404b540aSrobert      heap variables and constraints we had to break up.  */
239*404b540aSrobert   unsigned int is_artificial_var:1;
240*404b540aSrobert 
241*404b540aSrobert   /* True if this is a special variable whose solution set should not be
242*404b540aSrobert      changed.  */
243*404b540aSrobert   unsigned int is_special_var:1;
244*404b540aSrobert 
245*404b540aSrobert   /* True for variables whose size is not known or variable.  */
246*404b540aSrobert   unsigned int is_unknown_size_var:1;
247*404b540aSrobert 
248*404b540aSrobert   /* True for variables that have unions somewhere in them.  */
249*404b540aSrobert   unsigned int has_union:1;
250*404b540aSrobert 
251*404b540aSrobert   /* True if this is a heap variable.  */
252*404b540aSrobert   unsigned int is_heap_var:1;
253*404b540aSrobert 
254*404b540aSrobert   /* Points-to set for this variable.  */
255*404b540aSrobert   bitmap solution;
256*404b540aSrobert 
257*404b540aSrobert   /* Old points-to set for this variable.  */
258*404b540aSrobert   bitmap oldsolution;
259*404b540aSrobert 
260*404b540aSrobert   /* Variable ids represented by this node.  */
261*404b540aSrobert   bitmap variables;
262*404b540aSrobert 
263*404b540aSrobert   /* Variable id this was collapsed to due to type unsafety.  This
264*404b540aSrobert      should be unused completely after build_succ_graph, or something
265*404b540aSrobert      is broken.  */
266*404b540aSrobert   struct variable_info *collapsed_to;
267*404b540aSrobert };
268*404b540aSrobert typedef struct variable_info *varinfo_t;
269*404b540aSrobert 
270*404b540aSrobert static varinfo_t first_vi_for_offset (varinfo_t, unsigned HOST_WIDE_INT);
271*404b540aSrobert 
272*404b540aSrobert /* Pool of variable info structures.  */
273*404b540aSrobert static alloc_pool variable_info_pool;
274*404b540aSrobert 
275*404b540aSrobert DEF_VEC_P(varinfo_t);
276*404b540aSrobert 
277*404b540aSrobert DEF_VEC_ALLOC_P(varinfo_t, heap);
278*404b540aSrobert 
279*404b540aSrobert /* Table of variable info structures for constraint variables.
280*404b540aSrobert    Indexed directly by variable info id.  */
VEC(varinfo_t,heap)281*404b540aSrobert static VEC(varinfo_t,heap) *varmap;
282*404b540aSrobert 
283*404b540aSrobert /* Return the varmap element N */
284*404b540aSrobert 
285*404b540aSrobert static inline varinfo_t
286*404b540aSrobert get_varinfo (unsigned int n)
287*404b540aSrobert {
288*404b540aSrobert   return VEC_index (varinfo_t, varmap, n);
289*404b540aSrobert }
290*404b540aSrobert 
291*404b540aSrobert /* Return the varmap element N, following the collapsed_to link.  */
292*404b540aSrobert 
293*404b540aSrobert static inline varinfo_t
get_varinfo_fc(unsigned int n)294*404b540aSrobert get_varinfo_fc (unsigned int n)
295*404b540aSrobert {
296*404b540aSrobert   varinfo_t v = VEC_index (varinfo_t, varmap, n);
297*404b540aSrobert 
298*404b540aSrobert   if (v->collapsed_to)
299*404b540aSrobert     return v->collapsed_to;
300*404b540aSrobert   return v;
301*404b540aSrobert }
302*404b540aSrobert 
303*404b540aSrobert /* Variable that represents the unknown pointer.  */
304*404b540aSrobert static varinfo_t var_anything;
305*404b540aSrobert static tree anything_tree;
306*404b540aSrobert static unsigned int anything_id;
307*404b540aSrobert 
308*404b540aSrobert /* Variable that represents the NULL pointer.  */
309*404b540aSrobert static varinfo_t var_nothing;
310*404b540aSrobert static tree nothing_tree;
311*404b540aSrobert static unsigned int nothing_id;
312*404b540aSrobert 
313*404b540aSrobert /* Variable that represents read only memory.  */
314*404b540aSrobert static varinfo_t var_readonly;
315*404b540aSrobert static tree readonly_tree;
316*404b540aSrobert static unsigned int readonly_id;
317*404b540aSrobert 
318*404b540aSrobert /* Variable that represents integers.  This is used for when people do things
319*404b540aSrobert    like &0->a.b.  */
320*404b540aSrobert static varinfo_t var_integer;
321*404b540aSrobert static tree integer_tree;
322*404b540aSrobert static unsigned int integer_id;
323*404b540aSrobert 
324*404b540aSrobert /* Variable that represents escaped variables.  This is used to give
325*404b540aSrobert    incoming pointer variables a better set than ANYTHING.  */
326*404b540aSrobert static varinfo_t var_escaped_vars;
327*404b540aSrobert static tree escaped_vars_tree;
328*404b540aSrobert static unsigned int escaped_vars_id;
329*404b540aSrobert 
330*404b540aSrobert /* Variable that represents non-local variables before we expand it to
331*404b540aSrobert    one for each type.  */
332*404b540aSrobert static unsigned int nonlocal_vars_id;
333*404b540aSrobert /* Lookup a heap var for FROM, and return it if we find one.  */
334*404b540aSrobert 
335*404b540aSrobert static tree
heapvar_lookup(tree from)336*404b540aSrobert heapvar_lookup (tree from)
337*404b540aSrobert {
338*404b540aSrobert   struct tree_map *h, in;
339*404b540aSrobert   in.from = from;
340*404b540aSrobert 
341*404b540aSrobert   h = htab_find_with_hash (heapvar_for_stmt, &in, htab_hash_pointer (from));
342*404b540aSrobert   if (h)
343*404b540aSrobert     return h->to;
344*404b540aSrobert   return NULL_TREE;
345*404b540aSrobert }
346*404b540aSrobert 
347*404b540aSrobert /* Insert a mapping FROM->TO in the heap var for statement
348*404b540aSrobert    hashtable.  */
349*404b540aSrobert 
350*404b540aSrobert static void
heapvar_insert(tree from,tree to)351*404b540aSrobert heapvar_insert (tree from, tree to)
352*404b540aSrobert {
353*404b540aSrobert   struct tree_map *h;
354*404b540aSrobert   void **loc;
355*404b540aSrobert 
356*404b540aSrobert   h = ggc_alloc (sizeof (struct tree_map));
357*404b540aSrobert   h->hash = htab_hash_pointer (from);
358*404b540aSrobert   h->from = from;
359*404b540aSrobert   h->to = to;
360*404b540aSrobert   loc = htab_find_slot_with_hash (heapvar_for_stmt, h, h->hash, INSERT);
361*404b540aSrobert   *(struct tree_map **) loc = h;
362*404b540aSrobert }
363*404b540aSrobert 
364*404b540aSrobert /* Return a new variable info structure consisting for a variable
365*404b540aSrobert    named NAME, and using constraint graph node NODE.  */
366*404b540aSrobert 
367*404b540aSrobert static varinfo_t
new_var_info(tree t,unsigned int id,const char * name)368*404b540aSrobert new_var_info (tree t, unsigned int id, const char *name)
369*404b540aSrobert {
370*404b540aSrobert   varinfo_t ret = pool_alloc (variable_info_pool);
371*404b540aSrobert 
372*404b540aSrobert   ret->id = id;
373*404b540aSrobert   ret->name = name;
374*404b540aSrobert   ret->decl = t;
375*404b540aSrobert   ret->directly_dereferenced = false;
376*404b540aSrobert   ret->is_artificial_var = false;
377*404b540aSrobert   ret->is_heap_var = false;
378*404b540aSrobert   ret->is_special_var = false;
379*404b540aSrobert   ret->is_unknown_size_var = false;
380*404b540aSrobert   ret->has_union = false;
381*404b540aSrobert   ret->solution = BITMAP_ALLOC (&pta_obstack);
382*404b540aSrobert   ret->oldsolution = BITMAP_ALLOC (&oldpta_obstack);
383*404b540aSrobert   ret->next = NULL;
384*404b540aSrobert   ret->collapsed_to = NULL;
385*404b540aSrobert   return ret;
386*404b540aSrobert }
387*404b540aSrobert 
388*404b540aSrobert typedef enum {SCALAR, DEREF, ADDRESSOF} constraint_expr_type;
389*404b540aSrobert 
390*404b540aSrobert /* An expression that appears in a constraint.  */
391*404b540aSrobert 
392*404b540aSrobert struct constraint_expr
393*404b540aSrobert {
394*404b540aSrobert   /* Constraint type.  */
395*404b540aSrobert   constraint_expr_type type;
396*404b540aSrobert 
397*404b540aSrobert   /* Variable we are referring to in the constraint.  */
398*404b540aSrobert   unsigned int var;
399*404b540aSrobert 
400*404b540aSrobert   /* Offset, in bits, of this constraint from the beginning of
401*404b540aSrobert      variables it ends up referring to.
402*404b540aSrobert 
403*404b540aSrobert      IOW, in a deref constraint, we would deref, get the result set,
404*404b540aSrobert      then add OFFSET to each member.   */
405*404b540aSrobert   unsigned HOST_WIDE_INT offset;
406*404b540aSrobert };
407*404b540aSrobert 
408*404b540aSrobert typedef struct constraint_expr ce_s;
409*404b540aSrobert DEF_VEC_O(ce_s);
410*404b540aSrobert DEF_VEC_ALLOC_O(ce_s, heap);
411*404b540aSrobert static void get_constraint_for (tree, VEC(ce_s, heap) **);
412*404b540aSrobert static void do_deref (VEC (ce_s, heap) **);
413*404b540aSrobert 
414*404b540aSrobert /* Our set constraints are made up of two constraint expressions, one
415*404b540aSrobert    LHS, and one RHS.
416*404b540aSrobert 
417*404b540aSrobert    As described in the introduction, our set constraints each represent an
418*404b540aSrobert    operation between set valued variables.
419*404b540aSrobert */
420*404b540aSrobert struct constraint
421*404b540aSrobert {
422*404b540aSrobert   struct constraint_expr lhs;
423*404b540aSrobert   struct constraint_expr rhs;
424*404b540aSrobert };
425*404b540aSrobert 
426*404b540aSrobert /* List of constraints that we use to build the constraint graph from.  */
427*404b540aSrobert 
428*404b540aSrobert static VEC(constraint_t,heap) *constraints;
429*404b540aSrobert static alloc_pool constraint_pool;
430*404b540aSrobert 
431*404b540aSrobert 
432*404b540aSrobert DEF_VEC_I(int);
433*404b540aSrobert DEF_VEC_ALLOC_I(int, heap);
434*404b540aSrobert 
435*404b540aSrobert /* The constraint graph is represented as an array of bitmaps
436*404b540aSrobert    containing successor nodes.  */
437*404b540aSrobert 
438*404b540aSrobert struct constraint_graph
439*404b540aSrobert {
440*404b540aSrobert   /* Size of this graph, which may be different than the number of
441*404b540aSrobert      nodes in the variable map.  */
442*404b540aSrobert   unsigned int size;
443*404b540aSrobert 
444*404b540aSrobert   /* Explicit successors of each node. */
445*404b540aSrobert   bitmap *succs;
446*404b540aSrobert 
447*404b540aSrobert   /* Implicit predecessors of each node (Used for variable
448*404b540aSrobert      substitution). */
449*404b540aSrobert   bitmap *implicit_preds;
450*404b540aSrobert 
451*404b540aSrobert   /* Explicit predecessors of each node (Used for variable substitution).  */
452*404b540aSrobert   bitmap *preds;
453*404b540aSrobert 
454*404b540aSrobert   /* Indirect cycle representatives, or -1 if the node has no indirect
455*404b540aSrobert      cycles.  */
456*404b540aSrobert   int *indirect_cycles;
457*404b540aSrobert 
458*404b540aSrobert   /* Representative node for a node.  rep[a] == a unless the node has
459*404b540aSrobert      been unified. */
460*404b540aSrobert   unsigned int *rep;
461*404b540aSrobert 
462*404b540aSrobert   /* Equivalence class representative for a node.  This is used for
463*404b540aSrobert      variable substitution.  */
464*404b540aSrobert   int *eq_rep;
465*404b540aSrobert 
466*404b540aSrobert   /* Label for each node, used during variable substitution.  */
467*404b540aSrobert   unsigned int *label;
468*404b540aSrobert 
469*404b540aSrobert   /* Bitmap of nodes where the bit is set if the node is a direct
470*404b540aSrobert      node.  Used for variable substitution.  */
471*404b540aSrobert   sbitmap direct_nodes;
472*404b540aSrobert 
473*404b540aSrobert   /* Vector of complex constraints for each graph node.  Complex
474*404b540aSrobert      constraints are those involving dereferences or offsets that are
475*404b540aSrobert      not 0.  */
476*404b540aSrobert   VEC(constraint_t,heap) **complex;
477*404b540aSrobert };
478*404b540aSrobert 
479*404b540aSrobert static constraint_graph_t graph;
480*404b540aSrobert 
481*404b540aSrobert /* During variable substitution and the offline version of indirect
482*404b540aSrobert    cycle finding, we create nodes to represent dereferences and
483*404b540aSrobert    address taken constraints.  These represent where these start and
484*404b540aSrobert    end.  */
485*404b540aSrobert #define FIRST_REF_NODE (VEC_length (varinfo_t, varmap))
486*404b540aSrobert #define LAST_REF_NODE (FIRST_REF_NODE + (FIRST_REF_NODE - 1))
487*404b540aSrobert #define FIRST_ADDR_NODE (LAST_REF_NODE + 1)
488*404b540aSrobert 
489*404b540aSrobert /* Return the representative node for NODE, if NODE has been unioned
490*404b540aSrobert    with another NODE.
491*404b540aSrobert    This function performs path compression along the way to finding
492*404b540aSrobert    the representative.  */
493*404b540aSrobert 
494*404b540aSrobert static unsigned int
find(unsigned int node)495*404b540aSrobert find (unsigned int node)
496*404b540aSrobert {
497*404b540aSrobert   gcc_assert (node < graph->size);
498*404b540aSrobert   if (graph->rep[node] != node)
499*404b540aSrobert     return graph->rep[node] = find (graph->rep[node]);
500*404b540aSrobert   return node;
501*404b540aSrobert }
502*404b540aSrobert 
503*404b540aSrobert /* Union the TO and FROM nodes to the TO nodes.
504*404b540aSrobert    Note that at some point in the future, we may want to do
505*404b540aSrobert    union-by-rank, in which case we are going to have to return the
506*404b540aSrobert    node we unified to.  */
507*404b540aSrobert 
508*404b540aSrobert static bool
unite(unsigned int to,unsigned int from)509*404b540aSrobert unite (unsigned int to, unsigned int from)
510*404b540aSrobert {
511*404b540aSrobert   gcc_assert (to < graph->size && from < graph->size);
512*404b540aSrobert   if (to != from && graph->rep[from] != to)
513*404b540aSrobert     {
514*404b540aSrobert       graph->rep[from] = to;
515*404b540aSrobert       return true;
516*404b540aSrobert     }
517*404b540aSrobert   return false;
518*404b540aSrobert }
519*404b540aSrobert 
520*404b540aSrobert /* Create a new constraint consisting of LHS and RHS expressions.  */
521*404b540aSrobert 
522*404b540aSrobert static constraint_t
new_constraint(const struct constraint_expr lhs,const struct constraint_expr rhs)523*404b540aSrobert new_constraint (const struct constraint_expr lhs,
524*404b540aSrobert 		const struct constraint_expr rhs)
525*404b540aSrobert {
526*404b540aSrobert   constraint_t ret = pool_alloc (constraint_pool);
527*404b540aSrobert   ret->lhs = lhs;
528*404b540aSrobert   ret->rhs = rhs;
529*404b540aSrobert   return ret;
530*404b540aSrobert }
531*404b540aSrobert 
532*404b540aSrobert /* Print out constraint C to FILE.  */
533*404b540aSrobert 
534*404b540aSrobert void
dump_constraint(FILE * file,constraint_t c)535*404b540aSrobert dump_constraint (FILE *file, constraint_t c)
536*404b540aSrobert {
537*404b540aSrobert   if (c->lhs.type == ADDRESSOF)
538*404b540aSrobert     fprintf (file, "&");
539*404b540aSrobert   else if (c->lhs.type == DEREF)
540*404b540aSrobert     fprintf (file, "*");
541*404b540aSrobert   fprintf (file, "%s", get_varinfo_fc (c->lhs.var)->name);
542*404b540aSrobert   if (c->lhs.offset != 0)
543*404b540aSrobert     fprintf (file, " + " HOST_WIDE_INT_PRINT_DEC, c->lhs.offset);
544*404b540aSrobert   fprintf (file, " = ");
545*404b540aSrobert   if (c->rhs.type == ADDRESSOF)
546*404b540aSrobert     fprintf (file, "&");
547*404b540aSrobert   else if (c->rhs.type == DEREF)
548*404b540aSrobert     fprintf (file, "*");
549*404b540aSrobert   fprintf (file, "%s", get_varinfo_fc (c->rhs.var)->name);
550*404b540aSrobert   if (c->rhs.offset != 0)
551*404b540aSrobert     fprintf (file, " + " HOST_WIDE_INT_PRINT_DEC, c->rhs.offset);
552*404b540aSrobert   fprintf (file, "\n");
553*404b540aSrobert }
554*404b540aSrobert 
555*404b540aSrobert /* Print out constraint C to stderr.  */
556*404b540aSrobert 
557*404b540aSrobert void
debug_constraint(constraint_t c)558*404b540aSrobert debug_constraint (constraint_t c)
559*404b540aSrobert {
560*404b540aSrobert   dump_constraint (stderr, c);
561*404b540aSrobert }
562*404b540aSrobert 
563*404b540aSrobert /* Print out all constraints to FILE */
564*404b540aSrobert 
565*404b540aSrobert void
dump_constraints(FILE * file)566*404b540aSrobert dump_constraints (FILE *file)
567*404b540aSrobert {
568*404b540aSrobert   int i;
569*404b540aSrobert   constraint_t c;
570*404b540aSrobert   for (i = 0; VEC_iterate (constraint_t, constraints, i, c); i++)
571*404b540aSrobert     dump_constraint (file, c);
572*404b540aSrobert }
573*404b540aSrobert 
574*404b540aSrobert /* Print out all constraints to stderr.  */
575*404b540aSrobert 
576*404b540aSrobert void
debug_constraints(void)577*404b540aSrobert debug_constraints (void)
578*404b540aSrobert {
579*404b540aSrobert   dump_constraints (stderr);
580*404b540aSrobert }
581*404b540aSrobert 
582*404b540aSrobert /* SOLVER FUNCTIONS
583*404b540aSrobert 
584*404b540aSrobert    The solver is a simple worklist solver, that works on the following
585*404b540aSrobert    algorithm:
586*404b540aSrobert 
587*404b540aSrobert    sbitmap changed_nodes = all zeroes;
588*404b540aSrobert    changed_count = 0;
589*404b540aSrobert    For each node that is not already collapsed:
590*404b540aSrobert        changed_count++;
591*404b540aSrobert        set bit in changed nodes
592*404b540aSrobert 
593*404b540aSrobert    while (changed_count > 0)
594*404b540aSrobert    {
595*404b540aSrobert      compute topological ordering for constraint graph
596*404b540aSrobert 
597*404b540aSrobert      find and collapse cycles in the constraint graph (updating
598*404b540aSrobert      changed if necessary)
599*404b540aSrobert 
600*404b540aSrobert      for each node (n) in the graph in topological order:
601*404b540aSrobert        changed_count--;
602*404b540aSrobert 
603*404b540aSrobert        Process each complex constraint associated with the node,
604*404b540aSrobert        updating changed if necessary.
605*404b540aSrobert 
606*404b540aSrobert        For each outgoing edge from n, propagate the solution from n to
607*404b540aSrobert        the destination of the edge, updating changed as necessary.
608*404b540aSrobert 
609*404b540aSrobert    }  */
610*404b540aSrobert 
611*404b540aSrobert /* Return true if two constraint expressions A and B are equal.  */
612*404b540aSrobert 
613*404b540aSrobert static bool
constraint_expr_equal(struct constraint_expr a,struct constraint_expr b)614*404b540aSrobert constraint_expr_equal (struct constraint_expr a, struct constraint_expr b)
615*404b540aSrobert {
616*404b540aSrobert   return a.type == b.type && a.var == b.var && a.offset == b.offset;
617*404b540aSrobert }
618*404b540aSrobert 
619*404b540aSrobert /* Return true if constraint expression A is less than constraint expression
620*404b540aSrobert    B.  This is just arbitrary, but consistent, in order to give them an
621*404b540aSrobert    ordering.  */
622*404b540aSrobert 
623*404b540aSrobert static bool
constraint_expr_less(struct constraint_expr a,struct constraint_expr b)624*404b540aSrobert constraint_expr_less (struct constraint_expr a, struct constraint_expr b)
625*404b540aSrobert {
626*404b540aSrobert   if (a.type == b.type)
627*404b540aSrobert     {
628*404b540aSrobert       if (a.var == b.var)
629*404b540aSrobert 	return a.offset < b.offset;
630*404b540aSrobert       else
631*404b540aSrobert 	return a.var < b.var;
632*404b540aSrobert     }
633*404b540aSrobert   else
634*404b540aSrobert     return a.type < b.type;
635*404b540aSrobert }
636*404b540aSrobert 
637*404b540aSrobert /* Return true if constraint A is less than constraint B.  This is just
638*404b540aSrobert    arbitrary, but consistent, in order to give them an ordering.  */
639*404b540aSrobert 
640*404b540aSrobert static bool
constraint_less(const constraint_t a,const constraint_t b)641*404b540aSrobert constraint_less (const constraint_t a, const constraint_t b)
642*404b540aSrobert {
643*404b540aSrobert   if (constraint_expr_less (a->lhs, b->lhs))
644*404b540aSrobert     return true;
645*404b540aSrobert   else if (constraint_expr_less (b->lhs, a->lhs))
646*404b540aSrobert     return false;
647*404b540aSrobert   else
648*404b540aSrobert     return constraint_expr_less (a->rhs, b->rhs);
649*404b540aSrobert }
650*404b540aSrobert 
651*404b540aSrobert /* Return true if two constraints A and B are equal.  */
652*404b540aSrobert 
653*404b540aSrobert static bool
constraint_equal(struct constraint a,struct constraint b)654*404b540aSrobert constraint_equal (struct constraint a, struct constraint b)
655*404b540aSrobert {
656*404b540aSrobert   return constraint_expr_equal (a.lhs, b.lhs)
657*404b540aSrobert     && constraint_expr_equal (a.rhs, b.rhs);
658*404b540aSrobert }
659*404b540aSrobert 
660*404b540aSrobert 
661*404b540aSrobert /* Find a constraint LOOKFOR in the sorted constraint vector VEC */
662*404b540aSrobert 
663*404b540aSrobert static constraint_t
constraint_vec_find(VEC (constraint_t,heap)* vec,struct constraint lookfor)664*404b540aSrobert constraint_vec_find (VEC(constraint_t,heap) *vec,
665*404b540aSrobert 		     struct constraint lookfor)
666*404b540aSrobert {
667*404b540aSrobert   unsigned int place;
668*404b540aSrobert   constraint_t found;
669*404b540aSrobert 
670*404b540aSrobert   if (vec == NULL)
671*404b540aSrobert     return NULL;
672*404b540aSrobert 
673*404b540aSrobert   place = VEC_lower_bound (constraint_t, vec, &lookfor, constraint_less);
674*404b540aSrobert   if (place >= VEC_length (constraint_t, vec))
675*404b540aSrobert     return NULL;
676*404b540aSrobert   found = VEC_index (constraint_t, vec, place);
677*404b540aSrobert   if (!constraint_equal (*found, lookfor))
678*404b540aSrobert     return NULL;
679*404b540aSrobert   return found;
680*404b540aSrobert }
681*404b540aSrobert 
682*404b540aSrobert /* Union two constraint vectors, TO and FROM.  Put the result in TO.  */
683*404b540aSrobert 
684*404b540aSrobert static void
constraint_set_union(VEC (constraint_t,heap)** to,VEC (constraint_t,heap)** from)685*404b540aSrobert constraint_set_union (VEC(constraint_t,heap) **to,
686*404b540aSrobert 		      VEC(constraint_t,heap) **from)
687*404b540aSrobert {
688*404b540aSrobert   int i;
689*404b540aSrobert   constraint_t c;
690*404b540aSrobert 
691*404b540aSrobert   for (i = 0; VEC_iterate (constraint_t, *from, i, c); i++)
692*404b540aSrobert     {
693*404b540aSrobert       if (constraint_vec_find (*to, *c) == NULL)
694*404b540aSrobert 	{
695*404b540aSrobert 	  unsigned int place = VEC_lower_bound (constraint_t, *to, c,
696*404b540aSrobert 						constraint_less);
697*404b540aSrobert 	  VEC_safe_insert (constraint_t, heap, *to, place, c);
698*404b540aSrobert 	}
699*404b540aSrobert     }
700*404b540aSrobert }
701*404b540aSrobert 
702*404b540aSrobert /* Take a solution set SET, add OFFSET to each member of the set, and
703*404b540aSrobert    overwrite SET with the result when done.  */
704*404b540aSrobert 
705*404b540aSrobert static void
solution_set_add(bitmap set,unsigned HOST_WIDE_INT offset)706*404b540aSrobert solution_set_add (bitmap set, unsigned HOST_WIDE_INT offset)
707*404b540aSrobert {
708*404b540aSrobert   bitmap result = BITMAP_ALLOC (&iteration_obstack);
709*404b540aSrobert   unsigned int i;
710*404b540aSrobert   bitmap_iterator bi;
711*404b540aSrobert   unsigned HOST_WIDE_INT min = -1, max = 0;
712*404b540aSrobert 
713*404b540aSrobert   /* Compute set of vars we can reach from set + offset.  */
714*404b540aSrobert 
715*404b540aSrobert   EXECUTE_IF_SET_IN_BITMAP (set, 0, i, bi)
716*404b540aSrobert     {
717*404b540aSrobert       if (get_varinfo (i)->is_artificial_var
718*404b540aSrobert 	  || get_varinfo (i)->has_union
719*404b540aSrobert 	  || get_varinfo (i)->is_unknown_size_var)
720*404b540aSrobert 	continue;
721*404b540aSrobert 
722*404b540aSrobert       if (get_varinfo (i)->offset + offset < min)
723*404b540aSrobert 	min = get_varinfo (i)->offset + offset;
724*404b540aSrobert       if (get_varinfo (i)->offset + get_varinfo (i)->size + offset > max)
725*404b540aSrobert 	{
726*404b540aSrobert 	  max = get_varinfo (i)->offset + get_varinfo (i)->size + offset;
727*404b540aSrobert 	  if (max > get_varinfo (i)->fullsize)
728*404b540aSrobert 	    max = get_varinfo (i)->fullsize;
729*404b540aSrobert 	}
730*404b540aSrobert     }
731*404b540aSrobert 
732*404b540aSrobert   EXECUTE_IF_SET_IN_BITMAP (set, 0, i, bi)
733*404b540aSrobert     {
734*404b540aSrobert       /* If this is a properly sized variable, only add offset if it's
735*404b540aSrobert 	 less than end.  Otherwise, it is globbed to a single
736*404b540aSrobert 	 variable.  */
737*404b540aSrobert 
738*404b540aSrobert       if (get_varinfo (i)->offset + get_varinfo (i)->size - 1 >= min
739*404b540aSrobert 	  && get_varinfo (i)->offset < max)
740*404b540aSrobert 	{
741*404b540aSrobert 	  bitmap_set_bit (result, i);
742*404b540aSrobert 	}
743*404b540aSrobert       else if (get_varinfo (i)->is_artificial_var
744*404b540aSrobert 	       || get_varinfo (i)->has_union
745*404b540aSrobert 	       || get_varinfo (i)->is_unknown_size_var)
746*404b540aSrobert 	{
747*404b540aSrobert 	  bitmap_set_bit (result, i);
748*404b540aSrobert 	}
749*404b540aSrobert     }
750*404b540aSrobert 
751*404b540aSrobert   bitmap_copy (set, result);
752*404b540aSrobert   BITMAP_FREE (result);
753*404b540aSrobert }
754*404b540aSrobert 
755*404b540aSrobert /* Union solution sets TO and FROM, and add INC to each member of FROM in the
756*404b540aSrobert    process.  */
757*404b540aSrobert 
758*404b540aSrobert static bool
set_union_with_increment(bitmap to,bitmap from,unsigned HOST_WIDE_INT inc)759*404b540aSrobert set_union_with_increment  (bitmap to, bitmap from, unsigned HOST_WIDE_INT inc)
760*404b540aSrobert {
761*404b540aSrobert   if (inc == 0)
762*404b540aSrobert     return bitmap_ior_into (to, from);
763*404b540aSrobert   else
764*404b540aSrobert     {
765*404b540aSrobert       bitmap tmp;
766*404b540aSrobert       bool res;
767*404b540aSrobert 
768*404b540aSrobert       tmp = BITMAP_ALLOC (&iteration_obstack);
769*404b540aSrobert       bitmap_copy (tmp, from);
770*404b540aSrobert       solution_set_add (tmp, inc);
771*404b540aSrobert       res = bitmap_ior_into (to, tmp);
772*404b540aSrobert       BITMAP_FREE (tmp);
773*404b540aSrobert       return res;
774*404b540aSrobert     }
775*404b540aSrobert }
776*404b540aSrobert 
777*404b540aSrobert /* Insert constraint C into the list of complex constraints for graph
778*404b540aSrobert    node VAR.  */
779*404b540aSrobert 
780*404b540aSrobert static void
insert_into_complex(constraint_graph_t graph,unsigned int var,constraint_t c)781*404b540aSrobert insert_into_complex (constraint_graph_t graph,
782*404b540aSrobert 		     unsigned int var, constraint_t c)
783*404b540aSrobert {
784*404b540aSrobert   VEC (constraint_t, heap) *complex = graph->complex[var];
785*404b540aSrobert   unsigned int place = VEC_lower_bound (constraint_t, complex, c,
786*404b540aSrobert 					constraint_less);
787*404b540aSrobert 
788*404b540aSrobert   /* Only insert constraints that do not already exist.  */
789*404b540aSrobert   if (place >= VEC_length (constraint_t, complex)
790*404b540aSrobert       || !constraint_equal (*c, *VEC_index (constraint_t, complex, place)))
791*404b540aSrobert     VEC_safe_insert (constraint_t, heap, graph->complex[var], place, c);
792*404b540aSrobert }
793*404b540aSrobert 
794*404b540aSrobert 
795*404b540aSrobert /* Condense two variable nodes into a single variable node, by moving
796*404b540aSrobert    all associated info from SRC to TO.  */
797*404b540aSrobert 
798*404b540aSrobert static void
merge_node_constraints(constraint_graph_t graph,unsigned int to,unsigned int from)799*404b540aSrobert merge_node_constraints (constraint_graph_t graph, unsigned int to,
800*404b540aSrobert 			unsigned int from)
801*404b540aSrobert {
802*404b540aSrobert   unsigned int i;
803*404b540aSrobert   constraint_t c;
804*404b540aSrobert 
805*404b540aSrobert   gcc_assert (find (from) == to);
806*404b540aSrobert 
807*404b540aSrobert   /* Move all complex constraints from src node into to node  */
808*404b540aSrobert   for (i = 0; VEC_iterate (constraint_t, graph->complex[from], i, c); i++)
809*404b540aSrobert     {
810*404b540aSrobert       /* In complex constraints for node src, we may have either
811*404b540aSrobert 	 a = *src, and *src = a, or an offseted constraint which are
812*404b540aSrobert 	 always added to the rhs node's constraints.  */
813*404b540aSrobert 
814*404b540aSrobert       if (c->rhs.type == DEREF)
815*404b540aSrobert 	c->rhs.var = to;
816*404b540aSrobert       else if (c->lhs.type == DEREF)
817*404b540aSrobert 	c->lhs.var = to;
818*404b540aSrobert       else
819*404b540aSrobert 	c->rhs.var = to;
820*404b540aSrobert     }
821*404b540aSrobert   constraint_set_union (&graph->complex[to], &graph->complex[from]);
822*404b540aSrobert   VEC_free (constraint_t, heap, graph->complex[from]);
823*404b540aSrobert   graph->complex[from] = NULL;
824*404b540aSrobert }
825*404b540aSrobert 
826*404b540aSrobert 
827*404b540aSrobert /* Remove edges involving NODE from GRAPH.  */
828*404b540aSrobert 
829*404b540aSrobert static void
clear_edges_for_node(constraint_graph_t graph,unsigned int node)830*404b540aSrobert clear_edges_for_node (constraint_graph_t graph, unsigned int node)
831*404b540aSrobert {
832*404b540aSrobert   if (graph->succs[node])
833*404b540aSrobert     BITMAP_FREE (graph->succs[node]);
834*404b540aSrobert }
835*404b540aSrobert 
836*404b540aSrobert /* Merge GRAPH nodes FROM and TO into node TO.  */
837*404b540aSrobert 
838*404b540aSrobert static void
merge_graph_nodes(constraint_graph_t graph,unsigned int to,unsigned int from)839*404b540aSrobert merge_graph_nodes (constraint_graph_t graph, unsigned int to,
840*404b540aSrobert 		   unsigned int from)
841*404b540aSrobert {
842*404b540aSrobert   if (graph->indirect_cycles[from] != -1)
843*404b540aSrobert     {
844*404b540aSrobert       /* If we have indirect cycles with the from node, and we have
845*404b540aSrobert 	 none on the to node, the to node has indirect cycles from the
846*404b540aSrobert 	 from node now that they are unified.
847*404b540aSrobert 	 If indirect cycles exist on both, unify the nodes that they
848*404b540aSrobert 	 are in a cycle with, since we know they are in a cycle with
849*404b540aSrobert 	 each other.  */
850*404b540aSrobert       if (graph->indirect_cycles[to] == -1)
851*404b540aSrobert 	{
852*404b540aSrobert 	  graph->indirect_cycles[to] = graph->indirect_cycles[from];
853*404b540aSrobert 	}
854*404b540aSrobert       else
855*404b540aSrobert 	{
856*404b540aSrobert 	  unsigned int tonode = find (graph->indirect_cycles[to]);
857*404b540aSrobert 	  unsigned int fromnode = find (graph->indirect_cycles[from]);
858*404b540aSrobert 
859*404b540aSrobert 	  if (unite (tonode, fromnode))
860*404b540aSrobert 	    unify_nodes (graph, tonode, fromnode, true);
861*404b540aSrobert 	}
862*404b540aSrobert     }
863*404b540aSrobert 
864*404b540aSrobert   /* Merge all the successor edges.  */
865*404b540aSrobert   if (graph->succs[from])
866*404b540aSrobert     {
867*404b540aSrobert       if (!graph->succs[to])
868*404b540aSrobert 	graph->succs[to] = BITMAP_ALLOC (&pta_obstack);
869*404b540aSrobert       bitmap_ior_into (graph->succs[to],
870*404b540aSrobert 		       graph->succs[from]);
871*404b540aSrobert     }
872*404b540aSrobert 
873*404b540aSrobert   clear_edges_for_node (graph, from);
874*404b540aSrobert }
875*404b540aSrobert 
876*404b540aSrobert 
877*404b540aSrobert /* Add an indirect graph edge to GRAPH, going from TO to FROM if
878*404b540aSrobert    it doesn't exist in the graph already.  */
879*404b540aSrobert 
880*404b540aSrobert static void
add_implicit_graph_edge(constraint_graph_t graph,unsigned int to,unsigned int from)881*404b540aSrobert add_implicit_graph_edge (constraint_graph_t graph, unsigned int to,
882*404b540aSrobert 			 unsigned int from)
883*404b540aSrobert {
884*404b540aSrobert   if (to == from)
885*404b540aSrobert     return;
886*404b540aSrobert 
887*404b540aSrobert   if (!graph->implicit_preds[to])
888*404b540aSrobert     graph->implicit_preds[to] = BITMAP_ALLOC (&predbitmap_obstack);
889*404b540aSrobert 
890*404b540aSrobert   if (!bitmap_bit_p (graph->implicit_preds[to], from))
891*404b540aSrobert     {
892*404b540aSrobert       stats.num_implicit_edges++;
893*404b540aSrobert       bitmap_set_bit (graph->implicit_preds[to], from);
894*404b540aSrobert     }
895*404b540aSrobert }
896*404b540aSrobert 
897*404b540aSrobert /* Add a predecessor graph edge to GRAPH, going from TO to FROM if
898*404b540aSrobert    it doesn't exist in the graph already.
899*404b540aSrobert    Return false if the edge already existed, true otherwise.  */
900*404b540aSrobert 
901*404b540aSrobert static void
add_pred_graph_edge(constraint_graph_t graph,unsigned int to,unsigned int from)902*404b540aSrobert add_pred_graph_edge (constraint_graph_t graph, unsigned int to,
903*404b540aSrobert 		     unsigned int from)
904*404b540aSrobert {
905*404b540aSrobert   if (!graph->preds[to])
906*404b540aSrobert     graph->preds[to] = BITMAP_ALLOC (&predbitmap_obstack);
907*404b540aSrobert   if (!bitmap_bit_p (graph->preds[to], from))
908*404b540aSrobert     bitmap_set_bit (graph->preds[to], from);
909*404b540aSrobert }
910*404b540aSrobert 
911*404b540aSrobert /* Add a graph edge to GRAPH, going from FROM to TO if
912*404b540aSrobert    it doesn't exist in the graph already.
913*404b540aSrobert    Return false if the edge already existed, true otherwise.  */
914*404b540aSrobert 
915*404b540aSrobert static bool
add_graph_edge(constraint_graph_t graph,unsigned int to,unsigned int from)916*404b540aSrobert add_graph_edge (constraint_graph_t graph, unsigned int to,
917*404b540aSrobert 		unsigned int from)
918*404b540aSrobert {
919*404b540aSrobert   if (to == from)
920*404b540aSrobert     {
921*404b540aSrobert       return false;
922*404b540aSrobert     }
923*404b540aSrobert   else
924*404b540aSrobert     {
925*404b540aSrobert       bool r = false;
926*404b540aSrobert 
927*404b540aSrobert       if (!graph->succs[from])
928*404b540aSrobert 	graph->succs[from] = BITMAP_ALLOC (&pta_obstack);
929*404b540aSrobert       if (!bitmap_bit_p (graph->succs[from], to))
930*404b540aSrobert 	{
931*404b540aSrobert 	  r = true;
932*404b540aSrobert 	  if (to < FIRST_REF_NODE && from < FIRST_REF_NODE)
933*404b540aSrobert 	    stats.num_edges++;
934*404b540aSrobert 	  bitmap_set_bit (graph->succs[from], to);
935*404b540aSrobert 	}
936*404b540aSrobert       return r;
937*404b540aSrobert     }
938*404b540aSrobert }
939*404b540aSrobert 
940*404b540aSrobert 
941*404b540aSrobert /* Return true if {DEST.SRC} is an existing graph edge in GRAPH.  */
942*404b540aSrobert 
943*404b540aSrobert static bool
valid_graph_edge(constraint_graph_t graph,unsigned int src,unsigned int dest)944*404b540aSrobert valid_graph_edge (constraint_graph_t graph, unsigned int src,
945*404b540aSrobert 		  unsigned int dest)
946*404b540aSrobert {
947*404b540aSrobert   return (graph->succs[dest]
948*404b540aSrobert 	  && bitmap_bit_p (graph->succs[dest], src));
949*404b540aSrobert }
950*404b540aSrobert 
951*404b540aSrobert /* Build the constraint graph, adding only predecessor edges right now.  */
952*404b540aSrobert 
953*404b540aSrobert static void
build_pred_graph(void)954*404b540aSrobert build_pred_graph (void)
955*404b540aSrobert {
956*404b540aSrobert   int i;
957*404b540aSrobert   constraint_t c;
958*404b540aSrobert   unsigned int j;
959*404b540aSrobert 
960*404b540aSrobert   graph = XNEW (struct constraint_graph);
961*404b540aSrobert   graph->size = (VEC_length (varinfo_t, varmap)) * 3;
962*404b540aSrobert   graph->succs = XCNEWVEC (bitmap, graph->size);
963*404b540aSrobert   graph->implicit_preds = XCNEWVEC (bitmap, graph->size);
964*404b540aSrobert   graph->preds = XCNEWVEC (bitmap, graph->size);
965*404b540aSrobert   graph->indirect_cycles = XNEWVEC (int, VEC_length (varinfo_t, varmap));
966*404b540aSrobert   graph->label = XCNEWVEC (unsigned int, graph->size);
967*404b540aSrobert   graph->rep = XNEWVEC (unsigned int, graph->size);
968*404b540aSrobert   graph->eq_rep = XNEWVEC (int, graph->size);
969*404b540aSrobert   graph->complex = XCNEWVEC (VEC(constraint_t, heap) *,
970*404b540aSrobert 			     VEC_length (varinfo_t, varmap));
971*404b540aSrobert   graph->direct_nodes = sbitmap_alloc (graph->size);
972*404b540aSrobert   sbitmap_zero (graph->direct_nodes);
973*404b540aSrobert 
974*404b540aSrobert   for (j = 0; j < FIRST_REF_NODE; j++)
975*404b540aSrobert     {
976*404b540aSrobert       if (!get_varinfo (j)->is_special_var)
977*404b540aSrobert 	SET_BIT (graph->direct_nodes, j);
978*404b540aSrobert     }
979*404b540aSrobert 
980*404b540aSrobert   for (j = 0; j < graph->size; j++)
981*404b540aSrobert     {
982*404b540aSrobert       graph->rep[j] = j;
983*404b540aSrobert       graph->eq_rep[j] = -1;
984*404b540aSrobert     }
985*404b540aSrobert 
986*404b540aSrobert   for (j = 0; j < VEC_length (varinfo_t, varmap); j++)
987*404b540aSrobert     graph->indirect_cycles[j] = -1;
988*404b540aSrobert 
989*404b540aSrobert   for (i = 0; VEC_iterate (constraint_t, constraints, i, c); i++)
990*404b540aSrobert     {
991*404b540aSrobert       struct constraint_expr lhs = c->lhs;
992*404b540aSrobert       struct constraint_expr rhs = c->rhs;
993*404b540aSrobert       unsigned int lhsvar = get_varinfo_fc (lhs.var)->id;
994*404b540aSrobert       unsigned int rhsvar = get_varinfo_fc (rhs.var)->id;
995*404b540aSrobert 
996*404b540aSrobert       if (lhs.type == DEREF)
997*404b540aSrobert 	{
998*404b540aSrobert 	  /* *x = y.  */
999*404b540aSrobert 	  if (rhs.offset == 0 && lhs.offset == 0 && rhs.type == SCALAR)
1000*404b540aSrobert 	    add_pred_graph_edge (graph, FIRST_REF_NODE + lhsvar, rhsvar);
1001*404b540aSrobert 	  if (rhs.type == ADDRESSOF)
1002*404b540aSrobert 	    RESET_BIT (graph->direct_nodes, rhsvar);
1003*404b540aSrobert 	}
1004*404b540aSrobert       else if (rhs.type == DEREF)
1005*404b540aSrobert 	{
1006*404b540aSrobert 	  /* x = *y */
1007*404b540aSrobert 	  if (rhs.offset == 0 && lhs.offset == 0 && lhs.type == SCALAR)
1008*404b540aSrobert 	    add_pred_graph_edge (graph, lhsvar, FIRST_REF_NODE + rhsvar);
1009*404b540aSrobert 	  else
1010*404b540aSrobert 	    RESET_BIT (graph->direct_nodes, lhsvar);
1011*404b540aSrobert 	}
1012*404b540aSrobert       else if (rhs.type == ADDRESSOF)
1013*404b540aSrobert 	{
1014*404b540aSrobert 	  /* x = &y */
1015*404b540aSrobert 	  add_pred_graph_edge (graph, lhsvar, FIRST_ADDR_NODE + rhsvar);
1016*404b540aSrobert 	  /* Implicitly, *x = y */
1017*404b540aSrobert 	  add_implicit_graph_edge (graph, FIRST_REF_NODE + lhsvar, rhsvar);
1018*404b540aSrobert 
1019*404b540aSrobert 	  RESET_BIT (graph->direct_nodes, rhsvar);
1020*404b540aSrobert 	}
1021*404b540aSrobert       else if (lhsvar > anything_id
1022*404b540aSrobert 	       && lhsvar != rhsvar && lhs.offset == 0 && rhs.offset == 0)
1023*404b540aSrobert 	{
1024*404b540aSrobert 	  /* x = y */
1025*404b540aSrobert 	  add_pred_graph_edge (graph, lhsvar, rhsvar);
1026*404b540aSrobert 	  /* Implicitly, *x = *y */
1027*404b540aSrobert 	  add_implicit_graph_edge (graph, FIRST_REF_NODE + lhsvar,
1028*404b540aSrobert 				   FIRST_REF_NODE + rhsvar);
1029*404b540aSrobert 	}
1030*404b540aSrobert       else if (lhs.offset != 0 || rhs.offset != 0)
1031*404b540aSrobert 	{
1032*404b540aSrobert 	  if (rhs.offset != 0)
1033*404b540aSrobert 	    RESET_BIT (graph->direct_nodes, lhs.var);
1034*404b540aSrobert 	  if (lhs.offset != 0)
1035*404b540aSrobert 	    RESET_BIT (graph->direct_nodes, rhs.var);
1036*404b540aSrobert 	}
1037*404b540aSrobert     }
1038*404b540aSrobert }
1039*404b540aSrobert 
1040*404b540aSrobert /* Build the constraint graph, adding successor edges.  */
1041*404b540aSrobert 
1042*404b540aSrobert static void
build_succ_graph(void)1043*404b540aSrobert build_succ_graph (void)
1044*404b540aSrobert {
1045*404b540aSrobert   int i;
1046*404b540aSrobert   constraint_t c;
1047*404b540aSrobert 
1048*404b540aSrobert   for (i = 0; VEC_iterate (constraint_t, constraints, i, c); i++)
1049*404b540aSrobert     {
1050*404b540aSrobert       struct constraint_expr lhs;
1051*404b540aSrobert       struct constraint_expr rhs;
1052*404b540aSrobert       unsigned int lhsvar;
1053*404b540aSrobert       unsigned int rhsvar;
1054*404b540aSrobert 
1055*404b540aSrobert       if (!c)
1056*404b540aSrobert 	continue;
1057*404b540aSrobert 
1058*404b540aSrobert       lhs = c->lhs;
1059*404b540aSrobert       rhs = c->rhs;
1060*404b540aSrobert       lhsvar = find (get_varinfo_fc (lhs.var)->id);
1061*404b540aSrobert       rhsvar = find (get_varinfo_fc (rhs.var)->id);
1062*404b540aSrobert 
1063*404b540aSrobert       if (lhs.type == DEREF)
1064*404b540aSrobert 	{
1065*404b540aSrobert 	  if (rhs.offset == 0 && lhs.offset == 0 && rhs.type == SCALAR)
1066*404b540aSrobert 	    add_graph_edge (graph, FIRST_REF_NODE + lhsvar, rhsvar);
1067*404b540aSrobert 	}
1068*404b540aSrobert       else if (rhs.type == DEREF)
1069*404b540aSrobert 	{
1070*404b540aSrobert 	  if (rhs.offset == 0 && lhs.offset == 0 && lhs.type == SCALAR)
1071*404b540aSrobert 	    add_graph_edge (graph, lhsvar, FIRST_REF_NODE + rhsvar);
1072*404b540aSrobert 	}
1073*404b540aSrobert       else if (rhs.type == ADDRESSOF)
1074*404b540aSrobert 	{
1075*404b540aSrobert 	  /* x = &y */
1076*404b540aSrobert 	  gcc_assert (find (get_varinfo_fc (rhs.var)->id)
1077*404b540aSrobert 		      == get_varinfo_fc (rhs.var)->id);
1078*404b540aSrobert 	  bitmap_set_bit (get_varinfo (lhsvar)->solution, rhsvar);
1079*404b540aSrobert 	}
1080*404b540aSrobert       else if (lhsvar > anything_id
1081*404b540aSrobert 	       && lhsvar != rhsvar && lhs.offset == 0 && rhs.offset == 0)
1082*404b540aSrobert 	{
1083*404b540aSrobert 	  add_graph_edge (graph, lhsvar, rhsvar);
1084*404b540aSrobert 	}
1085*404b540aSrobert     }
1086*404b540aSrobert }
1087*404b540aSrobert 
1088*404b540aSrobert 
1089*404b540aSrobert /* Changed variables on the last iteration.  */
1090*404b540aSrobert static unsigned int changed_count;
1091*404b540aSrobert static sbitmap changed;
1092*404b540aSrobert 
1093*404b540aSrobert DEF_VEC_I(unsigned);
1094*404b540aSrobert DEF_VEC_ALLOC_I(unsigned,heap);
1095*404b540aSrobert 
1096*404b540aSrobert 
1097*404b540aSrobert /* Strongly Connected Component visitation info.  */
1098*404b540aSrobert 
1099*404b540aSrobert struct scc_info
1100*404b540aSrobert {
1101*404b540aSrobert   sbitmap visited;
1102*404b540aSrobert   sbitmap roots;
1103*404b540aSrobert   unsigned int *dfs;
1104*404b540aSrobert   unsigned int *node_mapping;
1105*404b540aSrobert   int current_index;
1106*404b540aSrobert   VEC(unsigned,heap) *scc_stack;
1107*404b540aSrobert };
1108*404b540aSrobert 
1109*404b540aSrobert 
1110*404b540aSrobert /* Recursive routine to find strongly connected components in GRAPH.
1111*404b540aSrobert    SI is the SCC info to store the information in, and N is the id of current
1112*404b540aSrobert    graph node we are processing.
1113*404b540aSrobert 
1114*404b540aSrobert    This is Tarjan's strongly connected component finding algorithm, as
1115*404b540aSrobert    modified by Nuutila to keep only non-root nodes on the stack.
1116*404b540aSrobert    The algorithm can be found in "On finding the strongly connected
1117*404b540aSrobert    connected components in a directed graph" by Esko Nuutila and Eljas
1118*404b540aSrobert    Soisalon-Soininen, in Information Processing Letters volume 49,
1119*404b540aSrobert    number 1, pages 9-14.  */
1120*404b540aSrobert 
1121*404b540aSrobert static void
scc_visit(constraint_graph_t graph,struct scc_info * si,unsigned int n)1122*404b540aSrobert scc_visit (constraint_graph_t graph, struct scc_info *si, unsigned int n)
1123*404b540aSrobert {
1124*404b540aSrobert   unsigned int i;
1125*404b540aSrobert   bitmap_iterator bi;
1126*404b540aSrobert   unsigned int my_dfs;
1127*404b540aSrobert 
1128*404b540aSrobert   SET_BIT (si->visited, n);
1129*404b540aSrobert   si->dfs[n] = si->current_index ++;
1130*404b540aSrobert   my_dfs = si->dfs[n];
1131*404b540aSrobert 
1132*404b540aSrobert   /* Visit all the successors.  */
1133*404b540aSrobert   EXECUTE_IF_IN_NONNULL_BITMAP (graph->succs[n], 0, i, bi)
1134*404b540aSrobert     {
1135*404b540aSrobert       unsigned int w;
1136*404b540aSrobert 
1137*404b540aSrobert       if (i > LAST_REF_NODE)
1138*404b540aSrobert 	break;
1139*404b540aSrobert 
1140*404b540aSrobert       w = find (i);
1141*404b540aSrobert       if (TEST_BIT (si->roots, w))
1142*404b540aSrobert 	continue;
1143*404b540aSrobert 
1144*404b540aSrobert       if (!TEST_BIT (si->visited, w))
1145*404b540aSrobert 	scc_visit (graph, si, w);
1146*404b540aSrobert       {
1147*404b540aSrobert 	unsigned int t = find (w);
1148*404b540aSrobert 	unsigned int nnode = find (n);
1149*404b540aSrobert 	gcc_assert (nnode == n);
1150*404b540aSrobert 
1151*404b540aSrobert 	if (si->dfs[t] < si->dfs[nnode])
1152*404b540aSrobert 	  si->dfs[n] = si->dfs[t];
1153*404b540aSrobert       }
1154*404b540aSrobert     }
1155*404b540aSrobert 
1156*404b540aSrobert   /* See if any components have been identified.  */
1157*404b540aSrobert   if (si->dfs[n] == my_dfs)
1158*404b540aSrobert     {
1159*404b540aSrobert       if (VEC_length (unsigned, si->scc_stack) > 0
1160*404b540aSrobert 	  && si->dfs[VEC_last (unsigned, si->scc_stack)] >= my_dfs)
1161*404b540aSrobert 	{
1162*404b540aSrobert 	  bitmap scc = BITMAP_ALLOC (NULL);
1163*404b540aSrobert 	  bool have_ref_node = n >= FIRST_REF_NODE;
1164*404b540aSrobert 	  unsigned int lowest_node;
1165*404b540aSrobert 	  bitmap_iterator bi;
1166*404b540aSrobert 
1167*404b540aSrobert 	  bitmap_set_bit (scc, n);
1168*404b540aSrobert 
1169*404b540aSrobert 	  while (VEC_length (unsigned, si->scc_stack) != 0
1170*404b540aSrobert 		 && si->dfs[VEC_last (unsigned, si->scc_stack)] >= my_dfs)
1171*404b540aSrobert 	    {
1172*404b540aSrobert 	      unsigned int w = VEC_pop (unsigned, si->scc_stack);
1173*404b540aSrobert 
1174*404b540aSrobert 	      bitmap_set_bit (scc, w);
1175*404b540aSrobert 	      if (w >= FIRST_REF_NODE)
1176*404b540aSrobert 		have_ref_node = true;
1177*404b540aSrobert 	    }
1178*404b540aSrobert 
1179*404b540aSrobert 	  lowest_node = bitmap_first_set_bit (scc);
1180*404b540aSrobert 	  gcc_assert (lowest_node < FIRST_REF_NODE);
1181*404b540aSrobert 	  EXECUTE_IF_SET_IN_BITMAP (scc, 0, i, bi)
1182*404b540aSrobert 	    {
1183*404b540aSrobert 	      if (i < FIRST_REF_NODE)
1184*404b540aSrobert 		{
1185*404b540aSrobert 		  /* Mark this node for collapsing.  */
1186*404b540aSrobert 		  if (unite (lowest_node, i))
1187*404b540aSrobert 		    unify_nodes (graph, lowest_node, i, false);
1188*404b540aSrobert 		}
1189*404b540aSrobert 	      else
1190*404b540aSrobert 		{
1191*404b540aSrobert 		  unite (lowest_node, i);
1192*404b540aSrobert 		  graph->indirect_cycles[i - FIRST_REF_NODE] = lowest_node;
1193*404b540aSrobert 		}
1194*404b540aSrobert 	    }
1195*404b540aSrobert 	}
1196*404b540aSrobert       SET_BIT (si->roots, n);
1197*404b540aSrobert     }
1198*404b540aSrobert   else
1199*404b540aSrobert     VEC_safe_push (unsigned, heap, si->scc_stack, n);
1200*404b540aSrobert }
1201*404b540aSrobert 
1202*404b540aSrobert /* Unify node FROM into node TO, updating the changed count if
1203*404b540aSrobert    necessary when UPDATE_CHANGED is true.  */
1204*404b540aSrobert 
1205*404b540aSrobert static void
unify_nodes(constraint_graph_t graph,unsigned int to,unsigned int from,bool update_changed)1206*404b540aSrobert unify_nodes (constraint_graph_t graph, unsigned int to, unsigned int from,
1207*404b540aSrobert 	     bool update_changed)
1208*404b540aSrobert {
1209*404b540aSrobert 
1210*404b540aSrobert   gcc_assert (to != from && find (to) == to);
1211*404b540aSrobert   if (dump_file && (dump_flags & TDF_DETAILS))
1212*404b540aSrobert     fprintf (dump_file, "Unifying %s to %s\n",
1213*404b540aSrobert 	     get_varinfo (from)->name,
1214*404b540aSrobert 	     get_varinfo (to)->name);
1215*404b540aSrobert 
1216*404b540aSrobert   if (update_changed)
1217*404b540aSrobert     stats.unified_vars_dynamic++;
1218*404b540aSrobert   else
1219*404b540aSrobert     stats.unified_vars_static++;
1220*404b540aSrobert 
1221*404b540aSrobert   merge_graph_nodes (graph, to, from);
1222*404b540aSrobert   merge_node_constraints (graph, to, from);
1223*404b540aSrobert 
1224*404b540aSrobert   if (update_changed && TEST_BIT (changed, from))
1225*404b540aSrobert     {
1226*404b540aSrobert       RESET_BIT (changed, from);
1227*404b540aSrobert       if (!TEST_BIT (changed, to))
1228*404b540aSrobert 	SET_BIT (changed, to);
1229*404b540aSrobert       else
1230*404b540aSrobert 	{
1231*404b540aSrobert 	  gcc_assert (changed_count > 0);
1232*404b540aSrobert 	  changed_count--;
1233*404b540aSrobert 	}
1234*404b540aSrobert     }
1235*404b540aSrobert 
1236*404b540aSrobert   /* If the solution changes because of the merging, we need to mark
1237*404b540aSrobert      the variable as changed.  */
1238*404b540aSrobert   if (bitmap_ior_into (get_varinfo (to)->solution,
1239*404b540aSrobert 		       get_varinfo (from)->solution))
1240*404b540aSrobert     {
1241*404b540aSrobert       if (update_changed && !TEST_BIT (changed, to))
1242*404b540aSrobert 	{
1243*404b540aSrobert 	  SET_BIT (changed, to);
1244*404b540aSrobert 	  changed_count++;
1245*404b540aSrobert 	}
1246*404b540aSrobert     }
1247*404b540aSrobert 
1248*404b540aSrobert   BITMAP_FREE (get_varinfo (from)->solution);
1249*404b540aSrobert   BITMAP_FREE (get_varinfo (from)->oldsolution);
1250*404b540aSrobert 
1251*404b540aSrobert   if (stats.iterations > 0)
1252*404b540aSrobert     {
1253*404b540aSrobert       BITMAP_FREE (get_varinfo (to)->oldsolution);
1254*404b540aSrobert       get_varinfo (to)->oldsolution = BITMAP_ALLOC (&oldpta_obstack);
1255*404b540aSrobert     }
1256*404b540aSrobert 
1257*404b540aSrobert   if (valid_graph_edge (graph, to, to))
1258*404b540aSrobert     {
1259*404b540aSrobert       if (graph->succs[to])
1260*404b540aSrobert 	bitmap_clear_bit (graph->succs[to], to);
1261*404b540aSrobert     }
1262*404b540aSrobert }
1263*404b540aSrobert 
1264*404b540aSrobert /* Information needed to compute the topological ordering of a graph.  */
1265*404b540aSrobert 
1266*404b540aSrobert struct topo_info
1267*404b540aSrobert {
1268*404b540aSrobert   /* sbitmap of visited nodes.  */
1269*404b540aSrobert   sbitmap visited;
1270*404b540aSrobert   /* Array that stores the topological order of the graph, *in
1271*404b540aSrobert      reverse*.  */
1272*404b540aSrobert   VEC(unsigned,heap) *topo_order;
1273*404b540aSrobert };
1274*404b540aSrobert 
1275*404b540aSrobert 
1276*404b540aSrobert /* Initialize and return a topological info structure.  */
1277*404b540aSrobert 
1278*404b540aSrobert static struct topo_info *
init_topo_info(void)1279*404b540aSrobert init_topo_info (void)
1280*404b540aSrobert {
1281*404b540aSrobert   size_t size = VEC_length (varinfo_t, varmap);
1282*404b540aSrobert   struct topo_info *ti = XNEW (struct topo_info);
1283*404b540aSrobert   ti->visited = sbitmap_alloc (size);
1284*404b540aSrobert   sbitmap_zero (ti->visited);
1285*404b540aSrobert   ti->topo_order = VEC_alloc (unsigned, heap, 1);
1286*404b540aSrobert   return ti;
1287*404b540aSrobert }
1288*404b540aSrobert 
1289*404b540aSrobert 
1290*404b540aSrobert /* Free the topological sort info pointed to by TI.  */
1291*404b540aSrobert 
1292*404b540aSrobert static void
free_topo_info(struct topo_info * ti)1293*404b540aSrobert free_topo_info (struct topo_info *ti)
1294*404b540aSrobert {
1295*404b540aSrobert   sbitmap_free (ti->visited);
1296*404b540aSrobert   VEC_free (unsigned, heap, ti->topo_order);
1297*404b540aSrobert   free (ti);
1298*404b540aSrobert }
1299*404b540aSrobert 
1300*404b540aSrobert /* Visit the graph in topological order, and store the order in the
1301*404b540aSrobert    topo_info structure.  */
1302*404b540aSrobert 
1303*404b540aSrobert static void
topo_visit(constraint_graph_t graph,struct topo_info * ti,unsigned int n)1304*404b540aSrobert topo_visit (constraint_graph_t graph, struct topo_info *ti,
1305*404b540aSrobert 	    unsigned int n)
1306*404b540aSrobert {
1307*404b540aSrobert   bitmap_iterator bi;
1308*404b540aSrobert   unsigned int j;
1309*404b540aSrobert 
1310*404b540aSrobert   SET_BIT (ti->visited, n);
1311*404b540aSrobert 
1312*404b540aSrobert   if (graph->succs[n])
1313*404b540aSrobert     EXECUTE_IF_SET_IN_BITMAP (graph->succs[n], 0, j, bi)
1314*404b540aSrobert       {
1315*404b540aSrobert 	if (!TEST_BIT (ti->visited, j))
1316*404b540aSrobert 	  topo_visit (graph, ti, j);
1317*404b540aSrobert       }
1318*404b540aSrobert 
1319*404b540aSrobert   VEC_safe_push (unsigned, heap, ti->topo_order, n);
1320*404b540aSrobert }
1321*404b540aSrobert 
1322*404b540aSrobert /* Return true if variable N + OFFSET is a legal field of N.  */
1323*404b540aSrobert 
1324*404b540aSrobert static bool
type_safe(unsigned int n,unsigned HOST_WIDE_INT * offset)1325*404b540aSrobert type_safe (unsigned int n, unsigned HOST_WIDE_INT *offset)
1326*404b540aSrobert {
1327*404b540aSrobert   varinfo_t ninfo = get_varinfo (n);
1328*404b540aSrobert 
1329*404b540aSrobert   /* For things we've globbed to single variables, any offset into the
1330*404b540aSrobert      variable acts like the entire variable, so that it becomes offset
1331*404b540aSrobert      0.  */
1332*404b540aSrobert   if (ninfo->is_special_var
1333*404b540aSrobert       || ninfo->is_artificial_var
1334*404b540aSrobert       || ninfo->is_unknown_size_var)
1335*404b540aSrobert     {
1336*404b540aSrobert       *offset = 0;
1337*404b540aSrobert       return true;
1338*404b540aSrobert     }
1339*404b540aSrobert   return (get_varinfo (n)->offset + *offset) < get_varinfo (n)->fullsize;
1340*404b540aSrobert }
1341*404b540aSrobert 
1342*404b540aSrobert /* Process a constraint C that represents *x = &y.  */
1343*404b540aSrobert 
1344*404b540aSrobert static void
do_da_constraint(constraint_graph_t graph ATTRIBUTE_UNUSED,constraint_t c,bitmap delta)1345*404b540aSrobert do_da_constraint (constraint_graph_t graph ATTRIBUTE_UNUSED,
1346*404b540aSrobert 		  constraint_t c, bitmap delta)
1347*404b540aSrobert {
1348*404b540aSrobert   unsigned int rhs = c->rhs.var;
1349*404b540aSrobert   unsigned int j;
1350*404b540aSrobert   bitmap_iterator bi;
1351*404b540aSrobert 
1352*404b540aSrobert   /* For each member j of Delta (Sol(x)), add x to Sol(j)  */
1353*404b540aSrobert   EXECUTE_IF_SET_IN_BITMAP (delta, 0, j, bi)
1354*404b540aSrobert     {
1355*404b540aSrobert       unsigned HOST_WIDE_INT offset = c->lhs.offset;
1356*404b540aSrobert       if (type_safe (j, &offset) && !(get_varinfo (j)->is_special_var))
1357*404b540aSrobert 	{
1358*404b540aSrobert 	/* *x != NULL && *x != ANYTHING*/
1359*404b540aSrobert 	  varinfo_t v;
1360*404b540aSrobert 	  unsigned int t;
1361*404b540aSrobert 	  bitmap sol;
1362*404b540aSrobert 	  unsigned HOST_WIDE_INT fieldoffset = get_varinfo (j)->offset + offset;
1363*404b540aSrobert 
1364*404b540aSrobert 	  v = first_vi_for_offset (get_varinfo (j), fieldoffset);
1365*404b540aSrobert 	  if (!v)
1366*404b540aSrobert 	    continue;
1367*404b540aSrobert 	  t = find (v->id);
1368*404b540aSrobert 	  sol = get_varinfo (t)->solution;
1369*404b540aSrobert 	  if (!bitmap_bit_p (sol, rhs))
1370*404b540aSrobert 	    {
1371*404b540aSrobert 	      bitmap_set_bit (sol, rhs);
1372*404b540aSrobert 	      if (!TEST_BIT (changed, t))
1373*404b540aSrobert 		{
1374*404b540aSrobert 		  SET_BIT (changed, t);
1375*404b540aSrobert 		  changed_count++;
1376*404b540aSrobert 		}
1377*404b540aSrobert 	    }
1378*404b540aSrobert 	}
1379*404b540aSrobert       else if (0 && dump_file && !(get_varinfo (j)->is_special_var))
1380*404b540aSrobert 	fprintf (dump_file, "Untypesafe usage in do_da_constraint.\n");
1381*404b540aSrobert 
1382*404b540aSrobert     }
1383*404b540aSrobert }
1384*404b540aSrobert 
1385*404b540aSrobert /* Process a constraint C that represents x = *y, using DELTA as the
1386*404b540aSrobert    starting solution.  */
1387*404b540aSrobert 
1388*404b540aSrobert static void
do_sd_constraint(constraint_graph_t graph,constraint_t c,bitmap delta)1389*404b540aSrobert do_sd_constraint (constraint_graph_t graph, constraint_t c,
1390*404b540aSrobert 		  bitmap delta)
1391*404b540aSrobert {
1392*404b540aSrobert   unsigned int lhs = find (c->lhs.var);
1393*404b540aSrobert   bool flag = false;
1394*404b540aSrobert   bitmap sol = get_varinfo (lhs)->solution;
1395*404b540aSrobert   unsigned int j;
1396*404b540aSrobert   bitmap_iterator bi;
1397*404b540aSrobert 
1398*404b540aSrobert  if (bitmap_bit_p (delta, anything_id))
1399*404b540aSrobert    {
1400*404b540aSrobert      flag = !bitmap_bit_p (sol, anything_id);
1401*404b540aSrobert      if (flag)
1402*404b540aSrobert        bitmap_set_bit (sol, anything_id);
1403*404b540aSrobert      goto done;
1404*404b540aSrobert    }
1405*404b540aSrobert   /* For each variable j in delta (Sol(y)), add
1406*404b540aSrobert      an edge in the graph from j to x, and union Sol(j) into Sol(x).  */
1407*404b540aSrobert   EXECUTE_IF_SET_IN_BITMAP (delta, 0, j, bi)
1408*404b540aSrobert     {
1409*404b540aSrobert       unsigned HOST_WIDE_INT roffset = c->rhs.offset;
1410*404b540aSrobert       if (type_safe (j, &roffset))
1411*404b540aSrobert 	{
1412*404b540aSrobert 	  varinfo_t v;
1413*404b540aSrobert 	  unsigned HOST_WIDE_INT fieldoffset = get_varinfo (j)->offset + roffset;
1414*404b540aSrobert 	  unsigned int t;
1415*404b540aSrobert 
1416*404b540aSrobert 	  v = first_vi_for_offset (get_varinfo (j), fieldoffset);
1417*404b540aSrobert 	  if (!v)
1418*404b540aSrobert 	    continue;
1419*404b540aSrobert 	  t = find (v->id);
1420*404b540aSrobert 
1421*404b540aSrobert 	  /* Adding edges from the special vars is pointless.
1422*404b540aSrobert 	     They don't have sets that can change.  */
1423*404b540aSrobert 	  if (get_varinfo (t) ->is_special_var)
1424*404b540aSrobert 	    flag |= bitmap_ior_into (sol, get_varinfo (t)->solution);
1425*404b540aSrobert 	  else if (add_graph_edge (graph, lhs, t))
1426*404b540aSrobert 	    flag |= bitmap_ior_into (sol, get_varinfo (t)->solution);
1427*404b540aSrobert 	}
1428*404b540aSrobert       else if (0 && dump_file && !(get_varinfo (j)->is_special_var))
1429*404b540aSrobert 	fprintf (dump_file, "Untypesafe usage in do_sd_constraint\n");
1430*404b540aSrobert 
1431*404b540aSrobert     }
1432*404b540aSrobert 
1433*404b540aSrobert done:
1434*404b540aSrobert   /* If the LHS solution changed, mark the var as changed.  */
1435*404b540aSrobert   if (flag)
1436*404b540aSrobert     {
1437*404b540aSrobert       get_varinfo (lhs)->solution = sol;
1438*404b540aSrobert       if (!TEST_BIT (changed, lhs))
1439*404b540aSrobert 	{
1440*404b540aSrobert 	  SET_BIT (changed, lhs);
1441*404b540aSrobert 	  changed_count++;
1442*404b540aSrobert 	}
1443*404b540aSrobert     }
1444*404b540aSrobert }
1445*404b540aSrobert 
1446*404b540aSrobert /* Process a constraint C that represents *x = y.  */
1447*404b540aSrobert 
1448*404b540aSrobert static void
do_ds_constraint(constraint_t c,bitmap delta)1449*404b540aSrobert do_ds_constraint (constraint_t c, bitmap delta)
1450*404b540aSrobert {
1451*404b540aSrobert   unsigned int rhs = find (c->rhs.var);
1452*404b540aSrobert   unsigned HOST_WIDE_INT roff = c->rhs.offset;
1453*404b540aSrobert   bitmap sol = get_varinfo (rhs)->solution;
1454*404b540aSrobert   unsigned int j;
1455*404b540aSrobert   bitmap_iterator bi;
1456*404b540aSrobert 
1457*404b540aSrobert  if (bitmap_bit_p (sol, anything_id))
1458*404b540aSrobert    {
1459*404b540aSrobert      EXECUTE_IF_SET_IN_BITMAP (delta, 0, j, bi)
1460*404b540aSrobert        {
1461*404b540aSrobert 	 varinfo_t jvi = get_varinfo (j);
1462*404b540aSrobert 	 unsigned int t;
1463*404b540aSrobert 	 unsigned int loff = c->lhs.offset;
1464*404b540aSrobert 	 unsigned HOST_WIDE_INT fieldoffset = jvi->offset + loff;
1465*404b540aSrobert 	 varinfo_t v;
1466*404b540aSrobert 
1467*404b540aSrobert 	 v = first_vi_for_offset (get_varinfo (j), fieldoffset);
1468*404b540aSrobert 	 if (!v)
1469*404b540aSrobert 	   continue;
1470*404b540aSrobert 	 t = find (v->id);
1471*404b540aSrobert 
1472*404b540aSrobert 	 if (!bitmap_bit_p (get_varinfo (t)->solution, anything_id))
1473*404b540aSrobert 	   {
1474*404b540aSrobert 	     bitmap_set_bit (get_varinfo (t)->solution, anything_id);
1475*404b540aSrobert 	     if (!TEST_BIT (changed, t))
1476*404b540aSrobert 	       {
1477*404b540aSrobert 		 SET_BIT (changed, t);
1478*404b540aSrobert 		 changed_count++;
1479*404b540aSrobert 	       }
1480*404b540aSrobert 	   }
1481*404b540aSrobert        }
1482*404b540aSrobert      return;
1483*404b540aSrobert    }
1484*404b540aSrobert 
1485*404b540aSrobert   /* For each member j of delta (Sol(x)), add an edge from y to j and
1486*404b540aSrobert      union Sol(y) into Sol(j) */
1487*404b540aSrobert   EXECUTE_IF_SET_IN_BITMAP (delta, 0, j, bi)
1488*404b540aSrobert     {
1489*404b540aSrobert       unsigned HOST_WIDE_INT loff = c->lhs.offset;
1490*404b540aSrobert       if (type_safe (j, &loff) && !(get_varinfo (j)->is_special_var))
1491*404b540aSrobert 	{
1492*404b540aSrobert 	  varinfo_t v;
1493*404b540aSrobert 	  unsigned int t;
1494*404b540aSrobert 	  unsigned HOST_WIDE_INT fieldoffset = get_varinfo (j)->offset + loff;
1495*404b540aSrobert 	  bitmap tmp;
1496*404b540aSrobert 
1497*404b540aSrobert 	  v = first_vi_for_offset (get_varinfo (j), fieldoffset);
1498*404b540aSrobert 	  if (!v)
1499*404b540aSrobert 	    continue;
1500*404b540aSrobert 	  t = find (v->id);
1501*404b540aSrobert 	  tmp = get_varinfo (t)->solution;
1502*404b540aSrobert 
1503*404b540aSrobert 	  if (set_union_with_increment (tmp, sol, roff))
1504*404b540aSrobert 	    {
1505*404b540aSrobert 	      get_varinfo (t)->solution = tmp;
1506*404b540aSrobert 	      if (t == rhs)
1507*404b540aSrobert 		sol = get_varinfo (rhs)->solution;
1508*404b540aSrobert 	      if (!TEST_BIT (changed, t))
1509*404b540aSrobert 		{
1510*404b540aSrobert 		  SET_BIT (changed, t);
1511*404b540aSrobert 		  changed_count++;
1512*404b540aSrobert 		}
1513*404b540aSrobert 	    }
1514*404b540aSrobert 	}
1515*404b540aSrobert       else if (0 && dump_file && !(get_varinfo (j)->is_special_var))
1516*404b540aSrobert 	fprintf (dump_file, "Untypesafe usage in do_ds_constraint\n");
1517*404b540aSrobert     }
1518*404b540aSrobert }
1519*404b540aSrobert 
1520*404b540aSrobert /* Handle a non-simple (simple meaning requires no iteration),
1521*404b540aSrobert    constraint (IE *x = &y, x = *y, *x = y, and x = y with offsets involved).  */
1522*404b540aSrobert 
1523*404b540aSrobert static void
do_complex_constraint(constraint_graph_t graph,constraint_t c,bitmap delta)1524*404b540aSrobert do_complex_constraint (constraint_graph_t graph, constraint_t c, bitmap delta)
1525*404b540aSrobert {
1526*404b540aSrobert   if (c->lhs.type == DEREF)
1527*404b540aSrobert     {
1528*404b540aSrobert       if (c->rhs.type == ADDRESSOF)
1529*404b540aSrobert 	{
1530*404b540aSrobert 	  /* *x = &y */
1531*404b540aSrobert 	  do_da_constraint (graph, c, delta);
1532*404b540aSrobert 	}
1533*404b540aSrobert       else
1534*404b540aSrobert 	{
1535*404b540aSrobert 	  /* *x = y */
1536*404b540aSrobert 	  do_ds_constraint (c, delta);
1537*404b540aSrobert 	}
1538*404b540aSrobert     }
1539*404b540aSrobert   else if (c->rhs.type == DEREF)
1540*404b540aSrobert     {
1541*404b540aSrobert       /* x = *y */
1542*404b540aSrobert       if (!(get_varinfo (c->lhs.var)->is_special_var))
1543*404b540aSrobert 	do_sd_constraint (graph, c, delta);
1544*404b540aSrobert     }
1545*404b540aSrobert   else
1546*404b540aSrobert     {
1547*404b540aSrobert       bitmap tmp;
1548*404b540aSrobert       bitmap solution;
1549*404b540aSrobert       bool flag = false;
1550*404b540aSrobert       unsigned int t;
1551*404b540aSrobert 
1552*404b540aSrobert       gcc_assert (c->rhs.type == SCALAR && c->lhs.type == SCALAR);
1553*404b540aSrobert       t = find (c->rhs.var);
1554*404b540aSrobert       solution = get_varinfo (t)->solution;
1555*404b540aSrobert       t = find (c->lhs.var);
1556*404b540aSrobert       tmp = get_varinfo (t)->solution;
1557*404b540aSrobert 
1558*404b540aSrobert       flag = set_union_with_increment (tmp, solution, c->rhs.offset);
1559*404b540aSrobert 
1560*404b540aSrobert       if (flag)
1561*404b540aSrobert 	{
1562*404b540aSrobert 	  get_varinfo (t)->solution = tmp;
1563*404b540aSrobert 	  if (!TEST_BIT (changed, t))
1564*404b540aSrobert 	    {
1565*404b540aSrobert 	      SET_BIT (changed, t);
1566*404b540aSrobert 	      changed_count++;
1567*404b540aSrobert 	    }
1568*404b540aSrobert 	}
1569*404b540aSrobert     }
1570*404b540aSrobert }
1571*404b540aSrobert 
1572*404b540aSrobert /* Initialize and return a new SCC info structure.  */
1573*404b540aSrobert 
1574*404b540aSrobert static struct scc_info *
init_scc_info(size_t size)1575*404b540aSrobert init_scc_info (size_t size)
1576*404b540aSrobert {
1577*404b540aSrobert   struct scc_info *si = XNEW (struct scc_info);
1578*404b540aSrobert   size_t i;
1579*404b540aSrobert 
1580*404b540aSrobert   si->current_index = 0;
1581*404b540aSrobert   si->visited = sbitmap_alloc (size);
1582*404b540aSrobert   sbitmap_zero (si->visited);
1583*404b540aSrobert   si->roots = sbitmap_alloc (size);
1584*404b540aSrobert   sbitmap_zero (si->roots);
1585*404b540aSrobert   si->node_mapping = XNEWVEC (unsigned int, size);
1586*404b540aSrobert   si->dfs = XCNEWVEC (unsigned int, size);
1587*404b540aSrobert 
1588*404b540aSrobert   for (i = 0; i < size; i++)
1589*404b540aSrobert     si->node_mapping[i] = i;
1590*404b540aSrobert 
1591*404b540aSrobert   si->scc_stack = VEC_alloc (unsigned, heap, 1);
1592*404b540aSrobert   return si;
1593*404b540aSrobert }
1594*404b540aSrobert 
1595*404b540aSrobert /* Free an SCC info structure pointed to by SI */
1596*404b540aSrobert 
1597*404b540aSrobert static void
free_scc_info(struct scc_info * si)1598*404b540aSrobert free_scc_info (struct scc_info *si)
1599*404b540aSrobert {
1600*404b540aSrobert   sbitmap_free (si->visited);
1601*404b540aSrobert   sbitmap_free (si->roots);
1602*404b540aSrobert   free (si->node_mapping);
1603*404b540aSrobert   free (si->dfs);
1604*404b540aSrobert   VEC_free (unsigned, heap, si->scc_stack);
1605*404b540aSrobert   free (si);
1606*404b540aSrobert }
1607*404b540aSrobert 
1608*404b540aSrobert 
1609*404b540aSrobert /* Find indirect cycles in GRAPH that occur, using strongly connected
1610*404b540aSrobert    components, and note them in the indirect cycles map.
1611*404b540aSrobert 
1612*404b540aSrobert    This technique comes from Ben Hardekopf and Calvin Lin,
1613*404b540aSrobert    "It Pays to be Lazy: Fast and Accurate Pointer Analysis for Millions of
1614*404b540aSrobert    Lines of Code", submitted to PLDI 2007.  */
1615*404b540aSrobert 
1616*404b540aSrobert static void
find_indirect_cycles(constraint_graph_t graph)1617*404b540aSrobert find_indirect_cycles (constraint_graph_t graph)
1618*404b540aSrobert {
1619*404b540aSrobert   unsigned int i;
1620*404b540aSrobert   unsigned int size = graph->size;
1621*404b540aSrobert   struct scc_info *si = init_scc_info (size);
1622*404b540aSrobert 
1623*404b540aSrobert   for (i = 0; i < MIN (LAST_REF_NODE, size); i ++ )
1624*404b540aSrobert     if (!TEST_BIT (si->visited, i) && find (i) == i)
1625*404b540aSrobert       scc_visit (graph, si, i);
1626*404b540aSrobert 
1627*404b540aSrobert   free_scc_info (si);
1628*404b540aSrobert }
1629*404b540aSrobert 
1630*404b540aSrobert /* Compute a topological ordering for GRAPH, and store the result in the
1631*404b540aSrobert    topo_info structure TI.  */
1632*404b540aSrobert 
1633*404b540aSrobert static void
compute_topo_order(constraint_graph_t graph,struct topo_info * ti)1634*404b540aSrobert compute_topo_order (constraint_graph_t graph,
1635*404b540aSrobert 		    struct topo_info *ti)
1636*404b540aSrobert {
1637*404b540aSrobert   unsigned int i;
1638*404b540aSrobert   unsigned int size = VEC_length (varinfo_t, varmap);
1639*404b540aSrobert 
1640*404b540aSrobert   for (i = 0; i != size; ++i)
1641*404b540aSrobert     if (!TEST_BIT (ti->visited, i) && find (i) == i)
1642*404b540aSrobert       topo_visit (graph, ti, i);
1643*404b540aSrobert }
1644*404b540aSrobert 
1645*404b540aSrobert /* Perform offline variable substitution.
1646*404b540aSrobert 
1647*404b540aSrobert    This is a linear time way of identifying variables that must have
1648*404b540aSrobert    equivalent points-to sets, including those caused by static cycles,
1649*404b540aSrobert    and single entry subgraphs, in the constraint graph.
1650*404b540aSrobert 
1651*404b540aSrobert    The technique is described in "Off-line variable substitution for
1652*404b540aSrobert    scaling points-to analysis" by Atanas Rountev and Satish Chandra,
1653*404b540aSrobert    in "ACM SIGPLAN Notices" volume 35, number 5, pages 47-56.
1654*404b540aSrobert 
1655*404b540aSrobert    There is an optimal way to do this involving hash based value
1656*404b540aSrobert    numbering, once the technique is published i will implement it
1657*404b540aSrobert    here.
1658*404b540aSrobert 
1659*404b540aSrobert    The general method of finding equivalence classes is as follows:
1660*404b540aSrobert    Add fake nodes (REF nodes) and edges for *a = b and a = *b constraints.
1661*404b540aSrobert    Add fake nodes (ADDRESS nodes) and edges for a = &b constraints.
1662*404b540aSrobert    Initialize all non-REF/ADDRESS nodes to be direct nodes
1663*404b540aSrobert    For each SCC in the predecessor graph:
1664*404b540aSrobert       for each member (x) of the SCC
1665*404b540aSrobert          if x is not a direct node:
1666*404b540aSrobert 	   set rootnode(SCC) to be not a direct node
1667*404b540aSrobert 	 collapse node x into rootnode(SCC).
1668*404b540aSrobert       if rootnode(SCC) is not a direct node:
1669*404b540aSrobert         label rootnode(SCC) with a new equivalence class
1670*404b540aSrobert       else:
1671*404b540aSrobert         if all labeled predecessors of rootnode(SCC) have the same
1672*404b540aSrobert 	label:
1673*404b540aSrobert 	  label rootnode(SCC) with this label
1674*404b540aSrobert 	else:
1675*404b540aSrobert 	  label rootnode(SCC) with a new equivalence class
1676*404b540aSrobert 
1677*404b540aSrobert    All direct nodes with the same equivalence class can be replaced
1678*404b540aSrobert    with a single representative node.
1679*404b540aSrobert    All unlabeled nodes (label == 0) are not pointers and all edges
1680*404b540aSrobert    involving them can be eliminated.
1681*404b540aSrobert    We perform these optimizations during move_complex_constraints.
1682*404b540aSrobert */
1683*404b540aSrobert 
1684*404b540aSrobert static int equivalence_class;
1685*404b540aSrobert 
1686*404b540aSrobert /* Recursive routine to find strongly connected components in GRAPH,
1687*404b540aSrobert    and label it's nodes with equivalence classes.
1688*404b540aSrobert    This is used during variable substitution to find cycles involving
1689*404b540aSrobert    the regular or implicit predecessors, and label them as equivalent.
1690*404b540aSrobert    The SCC finding algorithm used is the same as that for scc_visit.  */
1691*404b540aSrobert 
1692*404b540aSrobert static void
label_visit(constraint_graph_t graph,struct scc_info * si,unsigned int n)1693*404b540aSrobert label_visit (constraint_graph_t graph, struct scc_info *si, unsigned int n)
1694*404b540aSrobert {
1695*404b540aSrobert   unsigned int i;
1696*404b540aSrobert   bitmap_iterator bi;
1697*404b540aSrobert   unsigned int my_dfs;
1698*404b540aSrobert 
1699*404b540aSrobert   gcc_assert (si->node_mapping[n] == n);
1700*404b540aSrobert   SET_BIT (si->visited, n);
1701*404b540aSrobert   si->dfs[n] = si->current_index ++;
1702*404b540aSrobert   my_dfs = si->dfs[n];
1703*404b540aSrobert 
1704*404b540aSrobert   /* Visit all the successors.  */
1705*404b540aSrobert   EXECUTE_IF_IN_NONNULL_BITMAP (graph->preds[n], 0, i, bi)
1706*404b540aSrobert     {
1707*404b540aSrobert       unsigned int w = si->node_mapping[i];
1708*404b540aSrobert 
1709*404b540aSrobert       if (TEST_BIT (si->roots, w))
1710*404b540aSrobert 	continue;
1711*404b540aSrobert 
1712*404b540aSrobert       if (!TEST_BIT (si->visited, w))
1713*404b540aSrobert 	label_visit (graph, si, w);
1714*404b540aSrobert       {
1715*404b540aSrobert 	unsigned int t = si->node_mapping[w];
1716*404b540aSrobert 	unsigned int nnode = si->node_mapping[n];
1717*404b540aSrobert 	gcc_assert (nnode == n);
1718*404b540aSrobert 
1719*404b540aSrobert 	if (si->dfs[t] < si->dfs[nnode])
1720*404b540aSrobert 	  si->dfs[n] = si->dfs[t];
1721*404b540aSrobert       }
1722*404b540aSrobert     }
1723*404b540aSrobert 
1724*404b540aSrobert   /* Visit all the implicit predecessors.  */
1725*404b540aSrobert   EXECUTE_IF_IN_NONNULL_BITMAP (graph->implicit_preds[n], 0, i, bi)
1726*404b540aSrobert     {
1727*404b540aSrobert       unsigned int w = si->node_mapping[i];
1728*404b540aSrobert 
1729*404b540aSrobert       if (TEST_BIT (si->roots, w))
1730*404b540aSrobert 	continue;
1731*404b540aSrobert 
1732*404b540aSrobert       if (!TEST_BIT (si->visited, w))
1733*404b540aSrobert 	label_visit (graph, si, w);
1734*404b540aSrobert       {
1735*404b540aSrobert 	unsigned int t = si->node_mapping[w];
1736*404b540aSrobert 	unsigned int nnode = si->node_mapping[n];
1737*404b540aSrobert 	gcc_assert (nnode == n);
1738*404b540aSrobert 
1739*404b540aSrobert 	if (si->dfs[t] < si->dfs[nnode])
1740*404b540aSrobert 	  si->dfs[n] = si->dfs[t];
1741*404b540aSrobert       }
1742*404b540aSrobert     }
1743*404b540aSrobert 
1744*404b540aSrobert   /* See if any components have been identified.  */
1745*404b540aSrobert   if (si->dfs[n] == my_dfs)
1746*404b540aSrobert     {
1747*404b540aSrobert       while (VEC_length (unsigned, si->scc_stack) != 0
1748*404b540aSrobert 	     && si->dfs[VEC_last (unsigned, si->scc_stack)] >= my_dfs)
1749*404b540aSrobert 	{
1750*404b540aSrobert 	  unsigned int w = VEC_pop (unsigned, si->scc_stack);
1751*404b540aSrobert 	  si->node_mapping[w] = n;
1752*404b540aSrobert 
1753*404b540aSrobert 	  if (!TEST_BIT (graph->direct_nodes, w))
1754*404b540aSrobert 	    RESET_BIT (graph->direct_nodes, n);
1755*404b540aSrobert 	}
1756*404b540aSrobert       SET_BIT (si->roots, n);
1757*404b540aSrobert 
1758*404b540aSrobert       if (!TEST_BIT (graph->direct_nodes, n))
1759*404b540aSrobert 	{
1760*404b540aSrobert 	  graph->label[n] = equivalence_class++;
1761*404b540aSrobert 	}
1762*404b540aSrobert       else
1763*404b540aSrobert 	{
1764*404b540aSrobert 	  unsigned int size = 0;
1765*404b540aSrobert 	  unsigned int firstlabel = ~0;
1766*404b540aSrobert 
1767*404b540aSrobert 	  EXECUTE_IF_IN_NONNULL_BITMAP (graph->preds[n], 0, i, bi)
1768*404b540aSrobert 	    {
1769*404b540aSrobert 	      unsigned int j = si->node_mapping[i];
1770*404b540aSrobert 
1771*404b540aSrobert 	      if (j == n || graph->label[j] == 0)
1772*404b540aSrobert 		continue;
1773*404b540aSrobert 
1774*404b540aSrobert 	      if (firstlabel == (unsigned int)~0)
1775*404b540aSrobert 		{
1776*404b540aSrobert 		  firstlabel = graph->label[j];
1777*404b540aSrobert 		  size++;
1778*404b540aSrobert 		}
1779*404b540aSrobert 	      else if (graph->label[j] != firstlabel)
1780*404b540aSrobert 		size++;
1781*404b540aSrobert 	    }
1782*404b540aSrobert 
1783*404b540aSrobert 	  if (size == 0)
1784*404b540aSrobert 	    graph->label[n] = 0;
1785*404b540aSrobert 	  else if (size == 1)
1786*404b540aSrobert 	    graph->label[n] = firstlabel;
1787*404b540aSrobert 	  else
1788*404b540aSrobert 	    graph->label[n] = equivalence_class++;
1789*404b540aSrobert 	}
1790*404b540aSrobert     }
1791*404b540aSrobert   else
1792*404b540aSrobert     VEC_safe_push (unsigned, heap, si->scc_stack, n);
1793*404b540aSrobert }
1794*404b540aSrobert 
1795*404b540aSrobert /* Perform offline variable substitution, discovering equivalence
1796*404b540aSrobert    classes, and eliminating non-pointer variables.  */
1797*404b540aSrobert 
1798*404b540aSrobert static struct scc_info *
perform_var_substitution(constraint_graph_t graph)1799*404b540aSrobert perform_var_substitution (constraint_graph_t graph)
1800*404b540aSrobert {
1801*404b540aSrobert   unsigned int i;
1802*404b540aSrobert   unsigned int size = graph->size;
1803*404b540aSrobert   struct scc_info *si = init_scc_info (size);
1804*404b540aSrobert 
1805*404b540aSrobert   bitmap_obstack_initialize (&iteration_obstack);
1806*404b540aSrobert   equivalence_class = 0;
1807*404b540aSrobert 
1808*404b540aSrobert   /* We only need to visit the non-address nodes for labeling
1809*404b540aSrobert      purposes, as the address nodes will never have any predecessors,
1810*404b540aSrobert      because &x never appears on the LHS of a constraint.  */
1811*404b540aSrobert   for (i = 0; i < LAST_REF_NODE; i++)
1812*404b540aSrobert     if (!TEST_BIT (si->visited, si->node_mapping[i]))
1813*404b540aSrobert       label_visit (graph, si, si->node_mapping[i]);
1814*404b540aSrobert 
1815*404b540aSrobert   if (dump_file && (dump_flags & TDF_DETAILS))
1816*404b540aSrobert     for (i = 0; i < FIRST_REF_NODE; i++)
1817*404b540aSrobert       {
1818*404b540aSrobert 	bool direct_node = TEST_BIT (graph->direct_nodes, i);
1819*404b540aSrobert 	fprintf (dump_file,
1820*404b540aSrobert 		 "Equivalence class for %s node id %d:%s is %d\n",
1821*404b540aSrobert 		 direct_node ? "Direct node" : "Indirect node", i,
1822*404b540aSrobert 		 get_varinfo (i)->name,
1823*404b540aSrobert 		 graph->label[si->node_mapping[i]]);
1824*404b540aSrobert       }
1825*404b540aSrobert 
1826*404b540aSrobert   /* Quickly eliminate our non-pointer variables.  */
1827*404b540aSrobert 
1828*404b540aSrobert   for (i = 0; i < FIRST_REF_NODE; i++)
1829*404b540aSrobert     {
1830*404b540aSrobert       unsigned int node = si->node_mapping[i];
1831*404b540aSrobert 
1832*404b540aSrobert       if (graph->label[node] == 0 && TEST_BIT (graph->direct_nodes, node))
1833*404b540aSrobert 	{
1834*404b540aSrobert 	  if (dump_file && (dump_flags & TDF_DETAILS))
1835*404b540aSrobert 	    fprintf (dump_file,
1836*404b540aSrobert 		     "%s is a non-pointer variable, eliminating edges.\n",
1837*404b540aSrobert 		     get_varinfo (node)->name);
1838*404b540aSrobert 	  stats.nonpointer_vars++;
1839*404b540aSrobert 	  clear_edges_for_node (graph, node);
1840*404b540aSrobert 	}
1841*404b540aSrobert     }
1842*404b540aSrobert   return si;
1843*404b540aSrobert }
1844*404b540aSrobert 
1845*404b540aSrobert /* Free information that was only necessary for variable
1846*404b540aSrobert    substitution.  */
1847*404b540aSrobert 
1848*404b540aSrobert static void
free_var_substitution_info(struct scc_info * si)1849*404b540aSrobert free_var_substitution_info (struct scc_info *si)
1850*404b540aSrobert {
1851*404b540aSrobert   free_scc_info (si);
1852*404b540aSrobert   free (graph->label);
1853*404b540aSrobert   free (graph->eq_rep);
1854*404b540aSrobert   sbitmap_free (graph->direct_nodes);
1855*404b540aSrobert   bitmap_obstack_release (&iteration_obstack);
1856*404b540aSrobert }
1857*404b540aSrobert 
1858*404b540aSrobert /* Return an existing node that is equivalent to NODE, which has
1859*404b540aSrobert    equivalence class LABEL, if one exists.  Return NODE otherwise.  */
1860*404b540aSrobert 
1861*404b540aSrobert static unsigned int
find_equivalent_node(constraint_graph_t graph,unsigned int node,unsigned int label)1862*404b540aSrobert find_equivalent_node (constraint_graph_t graph,
1863*404b540aSrobert 		      unsigned int node, unsigned int label)
1864*404b540aSrobert {
1865*404b540aSrobert   /* If the address version of this variable is unused, we can
1866*404b540aSrobert      substitute it for anything else with the same label.
1867*404b540aSrobert      Otherwise, we know the pointers are equivalent, but not the
1868*404b540aSrobert      locations.  */
1869*404b540aSrobert 
1870*404b540aSrobert   if (graph->label[FIRST_ADDR_NODE + node] == 0)
1871*404b540aSrobert     {
1872*404b540aSrobert       gcc_assert (label < graph->size);
1873*404b540aSrobert 
1874*404b540aSrobert       if (graph->eq_rep[label] != -1)
1875*404b540aSrobert 	{
1876*404b540aSrobert 	  /* Unify the two variables since we know they are equivalent.  */
1877*404b540aSrobert 	  if (unite (graph->eq_rep[label], node))
1878*404b540aSrobert 	    unify_nodes (graph, graph->eq_rep[label], node, false);
1879*404b540aSrobert 	  return graph->eq_rep[label];
1880*404b540aSrobert 	}
1881*404b540aSrobert       else
1882*404b540aSrobert 	{
1883*404b540aSrobert 	  graph->eq_rep[label] = node;
1884*404b540aSrobert 	}
1885*404b540aSrobert     }
1886*404b540aSrobert   return node;
1887*404b540aSrobert }
1888*404b540aSrobert 
1889*404b540aSrobert /* Move complex constraints to the appropriate nodes, and collapse
1890*404b540aSrobert    variables we've discovered are equivalent during variable
1891*404b540aSrobert    substitution.  SI is the SCC_INFO that is the result of
1892*404b540aSrobert    perform_variable_substitution.  */
1893*404b540aSrobert 
1894*404b540aSrobert static void
move_complex_constraints(constraint_graph_t graph,struct scc_info * si)1895*404b540aSrobert move_complex_constraints (constraint_graph_t graph,
1896*404b540aSrobert 			  struct scc_info *si)
1897*404b540aSrobert {
1898*404b540aSrobert   int i;
1899*404b540aSrobert   unsigned int j;
1900*404b540aSrobert   constraint_t c;
1901*404b540aSrobert 
1902*404b540aSrobert   for (j = 0; j < graph->size; j++)
1903*404b540aSrobert     gcc_assert (find (j) == j);
1904*404b540aSrobert 
1905*404b540aSrobert   for (i = 0; VEC_iterate (constraint_t, constraints, i, c); i++)
1906*404b540aSrobert     {
1907*404b540aSrobert       struct constraint_expr lhs = c->lhs;
1908*404b540aSrobert       struct constraint_expr rhs = c->rhs;
1909*404b540aSrobert       unsigned int lhsvar = find (get_varinfo_fc (lhs.var)->id);
1910*404b540aSrobert       unsigned int rhsvar = find (get_varinfo_fc (rhs.var)->id);
1911*404b540aSrobert       unsigned int lhsnode, rhsnode;
1912*404b540aSrobert       unsigned int lhslabel, rhslabel;
1913*404b540aSrobert 
1914*404b540aSrobert       lhsnode = si->node_mapping[lhsvar];
1915*404b540aSrobert       rhsnode = si->node_mapping[rhsvar];
1916*404b540aSrobert       lhslabel = graph->label[lhsnode];
1917*404b540aSrobert       rhslabel = graph->label[rhsnode];
1918*404b540aSrobert 
1919*404b540aSrobert       /* See if it is really a non-pointer variable, and if so, ignore
1920*404b540aSrobert 	 the constraint.  */
1921*404b540aSrobert       if (lhslabel == 0)
1922*404b540aSrobert 	{
1923*404b540aSrobert 	  if (!TEST_BIT (graph->direct_nodes, lhsnode))
1924*404b540aSrobert 	    lhslabel = graph->label[lhsnode] = equivalence_class++;
1925*404b540aSrobert 	  else
1926*404b540aSrobert 	    {
1927*404b540aSrobert 	      if (dump_file && (dump_flags & TDF_DETAILS))
1928*404b540aSrobert 		{
1929*404b540aSrobert 
1930*404b540aSrobert 		  fprintf (dump_file, "%s is a non-pointer variable,"
1931*404b540aSrobert 			   "ignoring constraint:",
1932*404b540aSrobert 			   get_varinfo (lhs.var)->name);
1933*404b540aSrobert 		  dump_constraint (dump_file, c);
1934*404b540aSrobert 		}
1935*404b540aSrobert 	      VEC_replace (constraint_t, constraints, i, NULL);
1936*404b540aSrobert 	      continue;
1937*404b540aSrobert 	    }
1938*404b540aSrobert 	}
1939*404b540aSrobert 
1940*404b540aSrobert       if (rhslabel == 0)
1941*404b540aSrobert 	{
1942*404b540aSrobert 	  if (!TEST_BIT (graph->direct_nodes, rhsnode))
1943*404b540aSrobert 	    rhslabel = graph->label[rhsnode] = equivalence_class++;
1944*404b540aSrobert 	  else
1945*404b540aSrobert 	    {
1946*404b540aSrobert 	      if (dump_file && (dump_flags & TDF_DETAILS))
1947*404b540aSrobert 		{
1948*404b540aSrobert 
1949*404b540aSrobert 		  fprintf (dump_file, "%s is a non-pointer variable,"
1950*404b540aSrobert 			   "ignoring constraint:",
1951*404b540aSrobert 			   get_varinfo (rhs.var)->name);
1952*404b540aSrobert 		  dump_constraint (dump_file, c);
1953*404b540aSrobert 		}
1954*404b540aSrobert 	      VEC_replace (constraint_t, constraints, i, NULL);
1955*404b540aSrobert 	      continue;
1956*404b540aSrobert 	    }
1957*404b540aSrobert 	}
1958*404b540aSrobert 
1959*404b540aSrobert       lhsvar = find_equivalent_node (graph, lhsvar, lhslabel);
1960*404b540aSrobert       rhsvar = find_equivalent_node (graph, rhsvar, rhslabel);
1961*404b540aSrobert       c->lhs.var = lhsvar;
1962*404b540aSrobert       c->rhs.var = rhsvar;
1963*404b540aSrobert 
1964*404b540aSrobert       if (lhs.type == DEREF)
1965*404b540aSrobert 	{
1966*404b540aSrobert 	  if (rhs.type == ADDRESSOF || rhsvar > anything_id)
1967*404b540aSrobert 	    insert_into_complex (graph, lhsvar, c);
1968*404b540aSrobert 	}
1969*404b540aSrobert       else if (rhs.type == DEREF)
1970*404b540aSrobert 	{
1971*404b540aSrobert 	  if (!(get_varinfo (lhsvar)->is_special_var))
1972*404b540aSrobert 	    insert_into_complex (graph, rhsvar, c);
1973*404b540aSrobert 	}
1974*404b540aSrobert       else if (rhs.type != ADDRESSOF && lhsvar > anything_id
1975*404b540aSrobert 	       && (lhs.offset != 0 || rhs.offset != 0))
1976*404b540aSrobert 	{
1977*404b540aSrobert 	  insert_into_complex (graph, rhsvar, c);
1978*404b540aSrobert 	}
1979*404b540aSrobert 
1980*404b540aSrobert     }
1981*404b540aSrobert }
1982*404b540aSrobert 
1983*404b540aSrobert /* Eliminate indirect cycles involving NODE.  Return true if NODE was
1984*404b540aSrobert    part of an SCC, false otherwise.  */
1985*404b540aSrobert 
1986*404b540aSrobert static bool
eliminate_indirect_cycles(unsigned int node)1987*404b540aSrobert eliminate_indirect_cycles (unsigned int node)
1988*404b540aSrobert {
1989*404b540aSrobert   if (graph->indirect_cycles[node] != -1
1990*404b540aSrobert       && !bitmap_empty_p (get_varinfo (node)->solution))
1991*404b540aSrobert     {
1992*404b540aSrobert       unsigned int i;
1993*404b540aSrobert       VEC(unsigned,heap) *queue = NULL;
1994*404b540aSrobert       int queuepos;
1995*404b540aSrobert       unsigned int to = find (graph->indirect_cycles[node]);
1996*404b540aSrobert       bitmap_iterator bi;
1997*404b540aSrobert 
1998*404b540aSrobert       /* We can't touch the solution set and call unify_nodes
1999*404b540aSrobert 	 at the same time, because unify_nodes is going to do
2000*404b540aSrobert 	 bitmap unions into it. */
2001*404b540aSrobert 
2002*404b540aSrobert       EXECUTE_IF_SET_IN_BITMAP (get_varinfo (node)->solution, 0, i, bi)
2003*404b540aSrobert 	{
2004*404b540aSrobert 	  if (find (i) == i && i != to)
2005*404b540aSrobert 	    {
2006*404b540aSrobert 	      if (unite (to, i))
2007*404b540aSrobert 		VEC_safe_push (unsigned, heap, queue, i);
2008*404b540aSrobert 	    }
2009*404b540aSrobert 	}
2010*404b540aSrobert 
2011*404b540aSrobert       for (queuepos = 0;
2012*404b540aSrobert 	   VEC_iterate (unsigned, queue, queuepos, i);
2013*404b540aSrobert 	   queuepos++)
2014*404b540aSrobert 	{
2015*404b540aSrobert 	  unify_nodes (graph, to, i, true);
2016*404b540aSrobert 	}
2017*404b540aSrobert       VEC_free (unsigned, heap, queue);
2018*404b540aSrobert       return true;
2019*404b540aSrobert     }
2020*404b540aSrobert   return false;
2021*404b540aSrobert }
2022*404b540aSrobert 
2023*404b540aSrobert /* Solve the constraint graph GRAPH using our worklist solver.
2024*404b540aSrobert    This is based on the PW* family of solvers from the "Efficient Field
2025*404b540aSrobert    Sensitive Pointer Analysis for C" paper.
2026*404b540aSrobert    It works by iterating over all the graph nodes, processing the complex
2027*404b540aSrobert    constraints and propagating the copy constraints, until everything stops
2028*404b540aSrobert    changed.  This corresponds to steps 6-8 in the solving list given above.  */
2029*404b540aSrobert 
2030*404b540aSrobert static void
solve_graph(constraint_graph_t graph)2031*404b540aSrobert solve_graph (constraint_graph_t graph)
2032*404b540aSrobert {
2033*404b540aSrobert   unsigned int size = VEC_length (varinfo_t, varmap);
2034*404b540aSrobert   unsigned int i;
2035*404b540aSrobert   bitmap pts;
2036*404b540aSrobert 
2037*404b540aSrobert   changed_count = 0;
2038*404b540aSrobert   changed = sbitmap_alloc (size);
2039*404b540aSrobert   sbitmap_zero (changed);
2040*404b540aSrobert 
2041*404b540aSrobert   /* Mark all initial non-collapsed nodes as changed.  */
2042*404b540aSrobert   for (i = 0; i < size; i++)
2043*404b540aSrobert     {
2044*404b540aSrobert       varinfo_t ivi = get_varinfo (i);
2045*404b540aSrobert       if (find (i) == i && !bitmap_empty_p (ivi->solution)
2046*404b540aSrobert 	  && ((graph->succs[i] && !bitmap_empty_p (graph->succs[i]))
2047*404b540aSrobert 	      || VEC_length (constraint_t, graph->complex[i]) > 0))
2048*404b540aSrobert 	{
2049*404b540aSrobert 	  SET_BIT (changed, i);
2050*404b540aSrobert 	  changed_count++;
2051*404b540aSrobert 	}
2052*404b540aSrobert     }
2053*404b540aSrobert 
2054*404b540aSrobert   /* Allocate a bitmap to be used to store the changed bits.  */
2055*404b540aSrobert   pts = BITMAP_ALLOC (&pta_obstack);
2056*404b540aSrobert 
2057*404b540aSrobert   while (changed_count > 0)
2058*404b540aSrobert     {
2059*404b540aSrobert       unsigned int i;
2060*404b540aSrobert       struct topo_info *ti = init_topo_info ();
2061*404b540aSrobert       stats.iterations++;
2062*404b540aSrobert 
2063*404b540aSrobert       bitmap_obstack_initialize (&iteration_obstack);
2064*404b540aSrobert 
2065*404b540aSrobert       compute_topo_order (graph, ti);
2066*404b540aSrobert 
2067*404b540aSrobert       while (VEC_length (unsigned, ti->topo_order) != 0)
2068*404b540aSrobert 	{
2069*404b540aSrobert 
2070*404b540aSrobert 	  i = VEC_pop (unsigned, ti->topo_order);
2071*404b540aSrobert 
2072*404b540aSrobert 	  /* If this variable is not a representative, skip it.  */
2073*404b540aSrobert 	  if (find (i) != i)
2074*404b540aSrobert 	    continue;
2075*404b540aSrobert 
2076*404b540aSrobert 	  /* In certain indirect cycle cases, we may merge this
2077*404b540aSrobert 	     variable to another.  */
2078*404b540aSrobert 	  if (eliminate_indirect_cycles (i) && find (i) != i)
2079*404b540aSrobert 	    continue;
2080*404b540aSrobert 
2081*404b540aSrobert 	  /* If the node has changed, we need to process the
2082*404b540aSrobert 	     complex constraints and outgoing edges again.  */
2083*404b540aSrobert 	  if (TEST_BIT (changed, i))
2084*404b540aSrobert 	    {
2085*404b540aSrobert 	      unsigned int j;
2086*404b540aSrobert 	      constraint_t c;
2087*404b540aSrobert 	      bitmap solution;
2088*404b540aSrobert 	      VEC(constraint_t,heap) *complex = graph->complex[i];
2089*404b540aSrobert 	      bool solution_empty;
2090*404b540aSrobert 
2091*404b540aSrobert 	      RESET_BIT (changed, i);
2092*404b540aSrobert 	      changed_count--;
2093*404b540aSrobert 
2094*404b540aSrobert 	      /* Compute the changed set of solution bits.  */
2095*404b540aSrobert 	      bitmap_and_compl (pts, get_varinfo (i)->solution,
2096*404b540aSrobert 				get_varinfo (i)->oldsolution);
2097*404b540aSrobert 
2098*404b540aSrobert 	      if (bitmap_empty_p (pts))
2099*404b540aSrobert 		continue;
2100*404b540aSrobert 
2101*404b540aSrobert 	      bitmap_ior_into (get_varinfo (i)->oldsolution, pts);
2102*404b540aSrobert 
2103*404b540aSrobert 	      solution = get_varinfo (i)->solution;
2104*404b540aSrobert 	      solution_empty = bitmap_empty_p (solution);
2105*404b540aSrobert 
2106*404b540aSrobert 	      /* Process the complex constraints */
2107*404b540aSrobert 	      for (j = 0; VEC_iterate (constraint_t, complex, j, c); j++)
2108*404b540aSrobert 		{
2109*404b540aSrobert 		  /* The only complex constraint that can change our
2110*404b540aSrobert 		     solution to non-empty, given an empty solution,
2111*404b540aSrobert 		     is a constraint where the lhs side is receiving
2112*404b540aSrobert 		     some set from elsewhere.  */
2113*404b540aSrobert 		  if (!solution_empty || c->lhs.type != DEREF)
2114*404b540aSrobert 		    do_complex_constraint (graph, c, pts);
2115*404b540aSrobert 		}
2116*404b540aSrobert 
2117*404b540aSrobert 	      solution_empty = bitmap_empty_p (solution);
2118*404b540aSrobert 
2119*404b540aSrobert 	      if (!solution_empty)
2120*404b540aSrobert 		{
2121*404b540aSrobert 		  bitmap_iterator bi;
2122*404b540aSrobert 
2123*404b540aSrobert 		  /* Propagate solution to all successors.  */
2124*404b540aSrobert 		  EXECUTE_IF_IN_NONNULL_BITMAP (graph->succs[i],
2125*404b540aSrobert 						0, j, bi)
2126*404b540aSrobert 		    {
2127*404b540aSrobert 		      bitmap tmp;
2128*404b540aSrobert 		      bool flag;
2129*404b540aSrobert 
2130*404b540aSrobert 		      unsigned int to = find (j);
2131*404b540aSrobert 		      tmp = get_varinfo (to)->solution;
2132*404b540aSrobert 		      flag = false;
2133*404b540aSrobert 
2134*404b540aSrobert 		      /* Don't try to propagate to ourselves.  */
2135*404b540aSrobert 		      if (to == i)
2136*404b540aSrobert 			continue;
2137*404b540aSrobert 
2138*404b540aSrobert 		      flag = set_union_with_increment (tmp, pts, 0);
2139*404b540aSrobert 
2140*404b540aSrobert 		      if (flag)
2141*404b540aSrobert 			{
2142*404b540aSrobert 			  get_varinfo (to)->solution = tmp;
2143*404b540aSrobert 			  if (!TEST_BIT (changed, to))
2144*404b540aSrobert 			    {
2145*404b540aSrobert 			      SET_BIT (changed, to);
2146*404b540aSrobert 			      changed_count++;
2147*404b540aSrobert 			    }
2148*404b540aSrobert 			}
2149*404b540aSrobert 		    }
2150*404b540aSrobert 		}
2151*404b540aSrobert 	    }
2152*404b540aSrobert 	}
2153*404b540aSrobert       free_topo_info (ti);
2154*404b540aSrobert       bitmap_obstack_release (&iteration_obstack);
2155*404b540aSrobert     }
2156*404b540aSrobert 
2157*404b540aSrobert   BITMAP_FREE (pts);
2158*404b540aSrobert   sbitmap_free (changed);
2159*404b540aSrobert   bitmap_obstack_release (&oldpta_obstack);
2160*404b540aSrobert }
2161*404b540aSrobert 
2162*404b540aSrobert /* Map from trees to variable infos.  */
2163*404b540aSrobert static struct pointer_map_t *vi_for_tree;
2164*404b540aSrobert 
2165*404b540aSrobert 
2166*404b540aSrobert /* Insert ID as the variable id for tree T in the vi_for_tree map.  */
2167*404b540aSrobert 
2168*404b540aSrobert static void
insert_vi_for_tree(tree t,varinfo_t vi)2169*404b540aSrobert insert_vi_for_tree (tree t, varinfo_t vi)
2170*404b540aSrobert {
2171*404b540aSrobert   void **slot = pointer_map_insert (vi_for_tree, t);
2172*404b540aSrobert   gcc_assert (vi);
2173*404b540aSrobert   gcc_assert (*slot == NULL);
2174*404b540aSrobert   *slot = vi;
2175*404b540aSrobert }
2176*404b540aSrobert 
2177*404b540aSrobert /* Find the variable info for tree T in VI_FOR_TREE.  If T does not
2178*404b540aSrobert    exist in the map, return NULL, otherwise, return the varinfo we found.  */
2179*404b540aSrobert 
2180*404b540aSrobert static varinfo_t
lookup_vi_for_tree(tree t)2181*404b540aSrobert lookup_vi_for_tree (tree t)
2182*404b540aSrobert {
2183*404b540aSrobert   void **slot = pointer_map_contains (vi_for_tree, t);
2184*404b540aSrobert   if (slot == NULL)
2185*404b540aSrobert     return NULL;
2186*404b540aSrobert 
2187*404b540aSrobert   return (varinfo_t) *slot;
2188*404b540aSrobert }
2189*404b540aSrobert 
2190*404b540aSrobert /* Return a printable name for DECL  */
2191*404b540aSrobert 
2192*404b540aSrobert static const char *
alias_get_name(tree decl)2193*404b540aSrobert alias_get_name (tree decl)
2194*404b540aSrobert {
2195*404b540aSrobert   const char *res = get_name (decl);
2196*404b540aSrobert   char *temp;
2197*404b540aSrobert   int num_printed = 0;
2198*404b540aSrobert 
2199*404b540aSrobert   if (res != NULL)
2200*404b540aSrobert     return res;
2201*404b540aSrobert 
2202*404b540aSrobert   res = "NULL";
2203*404b540aSrobert   if (!dump_file)
2204*404b540aSrobert     return res;
2205*404b540aSrobert 
2206*404b540aSrobert   if (TREE_CODE (decl) == SSA_NAME)
2207*404b540aSrobert     {
2208*404b540aSrobert       num_printed = asprintf (&temp, "%s_%u",
2209*404b540aSrobert 			      alias_get_name (SSA_NAME_VAR (decl)),
2210*404b540aSrobert 			      SSA_NAME_VERSION (decl));
2211*404b540aSrobert     }
2212*404b540aSrobert   else if (DECL_P (decl))
2213*404b540aSrobert     {
2214*404b540aSrobert       num_printed = asprintf (&temp, "D.%u", DECL_UID (decl));
2215*404b540aSrobert     }
2216*404b540aSrobert   if (num_printed > 0)
2217*404b540aSrobert     {
2218*404b540aSrobert       res = ggc_strdup (temp);
2219*404b540aSrobert       free (temp);
2220*404b540aSrobert     }
2221*404b540aSrobert   return res;
2222*404b540aSrobert }
2223*404b540aSrobert 
2224*404b540aSrobert /* Find the variable id for tree T in the map.
2225*404b540aSrobert    If T doesn't exist in the map, create an entry for it and return it.  */
2226*404b540aSrobert 
2227*404b540aSrobert static varinfo_t
get_vi_for_tree(tree t)2228*404b540aSrobert get_vi_for_tree (tree t)
2229*404b540aSrobert {
2230*404b540aSrobert   void **slot = pointer_map_contains (vi_for_tree, t);
2231*404b540aSrobert   if (slot == NULL)
2232*404b540aSrobert     return get_varinfo (create_variable_info_for (t, alias_get_name (t)));
2233*404b540aSrobert 
2234*404b540aSrobert   return (varinfo_t) *slot;
2235*404b540aSrobert }
2236*404b540aSrobert 
2237*404b540aSrobert /* Get a constraint expression from an SSA_VAR_P node.  */
2238*404b540aSrobert 
2239*404b540aSrobert static struct constraint_expr
get_constraint_exp_from_ssa_var(tree t)2240*404b540aSrobert get_constraint_exp_from_ssa_var (tree t)
2241*404b540aSrobert {
2242*404b540aSrobert   struct constraint_expr cexpr;
2243*404b540aSrobert 
2244*404b540aSrobert   gcc_assert (SSA_VAR_P (t) || DECL_P (t));
2245*404b540aSrobert 
2246*404b540aSrobert   /* For parameters, get at the points-to set for the actual parm
2247*404b540aSrobert      decl.  */
2248*404b540aSrobert   if (TREE_CODE (t) == SSA_NAME
2249*404b540aSrobert       && TREE_CODE (SSA_NAME_VAR (t)) == PARM_DECL
2250*404b540aSrobert       && default_def (SSA_NAME_VAR (t)) == t)
2251*404b540aSrobert     return get_constraint_exp_from_ssa_var (SSA_NAME_VAR (t));
2252*404b540aSrobert 
2253*404b540aSrobert   cexpr.type = SCALAR;
2254*404b540aSrobert 
2255*404b540aSrobert   cexpr.var = get_vi_for_tree (t)->id;
2256*404b540aSrobert   /* If we determine the result is "anything", and we know this is readonly,
2257*404b540aSrobert      say it points to readonly memory instead.  */
2258*404b540aSrobert   if (cexpr.var == anything_id && TREE_READONLY (t))
2259*404b540aSrobert     {
2260*404b540aSrobert       cexpr.type = ADDRESSOF;
2261*404b540aSrobert       cexpr.var = readonly_id;
2262*404b540aSrobert     }
2263*404b540aSrobert 
2264*404b540aSrobert   cexpr.offset = 0;
2265*404b540aSrobert   return cexpr;
2266*404b540aSrobert }
2267*404b540aSrobert 
2268*404b540aSrobert /* Process a completed constraint T, and add it to the constraint
2269*404b540aSrobert    list.  */
2270*404b540aSrobert 
2271*404b540aSrobert static void
process_constraint(constraint_t t)2272*404b540aSrobert process_constraint (constraint_t t)
2273*404b540aSrobert {
2274*404b540aSrobert   struct constraint_expr rhs = t->rhs;
2275*404b540aSrobert   struct constraint_expr lhs = t->lhs;
2276*404b540aSrobert 
2277*404b540aSrobert   gcc_assert (rhs.var < VEC_length (varinfo_t, varmap));
2278*404b540aSrobert   gcc_assert (lhs.var < VEC_length (varinfo_t, varmap));
2279*404b540aSrobert 
2280*404b540aSrobert   if (lhs.type == DEREF)
2281*404b540aSrobert     get_varinfo (lhs.var)->directly_dereferenced = true;
2282*404b540aSrobert   if (rhs.type == DEREF)
2283*404b540aSrobert     get_varinfo (rhs.var)->directly_dereferenced = true;
2284*404b540aSrobert 
2285*404b540aSrobert   if (!use_field_sensitive)
2286*404b540aSrobert     {
2287*404b540aSrobert       t->rhs.offset = 0;
2288*404b540aSrobert       t->lhs.offset = 0;
2289*404b540aSrobert     }
2290*404b540aSrobert 
2291*404b540aSrobert   /* ANYTHING == ANYTHING is pointless.  */
2292*404b540aSrobert   if (lhs.var == anything_id && rhs.var == anything_id)
2293*404b540aSrobert     return;
2294*404b540aSrobert 
2295*404b540aSrobert   /* If we have &ANYTHING = something, convert to SOMETHING = &ANYTHING) */
2296*404b540aSrobert   else if (lhs.var == anything_id && lhs.type == ADDRESSOF)
2297*404b540aSrobert     {
2298*404b540aSrobert       rhs = t->lhs;
2299*404b540aSrobert       t->lhs = t->rhs;
2300*404b540aSrobert       t->rhs = rhs;
2301*404b540aSrobert       process_constraint (t);
2302*404b540aSrobert     }
2303*404b540aSrobert   /* This can happen in our IR with things like n->a = *p */
2304*404b540aSrobert   else if (rhs.type == DEREF && lhs.type == DEREF && rhs.var != anything_id)
2305*404b540aSrobert     {
2306*404b540aSrobert       /* Split into tmp = *rhs, *lhs = tmp */
2307*404b540aSrobert       tree rhsdecl = get_varinfo (rhs.var)->decl;
2308*404b540aSrobert       tree pointertype = TREE_TYPE (rhsdecl);
2309*404b540aSrobert       tree pointedtotype = TREE_TYPE (pointertype);
2310*404b540aSrobert       tree tmpvar = create_tmp_var_raw (pointedtotype, "doubledereftmp");
2311*404b540aSrobert       struct constraint_expr tmplhs = get_constraint_exp_from_ssa_var (tmpvar);
2312*404b540aSrobert 
2313*404b540aSrobert       /* If this is an aggregate of known size, we should have passed
2314*404b540aSrobert 	 this off to do_structure_copy, and it should have broken it
2315*404b540aSrobert 	 up.  */
2316*404b540aSrobert       gcc_assert (!AGGREGATE_TYPE_P (pointedtotype)
2317*404b540aSrobert 		  || get_varinfo (rhs.var)->is_unknown_size_var);
2318*404b540aSrobert 
2319*404b540aSrobert       process_constraint (new_constraint (tmplhs, rhs));
2320*404b540aSrobert       process_constraint (new_constraint (lhs, tmplhs));
2321*404b540aSrobert     }
2322*404b540aSrobert   else
2323*404b540aSrobert     {
2324*404b540aSrobert       gcc_assert (rhs.type != ADDRESSOF || rhs.offset == 0);
2325*404b540aSrobert       VEC_safe_push (constraint_t, heap, constraints, t);
2326*404b540aSrobert     }
2327*404b540aSrobert }
2328*404b540aSrobert 
2329*404b540aSrobert /* Return true if T is a variable of a type that could contain
2330*404b540aSrobert    pointers.  */
2331*404b540aSrobert 
2332*404b540aSrobert static bool
could_have_pointers(tree t)2333*404b540aSrobert could_have_pointers (tree t)
2334*404b540aSrobert {
2335*404b540aSrobert   tree type = TREE_TYPE (t);
2336*404b540aSrobert 
2337*404b540aSrobert   if (POINTER_TYPE_P (type)
2338*404b540aSrobert       || AGGREGATE_TYPE_P (type)
2339*404b540aSrobert       || TREE_CODE (type) == COMPLEX_TYPE)
2340*404b540aSrobert     return true;
2341*404b540aSrobert 
2342*404b540aSrobert   return false;
2343*404b540aSrobert }
2344*404b540aSrobert 
2345*404b540aSrobert /* Return the position, in bits, of FIELD_DECL from the beginning of its
2346*404b540aSrobert    structure.  */
2347*404b540aSrobert 
2348*404b540aSrobert static unsigned HOST_WIDE_INT
bitpos_of_field(const tree fdecl)2349*404b540aSrobert bitpos_of_field (const tree fdecl)
2350*404b540aSrobert {
2351*404b540aSrobert 
2352*404b540aSrobert   if (TREE_CODE (DECL_FIELD_OFFSET (fdecl)) != INTEGER_CST
2353*404b540aSrobert       || TREE_CODE (DECL_FIELD_BIT_OFFSET (fdecl)) != INTEGER_CST)
2354*404b540aSrobert     return -1;
2355*404b540aSrobert 
2356*404b540aSrobert   return (tree_low_cst (DECL_FIELD_OFFSET (fdecl), 1) * 8)
2357*404b540aSrobert 	 + tree_low_cst (DECL_FIELD_BIT_OFFSET (fdecl), 1);
2358*404b540aSrobert }
2359*404b540aSrobert 
2360*404b540aSrobert 
2361*404b540aSrobert /* Return true if an access to [ACCESSPOS, ACCESSSIZE]
2362*404b540aSrobert    overlaps with a field at [FIELDPOS, FIELDSIZE] */
2363*404b540aSrobert 
2364*404b540aSrobert static bool
offset_overlaps_with_access(const unsigned HOST_WIDE_INT fieldpos,const unsigned HOST_WIDE_INT fieldsize,const unsigned HOST_WIDE_INT accesspos,const unsigned HOST_WIDE_INT accesssize)2365*404b540aSrobert offset_overlaps_with_access (const unsigned HOST_WIDE_INT fieldpos,
2366*404b540aSrobert 			     const unsigned HOST_WIDE_INT fieldsize,
2367*404b540aSrobert 			     const unsigned HOST_WIDE_INT accesspos,
2368*404b540aSrobert 			     const unsigned HOST_WIDE_INT accesssize)
2369*404b540aSrobert {
2370*404b540aSrobert   if (fieldpos == accesspos && fieldsize == accesssize)
2371*404b540aSrobert     return true;
2372*404b540aSrobert   if (accesspos >= fieldpos && accesspos < (fieldpos + fieldsize))
2373*404b540aSrobert     return true;
2374*404b540aSrobert   if (accesspos < fieldpos && (accesspos + accesssize > fieldpos))
2375*404b540aSrobert     return true;
2376*404b540aSrobert 
2377*404b540aSrobert   return false;
2378*404b540aSrobert }
2379*404b540aSrobert 
2380*404b540aSrobert /* Given a COMPONENT_REF T, return the constraint_expr for it.  */
2381*404b540aSrobert 
2382*404b540aSrobert static void
get_constraint_for_component_ref(tree t,VEC (ce_s,heap)** results)2383*404b540aSrobert get_constraint_for_component_ref (tree t, VEC(ce_s, heap) **results)
2384*404b540aSrobert {
2385*404b540aSrobert   tree orig_t = t;
2386*404b540aSrobert   HOST_WIDE_INT bitsize = -1;
2387*404b540aSrobert   HOST_WIDE_INT bitmaxsize = -1;
2388*404b540aSrobert   HOST_WIDE_INT bitpos;
2389*404b540aSrobert   tree forzero;
2390*404b540aSrobert   struct constraint_expr *result;
2391*404b540aSrobert   unsigned int beforelength = VEC_length (ce_s, *results);
2392*404b540aSrobert 
2393*404b540aSrobert   /* Some people like to do cute things like take the address of
2394*404b540aSrobert      &0->a.b */
2395*404b540aSrobert   forzero = t;
2396*404b540aSrobert   while (!SSA_VAR_P (forzero) && !CONSTANT_CLASS_P (forzero))
2397*404b540aSrobert     forzero = TREE_OPERAND (forzero, 0);
2398*404b540aSrobert 
2399*404b540aSrobert   if (CONSTANT_CLASS_P (forzero) && integer_zerop (forzero))
2400*404b540aSrobert     {
2401*404b540aSrobert       struct constraint_expr temp;
2402*404b540aSrobert 
2403*404b540aSrobert       temp.offset = 0;
2404*404b540aSrobert       temp.var = integer_id;
2405*404b540aSrobert       temp.type = SCALAR;
2406*404b540aSrobert       VEC_safe_push (ce_s, heap, *results, &temp);
2407*404b540aSrobert       return;
2408*404b540aSrobert     }
2409*404b540aSrobert 
2410*404b540aSrobert   t = get_ref_base_and_extent (t, &bitpos, &bitsize, &bitmaxsize);
2411*404b540aSrobert 
2412*404b540aSrobert   /* String constants are readonly, so there is nothing to really do
2413*404b540aSrobert      here.  */
2414*404b540aSrobert   if (TREE_CODE (t) == STRING_CST)
2415*404b540aSrobert     return;
2416*404b540aSrobert 
2417*404b540aSrobert   get_constraint_for (t, results);
2418*404b540aSrobert   result = VEC_last (ce_s, *results);
2419*404b540aSrobert   result->offset = bitpos;
2420*404b540aSrobert 
2421*404b540aSrobert   gcc_assert (beforelength + 1 == VEC_length (ce_s, *results));
2422*404b540aSrobert 
2423*404b540aSrobert   /* This can also happen due to weird offsetof type macros.  */
2424*404b540aSrobert   if (TREE_CODE (t) != ADDR_EXPR && result->type == ADDRESSOF)
2425*404b540aSrobert     result->type = SCALAR;
2426*404b540aSrobert 
2427*404b540aSrobert   if (result->type == SCALAR)
2428*404b540aSrobert     {
2429*404b540aSrobert       /* In languages like C, you can access one past the end of an
2430*404b540aSrobert 	 array.  You aren't allowed to dereference it, so we can
2431*404b540aSrobert 	 ignore this constraint. When we handle pointer subtraction,
2432*404b540aSrobert 	 we may have to do something cute here.  */
2433*404b540aSrobert 
2434*404b540aSrobert       if (result->offset < get_varinfo (result->var)->fullsize
2435*404b540aSrobert 	  && bitmaxsize != 0)
2436*404b540aSrobert 	{
2437*404b540aSrobert 	  /* It's also not true that the constraint will actually start at the
2438*404b540aSrobert 	     right offset, it may start in some padding.  We only care about
2439*404b540aSrobert 	     setting the constraint to the first actual field it touches, so
2440*404b540aSrobert 	     walk to find it.  */
2441*404b540aSrobert 	  varinfo_t curr;
2442*404b540aSrobert 	  for (curr = get_varinfo (result->var); curr; curr = curr->next)
2443*404b540aSrobert 	    {
2444*404b540aSrobert 	      if (offset_overlaps_with_access (curr->offset, curr->size,
2445*404b540aSrobert 					       result->offset, bitmaxsize))
2446*404b540aSrobert 		{
2447*404b540aSrobert 		  result->var = curr->id;
2448*404b540aSrobert 		  break;
2449*404b540aSrobert 		}
2450*404b540aSrobert 	    }
2451*404b540aSrobert 	  /* assert that we found *some* field there. The user couldn't be
2452*404b540aSrobert 	     accessing *only* padding.  */
2453*404b540aSrobert 	  /* Still the user could access one past the end of an array
2454*404b540aSrobert 	     embedded in a struct resulting in accessing *only* padding.  */
2455*404b540aSrobert 	  gcc_assert (curr || ref_contains_array_ref (orig_t));
2456*404b540aSrobert 	}
2457*404b540aSrobert       else if (bitmaxsize == 0)
2458*404b540aSrobert 	{
2459*404b540aSrobert 	  if (dump_file && (dump_flags & TDF_DETAILS))
2460*404b540aSrobert 	    fprintf (dump_file, "Access to zero-sized part of variable,"
2461*404b540aSrobert 		     "ignoring\n");
2462*404b540aSrobert 	}
2463*404b540aSrobert       else
2464*404b540aSrobert 	if (dump_file && (dump_flags & TDF_DETAILS))
2465*404b540aSrobert 	  fprintf (dump_file, "Access to past the end of variable, ignoring\n");
2466*404b540aSrobert 
2467*404b540aSrobert       result->offset = 0;
2468*404b540aSrobert     }
2469*404b540aSrobert }
2470*404b540aSrobert 
2471*404b540aSrobert 
2472*404b540aSrobert /* Dereference the constraint expression CONS, and return the result.
2473*404b540aSrobert    DEREF (ADDRESSOF) = SCALAR
2474*404b540aSrobert    DEREF (SCALAR) = DEREF
2475*404b540aSrobert    DEREF (DEREF) = (temp = DEREF1; result = DEREF(temp))
2476*404b540aSrobert    This is needed so that we can handle dereferencing DEREF constraints.  */
2477*404b540aSrobert 
2478*404b540aSrobert static void
do_deref(VEC (ce_s,heap)** constraints)2479*404b540aSrobert do_deref (VEC (ce_s, heap) **constraints)
2480*404b540aSrobert {
2481*404b540aSrobert   struct constraint_expr *c;
2482*404b540aSrobert   unsigned int i = 0;
2483*404b540aSrobert 
2484*404b540aSrobert   for (i = 0; VEC_iterate (ce_s, *constraints, i, c); i++)
2485*404b540aSrobert     {
2486*404b540aSrobert       if (c->type == SCALAR)
2487*404b540aSrobert 	c->type = DEREF;
2488*404b540aSrobert       else if (c->type == ADDRESSOF)
2489*404b540aSrobert 	c->type = SCALAR;
2490*404b540aSrobert       else if (c->type == DEREF)
2491*404b540aSrobert 	{
2492*404b540aSrobert 	  tree tmpvar = create_tmp_var_raw (ptr_type_node, "dereftmp");
2493*404b540aSrobert 	  struct constraint_expr tmplhs = get_constraint_exp_from_ssa_var (tmpvar);
2494*404b540aSrobert 	  process_constraint (new_constraint (tmplhs, *c));
2495*404b540aSrobert 	  c->var = tmplhs.var;
2496*404b540aSrobert 	}
2497*404b540aSrobert       else
2498*404b540aSrobert 	gcc_unreachable ();
2499*404b540aSrobert     }
2500*404b540aSrobert }
2501*404b540aSrobert 
2502*404b540aSrobert /* Create a nonlocal variable of TYPE to represent nonlocals we can
2503*404b540aSrobert    alias.  */
2504*404b540aSrobert 
2505*404b540aSrobert static tree
create_nonlocal_var(tree type)2506*404b540aSrobert create_nonlocal_var (tree type)
2507*404b540aSrobert {
2508*404b540aSrobert   tree nonlocal = create_tmp_var_raw (type, "NONLOCAL");
2509*404b540aSrobert 
2510*404b540aSrobert   if (referenced_vars)
2511*404b540aSrobert     add_referenced_var (nonlocal);
2512*404b540aSrobert 
2513*404b540aSrobert   DECL_EXTERNAL (nonlocal) = 1;
2514*404b540aSrobert   return nonlocal;
2515*404b540aSrobert }
2516*404b540aSrobert 
2517*404b540aSrobert /* Given a tree T, return the constraint expression for it.  */
2518*404b540aSrobert 
2519*404b540aSrobert static void
get_constraint_for(tree t,VEC (ce_s,heap)** results)2520*404b540aSrobert get_constraint_for (tree t, VEC (ce_s, heap) **results)
2521*404b540aSrobert {
2522*404b540aSrobert   struct constraint_expr temp;
2523*404b540aSrobert 
2524*404b540aSrobert   /* x = integer is all glommed to a single variable, which doesn't
2525*404b540aSrobert      point to anything by itself.  That is, of course, unless it is an
2526*404b540aSrobert      integer constant being treated as a pointer, in which case, we
2527*404b540aSrobert      will return that this is really the addressof anything.  This
2528*404b540aSrobert      happens below, since it will fall into the default case. The only
2529*404b540aSrobert      case we know something about an integer treated like a pointer is
2530*404b540aSrobert      when it is the NULL pointer, and then we just say it points to
2531*404b540aSrobert      NULL.  */
2532*404b540aSrobert   if (TREE_CODE (t) == INTEGER_CST
2533*404b540aSrobert       && !POINTER_TYPE_P (TREE_TYPE (t)))
2534*404b540aSrobert     {
2535*404b540aSrobert       temp.var = integer_id;
2536*404b540aSrobert       temp.type = SCALAR;
2537*404b540aSrobert       temp.offset = 0;
2538*404b540aSrobert       VEC_safe_push (ce_s, heap, *results, &temp);
2539*404b540aSrobert       return;
2540*404b540aSrobert     }
2541*404b540aSrobert   else if (TREE_CODE (t) == INTEGER_CST
2542*404b540aSrobert 	   && integer_zerop (t))
2543*404b540aSrobert     {
2544*404b540aSrobert       temp.var = nothing_id;
2545*404b540aSrobert       temp.type = ADDRESSOF;
2546*404b540aSrobert       temp.offset = 0;
2547*404b540aSrobert       VEC_safe_push (ce_s, heap, *results, &temp);
2548*404b540aSrobert       return;
2549*404b540aSrobert     }
2550*404b540aSrobert 
2551*404b540aSrobert   switch (TREE_CODE_CLASS (TREE_CODE (t)))
2552*404b540aSrobert     {
2553*404b540aSrobert     case tcc_expression:
2554*404b540aSrobert       {
2555*404b540aSrobert 	switch (TREE_CODE (t))
2556*404b540aSrobert 	  {
2557*404b540aSrobert 	  case ADDR_EXPR:
2558*404b540aSrobert 	    {
2559*404b540aSrobert 	      struct constraint_expr *c;
2560*404b540aSrobert 	      unsigned int i;
2561*404b540aSrobert 	      tree exp = TREE_OPERAND (t, 0);
2562*404b540aSrobert 	      tree pttype = TREE_TYPE (TREE_TYPE (t));
2563*404b540aSrobert 
2564*404b540aSrobert 	      get_constraint_for (exp, results);
2565*404b540aSrobert 
2566*404b540aSrobert 	      /* Make sure we capture constraints to all elements
2567*404b540aSrobert 		 of an array.  */
2568*404b540aSrobert 	      if ((handled_component_p (exp)
2569*404b540aSrobert 		   && ref_contains_array_ref (exp))
2570*404b540aSrobert 		  || TREE_CODE (TREE_TYPE (exp)) == ARRAY_TYPE)
2571*404b540aSrobert 		{
2572*404b540aSrobert 		  struct constraint_expr *origrhs;
2573*404b540aSrobert 		  varinfo_t origvar;
2574*404b540aSrobert 		  struct constraint_expr tmp;
2575*404b540aSrobert 
2576*404b540aSrobert 		  if (VEC_length (ce_s, *results) == 0)
2577*404b540aSrobert 		    return;
2578*404b540aSrobert 
2579*404b540aSrobert 		  gcc_assert (VEC_length (ce_s, *results) == 1);
2580*404b540aSrobert 		  origrhs = VEC_last (ce_s, *results);
2581*404b540aSrobert 		  tmp = *origrhs;
2582*404b540aSrobert 		  VEC_pop (ce_s, *results);
2583*404b540aSrobert 		  origvar = get_varinfo (origrhs->var);
2584*404b540aSrobert 		  for (; origvar; origvar = origvar->next)
2585*404b540aSrobert 		    {
2586*404b540aSrobert 		      tmp.var = origvar->id;
2587*404b540aSrobert 		      VEC_safe_push (ce_s, heap, *results, &tmp);
2588*404b540aSrobert 		    }
2589*404b540aSrobert 		}
2590*404b540aSrobert 	      else if (VEC_length (ce_s, *results) == 1
2591*404b540aSrobert 		       && (AGGREGATE_TYPE_P (pttype)
2592*404b540aSrobert 			   || TREE_CODE (pttype) == COMPLEX_TYPE))
2593*404b540aSrobert 		{
2594*404b540aSrobert 		  struct constraint_expr *origrhs;
2595*404b540aSrobert 		  varinfo_t origvar;
2596*404b540aSrobert 		  struct constraint_expr tmp;
2597*404b540aSrobert 
2598*404b540aSrobert 		  gcc_assert (VEC_length (ce_s, *results) == 1);
2599*404b540aSrobert 		  origrhs = VEC_last (ce_s, *results);
2600*404b540aSrobert 		  tmp = *origrhs;
2601*404b540aSrobert 		  VEC_pop (ce_s, *results);
2602*404b540aSrobert 		  origvar = get_varinfo (origrhs->var);
2603*404b540aSrobert 		  for (; origvar; origvar = origvar->next)
2604*404b540aSrobert 		    {
2605*404b540aSrobert 		      tmp.var = origvar->id;
2606*404b540aSrobert 		      VEC_safe_push (ce_s, heap, *results, &tmp);
2607*404b540aSrobert 		    }
2608*404b540aSrobert 		}
2609*404b540aSrobert 
2610*404b540aSrobert 	      for (i = 0; VEC_iterate (ce_s, *results, i, c); i++)
2611*404b540aSrobert 		{
2612*404b540aSrobert 		  if (c->type == DEREF)
2613*404b540aSrobert 		    c->type = SCALAR;
2614*404b540aSrobert 		  else
2615*404b540aSrobert 		    c->type = ADDRESSOF;
2616*404b540aSrobert 		}
2617*404b540aSrobert 	      return;
2618*404b540aSrobert 	    }
2619*404b540aSrobert 	    break;
2620*404b540aSrobert 	  case CALL_EXPR:
2621*404b540aSrobert 	    /* XXX: In interprocedural mode, if we didn't have the
2622*404b540aSrobert 	       body, we would need to do *each pointer argument =
2623*404b540aSrobert 	       &ANYTHING added.  */
2624*404b540aSrobert 	    if (call_expr_flags (t) & (ECF_MALLOC | ECF_MAY_BE_ALLOCA))
2625*404b540aSrobert 	      {
2626*404b540aSrobert 		varinfo_t vi;
2627*404b540aSrobert 		tree heapvar = heapvar_lookup (t);
2628*404b540aSrobert 
2629*404b540aSrobert 		if (heapvar == NULL)
2630*404b540aSrobert 		  {
2631*404b540aSrobert 		    heapvar = create_tmp_var_raw (ptr_type_node, "HEAP");
2632*404b540aSrobert 		    DECL_EXTERNAL (heapvar) = 1;
2633*404b540aSrobert 		    if (referenced_vars)
2634*404b540aSrobert 		      add_referenced_var (heapvar);
2635*404b540aSrobert 		    heapvar_insert (t, heapvar);
2636*404b540aSrobert 		  }
2637*404b540aSrobert 
2638*404b540aSrobert 		temp.var = create_variable_info_for (heapvar,
2639*404b540aSrobert 						     alias_get_name (heapvar));
2640*404b540aSrobert 
2641*404b540aSrobert 		vi = get_varinfo (temp.var);
2642*404b540aSrobert 		vi->is_artificial_var = 1;
2643*404b540aSrobert 		vi->is_heap_var = 1;
2644*404b540aSrobert 		temp.type = ADDRESSOF;
2645*404b540aSrobert 		temp.offset = 0;
2646*404b540aSrobert 		VEC_safe_push (ce_s, heap, *results, &temp);
2647*404b540aSrobert 		return;
2648*404b540aSrobert 	      }
2649*404b540aSrobert 	    else
2650*404b540aSrobert 	      {
2651*404b540aSrobert 		temp.var = escaped_vars_id;
2652*404b540aSrobert 		temp.type = SCALAR;
2653*404b540aSrobert 		temp.offset = 0;
2654*404b540aSrobert 		VEC_safe_push (ce_s, heap, *results, &temp);
2655*404b540aSrobert 		return;
2656*404b540aSrobert 	      }
2657*404b540aSrobert 	    break;
2658*404b540aSrobert 	  default:
2659*404b540aSrobert 	    {
2660*404b540aSrobert 	      temp.type = ADDRESSOF;
2661*404b540aSrobert 	      temp.var = anything_id;
2662*404b540aSrobert 	      temp.offset = 0;
2663*404b540aSrobert 	      VEC_safe_push (ce_s, heap, *results, &temp);
2664*404b540aSrobert 	      return;
2665*404b540aSrobert 	    }
2666*404b540aSrobert 	  }
2667*404b540aSrobert       }
2668*404b540aSrobert     case tcc_reference:
2669*404b540aSrobert       {
2670*404b540aSrobert 	switch (TREE_CODE (t))
2671*404b540aSrobert 	  {
2672*404b540aSrobert 	  case INDIRECT_REF:
2673*404b540aSrobert 	    {
2674*404b540aSrobert 	      get_constraint_for (TREE_OPERAND (t, 0), results);
2675*404b540aSrobert 	      do_deref (results);
2676*404b540aSrobert 	      return;
2677*404b540aSrobert 	    }
2678*404b540aSrobert 	  case ARRAY_REF:
2679*404b540aSrobert 	  case ARRAY_RANGE_REF:
2680*404b540aSrobert 	  case COMPONENT_REF:
2681*404b540aSrobert 	    get_constraint_for_component_ref (t, results);
2682*404b540aSrobert 	    return;
2683*404b540aSrobert 	  default:
2684*404b540aSrobert 	    {
2685*404b540aSrobert 	      temp.type = ADDRESSOF;
2686*404b540aSrobert 	      temp.var = anything_id;
2687*404b540aSrobert 	      temp.offset = 0;
2688*404b540aSrobert 	      VEC_safe_push (ce_s, heap, *results, &temp);
2689*404b540aSrobert 	      return;
2690*404b540aSrobert 	    }
2691*404b540aSrobert 	  }
2692*404b540aSrobert       }
2693*404b540aSrobert     case tcc_unary:
2694*404b540aSrobert       {
2695*404b540aSrobert 	switch (TREE_CODE (t))
2696*404b540aSrobert 	  {
2697*404b540aSrobert 	  case NOP_EXPR:
2698*404b540aSrobert 	  case CONVERT_EXPR:
2699*404b540aSrobert 	  case NON_LVALUE_EXPR:
2700*404b540aSrobert 	    {
2701*404b540aSrobert 	      tree op = TREE_OPERAND (t, 0);
2702*404b540aSrobert 
2703*404b540aSrobert 	      /* Cast from non-pointer to pointers are bad news for us.
2704*404b540aSrobert 		 Anything else, we see through */
2705*404b540aSrobert 	      if (!(POINTER_TYPE_P (TREE_TYPE (t))
2706*404b540aSrobert 		    && ! POINTER_TYPE_P (TREE_TYPE (op))))
2707*404b540aSrobert 		{
2708*404b540aSrobert 		  get_constraint_for (op, results);
2709*404b540aSrobert 		  return;
2710*404b540aSrobert 		}
2711*404b540aSrobert 
2712*404b540aSrobert 	      /* FALLTHRU  */
2713*404b540aSrobert 	    }
2714*404b540aSrobert 	  default:
2715*404b540aSrobert 	    {
2716*404b540aSrobert 	      temp.type = ADDRESSOF;
2717*404b540aSrobert 	      temp.var = anything_id;
2718*404b540aSrobert 	      temp.offset = 0;
2719*404b540aSrobert 	      VEC_safe_push (ce_s, heap, *results, &temp);
2720*404b540aSrobert 	      return;
2721*404b540aSrobert 	    }
2722*404b540aSrobert 	  }
2723*404b540aSrobert       }
2724*404b540aSrobert     case tcc_exceptional:
2725*404b540aSrobert       {
2726*404b540aSrobert 	switch (TREE_CODE (t))
2727*404b540aSrobert 	  {
2728*404b540aSrobert 	  case PHI_NODE:
2729*404b540aSrobert 	    {
2730*404b540aSrobert 	      get_constraint_for (PHI_RESULT (t), results);
2731*404b540aSrobert 	      return;
2732*404b540aSrobert 	    }
2733*404b540aSrobert 	    break;
2734*404b540aSrobert 	  case SSA_NAME:
2735*404b540aSrobert 	    {
2736*404b540aSrobert 	      struct constraint_expr temp;
2737*404b540aSrobert 	      temp = get_constraint_exp_from_ssa_var (t);
2738*404b540aSrobert 	      VEC_safe_push (ce_s, heap, *results, &temp);
2739*404b540aSrobert 	      return;
2740*404b540aSrobert 	    }
2741*404b540aSrobert 	    break;
2742*404b540aSrobert 	  default:
2743*404b540aSrobert 	    {
2744*404b540aSrobert 	      temp.type = ADDRESSOF;
2745*404b540aSrobert 	      temp.var = anything_id;
2746*404b540aSrobert 	      temp.offset = 0;
2747*404b540aSrobert 	      VEC_safe_push (ce_s, heap, *results, &temp);
2748*404b540aSrobert 	      return;
2749*404b540aSrobert 	    }
2750*404b540aSrobert 	  }
2751*404b540aSrobert       }
2752*404b540aSrobert     case tcc_declaration:
2753*404b540aSrobert       {
2754*404b540aSrobert 	struct constraint_expr temp;
2755*404b540aSrobert 	temp = get_constraint_exp_from_ssa_var (t);
2756*404b540aSrobert 	VEC_safe_push (ce_s, heap, *results, &temp);
2757*404b540aSrobert 	return;
2758*404b540aSrobert       }
2759*404b540aSrobert     default:
2760*404b540aSrobert       {
2761*404b540aSrobert 	temp.type = ADDRESSOF;
2762*404b540aSrobert 	temp.var = anything_id;
2763*404b540aSrobert 	temp.offset = 0;
2764*404b540aSrobert 	VEC_safe_push (ce_s, heap, *results, &temp);
2765*404b540aSrobert 	return;
2766*404b540aSrobert       }
2767*404b540aSrobert     }
2768*404b540aSrobert }
2769*404b540aSrobert 
2770*404b540aSrobert 
2771*404b540aSrobert /* Handle the structure copy case where we have a simple structure copy
2772*404b540aSrobert    between LHS and RHS that is of SIZE (in bits)
2773*404b540aSrobert 
2774*404b540aSrobert    For each field of the lhs variable (lhsfield)
2775*404b540aSrobert      For each field of the rhs variable at lhsfield.offset (rhsfield)
2776*404b540aSrobert        add the constraint lhsfield = rhsfield
2777*404b540aSrobert 
2778*404b540aSrobert    If we fail due to some kind of type unsafety or other thing we
2779*404b540aSrobert    can't handle, return false.  We expect the caller to collapse the
2780*404b540aSrobert    variable in that case.  */
2781*404b540aSrobert 
2782*404b540aSrobert static bool
do_simple_structure_copy(const struct constraint_expr lhs,const struct constraint_expr rhs,const unsigned HOST_WIDE_INT size)2783*404b540aSrobert do_simple_structure_copy (const struct constraint_expr lhs,
2784*404b540aSrobert 			  const struct constraint_expr rhs,
2785*404b540aSrobert 			  const unsigned HOST_WIDE_INT size)
2786*404b540aSrobert {
2787*404b540aSrobert   varinfo_t p = get_varinfo (lhs.var);
2788*404b540aSrobert   unsigned HOST_WIDE_INT pstart, last;
2789*404b540aSrobert   pstart = p->offset;
2790*404b540aSrobert   last = p->offset + size;
2791*404b540aSrobert   for (; p && p->offset < last; p = p->next)
2792*404b540aSrobert     {
2793*404b540aSrobert       varinfo_t q;
2794*404b540aSrobert       struct constraint_expr templhs = lhs;
2795*404b540aSrobert       struct constraint_expr temprhs = rhs;
2796*404b540aSrobert       unsigned HOST_WIDE_INT fieldoffset;
2797*404b540aSrobert 
2798*404b540aSrobert       templhs.var = p->id;
2799*404b540aSrobert       q = get_varinfo (temprhs.var);
2800*404b540aSrobert       fieldoffset = p->offset - pstart;
2801*404b540aSrobert       q = first_vi_for_offset (q, q->offset + fieldoffset);
2802*404b540aSrobert       if (!q)
2803*404b540aSrobert 	return false;
2804*404b540aSrobert       temprhs.var = q->id;
2805*404b540aSrobert       process_constraint (new_constraint (templhs, temprhs));
2806*404b540aSrobert     }
2807*404b540aSrobert   return true;
2808*404b540aSrobert }
2809*404b540aSrobert 
2810*404b540aSrobert 
2811*404b540aSrobert /* Handle the structure copy case where we have a  structure copy between a
2812*404b540aSrobert    aggregate on the LHS and a dereference of a pointer on the RHS
2813*404b540aSrobert    that is of SIZE (in bits)
2814*404b540aSrobert 
2815*404b540aSrobert    For each field of the lhs variable (lhsfield)
2816*404b540aSrobert        rhs.offset = lhsfield->offset
2817*404b540aSrobert        add the constraint lhsfield = rhs
2818*404b540aSrobert */
2819*404b540aSrobert 
2820*404b540aSrobert static void
do_rhs_deref_structure_copy(const struct constraint_expr lhs,const struct constraint_expr rhs,const unsigned HOST_WIDE_INT size)2821*404b540aSrobert do_rhs_deref_structure_copy (const struct constraint_expr lhs,
2822*404b540aSrobert 			     const struct constraint_expr rhs,
2823*404b540aSrobert 			     const unsigned HOST_WIDE_INT size)
2824*404b540aSrobert {
2825*404b540aSrobert   varinfo_t p = get_varinfo (lhs.var);
2826*404b540aSrobert   unsigned HOST_WIDE_INT pstart,last;
2827*404b540aSrobert   pstart = p->offset;
2828*404b540aSrobert   last = p->offset + size;
2829*404b540aSrobert 
2830*404b540aSrobert   for (; p && p->offset < last; p = p->next)
2831*404b540aSrobert     {
2832*404b540aSrobert       varinfo_t q;
2833*404b540aSrobert       struct constraint_expr templhs = lhs;
2834*404b540aSrobert       struct constraint_expr temprhs = rhs;
2835*404b540aSrobert       unsigned HOST_WIDE_INT fieldoffset;
2836*404b540aSrobert 
2837*404b540aSrobert 
2838*404b540aSrobert       if (templhs.type == SCALAR)
2839*404b540aSrobert 	templhs.var = p->id;
2840*404b540aSrobert       else
2841*404b540aSrobert 	templhs.offset = p->offset;
2842*404b540aSrobert 
2843*404b540aSrobert       q = get_varinfo (temprhs.var);
2844*404b540aSrobert       fieldoffset = p->offset - pstart;
2845*404b540aSrobert       temprhs.offset += fieldoffset;
2846*404b540aSrobert       process_constraint (new_constraint (templhs, temprhs));
2847*404b540aSrobert     }
2848*404b540aSrobert }
2849*404b540aSrobert 
2850*404b540aSrobert /* Handle the structure copy case where we have a structure copy
2851*404b540aSrobert    between a aggregate on the RHS and a dereference of a pointer on
2852*404b540aSrobert    the LHS that is of SIZE (in bits)
2853*404b540aSrobert 
2854*404b540aSrobert    For each field of the rhs variable (rhsfield)
2855*404b540aSrobert        lhs.offset = rhsfield->offset
2856*404b540aSrobert        add the constraint lhs = rhsfield
2857*404b540aSrobert */
2858*404b540aSrobert 
2859*404b540aSrobert static void
do_lhs_deref_structure_copy(const struct constraint_expr lhs,const struct constraint_expr rhs,const unsigned HOST_WIDE_INT size)2860*404b540aSrobert do_lhs_deref_structure_copy (const struct constraint_expr lhs,
2861*404b540aSrobert 			     const struct constraint_expr rhs,
2862*404b540aSrobert 			     const unsigned HOST_WIDE_INT size)
2863*404b540aSrobert {
2864*404b540aSrobert   varinfo_t p = get_varinfo (rhs.var);
2865*404b540aSrobert   unsigned HOST_WIDE_INT pstart,last;
2866*404b540aSrobert   pstart = p->offset;
2867*404b540aSrobert   last = p->offset + size;
2868*404b540aSrobert 
2869*404b540aSrobert   for (; p && p->offset < last; p = p->next)
2870*404b540aSrobert     {
2871*404b540aSrobert       varinfo_t q;
2872*404b540aSrobert       struct constraint_expr templhs = lhs;
2873*404b540aSrobert       struct constraint_expr temprhs = rhs;
2874*404b540aSrobert       unsigned HOST_WIDE_INT fieldoffset;
2875*404b540aSrobert 
2876*404b540aSrobert 
2877*404b540aSrobert       if (temprhs.type == SCALAR)
2878*404b540aSrobert 	temprhs.var = p->id;
2879*404b540aSrobert       else
2880*404b540aSrobert 	temprhs.offset = p->offset;
2881*404b540aSrobert 
2882*404b540aSrobert       q = get_varinfo (templhs.var);
2883*404b540aSrobert       fieldoffset = p->offset - pstart;
2884*404b540aSrobert       templhs.offset += fieldoffset;
2885*404b540aSrobert       process_constraint (new_constraint (templhs, temprhs));
2886*404b540aSrobert     }
2887*404b540aSrobert }
2888*404b540aSrobert 
2889*404b540aSrobert /* Sometimes, frontends like to give us bad type information.  This
2890*404b540aSrobert    function will collapse all the fields from VAR to the end of VAR,
2891*404b540aSrobert    into VAR, so that we treat those fields as a single variable.
2892*404b540aSrobert    We return the variable they were collapsed into.  */
2893*404b540aSrobert 
2894*404b540aSrobert static unsigned int
collapse_rest_of_var(unsigned int var)2895*404b540aSrobert collapse_rest_of_var (unsigned int var)
2896*404b540aSrobert {
2897*404b540aSrobert   varinfo_t currvar = get_varinfo (var);
2898*404b540aSrobert   varinfo_t field;
2899*404b540aSrobert 
2900*404b540aSrobert   for (field = currvar->next; field; field = field->next)
2901*404b540aSrobert     {
2902*404b540aSrobert       if (dump_file)
2903*404b540aSrobert 	fprintf (dump_file, "Type safety: Collapsing var %s into %s\n",
2904*404b540aSrobert 		 field->name, currvar->name);
2905*404b540aSrobert 
2906*404b540aSrobert       gcc_assert (!field->collapsed_to);
2907*404b540aSrobert       field->collapsed_to = currvar;
2908*404b540aSrobert     }
2909*404b540aSrobert 
2910*404b540aSrobert   currvar->next = NULL;
2911*404b540aSrobert   currvar->size = currvar->fullsize - currvar->offset;
2912*404b540aSrobert 
2913*404b540aSrobert   return currvar->id;
2914*404b540aSrobert }
2915*404b540aSrobert 
2916*404b540aSrobert /* Handle aggregate copies by expanding into copies of the respective
2917*404b540aSrobert    fields of the structures.  */
2918*404b540aSrobert 
2919*404b540aSrobert static void
do_structure_copy(tree lhsop,tree rhsop)2920*404b540aSrobert do_structure_copy (tree lhsop, tree rhsop)
2921*404b540aSrobert {
2922*404b540aSrobert   struct constraint_expr lhs, rhs, tmp;
2923*404b540aSrobert   VEC (ce_s, heap) *lhsc = NULL, *rhsc = NULL;
2924*404b540aSrobert   varinfo_t p;
2925*404b540aSrobert   unsigned HOST_WIDE_INT lhssize;
2926*404b540aSrobert   unsigned HOST_WIDE_INT rhssize;
2927*404b540aSrobert 
2928*404b540aSrobert   get_constraint_for (lhsop, &lhsc);
2929*404b540aSrobert   get_constraint_for (rhsop, &rhsc);
2930*404b540aSrobert   gcc_assert (VEC_length (ce_s, lhsc) == 1);
2931*404b540aSrobert   gcc_assert (VEC_length (ce_s, rhsc) == 1);
2932*404b540aSrobert   lhs = *(VEC_last (ce_s, lhsc));
2933*404b540aSrobert   rhs = *(VEC_last (ce_s, rhsc));
2934*404b540aSrobert 
2935*404b540aSrobert   VEC_free (ce_s, heap, lhsc);
2936*404b540aSrobert   VEC_free (ce_s, heap, rhsc);
2937*404b540aSrobert 
2938*404b540aSrobert   /* If we have special var = x, swap it around.  */
2939*404b540aSrobert   if (lhs.var <= integer_id && !(get_varinfo (rhs.var)->is_special_var))
2940*404b540aSrobert     {
2941*404b540aSrobert       tmp = lhs;
2942*404b540aSrobert       lhs = rhs;
2943*404b540aSrobert       rhs = tmp;
2944*404b540aSrobert     }
2945*404b540aSrobert 
2946*404b540aSrobert   /*  This is fairly conservative for the RHS == ADDRESSOF case, in that it's
2947*404b540aSrobert       possible it's something we could handle.  However, most cases falling
2948*404b540aSrobert       into this are dealing with transparent unions, which are slightly
2949*404b540aSrobert       weird. */
2950*404b540aSrobert   if (rhs.type == ADDRESSOF && !(get_varinfo (rhs.var)->is_special_var))
2951*404b540aSrobert     {
2952*404b540aSrobert       rhs.type = ADDRESSOF;
2953*404b540aSrobert       rhs.var = anything_id;
2954*404b540aSrobert     }
2955*404b540aSrobert 
2956*404b540aSrobert   /* If the RHS is a special var, or an addressof, set all the LHS fields to
2957*404b540aSrobert      that special var.  */
2958*404b540aSrobert   if (rhs.var <= integer_id)
2959*404b540aSrobert     {
2960*404b540aSrobert       for (p = get_varinfo (lhs.var); p; p = p->next)
2961*404b540aSrobert 	{
2962*404b540aSrobert 	  struct constraint_expr templhs = lhs;
2963*404b540aSrobert 	  struct constraint_expr temprhs = rhs;
2964*404b540aSrobert 
2965*404b540aSrobert 	  if (templhs.type == SCALAR )
2966*404b540aSrobert 	    templhs.var = p->id;
2967*404b540aSrobert 	  else
2968*404b540aSrobert 	    templhs.offset += p->offset;
2969*404b540aSrobert 	  process_constraint (new_constraint (templhs, temprhs));
2970*404b540aSrobert 	}
2971*404b540aSrobert     }
2972*404b540aSrobert   else
2973*404b540aSrobert     {
2974*404b540aSrobert       tree rhstype = TREE_TYPE (rhsop);
2975*404b540aSrobert       tree lhstype = TREE_TYPE (lhsop);
2976*404b540aSrobert       tree rhstypesize;
2977*404b540aSrobert       tree lhstypesize;
2978*404b540aSrobert 
2979*404b540aSrobert       lhstypesize = DECL_P (lhsop) ? DECL_SIZE (lhsop) : TYPE_SIZE (lhstype);
2980*404b540aSrobert       rhstypesize = DECL_P (rhsop) ? DECL_SIZE (rhsop) : TYPE_SIZE (rhstype);
2981*404b540aSrobert 
2982*404b540aSrobert       /* If we have a variably sized types on the rhs or lhs, and a deref
2983*404b540aSrobert 	 constraint, add the constraint, lhsconstraint = &ANYTHING.
2984*404b540aSrobert 	 This is conservatively correct because either the lhs is an unknown
2985*404b540aSrobert 	 sized var (if the constraint is SCALAR), or the lhs is a DEREF
2986*404b540aSrobert 	 constraint, and every variable it can point to must be unknown sized
2987*404b540aSrobert 	 anyway, so we don't need to worry about fields at all.  */
2988*404b540aSrobert       if ((rhs.type == DEREF && TREE_CODE (rhstypesize) != INTEGER_CST)
2989*404b540aSrobert 	  || (lhs.type == DEREF && TREE_CODE (lhstypesize) != INTEGER_CST))
2990*404b540aSrobert 	{
2991*404b540aSrobert 	  rhs.var = anything_id;
2992*404b540aSrobert 	  rhs.type = ADDRESSOF;
2993*404b540aSrobert 	  rhs.offset = 0;
2994*404b540aSrobert 	  process_constraint (new_constraint (lhs, rhs));
2995*404b540aSrobert 	  return;
2996*404b540aSrobert 	}
2997*404b540aSrobert 
2998*404b540aSrobert       /* The size only really matters insofar as we don't set more or less of
2999*404b540aSrobert 	 the variable.  If we hit an unknown size var, the size should be the
3000*404b540aSrobert 	 whole darn thing.  */
3001*404b540aSrobert       if (get_varinfo (rhs.var)->is_unknown_size_var)
3002*404b540aSrobert 	rhssize = ~0;
3003*404b540aSrobert       else
3004*404b540aSrobert 	rhssize = TREE_INT_CST_LOW (rhstypesize);
3005*404b540aSrobert 
3006*404b540aSrobert       if (get_varinfo (lhs.var)->is_unknown_size_var)
3007*404b540aSrobert 	lhssize = ~0;
3008*404b540aSrobert       else
3009*404b540aSrobert 	lhssize = TREE_INT_CST_LOW (lhstypesize);
3010*404b540aSrobert 
3011*404b540aSrobert 
3012*404b540aSrobert       if (rhs.type == SCALAR && lhs.type == SCALAR)
3013*404b540aSrobert 	{
3014*404b540aSrobert 	  if (!do_simple_structure_copy (lhs, rhs, MIN (lhssize, rhssize)))
3015*404b540aSrobert 	    {
3016*404b540aSrobert 	      lhs.var = collapse_rest_of_var (lhs.var);
3017*404b540aSrobert 	      rhs.var = collapse_rest_of_var (rhs.var);
3018*404b540aSrobert 	      lhs.offset = 0;
3019*404b540aSrobert 	      rhs.offset = 0;
3020*404b540aSrobert 	      lhs.type = SCALAR;
3021*404b540aSrobert 	      rhs.type = SCALAR;
3022*404b540aSrobert 	      process_constraint (new_constraint (lhs, rhs));
3023*404b540aSrobert 	    }
3024*404b540aSrobert 	}
3025*404b540aSrobert       else if (lhs.type != DEREF && rhs.type == DEREF)
3026*404b540aSrobert 	do_rhs_deref_structure_copy (lhs, rhs, MIN (lhssize, rhssize));
3027*404b540aSrobert       else if (lhs.type == DEREF && rhs.type != DEREF)
3028*404b540aSrobert 	do_lhs_deref_structure_copy (lhs, rhs, MIN (lhssize, rhssize));
3029*404b540aSrobert       else
3030*404b540aSrobert 	{
3031*404b540aSrobert 	  tree pointedtotype = lhstype;
3032*404b540aSrobert 	  tree tmpvar;
3033*404b540aSrobert 
3034*404b540aSrobert 	  gcc_assert (rhs.type == DEREF && lhs.type == DEREF);
3035*404b540aSrobert 	  tmpvar = create_tmp_var_raw (pointedtotype, "structcopydereftmp");
3036*404b540aSrobert 	  do_structure_copy (tmpvar, rhsop);
3037*404b540aSrobert 	  do_structure_copy (lhsop, tmpvar);
3038*404b540aSrobert 	}
3039*404b540aSrobert     }
3040*404b540aSrobert }
3041*404b540aSrobert 
3042*404b540aSrobert 
3043*404b540aSrobert /* Update related alias information kept in AI.  This is used when
3044*404b540aSrobert    building name tags, alias sets and deciding grouping heuristics.
3045*404b540aSrobert    STMT is the statement to process.  This function also updates
3046*404b540aSrobert    ADDRESSABLE_VARS.  */
3047*404b540aSrobert 
3048*404b540aSrobert static void
update_alias_info(tree stmt,struct alias_info * ai)3049*404b540aSrobert update_alias_info (tree stmt, struct alias_info *ai)
3050*404b540aSrobert {
3051*404b540aSrobert   bitmap addr_taken;
3052*404b540aSrobert   use_operand_p use_p;
3053*404b540aSrobert   ssa_op_iter iter;
3054*404b540aSrobert   enum escape_type stmt_escape_type = is_escape_site (stmt);
3055*404b540aSrobert   tree op;
3056*404b540aSrobert 
3057*404b540aSrobert   if (stmt_escape_type == ESCAPE_TO_CALL
3058*404b540aSrobert       || stmt_escape_type == ESCAPE_TO_PURE_CONST)
3059*404b540aSrobert     {
3060*404b540aSrobert       ai->num_calls_found++;
3061*404b540aSrobert       if (stmt_escape_type == ESCAPE_TO_PURE_CONST)
3062*404b540aSrobert 	ai->num_pure_const_calls_found++;
3063*404b540aSrobert     }
3064*404b540aSrobert 
3065*404b540aSrobert   /* Mark all the variables whose address are taken by the statement.  */
3066*404b540aSrobert   addr_taken = addresses_taken (stmt);
3067*404b540aSrobert   if (addr_taken)
3068*404b540aSrobert     {
3069*404b540aSrobert       bitmap_ior_into (addressable_vars, addr_taken);
3070*404b540aSrobert 
3071*404b540aSrobert       /* If STMT is an escape point, all the addresses taken by it are
3072*404b540aSrobert 	 call-clobbered.  */
3073*404b540aSrobert       if (stmt_escape_type != NO_ESCAPE)
3074*404b540aSrobert 	{
3075*404b540aSrobert 	  bitmap_iterator bi;
3076*404b540aSrobert 	  unsigned i;
3077*404b540aSrobert 
3078*404b540aSrobert 	  EXECUTE_IF_SET_IN_BITMAP (addr_taken, 0, i, bi)
3079*404b540aSrobert 	    {
3080*404b540aSrobert 	      tree rvar = referenced_var (i);
3081*404b540aSrobert 	      if (!unmodifiable_var_p (rvar))
3082*404b540aSrobert 		mark_call_clobbered (rvar, stmt_escape_type);
3083*404b540aSrobert 	    }
3084*404b540aSrobert 	}
3085*404b540aSrobert     }
3086*404b540aSrobert 
3087*404b540aSrobert   /* Process each operand use.  If an operand may be aliased, keep
3088*404b540aSrobert      track of how many times it's being used.  For pointers, determine
3089*404b540aSrobert      whether they are dereferenced by the statement, or whether their
3090*404b540aSrobert      value escapes, etc.  */
3091*404b540aSrobert   FOR_EACH_PHI_OR_STMT_USE (use_p, stmt, iter, SSA_OP_USE)
3092*404b540aSrobert     {
3093*404b540aSrobert       tree op, var;
3094*404b540aSrobert       var_ann_t v_ann;
3095*404b540aSrobert       struct ptr_info_def *pi;
3096*404b540aSrobert       bool is_store, is_potential_deref;
3097*404b540aSrobert       unsigned num_uses, num_derefs;
3098*404b540aSrobert 
3099*404b540aSrobert       op = USE_FROM_PTR (use_p);
3100*404b540aSrobert 
3101*404b540aSrobert       /* If STMT is a PHI node, OP may be an ADDR_EXPR.  If so, add it
3102*404b540aSrobert 	 to the set of addressable variables.  */
3103*404b540aSrobert       if (TREE_CODE (op) == ADDR_EXPR)
3104*404b540aSrobert 	{
3105*404b540aSrobert 	  gcc_assert (TREE_CODE (stmt) == PHI_NODE);
3106*404b540aSrobert 
3107*404b540aSrobert 	  /* PHI nodes don't have annotations for pinning the set
3108*404b540aSrobert 	     of addresses taken, so we collect them here.
3109*404b540aSrobert 
3110*404b540aSrobert 	     FIXME, should we allow PHI nodes to have annotations
3111*404b540aSrobert 	     so that they can be treated like regular statements?
3112*404b540aSrobert 	     Currently, they are treated as second-class
3113*404b540aSrobert 	     statements.  */
3114*404b540aSrobert 	  add_to_addressable_set (TREE_OPERAND (op, 0), &addressable_vars);
3115*404b540aSrobert 	  continue;
3116*404b540aSrobert 	}
3117*404b540aSrobert 
3118*404b540aSrobert       /* Ignore constants.  */
3119*404b540aSrobert       if (TREE_CODE (op) != SSA_NAME)
3120*404b540aSrobert 	continue;
3121*404b540aSrobert 
3122*404b540aSrobert       var = SSA_NAME_VAR (op);
3123*404b540aSrobert       v_ann = var_ann (var);
3124*404b540aSrobert 
3125*404b540aSrobert       /* The base variable of an ssa name must be a GIMPLE register, and thus
3126*404b540aSrobert 	 it cannot be aliased.  */
3127*404b540aSrobert       gcc_assert (!may_be_aliased (var));
3128*404b540aSrobert 
3129*404b540aSrobert       /* We are only interested in pointers.  */
3130*404b540aSrobert       if (!POINTER_TYPE_P (TREE_TYPE (op)))
3131*404b540aSrobert 	continue;
3132*404b540aSrobert 
3133*404b540aSrobert       pi = get_ptr_info (op);
3134*404b540aSrobert 
3135*404b540aSrobert       /* Add OP to AI->PROCESSED_PTRS, if it's not there already.  */
3136*404b540aSrobert       if (!TEST_BIT (ai->ssa_names_visited, SSA_NAME_VERSION (op)))
3137*404b540aSrobert 	{
3138*404b540aSrobert 	  SET_BIT (ai->ssa_names_visited, SSA_NAME_VERSION (op));
3139*404b540aSrobert 	  VEC_safe_push (tree, heap, ai->processed_ptrs, op);
3140*404b540aSrobert 	}
3141*404b540aSrobert 
3142*404b540aSrobert       /* If STMT is a PHI node, then it will not have pointer
3143*404b540aSrobert 	 dereferences and it will not be an escape point.  */
3144*404b540aSrobert       if (TREE_CODE (stmt) == PHI_NODE)
3145*404b540aSrobert 	continue;
3146*404b540aSrobert 
3147*404b540aSrobert       /* Determine whether OP is a dereferenced pointer, and if STMT
3148*404b540aSrobert 	 is an escape point, whether OP escapes.  */
3149*404b540aSrobert       count_uses_and_derefs (op, stmt, &num_uses, &num_derefs, &is_store);
3150*404b540aSrobert 
3151*404b540aSrobert       /* Handle a corner case involving address expressions of the
3152*404b540aSrobert 	 form '&PTR->FLD'.  The problem with these expressions is that
3153*404b540aSrobert 	 they do not represent a dereference of PTR.  However, if some
3154*404b540aSrobert 	 other transformation propagates them into an INDIRECT_REF
3155*404b540aSrobert 	 expression, we end up with '*(&PTR->FLD)' which is folded
3156*404b540aSrobert 	 into 'PTR->FLD'.
3157*404b540aSrobert 
3158*404b540aSrobert 	 So, if the original code had no other dereferences of PTR,
3159*404b540aSrobert 	 the aliaser will not create memory tags for it, and when
3160*404b540aSrobert 	 &PTR->FLD gets propagated to INDIRECT_REF expressions, the
3161*404b540aSrobert 	 memory operations will receive no V_MAY_DEF/VUSE operands.
3162*404b540aSrobert 
3163*404b540aSrobert 	 One solution would be to have count_uses_and_derefs consider
3164*404b540aSrobert 	 &PTR->FLD a dereference of PTR.  But that is wrong, since it
3165*404b540aSrobert 	 is not really a dereference but an offset calculation.
3166*404b540aSrobert 
3167*404b540aSrobert 	 What we do here is to recognize these special ADDR_EXPR
3168*404b540aSrobert 	 nodes.  Since these expressions are never GIMPLE values (they
3169*404b540aSrobert 	 are not GIMPLE invariants), they can only appear on the RHS
3170*404b540aSrobert 	 of an assignment and their base address is always an
3171*404b540aSrobert 	 INDIRECT_REF expression.  */
3172*404b540aSrobert       is_potential_deref = false;
3173*404b540aSrobert       if (TREE_CODE (stmt) == MODIFY_EXPR
3174*404b540aSrobert 	  && TREE_CODE (TREE_OPERAND (stmt, 1)) == ADDR_EXPR
3175*404b540aSrobert 	  && !is_gimple_val (TREE_OPERAND (stmt, 1)))
3176*404b540aSrobert 	{
3177*404b540aSrobert 	  /* If the RHS if of the form &PTR->FLD and PTR == OP, then
3178*404b540aSrobert 	     this represents a potential dereference of PTR.  */
3179*404b540aSrobert 	  tree rhs = TREE_OPERAND (stmt, 1);
3180*404b540aSrobert 	  tree base = get_base_address (TREE_OPERAND (rhs, 0));
3181*404b540aSrobert 	  if (TREE_CODE (base) == INDIRECT_REF
3182*404b540aSrobert 	      && TREE_OPERAND (base, 0) == op)
3183*404b540aSrobert 	    is_potential_deref = true;
3184*404b540aSrobert 	}
3185*404b540aSrobert 
3186*404b540aSrobert       if (num_derefs > 0 || is_potential_deref)
3187*404b540aSrobert 	{
3188*404b540aSrobert 	  /* Mark OP as dereferenced.  In a subsequent pass,
3189*404b540aSrobert 	     dereferenced pointers that point to a set of
3190*404b540aSrobert 	     variables will be assigned a name tag to alias
3191*404b540aSrobert 	     all the variables OP points to.  */
3192*404b540aSrobert 	  pi->is_dereferenced = 1;
3193*404b540aSrobert 
3194*404b540aSrobert 	  /* Keep track of how many time we've dereferenced each
3195*404b540aSrobert 	     pointer.  */
3196*404b540aSrobert 	  NUM_REFERENCES_INC (v_ann);
3197*404b540aSrobert 
3198*404b540aSrobert 	  /* If this is a store operation, mark OP as being
3199*404b540aSrobert 	     dereferenced to store, otherwise mark it as being
3200*404b540aSrobert 	     dereferenced to load.  */
3201*404b540aSrobert 	  if (is_store)
3202*404b540aSrobert 	    bitmap_set_bit (ai->dereferenced_ptrs_store, DECL_UID (var));
3203*404b540aSrobert 	  else
3204*404b540aSrobert 	    bitmap_set_bit (ai->dereferenced_ptrs_load, DECL_UID (var));
3205*404b540aSrobert 	}
3206*404b540aSrobert 
3207*404b540aSrobert       if (stmt_escape_type != NO_ESCAPE && num_derefs < num_uses)
3208*404b540aSrobert 	{
3209*404b540aSrobert 	  /* If STMT is an escape point and STMT contains at
3210*404b540aSrobert 	     least one direct use of OP, then the value of OP
3211*404b540aSrobert 	     escapes and so the pointed-to variables need to
3212*404b540aSrobert 	     be marked call-clobbered.  */
3213*404b540aSrobert 	  pi->value_escapes_p = 1;
3214*404b540aSrobert 	  pi->escape_mask |= stmt_escape_type;
3215*404b540aSrobert 
3216*404b540aSrobert 	  /* If the statement makes a function call, assume
3217*404b540aSrobert 	     that pointer OP will be dereferenced in a store
3218*404b540aSrobert 	     operation inside the called function.  */
3219*404b540aSrobert 	  if (get_call_expr_in (stmt)
3220*404b540aSrobert 	      || stmt_escape_type == ESCAPE_STORED_IN_GLOBAL)
3221*404b540aSrobert 	    {
3222*404b540aSrobert 	      bitmap_set_bit (ai->dereferenced_ptrs_store, DECL_UID (var));
3223*404b540aSrobert 	      pi->is_dereferenced = 1;
3224*404b540aSrobert 	    }
3225*404b540aSrobert 	}
3226*404b540aSrobert     }
3227*404b540aSrobert 
3228*404b540aSrobert   if (TREE_CODE (stmt) == PHI_NODE)
3229*404b540aSrobert     return;
3230*404b540aSrobert 
3231*404b540aSrobert   /* Update reference counter for definitions to any
3232*404b540aSrobert      potentially aliased variable.  This is used in the alias
3233*404b540aSrobert      grouping heuristics.  */
3234*404b540aSrobert   FOR_EACH_SSA_TREE_OPERAND (op, stmt, iter, SSA_OP_DEF)
3235*404b540aSrobert     {
3236*404b540aSrobert       tree var = SSA_NAME_VAR (op);
3237*404b540aSrobert       var_ann_t ann = var_ann (var);
3238*404b540aSrobert       bitmap_set_bit (ai->written_vars, DECL_UID (var));
3239*404b540aSrobert       if (may_be_aliased (var))
3240*404b540aSrobert 	NUM_REFERENCES_INC (ann);
3241*404b540aSrobert 
3242*404b540aSrobert     }
3243*404b540aSrobert 
3244*404b540aSrobert   /* Mark variables in V_MAY_DEF operands as being written to.  */
3245*404b540aSrobert   FOR_EACH_SSA_TREE_OPERAND (op, stmt, iter, SSA_OP_VIRTUAL_DEFS)
3246*404b540aSrobert     {
3247*404b540aSrobert       tree var = DECL_P (op) ? op : SSA_NAME_VAR (op);
3248*404b540aSrobert       bitmap_set_bit (ai->written_vars, DECL_UID (var));
3249*404b540aSrobert     }
3250*404b540aSrobert }
3251*404b540aSrobert 
3252*404b540aSrobert /* Handle pointer arithmetic EXPR when creating aliasing constraints.
3253*404b540aSrobert    Expressions of the type PTR + CST can be handled in two ways:
3254*404b540aSrobert 
3255*404b540aSrobert    1- If the constraint for PTR is ADDRESSOF for a non-structure
3256*404b540aSrobert       variable, then we can use it directly because adding or
3257*404b540aSrobert       subtracting a constant may not alter the original ADDRESSOF
3258*404b540aSrobert       constraint (i.e., pointer arithmetic may not legally go outside
3259*404b540aSrobert       an object's boundaries).
3260*404b540aSrobert 
3261*404b540aSrobert    2- If the constraint for PTR is ADDRESSOF for a structure variable,
3262*404b540aSrobert       then if CST is a compile-time constant that can be used as an
3263*404b540aSrobert       offset, we can determine which sub-variable will be pointed-to
3264*404b540aSrobert       by the expression.
3265*404b540aSrobert 
3266*404b540aSrobert    Return true if the expression is handled.  For any other kind of
3267*404b540aSrobert    expression, return false so that each operand can be added as a
3268*404b540aSrobert    separate constraint by the caller.  */
3269*404b540aSrobert 
3270*404b540aSrobert static bool
handle_ptr_arith(VEC (ce_s,heap)* lhsc,tree expr)3271*404b540aSrobert handle_ptr_arith (VEC (ce_s, heap) *lhsc, tree expr)
3272*404b540aSrobert {
3273*404b540aSrobert   tree op0, op1;
3274*404b540aSrobert   struct constraint_expr *c, *c2;
3275*404b540aSrobert   unsigned int i = 0;
3276*404b540aSrobert   unsigned int j = 0;
3277*404b540aSrobert   VEC (ce_s, heap) *temp = NULL;
3278*404b540aSrobert   unsigned HOST_WIDE_INT rhsoffset = 0;
3279*404b540aSrobert 
3280*404b540aSrobert   if (TREE_CODE (expr) != PLUS_EXPR
3281*404b540aSrobert       && TREE_CODE (expr) != MINUS_EXPR)
3282*404b540aSrobert     return false;
3283*404b540aSrobert 
3284*404b540aSrobert   op0 = TREE_OPERAND (expr, 0);
3285*404b540aSrobert   op1 = TREE_OPERAND (expr, 1);
3286*404b540aSrobert 
3287*404b540aSrobert   get_constraint_for (op0, &temp);
3288*404b540aSrobert   if (POINTER_TYPE_P (TREE_TYPE (op0))
3289*404b540aSrobert       && host_integerp (op1, 1)
3290*404b540aSrobert       && TREE_CODE (expr) == PLUS_EXPR)
3291*404b540aSrobert     {
3292*404b540aSrobert       if ((TREE_INT_CST_LOW (op1) * BITS_PER_UNIT) / BITS_PER_UNIT
3293*404b540aSrobert 	  != TREE_INT_CST_LOW (op1))
3294*404b540aSrobert 	return false;
3295*404b540aSrobert       rhsoffset = TREE_INT_CST_LOW (op1) * BITS_PER_UNIT;
3296*404b540aSrobert     }
3297*404b540aSrobert   else
3298*404b540aSrobert     return false;
3299*404b540aSrobert 
3300*404b540aSrobert 
3301*404b540aSrobert   for (i = 0; VEC_iterate (ce_s, lhsc, i, c); i++)
3302*404b540aSrobert     for (j = 0; VEC_iterate (ce_s, temp, j, c2); j++)
3303*404b540aSrobert       {
3304*404b540aSrobert 	if (c2->type == ADDRESSOF && rhsoffset != 0)
3305*404b540aSrobert 	  {
3306*404b540aSrobert 	    varinfo_t temp = get_varinfo (c2->var);
3307*404b540aSrobert 
3308*404b540aSrobert 	    /* An access one after the end of an array is valid,
3309*404b540aSrobert 	       so simply punt on accesses we cannot resolve.  */
3310*404b540aSrobert 	    temp = first_vi_for_offset (temp, rhsoffset);
3311*404b540aSrobert 	    if (temp == NULL)
3312*404b540aSrobert 	      continue;
3313*404b540aSrobert 	    c2->var = temp->id;
3314*404b540aSrobert 	    c2->offset = 0;
3315*404b540aSrobert 	  }
3316*404b540aSrobert 	else
3317*404b540aSrobert 	  c2->offset = rhsoffset;
3318*404b540aSrobert 	process_constraint (new_constraint (*c, *c2));
3319*404b540aSrobert       }
3320*404b540aSrobert 
3321*404b540aSrobert   VEC_free (ce_s, heap, temp);
3322*404b540aSrobert 
3323*404b540aSrobert   return true;
3324*404b540aSrobert }
3325*404b540aSrobert 
3326*404b540aSrobert 
3327*404b540aSrobert /* Walk statement T setting up aliasing constraints according to the
3328*404b540aSrobert    references found in T.  This function is the main part of the
3329*404b540aSrobert    constraint builder.  AI points to auxiliary alias information used
3330*404b540aSrobert    when building alias sets and computing alias grouping heuristics.  */
3331*404b540aSrobert 
3332*404b540aSrobert static void
find_func_aliases(tree origt)3333*404b540aSrobert find_func_aliases (tree origt)
3334*404b540aSrobert {
3335*404b540aSrobert   tree t = origt;
3336*404b540aSrobert   VEC(ce_s, heap) *lhsc = NULL;
3337*404b540aSrobert   VEC(ce_s, heap) *rhsc = NULL;
3338*404b540aSrobert   struct constraint_expr *c;
3339*404b540aSrobert 
3340*404b540aSrobert   if (TREE_CODE (t) == RETURN_EXPR && TREE_OPERAND (t, 0))
3341*404b540aSrobert     t = TREE_OPERAND (t, 0);
3342*404b540aSrobert 
3343*404b540aSrobert   /* Now build constraints expressions.  */
3344*404b540aSrobert   if (TREE_CODE (t) == PHI_NODE)
3345*404b540aSrobert     {
3346*404b540aSrobert       gcc_assert (!AGGREGATE_TYPE_P (TREE_TYPE (PHI_RESULT (t))));
3347*404b540aSrobert 
3348*404b540aSrobert       /* Only care about pointers and structures containing
3349*404b540aSrobert 	 pointers.  */
3350*404b540aSrobert       if (could_have_pointers (PHI_RESULT (t)))
3351*404b540aSrobert 	{
3352*404b540aSrobert 	  int i;
3353*404b540aSrobert 	  unsigned int j;
3354*404b540aSrobert 
3355*404b540aSrobert 	  /* For a phi node, assign all the arguments to
3356*404b540aSrobert 	     the result.  */
3357*404b540aSrobert 	  get_constraint_for (PHI_RESULT (t), &lhsc);
3358*404b540aSrobert 	  for (i = 0; i < PHI_NUM_ARGS (t); i++)
3359*404b540aSrobert 	    {
3360*404b540aSrobert 	      tree rhstype;
3361*404b540aSrobert 	      tree strippedrhs = PHI_ARG_DEF (t, i);
3362*404b540aSrobert 
3363*404b540aSrobert 	      STRIP_NOPS (strippedrhs);
3364*404b540aSrobert 	      rhstype = TREE_TYPE (strippedrhs);
3365*404b540aSrobert 	      get_constraint_for (PHI_ARG_DEF (t, i), &rhsc);
3366*404b540aSrobert 
3367*404b540aSrobert 	      for (j = 0; VEC_iterate (ce_s, lhsc, j, c); j++)
3368*404b540aSrobert 		{
3369*404b540aSrobert 		  struct constraint_expr *c2;
3370*404b540aSrobert 		  while (VEC_length (ce_s, rhsc) > 0)
3371*404b540aSrobert 		    {
3372*404b540aSrobert 		      c2 = VEC_last (ce_s, rhsc);
3373*404b540aSrobert 		      process_constraint (new_constraint (*c, *c2));
3374*404b540aSrobert 		      VEC_pop (ce_s, rhsc);
3375*404b540aSrobert 		    }
3376*404b540aSrobert 		}
3377*404b540aSrobert 	    }
3378*404b540aSrobert 	}
3379*404b540aSrobert     }
3380*404b540aSrobert   /* In IPA mode, we need to generate constraints to pass call
3381*404b540aSrobert      arguments through their calls.   There are two case, either a
3382*404b540aSrobert      modify_expr when we are returning a value, or just a plain
3383*404b540aSrobert      call_expr when we are not.   */
3384*404b540aSrobert   else if (in_ipa_mode
3385*404b540aSrobert 	   && ((TREE_CODE (t) == MODIFY_EXPR
3386*404b540aSrobert 		&& TREE_CODE (TREE_OPERAND (t, 1)) == CALL_EXPR
3387*404b540aSrobert 	       && !(call_expr_flags (TREE_OPERAND (t, 1))
3388*404b540aSrobert 		    & (ECF_MALLOC | ECF_MAY_BE_ALLOCA)))
3389*404b540aSrobert 	       || (TREE_CODE (t) == CALL_EXPR
3390*404b540aSrobert 		   && !(call_expr_flags (t)
3391*404b540aSrobert 			& (ECF_MALLOC | ECF_MAY_BE_ALLOCA)))))
3392*404b540aSrobert     {
3393*404b540aSrobert       tree lhsop;
3394*404b540aSrobert       tree rhsop;
3395*404b540aSrobert       tree arglist;
3396*404b540aSrobert       varinfo_t fi;
3397*404b540aSrobert       int i = 1;
3398*404b540aSrobert       tree decl;
3399*404b540aSrobert       if (TREE_CODE (t) == MODIFY_EXPR)
3400*404b540aSrobert 	{
3401*404b540aSrobert 	  lhsop = TREE_OPERAND (t, 0);
3402*404b540aSrobert 	  rhsop = TREE_OPERAND (t, 1);
3403*404b540aSrobert 	}
3404*404b540aSrobert       else
3405*404b540aSrobert 	{
3406*404b540aSrobert 	  lhsop = NULL;
3407*404b540aSrobert 	  rhsop = t;
3408*404b540aSrobert 	}
3409*404b540aSrobert       decl = get_callee_fndecl (rhsop);
3410*404b540aSrobert 
3411*404b540aSrobert       /* If we can directly resolve the function being called, do so.
3412*404b540aSrobert 	 Otherwise, it must be some sort of indirect expression that
3413*404b540aSrobert 	 we should still be able to handle.  */
3414*404b540aSrobert       if (decl)
3415*404b540aSrobert 	{
3416*404b540aSrobert 	  fi = get_vi_for_tree (decl);
3417*404b540aSrobert 	}
3418*404b540aSrobert       else
3419*404b540aSrobert 	{
3420*404b540aSrobert 	  decl = TREE_OPERAND (rhsop, 0);
3421*404b540aSrobert 	  fi = get_vi_for_tree (decl);
3422*404b540aSrobert 	}
3423*404b540aSrobert 
3424*404b540aSrobert       /* Assign all the passed arguments to the appropriate incoming
3425*404b540aSrobert 	 parameters of the function.  */
3426*404b540aSrobert       arglist = TREE_OPERAND (rhsop, 1);
3427*404b540aSrobert 
3428*404b540aSrobert       for (;arglist; arglist = TREE_CHAIN (arglist))
3429*404b540aSrobert 	{
3430*404b540aSrobert 	  tree arg = TREE_VALUE (arglist);
3431*404b540aSrobert 	  struct constraint_expr lhs ;
3432*404b540aSrobert 	  struct constraint_expr *rhsp;
3433*404b540aSrobert 
3434*404b540aSrobert 	  get_constraint_for (arg, &rhsc);
3435*404b540aSrobert 	  if (TREE_CODE (decl) != FUNCTION_DECL)
3436*404b540aSrobert 	    {
3437*404b540aSrobert 	      lhs.type = DEREF;
3438*404b540aSrobert 	      lhs.var = fi->id;
3439*404b540aSrobert 	      lhs.offset = i;
3440*404b540aSrobert 	    }
3441*404b540aSrobert 	  else
3442*404b540aSrobert 	    {
3443*404b540aSrobert 	      lhs.type = SCALAR;
3444*404b540aSrobert 	      lhs.var = first_vi_for_offset (fi, i)->id;
3445*404b540aSrobert 	      lhs.offset = 0;
3446*404b540aSrobert 	    }
3447*404b540aSrobert 	  while (VEC_length (ce_s, rhsc) != 0)
3448*404b540aSrobert 	    {
3449*404b540aSrobert 	      rhsp = VEC_last (ce_s, rhsc);
3450*404b540aSrobert 	      process_constraint (new_constraint (lhs, *rhsp));
3451*404b540aSrobert 	      VEC_pop (ce_s, rhsc);
3452*404b540aSrobert 	    }
3453*404b540aSrobert 	  i++;
3454*404b540aSrobert 	}
3455*404b540aSrobert 
3456*404b540aSrobert       /* If we are returning a value, assign it to the result.  */
3457*404b540aSrobert       if (lhsop)
3458*404b540aSrobert 	{
3459*404b540aSrobert 	  struct constraint_expr rhs;
3460*404b540aSrobert 	  struct constraint_expr *lhsp;
3461*404b540aSrobert 	  unsigned int j = 0;
3462*404b540aSrobert 
3463*404b540aSrobert 	  get_constraint_for (lhsop, &lhsc);
3464*404b540aSrobert 	  if (TREE_CODE (decl) != FUNCTION_DECL)
3465*404b540aSrobert 	    {
3466*404b540aSrobert 	      rhs.type = DEREF;
3467*404b540aSrobert 	      rhs.var = fi->id;
3468*404b540aSrobert 	      rhs.offset = i;
3469*404b540aSrobert 	    }
3470*404b540aSrobert 	  else
3471*404b540aSrobert 	    {
3472*404b540aSrobert 	      rhs.type = SCALAR;
3473*404b540aSrobert 	      rhs.var = first_vi_for_offset (fi, i)->id;
3474*404b540aSrobert 	      rhs.offset = 0;
3475*404b540aSrobert 	    }
3476*404b540aSrobert 	  for (j = 0; VEC_iterate (ce_s, lhsc, j, lhsp); j++)
3477*404b540aSrobert 	    process_constraint (new_constraint (*lhsp, rhs));
3478*404b540aSrobert 	}
3479*404b540aSrobert     }
3480*404b540aSrobert   /* Otherwise, just a regular assignment statement.  */
3481*404b540aSrobert   else if (TREE_CODE (t) == MODIFY_EXPR)
3482*404b540aSrobert     {
3483*404b540aSrobert       tree lhsop = TREE_OPERAND (t, 0);
3484*404b540aSrobert       tree rhsop = TREE_OPERAND (t, 1);
3485*404b540aSrobert       int i;
3486*404b540aSrobert 
3487*404b540aSrobert       if ((AGGREGATE_TYPE_P (TREE_TYPE (lhsop))
3488*404b540aSrobert 	   || TREE_CODE (TREE_TYPE (lhsop)) == COMPLEX_TYPE)
3489*404b540aSrobert 	  && (AGGREGATE_TYPE_P (TREE_TYPE (rhsop))
3490*404b540aSrobert 	      || TREE_CODE (TREE_TYPE (lhsop)) == COMPLEX_TYPE))
3491*404b540aSrobert 	{
3492*404b540aSrobert 	  do_structure_copy (lhsop, rhsop);
3493*404b540aSrobert 	}
3494*404b540aSrobert       else
3495*404b540aSrobert 	{
3496*404b540aSrobert 	  /* Only care about operations with pointers, structures
3497*404b540aSrobert 	     containing pointers, dereferences, and call expressions.  */
3498*404b540aSrobert 	  if (could_have_pointers (lhsop)
3499*404b540aSrobert 	      || TREE_CODE (rhsop) == CALL_EXPR)
3500*404b540aSrobert 	    {
3501*404b540aSrobert 	      get_constraint_for (lhsop, &lhsc);
3502*404b540aSrobert 	      switch (TREE_CODE_CLASS (TREE_CODE (rhsop)))
3503*404b540aSrobert 		{
3504*404b540aSrobert 		  /* RHS that consist of unary operations,
3505*404b540aSrobert 		     exceptional types, or bare decls/constants, get
3506*404b540aSrobert 		     handled directly by get_constraint_for.  */
3507*404b540aSrobert 		  case tcc_reference:
3508*404b540aSrobert 		  case tcc_declaration:
3509*404b540aSrobert 		  case tcc_constant:
3510*404b540aSrobert 		  case tcc_exceptional:
3511*404b540aSrobert 		  case tcc_expression:
3512*404b540aSrobert 		  case tcc_unary:
3513*404b540aSrobert 		      {
3514*404b540aSrobert 			unsigned int j;
3515*404b540aSrobert 
3516*404b540aSrobert 			get_constraint_for (rhsop, &rhsc);
3517*404b540aSrobert 			for (j = 0; VEC_iterate (ce_s, lhsc, j, c); j++)
3518*404b540aSrobert 			  {
3519*404b540aSrobert 			    struct constraint_expr *c2;
3520*404b540aSrobert 			    unsigned int k;
3521*404b540aSrobert 
3522*404b540aSrobert 			    for (k = 0; VEC_iterate (ce_s, rhsc, k, c2); k++)
3523*404b540aSrobert 			      process_constraint (new_constraint (*c, *c2));
3524*404b540aSrobert 			  }
3525*404b540aSrobert 
3526*404b540aSrobert 		      }
3527*404b540aSrobert 		    break;
3528*404b540aSrobert 
3529*404b540aSrobert 		  case tcc_binary:
3530*404b540aSrobert 		      {
3531*404b540aSrobert 			/* For pointer arithmetic of the form
3532*404b540aSrobert 			   PTR + CST, we can simply use PTR's
3533*404b540aSrobert 			   constraint because pointer arithmetic is
3534*404b540aSrobert 			   not allowed to go out of bounds.  */
3535*404b540aSrobert 			if (handle_ptr_arith (lhsc, rhsop))
3536*404b540aSrobert 			  break;
3537*404b540aSrobert 		      }
3538*404b540aSrobert 		    /* FALLTHRU  */
3539*404b540aSrobert 
3540*404b540aSrobert 		  /* Otherwise, walk each operand.  Notice that we
3541*404b540aSrobert 		     can't use the operand interface because we need
3542*404b540aSrobert 		     to process expressions other than simple operands
3543*404b540aSrobert 		     (e.g. INDIRECT_REF, ADDR_EXPR, CALL_EXPR).  */
3544*404b540aSrobert 		  default:
3545*404b540aSrobert 		    for (i = 0; i < TREE_CODE_LENGTH (TREE_CODE (rhsop)); i++)
3546*404b540aSrobert 		      {
3547*404b540aSrobert 			tree op = TREE_OPERAND (rhsop, i);
3548*404b540aSrobert 			unsigned int j;
3549*404b540aSrobert 
3550*404b540aSrobert 			gcc_assert (VEC_length (ce_s, rhsc) == 0);
3551*404b540aSrobert 			get_constraint_for (op, &rhsc);
3552*404b540aSrobert 			for (j = 0; VEC_iterate (ce_s, lhsc, j, c); j++)
3553*404b540aSrobert 			  {
3554*404b540aSrobert 			    struct constraint_expr *c2;
3555*404b540aSrobert 			    while (VEC_length (ce_s, rhsc) > 0)
3556*404b540aSrobert 			      {
3557*404b540aSrobert 				c2 = VEC_last (ce_s, rhsc);
3558*404b540aSrobert 				process_constraint (new_constraint (*c, *c2));
3559*404b540aSrobert 				VEC_pop (ce_s, rhsc);
3560*404b540aSrobert 			      }
3561*404b540aSrobert 			  }
3562*404b540aSrobert 		      }
3563*404b540aSrobert 		}
3564*404b540aSrobert 	    }
3565*404b540aSrobert 	}
3566*404b540aSrobert     }
3567*404b540aSrobert 
3568*404b540aSrobert   /* After promoting variables and computing aliasing we will
3569*404b540aSrobert      need to re-scan most statements.  FIXME: Try to minimize the
3570*404b540aSrobert      number of statements re-scanned.  It's not really necessary to
3571*404b540aSrobert      re-scan *all* statements.  */
3572*404b540aSrobert   mark_stmt_modified (origt);
3573*404b540aSrobert   VEC_free (ce_s, heap, rhsc);
3574*404b540aSrobert   VEC_free (ce_s, heap, lhsc);
3575*404b540aSrobert }
3576*404b540aSrobert 
3577*404b540aSrobert 
3578*404b540aSrobert /* Find the first varinfo in the same variable as START that overlaps with
3579*404b540aSrobert    OFFSET.
3580*404b540aSrobert    Effectively, walk the chain of fields for the variable START to find the
3581*404b540aSrobert    first field that overlaps with OFFSET.
3582*404b540aSrobert    Return NULL if we can't find one.  */
3583*404b540aSrobert 
3584*404b540aSrobert static varinfo_t
first_vi_for_offset(varinfo_t start,unsigned HOST_WIDE_INT offset)3585*404b540aSrobert first_vi_for_offset (varinfo_t start, unsigned HOST_WIDE_INT offset)
3586*404b540aSrobert {
3587*404b540aSrobert   varinfo_t curr = start;
3588*404b540aSrobert   while (curr)
3589*404b540aSrobert     {
3590*404b540aSrobert       /* We may not find a variable in the field list with the actual
3591*404b540aSrobert 	 offset when when we have glommed a structure to a variable.
3592*404b540aSrobert 	 In that case, however, offset should still be within the size
3593*404b540aSrobert 	 of the variable. */
3594*404b540aSrobert       if (offset >= curr->offset && offset < (curr->offset +  curr->size))
3595*404b540aSrobert 	return curr;
3596*404b540aSrobert       curr = curr->next;
3597*404b540aSrobert     }
3598*404b540aSrobert   return NULL;
3599*404b540aSrobert }
3600*404b540aSrobert 
3601*404b540aSrobert 
3602*404b540aSrobert /* Insert the varinfo FIELD into the field list for BASE, at the front
3603*404b540aSrobert    of the list.  */
3604*404b540aSrobert 
3605*404b540aSrobert static void
insert_into_field_list(varinfo_t base,varinfo_t field)3606*404b540aSrobert insert_into_field_list (varinfo_t base, varinfo_t field)
3607*404b540aSrobert {
3608*404b540aSrobert   varinfo_t prev = base;
3609*404b540aSrobert   varinfo_t curr = base->next;
3610*404b540aSrobert 
3611*404b540aSrobert   field->next = curr;
3612*404b540aSrobert   prev->next = field;
3613*404b540aSrobert }
3614*404b540aSrobert 
3615*404b540aSrobert /* Insert the varinfo FIELD into the field list for BASE, ordered by
3616*404b540aSrobert    offset.  */
3617*404b540aSrobert 
3618*404b540aSrobert static void
insert_into_field_list_sorted(varinfo_t base,varinfo_t field)3619*404b540aSrobert insert_into_field_list_sorted (varinfo_t base, varinfo_t field)
3620*404b540aSrobert {
3621*404b540aSrobert   varinfo_t prev = base;
3622*404b540aSrobert   varinfo_t curr = base->next;
3623*404b540aSrobert 
3624*404b540aSrobert   if (curr == NULL)
3625*404b540aSrobert     {
3626*404b540aSrobert       prev->next = field;
3627*404b540aSrobert       field->next = NULL;
3628*404b540aSrobert     }
3629*404b540aSrobert   else
3630*404b540aSrobert     {
3631*404b540aSrobert       while (curr)
3632*404b540aSrobert 	{
3633*404b540aSrobert 	  if (field->offset <= curr->offset)
3634*404b540aSrobert 	    break;
3635*404b540aSrobert 	  prev = curr;
3636*404b540aSrobert 	  curr = curr->next;
3637*404b540aSrobert 	}
3638*404b540aSrobert       field->next = prev->next;
3639*404b540aSrobert       prev->next = field;
3640*404b540aSrobert     }
3641*404b540aSrobert }
3642*404b540aSrobert 
3643*404b540aSrobert /* qsort comparison function for two fieldoff's PA and PB */
3644*404b540aSrobert 
3645*404b540aSrobert static int
fieldoff_compare(const void * pa,const void * pb)3646*404b540aSrobert fieldoff_compare (const void *pa, const void *pb)
3647*404b540aSrobert {
3648*404b540aSrobert   const fieldoff_s *foa = (const fieldoff_s *)pa;
3649*404b540aSrobert   const fieldoff_s *fob = (const fieldoff_s *)pb;
3650*404b540aSrobert   HOST_WIDE_INT foasize, fobsize;
3651*404b540aSrobert 
3652*404b540aSrobert   if (foa->offset != fob->offset)
3653*404b540aSrobert     return foa->offset - fob->offset;
3654*404b540aSrobert 
3655*404b540aSrobert   foasize = TREE_INT_CST_LOW (foa->size);
3656*404b540aSrobert   fobsize = TREE_INT_CST_LOW (fob->size);
3657*404b540aSrobert   return foasize - fobsize;
3658*404b540aSrobert }
3659*404b540aSrobert 
3660*404b540aSrobert /* Sort a fieldstack according to the field offset and sizes.  */
3661*404b540aSrobert void
sort_fieldstack(VEC (fieldoff_s,heap)* fieldstack)3662*404b540aSrobert sort_fieldstack (VEC(fieldoff_s,heap) *fieldstack)
3663*404b540aSrobert {
3664*404b540aSrobert   qsort (VEC_address (fieldoff_s, fieldstack),
3665*404b540aSrobert 	 VEC_length (fieldoff_s, fieldstack),
3666*404b540aSrobert 	 sizeof (fieldoff_s),
3667*404b540aSrobert 	 fieldoff_compare);
3668*404b540aSrobert }
3669*404b540aSrobert 
3670*404b540aSrobert /* Given a TYPE, and a vector of field offsets FIELDSTACK, push all the fields
3671*404b540aSrobert    of TYPE onto fieldstack, recording their offsets along the way.
3672*404b540aSrobert    OFFSET is used to keep track of the offset in this entire structure, rather
3673*404b540aSrobert    than just the immediately containing structure.  Returns the number
3674*404b540aSrobert    of fields pushed.
3675*404b540aSrobert    HAS_UNION is set to true if we find a union type as a field of
3676*404b540aSrobert    TYPE.  */
3677*404b540aSrobert 
3678*404b540aSrobert int
push_fields_onto_fieldstack(tree type,VEC (fieldoff_s,heap)** fieldstack,HOST_WIDE_INT offset,bool * has_union)3679*404b540aSrobert push_fields_onto_fieldstack (tree type, VEC(fieldoff_s,heap) **fieldstack,
3680*404b540aSrobert 			     HOST_WIDE_INT offset, bool *has_union)
3681*404b540aSrobert {
3682*404b540aSrobert   tree field;
3683*404b540aSrobert   int count = 0;
3684*404b540aSrobert   unsigned HOST_WIDE_INT minoffset = -1;
3685*404b540aSrobert 
3686*404b540aSrobert   if (TREE_CODE (type) == COMPLEX_TYPE)
3687*404b540aSrobert     {
3688*404b540aSrobert       fieldoff_s *real_part, *img_part;
3689*404b540aSrobert       real_part = VEC_safe_push (fieldoff_s, heap, *fieldstack, NULL);
3690*404b540aSrobert       real_part->type = TREE_TYPE (type);
3691*404b540aSrobert       real_part->size = TYPE_SIZE (TREE_TYPE (type));
3692*404b540aSrobert       real_part->offset = offset;
3693*404b540aSrobert       real_part->decl = NULL_TREE;
3694*404b540aSrobert 
3695*404b540aSrobert       img_part = VEC_safe_push (fieldoff_s, heap, *fieldstack, NULL);
3696*404b540aSrobert       img_part->type = TREE_TYPE (type);
3697*404b540aSrobert       img_part->size = TYPE_SIZE (TREE_TYPE (type));
3698*404b540aSrobert       img_part->offset = offset + TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (type)));
3699*404b540aSrobert       img_part->decl = NULL_TREE;
3700*404b540aSrobert 
3701*404b540aSrobert       return 2;
3702*404b540aSrobert     }
3703*404b540aSrobert 
3704*404b540aSrobert   if (TREE_CODE (type) == ARRAY_TYPE)
3705*404b540aSrobert     {
3706*404b540aSrobert       tree sz = TYPE_SIZE (type);
3707*404b540aSrobert       tree elsz = TYPE_SIZE (TREE_TYPE (type));
3708*404b540aSrobert       HOST_WIDE_INT nr;
3709*404b540aSrobert       int i;
3710*404b540aSrobert 
3711*404b540aSrobert       if (! sz
3712*404b540aSrobert 	  || ! host_integerp (sz, 1)
3713*404b540aSrobert 	  || TREE_INT_CST_LOW (sz) == 0
3714*404b540aSrobert 	  || ! elsz
3715*404b540aSrobert 	  || ! host_integerp (elsz, 1)
3716*404b540aSrobert 	  || TREE_INT_CST_LOW (elsz) == 0)
3717*404b540aSrobert 	return 0;
3718*404b540aSrobert 
3719*404b540aSrobert       nr = TREE_INT_CST_LOW (sz) / TREE_INT_CST_LOW (elsz);
3720*404b540aSrobert       if (nr > SALIAS_MAX_ARRAY_ELEMENTS)
3721*404b540aSrobert 	return 0;
3722*404b540aSrobert 
3723*404b540aSrobert       for (i = 0; i < nr; ++i)
3724*404b540aSrobert 	{
3725*404b540aSrobert 	  bool push = false;
3726*404b540aSrobert 	  int pushed = 0;
3727*404b540aSrobert 
3728*404b540aSrobert 	  if (has_union
3729*404b540aSrobert 	      && (TREE_CODE (TREE_TYPE (type)) == QUAL_UNION_TYPE
3730*404b540aSrobert 		  || TREE_CODE (TREE_TYPE (type)) == UNION_TYPE))
3731*404b540aSrobert 	    *has_union = true;
3732*404b540aSrobert 
3733*404b540aSrobert 	  if (!AGGREGATE_TYPE_P (TREE_TYPE (type))) /* var_can_have_subvars */
3734*404b540aSrobert 	    push = true;
3735*404b540aSrobert 	  else if (!(pushed = push_fields_onto_fieldstack
3736*404b540aSrobert 		     (TREE_TYPE (type), fieldstack,
3737*404b540aSrobert 		      offset + i * TREE_INT_CST_LOW (elsz), has_union)))
3738*404b540aSrobert 	    /* Empty structures may have actual size, like in C++. So
3739*404b540aSrobert 	       see if we didn't push any subfields and the size is
3740*404b540aSrobert 	       nonzero, push the field onto the stack */
3741*404b540aSrobert 	    push = true;
3742*404b540aSrobert 
3743*404b540aSrobert 	  if (push)
3744*404b540aSrobert 	    {
3745*404b540aSrobert 	      fieldoff_s *pair;
3746*404b540aSrobert 
3747*404b540aSrobert 	      pair = VEC_safe_push (fieldoff_s, heap, *fieldstack, NULL);
3748*404b540aSrobert 	      pair->type = TREE_TYPE (type);
3749*404b540aSrobert 	      pair->size = elsz;
3750*404b540aSrobert 	      pair->decl = NULL_TREE;
3751*404b540aSrobert 	      pair->offset = offset + i * TREE_INT_CST_LOW (elsz);
3752*404b540aSrobert 	      count++;
3753*404b540aSrobert 	    }
3754*404b540aSrobert 	  else
3755*404b540aSrobert 	    count += pushed;
3756*404b540aSrobert 	}
3757*404b540aSrobert 
3758*404b540aSrobert       return count;
3759*404b540aSrobert     }
3760*404b540aSrobert 
3761*404b540aSrobert   for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
3762*404b540aSrobert     if (TREE_CODE (field) == FIELD_DECL)
3763*404b540aSrobert       {
3764*404b540aSrobert 	bool push = false;
3765*404b540aSrobert 	int pushed = 0;
3766*404b540aSrobert 
3767*404b540aSrobert 	if (has_union
3768*404b540aSrobert 	    && (TREE_CODE (TREE_TYPE (field)) == QUAL_UNION_TYPE
3769*404b540aSrobert 		|| TREE_CODE (TREE_TYPE (field)) == UNION_TYPE))
3770*404b540aSrobert 	  *has_union = true;
3771*404b540aSrobert 
3772*404b540aSrobert 	if (!var_can_have_subvars (field))
3773*404b540aSrobert 	  push = true;
3774*404b540aSrobert 	else if (!(pushed = push_fields_onto_fieldstack
3775*404b540aSrobert 		   (TREE_TYPE (field), fieldstack,
3776*404b540aSrobert 		    offset + bitpos_of_field (field), has_union))
3777*404b540aSrobert 		 && DECL_SIZE (field)
3778*404b540aSrobert 		 && !integer_zerop (DECL_SIZE (field)))
3779*404b540aSrobert 	  /* Empty structures may have actual size, like in C++. So
3780*404b540aSrobert 	     see if we didn't push any subfields and the size is
3781*404b540aSrobert 	     nonzero, push the field onto the stack */
3782*404b540aSrobert 	  push = true;
3783*404b540aSrobert 
3784*404b540aSrobert 	if (push)
3785*404b540aSrobert 	  {
3786*404b540aSrobert 	    fieldoff_s *pair;
3787*404b540aSrobert 
3788*404b540aSrobert 	    pair = VEC_safe_push (fieldoff_s, heap, *fieldstack, NULL);
3789*404b540aSrobert 	    pair->type = TREE_TYPE (field);
3790*404b540aSrobert 	    pair->size = DECL_SIZE (field);
3791*404b540aSrobert 	    pair->decl = field;
3792*404b540aSrobert 	    pair->offset = offset + bitpos_of_field (field);
3793*404b540aSrobert 	    count++;
3794*404b540aSrobert 	  }
3795*404b540aSrobert 	else
3796*404b540aSrobert 	  count += pushed;
3797*404b540aSrobert 
3798*404b540aSrobert 	if (bitpos_of_field (field) < minoffset)
3799*404b540aSrobert 	  minoffset = bitpos_of_field (field);
3800*404b540aSrobert       }
3801*404b540aSrobert 
3802*404b540aSrobert   /* We need to create a fake subvar for empty bases.  But _only_ for non-empty
3803*404b540aSrobert      classes.  */
3804*404b540aSrobert   if (minoffset != 0 && count != 0)
3805*404b540aSrobert     {
3806*404b540aSrobert       fieldoff_s *pair;
3807*404b540aSrobert 
3808*404b540aSrobert       pair = VEC_safe_push (fieldoff_s, heap, *fieldstack, NULL);
3809*404b540aSrobert       pair->type = void_type_node;
3810*404b540aSrobert       pair->size = build_int_cst (size_type_node, minoffset);
3811*404b540aSrobert       pair->decl = NULL;
3812*404b540aSrobert       pair->offset = offset;
3813*404b540aSrobert       count++;
3814*404b540aSrobert     }
3815*404b540aSrobert 
3816*404b540aSrobert   return count;
3817*404b540aSrobert }
3818*404b540aSrobert 
3819*404b540aSrobert /* Create a constraint from ESCAPED_VARS variable to VI.  */
3820*404b540aSrobert static void
make_constraint_from_escaped(varinfo_t vi)3821*404b540aSrobert make_constraint_from_escaped (varinfo_t vi)
3822*404b540aSrobert {
3823*404b540aSrobert   struct constraint_expr lhs, rhs;
3824*404b540aSrobert 
3825*404b540aSrobert   lhs.var = vi->id;
3826*404b540aSrobert   lhs.offset = 0;
3827*404b540aSrobert   lhs.type = SCALAR;
3828*404b540aSrobert 
3829*404b540aSrobert   rhs.var = escaped_vars_id;
3830*404b540aSrobert   rhs.offset = 0;
3831*404b540aSrobert   rhs.type = SCALAR;
3832*404b540aSrobert   process_constraint (new_constraint (lhs, rhs));
3833*404b540aSrobert }
3834*404b540aSrobert 
3835*404b540aSrobert /* Create a constraint to the ESCAPED_VARS variable from constraint
3836*404b540aSrobert    expression RHS. */
3837*404b540aSrobert 
3838*404b540aSrobert static void
make_constraint_to_escaped(struct constraint_expr rhs)3839*404b540aSrobert make_constraint_to_escaped (struct constraint_expr rhs)
3840*404b540aSrobert {
3841*404b540aSrobert   struct constraint_expr lhs;
3842*404b540aSrobert 
3843*404b540aSrobert   lhs.var = escaped_vars_id;
3844*404b540aSrobert   lhs.offset = 0;
3845*404b540aSrobert   lhs.type = SCALAR;
3846*404b540aSrobert 
3847*404b540aSrobert   process_constraint (new_constraint (lhs, rhs));
3848*404b540aSrobert }
3849*404b540aSrobert 
3850*404b540aSrobert /* Count the number of arguments DECL has, and set IS_VARARGS to true
3851*404b540aSrobert    if it is a varargs function.  */
3852*404b540aSrobert 
3853*404b540aSrobert static unsigned int
count_num_arguments(tree decl,bool * is_varargs)3854*404b540aSrobert count_num_arguments (tree decl, bool *is_varargs)
3855*404b540aSrobert {
3856*404b540aSrobert   unsigned int i = 0;
3857*404b540aSrobert   tree t;
3858*404b540aSrobert 
3859*404b540aSrobert   for (t = TYPE_ARG_TYPES (TREE_TYPE (decl));
3860*404b540aSrobert        t;
3861*404b540aSrobert        t = TREE_CHAIN (t))
3862*404b540aSrobert     {
3863*404b540aSrobert       if (TREE_VALUE (t) == void_type_node)
3864*404b540aSrobert 	break;
3865*404b540aSrobert       i++;
3866*404b540aSrobert     }
3867*404b540aSrobert 
3868*404b540aSrobert   if (!t)
3869*404b540aSrobert     *is_varargs = true;
3870*404b540aSrobert   return i;
3871*404b540aSrobert }
3872*404b540aSrobert 
3873*404b540aSrobert /* Creation function node for DECL, using NAME, and return the index
3874*404b540aSrobert    of the variable we've created for the function.  */
3875*404b540aSrobert 
3876*404b540aSrobert static unsigned int
create_function_info_for(tree decl,const char * name)3877*404b540aSrobert create_function_info_for (tree decl, const char *name)
3878*404b540aSrobert {
3879*404b540aSrobert   unsigned int index = VEC_length (varinfo_t, varmap);
3880*404b540aSrobert   varinfo_t vi;
3881*404b540aSrobert   tree arg;
3882*404b540aSrobert   unsigned int i;
3883*404b540aSrobert   bool is_varargs = false;
3884*404b540aSrobert 
3885*404b540aSrobert   /* Create the variable info.  */
3886*404b540aSrobert 
3887*404b540aSrobert   vi = new_var_info (decl, index, name);
3888*404b540aSrobert   vi->decl = decl;
3889*404b540aSrobert   vi->offset = 0;
3890*404b540aSrobert   vi->has_union = 0;
3891*404b540aSrobert   vi->size = 1;
3892*404b540aSrobert   vi->fullsize = count_num_arguments (decl, &is_varargs) + 1;
3893*404b540aSrobert   insert_vi_for_tree (vi->decl, vi);
3894*404b540aSrobert   VEC_safe_push (varinfo_t, heap, varmap, vi);
3895*404b540aSrobert 
3896*404b540aSrobert   stats.total_vars++;
3897*404b540aSrobert 
3898*404b540aSrobert   /* If it's varargs, we don't know how many arguments it has, so we
3899*404b540aSrobert      can't do much.
3900*404b540aSrobert   */
3901*404b540aSrobert   if (is_varargs)
3902*404b540aSrobert     {
3903*404b540aSrobert       vi->fullsize = ~0;
3904*404b540aSrobert       vi->size = ~0;
3905*404b540aSrobert       vi->is_unknown_size_var = true;
3906*404b540aSrobert       return index;
3907*404b540aSrobert     }
3908*404b540aSrobert 
3909*404b540aSrobert 
3910*404b540aSrobert   arg = DECL_ARGUMENTS (decl);
3911*404b540aSrobert 
3912*404b540aSrobert   /* Set up variables for each argument.  */
3913*404b540aSrobert   for (i = 1; i < vi->fullsize; i++)
3914*404b540aSrobert     {
3915*404b540aSrobert       varinfo_t argvi;
3916*404b540aSrobert       const char *newname;
3917*404b540aSrobert       char *tempname;
3918*404b540aSrobert       unsigned int newindex;
3919*404b540aSrobert       tree argdecl = decl;
3920*404b540aSrobert 
3921*404b540aSrobert       if (arg)
3922*404b540aSrobert 	argdecl = arg;
3923*404b540aSrobert 
3924*404b540aSrobert       newindex = VEC_length (varinfo_t, varmap);
3925*404b540aSrobert       asprintf (&tempname, "%s.arg%d", name, i-1);
3926*404b540aSrobert       newname = ggc_strdup (tempname);
3927*404b540aSrobert       free (tempname);
3928*404b540aSrobert 
3929*404b540aSrobert       argvi = new_var_info (argdecl, newindex, newname);
3930*404b540aSrobert       argvi->decl = argdecl;
3931*404b540aSrobert       VEC_safe_push (varinfo_t, heap, varmap, argvi);
3932*404b540aSrobert       argvi->offset = i;
3933*404b540aSrobert       argvi->size = 1;
3934*404b540aSrobert       argvi->fullsize = vi->fullsize;
3935*404b540aSrobert       argvi->has_union = false;
3936*404b540aSrobert       insert_into_field_list_sorted (vi, argvi);
3937*404b540aSrobert       stats.total_vars ++;
3938*404b540aSrobert       if (arg)
3939*404b540aSrobert 	{
3940*404b540aSrobert 	  insert_vi_for_tree (arg, argvi);
3941*404b540aSrobert 	  arg = TREE_CHAIN (arg);
3942*404b540aSrobert 	}
3943*404b540aSrobert     }
3944*404b540aSrobert 
3945*404b540aSrobert   /* Create a variable for the return var.  */
3946*404b540aSrobert   if (DECL_RESULT (decl) != NULL
3947*404b540aSrobert       || !VOID_TYPE_P (TREE_TYPE (TREE_TYPE (decl))))
3948*404b540aSrobert     {
3949*404b540aSrobert       varinfo_t resultvi;
3950*404b540aSrobert       const char *newname;
3951*404b540aSrobert       char *tempname;
3952*404b540aSrobert       unsigned int newindex;
3953*404b540aSrobert       tree resultdecl = decl;
3954*404b540aSrobert 
3955*404b540aSrobert       vi->fullsize ++;
3956*404b540aSrobert 
3957*404b540aSrobert       if (DECL_RESULT (decl))
3958*404b540aSrobert 	resultdecl = DECL_RESULT (decl);
3959*404b540aSrobert 
3960*404b540aSrobert       newindex = VEC_length (varinfo_t, varmap);
3961*404b540aSrobert       asprintf (&tempname, "%s.result", name);
3962*404b540aSrobert       newname = ggc_strdup (tempname);
3963*404b540aSrobert       free (tempname);
3964*404b540aSrobert 
3965*404b540aSrobert       resultvi = new_var_info (resultdecl, newindex, newname);
3966*404b540aSrobert       resultvi->decl = resultdecl;
3967*404b540aSrobert       VEC_safe_push (varinfo_t, heap, varmap, resultvi);
3968*404b540aSrobert       resultvi->offset = i;
3969*404b540aSrobert       resultvi->size = 1;
3970*404b540aSrobert       resultvi->fullsize = vi->fullsize;
3971*404b540aSrobert       resultvi->has_union = false;
3972*404b540aSrobert       insert_into_field_list_sorted (vi, resultvi);
3973*404b540aSrobert       stats.total_vars ++;
3974*404b540aSrobert       if (DECL_RESULT (decl))
3975*404b540aSrobert 	insert_vi_for_tree (DECL_RESULT (decl), resultvi);
3976*404b540aSrobert     }
3977*404b540aSrobert   return index;
3978*404b540aSrobert }
3979*404b540aSrobert 
3980*404b540aSrobert 
3981*404b540aSrobert /* Return true if FIELDSTACK contains fields that overlap.
3982*404b540aSrobert    FIELDSTACK is assumed to be sorted by offset.  */
3983*404b540aSrobert 
3984*404b540aSrobert static bool
check_for_overlaps(VEC (fieldoff_s,heap)* fieldstack)3985*404b540aSrobert check_for_overlaps (VEC (fieldoff_s,heap) *fieldstack)
3986*404b540aSrobert {
3987*404b540aSrobert   fieldoff_s *fo = NULL;
3988*404b540aSrobert   unsigned int i;
3989*404b540aSrobert   HOST_WIDE_INT lastoffset = -1;
3990*404b540aSrobert 
3991*404b540aSrobert   for (i = 0; VEC_iterate (fieldoff_s, fieldstack, i, fo); i++)
3992*404b540aSrobert     {
3993*404b540aSrobert       if (fo->offset == lastoffset)
3994*404b540aSrobert 	return true;
3995*404b540aSrobert       lastoffset = fo->offset;
3996*404b540aSrobert     }
3997*404b540aSrobert   return false;
3998*404b540aSrobert }
3999*404b540aSrobert 
4000*404b540aSrobert /* This function is called through walk_tree to walk global
4001*404b540aSrobert    initializers looking for constraints we need to add to the
4002*404b540aSrobert    constraint list.  */
4003*404b540aSrobert 
4004*404b540aSrobert static tree
find_global_initializers(tree * tp,int * walk_subtrees ATTRIBUTE_UNUSED,void * viv)4005*404b540aSrobert find_global_initializers (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED,
4006*404b540aSrobert 			  void *viv)
4007*404b540aSrobert {
4008*404b540aSrobert   varinfo_t vi = (varinfo_t)viv;
4009*404b540aSrobert   tree t = *tp;
4010*404b540aSrobert 
4011*404b540aSrobert   switch (TREE_CODE (t))
4012*404b540aSrobert     {
4013*404b540aSrobert       /* Dereferences and addressofs are the only important things
4014*404b540aSrobert 	 here, and i don't even remember if dereferences are legal
4015*404b540aSrobert 	 here in initializers.  */
4016*404b540aSrobert     case INDIRECT_REF:
4017*404b540aSrobert     case ADDR_EXPR:
4018*404b540aSrobert       {
4019*404b540aSrobert 	struct constraint_expr *c;
4020*404b540aSrobert 	size_t i;
4021*404b540aSrobert 
4022*404b540aSrobert 	VEC(ce_s, heap) *rhsc = NULL;
4023*404b540aSrobert 	get_constraint_for (t, &rhsc);
4024*404b540aSrobert 	for (i = 0; VEC_iterate (ce_s, rhsc, i, c); i++)
4025*404b540aSrobert 	  {
4026*404b540aSrobert 	    struct constraint_expr lhs;
4027*404b540aSrobert 
4028*404b540aSrobert 	    lhs.var = vi->id;
4029*404b540aSrobert 	    lhs.type = SCALAR;
4030*404b540aSrobert 	    lhs.offset = 0;
4031*404b540aSrobert 	    process_constraint (new_constraint (lhs, *c));
4032*404b540aSrobert 	  }
4033*404b540aSrobert 
4034*404b540aSrobert 	VEC_free (ce_s, heap, rhsc);
4035*404b540aSrobert       }
4036*404b540aSrobert       break;
4037*404b540aSrobert     case VAR_DECL:
4038*404b540aSrobert       /* We might not have walked this because we skip
4039*404b540aSrobert 	 DECL_EXTERNALs during the initial scan.  */
4040*404b540aSrobert       if (referenced_vars)
4041*404b540aSrobert 	{
4042*404b540aSrobert 	  get_var_ann (t);
4043*404b540aSrobert 	  if (referenced_var_check_and_insert (t))
4044*404b540aSrobert 	    mark_sym_for_renaming (t);
4045*404b540aSrobert 	}
4046*404b540aSrobert       break;
4047*404b540aSrobert     default:
4048*404b540aSrobert       break;
4049*404b540aSrobert     }
4050*404b540aSrobert   return NULL_TREE;
4051*404b540aSrobert }
4052*404b540aSrobert 
4053*404b540aSrobert /* Create a varinfo structure for NAME and DECL, and add it to VARMAP.
4054*404b540aSrobert    This will also create any varinfo structures necessary for fields
4055*404b540aSrobert    of DECL.  */
4056*404b540aSrobert 
4057*404b540aSrobert static unsigned int
create_variable_info_for(tree decl,const char * name)4058*404b540aSrobert create_variable_info_for (tree decl, const char *name)
4059*404b540aSrobert {
4060*404b540aSrobert   unsigned int index = VEC_length (varinfo_t, varmap);
4061*404b540aSrobert   varinfo_t vi;
4062*404b540aSrobert   tree decltype = TREE_TYPE (decl);
4063*404b540aSrobert   tree declsize = DECL_P (decl) ? DECL_SIZE (decl) : TYPE_SIZE (decltype);
4064*404b540aSrobert   bool notokay = false;
4065*404b540aSrobert   bool hasunion;
4066*404b540aSrobert   bool is_global = DECL_P (decl) ? is_global_var (decl) : false;
4067*404b540aSrobert   VEC (fieldoff_s,heap) *fieldstack = NULL;
4068*404b540aSrobert 
4069*404b540aSrobert   if (TREE_CODE (decl) == FUNCTION_DECL && in_ipa_mode)
4070*404b540aSrobert     return create_function_info_for (decl, name);
4071*404b540aSrobert 
4072*404b540aSrobert   hasunion = TREE_CODE (decltype) == UNION_TYPE
4073*404b540aSrobert 	     || TREE_CODE (decltype) == QUAL_UNION_TYPE;
4074*404b540aSrobert   if (var_can_have_subvars (decl) && use_field_sensitive && !hasunion)
4075*404b540aSrobert     {
4076*404b540aSrobert       push_fields_onto_fieldstack (decltype, &fieldstack, 0, &hasunion);
4077*404b540aSrobert       if (hasunion)
4078*404b540aSrobert 	{
4079*404b540aSrobert 	  VEC_free (fieldoff_s, heap, fieldstack);
4080*404b540aSrobert 	  notokay = true;
4081*404b540aSrobert 	}
4082*404b540aSrobert     }
4083*404b540aSrobert 
4084*404b540aSrobert 
4085*404b540aSrobert   /* If the variable doesn't have subvars, we may end up needing to
4086*404b540aSrobert      sort the field list and create fake variables for all the
4087*404b540aSrobert      fields.  */
4088*404b540aSrobert   vi = new_var_info (decl, index, name);
4089*404b540aSrobert   vi->decl = decl;
4090*404b540aSrobert   vi->offset = 0;
4091*404b540aSrobert   vi->has_union = hasunion;
4092*404b540aSrobert   if (!declsize
4093*404b540aSrobert       || TREE_CODE (declsize) != INTEGER_CST
4094*404b540aSrobert       || TREE_CODE (decltype) == UNION_TYPE
4095*404b540aSrobert       || TREE_CODE (decltype) == QUAL_UNION_TYPE)
4096*404b540aSrobert     {
4097*404b540aSrobert       vi->is_unknown_size_var = true;
4098*404b540aSrobert       vi->fullsize = ~0;
4099*404b540aSrobert       vi->size = ~0;
4100*404b540aSrobert     }
4101*404b540aSrobert   else
4102*404b540aSrobert     {
4103*404b540aSrobert       vi->fullsize = TREE_INT_CST_LOW (declsize);
4104*404b540aSrobert       vi->size = vi->fullsize;
4105*404b540aSrobert     }
4106*404b540aSrobert 
4107*404b540aSrobert   insert_vi_for_tree (vi->decl, vi);
4108*404b540aSrobert   VEC_safe_push (varinfo_t, heap, varmap, vi);
4109*404b540aSrobert   if (is_global && (!flag_whole_program || !in_ipa_mode))
4110*404b540aSrobert     {
4111*404b540aSrobert       make_constraint_from_escaped (vi);
4112*404b540aSrobert 
4113*404b540aSrobert       /* If the variable can't be aliased, there is no point in
4114*404b540aSrobert 	 putting it in the set of nonlocal vars.  */
4115*404b540aSrobert       if (may_be_aliased (vi->decl))
4116*404b540aSrobert 	{
4117*404b540aSrobert 	  struct constraint_expr rhs;
4118*404b540aSrobert 	  rhs.var = index;
4119*404b540aSrobert 	  rhs.type = ADDRESSOF;
4120*404b540aSrobert 	  rhs.offset = 0;
4121*404b540aSrobert 	  make_constraint_to_escaped (rhs);
4122*404b540aSrobert 	}
4123*404b540aSrobert 
4124*404b540aSrobert       if (TREE_CODE (decl) != FUNCTION_DECL && DECL_INITIAL (decl))
4125*404b540aSrobert 	{
4126*404b540aSrobert 	  walk_tree_without_duplicates (&DECL_INITIAL (decl),
4127*404b540aSrobert 					find_global_initializers,
4128*404b540aSrobert 					(void *)vi);
4129*404b540aSrobert 	}
4130*404b540aSrobert     }
4131*404b540aSrobert 
4132*404b540aSrobert   stats.total_vars++;
4133*404b540aSrobert   if (use_field_sensitive
4134*404b540aSrobert       && !notokay
4135*404b540aSrobert       && !vi->is_unknown_size_var
4136*404b540aSrobert       && var_can_have_subvars (decl)
4137*404b540aSrobert       && VEC_length (fieldoff_s, fieldstack) <= MAX_FIELDS_FOR_FIELD_SENSITIVE)
4138*404b540aSrobert     {
4139*404b540aSrobert       unsigned int newindex = VEC_length (varinfo_t, varmap);
4140*404b540aSrobert       fieldoff_s *fo = NULL;
4141*404b540aSrobert       unsigned int i;
4142*404b540aSrobert 
4143*404b540aSrobert       for (i = 0; !notokay && VEC_iterate (fieldoff_s, fieldstack, i, fo); i++)
4144*404b540aSrobert 	{
4145*404b540aSrobert 	  if (! fo->size
4146*404b540aSrobert 	      || TREE_CODE (fo->size) != INTEGER_CST
4147*404b540aSrobert 	      || fo->offset < 0)
4148*404b540aSrobert 	    {
4149*404b540aSrobert 	      notokay = true;
4150*404b540aSrobert 	      break;
4151*404b540aSrobert 	    }
4152*404b540aSrobert 	}
4153*404b540aSrobert 
4154*404b540aSrobert       /* We can't sort them if we have a field with a variable sized type,
4155*404b540aSrobert 	 which will make notokay = true.  In that case, we are going to return
4156*404b540aSrobert 	 without creating varinfos for the fields anyway, so sorting them is a
4157*404b540aSrobert 	 waste to boot.  */
4158*404b540aSrobert       if (!notokay)
4159*404b540aSrobert 	{
4160*404b540aSrobert 	  sort_fieldstack (fieldstack);
4161*404b540aSrobert 	  /* Due to some C++ FE issues, like PR 22488, we might end up
4162*404b540aSrobert 	     what appear to be overlapping fields even though they,
4163*404b540aSrobert 	     in reality, do not overlap.  Until the C++ FE is fixed,
4164*404b540aSrobert 	     we will simply disable field-sensitivity for these cases.  */
4165*404b540aSrobert 	  notokay = check_for_overlaps (fieldstack);
4166*404b540aSrobert 	}
4167*404b540aSrobert 
4168*404b540aSrobert 
4169*404b540aSrobert       if (VEC_length (fieldoff_s, fieldstack) != 0)
4170*404b540aSrobert 	fo = VEC_index (fieldoff_s, fieldstack, 0);
4171*404b540aSrobert 
4172*404b540aSrobert       if (fo == NULL || notokay)
4173*404b540aSrobert 	{
4174*404b540aSrobert 	  vi->is_unknown_size_var = 1;
4175*404b540aSrobert 	  vi->fullsize = ~0;
4176*404b540aSrobert 	  vi->size = ~0;
4177*404b540aSrobert 	  VEC_free (fieldoff_s, heap, fieldstack);
4178*404b540aSrobert 	  return index;
4179*404b540aSrobert 	}
4180*404b540aSrobert 
4181*404b540aSrobert       vi->size = TREE_INT_CST_LOW (fo->size);
4182*404b540aSrobert       vi->offset = fo->offset;
4183*404b540aSrobert       for (i = VEC_length (fieldoff_s, fieldstack) - 1;
4184*404b540aSrobert 	   i >= 1 && VEC_iterate (fieldoff_s, fieldstack, i, fo);
4185*404b540aSrobert 	   i--)
4186*404b540aSrobert 	{
4187*404b540aSrobert 	  varinfo_t newvi;
4188*404b540aSrobert 	  const char *newname = "NULL";
4189*404b540aSrobert 	  char *tempname;
4190*404b540aSrobert 
4191*404b540aSrobert 	  newindex = VEC_length (varinfo_t, varmap);
4192*404b540aSrobert 	  if (dump_file)
4193*404b540aSrobert 	    {
4194*404b540aSrobert 	      if (fo->decl)
4195*404b540aSrobert 		asprintf (&tempname, "%s.%s",
4196*404b540aSrobert 			  vi->name, alias_get_name (fo->decl));
4197*404b540aSrobert 	      else
4198*404b540aSrobert 		asprintf (&tempname, "%s." HOST_WIDE_INT_PRINT_DEC,
4199*404b540aSrobert 			  vi->name, fo->offset);
4200*404b540aSrobert 	      newname = ggc_strdup (tempname);
4201*404b540aSrobert 	      free (tempname);
4202*404b540aSrobert 	    }
4203*404b540aSrobert 	  newvi = new_var_info (decl, newindex, newname);
4204*404b540aSrobert 	  newvi->offset = fo->offset;
4205*404b540aSrobert 	  newvi->size = TREE_INT_CST_LOW (fo->size);
4206*404b540aSrobert 	  newvi->fullsize = vi->fullsize;
4207*404b540aSrobert 	  insert_into_field_list (vi, newvi);
4208*404b540aSrobert 	  VEC_safe_push (varinfo_t, heap, varmap, newvi);
4209*404b540aSrobert 	  if (is_global && (!flag_whole_program || !in_ipa_mode))
4210*404b540aSrobert 	    {
4211*404b540aSrobert 	      /* If the variable can't be aliased, there is no point in
4212*404b540aSrobert 		 putting it in the set of nonlocal vars.  */
4213*404b540aSrobert 	      if (may_be_aliased (vi->decl))
4214*404b540aSrobert 		{
4215*404b540aSrobert 		  struct constraint_expr rhs;
4216*404b540aSrobert 
4217*404b540aSrobert 		  rhs.var = newindex;
4218*404b540aSrobert 		  rhs.type = ADDRESSOF;
4219*404b540aSrobert 		  rhs.offset = 0;
4220*404b540aSrobert 		  make_constraint_to_escaped (rhs);
4221*404b540aSrobert 		}
4222*404b540aSrobert 	      make_constraint_from_escaped (newvi);
4223*404b540aSrobert 	    }
4224*404b540aSrobert 
4225*404b540aSrobert 	  stats.total_vars++;
4226*404b540aSrobert 	}
4227*404b540aSrobert       VEC_free (fieldoff_s, heap, fieldstack);
4228*404b540aSrobert     }
4229*404b540aSrobert   return index;
4230*404b540aSrobert }
4231*404b540aSrobert 
4232*404b540aSrobert /* Print out the points-to solution for VAR to FILE.  */
4233*404b540aSrobert 
4234*404b540aSrobert void
dump_solution_for_var(FILE * file,unsigned int var)4235*404b540aSrobert dump_solution_for_var (FILE *file, unsigned int var)
4236*404b540aSrobert {
4237*404b540aSrobert   varinfo_t vi = get_varinfo (var);
4238*404b540aSrobert   unsigned int i;
4239*404b540aSrobert   bitmap_iterator bi;
4240*404b540aSrobert 
4241*404b540aSrobert   if (find (var) != var)
4242*404b540aSrobert     {
4243*404b540aSrobert       varinfo_t vipt = get_varinfo (find (var));
4244*404b540aSrobert       fprintf (file, "%s = same as %s\n", vi->name, vipt->name);
4245*404b540aSrobert     }
4246*404b540aSrobert   else
4247*404b540aSrobert     {
4248*404b540aSrobert       fprintf (file, "%s = { ", vi->name);
4249*404b540aSrobert       EXECUTE_IF_SET_IN_BITMAP (vi->solution, 0, i, bi)
4250*404b540aSrobert 	{
4251*404b540aSrobert 	  fprintf (file, "%s ", get_varinfo (i)->name);
4252*404b540aSrobert 	}
4253*404b540aSrobert       fprintf (file, "}\n");
4254*404b540aSrobert     }
4255*404b540aSrobert }
4256*404b540aSrobert 
4257*404b540aSrobert /* Print the points-to solution for VAR to stdout.  */
4258*404b540aSrobert 
4259*404b540aSrobert void
debug_solution_for_var(unsigned int var)4260*404b540aSrobert debug_solution_for_var (unsigned int var)
4261*404b540aSrobert {
4262*404b540aSrobert   dump_solution_for_var (stdout, var);
4263*404b540aSrobert }
4264*404b540aSrobert 
4265*404b540aSrobert /* Create varinfo structures for all of the variables in the
4266*404b540aSrobert    function for intraprocedural mode.  */
4267*404b540aSrobert 
4268*404b540aSrobert static void
intra_create_variable_infos(void)4269*404b540aSrobert intra_create_variable_infos (void)
4270*404b540aSrobert {
4271*404b540aSrobert   tree t;
4272*404b540aSrobert   struct constraint_expr lhs, rhs;
4273*404b540aSrobert   varinfo_t nonlocal_vi;
4274*404b540aSrobert 
4275*404b540aSrobert   /* For each incoming pointer argument arg, ARG = ESCAPED_VARS or a
4276*404b540aSrobert      dummy variable if flag_argument_noalias > 2. */
4277*404b540aSrobert   for (t = DECL_ARGUMENTS (current_function_decl); t; t = TREE_CHAIN (t))
4278*404b540aSrobert     {
4279*404b540aSrobert       varinfo_t p;
4280*404b540aSrobert       unsigned int arg_id;
4281*404b540aSrobert 
4282*404b540aSrobert       if (!could_have_pointers (t))
4283*404b540aSrobert 	continue;
4284*404b540aSrobert 
4285*404b540aSrobert       arg_id = get_vi_for_tree (t)->id;
4286*404b540aSrobert 
4287*404b540aSrobert       /* With flag_argument_noalias greater than two means that the incoming
4288*404b540aSrobert          argument cannot alias anything except for itself so create a HEAP
4289*404b540aSrobert          variable.  */
4290*404b540aSrobert       if (POINTER_TYPE_P (TREE_TYPE (t))
4291*404b540aSrobert 	  && flag_argument_noalias > 2)
4292*404b540aSrobert 	{
4293*404b540aSrobert 	  varinfo_t vi;
4294*404b540aSrobert 	  tree heapvar = heapvar_lookup (t);
4295*404b540aSrobert 
4296*404b540aSrobert 	  lhs.offset = 0;
4297*404b540aSrobert 	  lhs.type = SCALAR;
4298*404b540aSrobert 	  lhs.var  = get_vi_for_tree (t)->id;
4299*404b540aSrobert 
4300*404b540aSrobert 	  if (heapvar == NULL_TREE)
4301*404b540aSrobert 	    {
4302*404b540aSrobert 	      heapvar = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (t)),
4303*404b540aSrobert 					    "PARM_NOALIAS");
4304*404b540aSrobert 	      DECL_EXTERNAL (heapvar) = 1;
4305*404b540aSrobert 	      if (referenced_vars)
4306*404b540aSrobert 		add_referenced_var (heapvar);
4307*404b540aSrobert 	      heapvar_insert (t, heapvar);
4308*404b540aSrobert 	    }
4309*404b540aSrobert 
4310*404b540aSrobert 	  vi = get_vi_for_tree (heapvar);
4311*404b540aSrobert 	  vi->is_artificial_var = 1;
4312*404b540aSrobert 	  vi->is_heap_var = 1;
4313*404b540aSrobert 	  rhs.var = vi->id;
4314*404b540aSrobert 	  rhs.type = ADDRESSOF;
4315*404b540aSrobert 	  rhs.offset = 0;
4316*404b540aSrobert           for (p = get_varinfo (lhs.var); p; p = p->next)
4317*404b540aSrobert 	    {
4318*404b540aSrobert 	      struct constraint_expr temp = lhs;
4319*404b540aSrobert 	      temp.var = p->id;
4320*404b540aSrobert 	      process_constraint (new_constraint (temp, rhs));
4321*404b540aSrobert 	    }
4322*404b540aSrobert 	}
4323*404b540aSrobert       else
4324*404b540aSrobert 	{
4325*404b540aSrobert 	  for (p = get_varinfo (arg_id); p; p = p->next)
4326*404b540aSrobert 	    make_constraint_from_escaped (p);
4327*404b540aSrobert 	}
4328*404b540aSrobert     }
4329*404b540aSrobert   if (!nonlocal_all)
4330*404b540aSrobert     nonlocal_all = create_nonlocal_var (void_type_node);
4331*404b540aSrobert 
4332*404b540aSrobert   /* Create variable info for the nonlocal var if it does not
4333*404b540aSrobert      exist.  */
4334*404b540aSrobert   nonlocal_vars_id = create_variable_info_for (nonlocal_all,
4335*404b540aSrobert 					       get_name (nonlocal_all));
4336*404b540aSrobert   nonlocal_vi = get_varinfo (nonlocal_vars_id);
4337*404b540aSrobert   nonlocal_vi->is_artificial_var = 1;
4338*404b540aSrobert   nonlocal_vi->is_heap_var = 1;
4339*404b540aSrobert   nonlocal_vi->is_unknown_size_var = 1;
4340*404b540aSrobert   nonlocal_vi->directly_dereferenced = true;
4341*404b540aSrobert 
4342*404b540aSrobert   rhs.var = nonlocal_vars_id;
4343*404b540aSrobert   rhs.type = ADDRESSOF;
4344*404b540aSrobert   rhs.offset = 0;
4345*404b540aSrobert 
4346*404b540aSrobert   lhs.var = escaped_vars_id;
4347*404b540aSrobert   lhs.type = SCALAR;
4348*404b540aSrobert   lhs.offset = 0;
4349*404b540aSrobert 
4350*404b540aSrobert   process_constraint (new_constraint (lhs, rhs));
4351*404b540aSrobert }
4352*404b540aSrobert 
4353*404b540aSrobert /* Set bits in INTO corresponding to the variable uids in solution set
4354*404b540aSrobert    FROM, which came from variable PTR.
4355*404b540aSrobert    For variables that are actually dereferenced, we also use type
4356*404b540aSrobert    based alias analysis to prune the points-to sets.  */
4357*404b540aSrobert 
4358*404b540aSrobert static void
set_uids_in_ptset(tree ptr,bitmap into,bitmap from)4359*404b540aSrobert set_uids_in_ptset (tree ptr, bitmap into, bitmap from)
4360*404b540aSrobert {
4361*404b540aSrobert   unsigned int i;
4362*404b540aSrobert   bitmap_iterator bi;
4363*404b540aSrobert   subvar_t sv;
4364*404b540aSrobert   unsigned HOST_WIDE_INT ptr_alias_set = get_alias_set (TREE_TYPE (ptr));
4365*404b540aSrobert 
4366*404b540aSrobert   EXECUTE_IF_SET_IN_BITMAP (from, 0, i, bi)
4367*404b540aSrobert     {
4368*404b540aSrobert       varinfo_t vi = get_varinfo (i);
4369*404b540aSrobert       unsigned HOST_WIDE_INT var_alias_set;
4370*404b540aSrobert 
4371*404b540aSrobert       /* The only artificial variables that are allowed in a may-alias
4372*404b540aSrobert 	 set are heap variables.  */
4373*404b540aSrobert       if (vi->is_artificial_var && !vi->is_heap_var)
4374*404b540aSrobert 	continue;
4375*404b540aSrobert 
4376*404b540aSrobert       if (vi->has_union && get_subvars_for_var (vi->decl) != NULL)
4377*404b540aSrobert 	{
4378*404b540aSrobert 	  /* Variables containing unions may need to be converted to
4379*404b540aSrobert 	     their SFT's, because SFT's can have unions and we cannot.  */
4380*404b540aSrobert 	  for (sv = get_subvars_for_var (vi->decl); sv; sv = sv->next)
4381*404b540aSrobert 	    bitmap_set_bit (into, DECL_UID (sv->var));
4382*404b540aSrobert 	}
4383*404b540aSrobert       else if (TREE_CODE (vi->decl) == VAR_DECL
4384*404b540aSrobert 	       || TREE_CODE (vi->decl) == PARM_DECL
4385*404b540aSrobert 	       || TREE_CODE (vi->decl) == RESULT_DECL)
4386*404b540aSrobert 	{
4387*404b540aSrobert 	  if (var_can_have_subvars (vi->decl)
4388*404b540aSrobert 	      && get_subvars_for_var (vi->decl))
4389*404b540aSrobert 	    {
4390*404b540aSrobert 	      /* If VI->DECL is an aggregate for which we created
4391*404b540aSrobert 		 SFTs, add the SFT corresponding to VI->OFFSET.  */
4392*404b540aSrobert 	      tree sft = get_subvar_at (vi->decl, vi->offset);
4393*404b540aSrobert 	      if (sft)
4394*404b540aSrobert 		{
4395*404b540aSrobert 		  var_alias_set = get_alias_set (sft);
4396*404b540aSrobert 		  if (!vi->directly_dereferenced
4397*404b540aSrobert 		      || alias_sets_conflict_p (ptr_alias_set, var_alias_set))
4398*404b540aSrobert 		    bitmap_set_bit (into, DECL_UID (sft));
4399*404b540aSrobert 		}
4400*404b540aSrobert 	    }
4401*404b540aSrobert 	  else
4402*404b540aSrobert 	    {
4403*404b540aSrobert 	      /* Otherwise, just add VI->DECL to the alias set.
4404*404b540aSrobert 		 Don't type prune artificial vars.  */
4405*404b540aSrobert 	      if (vi->is_artificial_var)
4406*404b540aSrobert 		bitmap_set_bit (into, DECL_UID (vi->decl));
4407*404b540aSrobert 	      else
4408*404b540aSrobert 		{
4409*404b540aSrobert 		  var_alias_set = get_alias_set (vi->decl);
4410*404b540aSrobert 		  if (!vi->directly_dereferenced
4411*404b540aSrobert 		      || alias_sets_conflict_p (ptr_alias_set, var_alias_set))
4412*404b540aSrobert 		    bitmap_set_bit (into, DECL_UID (vi->decl));
4413*404b540aSrobert 		}
4414*404b540aSrobert 	    }
4415*404b540aSrobert 	}
4416*404b540aSrobert     }
4417*404b540aSrobert }
4418*404b540aSrobert 
4419*404b540aSrobert 
4420*404b540aSrobert static bool have_alias_info = false;
4421*404b540aSrobert 
4422*404b540aSrobert /* Given a pointer variable P, fill in its points-to set, or return
4423*404b540aSrobert    false if we can't.  */
4424*404b540aSrobert 
4425*404b540aSrobert bool
find_what_p_points_to(tree p)4426*404b540aSrobert find_what_p_points_to (tree p)
4427*404b540aSrobert {
4428*404b540aSrobert   tree lookup_p = p;
4429*404b540aSrobert   varinfo_t vi;
4430*404b540aSrobert 
4431*404b540aSrobert   if (!have_alias_info)
4432*404b540aSrobert     return false;
4433*404b540aSrobert 
4434*404b540aSrobert   /* For parameters, get at the points-to set for the actual parm
4435*404b540aSrobert      decl.  */
4436*404b540aSrobert   if (TREE_CODE (p) == SSA_NAME
4437*404b540aSrobert       && TREE_CODE (SSA_NAME_VAR (p)) == PARM_DECL
4438*404b540aSrobert       && default_def (SSA_NAME_VAR (p)) == p)
4439*404b540aSrobert     lookup_p = SSA_NAME_VAR (p);
4440*404b540aSrobert 
4441*404b540aSrobert   vi = lookup_vi_for_tree (lookup_p);
4442*404b540aSrobert   if (vi)
4443*404b540aSrobert     {
4444*404b540aSrobert 
4445*404b540aSrobert       if (vi->is_artificial_var)
4446*404b540aSrobert 	return false;
4447*404b540aSrobert 
4448*404b540aSrobert       /* See if this is a field or a structure.  */
4449*404b540aSrobert       if (vi->size != vi->fullsize)
4450*404b540aSrobert 	{
4451*404b540aSrobert 	  /* Nothing currently asks about structure fields directly,
4452*404b540aSrobert 	     but when they do, we need code here to hand back the
4453*404b540aSrobert 	     points-to set.  */
4454*404b540aSrobert 	  if (!var_can_have_subvars (vi->decl)
4455*404b540aSrobert 	      || get_subvars_for_var (vi->decl) == NULL)
4456*404b540aSrobert 	    return false;
4457*404b540aSrobert 	}
4458*404b540aSrobert       else
4459*404b540aSrobert 	{
4460*404b540aSrobert 	  struct ptr_info_def *pi = get_ptr_info (p);
4461*404b540aSrobert 	  unsigned int i;
4462*404b540aSrobert 	  bitmap_iterator bi;
4463*404b540aSrobert 
4464*404b540aSrobert 	  /* This variable may have been collapsed, let's get the real
4465*404b540aSrobert 	     variable.  */
4466*404b540aSrobert 	  vi = get_varinfo (find (vi->id));
4467*404b540aSrobert 
4468*404b540aSrobert 	  /* Translate artificial variables into SSA_NAME_PTR_INFO
4469*404b540aSrobert 	     attributes.  */
4470*404b540aSrobert 	  EXECUTE_IF_SET_IN_BITMAP (vi->solution, 0, i, bi)
4471*404b540aSrobert 	    {
4472*404b540aSrobert 	      varinfo_t vi = get_varinfo (i);
4473*404b540aSrobert 
4474*404b540aSrobert 	      if (vi->is_artificial_var)
4475*404b540aSrobert 		{
4476*404b540aSrobert 		  /* FIXME.  READONLY should be handled better so that
4477*404b540aSrobert 		     flow insensitive aliasing can disregard writable
4478*404b540aSrobert 		     aliases.  */
4479*404b540aSrobert 		  if (vi->id == nothing_id)
4480*404b540aSrobert 		    pi->pt_null = 1;
4481*404b540aSrobert 		  else if (vi->id == anything_id)
4482*404b540aSrobert 		    pi->pt_anything = 1;
4483*404b540aSrobert 		  else if (vi->id == readonly_id)
4484*404b540aSrobert 		    pi->pt_anything = 1;
4485*404b540aSrobert 		  else if (vi->id == integer_id)
4486*404b540aSrobert 		    pi->pt_anything = 1;
4487*404b540aSrobert 		  else if (vi->is_heap_var)
4488*404b540aSrobert 		    pi->pt_global_mem = 1;
4489*404b540aSrobert 		}
4490*404b540aSrobert 	    }
4491*404b540aSrobert 
4492*404b540aSrobert 	  if (pi->pt_anything)
4493*404b540aSrobert 	    return false;
4494*404b540aSrobert 
4495*404b540aSrobert 	  if (!pi->pt_vars)
4496*404b540aSrobert 	    pi->pt_vars = BITMAP_GGC_ALLOC ();
4497*404b540aSrobert 
4498*404b540aSrobert 	  set_uids_in_ptset (vi->decl, pi->pt_vars, vi->solution);
4499*404b540aSrobert 
4500*404b540aSrobert 	  if (bitmap_empty_p (pi->pt_vars))
4501*404b540aSrobert 	    pi->pt_vars = NULL;
4502*404b540aSrobert 
4503*404b540aSrobert 	  return true;
4504*404b540aSrobert 	}
4505*404b540aSrobert     }
4506*404b540aSrobert 
4507*404b540aSrobert   return false;
4508*404b540aSrobert }
4509*404b540aSrobert 
4510*404b540aSrobert 
4511*404b540aSrobert 
4512*404b540aSrobert /* Dump points-to information to OUTFILE.  */
4513*404b540aSrobert 
4514*404b540aSrobert void
dump_sa_points_to_info(FILE * outfile)4515*404b540aSrobert dump_sa_points_to_info (FILE *outfile)
4516*404b540aSrobert {
4517*404b540aSrobert   unsigned int i;
4518*404b540aSrobert 
4519*404b540aSrobert   fprintf (outfile, "\nPoints-to sets\n\n");
4520*404b540aSrobert 
4521*404b540aSrobert   if (dump_flags & TDF_STATS)
4522*404b540aSrobert     {
4523*404b540aSrobert       fprintf (outfile, "Stats:\n");
4524*404b540aSrobert       fprintf (outfile, "Total vars:               %d\n", stats.total_vars);
4525*404b540aSrobert       fprintf (outfile, "Non-pointer vars:          %d\n",
4526*404b540aSrobert 	       stats.nonpointer_vars);
4527*404b540aSrobert       fprintf (outfile, "Statically unified vars:  %d\n",
4528*404b540aSrobert 	       stats.unified_vars_static);
4529*404b540aSrobert       fprintf (outfile, "Dynamically unified vars: %d\n",
4530*404b540aSrobert 	       stats.unified_vars_dynamic);
4531*404b540aSrobert       fprintf (outfile, "Iterations:               %d\n", stats.iterations);
4532*404b540aSrobert       fprintf (outfile, "Number of edges:          %d\n", stats.num_edges);
4533*404b540aSrobert       fprintf (outfile, "Number of implicit edges: %d\n",
4534*404b540aSrobert 	       stats.num_implicit_edges);
4535*404b540aSrobert     }
4536*404b540aSrobert 
4537*404b540aSrobert   for (i = 0; i < VEC_length (varinfo_t, varmap); i++)
4538*404b540aSrobert     dump_solution_for_var (outfile, i);
4539*404b540aSrobert }
4540*404b540aSrobert 
4541*404b540aSrobert 
4542*404b540aSrobert /* Debug points-to information to stderr.  */
4543*404b540aSrobert 
4544*404b540aSrobert void
debug_sa_points_to_info(void)4545*404b540aSrobert debug_sa_points_to_info (void)
4546*404b540aSrobert {
4547*404b540aSrobert   dump_sa_points_to_info (stderr);
4548*404b540aSrobert }
4549*404b540aSrobert 
4550*404b540aSrobert 
4551*404b540aSrobert /* Initialize the always-existing constraint variables for NULL
4552*404b540aSrobert    ANYTHING, READONLY, and INTEGER */
4553*404b540aSrobert 
4554*404b540aSrobert static void
init_base_vars(void)4555*404b540aSrobert init_base_vars (void)
4556*404b540aSrobert {
4557*404b540aSrobert   struct constraint_expr lhs, rhs;
4558*404b540aSrobert 
4559*404b540aSrobert   /* Create the NULL variable, used to represent that a variable points
4560*404b540aSrobert      to NULL.  */
4561*404b540aSrobert   nothing_tree = create_tmp_var_raw (void_type_node, "NULL");
4562*404b540aSrobert   var_nothing = new_var_info (nothing_tree, 0, "NULL");
4563*404b540aSrobert   insert_vi_for_tree (nothing_tree, var_nothing);
4564*404b540aSrobert   var_nothing->is_artificial_var = 1;
4565*404b540aSrobert   var_nothing->offset = 0;
4566*404b540aSrobert   var_nothing->size = ~0;
4567*404b540aSrobert   var_nothing->fullsize = ~0;
4568*404b540aSrobert   var_nothing->is_special_var = 1;
4569*404b540aSrobert   nothing_id = 0;
4570*404b540aSrobert   VEC_safe_push (varinfo_t, heap, varmap, var_nothing);
4571*404b540aSrobert 
4572*404b540aSrobert   /* Create the ANYTHING variable, used to represent that a variable
4573*404b540aSrobert      points to some unknown piece of memory.  */
4574*404b540aSrobert   anything_tree = create_tmp_var_raw (void_type_node, "ANYTHING");
4575*404b540aSrobert   var_anything = new_var_info (anything_tree, 1, "ANYTHING");
4576*404b540aSrobert   insert_vi_for_tree (anything_tree, var_anything);
4577*404b540aSrobert   var_anything->is_artificial_var = 1;
4578*404b540aSrobert   var_anything->size = ~0;
4579*404b540aSrobert   var_anything->offset = 0;
4580*404b540aSrobert   var_anything->next = NULL;
4581*404b540aSrobert   var_anything->fullsize = ~0;
4582*404b540aSrobert   var_anything->is_special_var = 1;
4583*404b540aSrobert   anything_id = 1;
4584*404b540aSrobert 
4585*404b540aSrobert   /* Anything points to anything.  This makes deref constraints just
4586*404b540aSrobert      work in the presence of linked list and other p = *p type loops,
4587*404b540aSrobert      by saying that *ANYTHING = ANYTHING. */
4588*404b540aSrobert   VEC_safe_push (varinfo_t, heap, varmap, var_anything);
4589*404b540aSrobert   lhs.type = SCALAR;
4590*404b540aSrobert   lhs.var = anything_id;
4591*404b540aSrobert   lhs.offset = 0;
4592*404b540aSrobert   rhs.type = ADDRESSOF;
4593*404b540aSrobert   rhs.var = anything_id;
4594*404b540aSrobert   rhs.offset = 0;
4595*404b540aSrobert 
4596*404b540aSrobert   /* This specifically does not use process_constraint because
4597*404b540aSrobert      process_constraint ignores all anything = anything constraints, since all
4598*404b540aSrobert      but this one are redundant.  */
4599*404b540aSrobert   VEC_safe_push (constraint_t, heap, constraints, new_constraint (lhs, rhs));
4600*404b540aSrobert 
4601*404b540aSrobert   /* Create the READONLY variable, used to represent that a variable
4602*404b540aSrobert      points to readonly memory.  */
4603*404b540aSrobert   readonly_tree = create_tmp_var_raw (void_type_node, "READONLY");
4604*404b540aSrobert   var_readonly = new_var_info (readonly_tree, 2, "READONLY");
4605*404b540aSrobert   var_readonly->is_artificial_var = 1;
4606*404b540aSrobert   var_readonly->offset = 0;
4607*404b540aSrobert   var_readonly->size = ~0;
4608*404b540aSrobert   var_readonly->fullsize = ~0;
4609*404b540aSrobert   var_readonly->next = NULL;
4610*404b540aSrobert   var_readonly->is_special_var = 1;
4611*404b540aSrobert   insert_vi_for_tree (readonly_tree, var_readonly);
4612*404b540aSrobert   readonly_id = 2;
4613*404b540aSrobert   VEC_safe_push (varinfo_t, heap, varmap, var_readonly);
4614*404b540aSrobert 
4615*404b540aSrobert   /* readonly memory points to anything, in order to make deref
4616*404b540aSrobert      easier.  In reality, it points to anything the particular
4617*404b540aSrobert      readonly variable can point to, but we don't track this
4618*404b540aSrobert      separately. */
4619*404b540aSrobert   lhs.type = SCALAR;
4620*404b540aSrobert   lhs.var = readonly_id;
4621*404b540aSrobert   lhs.offset = 0;
4622*404b540aSrobert   rhs.type = ADDRESSOF;
4623*404b540aSrobert   rhs.var = anything_id;
4624*404b540aSrobert   rhs.offset = 0;
4625*404b540aSrobert 
4626*404b540aSrobert   process_constraint (new_constraint (lhs, rhs));
4627*404b540aSrobert 
4628*404b540aSrobert   /* Create the INTEGER variable, used to represent that a variable points
4629*404b540aSrobert      to an INTEGER.  */
4630*404b540aSrobert   integer_tree = create_tmp_var_raw (void_type_node, "INTEGER");
4631*404b540aSrobert   var_integer = new_var_info (integer_tree, 3, "INTEGER");
4632*404b540aSrobert   insert_vi_for_tree (integer_tree, var_integer);
4633*404b540aSrobert   var_integer->is_artificial_var = 1;
4634*404b540aSrobert   var_integer->size = ~0;
4635*404b540aSrobert   var_integer->fullsize = ~0;
4636*404b540aSrobert   var_integer->offset = 0;
4637*404b540aSrobert   var_integer->next = NULL;
4638*404b540aSrobert   var_integer->is_special_var = 1;
4639*404b540aSrobert   integer_id = 3;
4640*404b540aSrobert   VEC_safe_push (varinfo_t, heap, varmap, var_integer);
4641*404b540aSrobert 
4642*404b540aSrobert   /* INTEGER = ANYTHING, because we don't know where a dereference of
4643*404b540aSrobert      a random integer will point to.  */
4644*404b540aSrobert   lhs.type = SCALAR;
4645*404b540aSrobert   lhs.var = integer_id;
4646*404b540aSrobert   lhs.offset = 0;
4647*404b540aSrobert   rhs.type = ADDRESSOF;
4648*404b540aSrobert   rhs.var = anything_id;
4649*404b540aSrobert   rhs.offset = 0;
4650*404b540aSrobert   process_constraint (new_constraint (lhs, rhs));
4651*404b540aSrobert 
4652*404b540aSrobert   /* Create the ESCAPED_VARS variable used to represent variables that
4653*404b540aSrobert      escape this function.  */
4654*404b540aSrobert   escaped_vars_tree = create_tmp_var_raw (void_type_node, "ESCAPED_VARS");
4655*404b540aSrobert   var_escaped_vars = new_var_info (escaped_vars_tree, 4, "ESCAPED_VARS");
4656*404b540aSrobert   insert_vi_for_tree (escaped_vars_tree, var_escaped_vars);
4657*404b540aSrobert   var_escaped_vars->is_artificial_var = 1;
4658*404b540aSrobert   var_escaped_vars->size = ~0;
4659*404b540aSrobert   var_escaped_vars->fullsize = ~0;
4660*404b540aSrobert   var_escaped_vars->offset = 0;
4661*404b540aSrobert   var_escaped_vars->next = NULL;
4662*404b540aSrobert   escaped_vars_id = 4;
4663*404b540aSrobert   VEC_safe_push (varinfo_t, heap, varmap, var_escaped_vars);
4664*404b540aSrobert 
4665*404b540aSrobert   /* ESCAPED_VARS = *ESCAPED_VARS */
4666*404b540aSrobert   lhs.type = SCALAR;
4667*404b540aSrobert   lhs.var = escaped_vars_id;
4668*404b540aSrobert   lhs.offset = 0;
4669*404b540aSrobert   rhs.type = DEREF;
4670*404b540aSrobert   rhs.var = escaped_vars_id;
4671*404b540aSrobert   rhs.offset = 0;
4672*404b540aSrobert   process_constraint (new_constraint (lhs, rhs));
4673*404b540aSrobert 
4674*404b540aSrobert }
4675*404b540aSrobert 
4676*404b540aSrobert /* Initialize things necessary to perform PTA */
4677*404b540aSrobert 
4678*404b540aSrobert static void
init_alias_vars(void)4679*404b540aSrobert init_alias_vars (void)
4680*404b540aSrobert {
4681*404b540aSrobert   bitmap_obstack_initialize (&pta_obstack);
4682*404b540aSrobert   bitmap_obstack_initialize (&oldpta_obstack);
4683*404b540aSrobert   bitmap_obstack_initialize (&predbitmap_obstack);
4684*404b540aSrobert 
4685*404b540aSrobert   constraint_pool = create_alloc_pool ("Constraint pool",
4686*404b540aSrobert 				       sizeof (struct constraint), 30);
4687*404b540aSrobert   variable_info_pool = create_alloc_pool ("Variable info pool",
4688*404b540aSrobert 					  sizeof (struct variable_info), 30);
4689*404b540aSrobert   constraints = VEC_alloc (constraint_t, heap, 8);
4690*404b540aSrobert   varmap = VEC_alloc (varinfo_t, heap, 8);
4691*404b540aSrobert   vi_for_tree = pointer_map_create ();
4692*404b540aSrobert 
4693*404b540aSrobert   memset (&stats, 0, sizeof (stats));
4694*404b540aSrobert   init_base_vars ();
4695*404b540aSrobert }
4696*404b540aSrobert 
4697*404b540aSrobert /* Given a statement STMT, generate necessary constraints to
4698*404b540aSrobert    escaped_vars for the escaping variables.  */
4699*404b540aSrobert 
4700*404b540aSrobert static void
find_escape_constraints(tree stmt)4701*404b540aSrobert find_escape_constraints (tree stmt)
4702*404b540aSrobert {
4703*404b540aSrobert   enum escape_type stmt_escape_type = is_escape_site (stmt);
4704*404b540aSrobert   tree rhs;
4705*404b540aSrobert   VEC(ce_s, heap) *rhsc = NULL;
4706*404b540aSrobert   struct constraint_expr *c;
4707*404b540aSrobert   size_t i;
4708*404b540aSrobert 
4709*404b540aSrobert   if (stmt_escape_type == NO_ESCAPE)
4710*404b540aSrobert     return;
4711*404b540aSrobert 
4712*404b540aSrobert   if (TREE_CODE (stmt) == RETURN_EXPR)
4713*404b540aSrobert     {
4714*404b540aSrobert       /* Returns are either bare, with an embedded MODIFY_EXPR, or
4715*404b540aSrobert 	 just a plain old expression.  */
4716*404b540aSrobert       if (!TREE_OPERAND (stmt, 0))
4717*404b540aSrobert 	return;
4718*404b540aSrobert       if (TREE_CODE (TREE_OPERAND (stmt, 0)) == MODIFY_EXPR)
4719*404b540aSrobert 	rhs = TREE_OPERAND (TREE_OPERAND (stmt, 0), 1);
4720*404b540aSrobert       else
4721*404b540aSrobert 	rhs = TREE_OPERAND (stmt, 0);
4722*404b540aSrobert 
4723*404b540aSrobert       get_constraint_for (rhs, &rhsc);
4724*404b540aSrobert       for (i = 0; VEC_iterate (ce_s, rhsc, i, c); i++)
4725*404b540aSrobert 	make_constraint_to_escaped (*c);
4726*404b540aSrobert       VEC_free (ce_s, heap, rhsc);
4727*404b540aSrobert       return;
4728*404b540aSrobert     }
4729*404b540aSrobert   else if (TREE_CODE (stmt) == ASM_EXPR)
4730*404b540aSrobert     {
4731*404b540aSrobert       /* Whatever the inputs of the ASM are, escape.  */
4732*404b540aSrobert       tree arg;
4733*404b540aSrobert 
4734*404b540aSrobert       for (arg = ASM_INPUTS (stmt); arg; arg = TREE_CHAIN (arg))
4735*404b540aSrobert 	{
4736*404b540aSrobert 	  rhsc = NULL;
4737*404b540aSrobert 	  get_constraint_for (TREE_VALUE (arg), &rhsc);
4738*404b540aSrobert 	  for (i = 0; VEC_iterate (ce_s, rhsc, i, c); i++)
4739*404b540aSrobert 	    make_constraint_to_escaped (*c);
4740*404b540aSrobert 	  VEC_free (ce_s, heap, rhsc);
4741*404b540aSrobert 	}
4742*404b540aSrobert       return;
4743*404b540aSrobert     }
4744*404b540aSrobert   else if (TREE_CODE (stmt) == CALL_EXPR
4745*404b540aSrobert 	   || (TREE_CODE (stmt) == MODIFY_EXPR
4746*404b540aSrobert 	       && TREE_CODE (TREE_OPERAND (stmt, 1)) == CALL_EXPR))
4747*404b540aSrobert     {
4748*404b540aSrobert       /* Calls cause all of the arguments passed in to escape.  */
4749*404b540aSrobert       tree arg;
4750*404b540aSrobert 
4751*404b540aSrobert       if (TREE_CODE (stmt) == MODIFY_EXPR)
4752*404b540aSrobert 	stmt = TREE_OPERAND (stmt, 1);
4753*404b540aSrobert       for (arg = TREE_OPERAND (stmt, 1); arg; arg = TREE_CHAIN (arg))
4754*404b540aSrobert 	{
4755*404b540aSrobert 	  if (POINTER_TYPE_P (TREE_TYPE (TREE_VALUE (arg))))
4756*404b540aSrobert 	    {
4757*404b540aSrobert 	      rhsc = NULL;
4758*404b540aSrobert 	      get_constraint_for (TREE_VALUE (arg), &rhsc);
4759*404b540aSrobert 	      for (i = 0; VEC_iterate (ce_s, rhsc, i, c); i++)
4760*404b540aSrobert 		make_constraint_to_escaped (*c);
4761*404b540aSrobert 	      VEC_free (ce_s, heap, rhsc);
4762*404b540aSrobert 	    }
4763*404b540aSrobert 	}
4764*404b540aSrobert       return;
4765*404b540aSrobert     }
4766*404b540aSrobert   else
4767*404b540aSrobert     {
4768*404b540aSrobert       gcc_assert (TREE_CODE (stmt) == MODIFY_EXPR);
4769*404b540aSrobert     }
4770*404b540aSrobert 
4771*404b540aSrobert   gcc_assert (stmt_escape_type == ESCAPE_BAD_CAST
4772*404b540aSrobert 	      || stmt_escape_type == ESCAPE_STORED_IN_GLOBAL
4773*404b540aSrobert 	      || stmt_escape_type == ESCAPE_UNKNOWN);
4774*404b540aSrobert   rhs = TREE_OPERAND (stmt, 1);
4775*404b540aSrobert 
4776*404b540aSrobert   /* Look through casts for the real escaping variable.
4777*404b540aSrobert      Constants don't really escape, so ignore them.
4778*404b540aSrobert      Otherwise, whatever escapes must be on our RHS.  */
4779*404b540aSrobert   if (TREE_CODE (rhs) == NOP_EXPR
4780*404b540aSrobert       || TREE_CODE (rhs) == CONVERT_EXPR
4781*404b540aSrobert       || TREE_CODE (rhs) == NON_LVALUE_EXPR)
4782*404b540aSrobert     {
4783*404b540aSrobert       get_constraint_for (TREE_OPERAND (rhs, 0), &rhsc);
4784*404b540aSrobert     }
4785*404b540aSrobert   else if (CONSTANT_CLASS_P (rhs))
4786*404b540aSrobert     return;
4787*404b540aSrobert   else
4788*404b540aSrobert     {
4789*404b540aSrobert       get_constraint_for (rhs, &rhsc);
4790*404b540aSrobert     }
4791*404b540aSrobert   for (i = 0; VEC_iterate (ce_s, rhsc, i, c); i++)
4792*404b540aSrobert     make_constraint_to_escaped (*c);
4793*404b540aSrobert   VEC_free (ce_s, heap, rhsc);
4794*404b540aSrobert }
4795*404b540aSrobert 
4796*404b540aSrobert 
4797*404b540aSrobert /* Remove the REF and ADDRESS edges from GRAPH, as well as all the
4798*404b540aSrobert    predecessor edges.  */
4799*404b540aSrobert 
4800*404b540aSrobert static void
remove_preds_and_fake_succs(constraint_graph_t graph)4801*404b540aSrobert remove_preds_and_fake_succs (constraint_graph_t graph)
4802*404b540aSrobert {
4803*404b540aSrobert   unsigned int i;
4804*404b540aSrobert 
4805*404b540aSrobert   /* Clear the implicit ref and address nodes from the successor
4806*404b540aSrobert      lists.  */
4807*404b540aSrobert   for (i = 0; i < FIRST_REF_NODE; i++)
4808*404b540aSrobert     {
4809*404b540aSrobert       if (graph->succs[i])
4810*404b540aSrobert 	bitmap_clear_range (graph->succs[i], FIRST_REF_NODE,
4811*404b540aSrobert 			    FIRST_REF_NODE * 2);
4812*404b540aSrobert     }
4813*404b540aSrobert 
4814*404b540aSrobert   /* Free the successor list for the non-ref nodes.  */
4815*404b540aSrobert   for (i = FIRST_REF_NODE; i < graph->size; i++)
4816*404b540aSrobert     {
4817*404b540aSrobert       if (graph->succs[i])
4818*404b540aSrobert 	BITMAP_FREE (graph->succs[i]);
4819*404b540aSrobert     }
4820*404b540aSrobert 
4821*404b540aSrobert   /* Now reallocate the size of the successor list as, and blow away
4822*404b540aSrobert      the predecessor bitmaps.  */
4823*404b540aSrobert   graph->size = VEC_length (varinfo_t, varmap);
4824*404b540aSrobert   graph->succs = xrealloc (graph->succs, graph->size * sizeof (bitmap));
4825*404b540aSrobert 
4826*404b540aSrobert   free (graph->implicit_preds);
4827*404b540aSrobert   graph->implicit_preds = NULL;
4828*404b540aSrobert   free (graph->preds);
4829*404b540aSrobert   graph->preds = NULL;
4830*404b540aSrobert   bitmap_obstack_release (&predbitmap_obstack);
4831*404b540aSrobert }
4832*404b540aSrobert 
4833*404b540aSrobert /* Create points-to sets for the current function.  See the comments
4834*404b540aSrobert    at the start of the file for an algorithmic overview.  */
4835*404b540aSrobert 
4836*404b540aSrobert void
compute_points_to_sets(struct alias_info * ai)4837*404b540aSrobert compute_points_to_sets (struct alias_info *ai)
4838*404b540aSrobert {
4839*404b540aSrobert   basic_block bb;
4840*404b540aSrobert   struct scc_info *si;
4841*404b540aSrobert 
4842*404b540aSrobert   timevar_push (TV_TREE_PTA);
4843*404b540aSrobert 
4844*404b540aSrobert   init_alias_vars ();
4845*404b540aSrobert   init_alias_heapvars ();
4846*404b540aSrobert 
4847*404b540aSrobert   intra_create_variable_infos ();
4848*404b540aSrobert 
4849*404b540aSrobert   /* Now walk all statements and derive aliases.  */
4850*404b540aSrobert   FOR_EACH_BB (bb)
4851*404b540aSrobert     {
4852*404b540aSrobert       block_stmt_iterator bsi;
4853*404b540aSrobert       tree phi;
4854*404b540aSrobert 
4855*404b540aSrobert       for (phi = phi_nodes (bb); phi; phi = TREE_CHAIN (phi))
4856*404b540aSrobert 	{
4857*404b540aSrobert 	  if (is_gimple_reg (PHI_RESULT (phi)))
4858*404b540aSrobert 	    {
4859*404b540aSrobert 	      find_func_aliases (phi);
4860*404b540aSrobert 	      /* Update various related attributes like escaped
4861*404b540aSrobert 		 addresses, pointer dereferences for loads and stores.
4862*404b540aSrobert 		 This is used when creating name tags and alias
4863*404b540aSrobert 		 sets.  */
4864*404b540aSrobert 	      update_alias_info (phi, ai);
4865*404b540aSrobert 	    }
4866*404b540aSrobert 	}
4867*404b540aSrobert 
4868*404b540aSrobert       for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
4869*404b540aSrobert 	{
4870*404b540aSrobert 	  tree stmt = bsi_stmt (bsi);
4871*404b540aSrobert 
4872*404b540aSrobert 	  find_func_aliases (stmt);
4873*404b540aSrobert 	  find_escape_constraints (stmt);
4874*404b540aSrobert 	  /* Update various related attributes like escaped
4875*404b540aSrobert 	     addresses, pointer dereferences for loads and stores.
4876*404b540aSrobert 	     This is used when creating name tags and alias
4877*404b540aSrobert 	     sets.  */
4878*404b540aSrobert 	  update_alias_info (stmt, ai);
4879*404b540aSrobert 	}
4880*404b540aSrobert     }
4881*404b540aSrobert 
4882*404b540aSrobert 
4883*404b540aSrobert   if (dump_file)
4884*404b540aSrobert     {
4885*404b540aSrobert       fprintf (dump_file, "Points-to analysis\n\nConstraints:\n\n");
4886*404b540aSrobert       dump_constraints (dump_file);
4887*404b540aSrobert     }
4888*404b540aSrobert 
4889*404b540aSrobert   if (dump_file)
4890*404b540aSrobert     fprintf (dump_file,
4891*404b540aSrobert 	     "\nCollapsing static cycles and doing variable "
4892*404b540aSrobert 	     "substitution:\n");
4893*404b540aSrobert 
4894*404b540aSrobert   build_pred_graph ();
4895*404b540aSrobert   si = perform_var_substitution (graph);
4896*404b540aSrobert   move_complex_constraints (graph, si);
4897*404b540aSrobert   free_var_substitution_info (si);
4898*404b540aSrobert 
4899*404b540aSrobert   build_succ_graph ();
4900*404b540aSrobert   find_indirect_cycles (graph);
4901*404b540aSrobert 
4902*404b540aSrobert   /* Implicit nodes and predecessors are no longer necessary at this
4903*404b540aSrobert      point. */
4904*404b540aSrobert   remove_preds_and_fake_succs (graph);
4905*404b540aSrobert 
4906*404b540aSrobert   if (dump_file)
4907*404b540aSrobert     fprintf (dump_file, "\nSolving graph:\n");
4908*404b540aSrobert 
4909*404b540aSrobert   solve_graph (graph);
4910*404b540aSrobert 
4911*404b540aSrobert   if (dump_file)
4912*404b540aSrobert     dump_sa_points_to_info (dump_file);
4913*404b540aSrobert   have_alias_info = true;
4914*404b540aSrobert 
4915*404b540aSrobert   timevar_pop (TV_TREE_PTA);
4916*404b540aSrobert }
4917*404b540aSrobert 
4918*404b540aSrobert /* Delete created points-to sets.  */
4919*404b540aSrobert 
4920*404b540aSrobert void
delete_points_to_sets(void)4921*404b540aSrobert delete_points_to_sets (void)
4922*404b540aSrobert {
4923*404b540aSrobert   varinfo_t v;
4924*404b540aSrobert   int i;
4925*404b540aSrobert 
4926*404b540aSrobert   if (dump_file && (dump_flags & TDF_STATS))
4927*404b540aSrobert     fprintf (dump_file, "Points to sets created:%d\n",
4928*404b540aSrobert 	     stats.points_to_sets_created);
4929*404b540aSrobert 
4930*404b540aSrobert   pointer_map_destroy (vi_for_tree);
4931*404b540aSrobert   bitmap_obstack_release (&pta_obstack);
4932*404b540aSrobert   VEC_free (constraint_t, heap, constraints);
4933*404b540aSrobert 
4934*404b540aSrobert   for (i = 0; VEC_iterate (varinfo_t, varmap, i, v); i++)
4935*404b540aSrobert     VEC_free (constraint_t, heap, graph->complex[i]);
4936*404b540aSrobert   free (graph->complex);
4937*404b540aSrobert 
4938*404b540aSrobert   free (graph->rep);
4939*404b540aSrobert   free (graph->succs);
4940*404b540aSrobert   free (graph->indirect_cycles);
4941*404b540aSrobert   free (graph);
4942*404b540aSrobert 
4943*404b540aSrobert   VEC_free (varinfo_t, heap, varmap);
4944*404b540aSrobert   free_alloc_pool (variable_info_pool);
4945*404b540aSrobert   free_alloc_pool (constraint_pool);
4946*404b540aSrobert   have_alias_info = false;
4947*404b540aSrobert }
4948*404b540aSrobert 
4949*404b540aSrobert /* Return true if we should execute IPA PTA.  */
4950*404b540aSrobert static bool
gate_ipa_pta(void)4951*404b540aSrobert gate_ipa_pta (void)
4952*404b540aSrobert {
4953*404b540aSrobert   return (flag_unit_at_a_time != 0
4954*404b540aSrobert           && flag_ipa_pta
4955*404b540aSrobert 	  /* Don't bother doing anything if the program has errors.  */
4956*404b540aSrobert 	  && !(errorcount || sorrycount));
4957*404b540aSrobert }
4958*404b540aSrobert 
4959*404b540aSrobert /* Execute the driver for IPA PTA.  */
4960*404b540aSrobert static unsigned int
ipa_pta_execute(void)4961*404b540aSrobert ipa_pta_execute (void)
4962*404b540aSrobert {
4963*404b540aSrobert #if 0
4964*404b540aSrobert   struct cgraph_node *node;
4965*404b540aSrobert   in_ipa_mode = 1;
4966*404b540aSrobert   init_alias_heapvars ();
4967*404b540aSrobert   init_alias_vars ();
4968*404b540aSrobert 
4969*404b540aSrobert   for (node = cgraph_nodes; node; node = node->next)
4970*404b540aSrobert     {
4971*404b540aSrobert       if (!node->analyzed || cgraph_is_master_clone (node))
4972*404b540aSrobert 	{
4973*404b540aSrobert 	  unsigned int varid;
4974*404b540aSrobert 
4975*404b540aSrobert 	  varid = create_function_info_for (node->decl,
4976*404b540aSrobert 					    cgraph_node_name (node));
4977*404b540aSrobert 	  if (node->local.externally_visible)
4978*404b540aSrobert 	    {
4979*404b540aSrobert 	      varinfo_t fi = get_varinfo (varid);
4980*404b540aSrobert 	      for (; fi; fi = fi->next)
4981*404b540aSrobert 		make_constraint_from_escaped (fi);
4982*404b540aSrobert 	    }
4983*404b540aSrobert 	}
4984*404b540aSrobert     }
4985*404b540aSrobert   for (node = cgraph_nodes; node; node = node->next)
4986*404b540aSrobert     {
4987*404b540aSrobert       if (node->analyzed && cgraph_is_master_clone (node))
4988*404b540aSrobert 	{
4989*404b540aSrobert 	  struct function *cfun = DECL_STRUCT_FUNCTION (node->decl);
4990*404b540aSrobert 	  basic_block bb;
4991*404b540aSrobert 	  tree old_func_decl = current_function_decl;
4992*404b540aSrobert 	  if (dump_file)
4993*404b540aSrobert 	    fprintf (dump_file,
4994*404b540aSrobert 		     "Generating constraints for %s\n",
4995*404b540aSrobert 		     cgraph_node_name (node));
4996*404b540aSrobert 	  push_cfun (cfun);
4997*404b540aSrobert 	  current_function_decl = node->decl;
4998*404b540aSrobert 
4999*404b540aSrobert 	  FOR_EACH_BB_FN (bb, cfun)
5000*404b540aSrobert 	    {
5001*404b540aSrobert 	      block_stmt_iterator bsi;
5002*404b540aSrobert 	      tree phi;
5003*404b540aSrobert 
5004*404b540aSrobert 	      for (phi = phi_nodes (bb); phi; phi = TREE_CHAIN (phi))
5005*404b540aSrobert 		{
5006*404b540aSrobert 		  if (is_gimple_reg (PHI_RESULT (phi)))
5007*404b540aSrobert 		    {
5008*404b540aSrobert 		      find_func_aliases (phi);
5009*404b540aSrobert 		    }
5010*404b540aSrobert 		}
5011*404b540aSrobert 
5012*404b540aSrobert 	      for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
5013*404b540aSrobert 		{
5014*404b540aSrobert 		  tree stmt = bsi_stmt (bsi);
5015*404b540aSrobert 		  find_func_aliases (stmt);
5016*404b540aSrobert 		}
5017*404b540aSrobert 	    }
5018*404b540aSrobert 	  current_function_decl = old_func_decl;
5019*404b540aSrobert 	  pop_cfun ();
5020*404b540aSrobert 	}
5021*404b540aSrobert       else
5022*404b540aSrobert 	{
5023*404b540aSrobert 	  /* Make point to anything.  */
5024*404b540aSrobert 	}
5025*404b540aSrobert     }
5026*404b540aSrobert 
5027*404b540aSrobert   build_constraint_graph ();
5028*404b540aSrobert 
5029*404b540aSrobert   if (dump_file)
5030*404b540aSrobert     {
5031*404b540aSrobert       fprintf (dump_file, "Points-to analysis\n\nConstraints:\n\n");
5032*404b540aSrobert       dump_constraints (dump_file);
5033*404b540aSrobert     }
5034*404b540aSrobert 
5035*404b540aSrobert   if (dump_file)
5036*404b540aSrobert     fprintf (dump_file,
5037*404b540aSrobert 	     "\nCollapsing static cycles and doing variable "
5038*404b540aSrobert 	     "substitution:\n");
5039*404b540aSrobert 
5040*404b540aSrobert   find_and_collapse_graph_cycles (graph, false);
5041*404b540aSrobert   perform_var_substitution (graph);
5042*404b540aSrobert 
5043*404b540aSrobert   if (dump_file)
5044*404b540aSrobert     fprintf (dump_file, "\nSolving graph:\n");
5045*404b540aSrobert 
5046*404b540aSrobert   solve_graph (graph);
5047*404b540aSrobert 
5048*404b540aSrobert   if (dump_file)
5049*404b540aSrobert     dump_sa_points_to_info (dump_file);
5050*404b540aSrobert   in_ipa_mode = 0;
5051*404b540aSrobert   delete_alias_heapvars ();
5052*404b540aSrobert   delete_points_to_sets ();
5053*404b540aSrobert #endif
5054*404b540aSrobert   return 0;
5055*404b540aSrobert }
5056*404b540aSrobert 
5057*404b540aSrobert struct tree_opt_pass pass_ipa_pta =
5058*404b540aSrobert {
5059*404b540aSrobert   "pta",		                /* name */
5060*404b540aSrobert   gate_ipa_pta,			/* gate */
5061*404b540aSrobert   ipa_pta_execute,			/* execute */
5062*404b540aSrobert   NULL,					/* sub */
5063*404b540aSrobert   NULL,					/* next */
5064*404b540aSrobert   0,					/* static_pass_number */
5065*404b540aSrobert   TV_IPA_PTA,		        /* tv_id */
5066*404b540aSrobert   0,	                                /* properties_required */
5067*404b540aSrobert   0,					/* properties_provided */
5068*404b540aSrobert   0,					/* properties_destroyed */
5069*404b540aSrobert   0,					/* todo_flags_start */
5070*404b540aSrobert   0,                                    /* todo_flags_finish */
5071*404b540aSrobert   0					/* letter */
5072*404b540aSrobert };
5073*404b540aSrobert 
5074*404b540aSrobert /* Initialize the heapvar for statement mapping.  */
5075*404b540aSrobert void
init_alias_heapvars(void)5076*404b540aSrobert init_alias_heapvars (void)
5077*404b540aSrobert {
5078*404b540aSrobert   if (!heapvar_for_stmt)
5079*404b540aSrobert     heapvar_for_stmt = htab_create_ggc (11, tree_map_hash, tree_map_eq,
5080*404b540aSrobert 					NULL);
5081*404b540aSrobert   nonlocal_all = NULL_TREE;
5082*404b540aSrobert }
5083*404b540aSrobert 
5084*404b540aSrobert void
delete_alias_heapvars(void)5085*404b540aSrobert delete_alias_heapvars (void)
5086*404b540aSrobert {
5087*404b540aSrobert   nonlocal_all = NULL_TREE;
5088*404b540aSrobert   htab_delete (heapvar_for_stmt);
5089*404b540aSrobert   heapvar_for_stmt = NULL;
5090*404b540aSrobert }
5091*404b540aSrobert 
5092*404b540aSrobert #include "gt-tree-ssa-structalias.h"
5093