1e4b17023SJohn Marino /* SCC value numbering for trees
2e4b17023SJohn Marino    Copyright (C) 2006, 2007, 2008, 2009, 2010
3e4b17023SJohn Marino    Free Software Foundation, Inc.
4e4b17023SJohn Marino    Contributed by Daniel Berlin <dan@dberlin.org>
5e4b17023SJohn Marino 
6e4b17023SJohn Marino This file is part of GCC.
7e4b17023SJohn Marino 
8e4b17023SJohn Marino GCC is free software; you can redistribute it and/or modify
9e4b17023SJohn Marino it under the terms of the GNU General Public License as published by
10e4b17023SJohn Marino the Free Software Foundation; either version 3, or (at your option)
11e4b17023SJohn Marino any later version.
12e4b17023SJohn Marino 
13e4b17023SJohn Marino GCC is distributed in the hope that it will be useful,
14e4b17023SJohn Marino but WITHOUT ANY WARRANTY; without even the implied warranty of
15e4b17023SJohn Marino MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16e4b17023SJohn Marino GNU General Public License for more details.
17e4b17023SJohn Marino 
18e4b17023SJohn Marino You should have received a copy of the GNU General Public License
19e4b17023SJohn Marino along with GCC; see the file COPYING3.  If not see
20e4b17023SJohn Marino <http://www.gnu.org/licenses/>.  */
21e4b17023SJohn Marino 
22e4b17023SJohn Marino #include "config.h"
23e4b17023SJohn Marino #include "system.h"
24e4b17023SJohn Marino #include "coretypes.h"
25e4b17023SJohn Marino #include "tm.h"
26e4b17023SJohn Marino #include "tree.h"
27e4b17023SJohn Marino #include "basic-block.h"
28e4b17023SJohn Marino #include "tree-pretty-print.h"
29e4b17023SJohn Marino #include "gimple-pretty-print.h"
30e4b17023SJohn Marino #include "tree-inline.h"
31e4b17023SJohn Marino #include "tree-flow.h"
32e4b17023SJohn Marino #include "gimple.h"
33e4b17023SJohn Marino #include "tree-dump.h"
34e4b17023SJohn Marino #include "timevar.h"
35e4b17023SJohn Marino #include "fibheap.h"
36e4b17023SJohn Marino #include "hashtab.h"
37e4b17023SJohn Marino #include "tree-iterator.h"
38e4b17023SJohn Marino #include "alloc-pool.h"
39e4b17023SJohn Marino #include "tree-pass.h"
40e4b17023SJohn Marino #include "flags.h"
41e4b17023SJohn Marino #include "bitmap.h"
42e4b17023SJohn Marino #include "langhooks.h"
43e4b17023SJohn Marino #include "cfgloop.h"
44e4b17023SJohn Marino #include "params.h"
45e4b17023SJohn Marino #include "tree-ssa-propagate.h"
46e4b17023SJohn Marino #include "tree-ssa-sccvn.h"
47e4b17023SJohn Marino #include "gimple-fold.h"
48e4b17023SJohn Marino 
49e4b17023SJohn Marino /* This algorithm is based on the SCC algorithm presented by Keith
50e4b17023SJohn Marino    Cooper and L. Taylor Simpson in "SCC-Based Value numbering"
51e4b17023SJohn Marino    (http://citeseer.ist.psu.edu/41805.html).  In
52e4b17023SJohn Marino    straight line code, it is equivalent to a regular hash based value
53e4b17023SJohn Marino    numbering that is performed in reverse postorder.
54e4b17023SJohn Marino 
55e4b17023SJohn Marino    For code with cycles, there are two alternatives, both of which
56e4b17023SJohn Marino    require keeping the hashtables separate from the actual list of
57e4b17023SJohn Marino    value numbers for SSA names.
58e4b17023SJohn Marino 
59e4b17023SJohn Marino    1. Iterate value numbering in an RPO walk of the blocks, removing
60e4b17023SJohn Marino    all the entries from the hashtable after each iteration (but
61e4b17023SJohn Marino    keeping the SSA name->value number mapping between iterations).
62e4b17023SJohn Marino    Iterate until it does not change.
63e4b17023SJohn Marino 
64e4b17023SJohn Marino    2. Perform value numbering as part of an SCC walk on the SSA graph,
65e4b17023SJohn Marino    iterating only the cycles in the SSA graph until they do not change
66e4b17023SJohn Marino    (using a separate, optimistic hashtable for value numbering the SCC
67e4b17023SJohn Marino    operands).
68e4b17023SJohn Marino 
69e4b17023SJohn Marino    The second is not just faster in practice (because most SSA graph
70e4b17023SJohn Marino    cycles do not involve all the variables in the graph), it also has
71e4b17023SJohn Marino    some nice properties.
72e4b17023SJohn Marino 
73e4b17023SJohn Marino    One of these nice properties is that when we pop an SCC off the
74e4b17023SJohn Marino    stack, we are guaranteed to have processed all the operands coming from
75e4b17023SJohn Marino    *outside of that SCC*, so we do not need to do anything special to
76e4b17023SJohn Marino    ensure they have value numbers.
77e4b17023SJohn Marino 
78e4b17023SJohn Marino    Another nice property is that the SCC walk is done as part of a DFS
79e4b17023SJohn Marino    of the SSA graph, which makes it easy to perform combining and
80e4b17023SJohn Marino    simplifying operations at the same time.
81e4b17023SJohn Marino 
82e4b17023SJohn Marino    The code below is deliberately written in a way that makes it easy
83e4b17023SJohn Marino    to separate the SCC walk from the other work it does.
84e4b17023SJohn Marino 
85e4b17023SJohn Marino    In order to propagate constants through the code, we track which
86e4b17023SJohn Marino    expressions contain constants, and use those while folding.  In
87e4b17023SJohn Marino    theory, we could also track expressions whose value numbers are
88e4b17023SJohn Marino    replaced, in case we end up folding based on expression
89e4b17023SJohn Marino    identities.
90e4b17023SJohn Marino 
91e4b17023SJohn Marino    In order to value number memory, we assign value numbers to vuses.
92e4b17023SJohn Marino    This enables us to note that, for example, stores to the same
93e4b17023SJohn Marino    address of the same value from the same starting memory states are
94e4b17023SJohn Marino    equivalent.
95e4b17023SJohn Marino    TODO:
96e4b17023SJohn Marino 
97e4b17023SJohn Marino    1. We can iterate only the changing portions of the SCC's, but
98e4b17023SJohn Marino    I have not seen an SCC big enough for this to be a win.
99e4b17023SJohn Marino    2. If you differentiate between phi nodes for loops and phi nodes
100e4b17023SJohn Marino    for if-then-else, you can properly consider phi nodes in different
101e4b17023SJohn Marino    blocks for equivalence.
102e4b17023SJohn Marino    3. We could value number vuses in more cases, particularly, whole
103e4b17023SJohn Marino    structure copies.
104e4b17023SJohn Marino */
105e4b17023SJohn Marino 
106e4b17023SJohn Marino /* The set of hashtables and alloc_pool's for their items.  */
107e4b17023SJohn Marino 
108e4b17023SJohn Marino typedef struct vn_tables_s
109e4b17023SJohn Marino {
110e4b17023SJohn Marino   htab_t nary;
111e4b17023SJohn Marino   htab_t phis;
112e4b17023SJohn Marino   htab_t references;
113e4b17023SJohn Marino   struct obstack nary_obstack;
114e4b17023SJohn Marino   alloc_pool phis_pool;
115e4b17023SJohn Marino   alloc_pool references_pool;
116e4b17023SJohn Marino } *vn_tables_t;
117e4b17023SJohn Marino 
118e4b17023SJohn Marino static htab_t constant_to_value_id;
119e4b17023SJohn Marino static bitmap constant_value_ids;
120e4b17023SJohn Marino 
121e4b17023SJohn Marino 
122e4b17023SJohn Marino /* Valid hashtables storing information we have proven to be
123e4b17023SJohn Marino    correct.  */
124e4b17023SJohn Marino 
125e4b17023SJohn Marino static vn_tables_t valid_info;
126e4b17023SJohn Marino 
127e4b17023SJohn Marino /* Optimistic hashtables storing information we are making assumptions about
128e4b17023SJohn Marino    during iterations.  */
129e4b17023SJohn Marino 
130e4b17023SJohn Marino static vn_tables_t optimistic_info;
131e4b17023SJohn Marino 
132e4b17023SJohn Marino /* Pointer to the set of hashtables that is currently being used.
133e4b17023SJohn Marino    Should always point to either the optimistic_info, or the
134e4b17023SJohn Marino    valid_info.  */
135e4b17023SJohn Marino 
136e4b17023SJohn Marino static vn_tables_t current_info;
137e4b17023SJohn Marino 
138e4b17023SJohn Marino 
139e4b17023SJohn Marino /* Reverse post order index for each basic block.  */
140e4b17023SJohn Marino 
141e4b17023SJohn Marino static int *rpo_numbers;
142e4b17023SJohn Marino 
143e4b17023SJohn Marino #define SSA_VAL(x) (VN_INFO ((x))->valnum)
144e4b17023SJohn Marino 
145e4b17023SJohn Marino /* This represents the top of the VN lattice, which is the universal
146e4b17023SJohn Marino    value.  */
147e4b17023SJohn Marino 
148e4b17023SJohn Marino tree VN_TOP;
149e4b17023SJohn Marino 
150e4b17023SJohn Marino /* Unique counter for our value ids.  */
151e4b17023SJohn Marino 
152e4b17023SJohn Marino static unsigned int next_value_id;
153e4b17023SJohn Marino 
154e4b17023SJohn Marino /* Next DFS number and the stack for strongly connected component
155e4b17023SJohn Marino    detection. */
156e4b17023SJohn Marino 
157e4b17023SJohn Marino static unsigned int next_dfs_num;
158e4b17023SJohn Marino static VEC (tree, heap) *sccstack;
159e4b17023SJohn Marino 
160e4b17023SJohn Marino 
161e4b17023SJohn Marino DEF_VEC_P(vn_ssa_aux_t);
162e4b17023SJohn Marino DEF_VEC_ALLOC_P(vn_ssa_aux_t, heap);
163e4b17023SJohn Marino 
164e4b17023SJohn Marino /* Table of vn_ssa_aux_t's, one per ssa_name.  The vn_ssa_aux_t objects
165e4b17023SJohn Marino    are allocated on an obstack for locality reasons, and to free them
166e4b17023SJohn Marino    without looping over the VEC.  */
167e4b17023SJohn Marino 
VEC(vn_ssa_aux_t,heap)168e4b17023SJohn Marino static VEC (vn_ssa_aux_t, heap) *vn_ssa_aux_table;
169e4b17023SJohn Marino static struct obstack vn_ssa_aux_obstack;
170e4b17023SJohn Marino 
171e4b17023SJohn Marino /* Return the value numbering information for a given SSA name.  */
172e4b17023SJohn Marino 
173e4b17023SJohn Marino vn_ssa_aux_t
174e4b17023SJohn Marino VN_INFO (tree name)
175e4b17023SJohn Marino {
176e4b17023SJohn Marino   vn_ssa_aux_t res = VEC_index (vn_ssa_aux_t, vn_ssa_aux_table,
177e4b17023SJohn Marino 				SSA_NAME_VERSION (name));
178e4b17023SJohn Marino   gcc_checking_assert (res);
179e4b17023SJohn Marino   return res;
180e4b17023SJohn Marino }
181e4b17023SJohn Marino 
182e4b17023SJohn Marino /* Set the value numbering info for a given SSA name to a given
183e4b17023SJohn Marino    value.  */
184e4b17023SJohn Marino 
185e4b17023SJohn Marino static inline void
VN_INFO_SET(tree name,vn_ssa_aux_t value)186e4b17023SJohn Marino VN_INFO_SET (tree name, vn_ssa_aux_t value)
187e4b17023SJohn Marino {
188e4b17023SJohn Marino   VEC_replace (vn_ssa_aux_t, vn_ssa_aux_table,
189e4b17023SJohn Marino 	       SSA_NAME_VERSION (name), value);
190e4b17023SJohn Marino }
191e4b17023SJohn Marino 
192e4b17023SJohn Marino /* Initialize the value numbering info for a given SSA name.
193e4b17023SJohn Marino    This should be called just once for every SSA name.  */
194e4b17023SJohn Marino 
195e4b17023SJohn Marino vn_ssa_aux_t
VN_INFO_GET(tree name)196e4b17023SJohn Marino VN_INFO_GET (tree name)
197e4b17023SJohn Marino {
198e4b17023SJohn Marino   vn_ssa_aux_t newinfo;
199e4b17023SJohn Marino 
200e4b17023SJohn Marino   newinfo = XOBNEW (&vn_ssa_aux_obstack, struct vn_ssa_aux);
201e4b17023SJohn Marino   memset (newinfo, 0, sizeof (struct vn_ssa_aux));
202e4b17023SJohn Marino   if (SSA_NAME_VERSION (name) >= VEC_length (vn_ssa_aux_t, vn_ssa_aux_table))
203e4b17023SJohn Marino     VEC_safe_grow (vn_ssa_aux_t, heap, vn_ssa_aux_table,
204e4b17023SJohn Marino 		   SSA_NAME_VERSION (name) + 1);
205e4b17023SJohn Marino   VEC_replace (vn_ssa_aux_t, vn_ssa_aux_table,
206e4b17023SJohn Marino 	       SSA_NAME_VERSION (name), newinfo);
207e4b17023SJohn Marino   return newinfo;
208e4b17023SJohn Marino }
209e4b17023SJohn Marino 
210e4b17023SJohn Marino 
211e4b17023SJohn Marino /* Get the representative expression for the SSA_NAME NAME.  Returns
212e4b17023SJohn Marino    the representative SSA_NAME if there is no expression associated with it.  */
213e4b17023SJohn Marino 
214e4b17023SJohn Marino tree
vn_get_expr_for(tree name)215e4b17023SJohn Marino vn_get_expr_for (tree name)
216e4b17023SJohn Marino {
217e4b17023SJohn Marino   vn_ssa_aux_t vn = VN_INFO (name);
218e4b17023SJohn Marino   gimple def_stmt;
219e4b17023SJohn Marino   tree expr = NULL_TREE;
220e4b17023SJohn Marino   enum tree_code code;
221e4b17023SJohn Marino 
222e4b17023SJohn Marino   if (vn->valnum == VN_TOP)
223e4b17023SJohn Marino     return name;
224e4b17023SJohn Marino 
225e4b17023SJohn Marino   /* If the value-number is a constant it is the representative
226e4b17023SJohn Marino      expression.  */
227e4b17023SJohn Marino   if (TREE_CODE (vn->valnum) != SSA_NAME)
228e4b17023SJohn Marino     return vn->valnum;
229e4b17023SJohn Marino 
230e4b17023SJohn Marino   /* Get to the information of the value of this SSA_NAME.  */
231e4b17023SJohn Marino   vn = VN_INFO (vn->valnum);
232e4b17023SJohn Marino 
233e4b17023SJohn Marino   /* If the value-number is a constant it is the representative
234e4b17023SJohn Marino      expression.  */
235e4b17023SJohn Marino   if (TREE_CODE (vn->valnum) != SSA_NAME)
236e4b17023SJohn Marino     return vn->valnum;
237e4b17023SJohn Marino 
238e4b17023SJohn Marino   /* Else if we have an expression, return it.  */
239e4b17023SJohn Marino   if (vn->expr != NULL_TREE)
240e4b17023SJohn Marino     return vn->expr;
241e4b17023SJohn Marino 
242e4b17023SJohn Marino   /* Otherwise use the defining statement to build the expression.  */
243e4b17023SJohn Marino   def_stmt = SSA_NAME_DEF_STMT (vn->valnum);
244e4b17023SJohn Marino 
245e4b17023SJohn Marino   /* If the value number is not an assignment use it directly.  */
246e4b17023SJohn Marino   if (!is_gimple_assign (def_stmt))
247e4b17023SJohn Marino     return vn->valnum;
248e4b17023SJohn Marino 
249e4b17023SJohn Marino   /* FIXME tuples.  This is incomplete and likely will miss some
250e4b17023SJohn Marino      simplifications.  */
251e4b17023SJohn Marino   code = gimple_assign_rhs_code (def_stmt);
252e4b17023SJohn Marino   switch (TREE_CODE_CLASS (code))
253e4b17023SJohn Marino     {
254e4b17023SJohn Marino     case tcc_reference:
255e4b17023SJohn Marino       if ((code == REALPART_EXPR
256e4b17023SJohn Marino 	   || code == IMAGPART_EXPR
257e4b17023SJohn Marino 	   || code == VIEW_CONVERT_EXPR)
258e4b17023SJohn Marino 	  && TREE_CODE (TREE_OPERAND (gimple_assign_rhs1 (def_stmt),
259e4b17023SJohn Marino 				      0)) == SSA_NAME)
260e4b17023SJohn Marino 	expr = fold_build1 (code,
261e4b17023SJohn Marino 			    gimple_expr_type (def_stmt),
262e4b17023SJohn Marino 			    TREE_OPERAND (gimple_assign_rhs1 (def_stmt), 0));
263e4b17023SJohn Marino       break;
264e4b17023SJohn Marino 
265e4b17023SJohn Marino     case tcc_unary:
266e4b17023SJohn Marino       expr = fold_build1 (code,
267e4b17023SJohn Marino 			  gimple_expr_type (def_stmt),
268e4b17023SJohn Marino 			  gimple_assign_rhs1 (def_stmt));
269e4b17023SJohn Marino       break;
270e4b17023SJohn Marino 
271e4b17023SJohn Marino     case tcc_binary:
272e4b17023SJohn Marino       expr = fold_build2 (code,
273e4b17023SJohn Marino 			  gimple_expr_type (def_stmt),
274e4b17023SJohn Marino 			  gimple_assign_rhs1 (def_stmt),
275e4b17023SJohn Marino 			  gimple_assign_rhs2 (def_stmt));
276e4b17023SJohn Marino       break;
277e4b17023SJohn Marino 
278e4b17023SJohn Marino     case tcc_exceptional:
279e4b17023SJohn Marino       if (code == CONSTRUCTOR
280e4b17023SJohn Marino 	  && TREE_CODE
281e4b17023SJohn Marino 	       (TREE_TYPE (gimple_assign_rhs1 (def_stmt))) == VECTOR_TYPE)
282e4b17023SJohn Marino 	expr = gimple_assign_rhs1 (def_stmt);
283e4b17023SJohn Marino       break;
284e4b17023SJohn Marino 
285e4b17023SJohn Marino     default:;
286e4b17023SJohn Marino     }
287e4b17023SJohn Marino   if (expr == NULL_TREE)
288e4b17023SJohn Marino     return vn->valnum;
289e4b17023SJohn Marino 
290e4b17023SJohn Marino   /* Cache the expression.  */
291e4b17023SJohn Marino   vn->expr = expr;
292e4b17023SJohn Marino 
293e4b17023SJohn Marino   return expr;
294e4b17023SJohn Marino }
295e4b17023SJohn Marino 
296e4b17023SJohn Marino 
297e4b17023SJohn Marino /* Free a phi operation structure VP.  */
298e4b17023SJohn Marino 
299e4b17023SJohn Marino static void
free_phi(void * vp)300e4b17023SJohn Marino free_phi (void *vp)
301e4b17023SJohn Marino {
302e4b17023SJohn Marino   vn_phi_t phi = (vn_phi_t) vp;
303e4b17023SJohn Marino   VEC_free (tree, heap, phi->phiargs);
304e4b17023SJohn Marino }
305e4b17023SJohn Marino 
306e4b17023SJohn Marino /* Free a reference operation structure VP.  */
307e4b17023SJohn Marino 
308e4b17023SJohn Marino static void
free_reference(void * vp)309e4b17023SJohn Marino free_reference (void *vp)
310e4b17023SJohn Marino {
311e4b17023SJohn Marino   vn_reference_t vr = (vn_reference_t) vp;
312e4b17023SJohn Marino   VEC_free (vn_reference_op_s, heap, vr->operands);
313e4b17023SJohn Marino }
314e4b17023SJohn Marino 
315e4b17023SJohn Marino /* Hash table equality function for vn_constant_t.  */
316e4b17023SJohn Marino 
317e4b17023SJohn Marino static int
vn_constant_eq(const void * p1,const void * p2)318e4b17023SJohn Marino vn_constant_eq (const void *p1, const void *p2)
319e4b17023SJohn Marino {
320e4b17023SJohn Marino   const struct vn_constant_s *vc1 = (const struct vn_constant_s *) p1;
321e4b17023SJohn Marino   const struct vn_constant_s *vc2 = (const struct vn_constant_s *) p2;
322e4b17023SJohn Marino 
323e4b17023SJohn Marino   if (vc1->hashcode != vc2->hashcode)
324e4b17023SJohn Marino     return false;
325e4b17023SJohn Marino 
326e4b17023SJohn Marino   return vn_constant_eq_with_type (vc1->constant, vc2->constant);
327e4b17023SJohn Marino }
328e4b17023SJohn Marino 
329e4b17023SJohn Marino /* Hash table hash function for vn_constant_t.  */
330e4b17023SJohn Marino 
331e4b17023SJohn Marino static hashval_t
vn_constant_hash(const void * p1)332e4b17023SJohn Marino vn_constant_hash (const void *p1)
333e4b17023SJohn Marino {
334e4b17023SJohn Marino   const struct vn_constant_s *vc1 = (const struct vn_constant_s *) p1;
335e4b17023SJohn Marino   return vc1->hashcode;
336e4b17023SJohn Marino }
337e4b17023SJohn Marino 
338e4b17023SJohn Marino /* Lookup a value id for CONSTANT and return it.  If it does not
339e4b17023SJohn Marino    exist returns 0.  */
340e4b17023SJohn Marino 
341e4b17023SJohn Marino unsigned int
get_constant_value_id(tree constant)342e4b17023SJohn Marino get_constant_value_id (tree constant)
343e4b17023SJohn Marino {
344e4b17023SJohn Marino   void **slot;
345e4b17023SJohn Marino   struct vn_constant_s vc;
346e4b17023SJohn Marino 
347e4b17023SJohn Marino   vc.hashcode = vn_hash_constant_with_type (constant);
348e4b17023SJohn Marino   vc.constant = constant;
349e4b17023SJohn Marino   slot = htab_find_slot_with_hash (constant_to_value_id, &vc,
350e4b17023SJohn Marino 				   vc.hashcode, NO_INSERT);
351e4b17023SJohn Marino   if (slot)
352e4b17023SJohn Marino     return ((vn_constant_t)*slot)->value_id;
353e4b17023SJohn Marino   return 0;
354e4b17023SJohn Marino }
355e4b17023SJohn Marino 
356e4b17023SJohn Marino /* Lookup a value id for CONSTANT, and if it does not exist, create a
357e4b17023SJohn Marino    new one and return it.  If it does exist, return it.  */
358e4b17023SJohn Marino 
359e4b17023SJohn Marino unsigned int
get_or_alloc_constant_value_id(tree constant)360e4b17023SJohn Marino get_or_alloc_constant_value_id (tree constant)
361e4b17023SJohn Marino {
362e4b17023SJohn Marino   void **slot;
363e4b17023SJohn Marino   struct vn_constant_s vc;
364e4b17023SJohn Marino   vn_constant_t vcp;
365e4b17023SJohn Marino 
366e4b17023SJohn Marino   vc.hashcode = vn_hash_constant_with_type (constant);
367e4b17023SJohn Marino   vc.constant = constant;
368e4b17023SJohn Marino   slot = htab_find_slot_with_hash (constant_to_value_id, &vc,
369e4b17023SJohn Marino 				   vc.hashcode, INSERT);
370e4b17023SJohn Marino   if (*slot)
371e4b17023SJohn Marino     return ((vn_constant_t)*slot)->value_id;
372e4b17023SJohn Marino 
373e4b17023SJohn Marino   vcp = XNEW (struct vn_constant_s);
374e4b17023SJohn Marino   vcp->hashcode = vc.hashcode;
375e4b17023SJohn Marino   vcp->constant = constant;
376e4b17023SJohn Marino   vcp->value_id = get_next_value_id ();
377e4b17023SJohn Marino   *slot = (void *) vcp;
378e4b17023SJohn Marino   bitmap_set_bit (constant_value_ids, vcp->value_id);
379e4b17023SJohn Marino   return vcp->value_id;
380e4b17023SJohn Marino }
381e4b17023SJohn Marino 
382e4b17023SJohn Marino /* Return true if V is a value id for a constant.  */
383e4b17023SJohn Marino 
384e4b17023SJohn Marino bool
value_id_constant_p(unsigned int v)385e4b17023SJohn Marino value_id_constant_p (unsigned int v)
386e4b17023SJohn Marino {
387e4b17023SJohn Marino   return bitmap_bit_p (constant_value_ids, v);
388e4b17023SJohn Marino }
389e4b17023SJohn Marino 
390e4b17023SJohn Marino /* Compare two reference operands P1 and P2 for equality.  Return true if
391e4b17023SJohn Marino    they are equal, and false otherwise.  */
392e4b17023SJohn Marino 
393e4b17023SJohn Marino static int
vn_reference_op_eq(const void * p1,const void * p2)394e4b17023SJohn Marino vn_reference_op_eq (const void *p1, const void *p2)
395e4b17023SJohn Marino {
396e4b17023SJohn Marino   const_vn_reference_op_t const vro1 = (const_vn_reference_op_t) p1;
397e4b17023SJohn Marino   const_vn_reference_op_t const vro2 = (const_vn_reference_op_t) p2;
398e4b17023SJohn Marino 
399e4b17023SJohn Marino   return (vro1->opcode == vro2->opcode
400e4b17023SJohn Marino 	  /* We do not care for differences in type qualification.  */
401e4b17023SJohn Marino 	  && (vro1->type == vro2->type
402e4b17023SJohn Marino 	      || (vro1->type && vro2->type
403e4b17023SJohn Marino 		  && types_compatible_p (TYPE_MAIN_VARIANT (vro1->type),
404e4b17023SJohn Marino 					 TYPE_MAIN_VARIANT (vro2->type))))
405e4b17023SJohn Marino 	  && expressions_equal_p (vro1->op0, vro2->op0)
406e4b17023SJohn Marino 	  && expressions_equal_p (vro1->op1, vro2->op1)
407e4b17023SJohn Marino 	  && expressions_equal_p (vro1->op2, vro2->op2));
408e4b17023SJohn Marino }
409e4b17023SJohn Marino 
410e4b17023SJohn Marino /* Compute the hash for a reference operand VRO1.  */
411e4b17023SJohn Marino 
412e4b17023SJohn Marino static hashval_t
vn_reference_op_compute_hash(const vn_reference_op_t vro1,hashval_t result)413e4b17023SJohn Marino vn_reference_op_compute_hash (const vn_reference_op_t vro1, hashval_t result)
414e4b17023SJohn Marino {
415e4b17023SJohn Marino   result = iterative_hash_hashval_t (vro1->opcode, result);
416e4b17023SJohn Marino   if (vro1->op0)
417e4b17023SJohn Marino     result = iterative_hash_expr (vro1->op0, result);
418e4b17023SJohn Marino   if (vro1->op1)
419e4b17023SJohn Marino     result = iterative_hash_expr (vro1->op1, result);
420e4b17023SJohn Marino   if (vro1->op2)
421e4b17023SJohn Marino     result = iterative_hash_expr (vro1->op2, result);
422e4b17023SJohn Marino   return result;
423e4b17023SJohn Marino }
424e4b17023SJohn Marino 
425e4b17023SJohn Marino /* Return the hashcode for a given reference operation P1.  */
426e4b17023SJohn Marino 
427e4b17023SJohn Marino static hashval_t
vn_reference_hash(const void * p1)428e4b17023SJohn Marino vn_reference_hash (const void *p1)
429e4b17023SJohn Marino {
430e4b17023SJohn Marino   const_vn_reference_t const vr1 = (const_vn_reference_t) p1;
431e4b17023SJohn Marino   return vr1->hashcode;
432e4b17023SJohn Marino }
433e4b17023SJohn Marino 
434e4b17023SJohn Marino /* Compute a hash for the reference operation VR1 and return it.  */
435e4b17023SJohn Marino 
436e4b17023SJohn Marino hashval_t
vn_reference_compute_hash(const vn_reference_t vr1)437e4b17023SJohn Marino vn_reference_compute_hash (const vn_reference_t vr1)
438e4b17023SJohn Marino {
439e4b17023SJohn Marino   hashval_t result = 0;
440e4b17023SJohn Marino   int i;
441e4b17023SJohn Marino   vn_reference_op_t vro;
442e4b17023SJohn Marino   HOST_WIDE_INT off = -1;
443e4b17023SJohn Marino   bool deref = false;
444e4b17023SJohn Marino 
445e4b17023SJohn Marino   FOR_EACH_VEC_ELT (vn_reference_op_s, vr1->operands, i, vro)
446e4b17023SJohn Marino     {
447e4b17023SJohn Marino       if (vro->opcode == MEM_REF)
448e4b17023SJohn Marino 	deref = true;
449e4b17023SJohn Marino       else if (vro->opcode != ADDR_EXPR)
450e4b17023SJohn Marino 	deref = false;
451e4b17023SJohn Marino       if (vro->off != -1)
452e4b17023SJohn Marino 	{
453e4b17023SJohn Marino 	  if (off == -1)
454e4b17023SJohn Marino 	    off = 0;
455e4b17023SJohn Marino 	  off += vro->off;
456e4b17023SJohn Marino 	}
457e4b17023SJohn Marino       else
458e4b17023SJohn Marino 	{
459e4b17023SJohn Marino 	  if (off != -1
460e4b17023SJohn Marino 	      && off != 0)
461e4b17023SJohn Marino 	    result = iterative_hash_hashval_t (off, result);
462e4b17023SJohn Marino 	  off = -1;
463e4b17023SJohn Marino 	  if (deref
464e4b17023SJohn Marino 	      && vro->opcode == ADDR_EXPR)
465e4b17023SJohn Marino 	    {
466e4b17023SJohn Marino 	      if (vro->op0)
467e4b17023SJohn Marino 		{
468e4b17023SJohn Marino 		  tree op = TREE_OPERAND (vro->op0, 0);
469e4b17023SJohn Marino 		  result = iterative_hash_hashval_t (TREE_CODE (op), result);
470e4b17023SJohn Marino 		  result = iterative_hash_expr (op, result);
471e4b17023SJohn Marino 		}
472e4b17023SJohn Marino 	    }
473e4b17023SJohn Marino 	  else
474e4b17023SJohn Marino 	    result = vn_reference_op_compute_hash (vro, result);
475e4b17023SJohn Marino 	}
476e4b17023SJohn Marino     }
477e4b17023SJohn Marino   if (vr1->vuse)
478e4b17023SJohn Marino     result += SSA_NAME_VERSION (vr1->vuse);
479e4b17023SJohn Marino 
480e4b17023SJohn Marino   return result;
481e4b17023SJohn Marino }
482e4b17023SJohn Marino 
483e4b17023SJohn Marino /* Return true if reference operations P1 and P2 are equivalent.  This
484e4b17023SJohn Marino    means they have the same set of operands and vuses.  */
485e4b17023SJohn Marino 
486e4b17023SJohn Marino int
vn_reference_eq(const void * p1,const void * p2)487e4b17023SJohn Marino vn_reference_eq (const void *p1, const void *p2)
488e4b17023SJohn Marino {
489e4b17023SJohn Marino   unsigned i, j;
490e4b17023SJohn Marino 
491e4b17023SJohn Marino   const_vn_reference_t const vr1 = (const_vn_reference_t) p1;
492e4b17023SJohn Marino   const_vn_reference_t const vr2 = (const_vn_reference_t) p2;
493e4b17023SJohn Marino   if (vr1->hashcode != vr2->hashcode)
494e4b17023SJohn Marino     return false;
495e4b17023SJohn Marino 
496e4b17023SJohn Marino   /* Early out if this is not a hash collision.  */
497e4b17023SJohn Marino   if (vr1->hashcode != vr2->hashcode)
498e4b17023SJohn Marino     return false;
499e4b17023SJohn Marino 
500e4b17023SJohn Marino   /* The VOP needs to be the same.  */
501e4b17023SJohn Marino   if (vr1->vuse != vr2->vuse)
502e4b17023SJohn Marino     return false;
503e4b17023SJohn Marino 
504e4b17023SJohn Marino   /* If the operands are the same we are done.  */
505e4b17023SJohn Marino   if (vr1->operands == vr2->operands)
506e4b17023SJohn Marino     return true;
507e4b17023SJohn Marino 
508e4b17023SJohn Marino   if (!expressions_equal_p (TYPE_SIZE (vr1->type), TYPE_SIZE (vr2->type)))
509e4b17023SJohn Marino     return false;
510e4b17023SJohn Marino 
511e4b17023SJohn Marino   if (INTEGRAL_TYPE_P (vr1->type)
512e4b17023SJohn Marino       && INTEGRAL_TYPE_P (vr2->type))
513e4b17023SJohn Marino     {
514e4b17023SJohn Marino       if (TYPE_PRECISION (vr1->type) != TYPE_PRECISION (vr2->type))
515e4b17023SJohn Marino 	return false;
516e4b17023SJohn Marino     }
517e4b17023SJohn Marino   else if (INTEGRAL_TYPE_P (vr1->type)
518e4b17023SJohn Marino 	   && (TYPE_PRECISION (vr1->type)
519e4b17023SJohn Marino 	       != TREE_INT_CST_LOW (TYPE_SIZE (vr1->type))))
520e4b17023SJohn Marino     return false;
521e4b17023SJohn Marino   else if (INTEGRAL_TYPE_P (vr2->type)
522e4b17023SJohn Marino 	   && (TYPE_PRECISION (vr2->type)
523e4b17023SJohn Marino 	       != TREE_INT_CST_LOW (TYPE_SIZE (vr2->type))))
524e4b17023SJohn Marino     return false;
525e4b17023SJohn Marino 
526e4b17023SJohn Marino   i = 0;
527e4b17023SJohn Marino   j = 0;
528e4b17023SJohn Marino   do
529e4b17023SJohn Marino     {
530e4b17023SJohn Marino       HOST_WIDE_INT off1 = 0, off2 = 0;
531e4b17023SJohn Marino       vn_reference_op_t vro1, vro2;
532e4b17023SJohn Marino       vn_reference_op_s tem1, tem2;
533e4b17023SJohn Marino       bool deref1 = false, deref2 = false;
534e4b17023SJohn Marino       for (; VEC_iterate (vn_reference_op_s, vr1->operands, i, vro1); i++)
535e4b17023SJohn Marino 	{
536e4b17023SJohn Marino 	  if (vro1->opcode == MEM_REF)
537e4b17023SJohn Marino 	    deref1 = true;
538e4b17023SJohn Marino 	  if (vro1->off == -1)
539e4b17023SJohn Marino 	    break;
540e4b17023SJohn Marino 	  off1 += vro1->off;
541e4b17023SJohn Marino 	}
542e4b17023SJohn Marino       for (; VEC_iterate (vn_reference_op_s, vr2->operands, j, vro2); j++)
543e4b17023SJohn Marino 	{
544e4b17023SJohn Marino 	  if (vro2->opcode == MEM_REF)
545e4b17023SJohn Marino 	    deref2 = true;
546e4b17023SJohn Marino 	  if (vro2->off == -1)
547e4b17023SJohn Marino 	    break;
548e4b17023SJohn Marino 	  off2 += vro2->off;
549e4b17023SJohn Marino 	}
550e4b17023SJohn Marino       if (off1 != off2)
551e4b17023SJohn Marino 	return false;
552e4b17023SJohn Marino       if (deref1 && vro1->opcode == ADDR_EXPR)
553e4b17023SJohn Marino 	{
554e4b17023SJohn Marino 	  memset (&tem1, 0, sizeof (tem1));
555e4b17023SJohn Marino 	  tem1.op0 = TREE_OPERAND (vro1->op0, 0);
556e4b17023SJohn Marino 	  tem1.type = TREE_TYPE (tem1.op0);
557e4b17023SJohn Marino 	  tem1.opcode = TREE_CODE (tem1.op0);
558e4b17023SJohn Marino 	  vro1 = &tem1;
559e4b17023SJohn Marino 	  deref1 = false;
560e4b17023SJohn Marino 	}
561e4b17023SJohn Marino       if (deref2 && vro2->opcode == ADDR_EXPR)
562e4b17023SJohn Marino 	{
563e4b17023SJohn Marino 	  memset (&tem2, 0, sizeof (tem2));
564e4b17023SJohn Marino 	  tem2.op0 = TREE_OPERAND (vro2->op0, 0);
565e4b17023SJohn Marino 	  tem2.type = TREE_TYPE (tem2.op0);
566e4b17023SJohn Marino 	  tem2.opcode = TREE_CODE (tem2.op0);
567e4b17023SJohn Marino 	  vro2 = &tem2;
568e4b17023SJohn Marino 	  deref2 = false;
569e4b17023SJohn Marino 	}
570e4b17023SJohn Marino       if (deref1 != deref2)
571e4b17023SJohn Marino 	return false;
572e4b17023SJohn Marino       if (!vn_reference_op_eq (vro1, vro2))
573e4b17023SJohn Marino 	return false;
574e4b17023SJohn Marino       ++j;
575e4b17023SJohn Marino       ++i;
576e4b17023SJohn Marino     }
577e4b17023SJohn Marino   while (VEC_length (vn_reference_op_s, vr1->operands) != i
578e4b17023SJohn Marino 	 || VEC_length (vn_reference_op_s, vr2->operands) != j);
579e4b17023SJohn Marino 
580e4b17023SJohn Marino   return true;
581e4b17023SJohn Marino }
582e4b17023SJohn Marino 
583e4b17023SJohn Marino /* Copy the operations present in load/store REF into RESULT, a vector of
584e4b17023SJohn Marino    vn_reference_op_s's.  */
585e4b17023SJohn Marino 
586e4b17023SJohn Marino void
copy_reference_ops_from_ref(tree ref,VEC (vn_reference_op_s,heap)** result)587e4b17023SJohn Marino copy_reference_ops_from_ref (tree ref, VEC(vn_reference_op_s, heap) **result)
588e4b17023SJohn Marino {
589e4b17023SJohn Marino   if (TREE_CODE (ref) == TARGET_MEM_REF)
590e4b17023SJohn Marino     {
591e4b17023SJohn Marino       vn_reference_op_s temp;
592e4b17023SJohn Marino 
593e4b17023SJohn Marino       memset (&temp, 0, sizeof (temp));
594e4b17023SJohn Marino       temp.type = TREE_TYPE (ref);
595e4b17023SJohn Marino       temp.opcode = TREE_CODE (ref);
596e4b17023SJohn Marino       temp.op0 = TMR_INDEX (ref);
597e4b17023SJohn Marino       temp.op1 = TMR_STEP (ref);
598e4b17023SJohn Marino       temp.op2 = TMR_OFFSET (ref);
599e4b17023SJohn Marino       temp.off = -1;
600e4b17023SJohn Marino       VEC_safe_push (vn_reference_op_s, heap, *result, &temp);
601e4b17023SJohn Marino 
602e4b17023SJohn Marino       memset (&temp, 0, sizeof (temp));
603e4b17023SJohn Marino       temp.type = NULL_TREE;
604e4b17023SJohn Marino       temp.opcode = ERROR_MARK;
605e4b17023SJohn Marino       temp.op0 = TMR_INDEX2 (ref);
606e4b17023SJohn Marino       temp.off = -1;
607e4b17023SJohn Marino       VEC_safe_push (vn_reference_op_s, heap, *result, &temp);
608e4b17023SJohn Marino 
609e4b17023SJohn Marino       memset (&temp, 0, sizeof (temp));
610e4b17023SJohn Marino       temp.type = NULL_TREE;
611e4b17023SJohn Marino       temp.opcode = TREE_CODE (TMR_BASE (ref));
612e4b17023SJohn Marino       temp.op0 = TMR_BASE (ref);
613e4b17023SJohn Marino       temp.off = -1;
614e4b17023SJohn Marino       VEC_safe_push (vn_reference_op_s, heap, *result, &temp);
615e4b17023SJohn Marino       return;
616e4b17023SJohn Marino     }
617e4b17023SJohn Marino 
618e4b17023SJohn Marino   /* For non-calls, store the information that makes up the address.  */
619e4b17023SJohn Marino 
620e4b17023SJohn Marino   while (ref)
621e4b17023SJohn Marino     {
622e4b17023SJohn Marino       vn_reference_op_s temp;
623e4b17023SJohn Marino 
624e4b17023SJohn Marino       memset (&temp, 0, sizeof (temp));
625e4b17023SJohn Marino       temp.type = TREE_TYPE (ref);
626e4b17023SJohn Marino       temp.opcode = TREE_CODE (ref);
627e4b17023SJohn Marino       temp.off = -1;
628e4b17023SJohn Marino 
629e4b17023SJohn Marino       switch (temp.opcode)
630e4b17023SJohn Marino 	{
631e4b17023SJohn Marino 	case WITH_SIZE_EXPR:
632e4b17023SJohn Marino 	  temp.op0 = TREE_OPERAND (ref, 1);
633e4b17023SJohn Marino 	  temp.off = 0;
634e4b17023SJohn Marino 	  break;
635e4b17023SJohn Marino 	case MEM_REF:
636e4b17023SJohn Marino 	  /* The base address gets its own vn_reference_op_s structure.  */
637e4b17023SJohn Marino 	  temp.op0 = TREE_OPERAND (ref, 1);
638e4b17023SJohn Marino 	  if (host_integerp (TREE_OPERAND (ref, 1), 0))
639e4b17023SJohn Marino 	    temp.off = TREE_INT_CST_LOW (TREE_OPERAND (ref, 1));
640e4b17023SJohn Marino 	  break;
641e4b17023SJohn Marino 	case BIT_FIELD_REF:
642e4b17023SJohn Marino 	  /* Record bits and position.  */
643e4b17023SJohn Marino 	  temp.op0 = TREE_OPERAND (ref, 1);
644e4b17023SJohn Marino 	  temp.op1 = TREE_OPERAND (ref, 2);
645e4b17023SJohn Marino 	  break;
646e4b17023SJohn Marino 	case COMPONENT_REF:
647e4b17023SJohn Marino 	  /* The field decl is enough to unambiguously specify the field,
648e4b17023SJohn Marino 	     a matching type is not necessary and a mismatching type
649e4b17023SJohn Marino 	     is always a spurious difference.  */
650e4b17023SJohn Marino 	  temp.type = NULL_TREE;
651e4b17023SJohn Marino 	  temp.op0 = TREE_OPERAND (ref, 1);
652e4b17023SJohn Marino 	  temp.op1 = TREE_OPERAND (ref, 2);
653e4b17023SJohn Marino 	  {
654e4b17023SJohn Marino 	    tree this_offset = component_ref_field_offset (ref);
655e4b17023SJohn Marino 	    if (this_offset
656e4b17023SJohn Marino 		&& TREE_CODE (this_offset) == INTEGER_CST)
657e4b17023SJohn Marino 	      {
658e4b17023SJohn Marino 		tree bit_offset = DECL_FIELD_BIT_OFFSET (TREE_OPERAND (ref, 1));
659e4b17023SJohn Marino 		if (TREE_INT_CST_LOW (bit_offset) % BITS_PER_UNIT == 0)
660e4b17023SJohn Marino 		  {
661e4b17023SJohn Marino 		    double_int off
662e4b17023SJohn Marino 		      = double_int_add (tree_to_double_int (this_offset),
663e4b17023SJohn Marino 					double_int_rshift
664e4b17023SJohn Marino 					  (tree_to_double_int (bit_offset),
665e4b17023SJohn Marino 					   BITS_PER_UNIT == 8
666e4b17023SJohn Marino 					   ? 3 : exact_log2 (BITS_PER_UNIT),
667e4b17023SJohn Marino 					   HOST_BITS_PER_DOUBLE_INT, true));
668e4b17023SJohn Marino 		    if (double_int_fits_in_shwi_p (off))
669e4b17023SJohn Marino 		      temp.off = off.low;
670e4b17023SJohn Marino 		  }
671e4b17023SJohn Marino 	      }
672e4b17023SJohn Marino 	  }
673e4b17023SJohn Marino 	  break;
674e4b17023SJohn Marino 	case ARRAY_RANGE_REF:
675e4b17023SJohn Marino 	case ARRAY_REF:
676e4b17023SJohn Marino 	  /* Record index as operand.  */
677e4b17023SJohn Marino 	  temp.op0 = TREE_OPERAND (ref, 1);
678e4b17023SJohn Marino 	  /* Always record lower bounds and element size.  */
679e4b17023SJohn Marino 	  temp.op1 = array_ref_low_bound (ref);
680e4b17023SJohn Marino 	  temp.op2 = array_ref_element_size (ref);
681e4b17023SJohn Marino 	  if (TREE_CODE (temp.op0) == INTEGER_CST
682e4b17023SJohn Marino 	      && TREE_CODE (temp.op1) == INTEGER_CST
683e4b17023SJohn Marino 	      && TREE_CODE (temp.op2) == INTEGER_CST)
684e4b17023SJohn Marino 	    {
685e4b17023SJohn Marino 	      double_int off = tree_to_double_int (temp.op0);
686e4b17023SJohn Marino 	      off = double_int_add (off,
687e4b17023SJohn Marino 				    double_int_neg
688e4b17023SJohn Marino 				      (tree_to_double_int (temp.op1)));
689e4b17023SJohn Marino 	      off = double_int_mul (off, tree_to_double_int (temp.op2));
690e4b17023SJohn Marino 	      if (double_int_fits_in_shwi_p (off))
691e4b17023SJohn Marino 		temp.off = off.low;
692e4b17023SJohn Marino 	    }
693e4b17023SJohn Marino 	  break;
694e4b17023SJohn Marino 	case VAR_DECL:
695e4b17023SJohn Marino 	  if (DECL_HARD_REGISTER (ref))
696e4b17023SJohn Marino 	    {
697e4b17023SJohn Marino 	      temp.op0 = ref;
698e4b17023SJohn Marino 	      break;
699e4b17023SJohn Marino 	    }
700e4b17023SJohn Marino 	  /* Fallthru.  */
701e4b17023SJohn Marino 	case PARM_DECL:
702e4b17023SJohn Marino 	case CONST_DECL:
703e4b17023SJohn Marino 	case RESULT_DECL:
704e4b17023SJohn Marino 	  /* Canonicalize decls to MEM[&decl] which is what we end up with
705e4b17023SJohn Marino 	     when valueizing MEM[ptr] with ptr = &decl.  */
706e4b17023SJohn Marino 	  temp.opcode = MEM_REF;
707e4b17023SJohn Marino 	  temp.op0 = build_int_cst (build_pointer_type (TREE_TYPE (ref)), 0);
708e4b17023SJohn Marino 	  temp.off = 0;
709e4b17023SJohn Marino 	  VEC_safe_push (vn_reference_op_s, heap, *result, &temp);
710e4b17023SJohn Marino 	  temp.opcode = ADDR_EXPR;
711e4b17023SJohn Marino 	  temp.op0 = build_fold_addr_expr (ref);
712e4b17023SJohn Marino 	  temp.type = TREE_TYPE (temp.op0);
713e4b17023SJohn Marino 	  temp.off = -1;
714e4b17023SJohn Marino 	  break;
715e4b17023SJohn Marino 	case STRING_CST:
716e4b17023SJohn Marino 	case INTEGER_CST:
717e4b17023SJohn Marino 	case COMPLEX_CST:
718e4b17023SJohn Marino 	case VECTOR_CST:
719e4b17023SJohn Marino 	case REAL_CST:
720e4b17023SJohn Marino 	case FIXED_CST:
721e4b17023SJohn Marino 	case CONSTRUCTOR:
722e4b17023SJohn Marino 	case SSA_NAME:
723e4b17023SJohn Marino 	  temp.op0 = ref;
724e4b17023SJohn Marino 	  break;
725e4b17023SJohn Marino 	case ADDR_EXPR:
726e4b17023SJohn Marino 	  if (is_gimple_min_invariant (ref))
727e4b17023SJohn Marino 	    {
728e4b17023SJohn Marino 	      temp.op0 = ref;
729e4b17023SJohn Marino 	      break;
730e4b17023SJohn Marino 	    }
731e4b17023SJohn Marino 	  /* Fallthrough.  */
732e4b17023SJohn Marino 	  /* These are only interesting for their operands, their
733e4b17023SJohn Marino 	     existence, and their type.  They will never be the last
734e4b17023SJohn Marino 	     ref in the chain of references (IE they require an
735e4b17023SJohn Marino 	     operand), so we don't have to put anything
736e4b17023SJohn Marino 	     for op* as it will be handled by the iteration  */
737e4b17023SJohn Marino 	case REALPART_EXPR:
738e4b17023SJohn Marino 	case VIEW_CONVERT_EXPR:
739e4b17023SJohn Marino 	  temp.off = 0;
740e4b17023SJohn Marino 	  break;
741e4b17023SJohn Marino 	case IMAGPART_EXPR:
742e4b17023SJohn Marino 	  /* This is only interesting for its constant offset.  */
743e4b17023SJohn Marino 	  temp.off = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (TREE_TYPE (ref)));
744e4b17023SJohn Marino 	  break;
745e4b17023SJohn Marino 	default:
746e4b17023SJohn Marino 	  gcc_unreachable ();
747e4b17023SJohn Marino 	}
748e4b17023SJohn Marino       VEC_safe_push (vn_reference_op_s, heap, *result, &temp);
749e4b17023SJohn Marino 
750e4b17023SJohn Marino       if (REFERENCE_CLASS_P (ref)
751e4b17023SJohn Marino 	  || TREE_CODE (ref) == WITH_SIZE_EXPR
752e4b17023SJohn Marino 	  || (TREE_CODE (ref) == ADDR_EXPR
753e4b17023SJohn Marino 	      && !is_gimple_min_invariant (ref)))
754e4b17023SJohn Marino 	ref = TREE_OPERAND (ref, 0);
755e4b17023SJohn Marino       else
756e4b17023SJohn Marino 	ref = NULL_TREE;
757e4b17023SJohn Marino     }
758e4b17023SJohn Marino }
759e4b17023SJohn Marino 
760e4b17023SJohn Marino /* Build a alias-oracle reference abstraction in *REF from the vn_reference
761e4b17023SJohn Marino    operands in *OPS, the reference alias set SET and the reference type TYPE.
762e4b17023SJohn Marino    Return true if something useful was produced.  */
763e4b17023SJohn Marino 
764e4b17023SJohn Marino bool
ao_ref_init_from_vn_reference(ao_ref * ref,alias_set_type set,tree type,VEC (vn_reference_op_s,heap)* ops)765e4b17023SJohn Marino ao_ref_init_from_vn_reference (ao_ref *ref,
766e4b17023SJohn Marino 			       alias_set_type set, tree type,
767e4b17023SJohn Marino 			       VEC (vn_reference_op_s, heap) *ops)
768e4b17023SJohn Marino {
769e4b17023SJohn Marino   vn_reference_op_t op;
770e4b17023SJohn Marino   unsigned i;
771e4b17023SJohn Marino   tree base = NULL_TREE;
772e4b17023SJohn Marino   tree *op0_p = &base;
773e4b17023SJohn Marino   HOST_WIDE_INT offset = 0;
774e4b17023SJohn Marino   HOST_WIDE_INT max_size;
775e4b17023SJohn Marino   HOST_WIDE_INT size = -1;
776e4b17023SJohn Marino   tree size_tree = NULL_TREE;
777e4b17023SJohn Marino   alias_set_type base_alias_set = -1;
778e4b17023SJohn Marino 
779e4b17023SJohn Marino   /* First get the final access size from just the outermost expression.  */
780e4b17023SJohn Marino   op = VEC_index (vn_reference_op_s, ops, 0);
781e4b17023SJohn Marino   if (op->opcode == COMPONENT_REF)
782e4b17023SJohn Marino     size_tree = DECL_SIZE (op->op0);
783e4b17023SJohn Marino   else if (op->opcode == BIT_FIELD_REF)
784e4b17023SJohn Marino     size_tree = op->op0;
785e4b17023SJohn Marino   else
786e4b17023SJohn Marino     {
787e4b17023SJohn Marino       enum machine_mode mode = TYPE_MODE (type);
788e4b17023SJohn Marino       if (mode == BLKmode)
789e4b17023SJohn Marino 	size_tree = TYPE_SIZE (type);
790e4b17023SJohn Marino       else
791e4b17023SJohn Marino         size = GET_MODE_BITSIZE (mode);
792e4b17023SJohn Marino     }
793e4b17023SJohn Marino   if (size_tree != NULL_TREE)
794e4b17023SJohn Marino     {
795e4b17023SJohn Marino       if (!host_integerp (size_tree, 1))
796e4b17023SJohn Marino 	size = -1;
797e4b17023SJohn Marino       else
798e4b17023SJohn Marino 	size = TREE_INT_CST_LOW (size_tree);
799e4b17023SJohn Marino     }
800e4b17023SJohn Marino 
801e4b17023SJohn Marino   /* Initially, maxsize is the same as the accessed element size.
802e4b17023SJohn Marino      In the following it will only grow (or become -1).  */
803e4b17023SJohn Marino   max_size = size;
804e4b17023SJohn Marino 
805e4b17023SJohn Marino   /* Compute cumulative bit-offset for nested component-refs and array-refs,
806e4b17023SJohn Marino      and find the ultimate containing object.  */
807e4b17023SJohn Marino   FOR_EACH_VEC_ELT (vn_reference_op_s, ops, i, op)
808e4b17023SJohn Marino     {
809e4b17023SJohn Marino       switch (op->opcode)
810e4b17023SJohn Marino 	{
811e4b17023SJohn Marino 	/* These may be in the reference ops, but we cannot do anything
812e4b17023SJohn Marino 	   sensible with them here.  */
813e4b17023SJohn Marino 	case ADDR_EXPR:
814e4b17023SJohn Marino 	  /* Apart from ADDR_EXPR arguments to MEM_REF.  */
815e4b17023SJohn Marino 	  if (base != NULL_TREE
816e4b17023SJohn Marino 	      && TREE_CODE (base) == MEM_REF
817e4b17023SJohn Marino 	      && op->op0
818e4b17023SJohn Marino 	      && DECL_P (TREE_OPERAND (op->op0, 0)))
819e4b17023SJohn Marino 	    {
820e4b17023SJohn Marino 	      vn_reference_op_t pop = VEC_index (vn_reference_op_s, ops, i-1);
821e4b17023SJohn Marino 	      base = TREE_OPERAND (op->op0, 0);
822e4b17023SJohn Marino 	      if (pop->off == -1)
823e4b17023SJohn Marino 		{
824e4b17023SJohn Marino 		  max_size = -1;
825e4b17023SJohn Marino 		  offset = 0;
826e4b17023SJohn Marino 		}
827e4b17023SJohn Marino 	      else
828e4b17023SJohn Marino 		offset += pop->off * BITS_PER_UNIT;
829e4b17023SJohn Marino 	      op0_p = NULL;
830e4b17023SJohn Marino 	      break;
831e4b17023SJohn Marino 	    }
832e4b17023SJohn Marino 	  /* Fallthru.  */
833e4b17023SJohn Marino 	case CALL_EXPR:
834e4b17023SJohn Marino 	  return false;
835e4b17023SJohn Marino 
836e4b17023SJohn Marino 	/* Record the base objects.  */
837e4b17023SJohn Marino 	case MEM_REF:
838e4b17023SJohn Marino 	  base_alias_set = get_deref_alias_set (op->op0);
839e4b17023SJohn Marino 	  *op0_p = build2 (MEM_REF, op->type,
840e4b17023SJohn Marino 			   NULL_TREE, op->op0);
841e4b17023SJohn Marino 	  op0_p = &TREE_OPERAND (*op0_p, 0);
842e4b17023SJohn Marino 	  break;
843e4b17023SJohn Marino 
844e4b17023SJohn Marino 	case VAR_DECL:
845e4b17023SJohn Marino 	case PARM_DECL:
846e4b17023SJohn Marino 	case RESULT_DECL:
847e4b17023SJohn Marino 	case SSA_NAME:
848e4b17023SJohn Marino 	  *op0_p = op->op0;
849e4b17023SJohn Marino 	  op0_p = NULL;
850e4b17023SJohn Marino 	  break;
851e4b17023SJohn Marino 
852e4b17023SJohn Marino 	/* And now the usual component-reference style ops.  */
853e4b17023SJohn Marino 	case BIT_FIELD_REF:
854e4b17023SJohn Marino 	  offset += tree_low_cst (op->op1, 0);
855e4b17023SJohn Marino 	  break;
856e4b17023SJohn Marino 
857e4b17023SJohn Marino 	case COMPONENT_REF:
858e4b17023SJohn Marino 	  {
859e4b17023SJohn Marino 	    tree field = op->op0;
860e4b17023SJohn Marino 	    /* We do not have a complete COMPONENT_REF tree here so we
861e4b17023SJohn Marino 	       cannot use component_ref_field_offset.  Do the interesting
862e4b17023SJohn Marino 	       parts manually.  */
863e4b17023SJohn Marino 
864e4b17023SJohn Marino 	    if (op->op1
865e4b17023SJohn Marino 		|| !host_integerp (DECL_FIELD_OFFSET (field), 1))
866e4b17023SJohn Marino 	      max_size = -1;
867e4b17023SJohn Marino 	    else
868e4b17023SJohn Marino 	      {
869e4b17023SJohn Marino 		offset += (TREE_INT_CST_LOW (DECL_FIELD_OFFSET (field))
870e4b17023SJohn Marino 			   * BITS_PER_UNIT);
871e4b17023SJohn Marino 		offset += TREE_INT_CST_LOW (DECL_FIELD_BIT_OFFSET (field));
872e4b17023SJohn Marino 	      }
873e4b17023SJohn Marino 	    break;
874e4b17023SJohn Marino 	  }
875e4b17023SJohn Marino 
876e4b17023SJohn Marino 	case ARRAY_RANGE_REF:
877e4b17023SJohn Marino 	case ARRAY_REF:
878e4b17023SJohn Marino 	  /* We recorded the lower bound and the element size.  */
879e4b17023SJohn Marino 	  if (!host_integerp (op->op0, 0)
880e4b17023SJohn Marino 	      || !host_integerp (op->op1, 0)
881e4b17023SJohn Marino 	      || !host_integerp (op->op2, 0))
882e4b17023SJohn Marino 	    max_size = -1;
883e4b17023SJohn Marino 	  else
884e4b17023SJohn Marino 	    {
885e4b17023SJohn Marino 	      HOST_WIDE_INT hindex = TREE_INT_CST_LOW (op->op0);
886e4b17023SJohn Marino 	      hindex -= TREE_INT_CST_LOW (op->op1);
887e4b17023SJohn Marino 	      hindex *= TREE_INT_CST_LOW (op->op2);
888e4b17023SJohn Marino 	      hindex *= BITS_PER_UNIT;
889e4b17023SJohn Marino 	      offset += hindex;
890e4b17023SJohn Marino 	    }
891e4b17023SJohn Marino 	  break;
892e4b17023SJohn Marino 
893e4b17023SJohn Marino 	case REALPART_EXPR:
894e4b17023SJohn Marino 	  break;
895e4b17023SJohn Marino 
896e4b17023SJohn Marino 	case IMAGPART_EXPR:
897e4b17023SJohn Marino 	  offset += size;
898e4b17023SJohn Marino 	  break;
899e4b17023SJohn Marino 
900e4b17023SJohn Marino 	case VIEW_CONVERT_EXPR:
901e4b17023SJohn Marino 	  break;
902e4b17023SJohn Marino 
903e4b17023SJohn Marino 	case STRING_CST:
904e4b17023SJohn Marino 	case INTEGER_CST:
905e4b17023SJohn Marino 	case COMPLEX_CST:
906e4b17023SJohn Marino 	case VECTOR_CST:
907e4b17023SJohn Marino 	case REAL_CST:
908e4b17023SJohn Marino 	case CONSTRUCTOR:
909e4b17023SJohn Marino 	case CONST_DECL:
910e4b17023SJohn Marino 	  return false;
911e4b17023SJohn Marino 
912e4b17023SJohn Marino 	default:
913e4b17023SJohn Marino 	  return false;
914e4b17023SJohn Marino 	}
915e4b17023SJohn Marino     }
916e4b17023SJohn Marino 
917e4b17023SJohn Marino   if (base == NULL_TREE)
918e4b17023SJohn Marino     return false;
919e4b17023SJohn Marino 
920e4b17023SJohn Marino   ref->ref = NULL_TREE;
921e4b17023SJohn Marino   ref->base = base;
922e4b17023SJohn Marino   ref->offset = offset;
923e4b17023SJohn Marino   ref->size = size;
924e4b17023SJohn Marino   ref->max_size = max_size;
925e4b17023SJohn Marino   ref->ref_alias_set = set;
926e4b17023SJohn Marino   if (base_alias_set != -1)
927e4b17023SJohn Marino     ref->base_alias_set = base_alias_set;
928e4b17023SJohn Marino   else
929e4b17023SJohn Marino     ref->base_alias_set = get_alias_set (base);
930e4b17023SJohn Marino   /* We discount volatiles from value-numbering elsewhere.  */
931e4b17023SJohn Marino   ref->volatile_p = false;
932e4b17023SJohn Marino 
933e4b17023SJohn Marino   return true;
934e4b17023SJohn Marino }
935e4b17023SJohn Marino 
936e4b17023SJohn Marino /* Copy the operations present in load/store/call REF into RESULT, a vector of
937e4b17023SJohn Marino    vn_reference_op_s's.  */
938e4b17023SJohn Marino 
939e4b17023SJohn Marino void
copy_reference_ops_from_call(gimple call,VEC (vn_reference_op_s,heap)** result)940e4b17023SJohn Marino copy_reference_ops_from_call (gimple call,
941e4b17023SJohn Marino 			      VEC(vn_reference_op_s, heap) **result)
942e4b17023SJohn Marino {
943e4b17023SJohn Marino   vn_reference_op_s temp;
944e4b17023SJohn Marino   unsigned i;
945e4b17023SJohn Marino 
946e4b17023SJohn Marino   /* Copy the type, opcode, function being called and static chain.  */
947e4b17023SJohn Marino   memset (&temp, 0, sizeof (temp));
948e4b17023SJohn Marino   temp.type = gimple_call_return_type (call);
949e4b17023SJohn Marino   temp.opcode = CALL_EXPR;
950e4b17023SJohn Marino   temp.op0 = gimple_call_fn (call);
951e4b17023SJohn Marino   temp.op1 = gimple_call_chain (call);
952e4b17023SJohn Marino   temp.off = -1;
953e4b17023SJohn Marino   VEC_safe_push (vn_reference_op_s, heap, *result, &temp);
954e4b17023SJohn Marino 
955e4b17023SJohn Marino   /* Copy the call arguments.  As they can be references as well,
956e4b17023SJohn Marino      just chain them together.  */
957e4b17023SJohn Marino   for (i = 0; i < gimple_call_num_args (call); ++i)
958e4b17023SJohn Marino     {
959e4b17023SJohn Marino       tree callarg = gimple_call_arg (call, i);
960e4b17023SJohn Marino       copy_reference_ops_from_ref (callarg, result);
961e4b17023SJohn Marino     }
962e4b17023SJohn Marino }
963e4b17023SJohn Marino 
964e4b17023SJohn Marino /* Create a vector of vn_reference_op_s structures from REF, a
965e4b17023SJohn Marino    REFERENCE_CLASS_P tree.  The vector is not shared. */
966e4b17023SJohn Marino 
VEC(vn_reference_op_s,heap)967e4b17023SJohn Marino static VEC(vn_reference_op_s, heap) *
968e4b17023SJohn Marino create_reference_ops_from_ref (tree ref)
969e4b17023SJohn Marino {
970e4b17023SJohn Marino   VEC (vn_reference_op_s, heap) *result = NULL;
971e4b17023SJohn Marino 
972e4b17023SJohn Marino   copy_reference_ops_from_ref (ref, &result);
973e4b17023SJohn Marino   return result;
974e4b17023SJohn Marino }
975e4b17023SJohn Marino 
976e4b17023SJohn Marino /* Create a vector of vn_reference_op_s structures from CALL, a
977e4b17023SJohn Marino    call statement.  The vector is not shared.  */
978e4b17023SJohn Marino 
VEC(vn_reference_op_s,heap)979e4b17023SJohn Marino static VEC(vn_reference_op_s, heap) *
980e4b17023SJohn Marino create_reference_ops_from_call (gimple call)
981e4b17023SJohn Marino {
982e4b17023SJohn Marino   VEC (vn_reference_op_s, heap) *result = NULL;
983e4b17023SJohn Marino 
984e4b17023SJohn Marino   copy_reference_ops_from_call (call, &result);
985e4b17023SJohn Marino   return result;
986e4b17023SJohn Marino }
987e4b17023SJohn Marino 
988e4b17023SJohn Marino /* Fold *& at position *I_P in a vn_reference_op_s vector *OPS.  Updates
989e4b17023SJohn Marino    *I_P to point to the last element of the replacement.  */
990e4b17023SJohn Marino void
vn_reference_fold_indirect(VEC (vn_reference_op_s,heap)** ops,unsigned int * i_p)991e4b17023SJohn Marino vn_reference_fold_indirect (VEC (vn_reference_op_s, heap) **ops,
992e4b17023SJohn Marino 			    unsigned int *i_p)
993e4b17023SJohn Marino {
994e4b17023SJohn Marino   unsigned int i = *i_p;
995e4b17023SJohn Marino   vn_reference_op_t op = VEC_index (vn_reference_op_s, *ops, i);
996e4b17023SJohn Marino   vn_reference_op_t mem_op = VEC_index (vn_reference_op_s, *ops, i - 1);
997e4b17023SJohn Marino   tree addr_base;
998e4b17023SJohn Marino   HOST_WIDE_INT addr_offset;
999e4b17023SJohn Marino 
1000e4b17023SJohn Marino   /* The only thing we have to do is from &OBJ.foo.bar add the offset
1001e4b17023SJohn Marino      from .foo.bar to the preceeding MEM_REF offset and replace the
1002e4b17023SJohn Marino      address with &OBJ.  */
1003e4b17023SJohn Marino   addr_base = get_addr_base_and_unit_offset (TREE_OPERAND (op->op0, 0),
1004e4b17023SJohn Marino 					     &addr_offset);
1005e4b17023SJohn Marino   gcc_checking_assert (addr_base && TREE_CODE (addr_base) != MEM_REF);
1006e4b17023SJohn Marino   if (addr_base != op->op0)
1007e4b17023SJohn Marino     {
1008e4b17023SJohn Marino       double_int off = tree_to_double_int (mem_op->op0);
1009e4b17023SJohn Marino       off = double_int_sext (off, TYPE_PRECISION (TREE_TYPE (mem_op->op0)));
1010e4b17023SJohn Marino       off = double_int_add (off, shwi_to_double_int (addr_offset));
1011e4b17023SJohn Marino       mem_op->op0 = double_int_to_tree (TREE_TYPE (mem_op->op0), off);
1012e4b17023SJohn Marino       op->op0 = build_fold_addr_expr (addr_base);
1013e4b17023SJohn Marino       if (host_integerp (mem_op->op0, 0))
1014e4b17023SJohn Marino 	mem_op->off = TREE_INT_CST_LOW (mem_op->op0);
1015e4b17023SJohn Marino       else
1016e4b17023SJohn Marino 	mem_op->off = -1;
1017e4b17023SJohn Marino     }
1018e4b17023SJohn Marino }
1019e4b17023SJohn Marino 
1020e4b17023SJohn Marino /* Fold *& at position *I_P in a vn_reference_op_s vector *OPS.  Updates
1021e4b17023SJohn Marino    *I_P to point to the last element of the replacement.  */
1022e4b17023SJohn Marino static void
vn_reference_maybe_forwprop_address(VEC (vn_reference_op_s,heap)** ops,unsigned int * i_p)1023e4b17023SJohn Marino vn_reference_maybe_forwprop_address (VEC (vn_reference_op_s, heap) **ops,
1024e4b17023SJohn Marino 				     unsigned int *i_p)
1025e4b17023SJohn Marino {
1026e4b17023SJohn Marino   unsigned int i = *i_p;
1027e4b17023SJohn Marino   vn_reference_op_t op = VEC_index (vn_reference_op_s, *ops, i);
1028e4b17023SJohn Marino   vn_reference_op_t mem_op = VEC_index (vn_reference_op_s, *ops, i - 1);
1029e4b17023SJohn Marino   gimple def_stmt;
1030e4b17023SJohn Marino   enum tree_code code;
1031e4b17023SJohn Marino   double_int off;
1032e4b17023SJohn Marino 
1033e4b17023SJohn Marino   def_stmt = SSA_NAME_DEF_STMT (op->op0);
1034e4b17023SJohn Marino   if (!is_gimple_assign (def_stmt))
1035e4b17023SJohn Marino     return;
1036e4b17023SJohn Marino 
1037e4b17023SJohn Marino   code = gimple_assign_rhs_code (def_stmt);
1038e4b17023SJohn Marino   if (code != ADDR_EXPR
1039e4b17023SJohn Marino       && code != POINTER_PLUS_EXPR)
1040e4b17023SJohn Marino     return;
1041e4b17023SJohn Marino 
1042e4b17023SJohn Marino   off = tree_to_double_int (mem_op->op0);
1043e4b17023SJohn Marino   off = double_int_sext (off, TYPE_PRECISION (TREE_TYPE (mem_op->op0)));
1044e4b17023SJohn Marino 
1045e4b17023SJohn Marino   /* The only thing we have to do is from &OBJ.foo.bar add the offset
1046e4b17023SJohn Marino      from .foo.bar to the preceeding MEM_REF offset and replace the
1047e4b17023SJohn Marino      address with &OBJ.  */
1048e4b17023SJohn Marino   if (code == ADDR_EXPR)
1049e4b17023SJohn Marino     {
1050e4b17023SJohn Marino       tree addr, addr_base;
1051e4b17023SJohn Marino       HOST_WIDE_INT addr_offset;
1052e4b17023SJohn Marino 
1053e4b17023SJohn Marino       addr = gimple_assign_rhs1 (def_stmt);
1054e4b17023SJohn Marino       addr_base = get_addr_base_and_unit_offset (TREE_OPERAND (addr, 0),
1055e4b17023SJohn Marino 						 &addr_offset);
1056e4b17023SJohn Marino       if (!addr_base
1057e4b17023SJohn Marino 	  || TREE_CODE (addr_base) != MEM_REF)
1058e4b17023SJohn Marino 	return;
1059e4b17023SJohn Marino 
1060e4b17023SJohn Marino       off = double_int_add (off, shwi_to_double_int (addr_offset));
1061e4b17023SJohn Marino       off = double_int_add (off, mem_ref_offset (addr_base));
1062e4b17023SJohn Marino       op->op0 = TREE_OPERAND (addr_base, 0);
1063e4b17023SJohn Marino     }
1064e4b17023SJohn Marino   else
1065e4b17023SJohn Marino     {
1066e4b17023SJohn Marino       tree ptr, ptroff;
1067e4b17023SJohn Marino       ptr = gimple_assign_rhs1 (def_stmt);
1068e4b17023SJohn Marino       ptroff = gimple_assign_rhs2 (def_stmt);
1069e4b17023SJohn Marino       if (TREE_CODE (ptr) != SSA_NAME
1070e4b17023SJohn Marino 	  || TREE_CODE (ptroff) != INTEGER_CST)
1071e4b17023SJohn Marino 	return;
1072e4b17023SJohn Marino 
1073e4b17023SJohn Marino       off = double_int_add (off, tree_to_double_int (ptroff));
1074e4b17023SJohn Marino       op->op0 = ptr;
1075e4b17023SJohn Marino     }
1076e4b17023SJohn Marino 
1077e4b17023SJohn Marino   mem_op->op0 = double_int_to_tree (TREE_TYPE (mem_op->op0), off);
1078e4b17023SJohn Marino   if (host_integerp (mem_op->op0, 0))
1079e4b17023SJohn Marino     mem_op->off = TREE_INT_CST_LOW (mem_op->op0);
1080e4b17023SJohn Marino   else
1081e4b17023SJohn Marino     mem_op->off = -1;
1082e4b17023SJohn Marino   if (TREE_CODE (op->op0) == SSA_NAME)
1083e4b17023SJohn Marino     op->op0 = SSA_VAL (op->op0);
1084e4b17023SJohn Marino   if (TREE_CODE (op->op0) != SSA_NAME)
1085e4b17023SJohn Marino     op->opcode = TREE_CODE (op->op0);
1086e4b17023SJohn Marino 
1087e4b17023SJohn Marino   /* And recurse.  */
1088e4b17023SJohn Marino   if (TREE_CODE (op->op0) == SSA_NAME)
1089e4b17023SJohn Marino     vn_reference_maybe_forwprop_address (ops, i_p);
1090e4b17023SJohn Marino   else if (TREE_CODE (op->op0) == ADDR_EXPR)
1091e4b17023SJohn Marino     vn_reference_fold_indirect (ops, i_p);
1092e4b17023SJohn Marino }
1093e4b17023SJohn Marino 
1094e4b17023SJohn Marino /* Optimize the reference REF to a constant if possible or return
1095e4b17023SJohn Marino    NULL_TREE if not.  */
1096e4b17023SJohn Marino 
1097e4b17023SJohn Marino tree
fully_constant_vn_reference_p(vn_reference_t ref)1098e4b17023SJohn Marino fully_constant_vn_reference_p (vn_reference_t ref)
1099e4b17023SJohn Marino {
1100e4b17023SJohn Marino   VEC (vn_reference_op_s, heap) *operands = ref->operands;
1101e4b17023SJohn Marino   vn_reference_op_t op;
1102e4b17023SJohn Marino 
1103e4b17023SJohn Marino   /* Try to simplify the translated expression if it is
1104e4b17023SJohn Marino      a call to a builtin function with at most two arguments.  */
1105e4b17023SJohn Marino   op = VEC_index (vn_reference_op_s, operands, 0);
1106e4b17023SJohn Marino   if (op->opcode == CALL_EXPR
1107e4b17023SJohn Marino       && TREE_CODE (op->op0) == ADDR_EXPR
1108e4b17023SJohn Marino       && TREE_CODE (TREE_OPERAND (op->op0, 0)) == FUNCTION_DECL
1109e4b17023SJohn Marino       && DECL_BUILT_IN (TREE_OPERAND (op->op0, 0))
1110e4b17023SJohn Marino       && VEC_length (vn_reference_op_s, operands) >= 2
1111e4b17023SJohn Marino       && VEC_length (vn_reference_op_s, operands) <= 3)
1112e4b17023SJohn Marino     {
1113e4b17023SJohn Marino       vn_reference_op_t arg0, arg1 = NULL;
1114e4b17023SJohn Marino       bool anyconst = false;
1115e4b17023SJohn Marino       arg0 = VEC_index (vn_reference_op_s, operands, 1);
1116e4b17023SJohn Marino       if (VEC_length (vn_reference_op_s, operands) > 2)
1117e4b17023SJohn Marino 	arg1 = VEC_index (vn_reference_op_s, operands, 2);
1118e4b17023SJohn Marino       if (TREE_CODE_CLASS (arg0->opcode) == tcc_constant
1119e4b17023SJohn Marino 	  || (arg0->opcode == ADDR_EXPR
1120e4b17023SJohn Marino 	      && is_gimple_min_invariant (arg0->op0)))
1121e4b17023SJohn Marino 	anyconst = true;
1122e4b17023SJohn Marino       if (arg1
1123e4b17023SJohn Marino 	  && (TREE_CODE_CLASS (arg1->opcode) == tcc_constant
1124e4b17023SJohn Marino 	      || (arg1->opcode == ADDR_EXPR
1125e4b17023SJohn Marino 		  && is_gimple_min_invariant (arg1->op0))))
1126e4b17023SJohn Marino 	anyconst = true;
1127e4b17023SJohn Marino       if (anyconst)
1128e4b17023SJohn Marino 	{
1129e4b17023SJohn Marino 	  tree folded = build_call_expr (TREE_OPERAND (op->op0, 0),
1130e4b17023SJohn Marino 					 arg1 ? 2 : 1,
1131e4b17023SJohn Marino 					 arg0->op0,
1132e4b17023SJohn Marino 					 arg1 ? arg1->op0 : NULL);
1133e4b17023SJohn Marino 	  if (folded
1134e4b17023SJohn Marino 	      && TREE_CODE (folded) == NOP_EXPR)
1135e4b17023SJohn Marino 	    folded = TREE_OPERAND (folded, 0);
1136e4b17023SJohn Marino 	  if (folded
1137e4b17023SJohn Marino 	      && is_gimple_min_invariant (folded))
1138e4b17023SJohn Marino 	    return folded;
1139e4b17023SJohn Marino 	}
1140e4b17023SJohn Marino     }
1141e4b17023SJohn Marino 
1142e4b17023SJohn Marino   /* Simplify reads from constant strings.  */
1143e4b17023SJohn Marino   else if (op->opcode == ARRAY_REF
1144e4b17023SJohn Marino 	   && TREE_CODE (op->op0) == INTEGER_CST
1145e4b17023SJohn Marino 	   && integer_zerop (op->op1)
1146e4b17023SJohn Marino 	   && VEC_length (vn_reference_op_s, operands) == 2)
1147e4b17023SJohn Marino     {
1148e4b17023SJohn Marino       vn_reference_op_t arg0;
1149e4b17023SJohn Marino       arg0 = VEC_index (vn_reference_op_s, operands, 1);
1150e4b17023SJohn Marino       if (arg0->opcode == STRING_CST
1151e4b17023SJohn Marino 	  && (TYPE_MODE (op->type)
1152e4b17023SJohn Marino 	      == TYPE_MODE (TREE_TYPE (TREE_TYPE (arg0->op0))))
1153e4b17023SJohn Marino 	  && GET_MODE_CLASS (TYPE_MODE (op->type)) == MODE_INT
1154e4b17023SJohn Marino 	  && GET_MODE_SIZE (TYPE_MODE (op->type)) == 1
1155e4b17023SJohn Marino 	  && compare_tree_int (op->op0, TREE_STRING_LENGTH (arg0->op0)) < 0)
1156e4b17023SJohn Marino 	return build_int_cst_type (op->type,
1157e4b17023SJohn Marino 				   (TREE_STRING_POINTER (arg0->op0)
1158e4b17023SJohn Marino 				    [TREE_INT_CST_LOW (op->op0)]));
1159e4b17023SJohn Marino     }
1160e4b17023SJohn Marino 
1161e4b17023SJohn Marino   return NULL_TREE;
1162e4b17023SJohn Marino }
1163e4b17023SJohn Marino 
1164e4b17023SJohn Marino /* Transform any SSA_NAME's in a vector of vn_reference_op_s
1165e4b17023SJohn Marino    structures into their value numbers.  This is done in-place, and
1166e4b17023SJohn Marino    the vector passed in is returned.  *VALUEIZED_ANYTHING will specify
1167e4b17023SJohn Marino    whether any operands were valueized.  */
1168e4b17023SJohn Marino 
VEC(vn_reference_op_s,heap)1169e4b17023SJohn Marino static VEC (vn_reference_op_s, heap) *
1170e4b17023SJohn Marino valueize_refs_1 (VEC (vn_reference_op_s, heap) *orig, bool *valueized_anything)
1171e4b17023SJohn Marino {
1172e4b17023SJohn Marino   vn_reference_op_t vro;
1173e4b17023SJohn Marino   unsigned int i;
1174e4b17023SJohn Marino 
1175e4b17023SJohn Marino   *valueized_anything = false;
1176e4b17023SJohn Marino 
1177e4b17023SJohn Marino   FOR_EACH_VEC_ELT (vn_reference_op_s, orig, i, vro)
1178e4b17023SJohn Marino     {
1179e4b17023SJohn Marino       if (vro->opcode == SSA_NAME
1180e4b17023SJohn Marino 	  || (vro->op0 && TREE_CODE (vro->op0) == SSA_NAME))
1181e4b17023SJohn Marino 	{
1182e4b17023SJohn Marino 	  tree tem = SSA_VAL (vro->op0);
1183e4b17023SJohn Marino 	  if (tem != vro->op0)
1184e4b17023SJohn Marino 	    {
1185e4b17023SJohn Marino 	      *valueized_anything = true;
1186e4b17023SJohn Marino 	      vro->op0 = tem;
1187e4b17023SJohn Marino 	    }
1188e4b17023SJohn Marino 	  /* If it transforms from an SSA_NAME to a constant, update
1189e4b17023SJohn Marino 	     the opcode.  */
1190e4b17023SJohn Marino 	  if (TREE_CODE (vro->op0) != SSA_NAME && vro->opcode == SSA_NAME)
1191e4b17023SJohn Marino 	    vro->opcode = TREE_CODE (vro->op0);
1192e4b17023SJohn Marino 	}
1193e4b17023SJohn Marino       if (vro->op1 && TREE_CODE (vro->op1) == SSA_NAME)
1194e4b17023SJohn Marino 	{
1195e4b17023SJohn Marino 	  tree tem = SSA_VAL (vro->op1);
1196e4b17023SJohn Marino 	  if (tem != vro->op1)
1197e4b17023SJohn Marino 	    {
1198e4b17023SJohn Marino 	      *valueized_anything = true;
1199e4b17023SJohn Marino 	      vro->op1 = tem;
1200e4b17023SJohn Marino 	    }
1201e4b17023SJohn Marino 	}
1202e4b17023SJohn Marino       if (vro->op2 && TREE_CODE (vro->op2) == SSA_NAME)
1203e4b17023SJohn Marino 	{
1204e4b17023SJohn Marino 	  tree tem = SSA_VAL (vro->op2);
1205e4b17023SJohn Marino 	  if (tem != vro->op2)
1206e4b17023SJohn Marino 	    {
1207e4b17023SJohn Marino 	      *valueized_anything = true;
1208e4b17023SJohn Marino 	      vro->op2 = tem;
1209e4b17023SJohn Marino 	    }
1210e4b17023SJohn Marino 	}
1211e4b17023SJohn Marino       /* If it transforms from an SSA_NAME to an address, fold with
1212e4b17023SJohn Marino 	 a preceding indirect reference.  */
1213e4b17023SJohn Marino       if (i > 0
1214e4b17023SJohn Marino 	  && vro->op0
1215e4b17023SJohn Marino 	  && TREE_CODE (vro->op0) == ADDR_EXPR
1216e4b17023SJohn Marino 	  && VEC_index (vn_reference_op_s,
1217e4b17023SJohn Marino 			orig, i - 1)->opcode == MEM_REF)
1218e4b17023SJohn Marino 	vn_reference_fold_indirect (&orig, &i);
1219e4b17023SJohn Marino       else if (i > 0
1220e4b17023SJohn Marino 	       && vro->opcode == SSA_NAME
1221e4b17023SJohn Marino 	       && VEC_index (vn_reference_op_s,
1222e4b17023SJohn Marino 			     orig, i - 1)->opcode == MEM_REF)
1223e4b17023SJohn Marino 	vn_reference_maybe_forwprop_address (&orig, &i);
1224e4b17023SJohn Marino       /* If it transforms a non-constant ARRAY_REF into a constant
1225e4b17023SJohn Marino 	 one, adjust the constant offset.  */
1226e4b17023SJohn Marino       else if (vro->opcode == ARRAY_REF
1227e4b17023SJohn Marino 	       && vro->off == -1
1228e4b17023SJohn Marino 	       && TREE_CODE (vro->op0) == INTEGER_CST
1229e4b17023SJohn Marino 	       && TREE_CODE (vro->op1) == INTEGER_CST
1230e4b17023SJohn Marino 	       && TREE_CODE (vro->op2) == INTEGER_CST)
1231e4b17023SJohn Marino 	{
1232e4b17023SJohn Marino 	  double_int off = tree_to_double_int (vro->op0);
1233e4b17023SJohn Marino 	  off = double_int_add (off,
1234e4b17023SJohn Marino 				double_int_neg
1235e4b17023SJohn Marino 				  (tree_to_double_int (vro->op1)));
1236e4b17023SJohn Marino 	  off = double_int_mul (off, tree_to_double_int (vro->op2));
1237e4b17023SJohn Marino 	  if (double_int_fits_in_shwi_p (off))
1238e4b17023SJohn Marino 	    vro->off = off.low;
1239e4b17023SJohn Marino 	}
1240e4b17023SJohn Marino     }
1241e4b17023SJohn Marino 
1242e4b17023SJohn Marino   return orig;
1243e4b17023SJohn Marino }
1244e4b17023SJohn Marino 
VEC(vn_reference_op_s,heap)1245e4b17023SJohn Marino static VEC (vn_reference_op_s, heap) *
1246e4b17023SJohn Marino valueize_refs (VEC (vn_reference_op_s, heap) *orig)
1247e4b17023SJohn Marino {
1248e4b17023SJohn Marino   bool tem;
1249e4b17023SJohn Marino   return valueize_refs_1 (orig, &tem);
1250e4b17023SJohn Marino }
1251e4b17023SJohn Marino 
VEC(vn_reference_op_s,heap)1252e4b17023SJohn Marino static VEC(vn_reference_op_s, heap) *shared_lookup_references;
1253e4b17023SJohn Marino 
1254e4b17023SJohn Marino /* Create a vector of vn_reference_op_s structures from REF, a
1255e4b17023SJohn Marino    REFERENCE_CLASS_P tree.  The vector is shared among all callers of
1256e4b17023SJohn Marino    this function.  *VALUEIZED_ANYTHING will specify whether any
1257e4b17023SJohn Marino    operands were valueized.  */
1258e4b17023SJohn Marino 
1259e4b17023SJohn Marino static VEC(vn_reference_op_s, heap) *
1260e4b17023SJohn Marino valueize_shared_reference_ops_from_ref (tree ref, bool *valueized_anything)
1261e4b17023SJohn Marino {
1262e4b17023SJohn Marino   if (!ref)
1263e4b17023SJohn Marino     return NULL;
1264e4b17023SJohn Marino   VEC_truncate (vn_reference_op_s, shared_lookup_references, 0);
1265e4b17023SJohn Marino   copy_reference_ops_from_ref (ref, &shared_lookup_references);
1266e4b17023SJohn Marino   shared_lookup_references = valueize_refs_1 (shared_lookup_references,
1267e4b17023SJohn Marino 					      valueized_anything);
1268e4b17023SJohn Marino   return shared_lookup_references;
1269e4b17023SJohn Marino }
1270e4b17023SJohn Marino 
1271e4b17023SJohn Marino /* Create a vector of vn_reference_op_s structures from CALL, a
1272e4b17023SJohn Marino    call statement.  The vector is shared among all callers of
1273e4b17023SJohn Marino    this function.  */
1274e4b17023SJohn Marino 
VEC(vn_reference_op_s,heap)1275e4b17023SJohn Marino static VEC(vn_reference_op_s, heap) *
1276e4b17023SJohn Marino valueize_shared_reference_ops_from_call (gimple call)
1277e4b17023SJohn Marino {
1278e4b17023SJohn Marino   if (!call)
1279e4b17023SJohn Marino     return NULL;
1280e4b17023SJohn Marino   VEC_truncate (vn_reference_op_s, shared_lookup_references, 0);
1281e4b17023SJohn Marino   copy_reference_ops_from_call (call, &shared_lookup_references);
1282e4b17023SJohn Marino   shared_lookup_references = valueize_refs (shared_lookup_references);
1283e4b17023SJohn Marino   return shared_lookup_references;
1284e4b17023SJohn Marino }
1285e4b17023SJohn Marino 
1286e4b17023SJohn Marino /* Lookup a SCCVN reference operation VR in the current hash table.
1287e4b17023SJohn Marino    Returns the resulting value number if it exists in the hash table,
1288e4b17023SJohn Marino    NULL_TREE otherwise.  VNRESULT will be filled in with the actual
1289e4b17023SJohn Marino    vn_reference_t stored in the hashtable if something is found.  */
1290e4b17023SJohn Marino 
1291e4b17023SJohn Marino static tree
vn_reference_lookup_1(vn_reference_t vr,vn_reference_t * vnresult)1292e4b17023SJohn Marino vn_reference_lookup_1 (vn_reference_t vr, vn_reference_t *vnresult)
1293e4b17023SJohn Marino {
1294e4b17023SJohn Marino   void **slot;
1295e4b17023SJohn Marino   hashval_t hash;
1296e4b17023SJohn Marino 
1297e4b17023SJohn Marino   hash = vr->hashcode;
1298e4b17023SJohn Marino   slot = htab_find_slot_with_hash (current_info->references, vr,
1299e4b17023SJohn Marino 				   hash, NO_INSERT);
1300e4b17023SJohn Marino   if (!slot && current_info == optimistic_info)
1301e4b17023SJohn Marino     slot = htab_find_slot_with_hash (valid_info->references, vr,
1302e4b17023SJohn Marino 				     hash, NO_INSERT);
1303e4b17023SJohn Marino   if (slot)
1304e4b17023SJohn Marino     {
1305e4b17023SJohn Marino       if (vnresult)
1306e4b17023SJohn Marino 	*vnresult = (vn_reference_t)*slot;
1307e4b17023SJohn Marino       return ((vn_reference_t)*slot)->result;
1308e4b17023SJohn Marino     }
1309e4b17023SJohn Marino 
1310e4b17023SJohn Marino   return NULL_TREE;
1311e4b17023SJohn Marino }
1312e4b17023SJohn Marino 
1313e4b17023SJohn Marino static tree *last_vuse_ptr;
1314e4b17023SJohn Marino static vn_lookup_kind vn_walk_kind;
1315e4b17023SJohn Marino static vn_lookup_kind default_vn_walk_kind;
1316e4b17023SJohn Marino 
1317e4b17023SJohn Marino /* Callback for walk_non_aliased_vuses.  Adjusts the vn_reference_t VR_
1318e4b17023SJohn Marino    with the current VUSE and performs the expression lookup.  */
1319e4b17023SJohn Marino 
1320e4b17023SJohn Marino static void *
vn_reference_lookup_2(ao_ref * op ATTRIBUTE_UNUSED,tree vuse,void * vr_)1321e4b17023SJohn Marino vn_reference_lookup_2 (ao_ref *op ATTRIBUTE_UNUSED, tree vuse, void *vr_)
1322e4b17023SJohn Marino {
1323e4b17023SJohn Marino   vn_reference_t vr = (vn_reference_t)vr_;
1324e4b17023SJohn Marino   void **slot;
1325e4b17023SJohn Marino   hashval_t hash;
1326e4b17023SJohn Marino 
1327e4b17023SJohn Marino   if (last_vuse_ptr)
1328e4b17023SJohn Marino     *last_vuse_ptr = vuse;
1329e4b17023SJohn Marino 
1330e4b17023SJohn Marino   /* Fixup vuse and hash.  */
1331e4b17023SJohn Marino   if (vr->vuse)
1332e4b17023SJohn Marino     vr->hashcode = vr->hashcode - SSA_NAME_VERSION (vr->vuse);
1333e4b17023SJohn Marino   vr->vuse = SSA_VAL (vuse);
1334e4b17023SJohn Marino   if (vr->vuse)
1335e4b17023SJohn Marino     vr->hashcode = vr->hashcode + SSA_NAME_VERSION (vr->vuse);
1336e4b17023SJohn Marino 
1337e4b17023SJohn Marino   hash = vr->hashcode;
1338e4b17023SJohn Marino   slot = htab_find_slot_with_hash (current_info->references, vr,
1339e4b17023SJohn Marino 				   hash, NO_INSERT);
1340e4b17023SJohn Marino   if (!slot && current_info == optimistic_info)
1341e4b17023SJohn Marino     slot = htab_find_slot_with_hash (valid_info->references, vr,
1342e4b17023SJohn Marino 				     hash, NO_INSERT);
1343e4b17023SJohn Marino   if (slot)
1344e4b17023SJohn Marino     return *slot;
1345e4b17023SJohn Marino 
1346e4b17023SJohn Marino   return NULL;
1347e4b17023SJohn Marino }
1348e4b17023SJohn Marino 
1349e4b17023SJohn Marino /* Lookup an existing or insert a new vn_reference entry into the
1350e4b17023SJohn Marino    value table for the VUSE, SET, TYPE, OPERANDS reference which
1351e4b17023SJohn Marino    has the value VALUE which is either a constant or an SSA name.  */
1352e4b17023SJohn Marino 
1353e4b17023SJohn Marino static vn_reference_t
vn_reference_lookup_or_insert_for_pieces(tree vuse,alias_set_type set,tree type,VEC (vn_reference_op_s,heap)* operands,tree value)1354e4b17023SJohn Marino vn_reference_lookup_or_insert_for_pieces (tree vuse,
1355e4b17023SJohn Marino 					  alias_set_type set,
1356e4b17023SJohn Marino 					  tree type,
1357e4b17023SJohn Marino 					  VEC (vn_reference_op_s,
1358e4b17023SJohn Marino 					       heap) *operands,
1359e4b17023SJohn Marino 					  tree value)
1360e4b17023SJohn Marino {
1361e4b17023SJohn Marino   struct vn_reference_s vr1;
1362e4b17023SJohn Marino   vn_reference_t result;
1363e4b17023SJohn Marino   unsigned value_id;
1364e4b17023SJohn Marino   vr1.vuse = vuse;
1365e4b17023SJohn Marino   vr1.operands = operands;
1366e4b17023SJohn Marino   vr1.type = type;
1367e4b17023SJohn Marino   vr1.set = set;
1368e4b17023SJohn Marino   vr1.hashcode = vn_reference_compute_hash (&vr1);
1369e4b17023SJohn Marino   if (vn_reference_lookup_1 (&vr1, &result))
1370e4b17023SJohn Marino     return result;
1371e4b17023SJohn Marino   if (TREE_CODE (value) == SSA_NAME)
1372e4b17023SJohn Marino     value_id = VN_INFO (value)->value_id;
1373e4b17023SJohn Marino   else
1374e4b17023SJohn Marino     value_id = get_or_alloc_constant_value_id (value);
1375e4b17023SJohn Marino   return vn_reference_insert_pieces (vuse, set, type,
1376e4b17023SJohn Marino 				     VEC_copy (vn_reference_op_s, heap,
1377e4b17023SJohn Marino 					       operands), value, value_id);
1378e4b17023SJohn Marino }
1379e4b17023SJohn Marino 
1380e4b17023SJohn Marino /* Callback for walk_non_aliased_vuses.  Tries to perform a lookup
1381e4b17023SJohn Marino    from the statement defining VUSE and if not successful tries to
1382e4b17023SJohn Marino    translate *REFP and VR_ through an aggregate copy at the defintion
1383e4b17023SJohn Marino    of VUSE.  */
1384e4b17023SJohn Marino 
1385e4b17023SJohn Marino static void *
vn_reference_lookup_3(ao_ref * ref,tree vuse,void * vr_)1386e4b17023SJohn Marino vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *vr_)
1387e4b17023SJohn Marino {
1388e4b17023SJohn Marino   vn_reference_t vr = (vn_reference_t)vr_;
1389e4b17023SJohn Marino   gimple def_stmt = SSA_NAME_DEF_STMT (vuse);
1390e4b17023SJohn Marino   tree base;
1391e4b17023SJohn Marino   HOST_WIDE_INT offset, maxsize;
1392e4b17023SJohn Marino   static VEC (vn_reference_op_s, heap) *lhs_ops = NULL;
1393e4b17023SJohn Marino   ao_ref lhs_ref;
1394e4b17023SJohn Marino   bool lhs_ref_ok = false;
1395e4b17023SJohn Marino 
1396e4b17023SJohn Marino   /* First try to disambiguate after value-replacing in the definitions LHS.  */
1397e4b17023SJohn Marino   if (is_gimple_assign (def_stmt))
1398e4b17023SJohn Marino     {
1399e4b17023SJohn Marino       VEC (vn_reference_op_s, heap) *tem;
1400e4b17023SJohn Marino       tree lhs = gimple_assign_lhs (def_stmt);
1401e4b17023SJohn Marino       bool valueized_anything = false;
1402e4b17023SJohn Marino       /* Avoid re-allocation overhead.  */
1403e4b17023SJohn Marino       VEC_truncate (vn_reference_op_s, lhs_ops, 0);
1404e4b17023SJohn Marino       copy_reference_ops_from_ref (lhs, &lhs_ops);
1405e4b17023SJohn Marino       tem = lhs_ops;
1406e4b17023SJohn Marino       lhs_ops = valueize_refs_1 (lhs_ops, &valueized_anything);
1407e4b17023SJohn Marino       gcc_assert (lhs_ops == tem);
1408e4b17023SJohn Marino       if (valueized_anything)
1409e4b17023SJohn Marino 	{
1410e4b17023SJohn Marino 	  lhs_ref_ok = ao_ref_init_from_vn_reference (&lhs_ref,
1411e4b17023SJohn Marino 						      get_alias_set (lhs),
1412e4b17023SJohn Marino 						      TREE_TYPE (lhs), lhs_ops);
1413e4b17023SJohn Marino 	  if (lhs_ref_ok
1414e4b17023SJohn Marino 	      && !refs_may_alias_p_1 (ref, &lhs_ref, true))
1415e4b17023SJohn Marino 	    return NULL;
1416e4b17023SJohn Marino 	}
1417e4b17023SJohn Marino       else
1418e4b17023SJohn Marino 	{
1419e4b17023SJohn Marino 	  ao_ref_init (&lhs_ref, lhs);
1420e4b17023SJohn Marino 	  lhs_ref_ok = true;
1421e4b17023SJohn Marino 	}
1422e4b17023SJohn Marino     }
1423e4b17023SJohn Marino 
1424e4b17023SJohn Marino   base = ao_ref_base (ref);
1425e4b17023SJohn Marino   offset = ref->offset;
1426e4b17023SJohn Marino   maxsize = ref->max_size;
1427e4b17023SJohn Marino 
1428e4b17023SJohn Marino   /* If we cannot constrain the size of the reference we cannot
1429e4b17023SJohn Marino      test if anything kills it.  */
1430e4b17023SJohn Marino   if (maxsize == -1)
1431e4b17023SJohn Marino     return (void *)-1;
1432e4b17023SJohn Marino 
1433e4b17023SJohn Marino   /* We can't deduce anything useful from clobbers.  */
1434e4b17023SJohn Marino   if (gimple_clobber_p (def_stmt))
1435e4b17023SJohn Marino     return (void *)-1;
1436e4b17023SJohn Marino 
1437e4b17023SJohn Marino   /* def_stmt may-defs *ref.  See if we can derive a value for *ref
1438e4b17023SJohn Marino      from that definition.
1439e4b17023SJohn Marino      1) Memset.  */
1440e4b17023SJohn Marino   if (is_gimple_reg_type (vr->type)
1441e4b17023SJohn Marino       && gimple_call_builtin_p (def_stmt, BUILT_IN_MEMSET)
1442e4b17023SJohn Marino       && integer_zerop (gimple_call_arg (def_stmt, 1))
1443e4b17023SJohn Marino       && host_integerp (gimple_call_arg (def_stmt, 2), 1)
1444e4b17023SJohn Marino       && TREE_CODE (gimple_call_arg (def_stmt, 0)) == ADDR_EXPR)
1445e4b17023SJohn Marino     {
1446e4b17023SJohn Marino       tree ref2 = TREE_OPERAND (gimple_call_arg (def_stmt, 0), 0);
1447e4b17023SJohn Marino       tree base2;
1448e4b17023SJohn Marino       HOST_WIDE_INT offset2, size2, maxsize2;
1449e4b17023SJohn Marino       base2 = get_ref_base_and_extent (ref2, &offset2, &size2, &maxsize2);
1450e4b17023SJohn Marino       size2 = TREE_INT_CST_LOW (gimple_call_arg (def_stmt, 2)) * 8;
1451e4b17023SJohn Marino       if ((unsigned HOST_WIDE_INT)size2 / 8
1452e4b17023SJohn Marino 	  == TREE_INT_CST_LOW (gimple_call_arg (def_stmt, 2))
1453e4b17023SJohn Marino 	  && maxsize2 != -1
1454e4b17023SJohn Marino 	  && operand_equal_p (base, base2, 0)
1455e4b17023SJohn Marino 	  && offset2 <= offset
1456e4b17023SJohn Marino 	  && offset2 + size2 >= offset + maxsize)
1457e4b17023SJohn Marino 	{
1458e4b17023SJohn Marino 	  tree val = build_zero_cst (vr->type);
1459e4b17023SJohn Marino 	  return vn_reference_lookup_or_insert_for_pieces
1460e4b17023SJohn Marino 	           (vuse, vr->set, vr->type, vr->operands, val);
1461e4b17023SJohn Marino 	}
1462e4b17023SJohn Marino     }
1463e4b17023SJohn Marino 
1464e4b17023SJohn Marino   /* 2) Assignment from an empty CONSTRUCTOR.  */
1465e4b17023SJohn Marino   else if (is_gimple_reg_type (vr->type)
1466e4b17023SJohn Marino 	   && gimple_assign_single_p (def_stmt)
1467e4b17023SJohn Marino 	   && gimple_assign_rhs_code (def_stmt) == CONSTRUCTOR
1468e4b17023SJohn Marino 	   && CONSTRUCTOR_NELTS (gimple_assign_rhs1 (def_stmt)) == 0)
1469e4b17023SJohn Marino     {
1470e4b17023SJohn Marino       tree base2;
1471e4b17023SJohn Marino       HOST_WIDE_INT offset2, size2, maxsize2;
1472e4b17023SJohn Marino       base2 = get_ref_base_and_extent (gimple_assign_lhs (def_stmt),
1473e4b17023SJohn Marino 				       &offset2, &size2, &maxsize2);
1474e4b17023SJohn Marino       if (maxsize2 != -1
1475e4b17023SJohn Marino 	  && operand_equal_p (base, base2, 0)
1476e4b17023SJohn Marino 	  && offset2 <= offset
1477e4b17023SJohn Marino 	  && offset2 + size2 >= offset + maxsize)
1478e4b17023SJohn Marino 	{
1479e4b17023SJohn Marino 	  tree val = build_zero_cst (vr->type);
1480e4b17023SJohn Marino 	  return vn_reference_lookup_or_insert_for_pieces
1481e4b17023SJohn Marino 	           (vuse, vr->set, vr->type, vr->operands, val);
1482e4b17023SJohn Marino 	}
1483e4b17023SJohn Marino     }
1484e4b17023SJohn Marino 
1485e4b17023SJohn Marino   /* 3) Assignment from a constant.  We can use folds native encode/interpret
1486e4b17023SJohn Marino      routines to extract the assigned bits.  */
14875ce9237cSJohn Marino   else if (vn_walk_kind == VN_WALKREWRITE
14885ce9237cSJohn Marino 	   && CHAR_BIT == 8 && BITS_PER_UNIT == 8
1489e4b17023SJohn Marino 	   && ref->size == maxsize
1490e4b17023SJohn Marino 	   && maxsize % BITS_PER_UNIT == 0
1491e4b17023SJohn Marino 	   && offset % BITS_PER_UNIT == 0
1492e4b17023SJohn Marino 	   && is_gimple_reg_type (vr->type)
1493e4b17023SJohn Marino 	   && gimple_assign_single_p (def_stmt)
1494e4b17023SJohn Marino 	   && is_gimple_min_invariant (gimple_assign_rhs1 (def_stmt)))
1495e4b17023SJohn Marino     {
1496e4b17023SJohn Marino       tree base2;
1497e4b17023SJohn Marino       HOST_WIDE_INT offset2, size2, maxsize2;
1498e4b17023SJohn Marino       base2 = get_ref_base_and_extent (gimple_assign_lhs (def_stmt),
1499e4b17023SJohn Marino 				       &offset2, &size2, &maxsize2);
1500e4b17023SJohn Marino       if (maxsize2 != -1
1501e4b17023SJohn Marino 	  && maxsize2 == size2
1502e4b17023SJohn Marino 	  && size2 % BITS_PER_UNIT == 0
1503e4b17023SJohn Marino 	  && offset2 % BITS_PER_UNIT == 0
1504e4b17023SJohn Marino 	  && operand_equal_p (base, base2, 0)
1505e4b17023SJohn Marino 	  && offset2 <= offset
1506e4b17023SJohn Marino 	  && offset2 + size2 >= offset + maxsize)
1507e4b17023SJohn Marino 	{
1508e4b17023SJohn Marino 	  /* We support up to 512-bit values (for V8DFmode).  */
1509e4b17023SJohn Marino 	  unsigned char buffer[64];
1510e4b17023SJohn Marino 	  int len;
1511e4b17023SJohn Marino 
1512e4b17023SJohn Marino 	  len = native_encode_expr (gimple_assign_rhs1 (def_stmt),
1513e4b17023SJohn Marino 				    buffer, sizeof (buffer));
1514e4b17023SJohn Marino 	  if (len > 0)
1515e4b17023SJohn Marino 	    {
1516e4b17023SJohn Marino 	      tree val = native_interpret_expr (vr->type,
1517e4b17023SJohn Marino 						buffer
1518e4b17023SJohn Marino 						+ ((offset - offset2)
1519e4b17023SJohn Marino 						   / BITS_PER_UNIT),
1520e4b17023SJohn Marino 						ref->size / BITS_PER_UNIT);
1521e4b17023SJohn Marino 	      if (val)
1522e4b17023SJohn Marino 		return vn_reference_lookup_or_insert_for_pieces
1523e4b17023SJohn Marino 		         (vuse, vr->set, vr->type, vr->operands, val);
1524e4b17023SJohn Marino 	    }
1525e4b17023SJohn Marino 	}
1526e4b17023SJohn Marino     }
1527e4b17023SJohn Marino 
1528e4b17023SJohn Marino   /* 4) Assignment from an SSA name which definition we may be able
1529e4b17023SJohn Marino      to access pieces from.  */
1530e4b17023SJohn Marino   else if (ref->size == maxsize
1531e4b17023SJohn Marino 	   && is_gimple_reg_type (vr->type)
1532e4b17023SJohn Marino 	   && gimple_assign_single_p (def_stmt)
1533e4b17023SJohn Marino 	   && TREE_CODE (gimple_assign_rhs1 (def_stmt)) == SSA_NAME)
1534e4b17023SJohn Marino     {
1535e4b17023SJohn Marino       tree rhs1 = gimple_assign_rhs1 (def_stmt);
1536e4b17023SJohn Marino       gimple def_stmt2 = SSA_NAME_DEF_STMT (rhs1);
1537e4b17023SJohn Marino       if (is_gimple_assign (def_stmt2)
1538e4b17023SJohn Marino 	  && (gimple_assign_rhs_code (def_stmt2) == COMPLEX_EXPR
1539e4b17023SJohn Marino 	      || gimple_assign_rhs_code (def_stmt2) == CONSTRUCTOR)
1540e4b17023SJohn Marino 	  && types_compatible_p (vr->type, TREE_TYPE (TREE_TYPE (rhs1))))
1541e4b17023SJohn Marino 	{
1542e4b17023SJohn Marino 	  tree base2;
1543e4b17023SJohn Marino 	  HOST_WIDE_INT offset2, size2, maxsize2, off;
1544e4b17023SJohn Marino 	  base2 = get_ref_base_and_extent (gimple_assign_lhs (def_stmt),
1545e4b17023SJohn Marino 					   &offset2, &size2, &maxsize2);
1546e4b17023SJohn Marino 	  off = offset - offset2;
1547e4b17023SJohn Marino 	  if (maxsize2 != -1
1548e4b17023SJohn Marino 	      && maxsize2 == size2
1549e4b17023SJohn Marino 	      && operand_equal_p (base, base2, 0)
1550e4b17023SJohn Marino 	      && offset2 <= offset
1551e4b17023SJohn Marino 	      && offset2 + size2 >= offset + maxsize)
1552e4b17023SJohn Marino 	    {
1553e4b17023SJohn Marino 	      tree val = NULL_TREE;
1554e4b17023SJohn Marino 	      HOST_WIDE_INT elsz
1555e4b17023SJohn Marino 		= TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (TREE_TYPE (rhs1))));
1556e4b17023SJohn Marino 	      if (gimple_assign_rhs_code (def_stmt2) == COMPLEX_EXPR)
1557e4b17023SJohn Marino 		{
1558e4b17023SJohn Marino 		  if (off == 0)
1559e4b17023SJohn Marino 		    val = gimple_assign_rhs1 (def_stmt2);
1560e4b17023SJohn Marino 		  else if (off == elsz)
1561e4b17023SJohn Marino 		    val = gimple_assign_rhs2 (def_stmt2);
1562e4b17023SJohn Marino 		}
1563e4b17023SJohn Marino 	      else if (gimple_assign_rhs_code (def_stmt2) == CONSTRUCTOR
1564e4b17023SJohn Marino 		       && off % elsz == 0)
1565e4b17023SJohn Marino 		{
1566e4b17023SJohn Marino 		  tree ctor = gimple_assign_rhs1 (def_stmt2);
1567e4b17023SJohn Marino 		  unsigned i = off / elsz;
1568e4b17023SJohn Marino 		  if (i < CONSTRUCTOR_NELTS (ctor))
1569e4b17023SJohn Marino 		    {
1570e4b17023SJohn Marino 		      constructor_elt *elt = CONSTRUCTOR_ELT (ctor, i);
1571e4b17023SJohn Marino 		      if (compare_tree_int (elt->index, i) == 0)
1572e4b17023SJohn Marino 			val = elt->value;
1573e4b17023SJohn Marino 		    }
1574e4b17023SJohn Marino 		}
1575e4b17023SJohn Marino 	      if (val)
1576e4b17023SJohn Marino 		return vn_reference_lookup_or_insert_for_pieces
1577e4b17023SJohn Marino 		         (vuse, vr->set, vr->type, vr->operands, val);
1578e4b17023SJohn Marino 	    }
1579e4b17023SJohn Marino 	}
1580e4b17023SJohn Marino     }
1581e4b17023SJohn Marino 
1582e4b17023SJohn Marino   /* 5) For aggregate copies translate the reference through them if
1583e4b17023SJohn Marino      the copy kills ref.  */
1584e4b17023SJohn Marino   else if (vn_walk_kind == VN_WALKREWRITE
1585e4b17023SJohn Marino 	   && gimple_assign_single_p (def_stmt)
1586e4b17023SJohn Marino 	   && (DECL_P (gimple_assign_rhs1 (def_stmt))
1587e4b17023SJohn Marino 	       || TREE_CODE (gimple_assign_rhs1 (def_stmt)) == MEM_REF
1588e4b17023SJohn Marino 	       || handled_component_p (gimple_assign_rhs1 (def_stmt))))
1589e4b17023SJohn Marino     {
1590e4b17023SJohn Marino       tree base2;
1591e4b17023SJohn Marino       HOST_WIDE_INT offset2, size2, maxsize2;
1592e4b17023SJohn Marino       int i, j;
1593e4b17023SJohn Marino       VEC (vn_reference_op_s, heap) *rhs = NULL;
1594e4b17023SJohn Marino       vn_reference_op_t vro;
1595e4b17023SJohn Marino       ao_ref r;
1596e4b17023SJohn Marino 
1597e4b17023SJohn Marino       if (!lhs_ref_ok)
1598e4b17023SJohn Marino 	return (void *)-1;
1599e4b17023SJohn Marino 
1600e4b17023SJohn Marino       /* See if the assignment kills REF.  */
1601e4b17023SJohn Marino       base2 = ao_ref_base (&lhs_ref);
1602e4b17023SJohn Marino       offset2 = lhs_ref.offset;
1603e4b17023SJohn Marino       size2 = lhs_ref.size;
1604e4b17023SJohn Marino       maxsize2 = lhs_ref.max_size;
1605e4b17023SJohn Marino       if (maxsize2 == -1
1606e4b17023SJohn Marino 	  || (base != base2 && !operand_equal_p (base, base2, 0))
1607e4b17023SJohn Marino 	  || offset2 > offset
1608e4b17023SJohn Marino 	  || offset2 + size2 < offset + maxsize)
1609e4b17023SJohn Marino 	return (void *)-1;
1610e4b17023SJohn Marino 
1611e4b17023SJohn Marino       /* Find the common base of ref and the lhs.  lhs_ops already
1612e4b17023SJohn Marino          contains valueized operands for the lhs.  */
1613e4b17023SJohn Marino       i = VEC_length (vn_reference_op_s, vr->operands) - 1;
1614e4b17023SJohn Marino       j = VEC_length (vn_reference_op_s, lhs_ops) - 1;
1615e4b17023SJohn Marino       while (j >= 0 && i >= 0
1616e4b17023SJohn Marino 	     && vn_reference_op_eq (VEC_index (vn_reference_op_s,
1617e4b17023SJohn Marino 					       vr->operands, i),
1618e4b17023SJohn Marino 				    VEC_index (vn_reference_op_s, lhs_ops, j)))
1619e4b17023SJohn Marino 	{
1620e4b17023SJohn Marino 	  i--;
1621e4b17023SJohn Marino 	  j--;
1622e4b17023SJohn Marino 	}
1623e4b17023SJohn Marino 
1624e4b17023SJohn Marino       /* ???  The innermost op should always be a MEM_REF and we already
1625e4b17023SJohn Marino          checked that the assignment to the lhs kills vr.  Thus for
1626e4b17023SJohn Marino 	 aggregate copies using char[] types the vn_reference_op_eq
1627e4b17023SJohn Marino 	 may fail when comparing types for compatibility.  But we really
1628e4b17023SJohn Marino 	 don't care here - further lookups with the rewritten operands
1629e4b17023SJohn Marino 	 will simply fail if we messed up types too badly.  */
1630e4b17023SJohn Marino       if (j == 0 && i >= 0
1631e4b17023SJohn Marino 	  && VEC_index (vn_reference_op_s, lhs_ops, 0)->opcode == MEM_REF
1632e4b17023SJohn Marino 	  && VEC_index (vn_reference_op_s, lhs_ops, 0)->off != -1
1633e4b17023SJohn Marino 	  && (VEC_index (vn_reference_op_s, lhs_ops, 0)->off
1634e4b17023SJohn Marino 	      == VEC_index (vn_reference_op_s, vr->operands, i)->off))
1635e4b17023SJohn Marino 	i--, j--;
1636e4b17023SJohn Marino 
1637e4b17023SJohn Marino       /* i now points to the first additional op.
1638e4b17023SJohn Marino 	 ???  LHS may not be completely contained in VR, one or more
1639e4b17023SJohn Marino 	 VIEW_CONVERT_EXPRs could be in its way.  We could at least
1640e4b17023SJohn Marino 	 try handling outermost VIEW_CONVERT_EXPRs.  */
1641e4b17023SJohn Marino       if (j != -1)
1642e4b17023SJohn Marino 	return (void *)-1;
1643e4b17023SJohn Marino 
1644e4b17023SJohn Marino       /* Now re-write REF to be based on the rhs of the assignment.  */
1645e4b17023SJohn Marino       copy_reference_ops_from_ref (gimple_assign_rhs1 (def_stmt), &rhs);
1646e4b17023SJohn Marino       /* We need to pre-pend vr->operands[0..i] to rhs.  */
1647e4b17023SJohn Marino       if (i + 1 + VEC_length (vn_reference_op_s, rhs)
1648e4b17023SJohn Marino 	  > VEC_length (vn_reference_op_s, vr->operands))
1649e4b17023SJohn Marino 	{
1650e4b17023SJohn Marino 	  VEC (vn_reference_op_s, heap) *old = vr->operands;
1651e4b17023SJohn Marino 	  VEC_safe_grow (vn_reference_op_s, heap, vr->operands,
1652e4b17023SJohn Marino 			 i + 1 + VEC_length (vn_reference_op_s, rhs));
1653e4b17023SJohn Marino 	  if (old == shared_lookup_references
1654e4b17023SJohn Marino 	      && vr->operands != old)
1655e4b17023SJohn Marino 	    shared_lookup_references = NULL;
1656e4b17023SJohn Marino 	}
1657e4b17023SJohn Marino       else
1658e4b17023SJohn Marino 	VEC_truncate (vn_reference_op_s, vr->operands,
1659e4b17023SJohn Marino 		      i + 1 + VEC_length (vn_reference_op_s, rhs));
1660e4b17023SJohn Marino       FOR_EACH_VEC_ELT (vn_reference_op_s, rhs, j, vro)
1661e4b17023SJohn Marino 	VEC_replace (vn_reference_op_s, vr->operands, i + 1 + j, vro);
1662e4b17023SJohn Marino       VEC_free (vn_reference_op_s, heap, rhs);
1663e4b17023SJohn Marino       vr->operands = valueize_refs (vr->operands);
1664e4b17023SJohn Marino       vr->hashcode = vn_reference_compute_hash (vr);
1665e4b17023SJohn Marino 
1666e4b17023SJohn Marino       /* Adjust *ref from the new operands.  */
1667e4b17023SJohn Marino       if (!ao_ref_init_from_vn_reference (&r, vr->set, vr->type, vr->operands))
1668e4b17023SJohn Marino 	return (void *)-1;
1669e4b17023SJohn Marino       /* This can happen with bitfields.  */
1670e4b17023SJohn Marino       if (ref->size != r.size)
1671e4b17023SJohn Marino 	return (void *)-1;
1672e4b17023SJohn Marino       *ref = r;
1673e4b17023SJohn Marino 
1674e4b17023SJohn Marino       /* Do not update last seen VUSE after translating.  */
1675e4b17023SJohn Marino       last_vuse_ptr = NULL;
1676e4b17023SJohn Marino 
1677e4b17023SJohn Marino       /* Keep looking for the adjusted *REF / VR pair.  */
1678e4b17023SJohn Marino       return NULL;
1679e4b17023SJohn Marino     }
1680e4b17023SJohn Marino 
1681e4b17023SJohn Marino   /* 6) For memcpy copies translate the reference through them if
1682e4b17023SJohn Marino      the copy kills ref.  */
1683e4b17023SJohn Marino   else if (vn_walk_kind == VN_WALKREWRITE
1684e4b17023SJohn Marino 	   && is_gimple_reg_type (vr->type)
1685e4b17023SJohn Marino 	   /* ???  Handle BCOPY as well.  */
1686e4b17023SJohn Marino 	   && (gimple_call_builtin_p (def_stmt, BUILT_IN_MEMCPY)
1687e4b17023SJohn Marino 	       || gimple_call_builtin_p (def_stmt, BUILT_IN_MEMPCPY)
1688e4b17023SJohn Marino 	       || gimple_call_builtin_p (def_stmt, BUILT_IN_MEMMOVE))
1689e4b17023SJohn Marino 	   && (TREE_CODE (gimple_call_arg (def_stmt, 0)) == ADDR_EXPR
1690e4b17023SJohn Marino 	       || TREE_CODE (gimple_call_arg (def_stmt, 0)) == SSA_NAME)
1691e4b17023SJohn Marino 	   && (TREE_CODE (gimple_call_arg (def_stmt, 1)) == ADDR_EXPR
1692e4b17023SJohn Marino 	       || TREE_CODE (gimple_call_arg (def_stmt, 1)) == SSA_NAME)
1693e4b17023SJohn Marino 	   && host_integerp (gimple_call_arg (def_stmt, 2), 1))
1694e4b17023SJohn Marino     {
1695e4b17023SJohn Marino       tree lhs, rhs;
1696e4b17023SJohn Marino       ao_ref r;
1697e4b17023SJohn Marino       HOST_WIDE_INT rhs_offset, copy_size, lhs_offset;
1698e4b17023SJohn Marino       vn_reference_op_s op;
1699e4b17023SJohn Marino       HOST_WIDE_INT at;
1700e4b17023SJohn Marino 
1701e4b17023SJohn Marino 
1702e4b17023SJohn Marino       /* Only handle non-variable, addressable refs.  */
1703e4b17023SJohn Marino       if (ref->size != maxsize
1704e4b17023SJohn Marino 	  || offset % BITS_PER_UNIT != 0
1705e4b17023SJohn Marino 	  || ref->size % BITS_PER_UNIT != 0)
1706e4b17023SJohn Marino 	return (void *)-1;
1707e4b17023SJohn Marino 
1708e4b17023SJohn Marino       /* Extract a pointer base and an offset for the destination.  */
1709e4b17023SJohn Marino       lhs = gimple_call_arg (def_stmt, 0);
1710e4b17023SJohn Marino       lhs_offset = 0;
1711e4b17023SJohn Marino       if (TREE_CODE (lhs) == SSA_NAME)
1712e4b17023SJohn Marino 	lhs = SSA_VAL (lhs);
1713e4b17023SJohn Marino       if (TREE_CODE (lhs) == ADDR_EXPR)
1714e4b17023SJohn Marino 	{
1715e4b17023SJohn Marino 	  tree tem = get_addr_base_and_unit_offset (TREE_OPERAND (lhs, 0),
1716e4b17023SJohn Marino 						    &lhs_offset);
1717e4b17023SJohn Marino 	  if (!tem)
1718e4b17023SJohn Marino 	    return (void *)-1;
1719e4b17023SJohn Marino 	  if (TREE_CODE (tem) == MEM_REF
1720e4b17023SJohn Marino 	      && host_integerp (TREE_OPERAND (tem, 1), 1))
1721e4b17023SJohn Marino 	    {
1722e4b17023SJohn Marino 	      lhs = TREE_OPERAND (tem, 0);
1723e4b17023SJohn Marino 	      lhs_offset += TREE_INT_CST_LOW (TREE_OPERAND (tem, 1));
1724e4b17023SJohn Marino 	    }
1725e4b17023SJohn Marino 	  else if (DECL_P (tem))
1726e4b17023SJohn Marino 	    lhs = build_fold_addr_expr (tem);
1727e4b17023SJohn Marino 	  else
1728e4b17023SJohn Marino 	    return (void *)-1;
1729e4b17023SJohn Marino 	}
1730e4b17023SJohn Marino       if (TREE_CODE (lhs) != SSA_NAME
1731e4b17023SJohn Marino 	  && TREE_CODE (lhs) != ADDR_EXPR)
1732e4b17023SJohn Marino 	return (void *)-1;
1733e4b17023SJohn Marino 
1734e4b17023SJohn Marino       /* Extract a pointer base and an offset for the source.  */
1735e4b17023SJohn Marino       rhs = gimple_call_arg (def_stmt, 1);
1736e4b17023SJohn Marino       rhs_offset = 0;
1737e4b17023SJohn Marino       if (TREE_CODE (rhs) == SSA_NAME)
1738e4b17023SJohn Marino 	rhs = SSA_VAL (rhs);
1739e4b17023SJohn Marino       if (TREE_CODE (rhs) == ADDR_EXPR)
1740e4b17023SJohn Marino 	{
1741e4b17023SJohn Marino 	  tree tem = get_addr_base_and_unit_offset (TREE_OPERAND (rhs, 0),
1742e4b17023SJohn Marino 						    &rhs_offset);
1743e4b17023SJohn Marino 	  if (!tem)
1744e4b17023SJohn Marino 	    return (void *)-1;
1745e4b17023SJohn Marino 	  if (TREE_CODE (tem) == MEM_REF
1746e4b17023SJohn Marino 	      && host_integerp (TREE_OPERAND (tem, 1), 1))
1747e4b17023SJohn Marino 	    {
1748e4b17023SJohn Marino 	      rhs = TREE_OPERAND (tem, 0);
1749e4b17023SJohn Marino 	      rhs_offset += TREE_INT_CST_LOW (TREE_OPERAND (tem, 1));
1750e4b17023SJohn Marino 	    }
1751e4b17023SJohn Marino 	  else if (DECL_P (tem))
1752e4b17023SJohn Marino 	    rhs = build_fold_addr_expr (tem);
1753e4b17023SJohn Marino 	  else
1754e4b17023SJohn Marino 	    return (void *)-1;
1755e4b17023SJohn Marino 	}
1756e4b17023SJohn Marino       if (TREE_CODE (rhs) != SSA_NAME
1757e4b17023SJohn Marino 	  && TREE_CODE (rhs) != ADDR_EXPR)
1758e4b17023SJohn Marino 	return (void *)-1;
1759e4b17023SJohn Marino 
1760e4b17023SJohn Marino       copy_size = TREE_INT_CST_LOW (gimple_call_arg (def_stmt, 2));
1761e4b17023SJohn Marino 
1762e4b17023SJohn Marino       /* The bases of the destination and the references have to agree.  */
1763e4b17023SJohn Marino       if ((TREE_CODE (base) != MEM_REF
1764e4b17023SJohn Marino 	   && !DECL_P (base))
1765e4b17023SJohn Marino 	  || (TREE_CODE (base) == MEM_REF
1766e4b17023SJohn Marino 	      && (TREE_OPERAND (base, 0) != lhs
1767e4b17023SJohn Marino 		  || !host_integerp (TREE_OPERAND (base, 1), 1)))
1768e4b17023SJohn Marino 	  || (DECL_P (base)
1769e4b17023SJohn Marino 	      && (TREE_CODE (lhs) != ADDR_EXPR
1770e4b17023SJohn Marino 		  || TREE_OPERAND (lhs, 0) != base)))
1771e4b17023SJohn Marino 	return (void *)-1;
1772e4b17023SJohn Marino 
1773e4b17023SJohn Marino       /* And the access has to be contained within the memcpy destination.  */
1774e4b17023SJohn Marino       at = offset / BITS_PER_UNIT;
1775e4b17023SJohn Marino       if (TREE_CODE (base) == MEM_REF)
1776e4b17023SJohn Marino 	at += TREE_INT_CST_LOW (TREE_OPERAND (base, 1));
1777e4b17023SJohn Marino       if (lhs_offset > at
1778e4b17023SJohn Marino 	  || lhs_offset + copy_size < at + maxsize / BITS_PER_UNIT)
1779e4b17023SJohn Marino 	return (void *)-1;
1780e4b17023SJohn Marino 
1781e4b17023SJohn Marino       /* Make room for 2 operands in the new reference.  */
1782e4b17023SJohn Marino       if (VEC_length (vn_reference_op_s, vr->operands) < 2)
1783e4b17023SJohn Marino 	{
1784e4b17023SJohn Marino 	  VEC (vn_reference_op_s, heap) *old = vr->operands;
1785e4b17023SJohn Marino 	  VEC_safe_grow (vn_reference_op_s, heap, vr->operands, 2);
1786e4b17023SJohn Marino 	  if (old == shared_lookup_references
1787e4b17023SJohn Marino 	      && vr->operands != old)
1788e4b17023SJohn Marino 	    shared_lookup_references = NULL;
1789e4b17023SJohn Marino 	}
1790e4b17023SJohn Marino       else
1791e4b17023SJohn Marino 	VEC_truncate (vn_reference_op_s, vr->operands, 2);
1792e4b17023SJohn Marino 
1793e4b17023SJohn Marino       /* The looked-through reference is a simple MEM_REF.  */
1794e4b17023SJohn Marino       memset (&op, 0, sizeof (op));
1795e4b17023SJohn Marino       op.type = vr->type;
1796e4b17023SJohn Marino       op.opcode = MEM_REF;
1797e4b17023SJohn Marino       op.op0 = build_int_cst (ptr_type_node, at - rhs_offset);
1798e4b17023SJohn Marino       op.off = at - lhs_offset + rhs_offset;
1799e4b17023SJohn Marino       VEC_replace (vn_reference_op_s, vr->operands, 0, &op);
1800e4b17023SJohn Marino       op.type = TREE_TYPE (rhs);
1801e4b17023SJohn Marino       op.opcode = TREE_CODE (rhs);
1802e4b17023SJohn Marino       op.op0 = rhs;
1803e4b17023SJohn Marino       op.off = -1;
1804e4b17023SJohn Marino       VEC_replace (vn_reference_op_s, vr->operands, 1, &op);
1805e4b17023SJohn Marino       vr->hashcode = vn_reference_compute_hash (vr);
1806e4b17023SJohn Marino 
1807e4b17023SJohn Marino       /* Adjust *ref from the new operands.  */
1808e4b17023SJohn Marino       if (!ao_ref_init_from_vn_reference (&r, vr->set, vr->type, vr->operands))
1809e4b17023SJohn Marino 	return (void *)-1;
1810e4b17023SJohn Marino       /* This can happen with bitfields.  */
1811e4b17023SJohn Marino       if (ref->size != r.size)
1812e4b17023SJohn Marino 	return (void *)-1;
1813e4b17023SJohn Marino       *ref = r;
1814e4b17023SJohn Marino 
1815e4b17023SJohn Marino       /* Do not update last seen VUSE after translating.  */
1816e4b17023SJohn Marino       last_vuse_ptr = NULL;
1817e4b17023SJohn Marino 
1818e4b17023SJohn Marino       /* Keep looking for the adjusted *REF / VR pair.  */
1819e4b17023SJohn Marino       return NULL;
1820e4b17023SJohn Marino     }
1821e4b17023SJohn Marino 
1822e4b17023SJohn Marino   /* Bail out and stop walking.  */
1823e4b17023SJohn Marino   return (void *)-1;
1824e4b17023SJohn Marino }
1825e4b17023SJohn Marino 
1826e4b17023SJohn Marino /* Lookup a reference operation by it's parts, in the current hash table.
1827e4b17023SJohn Marino    Returns the resulting value number if it exists in the hash table,
1828e4b17023SJohn Marino    NULL_TREE otherwise.  VNRESULT will be filled in with the actual
1829e4b17023SJohn Marino    vn_reference_t stored in the hashtable if something is found.  */
1830e4b17023SJohn Marino 
1831e4b17023SJohn Marino tree
vn_reference_lookup_pieces(tree vuse,alias_set_type set,tree type,VEC (vn_reference_op_s,heap)* operands,vn_reference_t * vnresult,vn_lookup_kind kind)1832e4b17023SJohn Marino vn_reference_lookup_pieces (tree vuse, alias_set_type set, tree type,
1833e4b17023SJohn Marino 			    VEC (vn_reference_op_s, heap) *operands,
1834e4b17023SJohn Marino 			    vn_reference_t *vnresult, vn_lookup_kind kind)
1835e4b17023SJohn Marino {
1836e4b17023SJohn Marino   struct vn_reference_s vr1;
1837e4b17023SJohn Marino   vn_reference_t tmp;
1838e4b17023SJohn Marino   tree cst;
1839e4b17023SJohn Marino 
1840e4b17023SJohn Marino   if (!vnresult)
1841e4b17023SJohn Marino     vnresult = &tmp;
1842e4b17023SJohn Marino   *vnresult = NULL;
1843e4b17023SJohn Marino 
1844e4b17023SJohn Marino   vr1.vuse = vuse ? SSA_VAL (vuse) : NULL_TREE;
1845e4b17023SJohn Marino   VEC_truncate (vn_reference_op_s, shared_lookup_references, 0);
1846e4b17023SJohn Marino   VEC_safe_grow (vn_reference_op_s, heap, shared_lookup_references,
1847e4b17023SJohn Marino 		 VEC_length (vn_reference_op_s, operands));
1848e4b17023SJohn Marino   memcpy (VEC_address (vn_reference_op_s, shared_lookup_references),
1849e4b17023SJohn Marino 	  VEC_address (vn_reference_op_s, operands),
1850e4b17023SJohn Marino 	  sizeof (vn_reference_op_s)
1851e4b17023SJohn Marino 	  * VEC_length (vn_reference_op_s, operands));
1852e4b17023SJohn Marino   vr1.operands = operands = shared_lookup_references
1853e4b17023SJohn Marino     = valueize_refs (shared_lookup_references);
1854e4b17023SJohn Marino   vr1.type = type;
1855e4b17023SJohn Marino   vr1.set = set;
1856e4b17023SJohn Marino   vr1.hashcode = vn_reference_compute_hash (&vr1);
1857e4b17023SJohn Marino   if ((cst = fully_constant_vn_reference_p (&vr1)))
1858e4b17023SJohn Marino     return cst;
1859e4b17023SJohn Marino 
1860e4b17023SJohn Marino   vn_reference_lookup_1 (&vr1, vnresult);
1861e4b17023SJohn Marino   if (!*vnresult
1862e4b17023SJohn Marino       && kind != VN_NOWALK
1863e4b17023SJohn Marino       && vr1.vuse)
1864e4b17023SJohn Marino     {
1865e4b17023SJohn Marino       ao_ref r;
1866e4b17023SJohn Marino       vn_walk_kind = kind;
1867e4b17023SJohn Marino       if (ao_ref_init_from_vn_reference (&r, set, type, vr1.operands))
1868e4b17023SJohn Marino 	*vnresult =
1869e4b17023SJohn Marino 	  (vn_reference_t)walk_non_aliased_vuses (&r, vr1.vuse,
1870e4b17023SJohn Marino 						  vn_reference_lookup_2,
1871e4b17023SJohn Marino 						  vn_reference_lookup_3, &vr1);
1872e4b17023SJohn Marino       if (vr1.operands != operands)
1873e4b17023SJohn Marino 	VEC_free (vn_reference_op_s, heap, vr1.operands);
1874e4b17023SJohn Marino     }
1875e4b17023SJohn Marino 
1876e4b17023SJohn Marino   if (*vnresult)
1877e4b17023SJohn Marino      return (*vnresult)->result;
1878e4b17023SJohn Marino 
1879e4b17023SJohn Marino   return NULL_TREE;
1880e4b17023SJohn Marino }
1881e4b17023SJohn Marino 
1882e4b17023SJohn Marino /* Lookup OP in the current hash table, and return the resulting value
1883e4b17023SJohn Marino    number if it exists in the hash table.  Return NULL_TREE if it does
1884e4b17023SJohn Marino    not exist in the hash table or if the result field of the structure
1885e4b17023SJohn Marino    was NULL..  VNRESULT will be filled in with the vn_reference_t
1886e4b17023SJohn Marino    stored in the hashtable if one exists.  */
1887e4b17023SJohn Marino 
1888e4b17023SJohn Marino tree
vn_reference_lookup(tree op,tree vuse,vn_lookup_kind kind,vn_reference_t * vnresult)1889e4b17023SJohn Marino vn_reference_lookup (tree op, tree vuse, vn_lookup_kind kind,
1890e4b17023SJohn Marino 		     vn_reference_t *vnresult)
1891e4b17023SJohn Marino {
1892e4b17023SJohn Marino   VEC (vn_reference_op_s, heap) *operands;
1893e4b17023SJohn Marino   struct vn_reference_s vr1;
1894e4b17023SJohn Marino   tree cst;
1895e4b17023SJohn Marino   bool valuezied_anything;
1896e4b17023SJohn Marino 
1897e4b17023SJohn Marino   if (vnresult)
1898e4b17023SJohn Marino     *vnresult = NULL;
1899e4b17023SJohn Marino 
1900e4b17023SJohn Marino   vr1.vuse = vuse ? SSA_VAL (vuse) : NULL_TREE;
1901e4b17023SJohn Marino   vr1.operands = operands
1902e4b17023SJohn Marino     = valueize_shared_reference_ops_from_ref (op, &valuezied_anything);
1903e4b17023SJohn Marino   vr1.type = TREE_TYPE (op);
1904e4b17023SJohn Marino   vr1.set = get_alias_set (op);
1905e4b17023SJohn Marino   vr1.hashcode = vn_reference_compute_hash (&vr1);
1906e4b17023SJohn Marino   if ((cst = fully_constant_vn_reference_p (&vr1)))
1907e4b17023SJohn Marino     return cst;
1908e4b17023SJohn Marino 
1909e4b17023SJohn Marino   if (kind != VN_NOWALK
1910e4b17023SJohn Marino       && vr1.vuse)
1911e4b17023SJohn Marino     {
1912e4b17023SJohn Marino       vn_reference_t wvnresult;
1913e4b17023SJohn Marino       ao_ref r;
1914e4b17023SJohn Marino       /* Make sure to use a valueized reference if we valueized anything.
1915e4b17023SJohn Marino          Otherwise preserve the full reference for advanced TBAA.  */
1916e4b17023SJohn Marino       if (!valuezied_anything
1917e4b17023SJohn Marino 	  || !ao_ref_init_from_vn_reference (&r, vr1.set, vr1.type,
1918e4b17023SJohn Marino 					     vr1.operands))
1919e4b17023SJohn Marino 	ao_ref_init (&r, op);
1920e4b17023SJohn Marino       vn_walk_kind = kind;
1921e4b17023SJohn Marino       wvnresult =
1922e4b17023SJohn Marino 	(vn_reference_t)walk_non_aliased_vuses (&r, vr1.vuse,
1923e4b17023SJohn Marino 						vn_reference_lookup_2,
1924e4b17023SJohn Marino 						vn_reference_lookup_3, &vr1);
1925e4b17023SJohn Marino       if (vr1.operands != operands)
1926e4b17023SJohn Marino 	VEC_free (vn_reference_op_s, heap, vr1.operands);
1927e4b17023SJohn Marino       if (wvnresult)
1928e4b17023SJohn Marino 	{
1929e4b17023SJohn Marino 	  if (vnresult)
1930e4b17023SJohn Marino 	    *vnresult = wvnresult;
1931e4b17023SJohn Marino 	  return wvnresult->result;
1932e4b17023SJohn Marino 	}
1933e4b17023SJohn Marino 
1934e4b17023SJohn Marino       return NULL_TREE;
1935e4b17023SJohn Marino     }
1936e4b17023SJohn Marino 
1937e4b17023SJohn Marino   return vn_reference_lookup_1 (&vr1, vnresult);
1938e4b17023SJohn Marino }
1939e4b17023SJohn Marino 
1940e4b17023SJohn Marino 
1941e4b17023SJohn Marino /* Insert OP into the current hash table with a value number of
1942e4b17023SJohn Marino    RESULT, and return the resulting reference structure we created.  */
1943e4b17023SJohn Marino 
1944e4b17023SJohn Marino vn_reference_t
vn_reference_insert(tree op,tree result,tree vuse)1945e4b17023SJohn Marino vn_reference_insert (tree op, tree result, tree vuse)
1946e4b17023SJohn Marino {
1947e4b17023SJohn Marino   void **slot;
1948e4b17023SJohn Marino   vn_reference_t vr1;
1949e4b17023SJohn Marino 
1950e4b17023SJohn Marino   vr1 = (vn_reference_t) pool_alloc (current_info->references_pool);
1951e4b17023SJohn Marino   if (TREE_CODE (result) == SSA_NAME)
1952e4b17023SJohn Marino     vr1->value_id = VN_INFO (result)->value_id;
1953e4b17023SJohn Marino   else
1954e4b17023SJohn Marino     vr1->value_id = get_or_alloc_constant_value_id (result);
1955e4b17023SJohn Marino   vr1->vuse = vuse ? SSA_VAL (vuse) : NULL_TREE;
1956e4b17023SJohn Marino   vr1->operands = valueize_refs (create_reference_ops_from_ref (op));
1957e4b17023SJohn Marino   vr1->type = TREE_TYPE (op);
1958e4b17023SJohn Marino   vr1->set = get_alias_set (op);
1959e4b17023SJohn Marino   vr1->hashcode = vn_reference_compute_hash (vr1);
1960e4b17023SJohn Marino   vr1->result = TREE_CODE (result) == SSA_NAME ? SSA_VAL (result) : result;
1961e4b17023SJohn Marino 
1962e4b17023SJohn Marino   slot = htab_find_slot_with_hash (current_info->references, vr1, vr1->hashcode,
1963e4b17023SJohn Marino 				   INSERT);
1964e4b17023SJohn Marino 
1965e4b17023SJohn Marino   /* Because we lookup stores using vuses, and value number failures
1966e4b17023SJohn Marino      using the vdefs (see visit_reference_op_store for how and why),
1967e4b17023SJohn Marino      it's possible that on failure we may try to insert an already
1968e4b17023SJohn Marino      inserted store.  This is not wrong, there is no ssa name for a
1969e4b17023SJohn Marino      store that we could use as a differentiator anyway.  Thus, unlike
1970e4b17023SJohn Marino      the other lookup functions, you cannot gcc_assert (!*slot)
1971e4b17023SJohn Marino      here.  */
1972e4b17023SJohn Marino 
1973e4b17023SJohn Marino   /* But free the old slot in case of a collision.  */
1974e4b17023SJohn Marino   if (*slot)
1975e4b17023SJohn Marino     free_reference (*slot);
1976e4b17023SJohn Marino 
1977e4b17023SJohn Marino   *slot = vr1;
1978e4b17023SJohn Marino   return vr1;
1979e4b17023SJohn Marino }
1980e4b17023SJohn Marino 
1981e4b17023SJohn Marino /* Insert a reference by it's pieces into the current hash table with
1982e4b17023SJohn Marino    a value number of RESULT.  Return the resulting reference
1983e4b17023SJohn Marino    structure we created.  */
1984e4b17023SJohn Marino 
1985e4b17023SJohn Marino vn_reference_t
vn_reference_insert_pieces(tree vuse,alias_set_type set,tree type,VEC (vn_reference_op_s,heap)* operands,tree result,unsigned int value_id)1986e4b17023SJohn Marino vn_reference_insert_pieces (tree vuse, alias_set_type set, tree type,
1987e4b17023SJohn Marino 			    VEC (vn_reference_op_s, heap) *operands,
1988e4b17023SJohn Marino 			    tree result, unsigned int value_id)
1989e4b17023SJohn Marino 
1990e4b17023SJohn Marino {
1991e4b17023SJohn Marino   void **slot;
1992e4b17023SJohn Marino   vn_reference_t vr1;
1993e4b17023SJohn Marino 
1994e4b17023SJohn Marino   vr1 = (vn_reference_t) pool_alloc (current_info->references_pool);
1995e4b17023SJohn Marino   vr1->value_id = value_id;
1996e4b17023SJohn Marino   vr1->vuse = vuse ? SSA_VAL (vuse) : NULL_TREE;
1997e4b17023SJohn Marino   vr1->operands = valueize_refs (operands);
1998e4b17023SJohn Marino   vr1->type = type;
1999e4b17023SJohn Marino   vr1->set = set;
2000e4b17023SJohn Marino   vr1->hashcode = vn_reference_compute_hash (vr1);
2001e4b17023SJohn Marino   if (result && TREE_CODE (result) == SSA_NAME)
2002e4b17023SJohn Marino     result = SSA_VAL (result);
2003e4b17023SJohn Marino   vr1->result = result;
2004e4b17023SJohn Marino 
2005e4b17023SJohn Marino   slot = htab_find_slot_with_hash (current_info->references, vr1, vr1->hashcode,
2006e4b17023SJohn Marino 				   INSERT);
2007e4b17023SJohn Marino 
2008e4b17023SJohn Marino   /* At this point we should have all the things inserted that we have
2009e4b17023SJohn Marino      seen before, and we should never try inserting something that
2010e4b17023SJohn Marino      already exists.  */
2011e4b17023SJohn Marino   gcc_assert (!*slot);
2012e4b17023SJohn Marino   if (*slot)
2013e4b17023SJohn Marino     free_reference (*slot);
2014e4b17023SJohn Marino 
2015e4b17023SJohn Marino   *slot = vr1;
2016e4b17023SJohn Marino   return vr1;
2017e4b17023SJohn Marino }
2018e4b17023SJohn Marino 
2019e4b17023SJohn Marino /* Compute and return the hash value for nary operation VBO1.  */
2020e4b17023SJohn Marino 
2021e4b17023SJohn Marino hashval_t
vn_nary_op_compute_hash(const vn_nary_op_t vno1)2022e4b17023SJohn Marino vn_nary_op_compute_hash (const vn_nary_op_t vno1)
2023e4b17023SJohn Marino {
2024e4b17023SJohn Marino   hashval_t hash;
2025e4b17023SJohn Marino   unsigned i;
2026e4b17023SJohn Marino 
2027e4b17023SJohn Marino   for (i = 0; i < vno1->length; ++i)
2028e4b17023SJohn Marino     if (TREE_CODE (vno1->op[i]) == SSA_NAME)
2029e4b17023SJohn Marino       vno1->op[i] = SSA_VAL (vno1->op[i]);
2030e4b17023SJohn Marino 
2031e4b17023SJohn Marino   if (vno1->length == 2
2032e4b17023SJohn Marino       && commutative_tree_code (vno1->opcode)
2033e4b17023SJohn Marino       && tree_swap_operands_p (vno1->op[0], vno1->op[1], false))
2034e4b17023SJohn Marino     {
2035e4b17023SJohn Marino       tree temp = vno1->op[0];
2036e4b17023SJohn Marino       vno1->op[0] = vno1->op[1];
2037e4b17023SJohn Marino       vno1->op[1] = temp;
2038e4b17023SJohn Marino     }
2039e4b17023SJohn Marino 
2040e4b17023SJohn Marino   hash = iterative_hash_hashval_t (vno1->opcode, 0);
2041e4b17023SJohn Marino   for (i = 0; i < vno1->length; ++i)
2042e4b17023SJohn Marino     hash = iterative_hash_expr (vno1->op[i], hash);
2043e4b17023SJohn Marino 
2044e4b17023SJohn Marino   return hash;
2045e4b17023SJohn Marino }
2046e4b17023SJohn Marino 
2047e4b17023SJohn Marino /* Return the computed hashcode for nary operation P1.  */
2048e4b17023SJohn Marino 
2049e4b17023SJohn Marino static hashval_t
vn_nary_op_hash(const void * p1)2050e4b17023SJohn Marino vn_nary_op_hash (const void *p1)
2051e4b17023SJohn Marino {
2052e4b17023SJohn Marino   const_vn_nary_op_t const vno1 = (const_vn_nary_op_t) p1;
2053e4b17023SJohn Marino   return vno1->hashcode;
2054e4b17023SJohn Marino }
2055e4b17023SJohn Marino 
2056e4b17023SJohn Marino /* Compare nary operations P1 and P2 and return true if they are
2057e4b17023SJohn Marino    equivalent.  */
2058e4b17023SJohn Marino 
2059e4b17023SJohn Marino int
vn_nary_op_eq(const void * p1,const void * p2)2060e4b17023SJohn Marino vn_nary_op_eq (const void *p1, const void *p2)
2061e4b17023SJohn Marino {
2062e4b17023SJohn Marino   const_vn_nary_op_t const vno1 = (const_vn_nary_op_t) p1;
2063e4b17023SJohn Marino   const_vn_nary_op_t const vno2 = (const_vn_nary_op_t) p2;
2064e4b17023SJohn Marino   unsigned i;
2065e4b17023SJohn Marino 
2066e4b17023SJohn Marino   if (vno1->hashcode != vno2->hashcode)
2067e4b17023SJohn Marino     return false;
2068e4b17023SJohn Marino 
2069e4b17023SJohn Marino   if (vno1->length != vno2->length)
2070e4b17023SJohn Marino     return false;
2071e4b17023SJohn Marino 
2072e4b17023SJohn Marino   if (vno1->opcode != vno2->opcode
2073e4b17023SJohn Marino       || !types_compatible_p (vno1->type, vno2->type))
2074e4b17023SJohn Marino     return false;
2075e4b17023SJohn Marino 
2076e4b17023SJohn Marino   for (i = 0; i < vno1->length; ++i)
2077e4b17023SJohn Marino     if (!expressions_equal_p (vno1->op[i], vno2->op[i]))
2078e4b17023SJohn Marino       return false;
2079e4b17023SJohn Marino 
2080e4b17023SJohn Marino   return true;
2081e4b17023SJohn Marino }
2082e4b17023SJohn Marino 
2083e4b17023SJohn Marino /* Initialize VNO from the pieces provided.  */
2084e4b17023SJohn Marino 
2085e4b17023SJohn Marino static void
init_vn_nary_op_from_pieces(vn_nary_op_t vno,unsigned int length,enum tree_code code,tree type,tree * ops)2086e4b17023SJohn Marino init_vn_nary_op_from_pieces (vn_nary_op_t vno, unsigned int length,
2087e4b17023SJohn Marino 			     enum tree_code code, tree type, tree *ops)
2088e4b17023SJohn Marino {
2089e4b17023SJohn Marino   vno->opcode = code;
2090e4b17023SJohn Marino   vno->length = length;
2091e4b17023SJohn Marino   vno->type = type;
2092e4b17023SJohn Marino   memcpy (&vno->op[0], ops, sizeof (tree) * length);
2093e4b17023SJohn Marino }
2094e4b17023SJohn Marino 
2095e4b17023SJohn Marino /* Initialize VNO from OP.  */
2096e4b17023SJohn Marino 
2097e4b17023SJohn Marino static void
init_vn_nary_op_from_op(vn_nary_op_t vno,tree op)2098e4b17023SJohn Marino init_vn_nary_op_from_op (vn_nary_op_t vno, tree op)
2099e4b17023SJohn Marino {
2100e4b17023SJohn Marino   unsigned i;
2101e4b17023SJohn Marino 
2102e4b17023SJohn Marino   vno->opcode = TREE_CODE (op);
2103e4b17023SJohn Marino   vno->length = TREE_CODE_LENGTH (TREE_CODE (op));
2104e4b17023SJohn Marino   vno->type = TREE_TYPE (op);
2105e4b17023SJohn Marino   for (i = 0; i < vno->length; ++i)
2106e4b17023SJohn Marino     vno->op[i] = TREE_OPERAND (op, i);
2107e4b17023SJohn Marino }
2108e4b17023SJohn Marino 
2109e4b17023SJohn Marino /* Return the number of operands for a vn_nary ops structure from STMT.  */
2110e4b17023SJohn Marino 
2111e4b17023SJohn Marino static unsigned int
vn_nary_length_from_stmt(gimple stmt)2112e4b17023SJohn Marino vn_nary_length_from_stmt (gimple stmt)
2113e4b17023SJohn Marino {
2114e4b17023SJohn Marino   switch (gimple_assign_rhs_code (stmt))
2115e4b17023SJohn Marino     {
2116e4b17023SJohn Marino     case REALPART_EXPR:
2117e4b17023SJohn Marino     case IMAGPART_EXPR:
2118e4b17023SJohn Marino     case VIEW_CONVERT_EXPR:
2119e4b17023SJohn Marino       return 1;
2120e4b17023SJohn Marino 
2121e4b17023SJohn Marino     case CONSTRUCTOR:
2122e4b17023SJohn Marino       return CONSTRUCTOR_NELTS (gimple_assign_rhs1 (stmt));
2123e4b17023SJohn Marino 
2124e4b17023SJohn Marino     default:
2125e4b17023SJohn Marino       return gimple_num_ops (stmt) - 1;
2126e4b17023SJohn Marino     }
2127e4b17023SJohn Marino }
2128e4b17023SJohn Marino 
2129e4b17023SJohn Marino /* Initialize VNO from STMT.  */
2130e4b17023SJohn Marino 
2131e4b17023SJohn Marino static void
init_vn_nary_op_from_stmt(vn_nary_op_t vno,gimple stmt)2132e4b17023SJohn Marino init_vn_nary_op_from_stmt (vn_nary_op_t vno, gimple stmt)
2133e4b17023SJohn Marino {
2134e4b17023SJohn Marino   unsigned i;
2135e4b17023SJohn Marino 
2136e4b17023SJohn Marino   vno->opcode = gimple_assign_rhs_code (stmt);
2137e4b17023SJohn Marino   vno->type = gimple_expr_type (stmt);
2138e4b17023SJohn Marino   switch (vno->opcode)
2139e4b17023SJohn Marino     {
2140e4b17023SJohn Marino     case REALPART_EXPR:
2141e4b17023SJohn Marino     case IMAGPART_EXPR:
2142e4b17023SJohn Marino     case VIEW_CONVERT_EXPR:
2143e4b17023SJohn Marino       vno->length = 1;
2144e4b17023SJohn Marino       vno->op[0] = TREE_OPERAND (gimple_assign_rhs1 (stmt), 0);
2145e4b17023SJohn Marino       break;
2146e4b17023SJohn Marino 
2147e4b17023SJohn Marino     case CONSTRUCTOR:
2148e4b17023SJohn Marino       vno->length = CONSTRUCTOR_NELTS (gimple_assign_rhs1 (stmt));
2149e4b17023SJohn Marino       for (i = 0; i < vno->length; ++i)
2150e4b17023SJohn Marino 	vno->op[i] = CONSTRUCTOR_ELT (gimple_assign_rhs1 (stmt), i)->value;
2151e4b17023SJohn Marino       break;
2152e4b17023SJohn Marino 
2153e4b17023SJohn Marino     default:
2154e4b17023SJohn Marino       vno->length = gimple_num_ops (stmt) - 1;
2155e4b17023SJohn Marino       for (i = 0; i < vno->length; ++i)
2156e4b17023SJohn Marino 	vno->op[i] = gimple_op (stmt, i + 1);
2157e4b17023SJohn Marino     }
2158e4b17023SJohn Marino }
2159e4b17023SJohn Marino 
2160e4b17023SJohn Marino /* Compute the hashcode for VNO and look for it in the hash table;
2161e4b17023SJohn Marino    return the resulting value number if it exists in the hash table.
2162e4b17023SJohn Marino    Return NULL_TREE if it does not exist in the hash table or if the
2163e4b17023SJohn Marino    result field of the operation is NULL.  VNRESULT will contain the
2164e4b17023SJohn Marino    vn_nary_op_t from the hashtable if it exists.  */
2165e4b17023SJohn Marino 
2166e4b17023SJohn Marino static tree
vn_nary_op_lookup_1(vn_nary_op_t vno,vn_nary_op_t * vnresult)2167e4b17023SJohn Marino vn_nary_op_lookup_1 (vn_nary_op_t vno, vn_nary_op_t *vnresult)
2168e4b17023SJohn Marino {
2169e4b17023SJohn Marino   void **slot;
2170e4b17023SJohn Marino 
2171e4b17023SJohn Marino   if (vnresult)
2172e4b17023SJohn Marino     *vnresult = NULL;
2173e4b17023SJohn Marino 
2174e4b17023SJohn Marino   vno->hashcode = vn_nary_op_compute_hash (vno);
2175e4b17023SJohn Marino   slot = htab_find_slot_with_hash (current_info->nary, vno, vno->hashcode,
2176e4b17023SJohn Marino 				   NO_INSERT);
2177e4b17023SJohn Marino   if (!slot && current_info == optimistic_info)
2178e4b17023SJohn Marino     slot = htab_find_slot_with_hash (valid_info->nary, vno, vno->hashcode,
2179e4b17023SJohn Marino 				     NO_INSERT);
2180e4b17023SJohn Marino   if (!slot)
2181e4b17023SJohn Marino     return NULL_TREE;
2182e4b17023SJohn Marino   if (vnresult)
2183e4b17023SJohn Marino     *vnresult = (vn_nary_op_t)*slot;
2184e4b17023SJohn Marino   return ((vn_nary_op_t)*slot)->result;
2185e4b17023SJohn Marino }
2186e4b17023SJohn Marino 
2187e4b17023SJohn Marino /* Lookup a n-ary operation by its pieces and return the resulting value
2188e4b17023SJohn Marino    number if it exists in the hash table.  Return NULL_TREE if it does
2189e4b17023SJohn Marino    not exist in the hash table or if the result field of the operation
2190e4b17023SJohn Marino    is NULL. VNRESULT will contain the vn_nary_op_t from the hashtable
2191e4b17023SJohn Marino    if it exists.  */
2192e4b17023SJohn Marino 
2193e4b17023SJohn Marino tree
vn_nary_op_lookup_pieces(unsigned int length,enum tree_code code,tree type,tree * ops,vn_nary_op_t * vnresult)2194e4b17023SJohn Marino vn_nary_op_lookup_pieces (unsigned int length, enum tree_code code,
2195e4b17023SJohn Marino 			  tree type, tree *ops, vn_nary_op_t *vnresult)
2196e4b17023SJohn Marino {
2197e4b17023SJohn Marino   vn_nary_op_t vno1 = XALLOCAVAR (struct vn_nary_op_s,
2198e4b17023SJohn Marino 				  sizeof_vn_nary_op (length));
2199e4b17023SJohn Marino   init_vn_nary_op_from_pieces (vno1, length, code, type, ops);
2200e4b17023SJohn Marino   return vn_nary_op_lookup_1 (vno1, vnresult);
2201e4b17023SJohn Marino }
2202e4b17023SJohn Marino 
2203e4b17023SJohn Marino /* Lookup OP in the current hash table, and return the resulting value
2204e4b17023SJohn Marino    number if it exists in the hash table.  Return NULL_TREE if it does
2205e4b17023SJohn Marino    not exist in the hash table or if the result field of the operation
2206e4b17023SJohn Marino    is NULL. VNRESULT will contain the vn_nary_op_t from the hashtable
2207e4b17023SJohn Marino    if it exists.  */
2208e4b17023SJohn Marino 
2209e4b17023SJohn Marino tree
vn_nary_op_lookup(tree op,vn_nary_op_t * vnresult)2210e4b17023SJohn Marino vn_nary_op_lookup (tree op, vn_nary_op_t *vnresult)
2211e4b17023SJohn Marino {
2212e4b17023SJohn Marino   vn_nary_op_t vno1
2213e4b17023SJohn Marino     = XALLOCAVAR (struct vn_nary_op_s,
2214e4b17023SJohn Marino 		  sizeof_vn_nary_op (TREE_CODE_LENGTH (TREE_CODE (op))));
2215e4b17023SJohn Marino   init_vn_nary_op_from_op (vno1, op);
2216e4b17023SJohn Marino   return vn_nary_op_lookup_1 (vno1, vnresult);
2217e4b17023SJohn Marino }
2218e4b17023SJohn Marino 
2219e4b17023SJohn Marino /* Lookup the rhs of STMT in the current hash table, and return the resulting
2220e4b17023SJohn Marino    value number if it exists in the hash table.  Return NULL_TREE if
2221e4b17023SJohn Marino    it does not exist in the hash table.  VNRESULT will contain the
2222e4b17023SJohn Marino    vn_nary_op_t from the hashtable if it exists.  */
2223e4b17023SJohn Marino 
2224e4b17023SJohn Marino tree
vn_nary_op_lookup_stmt(gimple stmt,vn_nary_op_t * vnresult)2225e4b17023SJohn Marino vn_nary_op_lookup_stmt (gimple stmt, vn_nary_op_t *vnresult)
2226e4b17023SJohn Marino {
2227e4b17023SJohn Marino   vn_nary_op_t vno1
2228e4b17023SJohn Marino     = XALLOCAVAR (struct vn_nary_op_s,
2229e4b17023SJohn Marino 		  sizeof_vn_nary_op (vn_nary_length_from_stmt (stmt)));
2230e4b17023SJohn Marino   init_vn_nary_op_from_stmt (vno1, stmt);
2231e4b17023SJohn Marino   return vn_nary_op_lookup_1 (vno1, vnresult);
2232e4b17023SJohn Marino }
2233e4b17023SJohn Marino 
2234e4b17023SJohn Marino /* Allocate a vn_nary_op_t with LENGTH operands on STACK.  */
2235e4b17023SJohn Marino 
2236e4b17023SJohn Marino static vn_nary_op_t
alloc_vn_nary_op_noinit(unsigned int length,struct obstack * stack)2237e4b17023SJohn Marino alloc_vn_nary_op_noinit (unsigned int length, struct obstack *stack)
2238e4b17023SJohn Marino {
2239e4b17023SJohn Marino   return (vn_nary_op_t) obstack_alloc (stack, sizeof_vn_nary_op (length));
2240e4b17023SJohn Marino }
2241e4b17023SJohn Marino 
2242e4b17023SJohn Marino /* Allocate and initialize a vn_nary_op_t on CURRENT_INFO's
2243e4b17023SJohn Marino    obstack.  */
2244e4b17023SJohn Marino 
2245e4b17023SJohn Marino static vn_nary_op_t
alloc_vn_nary_op(unsigned int length,tree result,unsigned int value_id)2246e4b17023SJohn Marino alloc_vn_nary_op (unsigned int length, tree result, unsigned int value_id)
2247e4b17023SJohn Marino {
2248e4b17023SJohn Marino   vn_nary_op_t vno1 = alloc_vn_nary_op_noinit (length,
2249e4b17023SJohn Marino 					       &current_info->nary_obstack);
2250e4b17023SJohn Marino 
2251e4b17023SJohn Marino   vno1->value_id = value_id;
2252e4b17023SJohn Marino   vno1->length = length;
2253e4b17023SJohn Marino   vno1->result = result;
2254e4b17023SJohn Marino 
2255e4b17023SJohn Marino   return vno1;
2256e4b17023SJohn Marino }
2257e4b17023SJohn Marino 
2258e4b17023SJohn Marino /* Insert VNO into TABLE.  If COMPUTE_HASH is true, then compute
2259e4b17023SJohn Marino    VNO->HASHCODE first.  */
2260e4b17023SJohn Marino 
2261e4b17023SJohn Marino static vn_nary_op_t
vn_nary_op_insert_into(vn_nary_op_t vno,htab_t table,bool compute_hash)2262e4b17023SJohn Marino vn_nary_op_insert_into (vn_nary_op_t vno, htab_t table, bool compute_hash)
2263e4b17023SJohn Marino {
2264e4b17023SJohn Marino   void **slot;
2265e4b17023SJohn Marino 
2266e4b17023SJohn Marino   if (compute_hash)
2267e4b17023SJohn Marino     vno->hashcode = vn_nary_op_compute_hash (vno);
2268e4b17023SJohn Marino 
2269e4b17023SJohn Marino   slot = htab_find_slot_with_hash (table, vno, vno->hashcode, INSERT);
2270e4b17023SJohn Marino   gcc_assert (!*slot);
2271e4b17023SJohn Marino 
2272e4b17023SJohn Marino   *slot = vno;
2273e4b17023SJohn Marino   return vno;
2274e4b17023SJohn Marino }
2275e4b17023SJohn Marino 
2276e4b17023SJohn Marino /* Insert a n-ary operation into the current hash table using it's
2277e4b17023SJohn Marino    pieces.  Return the vn_nary_op_t structure we created and put in
2278e4b17023SJohn Marino    the hashtable.  */
2279e4b17023SJohn Marino 
2280e4b17023SJohn Marino vn_nary_op_t
vn_nary_op_insert_pieces(unsigned int length,enum tree_code code,tree type,tree * ops,tree result,unsigned int value_id)2281e4b17023SJohn Marino vn_nary_op_insert_pieces (unsigned int length, enum tree_code code,
2282e4b17023SJohn Marino 			  tree type, tree *ops,
2283e4b17023SJohn Marino 			  tree result, unsigned int value_id)
2284e4b17023SJohn Marino {
2285e4b17023SJohn Marino   vn_nary_op_t vno1 = alloc_vn_nary_op (length, result, value_id);
2286e4b17023SJohn Marino   init_vn_nary_op_from_pieces (vno1, length, code, type, ops);
2287e4b17023SJohn Marino   return vn_nary_op_insert_into (vno1, current_info->nary, true);
2288e4b17023SJohn Marino }
2289e4b17023SJohn Marino 
2290e4b17023SJohn Marino /* Insert OP into the current hash table with a value number of
2291e4b17023SJohn Marino    RESULT.  Return the vn_nary_op_t structure we created and put in
2292e4b17023SJohn Marino    the hashtable.  */
2293e4b17023SJohn Marino 
2294e4b17023SJohn Marino vn_nary_op_t
vn_nary_op_insert(tree op,tree result)2295e4b17023SJohn Marino vn_nary_op_insert (tree op, tree result)
2296e4b17023SJohn Marino {
2297e4b17023SJohn Marino   unsigned length = TREE_CODE_LENGTH (TREE_CODE (op));
2298e4b17023SJohn Marino   vn_nary_op_t vno1;
2299e4b17023SJohn Marino 
2300e4b17023SJohn Marino   vno1 = alloc_vn_nary_op (length, result, VN_INFO (result)->value_id);
2301e4b17023SJohn Marino   init_vn_nary_op_from_op (vno1, op);
2302e4b17023SJohn Marino   return vn_nary_op_insert_into (vno1, current_info->nary, true);
2303e4b17023SJohn Marino }
2304e4b17023SJohn Marino 
2305e4b17023SJohn Marino /* Insert the rhs of STMT into the current hash table with a value number of
2306e4b17023SJohn Marino    RESULT.  */
2307e4b17023SJohn Marino 
2308e4b17023SJohn Marino vn_nary_op_t
vn_nary_op_insert_stmt(gimple stmt,tree result)2309e4b17023SJohn Marino vn_nary_op_insert_stmt (gimple stmt, tree result)
2310e4b17023SJohn Marino {
2311e4b17023SJohn Marino   vn_nary_op_t vno1
2312e4b17023SJohn Marino     = alloc_vn_nary_op (vn_nary_length_from_stmt (stmt),
2313e4b17023SJohn Marino 			result, VN_INFO (result)->value_id);
2314e4b17023SJohn Marino   init_vn_nary_op_from_stmt (vno1, stmt);
2315e4b17023SJohn Marino   return vn_nary_op_insert_into (vno1, current_info->nary, true);
2316e4b17023SJohn Marino }
2317e4b17023SJohn Marino 
2318e4b17023SJohn Marino /* Compute a hashcode for PHI operation VP1 and return it.  */
2319e4b17023SJohn Marino 
2320e4b17023SJohn Marino static inline hashval_t
vn_phi_compute_hash(vn_phi_t vp1)2321e4b17023SJohn Marino vn_phi_compute_hash (vn_phi_t vp1)
2322e4b17023SJohn Marino {
2323e4b17023SJohn Marino   hashval_t result;
2324e4b17023SJohn Marino   int i;
2325e4b17023SJohn Marino   tree phi1op;
2326e4b17023SJohn Marino   tree type;
2327e4b17023SJohn Marino 
2328e4b17023SJohn Marino   result = vp1->block->index;
2329e4b17023SJohn Marino 
2330e4b17023SJohn Marino   /* If all PHI arguments are constants we need to distinguish
2331e4b17023SJohn Marino      the PHI node via its type.  */
2332e4b17023SJohn Marino   type = TREE_TYPE (VEC_index (tree, vp1->phiargs, 0));
2333e4b17023SJohn Marino   result += (INTEGRAL_TYPE_P (type)
2334e4b17023SJohn Marino 	     + (INTEGRAL_TYPE_P (type)
2335e4b17023SJohn Marino 		? TYPE_PRECISION (type) + TYPE_UNSIGNED (type) : 0));
2336e4b17023SJohn Marino 
2337e4b17023SJohn Marino   FOR_EACH_VEC_ELT (tree, vp1->phiargs, i, phi1op)
2338e4b17023SJohn Marino     {
2339e4b17023SJohn Marino       if (phi1op == VN_TOP)
2340e4b17023SJohn Marino 	continue;
2341e4b17023SJohn Marino       result = iterative_hash_expr (phi1op, result);
2342e4b17023SJohn Marino     }
2343e4b17023SJohn Marino 
2344e4b17023SJohn Marino   return result;
2345e4b17023SJohn Marino }
2346e4b17023SJohn Marino 
2347e4b17023SJohn Marino /* Return the computed hashcode for phi operation P1.  */
2348e4b17023SJohn Marino 
2349e4b17023SJohn Marino static hashval_t
vn_phi_hash(const void * p1)2350e4b17023SJohn Marino vn_phi_hash (const void *p1)
2351e4b17023SJohn Marino {
2352e4b17023SJohn Marino   const_vn_phi_t const vp1 = (const_vn_phi_t) p1;
2353e4b17023SJohn Marino   return vp1->hashcode;
2354e4b17023SJohn Marino }
2355e4b17023SJohn Marino 
2356e4b17023SJohn Marino /* Compare two phi entries for equality, ignoring VN_TOP arguments.  */
2357e4b17023SJohn Marino 
2358e4b17023SJohn Marino static int
vn_phi_eq(const void * p1,const void * p2)2359e4b17023SJohn Marino vn_phi_eq (const void *p1, const void *p2)
2360e4b17023SJohn Marino {
2361e4b17023SJohn Marino   const_vn_phi_t const vp1 = (const_vn_phi_t) p1;
2362e4b17023SJohn Marino   const_vn_phi_t const vp2 = (const_vn_phi_t) p2;
2363e4b17023SJohn Marino 
2364e4b17023SJohn Marino   if (vp1->hashcode != vp2->hashcode)
2365e4b17023SJohn Marino     return false;
2366e4b17023SJohn Marino 
2367e4b17023SJohn Marino   if (vp1->block == vp2->block)
2368e4b17023SJohn Marino     {
2369e4b17023SJohn Marino       int i;
2370e4b17023SJohn Marino       tree phi1op;
2371e4b17023SJohn Marino 
2372e4b17023SJohn Marino       /* If the PHI nodes do not have compatible types
2373e4b17023SJohn Marino 	 they are not the same.  */
2374e4b17023SJohn Marino       if (!types_compatible_p (TREE_TYPE (VEC_index (tree, vp1->phiargs, 0)),
2375e4b17023SJohn Marino 			       TREE_TYPE (VEC_index (tree, vp2->phiargs, 0))))
2376e4b17023SJohn Marino 	return false;
2377e4b17023SJohn Marino 
2378e4b17023SJohn Marino       /* Any phi in the same block will have it's arguments in the
2379e4b17023SJohn Marino 	 same edge order, because of how we store phi nodes.  */
2380e4b17023SJohn Marino       FOR_EACH_VEC_ELT (tree, vp1->phiargs, i, phi1op)
2381e4b17023SJohn Marino 	{
2382e4b17023SJohn Marino 	  tree phi2op = VEC_index (tree, vp2->phiargs, i);
2383e4b17023SJohn Marino 	  if (phi1op == VN_TOP || phi2op == VN_TOP)
2384e4b17023SJohn Marino 	    continue;
2385e4b17023SJohn Marino 	  if (!expressions_equal_p (phi1op, phi2op))
2386e4b17023SJohn Marino 	    return false;
2387e4b17023SJohn Marino 	}
2388e4b17023SJohn Marino       return true;
2389e4b17023SJohn Marino     }
2390e4b17023SJohn Marino   return false;
2391e4b17023SJohn Marino }
2392e4b17023SJohn Marino 
VEC(tree,heap)2393e4b17023SJohn Marino static VEC(tree, heap) *shared_lookup_phiargs;
2394e4b17023SJohn Marino 
2395e4b17023SJohn Marino /* Lookup PHI in the current hash table, and return the resulting
2396e4b17023SJohn Marino    value number if it exists in the hash table.  Return NULL_TREE if
2397e4b17023SJohn Marino    it does not exist in the hash table. */
2398e4b17023SJohn Marino 
2399e4b17023SJohn Marino static tree
2400e4b17023SJohn Marino vn_phi_lookup (gimple phi)
2401e4b17023SJohn Marino {
2402e4b17023SJohn Marino   void **slot;
2403e4b17023SJohn Marino   struct vn_phi_s vp1;
2404e4b17023SJohn Marino   unsigned i;
2405e4b17023SJohn Marino 
2406e4b17023SJohn Marino   VEC_truncate (tree, shared_lookup_phiargs, 0);
2407e4b17023SJohn Marino 
2408e4b17023SJohn Marino   /* Canonicalize the SSA_NAME's to their value number.  */
2409e4b17023SJohn Marino   for (i = 0; i < gimple_phi_num_args (phi); i++)
2410e4b17023SJohn Marino     {
2411e4b17023SJohn Marino       tree def = PHI_ARG_DEF (phi, i);
2412e4b17023SJohn Marino       def = TREE_CODE (def) == SSA_NAME ? SSA_VAL (def) : def;
2413e4b17023SJohn Marino       VEC_safe_push (tree, heap, shared_lookup_phiargs, def);
2414e4b17023SJohn Marino     }
2415e4b17023SJohn Marino   vp1.phiargs = shared_lookup_phiargs;
2416e4b17023SJohn Marino   vp1.block = gimple_bb (phi);
2417e4b17023SJohn Marino   vp1.hashcode = vn_phi_compute_hash (&vp1);
2418e4b17023SJohn Marino   slot = htab_find_slot_with_hash (current_info->phis, &vp1, vp1.hashcode,
2419e4b17023SJohn Marino 				   NO_INSERT);
2420e4b17023SJohn Marino   if (!slot && current_info == optimistic_info)
2421e4b17023SJohn Marino     slot = htab_find_slot_with_hash (valid_info->phis, &vp1, vp1.hashcode,
2422e4b17023SJohn Marino 				     NO_INSERT);
2423e4b17023SJohn Marino   if (!slot)
2424e4b17023SJohn Marino     return NULL_TREE;
2425e4b17023SJohn Marino   return ((vn_phi_t)*slot)->result;
2426e4b17023SJohn Marino }
2427e4b17023SJohn Marino 
2428e4b17023SJohn Marino /* Insert PHI into the current hash table with a value number of
2429e4b17023SJohn Marino    RESULT.  */
2430e4b17023SJohn Marino 
2431e4b17023SJohn Marino static vn_phi_t
vn_phi_insert(gimple phi,tree result)2432e4b17023SJohn Marino vn_phi_insert (gimple phi, tree result)
2433e4b17023SJohn Marino {
2434e4b17023SJohn Marino   void **slot;
2435e4b17023SJohn Marino   vn_phi_t vp1 = (vn_phi_t) pool_alloc (current_info->phis_pool);
2436e4b17023SJohn Marino   unsigned i;
2437e4b17023SJohn Marino   VEC (tree, heap) *args = NULL;
2438e4b17023SJohn Marino 
2439e4b17023SJohn Marino   /* Canonicalize the SSA_NAME's to their value number.  */
2440e4b17023SJohn Marino   for (i = 0; i < gimple_phi_num_args (phi); i++)
2441e4b17023SJohn Marino     {
2442e4b17023SJohn Marino       tree def = PHI_ARG_DEF (phi, i);
2443e4b17023SJohn Marino       def = TREE_CODE (def) == SSA_NAME ? SSA_VAL (def) : def;
2444e4b17023SJohn Marino       VEC_safe_push (tree, heap, args, def);
2445e4b17023SJohn Marino     }
2446e4b17023SJohn Marino   vp1->value_id = VN_INFO (result)->value_id;
2447e4b17023SJohn Marino   vp1->phiargs = args;
2448e4b17023SJohn Marino   vp1->block = gimple_bb (phi);
2449e4b17023SJohn Marino   vp1->result = result;
2450e4b17023SJohn Marino   vp1->hashcode = vn_phi_compute_hash (vp1);
2451e4b17023SJohn Marino 
2452e4b17023SJohn Marino   slot = htab_find_slot_with_hash (current_info->phis, vp1, vp1->hashcode,
2453e4b17023SJohn Marino 				   INSERT);
2454e4b17023SJohn Marino 
2455e4b17023SJohn Marino   /* Because we iterate over phi operations more than once, it's
2456e4b17023SJohn Marino      possible the slot might already exist here, hence no assert.*/
2457e4b17023SJohn Marino   *slot = vp1;
2458e4b17023SJohn Marino   return vp1;
2459e4b17023SJohn Marino }
2460e4b17023SJohn Marino 
2461e4b17023SJohn Marino 
2462e4b17023SJohn Marino /* Print set of components in strongly connected component SCC to OUT. */
2463e4b17023SJohn Marino 
2464e4b17023SJohn Marino static void
print_scc(FILE * out,VEC (tree,heap)* scc)2465e4b17023SJohn Marino print_scc (FILE *out, VEC (tree, heap) *scc)
2466e4b17023SJohn Marino {
2467e4b17023SJohn Marino   tree var;
2468e4b17023SJohn Marino   unsigned int i;
2469e4b17023SJohn Marino 
2470e4b17023SJohn Marino   fprintf (out, "SCC consists of:");
2471e4b17023SJohn Marino   FOR_EACH_VEC_ELT (tree, scc, i, var)
2472e4b17023SJohn Marino     {
2473e4b17023SJohn Marino       fprintf (out, " ");
2474e4b17023SJohn Marino       print_generic_expr (out, var, 0);
2475e4b17023SJohn Marino     }
2476e4b17023SJohn Marino   fprintf (out, "\n");
2477e4b17023SJohn Marino }
2478e4b17023SJohn Marino 
2479e4b17023SJohn Marino /* Set the value number of FROM to TO, return true if it has changed
2480e4b17023SJohn Marino    as a result.  */
2481e4b17023SJohn Marino 
2482e4b17023SJohn Marino static inline bool
set_ssa_val_to(tree from,tree to)2483e4b17023SJohn Marino set_ssa_val_to (tree from, tree to)
2484e4b17023SJohn Marino {
2485e4b17023SJohn Marino   tree currval = SSA_VAL (from);
2486*95d28233SJohn Marino   HOST_WIDE_INT toff, coff;
2487e4b17023SJohn Marino 
2488e4b17023SJohn Marino   if (from != to)
2489e4b17023SJohn Marino     {
2490e4b17023SJohn Marino       if (currval == from)
2491e4b17023SJohn Marino 	{
2492e4b17023SJohn Marino 	  if (dump_file && (dump_flags & TDF_DETAILS))
2493e4b17023SJohn Marino 	    {
2494e4b17023SJohn Marino 	      fprintf (dump_file, "Not changing value number of ");
2495e4b17023SJohn Marino 	      print_generic_expr (dump_file, from, 0);
2496e4b17023SJohn Marino 	      fprintf (dump_file, " from VARYING to ");
2497e4b17023SJohn Marino 	      print_generic_expr (dump_file, to, 0);
2498e4b17023SJohn Marino 	      fprintf (dump_file, "\n");
2499e4b17023SJohn Marino 	    }
2500e4b17023SJohn Marino 	  return false;
2501e4b17023SJohn Marino 	}
2502e4b17023SJohn Marino       else if (TREE_CODE (to) == SSA_NAME
2503e4b17023SJohn Marino 	       && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (to))
2504e4b17023SJohn Marino 	to = from;
2505e4b17023SJohn Marino     }
2506e4b17023SJohn Marino 
2507e4b17023SJohn Marino   /* The only thing we allow as value numbers are VN_TOP, ssa_names
2508e4b17023SJohn Marino      and invariants.  So assert that here.  */
2509e4b17023SJohn Marino   gcc_assert (to != NULL_TREE
2510e4b17023SJohn Marino 	      && (to == VN_TOP
2511e4b17023SJohn Marino 		  || TREE_CODE (to) == SSA_NAME
2512e4b17023SJohn Marino 		  || is_gimple_min_invariant (to)));
2513e4b17023SJohn Marino 
2514e4b17023SJohn Marino   if (dump_file && (dump_flags & TDF_DETAILS))
2515e4b17023SJohn Marino     {
2516e4b17023SJohn Marino       fprintf (dump_file, "Setting value number of ");
2517e4b17023SJohn Marino       print_generic_expr (dump_file, from, 0);
2518e4b17023SJohn Marino       fprintf (dump_file, " to ");
2519e4b17023SJohn Marino       print_generic_expr (dump_file, to, 0);
2520e4b17023SJohn Marino     }
2521e4b17023SJohn Marino 
2522*95d28233SJohn Marino   if (currval != to
2523*95d28233SJohn Marino       && !operand_equal_p (currval, to, OEP_PURE_SAME)
2524*95d28233SJohn Marino       /* ???  For addresses involving volatile objects or types operand_equal_p
2525*95d28233SJohn Marino 	 does not reliably detect ADDR_EXPRs as equal.  We know we are only
2526*95d28233SJohn Marino 	 getting invariant gimple addresses here, so can use
2527*95d28233SJohn Marino 	 get_addr_base_and_unit_offset to do this comparison.  */
2528*95d28233SJohn Marino       && !(TREE_CODE (currval) == ADDR_EXPR
2529*95d28233SJohn Marino 	   && TREE_CODE (to) == ADDR_EXPR
2530*95d28233SJohn Marino 	   && (get_addr_base_and_unit_offset (TREE_OPERAND (currval, 0), &coff)
2531*95d28233SJohn Marino 	       == get_addr_base_and_unit_offset (TREE_OPERAND (to, 0), &toff))
2532*95d28233SJohn Marino 	   && coff == toff))
2533e4b17023SJohn Marino     {
2534e4b17023SJohn Marino       VN_INFO (from)->valnum = to;
2535e4b17023SJohn Marino       if (dump_file && (dump_flags & TDF_DETAILS))
2536e4b17023SJohn Marino 	fprintf (dump_file, " (changed)\n");
2537e4b17023SJohn Marino       return true;
2538e4b17023SJohn Marino     }
2539e4b17023SJohn Marino   if (dump_file && (dump_flags & TDF_DETAILS))
2540e4b17023SJohn Marino     fprintf (dump_file, "\n");
2541e4b17023SJohn Marino   return false;
2542e4b17023SJohn Marino }
2543e4b17023SJohn Marino 
2544e4b17023SJohn Marino /* Set all definitions in STMT to value number to themselves.
2545e4b17023SJohn Marino    Return true if a value number changed. */
2546e4b17023SJohn Marino 
2547e4b17023SJohn Marino static bool
defs_to_varying(gimple stmt)2548e4b17023SJohn Marino defs_to_varying (gimple stmt)
2549e4b17023SJohn Marino {
2550e4b17023SJohn Marino   bool changed = false;
2551e4b17023SJohn Marino   ssa_op_iter iter;
2552e4b17023SJohn Marino   def_operand_p defp;
2553e4b17023SJohn Marino 
2554e4b17023SJohn Marino   FOR_EACH_SSA_DEF_OPERAND (defp, stmt, iter, SSA_OP_ALL_DEFS)
2555e4b17023SJohn Marino     {
2556e4b17023SJohn Marino       tree def = DEF_FROM_PTR (defp);
2557e4b17023SJohn Marino 
2558e4b17023SJohn Marino       VN_INFO (def)->use_processed = true;
2559e4b17023SJohn Marino       changed |= set_ssa_val_to (def, def);
2560e4b17023SJohn Marino     }
2561e4b17023SJohn Marino   return changed;
2562e4b17023SJohn Marino }
2563e4b17023SJohn Marino 
2564e4b17023SJohn Marino static bool expr_has_constants (tree expr);
2565e4b17023SJohn Marino static tree valueize_expr (tree expr);
2566e4b17023SJohn Marino 
2567e4b17023SJohn Marino /* Visit a copy between LHS and RHS, return true if the value number
2568e4b17023SJohn Marino    changed.  */
2569e4b17023SJohn Marino 
2570e4b17023SJohn Marino static bool
visit_copy(tree lhs,tree rhs)2571e4b17023SJohn Marino visit_copy (tree lhs, tree rhs)
2572e4b17023SJohn Marino {
2573e4b17023SJohn Marino   /* Follow chains of copies to their destination.  */
2574e4b17023SJohn Marino   while (TREE_CODE (rhs) == SSA_NAME
2575e4b17023SJohn Marino 	 && SSA_VAL (rhs) != rhs)
2576e4b17023SJohn Marino     rhs = SSA_VAL (rhs);
2577e4b17023SJohn Marino 
2578e4b17023SJohn Marino   /* The copy may have a more interesting constant filled expression
2579e4b17023SJohn Marino      (we don't, since we know our RHS is just an SSA name).  */
2580e4b17023SJohn Marino   if (TREE_CODE (rhs) == SSA_NAME)
2581e4b17023SJohn Marino     {
2582e4b17023SJohn Marino       VN_INFO (lhs)->has_constants = VN_INFO (rhs)->has_constants;
2583e4b17023SJohn Marino       VN_INFO (lhs)->expr = VN_INFO (rhs)->expr;
2584e4b17023SJohn Marino     }
2585e4b17023SJohn Marino 
2586e4b17023SJohn Marino   return set_ssa_val_to (lhs, rhs);
2587e4b17023SJohn Marino }
2588e4b17023SJohn Marino 
2589e4b17023SJohn Marino /* Visit a nary operator RHS, value number it, and return true if the
2590e4b17023SJohn Marino    value number of LHS has changed as a result.  */
2591e4b17023SJohn Marino 
2592e4b17023SJohn Marino static bool
visit_nary_op(tree lhs,gimple stmt)2593e4b17023SJohn Marino visit_nary_op (tree lhs, gimple stmt)
2594e4b17023SJohn Marino {
2595e4b17023SJohn Marino   bool changed = false;
2596e4b17023SJohn Marino   tree result = vn_nary_op_lookup_stmt (stmt, NULL);
2597e4b17023SJohn Marino 
2598e4b17023SJohn Marino   if (result)
2599e4b17023SJohn Marino     changed = set_ssa_val_to (lhs, result);
2600e4b17023SJohn Marino   else
2601e4b17023SJohn Marino     {
2602e4b17023SJohn Marino       changed = set_ssa_val_to (lhs, lhs);
2603e4b17023SJohn Marino       vn_nary_op_insert_stmt (stmt, lhs);
2604e4b17023SJohn Marino     }
2605e4b17023SJohn Marino 
2606e4b17023SJohn Marino   return changed;
2607e4b17023SJohn Marino }
2608e4b17023SJohn Marino 
2609e4b17023SJohn Marino /* Visit a call STMT storing into LHS.  Return true if the value number
2610e4b17023SJohn Marino    of the LHS has changed as a result.  */
2611e4b17023SJohn Marino 
2612e4b17023SJohn Marino static bool
visit_reference_op_call(tree lhs,gimple stmt)2613e4b17023SJohn Marino visit_reference_op_call (tree lhs, gimple stmt)
2614e4b17023SJohn Marino {
2615e4b17023SJohn Marino   bool changed = false;
2616e4b17023SJohn Marino   struct vn_reference_s vr1;
2617e4b17023SJohn Marino   tree result;
2618e4b17023SJohn Marino   tree vuse = gimple_vuse (stmt);
2619e4b17023SJohn Marino 
2620e4b17023SJohn Marino   vr1.vuse = vuse ? SSA_VAL (vuse) : NULL_TREE;
2621e4b17023SJohn Marino   vr1.operands = valueize_shared_reference_ops_from_call (stmt);
2622e4b17023SJohn Marino   vr1.type = gimple_expr_type (stmt);
2623e4b17023SJohn Marino   vr1.set = 0;
2624e4b17023SJohn Marino   vr1.hashcode = vn_reference_compute_hash (&vr1);
2625e4b17023SJohn Marino   result = vn_reference_lookup_1 (&vr1, NULL);
2626e4b17023SJohn Marino   if (result)
2627e4b17023SJohn Marino     {
2628e4b17023SJohn Marino       changed = set_ssa_val_to (lhs, result);
2629e4b17023SJohn Marino       if (TREE_CODE (result) == SSA_NAME
2630e4b17023SJohn Marino 	  && VN_INFO (result)->has_constants)
2631e4b17023SJohn Marino 	VN_INFO (lhs)->has_constants = true;
2632e4b17023SJohn Marino     }
2633e4b17023SJohn Marino   else
2634e4b17023SJohn Marino     {
2635e4b17023SJohn Marino       void **slot;
2636e4b17023SJohn Marino       vn_reference_t vr2;
2637e4b17023SJohn Marino       changed = set_ssa_val_to (lhs, lhs);
2638e4b17023SJohn Marino       vr2 = (vn_reference_t) pool_alloc (current_info->references_pool);
2639e4b17023SJohn Marino       vr2->vuse = vr1.vuse;
2640e4b17023SJohn Marino       vr2->operands = valueize_refs (create_reference_ops_from_call (stmt));
2641e4b17023SJohn Marino       vr2->type = vr1.type;
2642e4b17023SJohn Marino       vr2->set = vr1.set;
2643e4b17023SJohn Marino       vr2->hashcode = vr1.hashcode;
2644e4b17023SJohn Marino       vr2->result = lhs;
2645e4b17023SJohn Marino       slot = htab_find_slot_with_hash (current_info->references,
2646e4b17023SJohn Marino 				       vr2, vr2->hashcode, INSERT);
2647e4b17023SJohn Marino       if (*slot)
2648e4b17023SJohn Marino 	free_reference (*slot);
2649e4b17023SJohn Marino       *slot = vr2;
2650e4b17023SJohn Marino     }
2651e4b17023SJohn Marino 
2652e4b17023SJohn Marino   return changed;
2653e4b17023SJohn Marino }
2654e4b17023SJohn Marino 
2655e4b17023SJohn Marino /* Visit a load from a reference operator RHS, part of STMT, value number it,
2656e4b17023SJohn Marino    and return true if the value number of the LHS has changed as a result.  */
2657e4b17023SJohn Marino 
2658e4b17023SJohn Marino static bool
visit_reference_op_load(tree lhs,tree op,gimple stmt)2659e4b17023SJohn Marino visit_reference_op_load (tree lhs, tree op, gimple stmt)
2660e4b17023SJohn Marino {
2661e4b17023SJohn Marino   bool changed = false;
2662e4b17023SJohn Marino   tree last_vuse;
2663e4b17023SJohn Marino   tree result;
2664e4b17023SJohn Marino 
2665e4b17023SJohn Marino   last_vuse = gimple_vuse (stmt);
2666e4b17023SJohn Marino   last_vuse_ptr = &last_vuse;
2667e4b17023SJohn Marino   result = vn_reference_lookup (op, gimple_vuse (stmt),
2668e4b17023SJohn Marino 				default_vn_walk_kind, NULL);
2669e4b17023SJohn Marino   last_vuse_ptr = NULL;
2670e4b17023SJohn Marino 
2671e4b17023SJohn Marino   /* If we have a VCE, try looking up its operand as it might be stored in
2672e4b17023SJohn Marino      a different type.  */
2673e4b17023SJohn Marino   if (!result && TREE_CODE (op) == VIEW_CONVERT_EXPR)
2674e4b17023SJohn Marino     result = vn_reference_lookup (TREE_OPERAND (op, 0), gimple_vuse (stmt),
2675e4b17023SJohn Marino     				  default_vn_walk_kind, NULL);
2676e4b17023SJohn Marino 
2677e4b17023SJohn Marino   /* We handle type-punning through unions by value-numbering based
2678e4b17023SJohn Marino      on offset and size of the access.  Be prepared to handle a
2679e4b17023SJohn Marino      type-mismatch here via creating a VIEW_CONVERT_EXPR.  */
2680e4b17023SJohn Marino   if (result
2681e4b17023SJohn Marino       && !useless_type_conversion_p (TREE_TYPE (result), TREE_TYPE (op)))
2682e4b17023SJohn Marino     {
2683e4b17023SJohn Marino       /* We will be setting the value number of lhs to the value number
2684e4b17023SJohn Marino 	 of VIEW_CONVERT_EXPR <TREE_TYPE (result)> (result).
2685e4b17023SJohn Marino 	 So first simplify and lookup this expression to see if it
2686e4b17023SJohn Marino 	 is already available.  */
2687e4b17023SJohn Marino       tree val = fold_build1 (VIEW_CONVERT_EXPR, TREE_TYPE (op), result);
2688e4b17023SJohn Marino       if ((CONVERT_EXPR_P (val)
2689e4b17023SJohn Marino 	   || TREE_CODE (val) == VIEW_CONVERT_EXPR)
2690e4b17023SJohn Marino 	  && TREE_CODE (TREE_OPERAND (val, 0)) == SSA_NAME)
2691e4b17023SJohn Marino         {
2692e4b17023SJohn Marino 	  tree tem = valueize_expr (vn_get_expr_for (TREE_OPERAND (val, 0)));
2693e4b17023SJohn Marino 	  if ((CONVERT_EXPR_P (tem)
2694e4b17023SJohn Marino 	       || TREE_CODE (tem) == VIEW_CONVERT_EXPR)
2695e4b17023SJohn Marino 	      && (tem = fold_unary_ignore_overflow (TREE_CODE (val),
2696e4b17023SJohn Marino 						    TREE_TYPE (val), tem)))
2697e4b17023SJohn Marino 	    val = tem;
2698e4b17023SJohn Marino 	}
2699e4b17023SJohn Marino       result = val;
2700e4b17023SJohn Marino       if (!is_gimple_min_invariant (val)
2701e4b17023SJohn Marino 	  && TREE_CODE (val) != SSA_NAME)
2702e4b17023SJohn Marino 	result = vn_nary_op_lookup (val, NULL);
2703e4b17023SJohn Marino       /* If the expression is not yet available, value-number lhs to
2704e4b17023SJohn Marino 	 a new SSA_NAME we create.  */
2705e4b17023SJohn Marino       if (!result)
2706e4b17023SJohn Marino         {
2707e4b17023SJohn Marino 	  result = make_ssa_name (SSA_NAME_VAR (lhs), gimple_build_nop ());
2708e4b17023SJohn Marino 	  /* Initialize value-number information properly.  */
2709e4b17023SJohn Marino 	  VN_INFO_GET (result)->valnum = result;
2710e4b17023SJohn Marino 	  VN_INFO (result)->value_id = get_next_value_id ();
2711e4b17023SJohn Marino 	  VN_INFO (result)->expr = val;
2712e4b17023SJohn Marino 	  VN_INFO (result)->has_constants = expr_has_constants (val);
2713e4b17023SJohn Marino 	  VN_INFO (result)->needs_insertion = true;
2714e4b17023SJohn Marino 	  /* As all "inserted" statements are singleton SCCs, insert
2715e4b17023SJohn Marino 	     to the valid table.  This is strictly needed to
2716e4b17023SJohn Marino 	     avoid re-generating new value SSA_NAMEs for the same
2717e4b17023SJohn Marino 	     expression during SCC iteration over and over (the
2718e4b17023SJohn Marino 	     optimistic table gets cleared after each iteration).
2719e4b17023SJohn Marino 	     We do not need to insert into the optimistic table, as
2720e4b17023SJohn Marino 	     lookups there will fall back to the valid table.  */
2721e4b17023SJohn Marino 	  if (current_info == optimistic_info)
2722e4b17023SJohn Marino 	    {
2723e4b17023SJohn Marino 	      current_info = valid_info;
2724e4b17023SJohn Marino 	      vn_nary_op_insert (val, result);
2725e4b17023SJohn Marino 	      current_info = optimistic_info;
2726e4b17023SJohn Marino 	    }
2727e4b17023SJohn Marino 	  else
2728e4b17023SJohn Marino 	    vn_nary_op_insert (val, result);
2729e4b17023SJohn Marino 	  if (dump_file && (dump_flags & TDF_DETAILS))
2730e4b17023SJohn Marino 	    {
2731e4b17023SJohn Marino 	      fprintf (dump_file, "Inserting name ");
2732e4b17023SJohn Marino 	      print_generic_expr (dump_file, result, 0);
2733e4b17023SJohn Marino 	      fprintf (dump_file, " for expression ");
2734e4b17023SJohn Marino 	      print_generic_expr (dump_file, val, 0);
2735e4b17023SJohn Marino 	      fprintf (dump_file, "\n");
2736e4b17023SJohn Marino 	    }
2737e4b17023SJohn Marino 	}
2738e4b17023SJohn Marino     }
2739e4b17023SJohn Marino 
2740e4b17023SJohn Marino   if (result)
2741e4b17023SJohn Marino     {
2742e4b17023SJohn Marino       changed = set_ssa_val_to (lhs, result);
2743e4b17023SJohn Marino       if (TREE_CODE (result) == SSA_NAME
2744e4b17023SJohn Marino 	  && VN_INFO (result)->has_constants)
2745e4b17023SJohn Marino 	{
2746e4b17023SJohn Marino 	  VN_INFO (lhs)->expr = VN_INFO (result)->expr;
2747e4b17023SJohn Marino 	  VN_INFO (lhs)->has_constants = true;
2748e4b17023SJohn Marino 	}
2749e4b17023SJohn Marino     }
2750e4b17023SJohn Marino   else
2751e4b17023SJohn Marino     {
2752e4b17023SJohn Marino       changed = set_ssa_val_to (lhs, lhs);
2753e4b17023SJohn Marino       vn_reference_insert (op, lhs, last_vuse);
2754e4b17023SJohn Marino     }
2755e4b17023SJohn Marino 
2756e4b17023SJohn Marino   return changed;
2757e4b17023SJohn Marino }
2758e4b17023SJohn Marino 
2759e4b17023SJohn Marino 
2760e4b17023SJohn Marino /* Visit a store to a reference operator LHS, part of STMT, value number it,
2761e4b17023SJohn Marino    and return true if the value number of the LHS has changed as a result.  */
2762e4b17023SJohn Marino 
2763e4b17023SJohn Marino static bool
visit_reference_op_store(tree lhs,tree op,gimple stmt)2764e4b17023SJohn Marino visit_reference_op_store (tree lhs, tree op, gimple stmt)
2765e4b17023SJohn Marino {
2766e4b17023SJohn Marino   bool changed = false;
2767e4b17023SJohn Marino   tree result;
2768e4b17023SJohn Marino   bool resultsame = false;
2769e4b17023SJohn Marino 
2770e4b17023SJohn Marino   /* First we want to lookup using the *vuses* from the store and see
2771e4b17023SJohn Marino      if there the last store to this location with the same address
2772e4b17023SJohn Marino      had the same value.
2773e4b17023SJohn Marino 
2774e4b17023SJohn Marino      The vuses represent the memory state before the store.  If the
2775e4b17023SJohn Marino      memory state, address, and value of the store is the same as the
2776e4b17023SJohn Marino      last store to this location, then this store will produce the
2777e4b17023SJohn Marino      same memory state as that store.
2778e4b17023SJohn Marino 
2779e4b17023SJohn Marino      In this case the vdef versions for this store are value numbered to those
2780e4b17023SJohn Marino      vuse versions, since they represent the same memory state after
2781e4b17023SJohn Marino      this store.
2782e4b17023SJohn Marino 
2783e4b17023SJohn Marino      Otherwise, the vdefs for the store are used when inserting into
2784e4b17023SJohn Marino      the table, since the store generates a new memory state.  */
2785e4b17023SJohn Marino 
2786e4b17023SJohn Marino   result = vn_reference_lookup (lhs, gimple_vuse (stmt), VN_NOWALK, NULL);
2787e4b17023SJohn Marino 
2788e4b17023SJohn Marino   if (result)
2789e4b17023SJohn Marino     {
2790e4b17023SJohn Marino       if (TREE_CODE (result) == SSA_NAME)
2791e4b17023SJohn Marino 	result = SSA_VAL (result);
2792e4b17023SJohn Marino       if (TREE_CODE (op) == SSA_NAME)
2793e4b17023SJohn Marino 	op = SSA_VAL (op);
2794e4b17023SJohn Marino       resultsame = expressions_equal_p (result, op);
2795e4b17023SJohn Marino     }
2796e4b17023SJohn Marino 
2797e4b17023SJohn Marino   if (!result || !resultsame)
2798e4b17023SJohn Marino     {
2799e4b17023SJohn Marino       tree vdef;
2800e4b17023SJohn Marino 
2801e4b17023SJohn Marino       if (dump_file && (dump_flags & TDF_DETAILS))
2802e4b17023SJohn Marino 	{
2803e4b17023SJohn Marino 	  fprintf (dump_file, "No store match\n");
2804e4b17023SJohn Marino 	  fprintf (dump_file, "Value numbering store ");
2805e4b17023SJohn Marino 	  print_generic_expr (dump_file, lhs, 0);
2806e4b17023SJohn Marino 	  fprintf (dump_file, " to ");
2807e4b17023SJohn Marino 	  print_generic_expr (dump_file, op, 0);
2808e4b17023SJohn Marino 	  fprintf (dump_file, "\n");
2809e4b17023SJohn Marino 	}
2810e4b17023SJohn Marino       /* Have to set value numbers before insert, since insert is
2811e4b17023SJohn Marino 	 going to valueize the references in-place.  */
2812e4b17023SJohn Marino       if ((vdef = gimple_vdef (stmt)))
2813e4b17023SJohn Marino 	{
2814e4b17023SJohn Marino 	  VN_INFO (vdef)->use_processed = true;
2815e4b17023SJohn Marino 	  changed |= set_ssa_val_to (vdef, vdef);
2816e4b17023SJohn Marino 	}
2817e4b17023SJohn Marino 
2818e4b17023SJohn Marino       /* Do not insert structure copies into the tables.  */
2819e4b17023SJohn Marino       if (is_gimple_min_invariant (op)
2820e4b17023SJohn Marino 	  || is_gimple_reg (op))
2821e4b17023SJohn Marino         vn_reference_insert (lhs, op, vdef);
2822e4b17023SJohn Marino     }
2823e4b17023SJohn Marino   else
2824e4b17023SJohn Marino     {
2825e4b17023SJohn Marino       /* We had a match, so value number the vdef to have the value
2826e4b17023SJohn Marino 	 number of the vuse it came from.  */
2827e4b17023SJohn Marino       tree def, use;
2828e4b17023SJohn Marino 
2829e4b17023SJohn Marino       if (dump_file && (dump_flags & TDF_DETAILS))
2830e4b17023SJohn Marino 	fprintf (dump_file, "Store matched earlier value,"
2831e4b17023SJohn Marino 		 "value numbering store vdefs to matching vuses.\n");
2832e4b17023SJohn Marino 
2833e4b17023SJohn Marino       def = gimple_vdef (stmt);
2834e4b17023SJohn Marino       use = gimple_vuse (stmt);
2835e4b17023SJohn Marino 
2836e4b17023SJohn Marino       VN_INFO (def)->use_processed = true;
2837e4b17023SJohn Marino       changed |= set_ssa_val_to (def, SSA_VAL (use));
2838e4b17023SJohn Marino     }
2839e4b17023SJohn Marino 
2840e4b17023SJohn Marino   return changed;
2841e4b17023SJohn Marino }
2842e4b17023SJohn Marino 
2843e4b17023SJohn Marino /* Visit and value number PHI, return true if the value number
2844e4b17023SJohn Marino    changed.  */
2845e4b17023SJohn Marino 
2846e4b17023SJohn Marino static bool
visit_phi(gimple phi)2847e4b17023SJohn Marino visit_phi (gimple phi)
2848e4b17023SJohn Marino {
2849e4b17023SJohn Marino   bool changed = false;
2850e4b17023SJohn Marino   tree result;
2851e4b17023SJohn Marino   tree sameval = VN_TOP;
2852e4b17023SJohn Marino   bool allsame = true;
2853e4b17023SJohn Marino   unsigned i;
2854e4b17023SJohn Marino 
2855e4b17023SJohn Marino   /* TODO: We could check for this in init_sccvn, and replace this
2856e4b17023SJohn Marino      with a gcc_assert.  */
2857e4b17023SJohn Marino   if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (PHI_RESULT (phi)))
2858e4b17023SJohn Marino     return set_ssa_val_to (PHI_RESULT (phi), PHI_RESULT (phi));
2859e4b17023SJohn Marino 
2860e4b17023SJohn Marino   /* See if all non-TOP arguments have the same value.  TOP is
2861e4b17023SJohn Marino      equivalent to everything, so we can ignore it.  */
2862e4b17023SJohn Marino   for (i = 0; i < gimple_phi_num_args (phi); i++)
2863e4b17023SJohn Marino     {
2864e4b17023SJohn Marino       tree def = PHI_ARG_DEF (phi, i);
2865e4b17023SJohn Marino 
2866e4b17023SJohn Marino       if (TREE_CODE (def) == SSA_NAME)
2867e4b17023SJohn Marino 	def = SSA_VAL (def);
2868e4b17023SJohn Marino       if (def == VN_TOP)
2869e4b17023SJohn Marino 	continue;
2870e4b17023SJohn Marino       if (sameval == VN_TOP)
2871e4b17023SJohn Marino 	{
2872e4b17023SJohn Marino 	  sameval = def;
2873e4b17023SJohn Marino 	}
2874e4b17023SJohn Marino       else
2875e4b17023SJohn Marino 	{
2876e4b17023SJohn Marino 	  if (!expressions_equal_p (def, sameval))
2877e4b17023SJohn Marino 	    {
2878e4b17023SJohn Marino 	      allsame = false;
2879e4b17023SJohn Marino 	      break;
2880e4b17023SJohn Marino 	    }
2881e4b17023SJohn Marino 	}
2882e4b17023SJohn Marino     }
2883e4b17023SJohn Marino 
2884e4b17023SJohn Marino   /* If all value numbered to the same value, the phi node has that
2885e4b17023SJohn Marino      value.  */
2886e4b17023SJohn Marino   if (allsame)
2887e4b17023SJohn Marino     {
2888e4b17023SJohn Marino       if (is_gimple_min_invariant (sameval))
2889e4b17023SJohn Marino 	{
2890e4b17023SJohn Marino 	  VN_INFO (PHI_RESULT (phi))->has_constants = true;
2891e4b17023SJohn Marino 	  VN_INFO (PHI_RESULT (phi))->expr = sameval;
2892e4b17023SJohn Marino 	}
2893e4b17023SJohn Marino       else
2894e4b17023SJohn Marino 	{
2895e4b17023SJohn Marino 	  VN_INFO (PHI_RESULT (phi))->has_constants = false;
2896e4b17023SJohn Marino 	  VN_INFO (PHI_RESULT (phi))->expr = sameval;
2897e4b17023SJohn Marino 	}
2898e4b17023SJohn Marino 
2899e4b17023SJohn Marino       if (TREE_CODE (sameval) == SSA_NAME)
2900e4b17023SJohn Marino 	return visit_copy (PHI_RESULT (phi), sameval);
2901e4b17023SJohn Marino 
2902e4b17023SJohn Marino       return set_ssa_val_to (PHI_RESULT (phi), sameval);
2903e4b17023SJohn Marino     }
2904e4b17023SJohn Marino 
2905e4b17023SJohn Marino   /* Otherwise, see if it is equivalent to a phi node in this block.  */
2906e4b17023SJohn Marino   result = vn_phi_lookup (phi);
2907e4b17023SJohn Marino   if (result)
2908e4b17023SJohn Marino     {
2909e4b17023SJohn Marino       if (TREE_CODE (result) == SSA_NAME)
2910e4b17023SJohn Marino 	changed = visit_copy (PHI_RESULT (phi), result);
2911e4b17023SJohn Marino       else
2912e4b17023SJohn Marino 	changed = set_ssa_val_to (PHI_RESULT (phi), result);
2913e4b17023SJohn Marino     }
2914e4b17023SJohn Marino   else
2915e4b17023SJohn Marino     {
2916e4b17023SJohn Marino       vn_phi_insert (phi, PHI_RESULT (phi));
2917e4b17023SJohn Marino       VN_INFO (PHI_RESULT (phi))->has_constants = false;
2918e4b17023SJohn Marino       VN_INFO (PHI_RESULT (phi))->expr = PHI_RESULT (phi);
2919e4b17023SJohn Marino       changed = set_ssa_val_to (PHI_RESULT (phi), PHI_RESULT (phi));
2920e4b17023SJohn Marino     }
2921e4b17023SJohn Marino 
2922e4b17023SJohn Marino   return changed;
2923e4b17023SJohn Marino }
2924e4b17023SJohn Marino 
2925e4b17023SJohn Marino /* Return true if EXPR contains constants.  */
2926e4b17023SJohn Marino 
2927e4b17023SJohn Marino static bool
expr_has_constants(tree expr)2928e4b17023SJohn Marino expr_has_constants (tree expr)
2929e4b17023SJohn Marino {
2930e4b17023SJohn Marino   switch (TREE_CODE_CLASS (TREE_CODE (expr)))
2931e4b17023SJohn Marino     {
2932e4b17023SJohn Marino     case tcc_unary:
2933e4b17023SJohn Marino       return is_gimple_min_invariant (TREE_OPERAND (expr, 0));
2934e4b17023SJohn Marino 
2935e4b17023SJohn Marino     case tcc_binary:
2936e4b17023SJohn Marino       return is_gimple_min_invariant (TREE_OPERAND (expr, 0))
2937e4b17023SJohn Marino 	|| is_gimple_min_invariant (TREE_OPERAND (expr, 1));
2938e4b17023SJohn Marino       /* Constants inside reference ops are rarely interesting, but
2939e4b17023SJohn Marino 	 it can take a lot of looking to find them.  */
2940e4b17023SJohn Marino     case tcc_reference:
2941e4b17023SJohn Marino     case tcc_declaration:
2942e4b17023SJohn Marino       return false;
2943e4b17023SJohn Marino     default:
2944e4b17023SJohn Marino       return is_gimple_min_invariant (expr);
2945e4b17023SJohn Marino     }
2946e4b17023SJohn Marino   return false;
2947e4b17023SJohn Marino }
2948e4b17023SJohn Marino 
2949e4b17023SJohn Marino /* Return true if STMT contains constants.  */
2950e4b17023SJohn Marino 
2951e4b17023SJohn Marino static bool
stmt_has_constants(gimple stmt)2952e4b17023SJohn Marino stmt_has_constants (gimple stmt)
2953e4b17023SJohn Marino {
2954e4b17023SJohn Marino   if (gimple_code (stmt) != GIMPLE_ASSIGN)
2955e4b17023SJohn Marino     return false;
2956e4b17023SJohn Marino 
2957e4b17023SJohn Marino   switch (get_gimple_rhs_class (gimple_assign_rhs_code (stmt)))
2958e4b17023SJohn Marino     {
2959e4b17023SJohn Marino     case GIMPLE_UNARY_RHS:
2960e4b17023SJohn Marino       return is_gimple_min_invariant (gimple_assign_rhs1 (stmt));
2961e4b17023SJohn Marino 
2962e4b17023SJohn Marino     case GIMPLE_BINARY_RHS:
2963e4b17023SJohn Marino       return (is_gimple_min_invariant (gimple_assign_rhs1 (stmt))
2964e4b17023SJohn Marino 	      || is_gimple_min_invariant (gimple_assign_rhs2 (stmt)));
2965e4b17023SJohn Marino     case GIMPLE_TERNARY_RHS:
2966e4b17023SJohn Marino       return (is_gimple_min_invariant (gimple_assign_rhs1 (stmt))
2967e4b17023SJohn Marino 	      || is_gimple_min_invariant (gimple_assign_rhs2 (stmt))
2968e4b17023SJohn Marino 	      || is_gimple_min_invariant (gimple_assign_rhs3 (stmt)));
2969e4b17023SJohn Marino     case GIMPLE_SINGLE_RHS:
2970e4b17023SJohn Marino       /* Constants inside reference ops are rarely interesting, but
2971e4b17023SJohn Marino 	 it can take a lot of looking to find them.  */
2972e4b17023SJohn Marino       return is_gimple_min_invariant (gimple_assign_rhs1 (stmt));
2973e4b17023SJohn Marino     default:
2974e4b17023SJohn Marino       gcc_unreachable ();
2975e4b17023SJohn Marino     }
2976e4b17023SJohn Marino   return false;
2977e4b17023SJohn Marino }
2978e4b17023SJohn Marino 
2979e4b17023SJohn Marino /* Replace SSA_NAMES in expr with their value numbers, and return the
2980e4b17023SJohn Marino    result.
2981e4b17023SJohn Marino    This is performed in place. */
2982e4b17023SJohn Marino 
2983e4b17023SJohn Marino static tree
valueize_expr(tree expr)2984e4b17023SJohn Marino valueize_expr (tree expr)
2985e4b17023SJohn Marino {
2986e4b17023SJohn Marino   switch (TREE_CODE_CLASS (TREE_CODE (expr)))
2987e4b17023SJohn Marino     {
2988e4b17023SJohn Marino     case tcc_binary:
2989e4b17023SJohn Marino       TREE_OPERAND (expr, 1) = vn_valueize (TREE_OPERAND (expr, 1));
2990e4b17023SJohn Marino       /* Fallthru.  */
2991e4b17023SJohn Marino     case tcc_unary:
2992e4b17023SJohn Marino       TREE_OPERAND (expr, 0) = vn_valueize (TREE_OPERAND (expr, 0));
2993e4b17023SJohn Marino       break;
2994e4b17023SJohn Marino     default:;
2995e4b17023SJohn Marino     }
2996e4b17023SJohn Marino   return expr;
2997e4b17023SJohn Marino }
2998e4b17023SJohn Marino 
2999e4b17023SJohn Marino /* Simplify the binary expression RHS, and return the result if
3000e4b17023SJohn Marino    simplified. */
3001e4b17023SJohn Marino 
3002e4b17023SJohn Marino static tree
simplify_binary_expression(gimple stmt)3003e4b17023SJohn Marino simplify_binary_expression (gimple stmt)
3004e4b17023SJohn Marino {
3005e4b17023SJohn Marino   tree result = NULL_TREE;
3006e4b17023SJohn Marino   tree op0 = gimple_assign_rhs1 (stmt);
3007e4b17023SJohn Marino   tree op1 = gimple_assign_rhs2 (stmt);
3008e4b17023SJohn Marino   enum tree_code code = gimple_assign_rhs_code (stmt);
3009e4b17023SJohn Marino 
3010e4b17023SJohn Marino   /* This will not catch every single case we could combine, but will
3011e4b17023SJohn Marino      catch those with constants.  The goal here is to simultaneously
3012e4b17023SJohn Marino      combine constants between expressions, but avoid infinite
3013e4b17023SJohn Marino      expansion of expressions during simplification.  */
3014e4b17023SJohn Marino   if (TREE_CODE (op0) == SSA_NAME)
3015e4b17023SJohn Marino     {
3016e4b17023SJohn Marino       if (VN_INFO (op0)->has_constants
3017e4b17023SJohn Marino 	  || TREE_CODE_CLASS (code) == tcc_comparison
3018e4b17023SJohn Marino 	  || code == COMPLEX_EXPR)
3019e4b17023SJohn Marino 	op0 = valueize_expr (vn_get_expr_for (op0));
3020e4b17023SJohn Marino       else
3021e4b17023SJohn Marino 	op0 = vn_valueize (op0);
3022e4b17023SJohn Marino     }
3023e4b17023SJohn Marino 
3024e4b17023SJohn Marino   if (TREE_CODE (op1) == SSA_NAME)
3025e4b17023SJohn Marino     {
3026e4b17023SJohn Marino       if (VN_INFO (op1)->has_constants
3027e4b17023SJohn Marino 	  || code == COMPLEX_EXPR)
3028e4b17023SJohn Marino 	op1 = valueize_expr (vn_get_expr_for (op1));
3029e4b17023SJohn Marino       else
3030e4b17023SJohn Marino 	op1 = vn_valueize (op1);
3031e4b17023SJohn Marino     }
3032e4b17023SJohn Marino 
3033e4b17023SJohn Marino   /* Pointer plus constant can be represented as invariant address.
3034e4b17023SJohn Marino      Do so to allow further propatation, see also tree forwprop.  */
3035e4b17023SJohn Marino   if (code == POINTER_PLUS_EXPR
3036e4b17023SJohn Marino       && host_integerp (op1, 1)
3037e4b17023SJohn Marino       && TREE_CODE (op0) == ADDR_EXPR
3038e4b17023SJohn Marino       && is_gimple_min_invariant (op0))
3039e4b17023SJohn Marino     return build_invariant_address (TREE_TYPE (op0),
3040e4b17023SJohn Marino 				    TREE_OPERAND (op0, 0),
3041e4b17023SJohn Marino 				    TREE_INT_CST_LOW (op1));
3042e4b17023SJohn Marino 
3043e4b17023SJohn Marino   /* Avoid folding if nothing changed.  */
3044e4b17023SJohn Marino   if (op0 == gimple_assign_rhs1 (stmt)
3045e4b17023SJohn Marino       && op1 == gimple_assign_rhs2 (stmt))
3046e4b17023SJohn Marino     return NULL_TREE;
3047e4b17023SJohn Marino 
3048e4b17023SJohn Marino   fold_defer_overflow_warnings ();
3049e4b17023SJohn Marino 
3050e4b17023SJohn Marino   result = fold_binary (code, gimple_expr_type (stmt), op0, op1);
3051e4b17023SJohn Marino   if (result)
3052e4b17023SJohn Marino     STRIP_USELESS_TYPE_CONVERSION (result);
3053e4b17023SJohn Marino 
3054e4b17023SJohn Marino   fold_undefer_overflow_warnings (result && valid_gimple_rhs_p (result),
3055e4b17023SJohn Marino 				  stmt, 0);
3056e4b17023SJohn Marino 
3057e4b17023SJohn Marino   /* Make sure result is not a complex expression consisting
3058e4b17023SJohn Marino      of operators of operators (IE (a + b) + (a + c))
3059e4b17023SJohn Marino      Otherwise, we will end up with unbounded expressions if
3060e4b17023SJohn Marino      fold does anything at all.  */
3061e4b17023SJohn Marino   if (result && valid_gimple_rhs_p (result))
3062e4b17023SJohn Marino     return result;
3063e4b17023SJohn Marino 
3064e4b17023SJohn Marino   return NULL_TREE;
3065e4b17023SJohn Marino }
3066e4b17023SJohn Marino 
3067e4b17023SJohn Marino /* Simplify the unary expression RHS, and return the result if
3068e4b17023SJohn Marino    simplified. */
3069e4b17023SJohn Marino 
3070e4b17023SJohn Marino static tree
simplify_unary_expression(gimple stmt)3071e4b17023SJohn Marino simplify_unary_expression (gimple stmt)
3072e4b17023SJohn Marino {
3073e4b17023SJohn Marino   tree result = NULL_TREE;
3074e4b17023SJohn Marino   tree orig_op0, op0 = gimple_assign_rhs1 (stmt);
3075e4b17023SJohn Marino   enum tree_code code = gimple_assign_rhs_code (stmt);
3076e4b17023SJohn Marino 
3077e4b17023SJohn Marino   /* We handle some tcc_reference codes here that are all
3078e4b17023SJohn Marino      GIMPLE_ASSIGN_SINGLE codes.  */
3079e4b17023SJohn Marino   if (code == REALPART_EXPR
3080e4b17023SJohn Marino       || code == IMAGPART_EXPR
3081e4b17023SJohn Marino       || code == VIEW_CONVERT_EXPR
3082e4b17023SJohn Marino       || code == BIT_FIELD_REF)
3083e4b17023SJohn Marino     op0 = TREE_OPERAND (op0, 0);
3084e4b17023SJohn Marino 
3085e4b17023SJohn Marino   if (TREE_CODE (op0) != SSA_NAME)
3086e4b17023SJohn Marino     return NULL_TREE;
3087e4b17023SJohn Marino 
3088e4b17023SJohn Marino   orig_op0 = op0;
3089e4b17023SJohn Marino   if (VN_INFO (op0)->has_constants)
3090e4b17023SJohn Marino     op0 = valueize_expr (vn_get_expr_for (op0));
3091e4b17023SJohn Marino   else if (CONVERT_EXPR_CODE_P (code)
3092e4b17023SJohn Marino 	   || code == REALPART_EXPR
3093e4b17023SJohn Marino 	   || code == IMAGPART_EXPR
3094e4b17023SJohn Marino 	   || code == VIEW_CONVERT_EXPR
3095e4b17023SJohn Marino 	   || code == BIT_FIELD_REF)
3096e4b17023SJohn Marino     {
3097e4b17023SJohn Marino       /* We want to do tree-combining on conversion-like expressions.
3098e4b17023SJohn Marino          Make sure we feed only SSA_NAMEs or constants to fold though.  */
3099e4b17023SJohn Marino       tree tem = valueize_expr (vn_get_expr_for (op0));
3100e4b17023SJohn Marino       if (UNARY_CLASS_P (tem)
3101e4b17023SJohn Marino 	  || BINARY_CLASS_P (tem)
3102e4b17023SJohn Marino 	  || TREE_CODE (tem) == VIEW_CONVERT_EXPR
3103e4b17023SJohn Marino 	  || TREE_CODE (tem) == SSA_NAME
3104e4b17023SJohn Marino 	  || TREE_CODE (tem) == CONSTRUCTOR
3105e4b17023SJohn Marino 	  || is_gimple_min_invariant (tem))
3106e4b17023SJohn Marino 	op0 = tem;
3107e4b17023SJohn Marino     }
3108e4b17023SJohn Marino 
3109e4b17023SJohn Marino   /* Avoid folding if nothing changed, but remember the expression.  */
3110e4b17023SJohn Marino   if (op0 == orig_op0)
3111e4b17023SJohn Marino     return NULL_TREE;
3112e4b17023SJohn Marino 
3113e4b17023SJohn Marino   if (code == BIT_FIELD_REF)
3114e4b17023SJohn Marino     {
3115e4b17023SJohn Marino       tree rhs = gimple_assign_rhs1 (stmt);
3116e4b17023SJohn Marino       result = fold_ternary (BIT_FIELD_REF, TREE_TYPE (rhs),
3117e4b17023SJohn Marino 			     op0, TREE_OPERAND (rhs, 1), TREE_OPERAND (rhs, 2));
3118e4b17023SJohn Marino     }
3119e4b17023SJohn Marino   else
3120e4b17023SJohn Marino     result = fold_unary_ignore_overflow (code, gimple_expr_type (stmt), op0);
3121e4b17023SJohn Marino   if (result)
3122e4b17023SJohn Marino     {
3123e4b17023SJohn Marino       STRIP_USELESS_TYPE_CONVERSION (result);
3124e4b17023SJohn Marino       if (valid_gimple_rhs_p (result))
3125e4b17023SJohn Marino         return result;
3126e4b17023SJohn Marino     }
3127e4b17023SJohn Marino 
3128e4b17023SJohn Marino   return NULL_TREE;
3129e4b17023SJohn Marino }
3130e4b17023SJohn Marino 
3131e4b17023SJohn Marino /* Try to simplify RHS using equivalences and constant folding.  */
3132e4b17023SJohn Marino 
3133e4b17023SJohn Marino static tree
try_to_simplify(gimple stmt)3134e4b17023SJohn Marino try_to_simplify (gimple stmt)
3135e4b17023SJohn Marino {
3136e4b17023SJohn Marino   enum tree_code code = gimple_assign_rhs_code (stmt);
3137e4b17023SJohn Marino   tree tem;
3138e4b17023SJohn Marino 
3139e4b17023SJohn Marino   /* For stores we can end up simplifying a SSA_NAME rhs.  Just return
3140e4b17023SJohn Marino      in this case, there is no point in doing extra work.  */
3141e4b17023SJohn Marino   if (code == SSA_NAME)
3142e4b17023SJohn Marino     return NULL_TREE;
3143e4b17023SJohn Marino 
3144e4b17023SJohn Marino   /* First try constant folding based on our current lattice.  */
3145e4b17023SJohn Marino   tem = gimple_fold_stmt_to_constant_1 (stmt, vn_valueize);
3146e4b17023SJohn Marino   if (tem
3147e4b17023SJohn Marino       && (TREE_CODE (tem) == SSA_NAME
3148e4b17023SJohn Marino 	  || is_gimple_min_invariant (tem)))
3149e4b17023SJohn Marino     return tem;
3150e4b17023SJohn Marino 
3151e4b17023SJohn Marino   /* If that didn't work try combining multiple statements.  */
3152e4b17023SJohn Marino   switch (TREE_CODE_CLASS (code))
3153e4b17023SJohn Marino     {
3154e4b17023SJohn Marino     case tcc_reference:
3155e4b17023SJohn Marino       /* Fallthrough for some unary codes that can operate on registers.  */
3156e4b17023SJohn Marino       if (!(code == REALPART_EXPR
3157e4b17023SJohn Marino 	    || code == IMAGPART_EXPR
3158e4b17023SJohn Marino 	    || code == VIEW_CONVERT_EXPR
3159e4b17023SJohn Marino 	    || code == BIT_FIELD_REF))
3160e4b17023SJohn Marino 	break;
3161e4b17023SJohn Marino       /* We could do a little more with unary ops, if they expand
3162e4b17023SJohn Marino 	 into binary ops, but it's debatable whether it is worth it. */
3163e4b17023SJohn Marino     case tcc_unary:
3164e4b17023SJohn Marino       return simplify_unary_expression (stmt);
3165e4b17023SJohn Marino 
3166e4b17023SJohn Marino     case tcc_comparison:
3167e4b17023SJohn Marino     case tcc_binary:
3168e4b17023SJohn Marino       return simplify_binary_expression (stmt);
3169e4b17023SJohn Marino 
3170e4b17023SJohn Marino     default:
3171e4b17023SJohn Marino       break;
3172e4b17023SJohn Marino     }
3173e4b17023SJohn Marino 
3174e4b17023SJohn Marino   return NULL_TREE;
3175e4b17023SJohn Marino }
3176e4b17023SJohn Marino 
3177e4b17023SJohn Marino /* Visit and value number USE, return true if the value number
3178e4b17023SJohn Marino    changed. */
3179e4b17023SJohn Marino 
3180e4b17023SJohn Marino static bool
visit_use(tree use)3181e4b17023SJohn Marino visit_use (tree use)
3182e4b17023SJohn Marino {
3183e4b17023SJohn Marino   bool changed = false;
3184e4b17023SJohn Marino   gimple stmt = SSA_NAME_DEF_STMT (use);
3185e4b17023SJohn Marino 
3186e4b17023SJohn Marino   VN_INFO (use)->use_processed = true;
3187e4b17023SJohn Marino 
3188e4b17023SJohn Marino   gcc_assert (!SSA_NAME_IN_FREE_LIST (use));
3189e4b17023SJohn Marino   if (dump_file && (dump_flags & TDF_DETAILS)
3190e4b17023SJohn Marino       && !SSA_NAME_IS_DEFAULT_DEF (use))
3191e4b17023SJohn Marino     {
3192e4b17023SJohn Marino       fprintf (dump_file, "Value numbering ");
3193e4b17023SJohn Marino       print_generic_expr (dump_file, use, 0);
3194e4b17023SJohn Marino       fprintf (dump_file, " stmt = ");
3195e4b17023SJohn Marino       print_gimple_stmt (dump_file, stmt, 0, 0);
3196e4b17023SJohn Marino     }
3197e4b17023SJohn Marino 
3198e4b17023SJohn Marino   /* Handle uninitialized uses.  */
3199e4b17023SJohn Marino   if (SSA_NAME_IS_DEFAULT_DEF (use))
3200e4b17023SJohn Marino     changed = set_ssa_val_to (use, use);
3201e4b17023SJohn Marino   else
3202e4b17023SJohn Marino     {
3203e4b17023SJohn Marino       if (gimple_code (stmt) == GIMPLE_PHI)
3204e4b17023SJohn Marino 	changed = visit_phi (stmt);
3205e4b17023SJohn Marino       else if (!gimple_has_lhs (stmt)
3206e4b17023SJohn Marino 	       || gimple_has_volatile_ops (stmt))
3207e4b17023SJohn Marino 	changed = defs_to_varying (stmt);
3208e4b17023SJohn Marino       else if (is_gimple_assign (stmt))
3209e4b17023SJohn Marino 	{
3210e4b17023SJohn Marino 	  enum tree_code code = gimple_assign_rhs_code (stmt);
3211e4b17023SJohn Marino 	  tree lhs = gimple_assign_lhs (stmt);
3212e4b17023SJohn Marino 	  tree rhs1 = gimple_assign_rhs1 (stmt);
3213e4b17023SJohn Marino 	  tree simplified;
3214e4b17023SJohn Marino 
3215e4b17023SJohn Marino 	  /* Shortcut for copies. Simplifying copies is pointless,
3216e4b17023SJohn Marino 	     since we copy the expression and value they represent.  */
3217e4b17023SJohn Marino 	  if (code == SSA_NAME
3218e4b17023SJohn Marino 	      && TREE_CODE (lhs) == SSA_NAME)
3219e4b17023SJohn Marino 	    {
3220e4b17023SJohn Marino 	      changed = visit_copy (lhs, rhs1);
3221e4b17023SJohn Marino 	      goto done;
3222e4b17023SJohn Marino 	    }
3223e4b17023SJohn Marino 	  simplified = try_to_simplify (stmt);
3224e4b17023SJohn Marino 	  if (simplified)
3225e4b17023SJohn Marino 	    {
3226e4b17023SJohn Marino 	      if (dump_file && (dump_flags & TDF_DETAILS))
3227e4b17023SJohn Marino 		{
3228e4b17023SJohn Marino 		  fprintf (dump_file, "RHS ");
3229e4b17023SJohn Marino 		  print_gimple_expr (dump_file, stmt, 0, 0);
3230e4b17023SJohn Marino 		  fprintf (dump_file, " simplified to ");
3231e4b17023SJohn Marino 		  print_generic_expr (dump_file, simplified, 0);
3232e4b17023SJohn Marino 		  if (TREE_CODE (lhs) == SSA_NAME)
3233e4b17023SJohn Marino 		    fprintf (dump_file, " has constants %d\n",
3234e4b17023SJohn Marino 			     expr_has_constants (simplified));
3235e4b17023SJohn Marino 		  else
3236e4b17023SJohn Marino 		    fprintf (dump_file, "\n");
3237e4b17023SJohn Marino 		}
3238e4b17023SJohn Marino 	    }
3239e4b17023SJohn Marino 	  /* Setting value numbers to constants will occasionally
3240e4b17023SJohn Marino 	     screw up phi congruence because constants are not
3241e4b17023SJohn Marino 	     uniquely associated with a single ssa name that can be
3242e4b17023SJohn Marino 	     looked up.  */
3243e4b17023SJohn Marino 	  if (simplified
3244e4b17023SJohn Marino 	      && is_gimple_min_invariant (simplified)
3245e4b17023SJohn Marino 	      && TREE_CODE (lhs) == SSA_NAME)
3246e4b17023SJohn Marino 	    {
3247e4b17023SJohn Marino 	      VN_INFO (lhs)->expr = simplified;
3248e4b17023SJohn Marino 	      VN_INFO (lhs)->has_constants = true;
3249e4b17023SJohn Marino 	      changed = set_ssa_val_to (lhs, simplified);
3250e4b17023SJohn Marino 	      goto done;
3251e4b17023SJohn Marino 	    }
3252e4b17023SJohn Marino 	  else if (simplified
3253e4b17023SJohn Marino 		   && TREE_CODE (simplified) == SSA_NAME
3254e4b17023SJohn Marino 		   && TREE_CODE (lhs) == SSA_NAME)
3255e4b17023SJohn Marino 	    {
3256e4b17023SJohn Marino 	      changed = visit_copy (lhs, simplified);
3257e4b17023SJohn Marino 	      goto done;
3258e4b17023SJohn Marino 	    }
3259e4b17023SJohn Marino 	  else if (simplified)
3260e4b17023SJohn Marino 	    {
3261e4b17023SJohn Marino 	      if (TREE_CODE (lhs) == SSA_NAME)
3262e4b17023SJohn Marino 		{
3263e4b17023SJohn Marino 		  VN_INFO (lhs)->has_constants = expr_has_constants (simplified);
3264e4b17023SJohn Marino 		  /* We have to unshare the expression or else
3265e4b17023SJohn Marino 		     valuizing may change the IL stream.  */
3266e4b17023SJohn Marino 		  VN_INFO (lhs)->expr = unshare_expr (simplified);
3267e4b17023SJohn Marino 		}
3268e4b17023SJohn Marino 	    }
3269e4b17023SJohn Marino 	  else if (stmt_has_constants (stmt)
3270e4b17023SJohn Marino 		   && TREE_CODE (lhs) == SSA_NAME)
3271e4b17023SJohn Marino 	    VN_INFO (lhs)->has_constants = true;
3272e4b17023SJohn Marino 	  else if (TREE_CODE (lhs) == SSA_NAME)
3273e4b17023SJohn Marino 	    {
3274e4b17023SJohn Marino 	      /* We reset expr and constantness here because we may
3275e4b17023SJohn Marino 		 have been value numbering optimistically, and
3276e4b17023SJohn Marino 		 iterating. They may become non-constant in this case,
3277e4b17023SJohn Marino 		 even if they were optimistically constant. */
3278e4b17023SJohn Marino 
3279e4b17023SJohn Marino 	      VN_INFO (lhs)->has_constants = false;
3280e4b17023SJohn Marino 	      VN_INFO (lhs)->expr = NULL_TREE;
3281e4b17023SJohn Marino 	    }
3282e4b17023SJohn Marino 
3283e4b17023SJohn Marino 	  if ((TREE_CODE (lhs) == SSA_NAME
3284e4b17023SJohn Marino 	       /* We can substitute SSA_NAMEs that are live over
3285e4b17023SJohn Marino 		  abnormal edges with their constant value.  */
3286e4b17023SJohn Marino 	       && !(gimple_assign_copy_p (stmt)
3287e4b17023SJohn Marino 		    && is_gimple_min_invariant (rhs1))
3288e4b17023SJohn Marino 	       && !(simplified
3289e4b17023SJohn Marino 		    && is_gimple_min_invariant (simplified))
3290e4b17023SJohn Marino 	       && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (lhs))
3291e4b17023SJohn Marino 	      /* Stores or copies from SSA_NAMEs that are live over
3292e4b17023SJohn Marino 		 abnormal edges are a problem.  */
3293e4b17023SJohn Marino 	      || (code == SSA_NAME
3294e4b17023SJohn Marino 		  && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (rhs1)))
3295e4b17023SJohn Marino 	    changed = defs_to_varying (stmt);
3296e4b17023SJohn Marino 	  else if (REFERENCE_CLASS_P (lhs)
3297e4b17023SJohn Marino 		   || DECL_P (lhs))
3298e4b17023SJohn Marino 	    changed = visit_reference_op_store (lhs, rhs1, stmt);
3299e4b17023SJohn Marino 	  else if (TREE_CODE (lhs) == SSA_NAME)
3300e4b17023SJohn Marino 	    {
3301e4b17023SJohn Marino 	      if ((gimple_assign_copy_p (stmt)
3302e4b17023SJohn Marino 		   && is_gimple_min_invariant (rhs1))
3303e4b17023SJohn Marino 		  || (simplified
3304e4b17023SJohn Marino 		      && is_gimple_min_invariant (simplified)))
3305e4b17023SJohn Marino 		{
3306e4b17023SJohn Marino 		  VN_INFO (lhs)->has_constants = true;
3307e4b17023SJohn Marino 		  if (simplified)
3308e4b17023SJohn Marino 		    changed = set_ssa_val_to (lhs, simplified);
3309e4b17023SJohn Marino 		  else
3310e4b17023SJohn Marino 		    changed = set_ssa_val_to (lhs, rhs1);
3311e4b17023SJohn Marino 		}
3312e4b17023SJohn Marino 	      else
3313e4b17023SJohn Marino 		{
3314e4b17023SJohn Marino 		  switch (get_gimple_rhs_class (code))
3315e4b17023SJohn Marino 		    {
3316e4b17023SJohn Marino 		    case GIMPLE_UNARY_RHS:
3317e4b17023SJohn Marino 		    case GIMPLE_BINARY_RHS:
3318e4b17023SJohn Marino 		    case GIMPLE_TERNARY_RHS:
3319e4b17023SJohn Marino 		      changed = visit_nary_op (lhs, stmt);
3320e4b17023SJohn Marino 		      break;
3321e4b17023SJohn Marino 		    case GIMPLE_SINGLE_RHS:
3322e4b17023SJohn Marino 		      switch (TREE_CODE_CLASS (code))
3323e4b17023SJohn Marino 			{
3324e4b17023SJohn Marino 			case tcc_reference:
3325e4b17023SJohn Marino 			  /* VOP-less references can go through unary case.  */
3326e4b17023SJohn Marino 			  if ((code == REALPART_EXPR
3327e4b17023SJohn Marino 			       || code == IMAGPART_EXPR
3328e4b17023SJohn Marino 			       || code == VIEW_CONVERT_EXPR
3329e4b17023SJohn Marino 			       || code == BIT_FIELD_REF)
3330e4b17023SJohn Marino 			      && TREE_CODE (TREE_OPERAND (rhs1, 0)) == SSA_NAME)
3331e4b17023SJohn Marino 			    {
3332e4b17023SJohn Marino 			      changed = visit_nary_op (lhs, stmt);
3333e4b17023SJohn Marino 			      break;
3334e4b17023SJohn Marino 			    }
3335e4b17023SJohn Marino 			  /* Fallthrough.  */
3336e4b17023SJohn Marino 			case tcc_declaration:
3337e4b17023SJohn Marino 			  changed = visit_reference_op_load (lhs, rhs1, stmt);
3338e4b17023SJohn Marino 			  break;
3339e4b17023SJohn Marino 			default:
3340e4b17023SJohn Marino 			  if (code == ADDR_EXPR)
3341e4b17023SJohn Marino 			    {
3342e4b17023SJohn Marino 			      changed = visit_nary_op (lhs, stmt);
3343e4b17023SJohn Marino 			      break;
3344e4b17023SJohn Marino 			    }
3345e4b17023SJohn Marino 			  else if (code == CONSTRUCTOR)
3346e4b17023SJohn Marino 			    {
3347e4b17023SJohn Marino 			      changed = visit_nary_op (lhs, stmt);
3348e4b17023SJohn Marino 			      break;
3349e4b17023SJohn Marino 			    }
3350e4b17023SJohn Marino 			  changed = defs_to_varying (stmt);
3351e4b17023SJohn Marino 			}
3352e4b17023SJohn Marino 		      break;
3353e4b17023SJohn Marino 		    default:
3354e4b17023SJohn Marino 		      changed = defs_to_varying (stmt);
3355e4b17023SJohn Marino 		      break;
3356e4b17023SJohn Marino 		    }
3357e4b17023SJohn Marino 		}
3358e4b17023SJohn Marino 	    }
3359e4b17023SJohn Marino 	  else
3360e4b17023SJohn Marino 	    changed = defs_to_varying (stmt);
3361e4b17023SJohn Marino 	}
3362e4b17023SJohn Marino       else if (is_gimple_call (stmt))
3363e4b17023SJohn Marino 	{
3364e4b17023SJohn Marino 	  tree lhs = gimple_call_lhs (stmt);
3365e4b17023SJohn Marino 
3366e4b17023SJohn Marino 	  /* ???  We could try to simplify calls.  */
3367e4b17023SJohn Marino 
3368e4b17023SJohn Marino 	  if (stmt_has_constants (stmt)
3369e4b17023SJohn Marino 	      && TREE_CODE (lhs) == SSA_NAME)
3370e4b17023SJohn Marino 	    VN_INFO (lhs)->has_constants = true;
3371e4b17023SJohn Marino 	  else if (TREE_CODE (lhs) == SSA_NAME)
3372e4b17023SJohn Marino 	    {
3373e4b17023SJohn Marino 	      /* We reset expr and constantness here because we may
3374e4b17023SJohn Marino 		 have been value numbering optimistically, and
3375e4b17023SJohn Marino 		 iterating. They may become non-constant in this case,
3376e4b17023SJohn Marino 		 even if they were optimistically constant. */
3377e4b17023SJohn Marino 	      VN_INFO (lhs)->has_constants = false;
3378e4b17023SJohn Marino 	      VN_INFO (lhs)->expr = NULL_TREE;
3379e4b17023SJohn Marino 	    }
3380e4b17023SJohn Marino 
3381e4b17023SJohn Marino 	  if (TREE_CODE (lhs) == SSA_NAME
3382e4b17023SJohn Marino 	      && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (lhs))
3383e4b17023SJohn Marino 	    changed = defs_to_varying (stmt);
3384e4b17023SJohn Marino 	  /* ???  We should handle stores from calls.  */
3385e4b17023SJohn Marino 	  else if (TREE_CODE (lhs) == SSA_NAME)
3386e4b17023SJohn Marino 	    {
3387e4b17023SJohn Marino 	      if (!gimple_call_internal_p (stmt)
3388e4b17023SJohn Marino 		  && gimple_call_flags (stmt) & (ECF_PURE | ECF_CONST))
3389e4b17023SJohn Marino 		changed = visit_reference_op_call (lhs, stmt);
3390e4b17023SJohn Marino 	      else
3391e4b17023SJohn Marino 		changed = defs_to_varying (stmt);
3392e4b17023SJohn Marino 	    }
3393e4b17023SJohn Marino 	  else
3394e4b17023SJohn Marino 	    changed = defs_to_varying (stmt);
3395e4b17023SJohn Marino 	}
3396e4b17023SJohn Marino     }
3397e4b17023SJohn Marino  done:
3398e4b17023SJohn Marino   return changed;
3399e4b17023SJohn Marino }
3400e4b17023SJohn Marino 
3401e4b17023SJohn Marino /* Compare two operands by reverse postorder index */
3402e4b17023SJohn Marino 
3403e4b17023SJohn Marino static int
compare_ops(const void * pa,const void * pb)3404e4b17023SJohn Marino compare_ops (const void *pa, const void *pb)
3405e4b17023SJohn Marino {
3406e4b17023SJohn Marino   const tree opa = *((const tree *)pa);
3407e4b17023SJohn Marino   const tree opb = *((const tree *)pb);
3408e4b17023SJohn Marino   gimple opstmta = SSA_NAME_DEF_STMT (opa);
3409e4b17023SJohn Marino   gimple opstmtb = SSA_NAME_DEF_STMT (opb);
3410e4b17023SJohn Marino   basic_block bba;
3411e4b17023SJohn Marino   basic_block bbb;
3412e4b17023SJohn Marino 
3413e4b17023SJohn Marino   if (gimple_nop_p (opstmta) && gimple_nop_p (opstmtb))
3414e4b17023SJohn Marino     return SSA_NAME_VERSION (opa) - SSA_NAME_VERSION (opb);
3415e4b17023SJohn Marino   else if (gimple_nop_p (opstmta))
3416e4b17023SJohn Marino     return -1;
3417e4b17023SJohn Marino   else if (gimple_nop_p (opstmtb))
3418e4b17023SJohn Marino     return 1;
3419e4b17023SJohn Marino 
3420e4b17023SJohn Marino   bba = gimple_bb (opstmta);
3421e4b17023SJohn Marino   bbb = gimple_bb (opstmtb);
3422e4b17023SJohn Marino 
3423e4b17023SJohn Marino   if (!bba && !bbb)
3424e4b17023SJohn Marino     return SSA_NAME_VERSION (opa) - SSA_NAME_VERSION (opb);
3425e4b17023SJohn Marino   else if (!bba)
3426e4b17023SJohn Marino     return -1;
3427e4b17023SJohn Marino   else if (!bbb)
3428e4b17023SJohn Marino     return 1;
3429e4b17023SJohn Marino 
3430e4b17023SJohn Marino   if (bba == bbb)
3431e4b17023SJohn Marino     {
3432e4b17023SJohn Marino       if (gimple_code (opstmta) == GIMPLE_PHI
3433e4b17023SJohn Marino 	  && gimple_code (opstmtb) == GIMPLE_PHI)
3434e4b17023SJohn Marino 	return SSA_NAME_VERSION (opa) - SSA_NAME_VERSION (opb);
3435e4b17023SJohn Marino       else if (gimple_code (opstmta) == GIMPLE_PHI)
3436e4b17023SJohn Marino 	return -1;
3437e4b17023SJohn Marino       else if (gimple_code (opstmtb) == GIMPLE_PHI)
3438e4b17023SJohn Marino 	return 1;
3439e4b17023SJohn Marino       else if (gimple_uid (opstmta) != gimple_uid (opstmtb))
3440e4b17023SJohn Marino         return gimple_uid (opstmta) - gimple_uid (opstmtb);
3441e4b17023SJohn Marino       else
3442e4b17023SJohn Marino 	return SSA_NAME_VERSION (opa) - SSA_NAME_VERSION (opb);
3443e4b17023SJohn Marino     }
3444e4b17023SJohn Marino   return rpo_numbers[bba->index] - rpo_numbers[bbb->index];
3445e4b17023SJohn Marino }
3446e4b17023SJohn Marino 
3447e4b17023SJohn Marino /* Sort an array containing members of a strongly connected component
3448e4b17023SJohn Marino    SCC so that the members are ordered by RPO number.
3449e4b17023SJohn Marino    This means that when the sort is complete, iterating through the
3450e4b17023SJohn Marino    array will give you the members in RPO order.  */
3451e4b17023SJohn Marino 
3452e4b17023SJohn Marino static void
sort_scc(VEC (tree,heap)* scc)3453e4b17023SJohn Marino sort_scc (VEC (tree, heap) *scc)
3454e4b17023SJohn Marino {
3455e4b17023SJohn Marino   VEC_qsort (tree, scc, compare_ops);
3456e4b17023SJohn Marino }
3457e4b17023SJohn Marino 
3458e4b17023SJohn Marino /* Insert the no longer used nary ONARY to the hash INFO.  */
3459e4b17023SJohn Marino 
3460e4b17023SJohn Marino static void
copy_nary(vn_nary_op_t onary,vn_tables_t info)3461e4b17023SJohn Marino copy_nary (vn_nary_op_t onary, vn_tables_t info)
3462e4b17023SJohn Marino {
3463e4b17023SJohn Marino   size_t size = sizeof_vn_nary_op (onary->length);
3464e4b17023SJohn Marino   vn_nary_op_t nary = alloc_vn_nary_op_noinit (onary->length,
3465e4b17023SJohn Marino 					       &info->nary_obstack);
3466e4b17023SJohn Marino   memcpy (nary, onary, size);
3467e4b17023SJohn Marino   vn_nary_op_insert_into (nary, info->nary, false);
3468e4b17023SJohn Marino }
3469e4b17023SJohn Marino 
3470e4b17023SJohn Marino /* Insert the no longer used phi OPHI to the hash INFO.  */
3471e4b17023SJohn Marino 
3472e4b17023SJohn Marino static void
copy_phi(vn_phi_t ophi,vn_tables_t info)3473e4b17023SJohn Marino copy_phi (vn_phi_t ophi, vn_tables_t info)
3474e4b17023SJohn Marino {
3475e4b17023SJohn Marino   vn_phi_t phi = (vn_phi_t) pool_alloc (info->phis_pool);
3476e4b17023SJohn Marino   void **slot;
3477e4b17023SJohn Marino   memcpy (phi, ophi, sizeof (*phi));
3478e4b17023SJohn Marino   ophi->phiargs = NULL;
3479e4b17023SJohn Marino   slot = htab_find_slot_with_hash (info->phis, phi, phi->hashcode, INSERT);
3480e4b17023SJohn Marino   gcc_assert (!*slot);
3481e4b17023SJohn Marino   *slot = phi;
3482e4b17023SJohn Marino }
3483e4b17023SJohn Marino 
3484e4b17023SJohn Marino /* Insert the no longer used reference OREF to the hash INFO.  */
3485e4b17023SJohn Marino 
3486e4b17023SJohn Marino static void
copy_reference(vn_reference_t oref,vn_tables_t info)3487e4b17023SJohn Marino copy_reference (vn_reference_t oref, vn_tables_t info)
3488e4b17023SJohn Marino {
3489e4b17023SJohn Marino   vn_reference_t ref;
3490e4b17023SJohn Marino   void **slot;
3491e4b17023SJohn Marino   ref = (vn_reference_t) pool_alloc (info->references_pool);
3492e4b17023SJohn Marino   memcpy (ref, oref, sizeof (*ref));
3493e4b17023SJohn Marino   oref->operands = NULL;
3494e4b17023SJohn Marino   slot = htab_find_slot_with_hash (info->references, ref, ref->hashcode,
3495e4b17023SJohn Marino 				   INSERT);
3496e4b17023SJohn Marino   if (*slot)
3497e4b17023SJohn Marino     free_reference (*slot);
3498e4b17023SJohn Marino   *slot = ref;
3499e4b17023SJohn Marino }
3500e4b17023SJohn Marino 
3501e4b17023SJohn Marino /* Process a strongly connected component in the SSA graph.  */
3502e4b17023SJohn Marino 
3503e4b17023SJohn Marino static void
process_scc(VEC (tree,heap)* scc)3504e4b17023SJohn Marino process_scc (VEC (tree, heap) *scc)
3505e4b17023SJohn Marino {
3506e4b17023SJohn Marino   tree var;
3507e4b17023SJohn Marino   unsigned int i;
3508e4b17023SJohn Marino   unsigned int iterations = 0;
3509e4b17023SJohn Marino   bool changed = true;
3510e4b17023SJohn Marino   htab_iterator hi;
3511e4b17023SJohn Marino   vn_nary_op_t nary;
3512e4b17023SJohn Marino   vn_phi_t phi;
3513e4b17023SJohn Marino   vn_reference_t ref;
3514e4b17023SJohn Marino 
3515e4b17023SJohn Marino   /* If the SCC has a single member, just visit it.  */
3516e4b17023SJohn Marino   if (VEC_length (tree, scc) == 1)
3517e4b17023SJohn Marino     {
3518e4b17023SJohn Marino       tree use = VEC_index (tree, scc, 0);
3519e4b17023SJohn Marino       if (VN_INFO (use)->use_processed)
3520e4b17023SJohn Marino 	return;
3521e4b17023SJohn Marino       /* We need to make sure it doesn't form a cycle itself, which can
3522e4b17023SJohn Marino 	 happen for self-referential PHI nodes.  In that case we would
3523e4b17023SJohn Marino 	 end up inserting an expression with VN_TOP operands into the
3524e4b17023SJohn Marino 	 valid table which makes us derive bogus equivalences later.
3525e4b17023SJohn Marino 	 The cheapest way to check this is to assume it for all PHI nodes.  */
3526e4b17023SJohn Marino       if (gimple_code (SSA_NAME_DEF_STMT (use)) == GIMPLE_PHI)
3527e4b17023SJohn Marino 	/* Fallthru to iteration.  */ ;
3528e4b17023SJohn Marino       else
3529e4b17023SJohn Marino 	{
3530e4b17023SJohn Marino 	  visit_use (use);
3531e4b17023SJohn Marino 	  return;
3532e4b17023SJohn Marino 	}
3533e4b17023SJohn Marino     }
3534e4b17023SJohn Marino 
3535e4b17023SJohn Marino   /* Iterate over the SCC with the optimistic table until it stops
3536e4b17023SJohn Marino      changing.  */
3537e4b17023SJohn Marino   current_info = optimistic_info;
3538e4b17023SJohn Marino   while (changed)
3539e4b17023SJohn Marino     {
3540e4b17023SJohn Marino       changed = false;
3541e4b17023SJohn Marino       iterations++;
3542e4b17023SJohn Marino       if (dump_file && (dump_flags & TDF_DETAILS))
3543e4b17023SJohn Marino 	fprintf (dump_file, "Starting iteration %d\n", iterations);
3544e4b17023SJohn Marino       /* As we are value-numbering optimistically we have to
3545e4b17023SJohn Marino 	 clear the expression tables and the simplified expressions
3546e4b17023SJohn Marino 	 in each iteration until we converge.  */
3547e4b17023SJohn Marino       htab_empty (optimistic_info->nary);
3548e4b17023SJohn Marino       htab_empty (optimistic_info->phis);
3549e4b17023SJohn Marino       htab_empty (optimistic_info->references);
3550e4b17023SJohn Marino       obstack_free (&optimistic_info->nary_obstack, NULL);
3551e4b17023SJohn Marino       gcc_obstack_init (&optimistic_info->nary_obstack);
3552e4b17023SJohn Marino       empty_alloc_pool (optimistic_info->phis_pool);
3553e4b17023SJohn Marino       empty_alloc_pool (optimistic_info->references_pool);
3554e4b17023SJohn Marino       FOR_EACH_VEC_ELT (tree, scc, i, var)
3555e4b17023SJohn Marino 	VN_INFO (var)->expr = NULL_TREE;
3556e4b17023SJohn Marino       FOR_EACH_VEC_ELT (tree, scc, i, var)
3557e4b17023SJohn Marino 	changed |= visit_use (var);
3558e4b17023SJohn Marino     }
3559e4b17023SJohn Marino 
3560e4b17023SJohn Marino   statistics_histogram_event (cfun, "SCC iterations", iterations);
3561e4b17023SJohn Marino 
3562e4b17023SJohn Marino   /* Finally, copy the contents of the no longer used optimistic
3563e4b17023SJohn Marino      table to the valid table.  */
3564e4b17023SJohn Marino   FOR_EACH_HTAB_ELEMENT (optimistic_info->nary, nary, vn_nary_op_t, hi)
3565e4b17023SJohn Marino     copy_nary (nary, valid_info);
3566e4b17023SJohn Marino   FOR_EACH_HTAB_ELEMENT (optimistic_info->phis, phi, vn_phi_t, hi)
3567e4b17023SJohn Marino     copy_phi (phi, valid_info);
3568e4b17023SJohn Marino   FOR_EACH_HTAB_ELEMENT (optimistic_info->references, ref, vn_reference_t, hi)
3569e4b17023SJohn Marino     copy_reference (ref, valid_info);
3570e4b17023SJohn Marino 
3571e4b17023SJohn Marino   current_info = valid_info;
3572e4b17023SJohn Marino }
3573e4b17023SJohn Marino 
3574e4b17023SJohn Marino DEF_VEC_O(ssa_op_iter);
3575e4b17023SJohn Marino DEF_VEC_ALLOC_O(ssa_op_iter,heap);
3576e4b17023SJohn Marino 
3577e4b17023SJohn Marino /* Pop the components of the found SCC for NAME off the SCC stack
3578e4b17023SJohn Marino    and process them.  Returns true if all went well, false if
3579e4b17023SJohn Marino    we run into resource limits.  */
3580e4b17023SJohn Marino 
3581e4b17023SJohn Marino static bool
extract_and_process_scc_for_name(tree name)3582e4b17023SJohn Marino extract_and_process_scc_for_name (tree name)
3583e4b17023SJohn Marino {
3584e4b17023SJohn Marino   VEC (tree, heap) *scc = NULL;
3585e4b17023SJohn Marino   tree x;
3586e4b17023SJohn Marino 
3587e4b17023SJohn Marino   /* Found an SCC, pop the components off the SCC stack and
3588e4b17023SJohn Marino      process them.  */
3589e4b17023SJohn Marino   do
3590e4b17023SJohn Marino     {
3591e4b17023SJohn Marino       x = VEC_pop (tree, sccstack);
3592e4b17023SJohn Marino 
3593e4b17023SJohn Marino       VN_INFO (x)->on_sccstack = false;
3594e4b17023SJohn Marino       VEC_safe_push (tree, heap, scc, x);
3595e4b17023SJohn Marino     } while (x != name);
3596e4b17023SJohn Marino 
3597e4b17023SJohn Marino   /* Bail out of SCCVN in case a SCC turns out to be incredibly large.  */
3598e4b17023SJohn Marino   if (VEC_length (tree, scc)
3599e4b17023SJohn Marino       > (unsigned)PARAM_VALUE (PARAM_SCCVN_MAX_SCC_SIZE))
3600e4b17023SJohn Marino     {
3601e4b17023SJohn Marino       if (dump_file)
3602e4b17023SJohn Marino 	fprintf (dump_file, "WARNING: Giving up with SCCVN due to "
3603e4b17023SJohn Marino 		 "SCC size %u exceeding %u\n", VEC_length (tree, scc),
3604e4b17023SJohn Marino 		 (unsigned)PARAM_VALUE (PARAM_SCCVN_MAX_SCC_SIZE));
3605e4b17023SJohn Marino 
3606e4b17023SJohn Marino       VEC_free (tree, heap, scc);
3607e4b17023SJohn Marino       return false;
3608e4b17023SJohn Marino     }
3609e4b17023SJohn Marino 
3610e4b17023SJohn Marino   if (VEC_length (tree, scc) > 1)
3611e4b17023SJohn Marino     sort_scc (scc);
3612e4b17023SJohn Marino 
3613e4b17023SJohn Marino   if (dump_file && (dump_flags & TDF_DETAILS))
3614e4b17023SJohn Marino     print_scc (dump_file, scc);
3615e4b17023SJohn Marino 
3616e4b17023SJohn Marino   process_scc (scc);
3617e4b17023SJohn Marino 
3618e4b17023SJohn Marino   VEC_free (tree, heap, scc);
3619e4b17023SJohn Marino 
3620e4b17023SJohn Marino   return true;
3621e4b17023SJohn Marino }
3622e4b17023SJohn Marino 
3623e4b17023SJohn Marino /* Depth first search on NAME to discover and process SCC's in the SSA
3624e4b17023SJohn Marino    graph.
3625e4b17023SJohn Marino    Execution of this algorithm relies on the fact that the SCC's are
3626e4b17023SJohn Marino    popped off the stack in topological order.
3627e4b17023SJohn Marino    Returns true if successful, false if we stopped processing SCC's due
3628e4b17023SJohn Marino    to resource constraints.  */
3629e4b17023SJohn Marino 
3630e4b17023SJohn Marino static bool
DFS(tree name)3631e4b17023SJohn Marino DFS (tree name)
3632e4b17023SJohn Marino {
3633e4b17023SJohn Marino   VEC(ssa_op_iter, heap) *itervec = NULL;
3634e4b17023SJohn Marino   VEC(tree, heap) *namevec = NULL;
3635e4b17023SJohn Marino   use_operand_p usep = NULL;
3636e4b17023SJohn Marino   gimple defstmt;
3637e4b17023SJohn Marino   tree use;
3638e4b17023SJohn Marino   ssa_op_iter iter;
3639e4b17023SJohn Marino 
3640e4b17023SJohn Marino start_over:
3641e4b17023SJohn Marino   /* SCC info */
3642e4b17023SJohn Marino   VN_INFO (name)->dfsnum = next_dfs_num++;
3643e4b17023SJohn Marino   VN_INFO (name)->visited = true;
3644e4b17023SJohn Marino   VN_INFO (name)->low = VN_INFO (name)->dfsnum;
3645e4b17023SJohn Marino 
3646e4b17023SJohn Marino   VEC_safe_push (tree, heap, sccstack, name);
3647e4b17023SJohn Marino   VN_INFO (name)->on_sccstack = true;
3648e4b17023SJohn Marino   defstmt = SSA_NAME_DEF_STMT (name);
3649e4b17023SJohn Marino 
3650e4b17023SJohn Marino   /* Recursively DFS on our operands, looking for SCC's.  */
3651e4b17023SJohn Marino   if (!gimple_nop_p (defstmt))
3652e4b17023SJohn Marino     {
3653e4b17023SJohn Marino       /* Push a new iterator.  */
3654e4b17023SJohn Marino       if (gimple_code (defstmt) == GIMPLE_PHI)
3655e4b17023SJohn Marino 	usep = op_iter_init_phiuse (&iter, defstmt, SSA_OP_ALL_USES);
3656e4b17023SJohn Marino       else
3657e4b17023SJohn Marino 	usep = op_iter_init_use (&iter, defstmt, SSA_OP_ALL_USES);
3658e4b17023SJohn Marino     }
3659e4b17023SJohn Marino   else
3660e4b17023SJohn Marino     clear_and_done_ssa_iter (&iter);
3661e4b17023SJohn Marino 
3662e4b17023SJohn Marino   while (1)
3663e4b17023SJohn Marino     {
3664e4b17023SJohn Marino       /* If we are done processing uses of a name, go up the stack
3665e4b17023SJohn Marino 	 of iterators and process SCCs as we found them.  */
3666e4b17023SJohn Marino       if (op_iter_done (&iter))
3667e4b17023SJohn Marino 	{
3668e4b17023SJohn Marino 	  /* See if we found an SCC.  */
3669e4b17023SJohn Marino 	  if (VN_INFO (name)->low == VN_INFO (name)->dfsnum)
3670e4b17023SJohn Marino 	    if (!extract_and_process_scc_for_name (name))
3671e4b17023SJohn Marino 	      {
3672e4b17023SJohn Marino 		VEC_free (tree, heap, namevec);
3673e4b17023SJohn Marino 		VEC_free (ssa_op_iter, heap, itervec);
3674e4b17023SJohn Marino 		return false;
3675e4b17023SJohn Marino 	      }
3676e4b17023SJohn Marino 
3677e4b17023SJohn Marino 	  /* Check if we are done.  */
3678e4b17023SJohn Marino 	  if (VEC_empty (tree, namevec))
3679e4b17023SJohn Marino 	    {
3680e4b17023SJohn Marino 	      VEC_free (tree, heap, namevec);
3681e4b17023SJohn Marino 	      VEC_free (ssa_op_iter, heap, itervec);
3682e4b17023SJohn Marino 	      return true;
3683e4b17023SJohn Marino 	    }
3684e4b17023SJohn Marino 
3685e4b17023SJohn Marino 	  /* Restore the last use walker and continue walking there.  */
3686e4b17023SJohn Marino 	  use = name;
3687e4b17023SJohn Marino 	  name = VEC_pop (tree, namevec);
3688e4b17023SJohn Marino 	  memcpy (&iter, VEC_last (ssa_op_iter, itervec),
3689e4b17023SJohn Marino 		  sizeof (ssa_op_iter));
3690e4b17023SJohn Marino 	  VEC_pop (ssa_op_iter, itervec);
3691e4b17023SJohn Marino 	  goto continue_walking;
3692e4b17023SJohn Marino 	}
3693e4b17023SJohn Marino 
3694e4b17023SJohn Marino       use = USE_FROM_PTR (usep);
3695e4b17023SJohn Marino 
3696e4b17023SJohn Marino       /* Since we handle phi nodes, we will sometimes get
3697e4b17023SJohn Marino 	 invariants in the use expression.  */
3698e4b17023SJohn Marino       if (TREE_CODE (use) == SSA_NAME)
3699e4b17023SJohn Marino 	{
3700e4b17023SJohn Marino 	  if (! (VN_INFO (use)->visited))
3701e4b17023SJohn Marino 	    {
3702e4b17023SJohn Marino 	      /* Recurse by pushing the current use walking state on
3703e4b17023SJohn Marino 		 the stack and starting over.  */
3704e4b17023SJohn Marino 	      VEC_safe_push(ssa_op_iter, heap, itervec, &iter);
3705e4b17023SJohn Marino 	      VEC_safe_push(tree, heap, namevec, name);
3706e4b17023SJohn Marino 	      name = use;
3707e4b17023SJohn Marino 	      goto start_over;
3708e4b17023SJohn Marino 
3709e4b17023SJohn Marino continue_walking:
3710e4b17023SJohn Marino 	      VN_INFO (name)->low = MIN (VN_INFO (name)->low,
3711e4b17023SJohn Marino 					 VN_INFO (use)->low);
3712e4b17023SJohn Marino 	    }
3713e4b17023SJohn Marino 	  if (VN_INFO (use)->dfsnum < VN_INFO (name)->dfsnum
3714e4b17023SJohn Marino 	      && VN_INFO (use)->on_sccstack)
3715e4b17023SJohn Marino 	    {
3716e4b17023SJohn Marino 	      VN_INFO (name)->low = MIN (VN_INFO (use)->dfsnum,
3717e4b17023SJohn Marino 					 VN_INFO (name)->low);
3718e4b17023SJohn Marino 	    }
3719e4b17023SJohn Marino 	}
3720e4b17023SJohn Marino 
3721e4b17023SJohn Marino       usep = op_iter_next_use (&iter);
3722e4b17023SJohn Marino     }
3723e4b17023SJohn Marino }
3724e4b17023SJohn Marino 
3725e4b17023SJohn Marino /* Allocate a value number table.  */
3726e4b17023SJohn Marino 
3727e4b17023SJohn Marino static void
allocate_vn_table(vn_tables_t table)3728e4b17023SJohn Marino allocate_vn_table (vn_tables_t table)
3729e4b17023SJohn Marino {
3730e4b17023SJohn Marino   table->phis = htab_create (23, vn_phi_hash, vn_phi_eq, free_phi);
3731e4b17023SJohn Marino   table->nary = htab_create (23, vn_nary_op_hash, vn_nary_op_eq, NULL);
3732e4b17023SJohn Marino   table->references = htab_create (23, vn_reference_hash, vn_reference_eq,
3733e4b17023SJohn Marino 				   free_reference);
3734e4b17023SJohn Marino 
3735e4b17023SJohn Marino   gcc_obstack_init (&table->nary_obstack);
3736e4b17023SJohn Marino   table->phis_pool = create_alloc_pool ("VN phis",
3737e4b17023SJohn Marino 					sizeof (struct vn_phi_s),
3738e4b17023SJohn Marino 					30);
3739e4b17023SJohn Marino   table->references_pool = create_alloc_pool ("VN references",
3740e4b17023SJohn Marino 					      sizeof (struct vn_reference_s),
3741e4b17023SJohn Marino 					      30);
3742e4b17023SJohn Marino }
3743e4b17023SJohn Marino 
3744e4b17023SJohn Marino /* Free a value number table.  */
3745e4b17023SJohn Marino 
3746e4b17023SJohn Marino static void
free_vn_table(vn_tables_t table)3747e4b17023SJohn Marino free_vn_table (vn_tables_t table)
3748e4b17023SJohn Marino {
3749e4b17023SJohn Marino   htab_delete (table->phis);
3750e4b17023SJohn Marino   htab_delete (table->nary);
3751e4b17023SJohn Marino   htab_delete (table->references);
3752e4b17023SJohn Marino   obstack_free (&table->nary_obstack, NULL);
3753e4b17023SJohn Marino   free_alloc_pool (table->phis_pool);
3754e4b17023SJohn Marino   free_alloc_pool (table->references_pool);
3755e4b17023SJohn Marino }
3756e4b17023SJohn Marino 
3757e4b17023SJohn Marino static void
init_scc_vn(void)3758e4b17023SJohn Marino init_scc_vn (void)
3759e4b17023SJohn Marino {
3760e4b17023SJohn Marino   size_t i;
3761e4b17023SJohn Marino   int j;
3762e4b17023SJohn Marino   int *rpo_numbers_temp;
3763e4b17023SJohn Marino 
3764e4b17023SJohn Marino   calculate_dominance_info (CDI_DOMINATORS);
3765e4b17023SJohn Marino   sccstack = NULL;
3766e4b17023SJohn Marino   constant_to_value_id = htab_create (23, vn_constant_hash, vn_constant_eq,
3767e4b17023SJohn Marino 				  free);
3768e4b17023SJohn Marino 
3769e4b17023SJohn Marino   constant_value_ids = BITMAP_ALLOC (NULL);
3770e4b17023SJohn Marino 
3771e4b17023SJohn Marino   next_dfs_num = 1;
3772e4b17023SJohn Marino   next_value_id = 1;
3773e4b17023SJohn Marino 
3774e4b17023SJohn Marino   vn_ssa_aux_table = VEC_alloc (vn_ssa_aux_t, heap, num_ssa_names + 1);
3775e4b17023SJohn Marino   /* VEC_alloc doesn't actually grow it to the right size, it just
3776e4b17023SJohn Marino      preallocates the space to do so.  */
3777e4b17023SJohn Marino   VEC_safe_grow_cleared (vn_ssa_aux_t, heap, vn_ssa_aux_table, num_ssa_names + 1);
3778e4b17023SJohn Marino   gcc_obstack_init (&vn_ssa_aux_obstack);
3779e4b17023SJohn Marino 
3780e4b17023SJohn Marino   shared_lookup_phiargs = NULL;
3781e4b17023SJohn Marino   shared_lookup_references = NULL;
3782e4b17023SJohn Marino   rpo_numbers = XCNEWVEC (int, last_basic_block + NUM_FIXED_BLOCKS);
3783e4b17023SJohn Marino   rpo_numbers_temp = XCNEWVEC (int, last_basic_block + NUM_FIXED_BLOCKS);
3784e4b17023SJohn Marino   pre_and_rev_post_order_compute (NULL, rpo_numbers_temp, false);
3785e4b17023SJohn Marino 
3786e4b17023SJohn Marino   /* RPO numbers is an array of rpo ordering, rpo[i] = bb means that
3787e4b17023SJohn Marino      the i'th block in RPO order is bb.  We want to map bb's to RPO
3788e4b17023SJohn Marino      numbers, so we need to rearrange this array.  */
3789e4b17023SJohn Marino   for (j = 0; j < n_basic_blocks - NUM_FIXED_BLOCKS; j++)
3790e4b17023SJohn Marino     rpo_numbers[rpo_numbers_temp[j]] = j;
3791e4b17023SJohn Marino 
3792e4b17023SJohn Marino   XDELETE (rpo_numbers_temp);
3793e4b17023SJohn Marino 
3794e4b17023SJohn Marino   VN_TOP = create_tmp_var_raw (void_type_node, "vn_top");
3795e4b17023SJohn Marino 
3796e4b17023SJohn Marino   /* Create the VN_INFO structures, and initialize value numbers to
3797e4b17023SJohn Marino      TOP.  */
3798e4b17023SJohn Marino   for (i = 0; i < num_ssa_names; i++)
3799e4b17023SJohn Marino     {
3800e4b17023SJohn Marino       tree name = ssa_name (i);
3801e4b17023SJohn Marino       if (name)
3802e4b17023SJohn Marino 	{
3803e4b17023SJohn Marino 	  VN_INFO_GET (name)->valnum = VN_TOP;
3804e4b17023SJohn Marino 	  VN_INFO (name)->expr = NULL_TREE;
3805e4b17023SJohn Marino 	  VN_INFO (name)->value_id = 0;
3806e4b17023SJohn Marino 	}
3807e4b17023SJohn Marino     }
3808e4b17023SJohn Marino 
3809e4b17023SJohn Marino   renumber_gimple_stmt_uids ();
3810e4b17023SJohn Marino 
3811e4b17023SJohn Marino   /* Create the valid and optimistic value numbering tables.  */
3812e4b17023SJohn Marino   valid_info = XCNEW (struct vn_tables_s);
3813e4b17023SJohn Marino   allocate_vn_table (valid_info);
3814e4b17023SJohn Marino   optimistic_info = XCNEW (struct vn_tables_s);
3815e4b17023SJohn Marino   allocate_vn_table (optimistic_info);
3816e4b17023SJohn Marino }
3817e4b17023SJohn Marino 
3818e4b17023SJohn Marino void
free_scc_vn(void)3819e4b17023SJohn Marino free_scc_vn (void)
3820e4b17023SJohn Marino {
3821e4b17023SJohn Marino   size_t i;
3822e4b17023SJohn Marino 
3823e4b17023SJohn Marino   htab_delete (constant_to_value_id);
3824e4b17023SJohn Marino   BITMAP_FREE (constant_value_ids);
3825e4b17023SJohn Marino   VEC_free (tree, heap, shared_lookup_phiargs);
3826e4b17023SJohn Marino   VEC_free (vn_reference_op_s, heap, shared_lookup_references);
3827e4b17023SJohn Marino   XDELETEVEC (rpo_numbers);
3828e4b17023SJohn Marino 
3829e4b17023SJohn Marino   for (i = 0; i < num_ssa_names; i++)
3830e4b17023SJohn Marino     {
3831e4b17023SJohn Marino       tree name = ssa_name (i);
3832e4b17023SJohn Marino       if (name
3833e4b17023SJohn Marino 	  && VN_INFO (name)->needs_insertion)
3834e4b17023SJohn Marino 	release_ssa_name (name);
3835e4b17023SJohn Marino     }
3836e4b17023SJohn Marino   obstack_free (&vn_ssa_aux_obstack, NULL);
3837e4b17023SJohn Marino   VEC_free (vn_ssa_aux_t, heap, vn_ssa_aux_table);
3838e4b17023SJohn Marino 
3839e4b17023SJohn Marino   VEC_free (tree, heap, sccstack);
3840e4b17023SJohn Marino   free_vn_table (valid_info);
3841e4b17023SJohn Marino   XDELETE (valid_info);
3842e4b17023SJohn Marino   free_vn_table (optimistic_info);
3843e4b17023SJohn Marino   XDELETE (optimistic_info);
3844e4b17023SJohn Marino }
3845e4b17023SJohn Marino 
3846e4b17023SJohn Marino /* Set *ID if we computed something useful in RESULT.  */
3847e4b17023SJohn Marino 
3848e4b17023SJohn Marino static void
set_value_id_for_result(tree result,unsigned int * id)3849e4b17023SJohn Marino set_value_id_for_result (tree result, unsigned int *id)
3850e4b17023SJohn Marino {
3851e4b17023SJohn Marino   if (result)
3852e4b17023SJohn Marino     {
3853e4b17023SJohn Marino       if (TREE_CODE (result) == SSA_NAME)
3854e4b17023SJohn Marino 	*id = VN_INFO (result)->value_id;
3855e4b17023SJohn Marino       else if (is_gimple_min_invariant (result))
3856e4b17023SJohn Marino 	*id = get_or_alloc_constant_value_id (result);
3857e4b17023SJohn Marino     }
3858e4b17023SJohn Marino }
3859e4b17023SJohn Marino 
3860e4b17023SJohn Marino /* Set the value ids in the valid hash tables.  */
3861e4b17023SJohn Marino 
3862e4b17023SJohn Marino static void
set_hashtable_value_ids(void)3863e4b17023SJohn Marino set_hashtable_value_ids (void)
3864e4b17023SJohn Marino {
3865e4b17023SJohn Marino   htab_iterator hi;
3866e4b17023SJohn Marino   vn_nary_op_t vno;
3867e4b17023SJohn Marino   vn_reference_t vr;
3868e4b17023SJohn Marino   vn_phi_t vp;
3869e4b17023SJohn Marino 
3870e4b17023SJohn Marino   /* Now set the value ids of the things we had put in the hash
3871e4b17023SJohn Marino      table.  */
3872e4b17023SJohn Marino 
3873e4b17023SJohn Marino   FOR_EACH_HTAB_ELEMENT (valid_info->nary,
3874e4b17023SJohn Marino 			 vno, vn_nary_op_t, hi)
3875e4b17023SJohn Marino     set_value_id_for_result (vno->result, &vno->value_id);
3876e4b17023SJohn Marino 
3877e4b17023SJohn Marino   FOR_EACH_HTAB_ELEMENT (valid_info->phis,
3878e4b17023SJohn Marino 			 vp, vn_phi_t, hi)
3879e4b17023SJohn Marino     set_value_id_for_result (vp->result, &vp->value_id);
3880e4b17023SJohn Marino 
3881e4b17023SJohn Marino   FOR_EACH_HTAB_ELEMENT (valid_info->references,
3882e4b17023SJohn Marino 			 vr, vn_reference_t, hi)
3883e4b17023SJohn Marino     set_value_id_for_result (vr->result, &vr->value_id);
3884e4b17023SJohn Marino }
3885e4b17023SJohn Marino 
3886e4b17023SJohn Marino /* Do SCCVN.  Returns true if it finished, false if we bailed out
3887e4b17023SJohn Marino    due to resource constraints.  DEFAULT_VN_WALK_KIND_ specifies
3888e4b17023SJohn Marino    how we use the alias oracle walking during the VN process.  */
3889e4b17023SJohn Marino 
3890e4b17023SJohn Marino bool
run_scc_vn(vn_lookup_kind default_vn_walk_kind_)3891e4b17023SJohn Marino run_scc_vn (vn_lookup_kind default_vn_walk_kind_)
3892e4b17023SJohn Marino {
3893e4b17023SJohn Marino   size_t i;
3894e4b17023SJohn Marino   tree param;
3895e4b17023SJohn Marino   bool changed = true;
3896e4b17023SJohn Marino 
3897e4b17023SJohn Marino   default_vn_walk_kind = default_vn_walk_kind_;
3898e4b17023SJohn Marino 
3899e4b17023SJohn Marino   init_scc_vn ();
3900e4b17023SJohn Marino   current_info = valid_info;
3901e4b17023SJohn Marino 
3902e4b17023SJohn Marino   for (param = DECL_ARGUMENTS (current_function_decl);
3903e4b17023SJohn Marino        param;
3904e4b17023SJohn Marino        param = DECL_CHAIN (param))
3905e4b17023SJohn Marino     {
3906e4b17023SJohn Marino       if (gimple_default_def (cfun, param) != NULL)
3907e4b17023SJohn Marino 	{
3908e4b17023SJohn Marino 	  tree def = gimple_default_def (cfun, param);
3909e4b17023SJohn Marino 	  VN_INFO (def)->valnum = def;
3910e4b17023SJohn Marino 	}
3911e4b17023SJohn Marino     }
3912e4b17023SJohn Marino 
3913e4b17023SJohn Marino   for (i = 1; i < num_ssa_names; ++i)
3914e4b17023SJohn Marino     {
3915e4b17023SJohn Marino       tree name = ssa_name (i);
3916e4b17023SJohn Marino       if (name
3917e4b17023SJohn Marino 	  && VN_INFO (name)->visited == false
3918e4b17023SJohn Marino 	  && !has_zero_uses (name))
3919e4b17023SJohn Marino 	if (!DFS (name))
3920e4b17023SJohn Marino 	  {
3921e4b17023SJohn Marino 	    free_scc_vn ();
3922e4b17023SJohn Marino 	    return false;
3923e4b17023SJohn Marino 	  }
3924e4b17023SJohn Marino     }
3925e4b17023SJohn Marino 
3926e4b17023SJohn Marino   /* Initialize the value ids.  */
3927e4b17023SJohn Marino 
3928e4b17023SJohn Marino   for (i = 1; i < num_ssa_names; ++i)
3929e4b17023SJohn Marino     {
3930e4b17023SJohn Marino       tree name = ssa_name (i);
3931e4b17023SJohn Marino       vn_ssa_aux_t info;
3932e4b17023SJohn Marino       if (!name)
3933e4b17023SJohn Marino 	continue;
3934e4b17023SJohn Marino       info = VN_INFO (name);
3935e4b17023SJohn Marino       if (info->valnum == name
3936e4b17023SJohn Marino 	  || info->valnum == VN_TOP)
3937e4b17023SJohn Marino 	info->value_id = get_next_value_id ();
3938e4b17023SJohn Marino       else if (is_gimple_min_invariant (info->valnum))
3939e4b17023SJohn Marino 	info->value_id = get_or_alloc_constant_value_id (info->valnum);
3940e4b17023SJohn Marino     }
3941e4b17023SJohn Marino 
3942e4b17023SJohn Marino   /* Propagate until they stop changing.  */
3943e4b17023SJohn Marino   while (changed)
3944e4b17023SJohn Marino     {
3945e4b17023SJohn Marino       changed = false;
3946e4b17023SJohn Marino       for (i = 1; i < num_ssa_names; ++i)
3947e4b17023SJohn Marino 	{
3948e4b17023SJohn Marino 	  tree name = ssa_name (i);
3949e4b17023SJohn Marino 	  vn_ssa_aux_t info;
3950e4b17023SJohn Marino 	  if (!name)
3951e4b17023SJohn Marino 	    continue;
3952e4b17023SJohn Marino 	  info = VN_INFO (name);
3953e4b17023SJohn Marino 	  if (TREE_CODE (info->valnum) == SSA_NAME
3954e4b17023SJohn Marino 	      && info->valnum != name
3955e4b17023SJohn Marino 	      && info->value_id != VN_INFO (info->valnum)->value_id)
3956e4b17023SJohn Marino 	    {
3957e4b17023SJohn Marino 	      changed = true;
3958e4b17023SJohn Marino 	      info->value_id = VN_INFO (info->valnum)->value_id;
3959e4b17023SJohn Marino 	    }
3960e4b17023SJohn Marino 	}
3961e4b17023SJohn Marino     }
3962e4b17023SJohn Marino 
3963e4b17023SJohn Marino   set_hashtable_value_ids ();
3964e4b17023SJohn Marino 
3965e4b17023SJohn Marino   if (dump_file && (dump_flags & TDF_DETAILS))
3966e4b17023SJohn Marino     {
3967e4b17023SJohn Marino       fprintf (dump_file, "Value numbers:\n");
3968e4b17023SJohn Marino       for (i = 0; i < num_ssa_names; i++)
3969e4b17023SJohn Marino 	{
3970e4b17023SJohn Marino 	  tree name = ssa_name (i);
3971e4b17023SJohn Marino 	  if (name
3972e4b17023SJohn Marino 	      && VN_INFO (name)->visited
3973e4b17023SJohn Marino 	      && SSA_VAL (name) != name)
3974e4b17023SJohn Marino 	    {
3975e4b17023SJohn Marino 	      print_generic_expr (dump_file, name, 0);
3976e4b17023SJohn Marino 	      fprintf (dump_file, " = ");
3977e4b17023SJohn Marino 	      print_generic_expr (dump_file, SSA_VAL (name), 0);
3978e4b17023SJohn Marino 	      fprintf (dump_file, "\n");
3979e4b17023SJohn Marino 	    }
3980e4b17023SJohn Marino 	}
3981e4b17023SJohn Marino     }
3982e4b17023SJohn Marino 
3983e4b17023SJohn Marino   return true;
3984e4b17023SJohn Marino }
3985e4b17023SJohn Marino 
3986e4b17023SJohn Marino /* Return the maximum value id we have ever seen.  */
3987e4b17023SJohn Marino 
3988e4b17023SJohn Marino unsigned int
get_max_value_id(void)3989e4b17023SJohn Marino get_max_value_id (void)
3990e4b17023SJohn Marino {
3991e4b17023SJohn Marino   return next_value_id;
3992e4b17023SJohn Marino }
3993e4b17023SJohn Marino 
3994e4b17023SJohn Marino /* Return the next unique value id.  */
3995e4b17023SJohn Marino 
3996e4b17023SJohn Marino unsigned int
get_next_value_id(void)3997e4b17023SJohn Marino get_next_value_id (void)
3998e4b17023SJohn Marino {
3999e4b17023SJohn Marino   return next_value_id++;
4000e4b17023SJohn Marino }
4001e4b17023SJohn Marino 
4002e4b17023SJohn Marino 
4003e4b17023SJohn Marino /* Compare two expressions E1 and E2 and return true if they are equal.  */
4004e4b17023SJohn Marino 
4005e4b17023SJohn Marino bool
expressions_equal_p(tree e1,tree e2)4006e4b17023SJohn Marino expressions_equal_p (tree e1, tree e2)
4007e4b17023SJohn Marino {
4008e4b17023SJohn Marino   /* The obvious case.  */
4009e4b17023SJohn Marino   if (e1 == e2)
4010e4b17023SJohn Marino     return true;
4011e4b17023SJohn Marino 
4012e4b17023SJohn Marino   /* If only one of them is null, they cannot be equal.  */
4013e4b17023SJohn Marino   if (!e1 || !e2)
4014e4b17023SJohn Marino     return false;
4015e4b17023SJohn Marino 
4016e4b17023SJohn Marino   /* Now perform the actual comparison.  */
4017e4b17023SJohn Marino   if (TREE_CODE (e1) == TREE_CODE (e2)
4018e4b17023SJohn Marino       && operand_equal_p (e1, e2, OEP_PURE_SAME))
4019e4b17023SJohn Marino     return true;
4020e4b17023SJohn Marino 
4021e4b17023SJohn Marino   return false;
4022e4b17023SJohn Marino }
4023e4b17023SJohn Marino 
4024e4b17023SJohn Marino 
4025e4b17023SJohn Marino /* Return true if the nary operation NARY may trap.  This is a copy
4026e4b17023SJohn Marino    of stmt_could_throw_1_p adjusted to the SCCVN IL.  */
4027e4b17023SJohn Marino 
4028e4b17023SJohn Marino bool
vn_nary_may_trap(vn_nary_op_t nary)4029e4b17023SJohn Marino vn_nary_may_trap (vn_nary_op_t nary)
4030e4b17023SJohn Marino {
4031e4b17023SJohn Marino   tree type;
4032e4b17023SJohn Marino   tree rhs2 = NULL_TREE;
4033e4b17023SJohn Marino   bool honor_nans = false;
4034e4b17023SJohn Marino   bool honor_snans = false;
4035e4b17023SJohn Marino   bool fp_operation = false;
4036e4b17023SJohn Marino   bool honor_trapv = false;
4037e4b17023SJohn Marino   bool handled, ret;
4038e4b17023SJohn Marino   unsigned i;
4039e4b17023SJohn Marino 
4040e4b17023SJohn Marino   if (TREE_CODE_CLASS (nary->opcode) == tcc_comparison
4041e4b17023SJohn Marino       || TREE_CODE_CLASS (nary->opcode) == tcc_unary
4042e4b17023SJohn Marino       || TREE_CODE_CLASS (nary->opcode) == tcc_binary)
4043e4b17023SJohn Marino     {
4044e4b17023SJohn Marino       type = nary->type;
4045e4b17023SJohn Marino       fp_operation = FLOAT_TYPE_P (type);
4046e4b17023SJohn Marino       if (fp_operation)
4047e4b17023SJohn Marino 	{
4048e4b17023SJohn Marino 	  honor_nans = flag_trapping_math && !flag_finite_math_only;
4049e4b17023SJohn Marino 	  honor_snans = flag_signaling_nans != 0;
4050e4b17023SJohn Marino 	}
4051e4b17023SJohn Marino       else if (INTEGRAL_TYPE_P (type)
4052e4b17023SJohn Marino 	       && TYPE_OVERFLOW_TRAPS (type))
4053e4b17023SJohn Marino 	honor_trapv = true;
4054e4b17023SJohn Marino     }
4055e4b17023SJohn Marino   if (nary->length >= 2)
4056e4b17023SJohn Marino     rhs2 = nary->op[1];
4057e4b17023SJohn Marino   ret = operation_could_trap_helper_p (nary->opcode, fp_operation,
4058e4b17023SJohn Marino 				       honor_trapv,
4059e4b17023SJohn Marino 				       honor_nans, honor_snans, rhs2,
4060e4b17023SJohn Marino 				       &handled);
4061e4b17023SJohn Marino   if (handled
4062e4b17023SJohn Marino       && ret)
4063e4b17023SJohn Marino     return true;
4064e4b17023SJohn Marino 
4065e4b17023SJohn Marino   for (i = 0; i < nary->length; ++i)
4066e4b17023SJohn Marino     if (tree_could_trap_p (nary->op[i]))
4067e4b17023SJohn Marino       return true;
4068e4b17023SJohn Marino 
4069e4b17023SJohn Marino   return false;
4070e4b17023SJohn Marino }
4071