Mercurial > hg > CbC > CbC_gcc
comparison gcc/ipa-cp.c @ 111:04ced10e8804
gcc 7
author | kono |
---|---|
date | Fri, 27 Oct 2017 22:46:09 +0900 |
parents | f6334be47118 |
children | 84e7813d76e9 |
comparison
equal
deleted
inserted
replaced
68:561a7518be6b | 111:04ced10e8804 |
---|---|
1 /* Interprocedural constant propagation | 1 /* Interprocedural constant propagation |
2 Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011 | 2 Copyright (C) 2005-2017 Free Software Foundation, Inc. |
3 Free Software Foundation, Inc. | 3 |
4 Contributed by Razya Ladelsky <RAZYA@il.ibm.com> | 4 Contributed by Razya Ladelsky <RAZYA@il.ibm.com> and Martin Jambor |
5 <mjambor@suse.cz> | |
5 | 6 |
6 This file is part of GCC. | 7 This file is part of GCC. |
7 | 8 |
8 GCC is free software; you can redistribute it and/or modify it under | 9 GCC is free software; you can redistribute it and/or modify it under |
9 the terms of the GNU General Public License as published by the Free | 10 the terms of the GNU General Public License as published by the Free |
17 | 18 |
18 You should have received a copy of the GNU General Public License | 19 You should have received a copy of the GNU General Public License |
19 along with GCC; see the file COPYING3. If not see | 20 along with GCC; see the file COPYING3. If not see |
20 <http://www.gnu.org/licenses/>. */ | 21 <http://www.gnu.org/licenses/>. */ |
21 | 22 |
22 /* Interprocedural constant propagation. The aim of interprocedural constant | 23 /* Interprocedural constant propagation (IPA-CP). |
23 propagation (IPCP) is to find which function's argument has the same | 24 |
24 constant value in each invocation throughout the whole program. For example, | 25 The goal of this transformation is to |
25 consider the following program: | 26 |
26 | 27 1) discover functions which are always invoked with some arguments with the |
27 int g (int y) | 28 same known constant values and modify the functions so that the |
28 { | 29 subsequent optimizations can take advantage of the knowledge, and |
29 printf ("value is %d",y); | 30 |
30 } | 31 2) partial specialization - create specialized versions of functions |
31 | 32 transformed in this way if some parameters are known constants only in |
32 int f (int x) | 33 certain contexts but the estimated tradeoff between speedup and cost size |
33 { | 34 is deemed good. |
34 g (x); | 35 |
35 } | 36 The algorithm also propagates types and attempts to perform type based |
36 | 37 devirtualization. Types are propagated much like constants. |
37 int h (int y) | 38 |
38 { | 39 The algorithm basically consists of three stages. In the first, functions |
39 g (y); | 40 are analyzed one at a time and jump functions are constructed for all known |
40 } | 41 call-sites. In the second phase, the pass propagates information from the |
41 | 42 jump functions across the call to reveal what values are available at what |
42 void main (void) | 43 call sites, performs estimations of effects of known values on functions and |
43 { | 44 their callees, and finally decides what specialized extra versions should be |
44 f (3); | 45 created. In the third, the special versions materialize and appropriate |
45 h (3); | 46 calls are redirected. |
46 } | 47 |
47 | 48 The algorithm used is to a certain extent based on "Interprocedural Constant |
48 | 49 Propagation", by David Callahan, Keith D Cooper, Ken Kennedy, Linda Torczon, |
49 The IPCP algorithm will find that g's formal argument y is always called | 50 Comp86, pg 152-161 and "A Methodology for Procedure Cloning" by Keith D |
50 with the value 3. | 51 Cooper, Mary W. Hall, and Ken Kennedy. |
51 | 52 |
52 The algorithm used is based on "Interprocedural Constant Propagation", by | |
53 David Callahan, Keith D Cooper, Ken Kennedy, Linda Torczon, Comp86, pg | |
54 152-161 | |
55 | |
56 The optimization is divided into three stages: | |
57 | 53 |
58 First stage - intraprocedural analysis | 54 First stage - intraprocedural analysis |
59 ======================================= | 55 ======================================= |
56 | |
60 This phase computes jump_function and modification flags. | 57 This phase computes jump_function and modification flags. |
61 | 58 |
62 A jump function for a callsite represents the values passed as an actual | 59 A jump function for a call-site represents the values passed as an actual |
63 arguments of a given callsite. There are three types of values: | 60 arguments of a given call-site. In principle, there are three types of |
64 Pass through - the caller's formal parameter is passed as an actual argument. | 61 values: |
62 | |
63 Pass through - the caller's formal parameter is passed as an actual | |
64 argument, plus an operation on it can be performed. | |
65 Constant - a constant is passed as an actual argument. | 65 Constant - a constant is passed as an actual argument. |
66 Unknown - neither of the above. | 66 Unknown - neither of the above. |
67 | 67 |
68 The jump function info, ipa_jump_func, is stored in ipa_edge_args | 68 All jump function types are described in detail in ipa-prop.h, together with |
69 structure (defined in ipa_prop.h and pointed to by cgraph_node->aux) | 69 the data structures that represent them and methods of accessing them. |
70 modified_flags are defined in ipa_node_params structure | 70 |
71 (defined in ipa_prop.h and pointed to by cgraph_edge->aux). | 71 ipcp_generate_summary() is the main function of the first stage. |
72 | |
73 -ipcp_generate_summary() is the first stage driver. | |
74 | 72 |
75 Second stage - interprocedural analysis | 73 Second stage - interprocedural analysis |
76 ======================================== | 74 ======================================== |
77 This phase does the interprocedural constant propagation. | 75 |
78 It computes lattices for all formal parameters in the program | 76 This stage is itself divided into two phases. In the first, we propagate |
79 and their value that may be: | 77 known values over the call graph, in the second, we make cloning decisions. |
80 TOP - unknown. | 78 It uses a different algorithm than the original Callahan's paper. |
81 BOTTOM - non constant. | 79 |
82 CONSTANT - constant value. | 80 First, we traverse the functions topologically from callers to callees and, |
83 | 81 for each strongly connected component (SCC), we propagate constants |
84 Lattice describing a formal parameter p will have a constant value if all | 82 according to previously computed jump functions. We also record what known |
85 callsites invoking this function have the same constant value passed to p. | 83 values depend on other known values and estimate local effects. Finally, we |
86 | 84 propagate cumulative information about these effects from dependent values |
87 The lattices are stored in ipcp_lattice which is itself in ipa_node_params | 85 to those on which they depend. |
88 structure (defined in ipa_prop.h and pointed to by cgraph_edge->aux). | 86 |
89 | 87 Second, we again traverse the call graph in the same topological order and |
90 -ipcp_iterate_stage() is the second stage driver. | 88 make clones for functions which we know are called with the same values in |
91 | 89 all contexts and decide about extra specialized clones of functions just for |
92 Third phase - transformation of function code | 90 some contexts - these decisions are based on both local estimates and |
91 cumulative estimates propagated from callees. | |
92 | |
93 ipcp_propagate_stage() and ipcp_decision_stage() together constitute the | |
94 third stage. | |
95 | |
96 Third phase - materialization of clones, call statement updates. | |
93 ============================================ | 97 ============================================ |
94 Propagates the constant-valued formals into the function. | 98 |
95 For each function whose parameters are constants, we create its clone. | 99 This stage is currently performed by call graph code (mainly in cgraphunit.c |
96 | 100 and tree-inline.c) according to instructions inserted to the call graph by |
97 Then we process the clone in two ways: | 101 the second stage. */ |
98 1. We insert an assignment statement 'parameter = const' at the beginning | |
99 of the cloned function. | |
100 2. For read-only parameters that do not live in memory, we replace all their | |
101 uses with the constant. | |
102 | |
103 We also need to modify some callsites to call the cloned functions instead | |
104 of the original ones. For a callsite passing an argument found to be a | |
105 constant by IPCP, there are two different cases to handle: | |
106 1. A constant is passed as an argument. In this case the callsite in the | |
107 should be redirected to call the cloned callee. | |
108 2. A parameter (of the caller) passed as an argument (pass through | |
109 argument). In such cases both the caller and the callee have clones and | |
110 only the callsite in the cloned caller is redirected to call to the | |
111 cloned callee. | |
112 | |
113 This update is done in two steps: First all cloned functions are created | |
114 during a traversal of the call graph, during which all callsites are | |
115 redirected to call the cloned function. Then the callsites are traversed | |
116 and many calls redirected back to fit the description above. | |
117 | |
118 -ipcp_insert_stage() is the third phase driver. | |
119 | |
120 | |
121 This pass also performs devirtualization - turns virtual calls into direct | |
122 ones if it can prove that all invocations of the function call the same | |
123 callee. This is achieved by building a list of all base types (actually, | |
124 their BINFOs) that individual parameters can have in an iterative matter | |
125 just like propagating scalar constants and then examining whether virtual | |
126 calls which take a parameter as their object fold to the same target for all | |
127 these types. If we cannot enumerate all types or there is a type which does | |
128 not have any BINFO associated with it, cannot_devirtualize of the associated | |
129 parameter descriptor is set which is an equivalent of BOTTOM lattice value | |
130 in standard IPA constant propagation. | |
131 */ | |
132 | 102 |
133 #include "config.h" | 103 #include "config.h" |
134 #include "system.h" | 104 #include "system.h" |
135 #include "coretypes.h" | 105 #include "coretypes.h" |
106 #include "backend.h" | |
136 #include "tree.h" | 107 #include "tree.h" |
137 #include "target.h" | 108 #include "gimple-expr.h" |
138 #include "gimple.h" | 109 #include "predict.h" |
110 #include "alloc-pool.h" | |
111 #include "tree-pass.h" | |
139 #include "cgraph.h" | 112 #include "cgraph.h" |
113 #include "diagnostic.h" | |
114 #include "fold-const.h" | |
115 #include "gimple-fold.h" | |
116 #include "symbol-summary.h" | |
117 #include "tree-vrp.h" | |
140 #include "ipa-prop.h" | 118 #include "ipa-prop.h" |
141 #include "tree-flow.h" | |
142 #include "tree-pass.h" | |
143 #include "flags.h" | |
144 #include "timevar.h" | |
145 #include "diagnostic.h" | |
146 #include "tree-pretty-print.h" | 119 #include "tree-pretty-print.h" |
147 #include "tree-dump.h" | |
148 #include "tree-inline.h" | 120 #include "tree-inline.h" |
149 #include "fibheap.h" | |
150 #include "params.h" | 121 #include "params.h" |
151 | 122 #include "ipa-fnsummary.h" |
152 /* Number of functions identified as candidates for cloning. When not cloning | 123 #include "ipa-utils.h" |
153 we can simplify iterate stage not forcing it to go through the decision | 124 #include "tree-ssa-ccp.h" |
154 on what is profitable and what not. */ | 125 #include "stringpool.h" |
155 static int n_cloning_candidates; | 126 #include "attribs.h" |
127 | |
128 template <typename valtype> class ipcp_value; | |
129 | |
130 /* Describes a particular source for an IPA-CP value. */ | |
131 | |
132 template <typename valtype> | |
133 class ipcp_value_source | |
134 { | |
135 public: | |
136 /* Aggregate offset of the source, negative if the source is scalar value of | |
137 the argument itself. */ | |
138 HOST_WIDE_INT offset; | |
139 /* The incoming edge that brought the value. */ | |
140 cgraph_edge *cs; | |
141 /* If the jump function that resulted into his value was a pass-through or an | |
142 ancestor, this is the ipcp_value of the caller from which the described | |
143 value has been derived. Otherwise it is NULL. */ | |
144 ipcp_value<valtype> *val; | |
145 /* Next pointer in a linked list of sources of a value. */ | |
146 ipcp_value_source *next; | |
147 /* If the jump function that resulted into his value was a pass-through or an | |
148 ancestor, this is the index of the parameter of the caller the jump | |
149 function references. */ | |
150 int index; | |
151 }; | |
152 | |
153 /* Common ancestor for all ipcp_value instantiations. */ | |
154 | |
155 class ipcp_value_base | |
156 { | |
157 public: | |
158 /* Time benefit and size cost that specializing the function for this value | |
159 would bring about in this function alone. */ | |
160 int local_time_benefit, local_size_cost; | |
161 /* Time benefit and size cost that specializing the function for this value | |
162 can bring about in it's callees (transitively). */ | |
163 int prop_time_benefit, prop_size_cost; | |
164 | |
165 ipcp_value_base () | |
166 : local_time_benefit (0), local_size_cost (0), | |
167 prop_time_benefit (0), prop_size_cost (0) {} | |
168 }; | |
169 | |
170 /* Describes one particular value stored in struct ipcp_lattice. */ | |
171 | |
172 template <typename valtype> | |
173 class ipcp_value : public ipcp_value_base | |
174 { | |
175 public: | |
176 /* The actual value for the given parameter. */ | |
177 valtype value; | |
178 /* The list of sources from which this value originates. */ | |
179 ipcp_value_source <valtype> *sources; | |
180 /* Next pointers in a linked list of all values in a lattice. */ | |
181 ipcp_value *next; | |
182 /* Next pointers in a linked list of values in a strongly connected component | |
183 of values. */ | |
184 ipcp_value *scc_next; | |
185 /* Next pointers in a linked list of SCCs of values sorted topologically | |
186 according their sources. */ | |
187 ipcp_value *topo_next; | |
188 /* A specialized node created for this value, NULL if none has been (so far) | |
189 created. */ | |
190 cgraph_node *spec_node; | |
191 /* Depth first search number and low link for topological sorting of | |
192 values. */ | |
193 int dfs, low_link; | |
194 /* True if this valye is currently on the topo-sort stack. */ | |
195 bool on_stack; | |
196 | |
197 ipcp_value() | |
198 : sources (0), next (0), scc_next (0), topo_next (0), | |
199 spec_node (0), dfs (0), low_link (0), on_stack (false) {} | |
200 | |
201 void add_source (cgraph_edge *cs, ipcp_value *src_val, int src_idx, | |
202 HOST_WIDE_INT offset); | |
203 }; | |
204 | |
205 /* Lattice describing potential values of a formal parameter of a function, or | |
206 a part of an aggregate. TOP is represented by a lattice with zero values | |
207 and with contains_variable and bottom flags cleared. BOTTOM is represented | |
208 by a lattice with the bottom flag set. In that case, values and | |
209 contains_variable flag should be disregarded. */ | |
210 | |
211 template <typename valtype> | |
212 class ipcp_lattice | |
213 { | |
214 public: | |
215 /* The list of known values and types in this lattice. Note that values are | |
216 not deallocated if a lattice is set to bottom because there may be value | |
217 sources referencing them. */ | |
218 ipcp_value<valtype> *values; | |
219 /* Number of known values and types in this lattice. */ | |
220 int values_count; | |
221 /* The lattice contains a variable component (in addition to values). */ | |
222 bool contains_variable; | |
223 /* The value of the lattice is bottom (i.e. variable and unusable for any | |
224 propagation). */ | |
225 bool bottom; | |
226 | |
227 inline bool is_single_const (); | |
228 inline bool set_to_bottom (); | |
229 inline bool set_contains_variable (); | |
230 bool add_value (valtype newval, cgraph_edge *cs, | |
231 ipcp_value<valtype> *src_val = NULL, | |
232 int src_idx = 0, HOST_WIDE_INT offset = -1); | |
233 void print (FILE * f, bool dump_sources, bool dump_benefits); | |
234 }; | |
235 | |
236 /* Lattice of tree values with an offset to describe a part of an | |
237 aggregate. */ | |
238 | |
239 class ipcp_agg_lattice : public ipcp_lattice<tree> | |
240 { | |
241 public: | |
242 /* Offset that is being described by this lattice. */ | |
243 HOST_WIDE_INT offset; | |
244 /* Size so that we don't have to re-compute it every time we traverse the | |
245 list. Must correspond to TYPE_SIZE of all lat values. */ | |
246 HOST_WIDE_INT size; | |
247 /* Next element of the linked list. */ | |
248 struct ipcp_agg_lattice *next; | |
249 }; | |
250 | |
251 /* Lattice of known bits, only capable of holding one value. | |
252 Bitwise constant propagation propagates which bits of a | |
253 value are constant. | |
254 For eg: | |
255 int f(int x) | |
256 { | |
257 return some_op (x); | |
258 } | |
259 | |
260 int f1(int y) | |
261 { | |
262 if (cond) | |
263 return f (y & 0xff); | |
264 else | |
265 return f (y & 0xf); | |
266 } | |
267 | |
268 In the above case, the param 'x' will always have all | |
269 the bits (except the bits in lsb) set to 0. | |
270 Hence the mask of 'x' would be 0xff. The mask | |
271 reflects that the bits in lsb are unknown. | |
272 The actual propagated value is given by m_value & ~m_mask. */ | |
273 | |
274 class ipcp_bits_lattice | |
275 { | |
276 public: | |
277 bool bottom_p () { return m_lattice_val == IPA_BITS_VARYING; } | |
278 bool top_p () { return m_lattice_val == IPA_BITS_UNDEFINED; } | |
279 bool constant_p () { return m_lattice_val == IPA_BITS_CONSTANT; } | |
280 bool set_to_bottom (); | |
281 bool set_to_constant (widest_int, widest_int); | |
282 | |
283 widest_int get_value () { return m_value; } | |
284 widest_int get_mask () { return m_mask; } | |
285 | |
286 bool meet_with (ipcp_bits_lattice& other, unsigned, signop, | |
287 enum tree_code, tree); | |
288 | |
289 bool meet_with (widest_int, widest_int, unsigned); | |
290 | |
291 void print (FILE *); | |
292 | |
293 private: | |
294 enum { IPA_BITS_UNDEFINED, IPA_BITS_CONSTANT, IPA_BITS_VARYING } m_lattice_val; | |
295 | |
296 /* Similar to ccp_lattice_t, mask represents which bits of value are constant. | |
297 If a bit in mask is set to 0, then the corresponding bit in | |
298 value is known to be constant. */ | |
299 widest_int m_value, m_mask; | |
300 | |
301 bool meet_with_1 (widest_int, widest_int, unsigned); | |
302 void get_value_and_mask (tree, widest_int *, widest_int *); | |
303 }; | |
304 | |
305 /* Lattice of value ranges. */ | |
306 | |
307 class ipcp_vr_lattice | |
308 { | |
309 public: | |
310 value_range m_vr; | |
311 | |
312 inline bool bottom_p () const; | |
313 inline bool top_p () const; | |
314 inline bool set_to_bottom (); | |
315 bool meet_with (const value_range *p_vr); | |
316 bool meet_with (const ipcp_vr_lattice &other); | |
317 void init () { m_vr.type = VR_UNDEFINED; } | |
318 void print (FILE * f); | |
319 | |
320 private: | |
321 bool meet_with_1 (const value_range *other_vr); | |
322 }; | |
323 | |
324 /* Structure containing lattices for a parameter itself and for pieces of | |
325 aggregates that are passed in the parameter or by a reference in a parameter | |
326 plus some other useful flags. */ | |
327 | |
328 class ipcp_param_lattices | |
329 { | |
330 public: | |
331 /* Lattice describing the value of the parameter itself. */ | |
332 ipcp_lattice<tree> itself; | |
333 /* Lattice describing the polymorphic contexts of a parameter. */ | |
334 ipcp_lattice<ipa_polymorphic_call_context> ctxlat; | |
335 /* Lattices describing aggregate parts. */ | |
336 ipcp_agg_lattice *aggs; | |
337 /* Lattice describing known bits. */ | |
338 ipcp_bits_lattice bits_lattice; | |
339 /* Lattice describing value range. */ | |
340 ipcp_vr_lattice m_value_range; | |
341 /* Number of aggregate lattices */ | |
342 int aggs_count; | |
343 /* True if aggregate data were passed by reference (as opposed to by | |
344 value). */ | |
345 bool aggs_by_ref; | |
346 /* All aggregate lattices contain a variable component (in addition to | |
347 values). */ | |
348 bool aggs_contain_variable; | |
349 /* The value of all aggregate lattices is bottom (i.e. variable and unusable | |
350 for any propagation). */ | |
351 bool aggs_bottom; | |
352 | |
353 /* There is a virtual call based on this parameter. */ | |
354 bool virt_call; | |
355 }; | |
356 | |
357 /* Allocation pools for values and their sources in ipa-cp. */ | |
358 | |
359 object_allocator<ipcp_value<tree> > ipcp_cst_values_pool | |
360 ("IPA-CP constant values"); | |
361 | |
362 object_allocator<ipcp_value<ipa_polymorphic_call_context> > | |
363 ipcp_poly_ctx_values_pool ("IPA-CP polymorphic contexts"); | |
364 | |
365 object_allocator<ipcp_value_source<tree> > ipcp_sources_pool | |
366 ("IPA-CP value sources"); | |
367 | |
368 object_allocator<ipcp_agg_lattice> ipcp_agg_lattice_pool | |
369 ("IPA_CP aggregate lattices"); | |
156 | 370 |
157 /* Maximal count found in program. */ | 371 /* Maximal count found in program. */ |
158 static gcov_type max_count; | 372 |
159 | 373 static profile_count max_count; |
160 /* Cgraph nodes that has been completely replaced by cloning during iterate | 374 |
161 * stage and will be removed after ipcp is finished. */ | 375 /* Original overall size of the program. */ |
162 static bitmap dead_nodes; | 376 |
163 | 377 static long overall_size, max_new_size; |
164 static void ipcp_print_profile_data (FILE *); | 378 |
165 static void ipcp_function_scale_print (FILE *); | 379 /* Return the param lattices structure corresponding to the Ith formal |
166 | 380 parameter of the function described by INFO. */ |
167 /* Get the original node field of ipa_node_params associated with node NODE. */ | 381 static inline struct ipcp_param_lattices * |
168 static inline struct cgraph_node * | 382 ipa_get_parm_lattices (struct ipa_node_params *info, int i) |
169 ipcp_get_orig_node (struct cgraph_node *node) | 383 { |
170 { | 384 gcc_assert (i >= 0 && i < ipa_get_param_count (info)); |
171 return IPA_NODE_REF (node)->ipcp_orig_node; | 385 gcc_checking_assert (!info->ipcp_orig_node); |
172 } | 386 gcc_checking_assert (info->lattices); |
173 | 387 return &(info->lattices[i]); |
174 /* Return true if NODE describes a cloned/versioned function. */ | 388 } |
389 | |
390 /* Return the lattice corresponding to the scalar value of the Ith formal | |
391 parameter of the function described by INFO. */ | |
392 static inline ipcp_lattice<tree> * | |
393 ipa_get_scalar_lat (struct ipa_node_params *info, int i) | |
394 { | |
395 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i); | |
396 return &plats->itself; | |
397 } | |
398 | |
399 /* Return the lattice corresponding to the scalar value of the Ith formal | |
400 parameter of the function described by INFO. */ | |
401 static inline ipcp_lattice<ipa_polymorphic_call_context> * | |
402 ipa_get_poly_ctx_lat (struct ipa_node_params *info, int i) | |
403 { | |
404 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i); | |
405 return &plats->ctxlat; | |
406 } | |
407 | |
408 /* Return the lattice corresponding to the value range of the Ith formal | |
409 parameter of the function described by INFO. */ | |
410 | |
411 static inline ipcp_vr_lattice * | |
412 ipa_get_vr_lat (struct ipa_node_params *info, int i) | |
413 { | |
414 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i); | |
415 return &plats->m_value_range; | |
416 } | |
417 | |
418 /* Return whether LAT is a lattice with a single constant and without an | |
419 undefined value. */ | |
420 | |
421 template <typename valtype> | |
422 inline bool | |
423 ipcp_lattice<valtype>::is_single_const () | |
424 { | |
425 if (bottom || contains_variable || values_count != 1) | |
426 return false; | |
427 else | |
428 return true; | |
429 } | |
430 | |
431 /* Print V which is extracted from a value in a lattice to F. */ | |
432 | |
433 static void | |
434 print_ipcp_constant_value (FILE * f, tree v) | |
435 { | |
436 if (TREE_CODE (v) == ADDR_EXPR | |
437 && TREE_CODE (TREE_OPERAND (v, 0)) == CONST_DECL) | |
438 { | |
439 fprintf (f, "& "); | |
440 print_generic_expr (f, DECL_INITIAL (TREE_OPERAND (v, 0))); | |
441 } | |
442 else | |
443 print_generic_expr (f, v); | |
444 } | |
445 | |
446 /* Print V which is extracted from a value in a lattice to F. */ | |
447 | |
448 static void | |
449 print_ipcp_constant_value (FILE * f, ipa_polymorphic_call_context v) | |
450 { | |
451 v.dump(f, false); | |
452 } | |
453 | |
454 /* Print a lattice LAT to F. */ | |
455 | |
456 template <typename valtype> | |
457 void | |
458 ipcp_lattice<valtype>::print (FILE * f, bool dump_sources, bool dump_benefits) | |
459 { | |
460 ipcp_value<valtype> *val; | |
461 bool prev = false; | |
462 | |
463 if (bottom) | |
464 { | |
465 fprintf (f, "BOTTOM\n"); | |
466 return; | |
467 } | |
468 | |
469 if (!values_count && !contains_variable) | |
470 { | |
471 fprintf (f, "TOP\n"); | |
472 return; | |
473 } | |
474 | |
475 if (contains_variable) | |
476 { | |
477 fprintf (f, "VARIABLE"); | |
478 prev = true; | |
479 if (dump_benefits) | |
480 fprintf (f, "\n"); | |
481 } | |
482 | |
483 for (val = values; val; val = val->next) | |
484 { | |
485 if (dump_benefits && prev) | |
486 fprintf (f, " "); | |
487 else if (!dump_benefits && prev) | |
488 fprintf (f, ", "); | |
489 else | |
490 prev = true; | |
491 | |
492 print_ipcp_constant_value (f, val->value); | |
493 | |
494 if (dump_sources) | |
495 { | |
496 ipcp_value_source<valtype> *s; | |
497 | |
498 fprintf (f, " [from:"); | |
499 for (s = val->sources; s; s = s->next) | |
500 fprintf (f, " %i(%i)", s->cs->caller->order, | |
501 s->cs->frequency); | |
502 fprintf (f, "]"); | |
503 } | |
504 | |
505 if (dump_benefits) | |
506 fprintf (f, " [loc_time: %i, loc_size: %i, " | |
507 "prop_time: %i, prop_size: %i]\n", | |
508 val->local_time_benefit, val->local_size_cost, | |
509 val->prop_time_benefit, val->prop_size_cost); | |
510 } | |
511 if (!dump_benefits) | |
512 fprintf (f, "\n"); | |
513 } | |
514 | |
515 void | |
516 ipcp_bits_lattice::print (FILE *f) | |
517 { | |
518 if (top_p ()) | |
519 fprintf (f, " Bits unknown (TOP)\n"); | |
520 else if (bottom_p ()) | |
521 fprintf (f, " Bits unusable (BOTTOM)\n"); | |
522 else | |
523 { | |
524 fprintf (f, " Bits: value = "); print_hex (get_value (), f); | |
525 fprintf (f, ", mask = "); print_hex (get_mask (), f); | |
526 fprintf (f, "\n"); | |
527 } | |
528 } | |
529 | |
530 /* Print value range lattice to F. */ | |
531 | |
532 void | |
533 ipcp_vr_lattice::print (FILE * f) | |
534 { | |
535 dump_value_range (f, &m_vr); | |
536 } | |
537 | |
538 /* Print all ipcp_lattices of all functions to F. */ | |
539 | |
540 static void | |
541 print_all_lattices (FILE * f, bool dump_sources, bool dump_benefits) | |
542 { | |
543 struct cgraph_node *node; | |
544 int i, count; | |
545 | |
546 fprintf (f, "\nLattices:\n"); | |
547 FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node) | |
548 { | |
549 struct ipa_node_params *info; | |
550 | |
551 info = IPA_NODE_REF (node); | |
552 fprintf (f, " Node: %s:\n", node->dump_name ()); | |
553 count = ipa_get_param_count (info); | |
554 for (i = 0; i < count; i++) | |
555 { | |
556 struct ipcp_agg_lattice *aglat; | |
557 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i); | |
558 fprintf (f, " param [%d]: ", i); | |
559 plats->itself.print (f, dump_sources, dump_benefits); | |
560 fprintf (f, " ctxs: "); | |
561 plats->ctxlat.print (f, dump_sources, dump_benefits); | |
562 plats->bits_lattice.print (f); | |
563 fprintf (f, " "); | |
564 plats->m_value_range.print (f); | |
565 fprintf (f, "\n"); | |
566 if (plats->virt_call) | |
567 fprintf (f, " virt_call flag set\n"); | |
568 | |
569 if (plats->aggs_bottom) | |
570 { | |
571 fprintf (f, " AGGS BOTTOM\n"); | |
572 continue; | |
573 } | |
574 if (plats->aggs_contain_variable) | |
575 fprintf (f, " AGGS VARIABLE\n"); | |
576 for (aglat = plats->aggs; aglat; aglat = aglat->next) | |
577 { | |
578 fprintf (f, " %soffset " HOST_WIDE_INT_PRINT_DEC ": ", | |
579 plats->aggs_by_ref ? "ref " : "", aglat->offset); | |
580 aglat->print (f, dump_sources, dump_benefits); | |
581 } | |
582 } | |
583 } | |
584 } | |
585 | |
586 /* Determine whether it is at all technically possible to create clones of NODE | |
587 and store this information in the ipa_node_params structure associated | |
588 with NODE. */ | |
589 | |
590 static void | |
591 determine_versionability (struct cgraph_node *node, | |
592 struct ipa_node_params *info) | |
593 { | |
594 const char *reason = NULL; | |
595 | |
596 /* There are a number of generic reasons functions cannot be versioned. We | |
597 also cannot remove parameters if there are type attributes such as fnspec | |
598 present. */ | |
599 if (node->alias || node->thunk.thunk_p) | |
600 reason = "alias or thunk"; | |
601 else if (!node->local.versionable) | |
602 reason = "not a tree_versionable_function"; | |
603 else if (node->get_availability () <= AVAIL_INTERPOSABLE) | |
604 reason = "insufficient body availability"; | |
605 else if (!opt_for_fn (node->decl, optimize) | |
606 || !opt_for_fn (node->decl, flag_ipa_cp)) | |
607 reason = "non-optimized function"; | |
608 else if (lookup_attribute ("omp declare simd", DECL_ATTRIBUTES (node->decl))) | |
609 { | |
610 /* Ideally we should clone the SIMD clones themselves and create | |
611 vector copies of them, so IPA-cp and SIMD clones can happily | |
612 coexist, but that may not be worth the effort. */ | |
613 reason = "function has SIMD clones"; | |
614 } | |
615 else if (lookup_attribute ("target_clones", DECL_ATTRIBUTES (node->decl))) | |
616 { | |
617 /* Ideally we should clone the target clones themselves and create | |
618 copies of them, so IPA-cp and target clones can happily | |
619 coexist, but that may not be worth the effort. */ | |
620 reason = "function target_clones attribute"; | |
621 } | |
622 /* Don't clone decls local to a comdat group; it breaks and for C++ | |
623 decloned constructors, inlining is always better anyway. */ | |
624 else if (node->comdat_local_p ()) | |
625 reason = "comdat-local function"; | |
626 else if (node->calls_comdat_local) | |
627 { | |
628 /* TODO: call is versionable if we make sure that all | |
629 callers are inside of a comdat group. */ | |
630 reason = "calls comdat-local function"; | |
631 } | |
632 | |
633 if (reason && dump_file && !node->alias && !node->thunk.thunk_p) | |
634 fprintf (dump_file, "Function %s is not versionable, reason: %s.\n", | |
635 node->dump_name (), reason); | |
636 | |
637 info->versionable = (reason == NULL); | |
638 } | |
639 | |
640 /* Return true if it is at all technically possible to create clones of a | |
641 NODE. */ | |
642 | |
643 static bool | |
644 ipcp_versionable_function_p (struct cgraph_node *node) | |
645 { | |
646 return IPA_NODE_REF (node)->versionable; | |
647 } | |
648 | |
649 /* Structure holding accumulated information about callers of a node. */ | |
650 | |
651 struct caller_statistics | |
652 { | |
653 profile_count count_sum; | |
654 int n_calls, n_hot_calls, freq_sum; | |
655 }; | |
656 | |
657 /* Initialize fields of STAT to zeroes. */ | |
658 | |
659 static inline void | |
660 init_caller_stats (struct caller_statistics *stats) | |
661 { | |
662 stats->count_sum = profile_count::zero (); | |
663 stats->n_calls = 0; | |
664 stats->n_hot_calls = 0; | |
665 stats->freq_sum = 0; | |
666 } | |
667 | |
668 /* Worker callback of cgraph_for_node_and_aliases accumulating statistics of | |
669 non-thunk incoming edges to NODE. */ | |
670 | |
671 static bool | |
672 gather_caller_stats (struct cgraph_node *node, void *data) | |
673 { | |
674 struct caller_statistics *stats = (struct caller_statistics *) data; | |
675 struct cgraph_edge *cs; | |
676 | |
677 for (cs = node->callers; cs; cs = cs->next_caller) | |
678 if (!cs->caller->thunk.thunk_p) | |
679 { | |
680 if (cs->count.initialized_p ()) | |
681 stats->count_sum += cs->count; | |
682 stats->freq_sum += cs->frequency; | |
683 stats->n_calls++; | |
684 if (cs->maybe_hot_p ()) | |
685 stats->n_hot_calls ++; | |
686 } | |
687 return false; | |
688 | |
689 } | |
690 | |
691 /* Return true if this NODE is viable candidate for cloning. */ | |
692 | |
693 static bool | |
694 ipcp_cloning_candidate_p (struct cgraph_node *node) | |
695 { | |
696 struct caller_statistics stats; | |
697 | |
698 gcc_checking_assert (node->has_gimple_body_p ()); | |
699 | |
700 if (!opt_for_fn (node->decl, flag_ipa_cp_clone)) | |
701 { | |
702 if (dump_file) | |
703 fprintf (dump_file, "Not considering %s for cloning; " | |
704 "-fipa-cp-clone disabled.\n", | |
705 node->name ()); | |
706 return false; | |
707 } | |
708 | |
709 if (node->optimize_for_size_p ()) | |
710 { | |
711 if (dump_file) | |
712 fprintf (dump_file, "Not considering %s for cloning; " | |
713 "optimizing it for size.\n", | |
714 node->name ()); | |
715 return false; | |
716 } | |
717 | |
718 init_caller_stats (&stats); | |
719 node->call_for_symbol_thunks_and_aliases (gather_caller_stats, &stats, false); | |
720 | |
721 if (ipa_fn_summaries->get (node)->self_size < stats.n_calls) | |
722 { | |
723 if (dump_file) | |
724 fprintf (dump_file, "Considering %s for cloning; code might shrink.\n", | |
725 node->name ()); | |
726 return true; | |
727 } | |
728 | |
729 /* When profile is available and function is hot, propagate into it even if | |
730 calls seems cold; constant propagation can improve function's speed | |
731 significantly. */ | |
732 if (max_count > profile_count::zero ()) | |
733 { | |
734 if (stats.count_sum > node->count.apply_scale (90, 100)) | |
735 { | |
736 if (dump_file) | |
737 fprintf (dump_file, "Considering %s for cloning; " | |
738 "usually called directly.\n", | |
739 node->name ()); | |
740 return true; | |
741 } | |
742 } | |
743 if (!stats.n_hot_calls) | |
744 { | |
745 if (dump_file) | |
746 fprintf (dump_file, "Not considering %s for cloning; no hot calls.\n", | |
747 node->name ()); | |
748 return false; | |
749 } | |
750 if (dump_file) | |
751 fprintf (dump_file, "Considering %s for cloning.\n", | |
752 node->name ()); | |
753 return true; | |
754 } | |
755 | |
756 template <typename valtype> | |
757 class value_topo_info | |
758 { | |
759 public: | |
760 /* Head of the linked list of topologically sorted values. */ | |
761 ipcp_value<valtype> *values_topo; | |
762 /* Stack for creating SCCs, represented by a linked list too. */ | |
763 ipcp_value<valtype> *stack; | |
764 /* Counter driving the algorithm in add_val_to_toposort. */ | |
765 int dfs_counter; | |
766 | |
767 value_topo_info () : values_topo (NULL), stack (NULL), dfs_counter (0) | |
768 {} | |
769 void add_val (ipcp_value<valtype> *cur_val); | |
770 void propagate_effects (); | |
771 }; | |
772 | |
773 /* Arrays representing a topological ordering of call graph nodes and a stack | |
774 of nodes used during constant propagation and also data required to perform | |
775 topological sort of values and propagation of benefits in the determined | |
776 order. */ | |
777 | |
778 class ipa_topo_info | |
779 { | |
780 public: | |
781 /* Array with obtained topological order of cgraph nodes. */ | |
782 struct cgraph_node **order; | |
783 /* Stack of cgraph nodes used during propagation within SCC until all values | |
784 in the SCC stabilize. */ | |
785 struct cgraph_node **stack; | |
786 int nnodes, stack_top; | |
787 | |
788 value_topo_info<tree> constants; | |
789 value_topo_info<ipa_polymorphic_call_context> contexts; | |
790 | |
791 ipa_topo_info () : order(NULL), stack(NULL), nnodes(0), stack_top(0), | |
792 constants () | |
793 {} | |
794 }; | |
795 | |
796 /* Allocate the arrays in TOPO and topologically sort the nodes into order. */ | |
797 | |
798 static void | |
799 build_toporder_info (struct ipa_topo_info *topo) | |
800 { | |
801 topo->order = XCNEWVEC (struct cgraph_node *, symtab->cgraph_count); | |
802 topo->stack = XCNEWVEC (struct cgraph_node *, symtab->cgraph_count); | |
803 | |
804 gcc_checking_assert (topo->stack_top == 0); | |
805 topo->nnodes = ipa_reduced_postorder (topo->order, true, true, NULL); | |
806 } | |
807 | |
808 /* Free information about strongly connected components and the arrays in | |
809 TOPO. */ | |
810 | |
811 static void | |
812 free_toporder_info (struct ipa_topo_info *topo) | |
813 { | |
814 ipa_free_postorder_info (); | |
815 free (topo->order); | |
816 free (topo->stack); | |
817 } | |
818 | |
819 /* Add NODE to the stack in TOPO, unless it is already there. */ | |
820 | |
821 static inline void | |
822 push_node_to_stack (struct ipa_topo_info *topo, struct cgraph_node *node) | |
823 { | |
824 struct ipa_node_params *info = IPA_NODE_REF (node); | |
825 if (info->node_enqueued) | |
826 return; | |
827 info->node_enqueued = 1; | |
828 topo->stack[topo->stack_top++] = node; | |
829 } | |
830 | |
831 /* Pop a node from the stack in TOPO and return it or return NULL if the stack | |
832 is empty. */ | |
833 | |
834 static struct cgraph_node * | |
835 pop_node_from_stack (struct ipa_topo_info *topo) | |
836 { | |
837 if (topo->stack_top) | |
838 { | |
839 struct cgraph_node *node; | |
840 topo->stack_top--; | |
841 node = topo->stack[topo->stack_top]; | |
842 IPA_NODE_REF (node)->node_enqueued = 0; | |
843 return node; | |
844 } | |
845 else | |
846 return NULL; | |
847 } | |
848 | |
849 /* Set lattice LAT to bottom and return true if it previously was not set as | |
850 such. */ | |
851 | |
852 template <typename valtype> | |
853 inline bool | |
854 ipcp_lattice<valtype>::set_to_bottom () | |
855 { | |
856 bool ret = !bottom; | |
857 bottom = true; | |
858 return ret; | |
859 } | |
860 | |
861 /* Mark lattice as containing an unknown value and return true if it previously | |
862 was not marked as such. */ | |
863 | |
864 template <typename valtype> | |
865 inline bool | |
866 ipcp_lattice<valtype>::set_contains_variable () | |
867 { | |
868 bool ret = !contains_variable; | |
869 contains_variable = true; | |
870 return ret; | |
871 } | |
872 | |
873 /* Set all aggegate lattices in PLATS to bottom and return true if they were | |
874 not previously set as such. */ | |
875 | |
175 static inline bool | 876 static inline bool |
176 ipcp_node_is_clone (struct cgraph_node *node) | 877 set_agg_lats_to_bottom (struct ipcp_param_lattices *plats) |
177 { | 878 { |
178 return (ipcp_get_orig_node (node) != NULL); | 879 bool ret = !plats->aggs_bottom; |
179 } | 880 plats->aggs_bottom = true; |
180 | 881 return ret; |
181 /* Create ipa_node_params and its data structures for NEW_NODE. Set ORIG_NODE | 882 } |
182 as the ipcp_orig_node field in ipa_node_params. */ | 883 |
183 static void | 884 /* Mark all aggegate lattices in PLATS as containing an unknown value and |
184 ipcp_init_cloned_node (struct cgraph_node *orig_node, | 885 return true if they were not previously marked as such. */ |
185 struct cgraph_node *new_node) | 886 |
186 { | |
187 gcc_checking_assert (ipa_node_params_vector | |
188 && (VEC_length (ipa_node_params_t, | |
189 ipa_node_params_vector) | |
190 > (unsigned) cgraph_max_uid)); | |
191 gcc_checking_assert (IPA_NODE_REF (new_node)->params); | |
192 IPA_NODE_REF (new_node)->ipcp_orig_node = orig_node; | |
193 } | |
194 | |
195 /* Return scale for NODE. */ | |
196 static inline gcov_type | |
197 ipcp_get_node_scale (struct cgraph_node *node) | |
198 { | |
199 return IPA_NODE_REF (node)->count_scale; | |
200 } | |
201 | |
202 /* Set COUNT as scale for NODE. */ | |
203 static inline void | |
204 ipcp_set_node_scale (struct cgraph_node *node, gcov_type count) | |
205 { | |
206 IPA_NODE_REF (node)->count_scale = count; | |
207 } | |
208 | |
209 /* Return whether LAT is a constant lattice. */ | |
210 static inline bool | 887 static inline bool |
211 ipcp_lat_is_const (struct ipcp_lattice *lat) | 888 set_agg_lats_contain_variable (struct ipcp_param_lattices *plats) |
212 { | 889 { |
213 if (lat->type == IPA_CONST_VALUE) | 890 bool ret = !plats->aggs_contain_variable; |
891 plats->aggs_contain_variable = true; | |
892 return ret; | |
893 } | |
894 | |
895 bool | |
896 ipcp_vr_lattice::meet_with (const ipcp_vr_lattice &other) | |
897 { | |
898 return meet_with_1 (&other.m_vr); | |
899 } | |
900 | |
901 /* Meet the current value of the lattice with value ranfge described by VR | |
902 lattice. */ | |
903 | |
904 bool | |
905 ipcp_vr_lattice::meet_with (const value_range *p_vr) | |
906 { | |
907 return meet_with_1 (p_vr); | |
908 } | |
909 | |
910 /* Meet the current value of the lattice with value ranfge described by | |
911 OTHER_VR lattice. */ | |
912 | |
913 bool | |
914 ipcp_vr_lattice::meet_with_1 (const value_range *other_vr) | |
915 { | |
916 tree min = m_vr.min, max = m_vr.max; | |
917 value_range_type type = m_vr.type; | |
918 | |
919 if (bottom_p ()) | |
920 return false; | |
921 | |
922 if (other_vr->type == VR_VARYING) | |
923 return set_to_bottom (); | |
924 | |
925 vrp_meet (&m_vr, other_vr); | |
926 if (type != m_vr.type | |
927 || min != m_vr.min | |
928 || max != m_vr.max) | |
214 return true; | 929 return true; |
215 else | 930 else |
216 return false; | 931 return false; |
217 } | 932 } |
218 | 933 |
219 /* Return whether LAT is a constant lattice that ipa-cp can actually insert | 934 /* Return true if value range information in the lattice is yet unknown. */ |
220 into the code (i.e. constants excluding member pointers and pointers). */ | 935 |
936 bool | |
937 ipcp_vr_lattice::top_p () const | |
938 { | |
939 return m_vr.type == VR_UNDEFINED; | |
940 } | |
941 | |
942 /* Return true if value range information in the lattice is known to be | |
943 unusable. */ | |
944 | |
945 bool | |
946 ipcp_vr_lattice::bottom_p () const | |
947 { | |
948 return m_vr.type == VR_VARYING; | |
949 } | |
950 | |
951 /* Set value range information in the lattice to bottom. Return true if it | |
952 previously was in a different state. */ | |
953 | |
954 bool | |
955 ipcp_vr_lattice::set_to_bottom () | |
956 { | |
957 if (m_vr.type == VR_VARYING) | |
958 return false; | |
959 m_vr.type = VR_VARYING; | |
960 return true; | |
961 } | |
962 | |
963 /* Set lattice value to bottom, if it already isn't the case. */ | |
964 | |
965 bool | |
966 ipcp_bits_lattice::set_to_bottom () | |
967 { | |
968 if (bottom_p ()) | |
969 return false; | |
970 m_lattice_val = IPA_BITS_VARYING; | |
971 m_value = 0; | |
972 m_mask = -1; | |
973 return true; | |
974 } | |
975 | |
976 /* Set to constant if it isn't already. Only meant to be called | |
977 when switching state from TOP. */ | |
978 | |
979 bool | |
980 ipcp_bits_lattice::set_to_constant (widest_int value, widest_int mask) | |
981 { | |
982 gcc_assert (top_p ()); | |
983 m_lattice_val = IPA_BITS_CONSTANT; | |
984 m_value = value; | |
985 m_mask = mask; | |
986 return true; | |
987 } | |
988 | |
989 /* Convert operand to value, mask form. */ | |
990 | |
991 void | |
992 ipcp_bits_lattice::get_value_and_mask (tree operand, widest_int *valuep, widest_int *maskp) | |
993 { | |
994 wide_int get_nonzero_bits (const_tree); | |
995 | |
996 if (TREE_CODE (operand) == INTEGER_CST) | |
997 { | |
998 *valuep = wi::to_widest (operand); | |
999 *maskp = 0; | |
1000 } | |
1001 else | |
1002 { | |
1003 *valuep = 0; | |
1004 *maskp = -1; | |
1005 } | |
1006 } | |
1007 | |
1008 /* Meet operation, similar to ccp_lattice_meet, we xor values | |
1009 if this->value, value have different values at same bit positions, we want | |
1010 to drop that bit to varying. Return true if mask is changed. | |
1011 This function assumes that the lattice value is in CONSTANT state */ | |
1012 | |
1013 bool | |
1014 ipcp_bits_lattice::meet_with_1 (widest_int value, widest_int mask, | |
1015 unsigned precision) | |
1016 { | |
1017 gcc_assert (constant_p ()); | |
1018 | |
1019 widest_int old_mask = m_mask; | |
1020 m_mask = (m_mask | mask) | (m_value ^ value); | |
1021 | |
1022 if (wi::sext (m_mask, precision) == -1) | |
1023 return set_to_bottom (); | |
1024 | |
1025 return m_mask != old_mask; | |
1026 } | |
1027 | |
1028 /* Meet the bits lattice with operand | |
1029 described by <value, mask, sgn, precision. */ | |
1030 | |
1031 bool | |
1032 ipcp_bits_lattice::meet_with (widest_int value, widest_int mask, | |
1033 unsigned precision) | |
1034 { | |
1035 if (bottom_p ()) | |
1036 return false; | |
1037 | |
1038 if (top_p ()) | |
1039 { | |
1040 if (wi::sext (mask, precision) == -1) | |
1041 return set_to_bottom (); | |
1042 return set_to_constant (value, mask); | |
1043 } | |
1044 | |
1045 return meet_with_1 (value, mask, precision); | |
1046 } | |
1047 | |
1048 /* Meet bits lattice with the result of bit_value_binop (other, operand) | |
1049 if code is binary operation or bit_value_unop (other) if code is unary op. | |
1050 In the case when code is nop_expr, no adjustment is required. */ | |
1051 | |
1052 bool | |
1053 ipcp_bits_lattice::meet_with (ipcp_bits_lattice& other, unsigned precision, | |
1054 signop sgn, enum tree_code code, tree operand) | |
1055 { | |
1056 if (other.bottom_p ()) | |
1057 return set_to_bottom (); | |
1058 | |
1059 if (bottom_p () || other.top_p ()) | |
1060 return false; | |
1061 | |
1062 widest_int adjusted_value, adjusted_mask; | |
1063 | |
1064 if (TREE_CODE_CLASS (code) == tcc_binary) | |
1065 { | |
1066 tree type = TREE_TYPE (operand); | |
1067 gcc_assert (INTEGRAL_TYPE_P (type)); | |
1068 widest_int o_value, o_mask; | |
1069 get_value_and_mask (operand, &o_value, &o_mask); | |
1070 | |
1071 bit_value_binop (code, sgn, precision, &adjusted_value, &adjusted_mask, | |
1072 sgn, precision, other.get_value (), other.get_mask (), | |
1073 TYPE_SIGN (type), TYPE_PRECISION (type), o_value, o_mask); | |
1074 | |
1075 if (wi::sext (adjusted_mask, precision) == -1) | |
1076 return set_to_bottom (); | |
1077 } | |
1078 | |
1079 else if (TREE_CODE_CLASS (code) == tcc_unary) | |
1080 { | |
1081 bit_value_unop (code, sgn, precision, &adjusted_value, | |
1082 &adjusted_mask, sgn, precision, other.get_value (), | |
1083 other.get_mask ()); | |
1084 | |
1085 if (wi::sext (adjusted_mask, precision) == -1) | |
1086 return set_to_bottom (); | |
1087 } | |
1088 | |
1089 else | |
1090 return set_to_bottom (); | |
1091 | |
1092 if (top_p ()) | |
1093 { | |
1094 if (wi::sext (adjusted_mask, precision) == -1) | |
1095 return set_to_bottom (); | |
1096 return set_to_constant (adjusted_value, adjusted_mask); | |
1097 } | |
1098 else | |
1099 return meet_with_1 (adjusted_value, adjusted_mask, precision); | |
1100 } | |
1101 | |
1102 /* Mark bot aggregate and scalar lattices as containing an unknown variable, | |
1103 return true is any of them has not been marked as such so far. */ | |
1104 | |
221 static inline bool | 1105 static inline bool |
222 ipcp_lat_is_insertable (struct ipcp_lattice *lat) | 1106 set_all_contains_variable (struct ipcp_param_lattices *plats) |
223 { | 1107 { |
224 return lat->type == IPA_CONST_VALUE; | 1108 bool ret; |
225 } | 1109 ret = plats->itself.set_contains_variable (); |
226 | 1110 ret |= plats->ctxlat.set_contains_variable (); |
227 /* Return true if LAT1 and LAT2 are equal. */ | 1111 ret |= set_agg_lats_contain_variable (plats); |
228 static inline bool | 1112 ret |= plats->bits_lattice.set_to_bottom (); |
229 ipcp_lats_are_equal (struct ipcp_lattice *lat1, struct ipcp_lattice *lat2) | 1113 ret |= plats->m_value_range.set_to_bottom (); |
230 { | 1114 return ret; |
231 gcc_assert (ipcp_lat_is_const (lat1) && ipcp_lat_is_const (lat2)); | 1115 } |
232 if (lat1->type != lat2->type) | 1116 |
1117 /* Worker of call_for_symbol_thunks_and_aliases, increment the integer DATA | |
1118 points to by the number of callers to NODE. */ | |
1119 | |
1120 static bool | |
1121 count_callers (cgraph_node *node, void *data) | |
1122 { | |
1123 int *caller_count = (int *) data; | |
1124 | |
1125 for (cgraph_edge *cs = node->callers; cs; cs = cs->next_caller) | |
1126 /* Local thunks can be handled transparently, but if the thunk can not | |
1127 be optimized out, count it as a real use. */ | |
1128 if (!cs->caller->thunk.thunk_p || !cs->caller->local.local) | |
1129 ++*caller_count; | |
1130 return false; | |
1131 } | |
1132 | |
1133 /* Worker of call_for_symbol_thunks_and_aliases, it is supposed to be called on | |
1134 the one caller of some other node. Set the caller's corresponding flag. */ | |
1135 | |
1136 static bool | |
1137 set_single_call_flag (cgraph_node *node, void *) | |
1138 { | |
1139 cgraph_edge *cs = node->callers; | |
1140 /* Local thunks can be handled transparently, skip them. */ | |
1141 while (cs && cs->caller->thunk.thunk_p && cs->caller->local.local) | |
1142 cs = cs->next_caller; | |
1143 if (cs) | |
1144 { | |
1145 IPA_NODE_REF (cs->caller)->node_calling_single_call = true; | |
1146 return true; | |
1147 } | |
1148 return false; | |
1149 } | |
1150 | |
1151 /* Initialize ipcp_lattices. */ | |
1152 | |
1153 static void | |
1154 initialize_node_lattices (struct cgraph_node *node) | |
1155 { | |
1156 struct ipa_node_params *info = IPA_NODE_REF (node); | |
1157 struct cgraph_edge *ie; | |
1158 bool disable = false, variable = false; | |
1159 int i; | |
1160 | |
1161 gcc_checking_assert (node->has_gimple_body_p ()); | |
1162 if (cgraph_local_p (node)) | |
1163 { | |
1164 int caller_count = 0; | |
1165 node->call_for_symbol_thunks_and_aliases (count_callers, &caller_count, | |
1166 true); | |
1167 gcc_checking_assert (caller_count > 0); | |
1168 if (caller_count == 1) | |
1169 node->call_for_symbol_thunks_and_aliases (set_single_call_flag, | |
1170 NULL, true); | |
1171 } | |
1172 else | |
1173 { | |
1174 /* When cloning is allowed, we can assume that externally visible | |
1175 functions are not called. We will compensate this by cloning | |
1176 later. */ | |
1177 if (ipcp_versionable_function_p (node) | |
1178 && ipcp_cloning_candidate_p (node)) | |
1179 variable = true; | |
1180 else | |
1181 disable = true; | |
1182 } | |
1183 | |
1184 for (i = 0; i < ipa_get_param_count (info); i++) | |
1185 { | |
1186 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i); | |
1187 plats->m_value_range.init (); | |
1188 } | |
1189 | |
1190 if (disable || variable) | |
1191 { | |
1192 for (i = 0; i < ipa_get_param_count (info); i++) | |
1193 { | |
1194 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i); | |
1195 if (disable) | |
1196 { | |
1197 plats->itself.set_to_bottom (); | |
1198 plats->ctxlat.set_to_bottom (); | |
1199 set_agg_lats_to_bottom (plats); | |
1200 plats->bits_lattice.set_to_bottom (); | |
1201 plats->m_value_range.set_to_bottom (); | |
1202 } | |
1203 else | |
1204 set_all_contains_variable (plats); | |
1205 } | |
1206 if (dump_file && (dump_flags & TDF_DETAILS) | |
1207 && !node->alias && !node->thunk.thunk_p) | |
1208 fprintf (dump_file, "Marking all lattices of %s as %s\n", | |
1209 node->dump_name (), disable ? "BOTTOM" : "VARIABLE"); | |
1210 } | |
1211 | |
1212 for (ie = node->indirect_calls; ie; ie = ie->next_callee) | |
1213 if (ie->indirect_info->polymorphic | |
1214 && ie->indirect_info->param_index >= 0) | |
1215 { | |
1216 gcc_checking_assert (ie->indirect_info->param_index >= 0); | |
1217 ipa_get_parm_lattices (info, | |
1218 ie->indirect_info->param_index)->virt_call = 1; | |
1219 } | |
1220 } | |
1221 | |
1222 /* Return the result of a (possibly arithmetic) pass through jump function | |
1223 JFUNC on the constant value INPUT. Return NULL_TREE if that cannot be | |
1224 determined or be considered an interprocedural invariant. */ | |
1225 | |
1226 static tree | |
1227 ipa_get_jf_pass_through_result (struct ipa_jump_func *jfunc, tree input) | |
1228 { | |
1229 tree restype, res; | |
1230 | |
1231 if (ipa_get_jf_pass_through_operation (jfunc) == NOP_EXPR) | |
1232 return input; | |
1233 if (!is_gimple_ip_invariant (input)) | |
1234 return NULL_TREE; | |
1235 | |
1236 if (TREE_CODE_CLASS (ipa_get_jf_pass_through_operation (jfunc)) | |
1237 == tcc_unary) | |
1238 res = fold_unary (ipa_get_jf_pass_through_operation (jfunc), | |
1239 TREE_TYPE (input), input); | |
1240 else | |
1241 { | |
1242 if (TREE_CODE_CLASS (ipa_get_jf_pass_through_operation (jfunc)) | |
1243 == tcc_comparison) | |
1244 restype = boolean_type_node; | |
1245 else | |
1246 restype = TREE_TYPE (input); | |
1247 res = fold_binary (ipa_get_jf_pass_through_operation (jfunc), restype, | |
1248 input, ipa_get_jf_pass_through_operand (jfunc)); | |
1249 } | |
1250 if (res && !is_gimple_ip_invariant (res)) | |
1251 return NULL_TREE; | |
1252 | |
1253 return res; | |
1254 } | |
1255 | |
1256 /* Return the result of an ancestor jump function JFUNC on the constant value | |
1257 INPUT. Return NULL_TREE if that cannot be determined. */ | |
1258 | |
1259 static tree | |
1260 ipa_get_jf_ancestor_result (struct ipa_jump_func *jfunc, tree input) | |
1261 { | |
1262 gcc_checking_assert (TREE_CODE (input) != TREE_BINFO); | |
1263 if (TREE_CODE (input) == ADDR_EXPR) | |
1264 { | |
1265 tree t = TREE_OPERAND (input, 0); | |
1266 t = build_ref_for_offset (EXPR_LOCATION (t), t, | |
1267 ipa_get_jf_ancestor_offset (jfunc), false, | |
1268 ptr_type_node, NULL, false); | |
1269 return build_fold_addr_expr (t); | |
1270 } | |
1271 else | |
1272 return NULL_TREE; | |
1273 } | |
1274 | |
1275 /* Determine whether JFUNC evaluates to a single known constant value and if | |
1276 so, return it. Otherwise return NULL. INFO describes the caller node or | |
1277 the one it is inlined to, so that pass-through jump functions can be | |
1278 evaluated. */ | |
1279 | |
1280 tree | |
1281 ipa_value_from_jfunc (struct ipa_node_params *info, struct ipa_jump_func *jfunc) | |
1282 { | |
1283 if (jfunc->type == IPA_JF_CONST) | |
1284 return ipa_get_jf_constant (jfunc); | |
1285 else if (jfunc->type == IPA_JF_PASS_THROUGH | |
1286 || jfunc->type == IPA_JF_ANCESTOR) | |
1287 { | |
1288 tree input; | |
1289 int idx; | |
1290 | |
1291 if (jfunc->type == IPA_JF_PASS_THROUGH) | |
1292 idx = ipa_get_jf_pass_through_formal_id (jfunc); | |
1293 else | |
1294 idx = ipa_get_jf_ancestor_formal_id (jfunc); | |
1295 | |
1296 if (info->ipcp_orig_node) | |
1297 input = info->known_csts[idx]; | |
1298 else | |
1299 { | |
1300 ipcp_lattice<tree> *lat; | |
1301 | |
1302 if (!info->lattices | |
1303 || idx >= ipa_get_param_count (info)) | |
1304 return NULL_TREE; | |
1305 lat = ipa_get_scalar_lat (info, idx); | |
1306 if (!lat->is_single_const ()) | |
1307 return NULL_TREE; | |
1308 input = lat->values->value; | |
1309 } | |
1310 | |
1311 if (!input) | |
1312 return NULL_TREE; | |
1313 | |
1314 if (jfunc->type == IPA_JF_PASS_THROUGH) | |
1315 return ipa_get_jf_pass_through_result (jfunc, input); | |
1316 else | |
1317 return ipa_get_jf_ancestor_result (jfunc, input); | |
1318 } | |
1319 else | |
1320 return NULL_TREE; | |
1321 } | |
1322 | |
1323 /* Determie whether JFUNC evaluates to single known polymorphic context, given | |
1324 that INFO describes the caller node or the one it is inlined to, CS is the | |
1325 call graph edge corresponding to JFUNC and CSIDX index of the described | |
1326 parameter. */ | |
1327 | |
1328 ipa_polymorphic_call_context | |
1329 ipa_context_from_jfunc (ipa_node_params *info, cgraph_edge *cs, int csidx, | |
1330 ipa_jump_func *jfunc) | |
1331 { | |
1332 ipa_edge_args *args = IPA_EDGE_REF (cs); | |
1333 ipa_polymorphic_call_context ctx; | |
1334 ipa_polymorphic_call_context *edge_ctx | |
1335 = cs ? ipa_get_ith_polymorhic_call_context (args, csidx) : NULL; | |
1336 | |
1337 if (edge_ctx && !edge_ctx->useless_p ()) | |
1338 ctx = *edge_ctx; | |
1339 | |
1340 if (jfunc->type == IPA_JF_PASS_THROUGH | |
1341 || jfunc->type == IPA_JF_ANCESTOR) | |
1342 { | |
1343 ipa_polymorphic_call_context srcctx; | |
1344 int srcidx; | |
1345 bool type_preserved = true; | |
1346 if (jfunc->type == IPA_JF_PASS_THROUGH) | |
1347 { | |
1348 if (ipa_get_jf_pass_through_operation (jfunc) != NOP_EXPR) | |
1349 return ctx; | |
1350 type_preserved = ipa_get_jf_pass_through_type_preserved (jfunc); | |
1351 srcidx = ipa_get_jf_pass_through_formal_id (jfunc); | |
1352 } | |
1353 else | |
1354 { | |
1355 type_preserved = ipa_get_jf_ancestor_type_preserved (jfunc); | |
1356 srcidx = ipa_get_jf_ancestor_formal_id (jfunc); | |
1357 } | |
1358 if (info->ipcp_orig_node) | |
1359 { | |
1360 if (info->known_contexts.exists ()) | |
1361 srcctx = info->known_contexts[srcidx]; | |
1362 } | |
1363 else | |
1364 { | |
1365 if (!info->lattices | |
1366 || srcidx >= ipa_get_param_count (info)) | |
1367 return ctx; | |
1368 ipcp_lattice<ipa_polymorphic_call_context> *lat; | |
1369 lat = ipa_get_poly_ctx_lat (info, srcidx); | |
1370 if (!lat->is_single_const ()) | |
1371 return ctx; | |
1372 srcctx = lat->values->value; | |
1373 } | |
1374 if (srcctx.useless_p ()) | |
1375 return ctx; | |
1376 if (jfunc->type == IPA_JF_ANCESTOR) | |
1377 srcctx.offset_by (ipa_get_jf_ancestor_offset (jfunc)); | |
1378 if (!type_preserved) | |
1379 srcctx.possible_dynamic_type_change (cs->in_polymorphic_cdtor); | |
1380 srcctx.combine_with (ctx); | |
1381 return srcctx; | |
1382 } | |
1383 | |
1384 return ctx; | |
1385 } | |
1386 | |
1387 /* If checking is enabled, verify that no lattice is in the TOP state, i.e. not | |
1388 bottom, not containing a variable component and without any known value at | |
1389 the same time. */ | |
1390 | |
1391 DEBUG_FUNCTION void | |
1392 ipcp_verify_propagated_values (void) | |
1393 { | |
1394 struct cgraph_node *node; | |
1395 | |
1396 FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node) | |
1397 { | |
1398 struct ipa_node_params *info = IPA_NODE_REF (node); | |
1399 int i, count = ipa_get_param_count (info); | |
1400 | |
1401 for (i = 0; i < count; i++) | |
1402 { | |
1403 ipcp_lattice<tree> *lat = ipa_get_scalar_lat (info, i); | |
1404 | |
1405 if (!lat->bottom | |
1406 && !lat->contains_variable | |
1407 && lat->values_count == 0) | |
1408 { | |
1409 if (dump_file) | |
1410 { | |
1411 symtab->dump (dump_file); | |
1412 fprintf (dump_file, "\nIPA lattices after constant " | |
1413 "propagation, before gcc_unreachable:\n"); | |
1414 print_all_lattices (dump_file, true, false); | |
1415 } | |
1416 | |
1417 gcc_unreachable (); | |
1418 } | |
1419 } | |
1420 } | |
1421 } | |
1422 | |
1423 /* Return true iff X and Y should be considered equal values by IPA-CP. */ | |
1424 | |
1425 static bool | |
1426 values_equal_for_ipcp_p (tree x, tree y) | |
1427 { | |
1428 gcc_checking_assert (x != NULL_TREE && y != NULL_TREE); | |
1429 | |
1430 if (x == y) | |
1431 return true; | |
1432 | |
1433 if (TREE_CODE (x) == ADDR_EXPR | |
1434 && TREE_CODE (y) == ADDR_EXPR | |
1435 && TREE_CODE (TREE_OPERAND (x, 0)) == CONST_DECL | |
1436 && TREE_CODE (TREE_OPERAND (y, 0)) == CONST_DECL) | |
1437 return operand_equal_p (DECL_INITIAL (TREE_OPERAND (x, 0)), | |
1438 DECL_INITIAL (TREE_OPERAND (y, 0)), 0); | |
1439 else | |
1440 return operand_equal_p (x, y, 0); | |
1441 } | |
1442 | |
1443 /* Return true iff X and Y should be considered equal contexts by IPA-CP. */ | |
1444 | |
1445 static bool | |
1446 values_equal_for_ipcp_p (ipa_polymorphic_call_context x, | |
1447 ipa_polymorphic_call_context y) | |
1448 { | |
1449 return x.equal_to (y); | |
1450 } | |
1451 | |
1452 | |
1453 /* Add a new value source to the value represented by THIS, marking that a | |
1454 value comes from edge CS and (if the underlying jump function is a | |
1455 pass-through or an ancestor one) from a caller value SRC_VAL of a caller | |
1456 parameter described by SRC_INDEX. OFFSET is negative if the source was the | |
1457 scalar value of the parameter itself or the offset within an aggregate. */ | |
1458 | |
1459 template <typename valtype> | |
1460 void | |
1461 ipcp_value<valtype>::add_source (cgraph_edge *cs, ipcp_value *src_val, | |
1462 int src_idx, HOST_WIDE_INT offset) | |
1463 { | |
1464 ipcp_value_source<valtype> *src; | |
1465 | |
1466 src = new (ipcp_sources_pool.allocate ()) ipcp_value_source<valtype>; | |
1467 src->offset = offset; | |
1468 src->cs = cs; | |
1469 src->val = src_val; | |
1470 src->index = src_idx; | |
1471 | |
1472 src->next = sources; | |
1473 sources = src; | |
1474 } | |
1475 | |
1476 /* Allocate a new ipcp_value holding a tree constant, initialize its value to | |
1477 SOURCE and clear all other fields. */ | |
1478 | |
1479 static ipcp_value<tree> * | |
1480 allocate_and_init_ipcp_value (tree source) | |
1481 { | |
1482 ipcp_value<tree> *val; | |
1483 | |
1484 val = new (ipcp_cst_values_pool.allocate ()) ipcp_value<tree>(); | |
1485 val->value = source; | |
1486 return val; | |
1487 } | |
1488 | |
1489 /* Allocate a new ipcp_value holding a polymorphic context, initialize its | |
1490 value to SOURCE and clear all other fields. */ | |
1491 | |
1492 static ipcp_value<ipa_polymorphic_call_context> * | |
1493 allocate_and_init_ipcp_value (ipa_polymorphic_call_context source) | |
1494 { | |
1495 ipcp_value<ipa_polymorphic_call_context> *val; | |
1496 | |
1497 // TODO | |
1498 val = new (ipcp_poly_ctx_values_pool.allocate ()) | |
1499 ipcp_value<ipa_polymorphic_call_context>(); | |
1500 val->value = source; | |
1501 return val; | |
1502 } | |
1503 | |
1504 /* Try to add NEWVAL to LAT, potentially creating a new ipcp_value for it. CS, | |
1505 SRC_VAL SRC_INDEX and OFFSET are meant for add_source and have the same | |
1506 meaning. OFFSET -1 means the source is scalar and not a part of an | |
1507 aggregate. */ | |
1508 | |
1509 template <typename valtype> | |
1510 bool | |
1511 ipcp_lattice<valtype>::add_value (valtype newval, cgraph_edge *cs, | |
1512 ipcp_value<valtype> *src_val, | |
1513 int src_idx, HOST_WIDE_INT offset) | |
1514 { | |
1515 ipcp_value<valtype> *val; | |
1516 | |
1517 if (bottom) | |
233 return false; | 1518 return false; |
234 | 1519 |
235 if (TREE_CODE (lat1->constant) == ADDR_EXPR | 1520 for (val = values; val; val = val->next) |
236 && TREE_CODE (lat2->constant) == ADDR_EXPR | 1521 if (values_equal_for_ipcp_p (val->value, newval)) |
237 && TREE_CODE (TREE_OPERAND (lat1->constant, 0)) == CONST_DECL | 1522 { |
238 && TREE_CODE (TREE_OPERAND (lat2->constant, 0)) == CONST_DECL) | 1523 if (ipa_edge_within_scc (cs)) |
239 return operand_equal_p (DECL_INITIAL (TREE_OPERAND (lat1->constant, 0)), | 1524 { |
240 DECL_INITIAL (TREE_OPERAND (lat2->constant, 0)), 0); | 1525 ipcp_value_source<valtype> *s; |
1526 for (s = val->sources; s; s = s->next) | |
1527 if (s->cs == cs) | |
1528 break; | |
1529 if (s) | |
1530 return false; | |
1531 } | |
1532 | |
1533 val->add_source (cs, src_val, src_idx, offset); | |
1534 return false; | |
1535 } | |
1536 | |
1537 if (values_count == PARAM_VALUE (PARAM_IPA_CP_VALUE_LIST_SIZE)) | |
1538 { | |
1539 /* We can only free sources, not the values themselves, because sources | |
1540 of other values in this SCC might point to them. */ | |
1541 for (val = values; val; val = val->next) | |
1542 { | |
1543 while (val->sources) | |
1544 { | |
1545 ipcp_value_source<valtype> *src = val->sources; | |
1546 val->sources = src->next; | |
1547 ipcp_sources_pool.remove ((ipcp_value_source<tree>*)src); | |
1548 } | |
1549 } | |
1550 | |
1551 values = NULL; | |
1552 return set_to_bottom (); | |
1553 } | |
1554 | |
1555 values_count++; | |
1556 val = allocate_and_init_ipcp_value (newval); | |
1557 val->add_source (cs, src_val, src_idx, offset); | |
1558 val->next = values; | |
1559 values = val; | |
1560 return true; | |
1561 } | |
1562 | |
1563 /* Propagate values through a pass-through jump function JFUNC associated with | |
1564 edge CS, taking values from SRC_LAT and putting them into DEST_LAT. SRC_IDX | |
1565 is the index of the source parameter. */ | |
1566 | |
1567 static bool | |
1568 propagate_vals_across_pass_through (cgraph_edge *cs, ipa_jump_func *jfunc, | |
1569 ipcp_lattice<tree> *src_lat, | |
1570 ipcp_lattice<tree> *dest_lat, int src_idx) | |
1571 { | |
1572 ipcp_value<tree> *src_val; | |
1573 bool ret = false; | |
1574 | |
1575 /* Do not create new values when propagating within an SCC because if there | |
1576 are arithmetic functions with circular dependencies, there is infinite | |
1577 number of them and we would just make lattices bottom. */ | |
1578 if ((ipa_get_jf_pass_through_operation (jfunc) != NOP_EXPR) | |
1579 && ipa_edge_within_scc (cs)) | |
1580 ret = dest_lat->set_contains_variable (); | |
241 else | 1581 else |
242 return operand_equal_p (lat1->constant, lat2->constant, 0); | 1582 for (src_val = src_lat->values; src_val; src_val = src_val->next) |
243 } | 1583 { |
244 | 1584 tree cstval = ipa_get_jf_pass_through_result (jfunc, src_val->value); |
245 /* Compute Meet arithmetics: | 1585 |
246 Meet (IPA_BOTTOM, x) = IPA_BOTTOM | 1586 if (cstval) |
247 Meet (IPA_TOP,x) = x | 1587 ret |= dest_lat->add_value (cstval, cs, src_val, src_idx); |
248 Meet (const_a,const_b) = IPA_BOTTOM, if const_a != const_b. | 1588 else |
249 MEET (const_a,const_b) = const_a, if const_a == const_b.*/ | 1589 ret |= dest_lat->set_contains_variable (); |
250 static void | 1590 } |
251 ipa_lattice_meet (struct ipcp_lattice *res, struct ipcp_lattice *lat1, | 1591 |
252 struct ipcp_lattice *lat2) | 1592 return ret; |
253 { | 1593 } |
254 if (lat1->type == IPA_BOTTOM || lat2->type == IPA_BOTTOM) | 1594 |
255 { | 1595 /* Propagate values through an ancestor jump function JFUNC associated with |
256 res->type = IPA_BOTTOM; | 1596 edge CS, taking values from SRC_LAT and putting them into DEST_LAT. SRC_IDX |
257 return; | 1597 is the index of the source parameter. */ |
258 } | 1598 |
259 if (lat1->type == IPA_TOP) | 1599 static bool |
260 { | 1600 propagate_vals_across_ancestor (struct cgraph_edge *cs, |
261 res->type = lat2->type; | 1601 struct ipa_jump_func *jfunc, |
262 res->constant = lat2->constant; | 1602 ipcp_lattice<tree> *src_lat, |
263 return; | 1603 ipcp_lattice<tree> *dest_lat, int src_idx) |
264 } | 1604 { |
265 if (lat2->type == IPA_TOP) | 1605 ipcp_value<tree> *src_val; |
266 { | 1606 bool ret = false; |
267 res->type = lat1->type; | 1607 |
268 res->constant = lat1->constant; | 1608 if (ipa_edge_within_scc (cs)) |
269 return; | 1609 return dest_lat->set_contains_variable (); |
270 } | 1610 |
271 if (!ipcp_lats_are_equal (lat1, lat2)) | 1611 for (src_val = src_lat->values; src_val; src_val = src_val->next) |
272 { | 1612 { |
273 res->type = IPA_BOTTOM; | 1613 tree t = ipa_get_jf_ancestor_result (jfunc, src_val->value); |
274 return; | 1614 |
275 } | 1615 if (t) |
276 res->type = lat1->type; | 1616 ret |= dest_lat->add_value (t, cs, src_val, src_idx); |
277 res->constant = lat1->constant; | 1617 else |
278 } | 1618 ret |= dest_lat->set_contains_variable (); |
279 | 1619 } |
280 /* Return the lattice corresponding to the Ith formal parameter of the function | 1620 |
281 described by INFO. */ | 1621 return ret; |
282 static inline struct ipcp_lattice * | 1622 } |
283 ipcp_get_lattice (struct ipa_node_params *info, int i) | 1623 |
284 { | 1624 /* Propagate scalar values across jump function JFUNC that is associated with |
285 return &(info->params[i].ipcp_lattice); | 1625 edge CS and put the values into DEST_LAT. */ |
286 } | 1626 |
287 | 1627 static bool |
288 /* Given the jump function JFUNC, compute the lattice LAT that describes the | 1628 propagate_scalar_across_jump_function (struct cgraph_edge *cs, |
289 value coming down the callsite. INFO describes the caller node so that | 1629 struct ipa_jump_func *jfunc, |
290 pass-through jump functions can be evaluated. */ | 1630 ipcp_lattice<tree> *dest_lat) |
291 static void | 1631 { |
292 ipcp_lattice_from_jfunc (struct ipa_node_params *info, struct ipcp_lattice *lat, | 1632 if (dest_lat->bottom) |
293 struct ipa_jump_func *jfunc) | 1633 return false; |
294 { | 1634 |
295 if (jfunc->type == IPA_JF_CONST) | 1635 if (jfunc->type == IPA_JF_CONST) |
296 { | 1636 { |
297 lat->type = IPA_CONST_VALUE; | 1637 tree val = ipa_get_jf_constant (jfunc); |
298 lat->constant = jfunc->value.constant; | 1638 return dest_lat->add_value (val, cs, NULL, 0); |
299 } | 1639 } |
300 else if (jfunc->type == IPA_JF_PASS_THROUGH) | 1640 else if (jfunc->type == IPA_JF_PASS_THROUGH |
301 { | 1641 || jfunc->type == IPA_JF_ANCESTOR) |
302 struct ipcp_lattice *caller_lat; | 1642 { |
303 tree cst; | 1643 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller); |
304 | 1644 ipcp_lattice<tree> *src_lat; |
305 caller_lat = ipcp_get_lattice (info, jfunc->value.pass_through.formal_id); | 1645 int src_idx; |
306 lat->type = caller_lat->type; | 1646 bool ret; |
307 if (caller_lat->type != IPA_CONST_VALUE) | 1647 |
308 return; | 1648 if (jfunc->type == IPA_JF_PASS_THROUGH) |
309 cst = caller_lat->constant; | 1649 src_idx = ipa_get_jf_pass_through_formal_id (jfunc); |
310 | 1650 else |
311 if (jfunc->value.pass_through.operation != NOP_EXPR) | 1651 src_idx = ipa_get_jf_ancestor_formal_id (jfunc); |
312 { | 1652 |
313 tree restype; | 1653 src_lat = ipa_get_scalar_lat (caller_info, src_idx); |
314 if (TREE_CODE_CLASS (jfunc->value.pass_through.operation) | 1654 if (src_lat->bottom) |
315 == tcc_comparison) | 1655 return dest_lat->set_contains_variable (); |
316 restype = boolean_type_node; | 1656 |
1657 /* If we would need to clone the caller and cannot, do not propagate. */ | |
1658 if (!ipcp_versionable_function_p (cs->caller) | |
1659 && (src_lat->contains_variable | |
1660 || (src_lat->values_count > 1))) | |
1661 return dest_lat->set_contains_variable (); | |
1662 | |
1663 if (jfunc->type == IPA_JF_PASS_THROUGH) | |
1664 ret = propagate_vals_across_pass_through (cs, jfunc, src_lat, | |
1665 dest_lat, src_idx); | |
1666 else | |
1667 ret = propagate_vals_across_ancestor (cs, jfunc, src_lat, dest_lat, | |
1668 src_idx); | |
1669 | |
1670 if (src_lat->contains_variable) | |
1671 ret |= dest_lat->set_contains_variable (); | |
1672 | |
1673 return ret; | |
1674 } | |
1675 | |
1676 /* TODO: We currently do not handle member method pointers in IPA-CP (we only | |
1677 use it for indirect inlining), we should propagate them too. */ | |
1678 return dest_lat->set_contains_variable (); | |
1679 } | |
1680 | |
1681 /* Propagate scalar values across jump function JFUNC that is associated with | |
1682 edge CS and describes argument IDX and put the values into DEST_LAT. */ | |
1683 | |
1684 static bool | |
1685 propagate_context_across_jump_function (cgraph_edge *cs, | |
1686 ipa_jump_func *jfunc, int idx, | |
1687 ipcp_lattice<ipa_polymorphic_call_context> *dest_lat) | |
1688 { | |
1689 ipa_edge_args *args = IPA_EDGE_REF (cs); | |
1690 if (dest_lat->bottom) | |
1691 return false; | |
1692 bool ret = false; | |
1693 bool added_sth = false; | |
1694 bool type_preserved = true; | |
1695 | |
1696 ipa_polymorphic_call_context edge_ctx, *edge_ctx_ptr | |
1697 = ipa_get_ith_polymorhic_call_context (args, idx); | |
1698 | |
1699 if (edge_ctx_ptr) | |
1700 edge_ctx = *edge_ctx_ptr; | |
1701 | |
1702 if (jfunc->type == IPA_JF_PASS_THROUGH | |
1703 || jfunc->type == IPA_JF_ANCESTOR) | |
1704 { | |
1705 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller); | |
1706 int src_idx; | |
1707 ipcp_lattice<ipa_polymorphic_call_context> *src_lat; | |
1708 | |
1709 /* TODO: Once we figure out how to propagate speculations, it will | |
1710 probably be a good idea to switch to speculation if type_preserved is | |
1711 not set instead of punting. */ | |
1712 if (jfunc->type == IPA_JF_PASS_THROUGH) | |
1713 { | |
1714 if (ipa_get_jf_pass_through_operation (jfunc) != NOP_EXPR) | |
1715 goto prop_fail; | |
1716 type_preserved = ipa_get_jf_pass_through_type_preserved (jfunc); | |
1717 src_idx = ipa_get_jf_pass_through_formal_id (jfunc); | |
1718 } | |
1719 else | |
1720 { | |
1721 type_preserved = ipa_get_jf_ancestor_type_preserved (jfunc); | |
1722 src_idx = ipa_get_jf_ancestor_formal_id (jfunc); | |
1723 } | |
1724 | |
1725 src_lat = ipa_get_poly_ctx_lat (caller_info, src_idx); | |
1726 /* If we would need to clone the caller and cannot, do not propagate. */ | |
1727 if (!ipcp_versionable_function_p (cs->caller) | |
1728 && (src_lat->contains_variable | |
1729 || (src_lat->values_count > 1))) | |
1730 goto prop_fail; | |
1731 | |
1732 ipcp_value<ipa_polymorphic_call_context> *src_val; | |
1733 for (src_val = src_lat->values; src_val; src_val = src_val->next) | |
1734 { | |
1735 ipa_polymorphic_call_context cur = src_val->value; | |
1736 | |
1737 if (!type_preserved) | |
1738 cur.possible_dynamic_type_change (cs->in_polymorphic_cdtor); | |
1739 if (jfunc->type == IPA_JF_ANCESTOR) | |
1740 cur.offset_by (ipa_get_jf_ancestor_offset (jfunc)); | |
1741 /* TODO: In cases we know how the context is going to be used, | |
1742 we can improve the result by passing proper OTR_TYPE. */ | |
1743 cur.combine_with (edge_ctx); | |
1744 if (!cur.useless_p ()) | |
1745 { | |
1746 if (src_lat->contains_variable | |
1747 && !edge_ctx.equal_to (cur)) | |
1748 ret |= dest_lat->set_contains_variable (); | |
1749 ret |= dest_lat->add_value (cur, cs, src_val, src_idx); | |
1750 added_sth = true; | |
1751 } | |
1752 } | |
1753 | |
1754 } | |
1755 | |
1756 prop_fail: | |
1757 if (!added_sth) | |
1758 { | |
1759 if (!edge_ctx.useless_p ()) | |
1760 ret |= dest_lat->add_value (edge_ctx, cs); | |
1761 else | |
1762 ret |= dest_lat->set_contains_variable (); | |
1763 } | |
1764 | |
1765 return ret; | |
1766 } | |
1767 | |
1768 /* Propagate bits across jfunc that is associated with | |
1769 edge cs and update dest_lattice accordingly. */ | |
1770 | |
1771 bool | |
1772 propagate_bits_across_jump_function (cgraph_edge *cs, int idx, | |
1773 ipa_jump_func *jfunc, | |
1774 ipcp_bits_lattice *dest_lattice) | |
1775 { | |
1776 if (dest_lattice->bottom_p ()) | |
1777 return false; | |
1778 | |
1779 enum availability availability; | |
1780 cgraph_node *callee = cs->callee->function_symbol (&availability); | |
1781 struct ipa_node_params *callee_info = IPA_NODE_REF (callee); | |
1782 tree parm_type = ipa_get_type (callee_info, idx); | |
1783 | |
1784 /* For K&R C programs, ipa_get_type() could return NULL_TREE. | |
1785 Avoid the transform for these cases. */ | |
1786 if (!parm_type) | |
1787 { | |
1788 if (dump_file && (dump_flags & TDF_DETAILS)) | |
1789 fprintf (dump_file, "Setting dest_lattice to bottom, because" | |
1790 " param %i type is NULL for %s\n", idx, | |
1791 cs->callee->name ()); | |
1792 | |
1793 return dest_lattice->set_to_bottom (); | |
1794 } | |
1795 | |
1796 unsigned precision = TYPE_PRECISION (parm_type); | |
1797 signop sgn = TYPE_SIGN (parm_type); | |
1798 | |
1799 if (jfunc->type == IPA_JF_PASS_THROUGH | |
1800 || jfunc->type == IPA_JF_ANCESTOR) | |
1801 { | |
1802 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller); | |
1803 tree operand = NULL_TREE; | |
1804 enum tree_code code; | |
1805 unsigned src_idx; | |
1806 | |
1807 if (jfunc->type == IPA_JF_PASS_THROUGH) | |
1808 { | |
1809 code = ipa_get_jf_pass_through_operation (jfunc); | |
1810 src_idx = ipa_get_jf_pass_through_formal_id (jfunc); | |
1811 if (code != NOP_EXPR) | |
1812 operand = ipa_get_jf_pass_through_operand (jfunc); | |
1813 } | |
1814 else | |
1815 { | |
1816 code = POINTER_PLUS_EXPR; | |
1817 src_idx = ipa_get_jf_ancestor_formal_id (jfunc); | |
1818 unsigned HOST_WIDE_INT offset = ipa_get_jf_ancestor_offset (jfunc) / BITS_PER_UNIT; | |
1819 operand = build_int_cstu (size_type_node, offset); | |
1820 } | |
1821 | |
1822 struct ipcp_param_lattices *src_lats | |
1823 = ipa_get_parm_lattices (caller_info, src_idx); | |
1824 | |
1825 /* Try to propagate bits if src_lattice is bottom, but jfunc is known. | |
1826 for eg consider: | |
1827 int f(int x) | |
1828 { | |
1829 g (x & 0xff); | |
1830 } | |
1831 Assume lattice for x is bottom, however we can still propagate | |
1832 result of x & 0xff == 0xff, which gets computed during ccp1 pass | |
1833 and we store it in jump function during analysis stage. */ | |
1834 | |
1835 if (src_lats->bits_lattice.bottom_p () | |
1836 && jfunc->bits) | |
1837 return dest_lattice->meet_with (jfunc->bits->value, jfunc->bits->mask, | |
1838 precision); | |
1839 else | |
1840 return dest_lattice->meet_with (src_lats->bits_lattice, precision, sgn, | |
1841 code, operand); | |
1842 } | |
1843 | |
1844 else if (jfunc->type == IPA_JF_ANCESTOR) | |
1845 return dest_lattice->set_to_bottom (); | |
1846 else if (jfunc->bits) | |
1847 return dest_lattice->meet_with (jfunc->bits->value, jfunc->bits->mask, | |
1848 precision); | |
1849 else | |
1850 return dest_lattice->set_to_bottom (); | |
1851 } | |
1852 | |
1853 /* Emulate effects of unary OPERATION and/or conversion from SRC_TYPE to | |
1854 DST_TYPE on value range in SRC_VR and store it to DST_VR. Return true if | |
1855 the result is a range or an anti-range. */ | |
1856 | |
1857 static bool | |
1858 ipa_vr_operation_and_type_effects (value_range *dst_vr, value_range *src_vr, | |
1859 enum tree_code operation, | |
1860 tree dst_type, tree src_type) | |
1861 { | |
1862 memset (dst_vr, 0, sizeof (*dst_vr)); | |
1863 extract_range_from_unary_expr (dst_vr, operation, dst_type, src_vr, src_type); | |
1864 if (dst_vr->type == VR_RANGE || dst_vr->type == VR_ANTI_RANGE) | |
1865 return true; | |
1866 else | |
1867 return false; | |
1868 } | |
1869 | |
1870 /* Propagate value range across jump function JFUNC that is associated with | |
1871 edge CS with param of callee of PARAM_TYPE and update DEST_PLATS | |
1872 accordingly. */ | |
1873 | |
1874 static bool | |
1875 propagate_vr_across_jump_function (cgraph_edge *cs, ipa_jump_func *jfunc, | |
1876 struct ipcp_param_lattices *dest_plats, | |
1877 tree param_type) | |
1878 { | |
1879 ipcp_vr_lattice *dest_lat = &dest_plats->m_value_range; | |
1880 | |
1881 if (dest_lat->bottom_p ()) | |
1882 return false; | |
1883 | |
1884 if (!param_type | |
1885 || (!INTEGRAL_TYPE_P (param_type) | |
1886 && !POINTER_TYPE_P (param_type))) | |
1887 return dest_lat->set_to_bottom (); | |
1888 | |
1889 if (jfunc->type == IPA_JF_PASS_THROUGH) | |
1890 { | |
1891 enum tree_code operation = ipa_get_jf_pass_through_operation (jfunc); | |
1892 | |
1893 if (TREE_CODE_CLASS (operation) == tcc_unary) | |
1894 { | |
1895 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller); | |
1896 int src_idx = ipa_get_jf_pass_through_formal_id (jfunc); | |
1897 tree operand_type = ipa_get_type (caller_info, src_idx); | |
1898 struct ipcp_param_lattices *src_lats | |
1899 = ipa_get_parm_lattices (caller_info, src_idx); | |
1900 | |
1901 if (src_lats->m_value_range.bottom_p ()) | |
1902 return dest_lat->set_to_bottom (); | |
1903 value_range vr; | |
1904 if (ipa_vr_operation_and_type_effects (&vr, | |
1905 &src_lats->m_value_range.m_vr, | |
1906 operation, param_type, | |
1907 operand_type)) | |
1908 return dest_lat->meet_with (&vr); | |
1909 } | |
1910 } | |
1911 else if (jfunc->type == IPA_JF_CONST) | |
1912 { | |
1913 tree val = ipa_get_jf_constant (jfunc); | |
1914 if (TREE_CODE (val) == INTEGER_CST) | |
1915 { | |
1916 val = fold_convert (param_type, val); | |
1917 if (TREE_OVERFLOW_P (val)) | |
1918 val = drop_tree_overflow (val); | |
1919 | |
1920 value_range tmpvr; | |
1921 memset (&tmpvr, 0, sizeof (tmpvr)); | |
1922 tmpvr.type = VR_RANGE; | |
1923 tmpvr.min = val; | |
1924 tmpvr.max = val; | |
1925 return dest_lat->meet_with (&tmpvr); | |
1926 } | |
1927 } | |
1928 | |
1929 value_range vr; | |
1930 if (jfunc->m_vr | |
1931 && ipa_vr_operation_and_type_effects (&vr, jfunc->m_vr, NOP_EXPR, | |
1932 param_type, | |
1933 TREE_TYPE (jfunc->m_vr->min))) | |
1934 return dest_lat->meet_with (&vr); | |
1935 else | |
1936 return dest_lat->set_to_bottom (); | |
1937 } | |
1938 | |
1939 /* If DEST_PLATS already has aggregate items, check that aggs_by_ref matches | |
1940 NEW_AGGS_BY_REF and if not, mark all aggs as bottoms and return true (in all | |
1941 other cases, return false). If there are no aggregate items, set | |
1942 aggs_by_ref to NEW_AGGS_BY_REF. */ | |
1943 | |
1944 static bool | |
1945 set_check_aggs_by_ref (struct ipcp_param_lattices *dest_plats, | |
1946 bool new_aggs_by_ref) | |
1947 { | |
1948 if (dest_plats->aggs) | |
1949 { | |
1950 if (dest_plats->aggs_by_ref != new_aggs_by_ref) | |
1951 { | |
1952 set_agg_lats_to_bottom (dest_plats); | |
1953 return true; | |
1954 } | |
1955 } | |
1956 else | |
1957 dest_plats->aggs_by_ref = new_aggs_by_ref; | |
1958 return false; | |
1959 } | |
1960 | |
1961 /* Walk aggregate lattices in DEST_PLATS from ***AGLAT on, until ***aglat is an | |
1962 already existing lattice for the given OFFSET and SIZE, marking all skipped | |
1963 lattices as containing variable and checking for overlaps. If there is no | |
1964 already existing lattice for the OFFSET and VAL_SIZE, create one, initialize | |
1965 it with offset, size and contains_variable to PRE_EXISTING, and return true, | |
1966 unless there are too many already. If there are two many, return false. If | |
1967 there are overlaps turn whole DEST_PLATS to bottom and return false. If any | |
1968 skipped lattices were newly marked as containing variable, set *CHANGE to | |
1969 true. */ | |
1970 | |
1971 static bool | |
1972 merge_agg_lats_step (struct ipcp_param_lattices *dest_plats, | |
1973 HOST_WIDE_INT offset, HOST_WIDE_INT val_size, | |
1974 struct ipcp_agg_lattice ***aglat, | |
1975 bool pre_existing, bool *change) | |
1976 { | |
1977 gcc_checking_assert (offset >= 0); | |
1978 | |
1979 while (**aglat && (**aglat)->offset < offset) | |
1980 { | |
1981 if ((**aglat)->offset + (**aglat)->size > offset) | |
1982 { | |
1983 set_agg_lats_to_bottom (dest_plats); | |
1984 return false; | |
1985 } | |
1986 *change |= (**aglat)->set_contains_variable (); | |
1987 *aglat = &(**aglat)->next; | |
1988 } | |
1989 | |
1990 if (**aglat && (**aglat)->offset == offset) | |
1991 { | |
1992 if ((**aglat)->size != val_size | |
1993 || ((**aglat)->next | |
1994 && (**aglat)->next->offset < offset + val_size)) | |
1995 { | |
1996 set_agg_lats_to_bottom (dest_plats); | |
1997 return false; | |
1998 } | |
1999 gcc_checking_assert (!(**aglat)->next | |
2000 || (**aglat)->next->offset >= offset + val_size); | |
2001 return true; | |
2002 } | |
2003 else | |
2004 { | |
2005 struct ipcp_agg_lattice *new_al; | |
2006 | |
2007 if (**aglat && (**aglat)->offset < offset + val_size) | |
2008 { | |
2009 set_agg_lats_to_bottom (dest_plats); | |
2010 return false; | |
2011 } | |
2012 if (dest_plats->aggs_count == PARAM_VALUE (PARAM_IPA_MAX_AGG_ITEMS)) | |
2013 return false; | |
2014 dest_plats->aggs_count++; | |
2015 new_al = ipcp_agg_lattice_pool.allocate (); | |
2016 memset (new_al, 0, sizeof (*new_al)); | |
2017 | |
2018 new_al->offset = offset; | |
2019 new_al->size = val_size; | |
2020 new_al->contains_variable = pre_existing; | |
2021 | |
2022 new_al->next = **aglat; | |
2023 **aglat = new_al; | |
2024 return true; | |
2025 } | |
2026 } | |
2027 | |
2028 /* Set all AGLAT and all other aggregate lattices reachable by next pointers as | |
2029 containing an unknown value. */ | |
2030 | |
2031 static bool | |
2032 set_chain_of_aglats_contains_variable (struct ipcp_agg_lattice *aglat) | |
2033 { | |
2034 bool ret = false; | |
2035 while (aglat) | |
2036 { | |
2037 ret |= aglat->set_contains_variable (); | |
2038 aglat = aglat->next; | |
2039 } | |
2040 return ret; | |
2041 } | |
2042 | |
2043 /* Merge existing aggregate lattices in SRC_PLATS to DEST_PLATS, subtracting | |
2044 DELTA_OFFSET. CS is the call graph edge and SRC_IDX the index of the source | |
2045 parameter used for lattice value sources. Return true if DEST_PLATS changed | |
2046 in any way. */ | |
2047 | |
2048 static bool | |
2049 merge_aggregate_lattices (struct cgraph_edge *cs, | |
2050 struct ipcp_param_lattices *dest_plats, | |
2051 struct ipcp_param_lattices *src_plats, | |
2052 int src_idx, HOST_WIDE_INT offset_delta) | |
2053 { | |
2054 bool pre_existing = dest_plats->aggs != NULL; | |
2055 struct ipcp_agg_lattice **dst_aglat; | |
2056 bool ret = false; | |
2057 | |
2058 if (set_check_aggs_by_ref (dest_plats, src_plats->aggs_by_ref)) | |
2059 return true; | |
2060 if (src_plats->aggs_bottom) | |
2061 return set_agg_lats_contain_variable (dest_plats); | |
2062 if (src_plats->aggs_contain_variable) | |
2063 ret |= set_agg_lats_contain_variable (dest_plats); | |
2064 dst_aglat = &dest_plats->aggs; | |
2065 | |
2066 for (struct ipcp_agg_lattice *src_aglat = src_plats->aggs; | |
2067 src_aglat; | |
2068 src_aglat = src_aglat->next) | |
2069 { | |
2070 HOST_WIDE_INT new_offset = src_aglat->offset - offset_delta; | |
2071 | |
2072 if (new_offset < 0) | |
2073 continue; | |
2074 if (merge_agg_lats_step (dest_plats, new_offset, src_aglat->size, | |
2075 &dst_aglat, pre_existing, &ret)) | |
2076 { | |
2077 struct ipcp_agg_lattice *new_al = *dst_aglat; | |
2078 | |
2079 dst_aglat = &(*dst_aglat)->next; | |
2080 if (src_aglat->bottom) | |
2081 { | |
2082 ret |= new_al->set_contains_variable (); | |
2083 continue; | |
2084 } | |
2085 if (src_aglat->contains_variable) | |
2086 ret |= new_al->set_contains_variable (); | |
2087 for (ipcp_value<tree> *val = src_aglat->values; | |
2088 val; | |
2089 val = val->next) | |
2090 ret |= new_al->add_value (val->value, cs, val, src_idx, | |
2091 src_aglat->offset); | |
2092 } | |
2093 else if (dest_plats->aggs_bottom) | |
2094 return true; | |
2095 } | |
2096 ret |= set_chain_of_aglats_contains_variable (*dst_aglat); | |
2097 return ret; | |
2098 } | |
2099 | |
2100 /* Determine whether there is anything to propagate FROM SRC_PLATS through a | |
2101 pass-through JFUNC and if so, whether it has conform and conforms to the | |
2102 rules about propagating values passed by reference. */ | |
2103 | |
2104 static bool | |
2105 agg_pass_through_permissible_p (struct ipcp_param_lattices *src_plats, | |
2106 struct ipa_jump_func *jfunc) | |
2107 { | |
2108 return src_plats->aggs | |
2109 && (!src_plats->aggs_by_ref | |
2110 || ipa_get_jf_pass_through_agg_preserved (jfunc)); | |
2111 } | |
2112 | |
2113 /* Propagate scalar values across jump function JFUNC that is associated with | |
2114 edge CS and put the values into DEST_LAT. */ | |
2115 | |
2116 static bool | |
2117 propagate_aggs_across_jump_function (struct cgraph_edge *cs, | |
2118 struct ipa_jump_func *jfunc, | |
2119 struct ipcp_param_lattices *dest_plats) | |
2120 { | |
2121 bool ret = false; | |
2122 | |
2123 if (dest_plats->aggs_bottom) | |
2124 return false; | |
2125 | |
2126 if (jfunc->type == IPA_JF_PASS_THROUGH | |
2127 && ipa_get_jf_pass_through_operation (jfunc) == NOP_EXPR) | |
2128 { | |
2129 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller); | |
2130 int src_idx = ipa_get_jf_pass_through_formal_id (jfunc); | |
2131 struct ipcp_param_lattices *src_plats; | |
2132 | |
2133 src_plats = ipa_get_parm_lattices (caller_info, src_idx); | |
2134 if (agg_pass_through_permissible_p (src_plats, jfunc)) | |
2135 { | |
2136 /* Currently we do not produce clobber aggregate jump | |
2137 functions, replace with merging when we do. */ | |
2138 gcc_assert (!jfunc->agg.items); | |
2139 ret |= merge_aggregate_lattices (cs, dest_plats, src_plats, | |
2140 src_idx, 0); | |
2141 } | |
2142 else | |
2143 ret |= set_agg_lats_contain_variable (dest_plats); | |
2144 } | |
2145 else if (jfunc->type == IPA_JF_ANCESTOR | |
2146 && ipa_get_jf_ancestor_agg_preserved (jfunc)) | |
2147 { | |
2148 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller); | |
2149 int src_idx = ipa_get_jf_ancestor_formal_id (jfunc); | |
2150 struct ipcp_param_lattices *src_plats; | |
2151 | |
2152 src_plats = ipa_get_parm_lattices (caller_info, src_idx); | |
2153 if (src_plats->aggs && src_plats->aggs_by_ref) | |
2154 { | |
2155 /* Currently we do not produce clobber aggregate jump | |
2156 functions, replace with merging when we do. */ | |
2157 gcc_assert (!jfunc->agg.items); | |
2158 ret |= merge_aggregate_lattices (cs, dest_plats, src_plats, src_idx, | |
2159 ipa_get_jf_ancestor_offset (jfunc)); | |
2160 } | |
2161 else if (!src_plats->aggs_by_ref) | |
2162 ret |= set_agg_lats_to_bottom (dest_plats); | |
2163 else | |
2164 ret |= set_agg_lats_contain_variable (dest_plats); | |
2165 } | |
2166 else if (jfunc->agg.items) | |
2167 { | |
2168 bool pre_existing = dest_plats->aggs != NULL; | |
2169 struct ipcp_agg_lattice **aglat = &dest_plats->aggs; | |
2170 struct ipa_agg_jf_item *item; | |
2171 int i; | |
2172 | |
2173 if (set_check_aggs_by_ref (dest_plats, jfunc->agg.by_ref)) | |
2174 return true; | |
2175 | |
2176 FOR_EACH_VEC_ELT (*jfunc->agg.items, i, item) | |
2177 { | |
2178 HOST_WIDE_INT val_size; | |
2179 | |
2180 if (item->offset < 0) | |
2181 continue; | |
2182 gcc_checking_assert (is_gimple_ip_invariant (item->value)); | |
2183 val_size = tree_to_uhwi (TYPE_SIZE (TREE_TYPE (item->value))); | |
2184 | |
2185 if (merge_agg_lats_step (dest_plats, item->offset, val_size, | |
2186 &aglat, pre_existing, &ret)) | |
2187 { | |
2188 ret |= (*aglat)->add_value (item->value, cs, NULL, 0, 0); | |
2189 aglat = &(*aglat)->next; | |
2190 } | |
2191 else if (dest_plats->aggs_bottom) | |
2192 return true; | |
2193 } | |
2194 | |
2195 ret |= set_chain_of_aglats_contains_variable (*aglat); | |
2196 } | |
2197 else | |
2198 ret |= set_agg_lats_contain_variable (dest_plats); | |
2199 | |
2200 return ret; | |
2201 } | |
2202 | |
2203 /* Return true if on the way cfrom CS->caller to the final (non-alias and | |
2204 non-thunk) destination, the call passes through a thunk. */ | |
2205 | |
2206 static bool | |
2207 call_passes_through_thunk_p (cgraph_edge *cs) | |
2208 { | |
2209 cgraph_node *alias_or_thunk = cs->callee; | |
2210 while (alias_or_thunk->alias) | |
2211 alias_or_thunk = alias_or_thunk->get_alias_target (); | |
2212 return alias_or_thunk->thunk.thunk_p; | |
2213 } | |
2214 | |
2215 /* Propagate constants from the caller to the callee of CS. INFO describes the | |
2216 caller. */ | |
2217 | |
2218 static bool | |
2219 propagate_constants_across_call (struct cgraph_edge *cs) | |
2220 { | |
2221 struct ipa_node_params *callee_info; | |
2222 enum availability availability; | |
2223 cgraph_node *callee; | |
2224 struct ipa_edge_args *args; | |
2225 bool ret = false; | |
2226 int i, args_count, parms_count; | |
2227 | |
2228 callee = cs->callee->function_symbol (&availability); | |
2229 if (!callee->definition) | |
2230 return false; | |
2231 gcc_checking_assert (callee->has_gimple_body_p ()); | |
2232 callee_info = IPA_NODE_REF (callee); | |
2233 | |
2234 args = IPA_EDGE_REF (cs); | |
2235 args_count = ipa_get_cs_argument_count (args); | |
2236 parms_count = ipa_get_param_count (callee_info); | |
2237 if (parms_count == 0) | |
2238 return false; | |
2239 | |
2240 /* No propagation through instrumentation thunks is available yet. | |
2241 It should be possible with proper mapping of call args and | |
2242 instrumented callee params in the propagation loop below. But | |
2243 this case mostly occurs when legacy code calls instrumented code | |
2244 and it is not a primary target for optimizations. | |
2245 We detect instrumentation thunks in aliases and thunks chain by | |
2246 checking instrumentation_clone flag for chain source and target. | |
2247 Going through instrumentation thunks we always have it changed | |
2248 from 0 to 1 and all other nodes do not change it. */ | |
2249 if (!cs->callee->instrumentation_clone | |
2250 && callee->instrumentation_clone) | |
2251 { | |
2252 for (i = 0; i < parms_count; i++) | |
2253 ret |= set_all_contains_variable (ipa_get_parm_lattices (callee_info, | |
2254 i)); | |
2255 return ret; | |
2256 } | |
2257 | |
2258 /* If this call goes through a thunk we must not propagate to the first (0th) | |
2259 parameter. However, we might need to uncover a thunk from below a series | |
2260 of aliases first. */ | |
2261 if (call_passes_through_thunk_p (cs)) | |
2262 { | |
2263 ret |= set_all_contains_variable (ipa_get_parm_lattices (callee_info, | |
2264 0)); | |
2265 i = 1; | |
2266 } | |
2267 else | |
2268 i = 0; | |
2269 | |
2270 for (; (i < args_count) && (i < parms_count); i++) | |
2271 { | |
2272 struct ipa_jump_func *jump_func = ipa_get_ith_jump_func (args, i); | |
2273 struct ipcp_param_lattices *dest_plats; | |
2274 tree param_type = ipa_get_type (callee_info, i); | |
2275 | |
2276 dest_plats = ipa_get_parm_lattices (callee_info, i); | |
2277 if (availability == AVAIL_INTERPOSABLE) | |
2278 ret |= set_all_contains_variable (dest_plats); | |
2279 else | |
2280 { | |
2281 ret |= propagate_scalar_across_jump_function (cs, jump_func, | |
2282 &dest_plats->itself); | |
2283 ret |= propagate_context_across_jump_function (cs, jump_func, i, | |
2284 &dest_plats->ctxlat); | |
2285 ret | |
2286 |= propagate_bits_across_jump_function (cs, i, jump_func, | |
2287 &dest_plats->bits_lattice); | |
2288 ret |= propagate_aggs_across_jump_function (cs, jump_func, | |
2289 dest_plats); | |
2290 if (opt_for_fn (callee->decl, flag_ipa_vrp)) | |
2291 ret |= propagate_vr_across_jump_function (cs, jump_func, | |
2292 dest_plats, param_type); | |
317 else | 2293 else |
318 restype = TREE_TYPE (cst); | 2294 ret |= dest_plats->m_value_range.set_to_bottom (); |
319 cst = fold_binary (jfunc->value.pass_through.operation, | 2295 } |
320 restype, cst, jfunc->value.pass_through.operand); | 2296 } |
321 } | 2297 for (; i < parms_count; i++) |
322 if (!cst || !is_gimple_ip_invariant (cst)) | 2298 ret |= set_all_contains_variable (ipa_get_parm_lattices (callee_info, i)); |
323 lat->type = IPA_BOTTOM; | 2299 |
324 lat->constant = cst; | 2300 return ret; |
325 } | 2301 } |
326 else if (jfunc->type == IPA_JF_ANCESTOR) | 2302 |
327 { | 2303 /* If an indirect edge IE can be turned into a direct one based on KNOWN_VALS |
328 struct ipcp_lattice *caller_lat; | 2304 KNOWN_CONTEXTS, KNOWN_AGGS or AGG_REPS return the destination. The latter |
2305 three can be NULL. If AGG_REPS is not NULL, KNOWN_AGGS is ignored. */ | |
2306 | |
2307 static tree | |
2308 ipa_get_indirect_edge_target_1 (struct cgraph_edge *ie, | |
2309 vec<tree> known_csts, | |
2310 vec<ipa_polymorphic_call_context> known_contexts, | |
2311 vec<ipa_agg_jump_function_p> known_aggs, | |
2312 struct ipa_agg_replacement_value *agg_reps, | |
2313 bool *speculative) | |
2314 { | |
2315 int param_index = ie->indirect_info->param_index; | |
2316 HOST_WIDE_INT anc_offset; | |
2317 tree t; | |
2318 tree target = NULL; | |
2319 | |
2320 *speculative = false; | |
2321 | |
2322 if (param_index == -1 | |
2323 || known_csts.length () <= (unsigned int) param_index) | |
2324 return NULL_TREE; | |
2325 | |
2326 if (!ie->indirect_info->polymorphic) | |
2327 { | |
329 tree t; | 2328 tree t; |
330 | 2329 |
331 caller_lat = ipcp_get_lattice (info, jfunc->value.ancestor.formal_id); | 2330 if (ie->indirect_info->agg_contents) |
332 lat->type = caller_lat->type; | 2331 { |
333 if (caller_lat->type != IPA_CONST_VALUE) | 2332 t = NULL; |
334 return; | 2333 if (agg_reps && ie->indirect_info->guaranteed_unmodified) |
335 if (TREE_CODE (caller_lat->constant) != ADDR_EXPR) | |
336 { | |
337 /* This can happen when the constant is a NULL pointer. */ | |
338 lat->type = IPA_BOTTOM; | |
339 return; | |
340 } | |
341 t = TREE_OPERAND (caller_lat->constant, 0); | |
342 t = build_ref_for_offset (EXPR_LOCATION (t), t, | |
343 jfunc->value.ancestor.offset, | |
344 jfunc->value.ancestor.type, NULL, false); | |
345 lat->constant = build_fold_addr_expr (t); | |
346 } | |
347 else | |
348 lat->type = IPA_BOTTOM; | |
349 } | |
350 | |
351 /* True when OLD_LAT and NEW_LAT values are not the same. */ | |
352 | |
353 static bool | |
354 ipcp_lattice_changed (struct ipcp_lattice *old_lat, | |
355 struct ipcp_lattice *new_lat) | |
356 { | |
357 if (old_lat->type == new_lat->type) | |
358 { | |
359 if (!ipcp_lat_is_const (old_lat)) | |
360 return false; | |
361 if (ipcp_lats_are_equal (old_lat, new_lat)) | |
362 return false; | |
363 } | |
364 return true; | |
365 } | |
366 | |
367 /* Print all ipcp_lattices of all functions to F. */ | |
368 static void | |
369 ipcp_print_all_lattices (FILE * f) | |
370 { | |
371 struct cgraph_node *node; | |
372 int i, count; | |
373 | |
374 fprintf (f, "\nLattice:\n"); | |
375 for (node = cgraph_nodes; node; node = node->next) | |
376 { | |
377 struct ipa_node_params *info; | |
378 | |
379 if (!node->analyzed) | |
380 continue; | |
381 info = IPA_NODE_REF (node); | |
382 fprintf (f, " Node: %s:\n", cgraph_node_name (node)); | |
383 count = ipa_get_param_count (info); | |
384 for (i = 0; i < count; i++) | |
385 { | |
386 struct ipcp_lattice *lat = ipcp_get_lattice (info, i); | |
387 | |
388 fprintf (f, " param [%d]: ", i); | |
389 if (lat->type == IPA_CONST_VALUE) | |
390 { | 2334 { |
391 tree cst = lat->constant; | 2335 while (agg_reps) |
392 fprintf (f, "type is CONST "); | |
393 print_generic_expr (f, cst, 0); | |
394 if (TREE_CODE (cst) == ADDR_EXPR | |
395 && TREE_CODE (TREE_OPERAND (cst, 0)) == CONST_DECL) | |
396 { | 2336 { |
397 fprintf (f, " -> "); | 2337 if (agg_reps->index == param_index |
398 print_generic_expr (f, DECL_INITIAL (TREE_OPERAND (cst, 0)), | 2338 && agg_reps->offset == ie->indirect_info->offset |
399 0); | 2339 && agg_reps->by_ref == ie->indirect_info->by_ref) |
2340 { | |
2341 t = agg_reps->value; | |
2342 break; | |
2343 } | |
2344 agg_reps = agg_reps->next; | |
400 } | 2345 } |
401 } | 2346 } |
402 else if (lat->type == IPA_TOP) | 2347 if (!t) |
403 fprintf (f, "type is TOP"); | 2348 { |
404 else | 2349 struct ipa_agg_jump_function *agg; |
405 fprintf (f, "type is BOTTOM"); | 2350 if (known_aggs.length () > (unsigned int) param_index) |
406 if (ipa_param_cannot_devirtualize_p (info, i)) | 2351 agg = known_aggs[param_index]; |
407 fprintf (f, " - cannot_devirtualize set\n"); | 2352 else |
408 else if (ipa_param_types_vec_empty (info, i)) | 2353 agg = NULL; |
409 fprintf (f, " - type list empty\n"); | 2354 bool from_global_constant; |
410 else | 2355 t = ipa_find_agg_cst_for_param (agg, known_csts[param_index], |
411 fprintf (f, "\n"); | 2356 ie->indirect_info->offset, |
412 } | 2357 ie->indirect_info->by_ref, |
413 } | 2358 &from_global_constant); |
414 } | 2359 if (t |
415 | 2360 && !from_global_constant |
416 /* Return true if ipcp algorithms would allow cloning NODE. */ | 2361 && !ie->indirect_info->guaranteed_unmodified) |
417 | 2362 t = NULL_TREE; |
418 static bool | 2363 } |
419 ipcp_versionable_function_p (struct cgraph_node *node) | 2364 } |
420 { | 2365 else |
421 struct cgraph_edge *edge; | 2366 t = known_csts[param_index]; |
422 | 2367 |
423 /* There are a number of generic reasons functions cannot be versioned. We | 2368 if (t |
424 also cannot remove parameters if there are type attributes such as fnspec | 2369 && TREE_CODE (t) == ADDR_EXPR |
425 present. */ | 2370 && TREE_CODE (TREE_OPERAND (t, 0)) == FUNCTION_DECL) |
426 if (!node->local.versionable | 2371 return TREE_OPERAND (t, 0); |
427 || TYPE_ATTRIBUTES (TREE_TYPE (node->decl))) | 2372 else |
428 return false; | 2373 return NULL_TREE; |
429 | 2374 } |
430 /* Removing arguments doesn't work if the function takes varargs | 2375 |
431 or use __builtin_apply_args. */ | 2376 if (!opt_for_fn (ie->caller->decl, flag_devirtualize)) |
432 for (edge = node->callees; edge; edge = edge->next_callee) | 2377 return NULL_TREE; |
433 { | 2378 |
434 tree t = edge->callee->decl; | 2379 gcc_assert (!ie->indirect_info->agg_contents); |
435 if (DECL_BUILT_IN_CLASS (t) == BUILT_IN_NORMAL | 2380 anc_offset = ie->indirect_info->offset; |
436 && (DECL_FUNCTION_CODE (t) == BUILT_IN_APPLY_ARGS | 2381 |
437 || DECL_FUNCTION_CODE (t) == BUILT_IN_VA_START)) | 2382 t = NULL; |
438 return false; | 2383 |
439 } | 2384 /* Try to work out value of virtual table pointer value in replacemnets. */ |
440 | 2385 if (!t && agg_reps && !ie->indirect_info->by_ref) |
441 return true; | 2386 { |
442 } | 2387 while (agg_reps) |
443 | 2388 { |
444 /* Return true if this NODE is viable candidate for cloning. */ | 2389 if (agg_reps->index == param_index |
445 static bool | 2390 && agg_reps->offset == ie->indirect_info->offset |
446 ipcp_cloning_candidate_p (struct cgraph_node *node) | 2391 && agg_reps->by_ref) |
447 { | 2392 { |
448 int n_calls = 0; | 2393 t = agg_reps->value; |
449 int n_hot_calls = 0; | 2394 break; |
450 gcov_type direct_call_sum = 0; | 2395 } |
451 struct cgraph_edge *e; | 2396 agg_reps = agg_reps->next; |
452 | 2397 } |
453 /* We never clone functions that are not visible from outside. | 2398 } |
454 FIXME: in future we should clone such functions when they are called with | 2399 |
455 different constants, but current ipcp implementation is not good on this. | 2400 /* Try to work out value of virtual table pointer value in known |
456 */ | 2401 aggregate values. */ |
457 if (cgraph_only_called_directly_p (node) || !node->analyzed) | 2402 if (!t && known_aggs.length () > (unsigned int) param_index |
458 return false; | 2403 && !ie->indirect_info->by_ref) |
459 | 2404 { |
460 /* When function address is taken, we are pretty sure it will be called in hidden way. */ | 2405 struct ipa_agg_jump_function *agg; |
461 if (node->address_taken) | 2406 agg = known_aggs[param_index]; |
462 { | 2407 t = ipa_find_agg_cst_for_param (agg, known_csts[param_index], |
463 if (dump_file) | 2408 ie->indirect_info->offset, true); |
464 fprintf (dump_file, "Not considering %s for cloning; address is taken.\n", | 2409 } |
465 cgraph_node_name (node)); | 2410 |
466 return false; | 2411 /* If we found the virtual table pointer, lookup the target. */ |
467 } | 2412 if (t) |
468 | 2413 { |
469 if (cgraph_function_body_availability (node) <= AVAIL_OVERWRITABLE) | 2414 tree vtable; |
470 { | 2415 unsigned HOST_WIDE_INT offset; |
471 if (dump_file) | 2416 if (vtable_pointer_value_to_vtable (t, &vtable, &offset)) |
472 fprintf (dump_file, "Not considering %s for cloning; body is overwritable.\n", | 2417 { |
473 cgraph_node_name (node)); | 2418 bool can_refer; |
474 return false; | 2419 target = gimple_get_virt_method_for_vtable (ie->indirect_info->otr_token, |
475 } | 2420 vtable, offset, &can_refer); |
476 if (!ipcp_versionable_function_p (node)) | 2421 if (can_refer) |
477 { | 2422 { |
478 if (dump_file) | 2423 if (!target |
479 fprintf (dump_file, "Not considering %s for cloning; body is not versionable.\n", | 2424 || (TREE_CODE (TREE_TYPE (target)) == FUNCTION_TYPE |
480 cgraph_node_name (node)); | 2425 && DECL_FUNCTION_CODE (target) == BUILT_IN_UNREACHABLE) |
481 return false; | 2426 || !possible_polymorphic_call_target_p |
482 } | 2427 (ie, cgraph_node::get (target))) |
483 for (e = node->callers; e; e = e->next_caller) | 2428 { |
484 { | 2429 /* Do not speculate builtin_unreachable, it is stupid! */ |
485 direct_call_sum += e->count; | 2430 if (ie->indirect_info->vptr_changed) |
486 n_calls ++; | 2431 return NULL; |
487 if (cgraph_maybe_hot_edge_p (e)) | 2432 target = ipa_impossible_devirt_target (ie, target); |
488 n_hot_calls ++; | 2433 } |
489 } | 2434 *speculative = ie->indirect_info->vptr_changed; |
490 | 2435 if (!*speculative) |
491 if (!n_calls) | 2436 return target; |
492 { | 2437 } |
493 if (dump_file) | 2438 } |
494 fprintf (dump_file, "Not considering %s for cloning; no direct calls.\n", | 2439 } |
495 cgraph_node_name (node)); | 2440 |
496 return false; | 2441 /* Do we know the constant value of pointer? */ |
497 } | 2442 if (!t) |
498 if (node->local.inline_summary.self_size < n_calls) | 2443 t = known_csts[param_index]; |
499 { | 2444 |
500 if (dump_file) | 2445 gcc_checking_assert (!t || TREE_CODE (t) != TREE_BINFO); |
501 fprintf (dump_file, "Considering %s for cloning; code would shrink.\n", | 2446 |
502 cgraph_node_name (node)); | 2447 ipa_polymorphic_call_context context; |
503 return true; | 2448 if (known_contexts.length () > (unsigned int) param_index) |
504 } | 2449 { |
505 | 2450 context = known_contexts[param_index]; |
506 if (!flag_ipa_cp_clone) | 2451 context.offset_by (anc_offset); |
507 { | 2452 if (ie->indirect_info->vptr_changed) |
508 if (dump_file) | 2453 context.possible_dynamic_type_change (ie->in_polymorphic_cdtor, |
509 fprintf (dump_file, "Not considering %s for cloning; -fipa-cp-clone disabled.\n", | 2454 ie->indirect_info->otr_type); |
510 cgraph_node_name (node)); | 2455 if (t) |
511 return false; | 2456 { |
512 } | 2457 ipa_polymorphic_call_context ctx2 = ipa_polymorphic_call_context |
513 | 2458 (t, ie->indirect_info->otr_type, anc_offset); |
514 if (!optimize_function_for_speed_p (DECL_STRUCT_FUNCTION (node->decl))) | 2459 if (!ctx2.useless_p ()) |
515 { | 2460 context.combine_with (ctx2, ie->indirect_info->otr_type); |
516 if (dump_file) | 2461 } |
517 fprintf (dump_file, "Not considering %s for cloning; optimizing it for size.\n", | 2462 } |
518 cgraph_node_name (node)); | 2463 else if (t) |
519 return false; | 2464 { |
520 } | 2465 context = ipa_polymorphic_call_context (t, ie->indirect_info->otr_type, |
521 | 2466 anc_offset); |
522 /* When profile is available and function is hot, propagate into it even if | 2467 if (ie->indirect_info->vptr_changed) |
523 calls seems cold; constant propagation can improve function's speed | 2468 context.possible_dynamic_type_change (ie->in_polymorphic_cdtor, |
524 significantly. */ | 2469 ie->indirect_info->otr_type); |
525 if (max_count) | 2470 } |
526 { | |
527 if (direct_call_sum > node->count * 90 / 100) | |
528 { | |
529 if (dump_file) | |
530 fprintf (dump_file, "Considering %s for cloning; usually called directly.\n", | |
531 cgraph_node_name (node)); | |
532 return true; | |
533 } | |
534 } | |
535 if (!n_hot_calls) | |
536 { | |
537 if (dump_file) | |
538 fprintf (dump_file, "Not considering %s for cloning; no hot calls.\n", | |
539 cgraph_node_name (node)); | |
540 return false; | |
541 } | |
542 if (dump_file) | |
543 fprintf (dump_file, "Considering %s for cloning.\n", | |
544 cgraph_node_name (node)); | |
545 return true; | |
546 } | |
547 | |
548 /* Mark parameter with index I of function described by INFO as unsuitable for | |
549 devirtualization. Return true if it has already been marked so. */ | |
550 | |
551 static bool | |
552 ipa_set_param_cannot_devirtualize (struct ipa_node_params *info, int i) | |
553 { | |
554 bool ret = info->params[i].cannot_devirtualize; | |
555 info->params[i].cannot_devirtualize = true; | |
556 if (info->params[i].types) | |
557 VEC_free (tree, heap, info->params[i].types); | |
558 return ret; | |
559 } | |
560 | |
561 /* Initialize ipcp_lattices array. The lattices corresponding to supported | |
562 types (integers, real types and Fortran constants defined as const_decls) | |
563 are initialized to IPA_TOP, the rest of them to IPA_BOTTOM. */ | |
564 static void | |
565 ipcp_initialize_node_lattices (struct cgraph_node *node) | |
566 { | |
567 int i; | |
568 struct ipa_node_params *info = IPA_NODE_REF (node); | |
569 enum ipa_lattice_type type; | |
570 | |
571 if (ipa_is_called_with_var_arguments (info)) | |
572 type = IPA_BOTTOM; | |
573 else if (node->local.local) | |
574 type = IPA_TOP; | |
575 /* When cloning is allowed, we can assume that externally visible functions | |
576 are not called. We will compensate this by cloning later. */ | |
577 else if (ipcp_cloning_candidate_p (node)) | |
578 type = IPA_TOP, n_cloning_candidates ++; | |
579 else | 2471 else |
580 type = IPA_BOTTOM; | 2472 return NULL_TREE; |
581 | 2473 |
582 for (i = 0; i < ipa_get_param_count (info) ; i++) | 2474 vec <cgraph_node *>targets; |
583 { | 2475 bool final; |
584 ipcp_get_lattice (info, i)->type = type; | 2476 |
585 if (type == IPA_BOTTOM) | 2477 targets = possible_polymorphic_call_targets |
586 ipa_set_param_cannot_devirtualize (info, i); | 2478 (ie->indirect_info->otr_type, |
587 } | 2479 ie->indirect_info->otr_token, |
588 } | 2480 context, &final); |
589 | 2481 if (!final || targets.length () > 1) |
590 /* Build a constant tree with type TREE_TYPE and value according to LAT. | 2482 { |
591 Return the tree, or, if it is not possible to convert such value | 2483 struct cgraph_node *node; |
592 to TREE_TYPE, NULL. */ | 2484 if (*speculative) |
593 static tree | 2485 return target; |
594 build_const_val (struct ipcp_lattice *lat, tree tree_type) | 2486 if (!opt_for_fn (ie->caller->decl, flag_devirtualize_speculatively) |
595 { | 2487 || ie->speculative || !ie->maybe_hot_p ()) |
596 tree val; | 2488 return NULL; |
597 | 2489 node = try_speculative_devirtualization (ie->indirect_info->otr_type, |
598 gcc_assert (ipcp_lat_is_const (lat)); | 2490 ie->indirect_info->otr_token, |
599 val = lat->constant; | 2491 context); |
600 | 2492 if (node) |
601 if (!useless_type_conversion_p (tree_type, TREE_TYPE (val))) | 2493 { |
602 { | 2494 *speculative = true; |
603 if (fold_convertible_p (tree_type, val)) | 2495 target = node->decl; |
604 return fold_build1 (NOP_EXPR, tree_type, val); | 2496 } |
605 else if (TYPE_SIZE (tree_type) == TYPE_SIZE (TREE_TYPE (val))) | |
606 return fold_build1 (VIEW_CONVERT_EXPR, tree_type, val); | |
607 else | 2497 else |
608 return NULL; | 2498 return NULL; |
609 } | 2499 } |
610 return val; | 2500 else |
611 } | 2501 { |
612 | 2502 *speculative = false; |
613 /* Compute the proper scale for NODE. It is the ratio between the number of | 2503 if (targets.length () == 1) |
614 direct calls (represented on the incoming cgraph_edges) and sum of all | 2504 target = targets[0]->decl; |
615 invocations of NODE (represented as count in cgraph_node). | 2505 else |
616 | 2506 target = ipa_impossible_devirt_target (ie, NULL_TREE); |
617 FIXME: This code is wrong. Since the callers can be also clones and | 2507 } |
618 the clones are not scaled yet, the sums gets unrealistically high. | 2508 |
619 To properly compute the counts, we would need to do propagation across | 2509 if (target && !possible_polymorphic_call_target_p (ie, |
620 callgraph (as external call to A might imply call to non-cloned B | 2510 cgraph_node::get (target))) |
621 if A's clone calls cloned B). */ | 2511 { |
2512 if (*speculative) | |
2513 return NULL; | |
2514 target = ipa_impossible_devirt_target (ie, target); | |
2515 } | |
2516 | |
2517 return target; | |
2518 } | |
2519 | |
2520 | |
2521 /* If an indirect edge IE can be turned into a direct one based on KNOWN_CSTS, | |
2522 KNOWN_CONTEXTS (which can be vNULL) or KNOWN_AGGS (which also can be vNULL) | |
2523 return the destination. */ | |
2524 | |
2525 tree | |
2526 ipa_get_indirect_edge_target (struct cgraph_edge *ie, | |
2527 vec<tree> known_csts, | |
2528 vec<ipa_polymorphic_call_context> known_contexts, | |
2529 vec<ipa_agg_jump_function_p> known_aggs, | |
2530 bool *speculative) | |
2531 { | |
2532 return ipa_get_indirect_edge_target_1 (ie, known_csts, known_contexts, | |
2533 known_aggs, NULL, speculative); | |
2534 } | |
2535 | |
2536 /* Calculate devirtualization time bonus for NODE, assuming we know KNOWN_CSTS | |
2537 and KNOWN_CONTEXTS. */ | |
2538 | |
2539 static int | |
2540 devirtualization_time_bonus (struct cgraph_node *node, | |
2541 vec<tree> known_csts, | |
2542 vec<ipa_polymorphic_call_context> known_contexts, | |
2543 vec<ipa_agg_jump_function_p> known_aggs) | |
2544 { | |
2545 struct cgraph_edge *ie; | |
2546 int res = 0; | |
2547 | |
2548 for (ie = node->indirect_calls; ie; ie = ie->next_callee) | |
2549 { | |
2550 struct cgraph_node *callee; | |
2551 struct ipa_fn_summary *isummary; | |
2552 enum availability avail; | |
2553 tree target; | |
2554 bool speculative; | |
2555 | |
2556 target = ipa_get_indirect_edge_target (ie, known_csts, known_contexts, | |
2557 known_aggs, &speculative); | |
2558 if (!target) | |
2559 continue; | |
2560 | |
2561 /* Only bare minimum benefit for clearly un-inlineable targets. */ | |
2562 res += 1; | |
2563 callee = cgraph_node::get (target); | |
2564 if (!callee || !callee->definition) | |
2565 continue; | |
2566 callee = callee->function_symbol (&avail); | |
2567 if (avail < AVAIL_AVAILABLE) | |
2568 continue; | |
2569 isummary = ipa_fn_summaries->get (callee); | |
2570 if (!isummary->inlinable) | |
2571 continue; | |
2572 | |
2573 /* FIXME: The values below need re-considering and perhaps also | |
2574 integrating into the cost metrics, at lest in some very basic way. */ | |
2575 if (isummary->size <= MAX_INLINE_INSNS_AUTO / 4) | |
2576 res += 31 / ((int)speculative + 1); | |
2577 else if (isummary->size <= MAX_INLINE_INSNS_AUTO / 2) | |
2578 res += 15 / ((int)speculative + 1); | |
2579 else if (isummary->size <= MAX_INLINE_INSNS_AUTO | |
2580 || DECL_DECLARED_INLINE_P (callee->decl)) | |
2581 res += 7 / ((int)speculative + 1); | |
2582 } | |
2583 | |
2584 return res; | |
2585 } | |
2586 | |
2587 /* Return time bonus incurred because of HINTS. */ | |
2588 | |
2589 static int | |
2590 hint_time_bonus (ipa_hints hints) | |
2591 { | |
2592 int result = 0; | |
2593 if (hints & (INLINE_HINT_loop_iterations | INLINE_HINT_loop_stride)) | |
2594 result += PARAM_VALUE (PARAM_IPA_CP_LOOP_HINT_BONUS); | |
2595 if (hints & INLINE_HINT_array_index) | |
2596 result += PARAM_VALUE (PARAM_IPA_CP_ARRAY_INDEX_HINT_BONUS); | |
2597 return result; | |
2598 } | |
2599 | |
2600 /* If there is a reason to penalize the function described by INFO in the | |
2601 cloning goodness evaluation, do so. */ | |
2602 | |
2603 static inline int64_t | |
2604 incorporate_penalties (ipa_node_params *info, int64_t evaluation) | |
2605 { | |
2606 if (info->node_within_scc) | |
2607 evaluation = (evaluation | |
2608 * (100 - PARAM_VALUE (PARAM_IPA_CP_RECURSION_PENALTY))) / 100; | |
2609 | |
2610 if (info->node_calling_single_call) | |
2611 evaluation = (evaluation | |
2612 * (100 - PARAM_VALUE (PARAM_IPA_CP_SINGLE_CALL_PENALTY))) | |
2613 / 100; | |
2614 | |
2615 return evaluation; | |
2616 } | |
2617 | |
2618 /* Return true if cloning NODE is a good idea, given the estimated TIME_BENEFIT | |
2619 and SIZE_COST and with the sum of frequencies of incoming edges to the | |
2620 potential new clone in FREQUENCIES. */ | |
2621 | |
2622 static bool | |
2623 good_cloning_opportunity_p (struct cgraph_node *node, int time_benefit, | |
2624 int freq_sum, profile_count count_sum, int size_cost) | |
2625 { | |
2626 if (time_benefit == 0 | |
2627 || !opt_for_fn (node->decl, flag_ipa_cp_clone) | |
2628 || node->optimize_for_size_p ()) | |
2629 return false; | |
2630 | |
2631 gcc_assert (size_cost > 0); | |
2632 | |
2633 struct ipa_node_params *info = IPA_NODE_REF (node); | |
2634 if (max_count > profile_count::zero ()) | |
2635 { | |
2636 int factor = RDIV (count_sum.probability_in | |
2637 (max_count).to_reg_br_prob_base () | |
2638 * 1000, REG_BR_PROB_BASE); | |
2639 int64_t evaluation = (((int64_t) time_benefit * factor) | |
2640 / size_cost); | |
2641 evaluation = incorporate_penalties (info, evaluation); | |
2642 | |
2643 if (dump_file && (dump_flags & TDF_DETAILS)) | |
2644 { | |
2645 fprintf (dump_file, " good_cloning_opportunity_p (time: %i, " | |
2646 "size: %i, count_sum: ", time_benefit, size_cost); | |
2647 count_sum.dump (dump_file); | |
2648 fprintf (dump_file, "%s%s) -> evaluation: " "%" PRId64 | |
2649 ", threshold: %i\n", | |
2650 info->node_within_scc ? ", scc" : "", | |
2651 info->node_calling_single_call ? ", single_call" : "", | |
2652 evaluation, PARAM_VALUE (PARAM_IPA_CP_EVAL_THRESHOLD)); | |
2653 } | |
2654 | |
2655 return evaluation >= PARAM_VALUE (PARAM_IPA_CP_EVAL_THRESHOLD); | |
2656 } | |
2657 else | |
2658 { | |
2659 int64_t evaluation = (((int64_t) time_benefit * freq_sum) | |
2660 / size_cost); | |
2661 evaluation = incorporate_penalties (info, evaluation); | |
2662 | |
2663 if (dump_file && (dump_flags & TDF_DETAILS)) | |
2664 fprintf (dump_file, " good_cloning_opportunity_p (time: %i, " | |
2665 "size: %i, freq_sum: %i%s%s) -> evaluation: " | |
2666 "%" PRId64 ", threshold: %i\n", | |
2667 time_benefit, size_cost, freq_sum, | |
2668 info->node_within_scc ? ", scc" : "", | |
2669 info->node_calling_single_call ? ", single_call" : "", | |
2670 evaluation, PARAM_VALUE (PARAM_IPA_CP_EVAL_THRESHOLD)); | |
2671 | |
2672 return evaluation >= PARAM_VALUE (PARAM_IPA_CP_EVAL_THRESHOLD); | |
2673 } | |
2674 } | |
2675 | |
2676 /* Return all context independent values from aggregate lattices in PLATS in a | |
2677 vector. Return NULL if there are none. */ | |
2678 | |
2679 static vec<ipa_agg_jf_item, va_gc> * | |
2680 context_independent_aggregate_values (struct ipcp_param_lattices *plats) | |
2681 { | |
2682 vec<ipa_agg_jf_item, va_gc> *res = NULL; | |
2683 | |
2684 if (plats->aggs_bottom | |
2685 || plats->aggs_contain_variable | |
2686 || plats->aggs_count == 0) | |
2687 return NULL; | |
2688 | |
2689 for (struct ipcp_agg_lattice *aglat = plats->aggs; | |
2690 aglat; | |
2691 aglat = aglat->next) | |
2692 if (aglat->is_single_const ()) | |
2693 { | |
2694 struct ipa_agg_jf_item item; | |
2695 item.offset = aglat->offset; | |
2696 item.value = aglat->values->value; | |
2697 vec_safe_push (res, item); | |
2698 } | |
2699 return res; | |
2700 } | |
2701 | |
2702 /* Allocate KNOWN_CSTS, KNOWN_CONTEXTS and, if non-NULL, KNOWN_AGGS and | |
2703 populate them with values of parameters that are known independent of the | |
2704 context. INFO describes the function. If REMOVABLE_PARAMS_COST is | |
2705 non-NULL, the movement cost of all removable parameters will be stored in | |
2706 it. */ | |
2707 | |
2708 static bool | |
2709 gather_context_independent_values (struct ipa_node_params *info, | |
2710 vec<tree> *known_csts, | |
2711 vec<ipa_polymorphic_call_context> | |
2712 *known_contexts, | |
2713 vec<ipa_agg_jump_function> *known_aggs, | |
2714 int *removable_params_cost) | |
2715 { | |
2716 int i, count = ipa_get_param_count (info); | |
2717 bool ret = false; | |
2718 | |
2719 known_csts->create (0); | |
2720 known_contexts->create (0); | |
2721 known_csts->safe_grow_cleared (count); | |
2722 known_contexts->safe_grow_cleared (count); | |
2723 if (known_aggs) | |
2724 { | |
2725 known_aggs->create (0); | |
2726 known_aggs->safe_grow_cleared (count); | |
2727 } | |
2728 | |
2729 if (removable_params_cost) | |
2730 *removable_params_cost = 0; | |
2731 | |
2732 for (i = 0; i < count; i++) | |
2733 { | |
2734 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i); | |
2735 ipcp_lattice<tree> *lat = &plats->itself; | |
2736 | |
2737 if (lat->is_single_const ()) | |
2738 { | |
2739 ipcp_value<tree> *val = lat->values; | |
2740 gcc_checking_assert (TREE_CODE (val->value) != TREE_BINFO); | |
2741 (*known_csts)[i] = val->value; | |
2742 if (removable_params_cost) | |
2743 *removable_params_cost | |
2744 += estimate_move_cost (TREE_TYPE (val->value), false); | |
2745 ret = true; | |
2746 } | |
2747 else if (removable_params_cost | |
2748 && !ipa_is_param_used (info, i)) | |
2749 *removable_params_cost | |
2750 += ipa_get_param_move_cost (info, i); | |
2751 | |
2752 if (!ipa_is_param_used (info, i)) | |
2753 continue; | |
2754 | |
2755 ipcp_lattice<ipa_polymorphic_call_context> *ctxlat = &plats->ctxlat; | |
2756 /* Do not account known context as reason for cloning. We can see | |
2757 if it permits devirtualization. */ | |
2758 if (ctxlat->is_single_const ()) | |
2759 (*known_contexts)[i] = ctxlat->values->value; | |
2760 | |
2761 if (known_aggs) | |
2762 { | |
2763 vec<ipa_agg_jf_item, va_gc> *agg_items; | |
2764 struct ipa_agg_jump_function *ajf; | |
2765 | |
2766 agg_items = context_independent_aggregate_values (plats); | |
2767 ajf = &(*known_aggs)[i]; | |
2768 ajf->items = agg_items; | |
2769 ajf->by_ref = plats->aggs_by_ref; | |
2770 ret |= agg_items != NULL; | |
2771 } | |
2772 } | |
2773 | |
2774 return ret; | |
2775 } | |
2776 | |
2777 /* The current interface in ipa-inline-analysis requires a pointer vector. | |
2778 Create it. | |
2779 | |
2780 FIXME: That interface should be re-worked, this is slightly silly. Still, | |
2781 I'd like to discuss how to change it first and this demonstrates the | |
2782 issue. */ | |
2783 | |
2784 static vec<ipa_agg_jump_function_p> | |
2785 agg_jmp_p_vec_for_t_vec (vec<ipa_agg_jump_function> known_aggs) | |
2786 { | |
2787 vec<ipa_agg_jump_function_p> ret; | |
2788 struct ipa_agg_jump_function *ajf; | |
2789 int i; | |
2790 | |
2791 ret.create (known_aggs.length ()); | |
2792 FOR_EACH_VEC_ELT (known_aggs, i, ajf) | |
2793 ret.quick_push (ajf); | |
2794 return ret; | |
2795 } | |
2796 | |
2797 /* Perform time and size measurement of NODE with the context given in | |
2798 KNOWN_CSTS, KNOWN_CONTEXTS and KNOWN_AGGS, calculate the benefit and cost | |
2799 given BASE_TIME of the node without specialization, REMOVABLE_PARAMS_COST of | |
2800 all context-independent removable parameters and EST_MOVE_COST of estimated | |
2801 movement of the considered parameter and store it into VAL. */ | |
2802 | |
622 static void | 2803 static void |
623 ipcp_compute_node_scale (struct cgraph_node *node) | 2804 perform_estimation_of_a_value (cgraph_node *node, vec<tree> known_csts, |
624 { | 2805 vec<ipa_polymorphic_call_context> known_contexts, |
625 gcov_type sum; | 2806 vec<ipa_agg_jump_function_p> known_aggs_ptrs, |
626 struct cgraph_edge *cs; | 2807 int removable_params_cost, |
627 | 2808 int est_move_cost, ipcp_value_base *val) |
628 sum = 0; | 2809 { |
629 /* Compute sum of all counts of callers. */ | 2810 int size, time_benefit; |
630 for (cs = node->callers; cs != NULL; cs = cs->next_caller) | 2811 sreal time, base_time; |
631 sum += cs->count; | 2812 ipa_hints hints; |
632 /* Work around the unrealistically high sum problem. We just don't want | 2813 |
633 the non-cloned body to have negative or very low frequency. Since | 2814 estimate_ipcp_clone_size_and_time (node, known_csts, known_contexts, |
634 majority of execution time will be spent in clones anyway, this should | 2815 known_aggs_ptrs, &size, &time, |
635 give good enough profile. */ | 2816 &base_time, &hints); |
636 if (sum > node->count * 9 / 10) | 2817 base_time -= time; |
637 sum = node->count * 9 / 10; | 2818 if (base_time > 65535) |
638 if (node->count == 0) | 2819 base_time = 65535; |
639 ipcp_set_node_scale (node, 0); | 2820 time_benefit = base_time.to_int () |
2821 + devirtualization_time_bonus (node, known_csts, known_contexts, | |
2822 known_aggs_ptrs) | |
2823 + hint_time_bonus (hints) | |
2824 + removable_params_cost + est_move_cost; | |
2825 | |
2826 gcc_checking_assert (size >=0); | |
2827 /* The inliner-heuristics based estimates may think that in certain | |
2828 contexts some functions do not have any size at all but we want | |
2829 all specializations to have at least a tiny cost, not least not to | |
2830 divide by zero. */ | |
2831 if (size == 0) | |
2832 size = 1; | |
2833 | |
2834 val->local_time_benefit = time_benefit; | |
2835 val->local_size_cost = size; | |
2836 } | |
2837 | |
2838 /* Iterate over known values of parameters of NODE and estimate the local | |
2839 effects in terms of time and size they have. */ | |
2840 | |
2841 static void | |
2842 estimate_local_effects (struct cgraph_node *node) | |
2843 { | |
2844 struct ipa_node_params *info = IPA_NODE_REF (node); | |
2845 int i, count = ipa_get_param_count (info); | |
2846 vec<tree> known_csts; | |
2847 vec<ipa_polymorphic_call_context> known_contexts; | |
2848 vec<ipa_agg_jump_function> known_aggs; | |
2849 vec<ipa_agg_jump_function_p> known_aggs_ptrs; | |
2850 bool always_const; | |
2851 int removable_params_cost; | |
2852 | |
2853 if (!count || !ipcp_versionable_function_p (node)) | |
2854 return; | |
2855 | |
2856 if (dump_file && (dump_flags & TDF_DETAILS)) | |
2857 fprintf (dump_file, "\nEstimating effects for %s.\n", node->dump_name ()); | |
2858 | |
2859 always_const = gather_context_independent_values (info, &known_csts, | |
2860 &known_contexts, &known_aggs, | |
2861 &removable_params_cost); | |
2862 known_aggs_ptrs = agg_jmp_p_vec_for_t_vec (known_aggs); | |
2863 int devirt_bonus = devirtualization_time_bonus (node, known_csts, | |
2864 known_contexts, known_aggs_ptrs); | |
2865 if (always_const || devirt_bonus | |
2866 || (removable_params_cost && node->local.can_change_signature)) | |
2867 { | |
2868 struct caller_statistics stats; | |
2869 ipa_hints hints; | |
2870 sreal time, base_time; | |
2871 int size; | |
2872 | |
2873 init_caller_stats (&stats); | |
2874 node->call_for_symbol_thunks_and_aliases (gather_caller_stats, &stats, | |
2875 false); | |
2876 estimate_ipcp_clone_size_and_time (node, known_csts, known_contexts, | |
2877 known_aggs_ptrs, &size, &time, | |
2878 &base_time, &hints); | |
2879 time -= devirt_bonus; | |
2880 time -= hint_time_bonus (hints); | |
2881 time -= removable_params_cost; | |
2882 size -= stats.n_calls * removable_params_cost; | |
2883 | |
2884 if (dump_file) | |
2885 fprintf (dump_file, " - context independent values, size: %i, " | |
2886 "time_benefit: %f\n", size, (base_time - time).to_double ()); | |
2887 | |
2888 if (size <= 0 || node->local.local) | |
2889 { | |
2890 info->do_clone_for_all_contexts = true; | |
2891 | |
2892 if (dump_file) | |
2893 fprintf (dump_file, " Decided to specialize for all " | |
2894 "known contexts, code not going to grow.\n"); | |
2895 } | |
2896 else if (good_cloning_opportunity_p (node, | |
2897 MAX ((base_time - time).to_int (), | |
2898 65536), | |
2899 stats.freq_sum, stats.count_sum, | |
2900 size)) | |
2901 { | |
2902 if (size + overall_size <= max_new_size) | |
2903 { | |
2904 info->do_clone_for_all_contexts = true; | |
2905 overall_size += size; | |
2906 | |
2907 if (dump_file) | |
2908 fprintf (dump_file, " Decided to specialize for all " | |
2909 "known contexts, growth deemed beneficial.\n"); | |
2910 } | |
2911 else if (dump_file && (dump_flags & TDF_DETAILS)) | |
2912 fprintf (dump_file, " Not cloning for all contexts because " | |
2913 "max_new_size would be reached with %li.\n", | |
2914 size + overall_size); | |
2915 } | |
2916 else if (dump_file && (dump_flags & TDF_DETAILS)) | |
2917 fprintf (dump_file, " Not cloning for all contexts because " | |
2918 "!good_cloning_opportunity_p.\n"); | |
2919 | |
2920 } | |
2921 | |
2922 for (i = 0; i < count; i++) | |
2923 { | |
2924 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i); | |
2925 ipcp_lattice<tree> *lat = &plats->itself; | |
2926 ipcp_value<tree> *val; | |
2927 | |
2928 if (lat->bottom | |
2929 || !lat->values | |
2930 || known_csts[i]) | |
2931 continue; | |
2932 | |
2933 for (val = lat->values; val; val = val->next) | |
2934 { | |
2935 gcc_checking_assert (TREE_CODE (val->value) != TREE_BINFO); | |
2936 known_csts[i] = val->value; | |
2937 | |
2938 int emc = estimate_move_cost (TREE_TYPE (val->value), true); | |
2939 perform_estimation_of_a_value (node, known_csts, known_contexts, | |
2940 known_aggs_ptrs, | |
2941 removable_params_cost, emc, val); | |
2942 | |
2943 if (dump_file && (dump_flags & TDF_DETAILS)) | |
2944 { | |
2945 fprintf (dump_file, " - estimates for value "); | |
2946 print_ipcp_constant_value (dump_file, val->value); | |
2947 fprintf (dump_file, " for "); | |
2948 ipa_dump_param (dump_file, info, i); | |
2949 fprintf (dump_file, ": time_benefit: %i, size: %i\n", | |
2950 val->local_time_benefit, val->local_size_cost); | |
2951 } | |
2952 } | |
2953 known_csts[i] = NULL_TREE; | |
2954 } | |
2955 | |
2956 for (i = 0; i < count; i++) | |
2957 { | |
2958 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i); | |
2959 | |
2960 if (!plats->virt_call) | |
2961 continue; | |
2962 | |
2963 ipcp_lattice<ipa_polymorphic_call_context> *ctxlat = &plats->ctxlat; | |
2964 ipcp_value<ipa_polymorphic_call_context> *val; | |
2965 | |
2966 if (ctxlat->bottom | |
2967 || !ctxlat->values | |
2968 || !known_contexts[i].useless_p ()) | |
2969 continue; | |
2970 | |
2971 for (val = ctxlat->values; val; val = val->next) | |
2972 { | |
2973 known_contexts[i] = val->value; | |
2974 perform_estimation_of_a_value (node, known_csts, known_contexts, | |
2975 known_aggs_ptrs, | |
2976 removable_params_cost, 0, val); | |
2977 | |
2978 if (dump_file && (dump_flags & TDF_DETAILS)) | |
2979 { | |
2980 fprintf (dump_file, " - estimates for polymorphic context "); | |
2981 print_ipcp_constant_value (dump_file, val->value); | |
2982 fprintf (dump_file, " for "); | |
2983 ipa_dump_param (dump_file, info, i); | |
2984 fprintf (dump_file, ": time_benefit: %i, size: %i\n", | |
2985 val->local_time_benefit, val->local_size_cost); | |
2986 } | |
2987 } | |
2988 known_contexts[i] = ipa_polymorphic_call_context (); | |
2989 } | |
2990 | |
2991 for (i = 0; i < count; i++) | |
2992 { | |
2993 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i); | |
2994 struct ipa_agg_jump_function *ajf; | |
2995 struct ipcp_agg_lattice *aglat; | |
2996 | |
2997 if (plats->aggs_bottom || !plats->aggs) | |
2998 continue; | |
2999 | |
3000 ajf = &known_aggs[i]; | |
3001 for (aglat = plats->aggs; aglat; aglat = aglat->next) | |
3002 { | |
3003 ipcp_value<tree> *val; | |
3004 if (aglat->bottom || !aglat->values | |
3005 /* If the following is true, the one value is in known_aggs. */ | |
3006 || (!plats->aggs_contain_variable | |
3007 && aglat->is_single_const ())) | |
3008 continue; | |
3009 | |
3010 for (val = aglat->values; val; val = val->next) | |
3011 { | |
3012 struct ipa_agg_jf_item item; | |
3013 | |
3014 item.offset = aglat->offset; | |
3015 item.value = val->value; | |
3016 vec_safe_push (ajf->items, item); | |
3017 | |
3018 perform_estimation_of_a_value (node, known_csts, known_contexts, | |
3019 known_aggs_ptrs, | |
3020 removable_params_cost, 0, val); | |
3021 | |
3022 if (dump_file && (dump_flags & TDF_DETAILS)) | |
3023 { | |
3024 fprintf (dump_file, " - estimates for value "); | |
3025 print_ipcp_constant_value (dump_file, val->value); | |
3026 fprintf (dump_file, " for "); | |
3027 ipa_dump_param (dump_file, info, i); | |
3028 fprintf (dump_file, "[%soffset: " HOST_WIDE_INT_PRINT_DEC | |
3029 "]: time_benefit: %i, size: %i\n", | |
3030 plats->aggs_by_ref ? "ref " : "", | |
3031 aglat->offset, | |
3032 val->local_time_benefit, val->local_size_cost); | |
3033 } | |
3034 | |
3035 ajf->items->pop (); | |
3036 } | |
3037 } | |
3038 } | |
3039 | |
3040 for (i = 0; i < count; i++) | |
3041 vec_free (known_aggs[i].items); | |
3042 | |
3043 known_csts.release (); | |
3044 known_contexts.release (); | |
3045 known_aggs.release (); | |
3046 known_aggs_ptrs.release (); | |
3047 } | |
3048 | |
3049 | |
3050 /* Add value CUR_VAL and all yet-unsorted values it is dependent on to the | |
3051 topological sort of values. */ | |
3052 | |
3053 template <typename valtype> | |
3054 void | |
3055 value_topo_info<valtype>::add_val (ipcp_value<valtype> *cur_val) | |
3056 { | |
3057 ipcp_value_source<valtype> *src; | |
3058 | |
3059 if (cur_val->dfs) | |
3060 return; | |
3061 | |
3062 dfs_counter++; | |
3063 cur_val->dfs = dfs_counter; | |
3064 cur_val->low_link = dfs_counter; | |
3065 | |
3066 cur_val->topo_next = stack; | |
3067 stack = cur_val; | |
3068 cur_val->on_stack = true; | |
3069 | |
3070 for (src = cur_val->sources; src; src = src->next) | |
3071 if (src->val) | |
3072 { | |
3073 if (src->val->dfs == 0) | |
3074 { | |
3075 add_val (src->val); | |
3076 if (src->val->low_link < cur_val->low_link) | |
3077 cur_val->low_link = src->val->low_link; | |
3078 } | |
3079 else if (src->val->on_stack | |
3080 && src->val->dfs < cur_val->low_link) | |
3081 cur_val->low_link = src->val->dfs; | |
3082 } | |
3083 | |
3084 if (cur_val->dfs == cur_val->low_link) | |
3085 { | |
3086 ipcp_value<valtype> *v, *scc_list = NULL; | |
3087 | |
3088 do | |
3089 { | |
3090 v = stack; | |
3091 stack = v->topo_next; | |
3092 v->on_stack = false; | |
3093 | |
3094 v->scc_next = scc_list; | |
3095 scc_list = v; | |
3096 } | |
3097 while (v != cur_val); | |
3098 | |
3099 cur_val->topo_next = values_topo; | |
3100 values_topo = cur_val; | |
3101 } | |
3102 } | |
3103 | |
3104 /* Add all values in lattices associated with NODE to the topological sort if | |
3105 they are not there yet. */ | |
3106 | |
3107 static void | |
3108 add_all_node_vals_to_toposort (cgraph_node *node, ipa_topo_info *topo) | |
3109 { | |
3110 struct ipa_node_params *info = IPA_NODE_REF (node); | |
3111 int i, count = ipa_get_param_count (info); | |
3112 | |
3113 for (i = 0; i < count; i++) | |
3114 { | |
3115 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i); | |
3116 ipcp_lattice<tree> *lat = &plats->itself; | |
3117 struct ipcp_agg_lattice *aglat; | |
3118 | |
3119 if (!lat->bottom) | |
3120 { | |
3121 ipcp_value<tree> *val; | |
3122 for (val = lat->values; val; val = val->next) | |
3123 topo->constants.add_val (val); | |
3124 } | |
3125 | |
3126 if (!plats->aggs_bottom) | |
3127 for (aglat = plats->aggs; aglat; aglat = aglat->next) | |
3128 if (!aglat->bottom) | |
3129 { | |
3130 ipcp_value<tree> *val; | |
3131 for (val = aglat->values; val; val = val->next) | |
3132 topo->constants.add_val (val); | |
3133 } | |
3134 | |
3135 ipcp_lattice<ipa_polymorphic_call_context> *ctxlat = &plats->ctxlat; | |
3136 if (!ctxlat->bottom) | |
3137 { | |
3138 ipcp_value<ipa_polymorphic_call_context> *ctxval; | |
3139 for (ctxval = ctxlat->values; ctxval; ctxval = ctxval->next) | |
3140 topo->contexts.add_val (ctxval); | |
3141 } | |
3142 } | |
3143 } | |
3144 | |
3145 /* One pass of constants propagation along the call graph edges, from callers | |
3146 to callees (requires topological ordering in TOPO), iterate over strongly | |
3147 connected components. */ | |
3148 | |
3149 static void | |
3150 propagate_constants_topo (struct ipa_topo_info *topo) | |
3151 { | |
3152 int i; | |
3153 | |
3154 for (i = topo->nnodes - 1; i >= 0; i--) | |
3155 { | |
3156 unsigned j; | |
3157 struct cgraph_node *v, *node = topo->order[i]; | |
3158 vec<cgraph_node *> cycle_nodes = ipa_get_nodes_in_cycle (node); | |
3159 | |
3160 /* First, iteratively propagate within the strongly connected component | |
3161 until all lattices stabilize. */ | |
3162 FOR_EACH_VEC_ELT (cycle_nodes, j, v) | |
3163 if (v->has_gimple_body_p ()) | |
3164 push_node_to_stack (topo, v); | |
3165 | |
3166 v = pop_node_from_stack (topo); | |
3167 while (v) | |
3168 { | |
3169 struct cgraph_edge *cs; | |
3170 | |
3171 for (cs = v->callees; cs; cs = cs->next_callee) | |
3172 if (ipa_edge_within_scc (cs)) | |
3173 { | |
3174 IPA_NODE_REF (v)->node_within_scc = true; | |
3175 if (propagate_constants_across_call (cs)) | |
3176 push_node_to_stack (topo, cs->callee->function_symbol ()); | |
3177 } | |
3178 v = pop_node_from_stack (topo); | |
3179 } | |
3180 | |
3181 /* Afterwards, propagate along edges leading out of the SCC, calculates | |
3182 the local effects of the discovered constants and all valid values to | |
3183 their topological sort. */ | |
3184 FOR_EACH_VEC_ELT (cycle_nodes, j, v) | |
3185 if (v->has_gimple_body_p ()) | |
3186 { | |
3187 struct cgraph_edge *cs; | |
3188 | |
3189 estimate_local_effects (v); | |
3190 add_all_node_vals_to_toposort (v, topo); | |
3191 for (cs = v->callees; cs; cs = cs->next_callee) | |
3192 if (!ipa_edge_within_scc (cs)) | |
3193 propagate_constants_across_call (cs); | |
3194 } | |
3195 cycle_nodes.release (); | |
3196 } | |
3197 } | |
3198 | |
3199 | |
3200 /* Return the sum of A and B if none of them is bigger than INT_MAX/2, return | |
3201 the bigger one if otherwise. */ | |
3202 | |
3203 static int | |
3204 safe_add (int a, int b) | |
3205 { | |
3206 if (a > INT_MAX/2 || b > INT_MAX/2) | |
3207 return a > b ? a : b; | |
640 else | 3208 else |
641 ipcp_set_node_scale (node, sum * REG_BR_PROB_BASE / node->count); | 3209 return a + b; |
642 } | 3210 } |
643 | 3211 |
644 /* Return true if there are some formal parameters whose value is IPA_TOP (in | 3212 |
645 the whole compilation unit). Change their values to IPA_BOTTOM, since they | 3213 /* Propagate the estimated effects of individual values along the topological |
646 most probably get their values from outside of this compilation unit. */ | 3214 from the dependent values to those they depend on. */ |
647 static bool | 3215 |
648 ipcp_change_tops_to_bottom (void) | 3216 template <typename valtype> |
649 { | 3217 void |
650 int i, count; | 3218 value_topo_info<valtype>::propagate_effects () |
3219 { | |
3220 ipcp_value<valtype> *base; | |
3221 | |
3222 for (base = values_topo; base; base = base->topo_next) | |
3223 { | |
3224 ipcp_value_source<valtype> *src; | |
3225 ipcp_value<valtype> *val; | |
3226 int time = 0, size = 0; | |
3227 | |
3228 for (val = base; val; val = val->scc_next) | |
3229 { | |
3230 time = safe_add (time, | |
3231 val->local_time_benefit + val->prop_time_benefit); | |
3232 size = safe_add (size, val->local_size_cost + val->prop_size_cost); | |
3233 } | |
3234 | |
3235 for (val = base; val; val = val->scc_next) | |
3236 for (src = val->sources; src; src = src->next) | |
3237 if (src->val | |
3238 && src->cs->maybe_hot_p ()) | |
3239 { | |
3240 src->val->prop_time_benefit = safe_add (time, | |
3241 src->val->prop_time_benefit); | |
3242 src->val->prop_size_cost = safe_add (size, | |
3243 src->val->prop_size_cost); | |
3244 } | |
3245 } | |
3246 } | |
3247 | |
3248 | |
3249 /* Propagate constants, polymorphic contexts and their effects from the | |
3250 summaries interprocedurally. */ | |
3251 | |
3252 static void | |
3253 ipcp_propagate_stage (struct ipa_topo_info *topo) | |
3254 { | |
651 struct cgraph_node *node; | 3255 struct cgraph_node *node; |
652 bool prop_again; | |
653 | |
654 prop_again = false; | |
655 for (node = cgraph_nodes; node; node = node->next) | |
656 { | |
657 struct ipa_node_params *info = IPA_NODE_REF (node); | |
658 count = ipa_get_param_count (info); | |
659 for (i = 0; i < count; i++) | |
660 { | |
661 struct ipcp_lattice *lat = ipcp_get_lattice (info, i); | |
662 if (lat->type == IPA_TOP) | |
663 { | |
664 prop_again = true; | |
665 if (dump_file) | |
666 { | |
667 fprintf (dump_file, "Forcing param "); | |
668 print_generic_expr (dump_file, ipa_get_param (info, i), 0); | |
669 fprintf (dump_file, " of node %s to bottom.\n", | |
670 cgraph_node_name (node)); | |
671 } | |
672 lat->type = IPA_BOTTOM; | |
673 } | |
674 if (!ipa_param_cannot_devirtualize_p (info, i) | |
675 && ipa_param_types_vec_empty (info, i)) | |
676 { | |
677 prop_again = true; | |
678 ipa_set_param_cannot_devirtualize (info, i); | |
679 if (dump_file) | |
680 { | |
681 fprintf (dump_file, "Marking param "); | |
682 print_generic_expr (dump_file, ipa_get_param (info, i), 0); | |
683 fprintf (dump_file, " of node %s as unusable for " | |
684 "devirtualization.\n", | |
685 cgraph_node_name (node)); | |
686 } | |
687 } | |
688 } | |
689 } | |
690 return prop_again; | |
691 } | |
692 | |
693 /* Insert BINFO to the list of known types of parameter number I of the | |
694 function described by CALLEE_INFO. Return true iff the type information | |
695 associated with the callee parameter changed in any way. */ | |
696 | |
697 static bool | |
698 ipcp_add_param_type (struct ipa_node_params *callee_info, int i, tree binfo) | |
699 { | |
700 int j, count; | |
701 | |
702 if (ipa_param_cannot_devirtualize_p (callee_info, i)) | |
703 return false; | |
704 | |
705 if (callee_info->params[i].types) | |
706 { | |
707 count = VEC_length (tree, callee_info->params[i].types); | |
708 for (j = 0; j < count; j++) | |
709 if (VEC_index (tree, callee_info->params[i].types, j) == binfo) | |
710 return false; | |
711 } | |
712 | |
713 if (VEC_length (tree, callee_info->params[i].types) | |
714 == (unsigned) PARAM_VALUE (PARAM_DEVIRT_TYPE_LIST_SIZE)) | |
715 return !ipa_set_param_cannot_devirtualize (callee_info, i); | |
716 | |
717 VEC_safe_push (tree, heap, callee_info->params[i].types, binfo); | |
718 return true; | |
719 } | |
720 | |
721 /* Copy known types information for parameter number CALLEE_IDX of CALLEE_INFO | |
722 from a parameter of CALLER_INFO as described by JF. Return true iff the | |
723 type information changed in any way. JF must be a pass-through or an | |
724 ancestor jump function. */ | |
725 | |
726 static bool | |
727 ipcp_copy_types (struct ipa_node_params *caller_info, | |
728 struct ipa_node_params *callee_info, | |
729 int callee_idx, struct ipa_jump_func *jf) | |
730 { | |
731 int caller_idx, j, count; | |
732 bool res; | |
733 | |
734 if (ipa_param_cannot_devirtualize_p (callee_info, callee_idx)) | |
735 return false; | |
736 | |
737 if (jf->type == IPA_JF_PASS_THROUGH) | |
738 { | |
739 if (jf->value.pass_through.operation != NOP_EXPR) | |
740 { | |
741 ipa_set_param_cannot_devirtualize (callee_info, callee_idx); | |
742 return true; | |
743 } | |
744 caller_idx = jf->value.pass_through.formal_id; | |
745 } | |
746 else | |
747 caller_idx = jf->value.ancestor.formal_id; | |
748 | |
749 if (ipa_param_cannot_devirtualize_p (caller_info, caller_idx)) | |
750 { | |
751 ipa_set_param_cannot_devirtualize (callee_info, callee_idx); | |
752 return true; | |
753 } | |
754 | |
755 if (!caller_info->params[caller_idx].types) | |
756 return false; | |
757 | |
758 res = false; | |
759 count = VEC_length (tree, caller_info->params[caller_idx].types); | |
760 for (j = 0; j < count; j++) | |
761 { | |
762 tree binfo = VEC_index (tree, caller_info->params[caller_idx].types, j); | |
763 if (jf->type == IPA_JF_ANCESTOR) | |
764 { | |
765 binfo = get_binfo_at_offset (binfo, jf->value.ancestor.offset, | |
766 jf->value.ancestor.type); | |
767 if (!binfo) | |
768 { | |
769 ipa_set_param_cannot_devirtualize (callee_info, callee_idx); | |
770 return true; | |
771 } | |
772 } | |
773 res |= ipcp_add_param_type (callee_info, callee_idx, binfo); | |
774 } | |
775 return res; | |
776 } | |
777 | |
778 /* Propagate type information for parameter of CALLEE_INFO number I as | |
779 described by JF. CALLER_INFO describes the caller. Return true iff the | |
780 type information changed in any way. */ | |
781 | |
782 static bool | |
783 ipcp_propagate_types (struct ipa_node_params *caller_info, | |
784 struct ipa_node_params *callee_info, | |
785 struct ipa_jump_func *jf, int i) | |
786 { | |
787 switch (jf->type) | |
788 { | |
789 case IPA_JF_UNKNOWN: | |
790 case IPA_JF_CONST_MEMBER_PTR: | |
791 case IPA_JF_CONST: | |
792 break; | |
793 | |
794 case IPA_JF_KNOWN_TYPE: | |
795 return ipcp_add_param_type (callee_info, i, jf->value.base_binfo); | |
796 | |
797 case IPA_JF_PASS_THROUGH: | |
798 case IPA_JF_ANCESTOR: | |
799 return ipcp_copy_types (caller_info, callee_info, i, jf); | |
800 } | |
801 | |
802 /* If we reach this we cannot use this parameter for devirtualization. */ | |
803 return !ipa_set_param_cannot_devirtualize (callee_info, i); | |
804 } | |
805 | |
806 /* Interprocedural analysis. The algorithm propagates constants from the | |
807 caller's parameters to the callee's arguments. */ | |
808 static void | |
809 ipcp_propagate_stage (void) | |
810 { | |
811 int i; | |
812 struct ipcp_lattice inc_lat = { IPA_BOTTOM, NULL }; | |
813 struct ipcp_lattice new_lat = { IPA_BOTTOM, NULL }; | |
814 struct ipcp_lattice *dest_lat; | |
815 struct cgraph_edge *cs; | |
816 struct ipa_jump_func *jump_func; | |
817 struct ipa_func_list *wl; | |
818 int count; | |
819 | |
820 ipa_check_create_node_params (); | |
821 ipa_check_create_edge_args (); | |
822 | |
823 /* Initialize worklist to contain all functions. */ | |
824 wl = ipa_init_func_list (); | |
825 while (wl) | |
826 { | |
827 struct cgraph_node *node = ipa_pop_func_from_list (&wl); | |
828 struct ipa_node_params *info = IPA_NODE_REF (node); | |
829 | |
830 for (cs = node->callees; cs; cs = cs->next_callee) | |
831 { | |
832 struct ipa_node_params *callee_info = IPA_NODE_REF (cs->callee); | |
833 struct ipa_edge_args *args = IPA_EDGE_REF (cs); | |
834 | |
835 if (ipa_is_called_with_var_arguments (callee_info) | |
836 || !cs->callee->analyzed | |
837 || ipa_is_called_with_var_arguments (callee_info)) | |
838 continue; | |
839 | |
840 count = ipa_get_cs_argument_count (args); | |
841 for (i = 0; i < count; i++) | |
842 { | |
843 jump_func = ipa_get_ith_jump_func (args, i); | |
844 ipcp_lattice_from_jfunc (info, &inc_lat, jump_func); | |
845 dest_lat = ipcp_get_lattice (callee_info, i); | |
846 ipa_lattice_meet (&new_lat, &inc_lat, dest_lat); | |
847 if (ipcp_lattice_changed (&new_lat, dest_lat)) | |
848 { | |
849 dest_lat->type = new_lat.type; | |
850 dest_lat->constant = new_lat.constant; | |
851 ipa_push_func_to_list (&wl, cs->callee); | |
852 } | |
853 | |
854 if (ipcp_propagate_types (info, callee_info, jump_func, i)) | |
855 ipa_push_func_to_list (&wl, cs->callee); | |
856 } | |
857 } | |
858 } | |
859 } | |
860 | |
861 /* Call the constant propagation algorithm and re-call it if necessary | |
862 (if there are undetermined values left). */ | |
863 static void | |
864 ipcp_iterate_stage (void) | |
865 { | |
866 struct cgraph_node *node; | |
867 n_cloning_candidates = 0; | |
868 | 3256 |
869 if (dump_file) | 3257 if (dump_file) |
870 fprintf (dump_file, "\nIPA iterate stage:\n\n"); | 3258 fprintf (dump_file, "\n Propagating constants:\n\n"); |
871 | 3259 |
872 if (in_lto_p) | 3260 FOR_EACH_DEFINED_FUNCTION (node) |
873 ipa_update_after_lto_read (); | 3261 { |
874 | 3262 struct ipa_node_params *info = IPA_NODE_REF (node); |
875 for (node = cgraph_nodes; node; node = node->next) | 3263 |
876 { | 3264 determine_versionability (node, info); |
877 ipcp_initialize_node_lattices (node); | 3265 if (node->has_gimple_body_p ()) |
878 ipcp_compute_node_scale (node); | |
879 } | |
880 if (dump_file && (dump_flags & TDF_DETAILS)) | |
881 { | |
882 ipcp_print_all_lattices (dump_file); | |
883 ipcp_function_scale_print (dump_file); | |
884 } | |
885 | |
886 ipcp_propagate_stage (); | |
887 if (ipcp_change_tops_to_bottom ()) | |
888 /* Some lattices have changed from IPA_TOP to IPA_BOTTOM. | |
889 This change should be propagated. */ | |
890 { | |
891 gcc_assert (n_cloning_candidates); | |
892 ipcp_propagate_stage (); | |
893 } | |
894 if (dump_file) | |
895 { | |
896 fprintf (dump_file, "\nIPA lattices after propagation:\n"); | |
897 ipcp_print_all_lattices (dump_file); | |
898 if (dump_flags & TDF_DETAILS) | |
899 ipcp_print_profile_data (dump_file); | |
900 } | |
901 } | |
902 | |
903 /* Check conditions to forbid constant insertion to function described by | |
904 NODE. */ | |
905 static inline bool | |
906 ipcp_node_modifiable_p (struct cgraph_node *node) | |
907 { | |
908 /* Once we will be able to do in-place replacement, we can be more | |
909 lax here. */ | |
910 return ipcp_versionable_function_p (node); | |
911 } | |
912 | |
913 /* Print count scale data structures. */ | |
914 static void | |
915 ipcp_function_scale_print (FILE * f) | |
916 { | |
917 struct cgraph_node *node; | |
918 | |
919 for (node = cgraph_nodes; node; node = node->next) | |
920 { | |
921 if (!node->analyzed) | |
922 continue; | |
923 fprintf (f, "printing scale for %s: ", cgraph_node_name (node)); | |
924 fprintf (f, "value is " HOST_WIDE_INT_PRINT_DEC | |
925 " \n", (HOST_WIDE_INT) ipcp_get_node_scale (node)); | |
926 } | |
927 } | |
928 | |
929 /* Print counts of all cgraph nodes. */ | |
930 static void | |
931 ipcp_print_func_profile_counts (FILE * f) | |
932 { | |
933 struct cgraph_node *node; | |
934 | |
935 for (node = cgraph_nodes; node; node = node->next) | |
936 { | |
937 fprintf (f, "function %s: ", cgraph_node_name (node)); | |
938 fprintf (f, "count is " HOST_WIDE_INT_PRINT_DEC | |
939 " \n", (HOST_WIDE_INT) node->count); | |
940 } | |
941 } | |
942 | |
943 /* Print counts of all cgraph edges. */ | |
944 static void | |
945 ipcp_print_call_profile_counts (FILE * f) | |
946 { | |
947 struct cgraph_node *node; | |
948 struct cgraph_edge *cs; | |
949 | |
950 for (node = cgraph_nodes; node; node = node->next) | |
951 { | |
952 for (cs = node->callees; cs; cs = cs->next_callee) | |
953 { | |
954 fprintf (f, "%s -> %s ", cgraph_node_name (cs->caller), | |
955 cgraph_node_name (cs->callee)); | |
956 fprintf (f, "count is " HOST_WIDE_INT_PRINT_DEC " \n", | |
957 (HOST_WIDE_INT) cs->count); | |
958 } | |
959 } | |
960 } | |
961 | |
962 /* Print profile info for all functions. */ | |
963 static void | |
964 ipcp_print_profile_data (FILE * f) | |
965 { | |
966 fprintf (f, "\nNODE COUNTS :\n"); | |
967 ipcp_print_func_profile_counts (f); | |
968 fprintf (f, "\nCS COUNTS stage:\n"); | |
969 ipcp_print_call_profile_counts (f); | |
970 } | |
971 | |
972 /* Build and initialize ipa_replace_map struct according to LAT. This struct is | |
973 processed by versioning, which operates according to the flags set. | |
974 PARM_TREE is the formal parameter found to be constant. LAT represents the | |
975 constant. */ | |
976 static struct ipa_replace_map * | |
977 ipcp_create_replace_map (tree parm_tree, struct ipcp_lattice *lat) | |
978 { | |
979 struct ipa_replace_map *replace_map; | |
980 tree const_val; | |
981 | |
982 const_val = build_const_val (lat, TREE_TYPE (parm_tree)); | |
983 if (const_val == NULL_TREE) | |
984 { | |
985 if (dump_file) | |
986 { | |
987 fprintf (dump_file, " const "); | |
988 print_generic_expr (dump_file, lat->constant, 0); | |
989 fprintf (dump_file, " can't be converted to param "); | |
990 print_generic_expr (dump_file, parm_tree, 0); | |
991 fprintf (dump_file, "\n"); | |
992 } | |
993 return NULL; | |
994 } | |
995 replace_map = ggc_alloc_ipa_replace_map (); | |
996 if (dump_file) | |
997 { | |
998 fprintf (dump_file, " replacing param "); | |
999 print_generic_expr (dump_file, parm_tree, 0); | |
1000 fprintf (dump_file, " with const "); | |
1001 print_generic_expr (dump_file, const_val, 0); | |
1002 fprintf (dump_file, "\n"); | |
1003 } | |
1004 replace_map->old_tree = parm_tree; | |
1005 replace_map->new_tree = const_val; | |
1006 replace_map->replace_p = true; | |
1007 replace_map->ref_p = false; | |
1008 | |
1009 return replace_map; | |
1010 } | |
1011 | |
1012 /* Return true if this callsite should be redirected to the original callee | |
1013 (instead of the cloned one). */ | |
1014 static bool | |
1015 ipcp_need_redirect_p (struct cgraph_edge *cs) | |
1016 { | |
1017 struct ipa_node_params *orig_callee_info; | |
1018 int i, count; | |
1019 struct cgraph_node *node = cs->callee, *orig; | |
1020 | |
1021 if (!n_cloning_candidates) | |
1022 return false; | |
1023 | |
1024 if ((orig = ipcp_get_orig_node (node)) != NULL) | |
1025 node = orig; | |
1026 if (ipcp_get_orig_node (cs->caller)) | |
1027 return false; | |
1028 | |
1029 orig_callee_info = IPA_NODE_REF (node); | |
1030 count = ipa_get_param_count (orig_callee_info); | |
1031 for (i = 0; i < count; i++) | |
1032 { | |
1033 struct ipcp_lattice *lat = ipcp_get_lattice (orig_callee_info, i); | |
1034 struct ipa_jump_func *jump_func; | |
1035 | |
1036 jump_func = ipa_get_ith_jump_func (IPA_EDGE_REF (cs), i); | |
1037 if ((ipcp_lat_is_const (lat) | |
1038 && jump_func->type != IPA_JF_CONST) | |
1039 || (!ipa_param_cannot_devirtualize_p (orig_callee_info, i) | |
1040 && !ipa_param_types_vec_empty (orig_callee_info, i) | |
1041 && jump_func->type != IPA_JF_CONST | |
1042 && jump_func->type != IPA_JF_KNOWN_TYPE)) | |
1043 return true; | |
1044 } | |
1045 | |
1046 return false; | |
1047 } | |
1048 | |
1049 /* Fix the callsites and the call graph after function cloning was done. */ | |
1050 static void | |
1051 ipcp_update_callgraph (void) | |
1052 { | |
1053 struct cgraph_node *node; | |
1054 | |
1055 for (node = cgraph_nodes; node; node = node->next) | |
1056 if (node->analyzed && ipcp_node_is_clone (node)) | |
1057 { | 3266 { |
1058 bitmap args_to_skip = NULL; | 3267 info->lattices = XCNEWVEC (struct ipcp_param_lattices, |
1059 struct cgraph_node *orig_node = ipcp_get_orig_node (node); | 3268 ipa_get_param_count (info)); |
1060 struct ipa_node_params *info = IPA_NODE_REF (orig_node); | 3269 initialize_node_lattices (node); |
1061 int i, count = ipa_get_param_count (info); | |
1062 struct cgraph_edge *cs, *next; | |
1063 | |
1064 if (node->local.can_change_signature) | |
1065 { | |
1066 args_to_skip = BITMAP_ALLOC (NULL); | |
1067 for (i = 0; i < count; i++) | |
1068 { | |
1069 struct ipcp_lattice *lat = ipcp_get_lattice (info, i); | |
1070 | |
1071 /* We can proactively remove obviously unused arguments. */ | |
1072 if (!ipa_is_param_used (info, i)) | |
1073 { | |
1074 bitmap_set_bit (args_to_skip, i); | |
1075 continue; | |
1076 } | |
1077 | |
1078 if (lat->type == IPA_CONST_VALUE) | |
1079 bitmap_set_bit (args_to_skip, i); | |
1080 } | |
1081 } | |
1082 for (cs = node->callers; cs; cs = next) | |
1083 { | |
1084 next = cs->next_caller; | |
1085 if (!ipcp_node_is_clone (cs->caller) && ipcp_need_redirect_p (cs)) | |
1086 { | |
1087 if (dump_file) | |
1088 fprintf (dump_file, "Redirecting edge %s/%i -> %s/%i " | |
1089 "back to %s/%i.", | |
1090 cgraph_node_name (cs->caller), cs->caller->uid, | |
1091 cgraph_node_name (cs->callee), cs->callee->uid, | |
1092 cgraph_node_name (orig_node), orig_node->uid); | |
1093 cgraph_redirect_edge_callee (cs, orig_node); | |
1094 } | |
1095 } | |
1096 } | 3270 } |
1097 } | 3271 if (node->definition && !node->alias) |
1098 | 3272 overall_size += ipa_fn_summaries->get (node)->self_size; |
1099 /* Update profiling info for versioned functions and the functions they were | 3273 if (node->count > max_count) |
1100 versioned from. */ | 3274 max_count = node->count; |
1101 static void | 3275 } |
1102 ipcp_update_profiling (void) | |
1103 { | |
1104 struct cgraph_node *node, *orig_node; | |
1105 gcov_type scale, scale_complement; | |
1106 struct cgraph_edge *cs; | |
1107 | |
1108 for (node = cgraph_nodes; node; node = node->next) | |
1109 { | |
1110 if (ipcp_node_is_clone (node)) | |
1111 { | |
1112 orig_node = ipcp_get_orig_node (node); | |
1113 scale = ipcp_get_node_scale (orig_node); | |
1114 node->count = orig_node->count * scale / REG_BR_PROB_BASE; | |
1115 scale_complement = REG_BR_PROB_BASE - scale; | |
1116 orig_node->count = | |
1117 orig_node->count * scale_complement / REG_BR_PROB_BASE; | |
1118 for (cs = node->callees; cs; cs = cs->next_callee) | |
1119 cs->count = cs->count * scale / REG_BR_PROB_BASE; | |
1120 for (cs = orig_node->callees; cs; cs = cs->next_callee) | |
1121 cs->count = cs->count * scale_complement / REG_BR_PROB_BASE; | |
1122 } | |
1123 } | |
1124 } | |
1125 | |
1126 /* If NODE was cloned, how much would program grow? */ | |
1127 static long | |
1128 ipcp_estimate_growth (struct cgraph_node *node) | |
1129 { | |
1130 struct cgraph_edge *cs; | |
1131 int redirectable_node_callers = 0; | |
1132 int removable_args = 0; | |
1133 bool need_original | |
1134 = !cgraph_will_be_removed_from_program_if_no_direct_calls (node); | |
1135 struct ipa_node_params *info; | |
1136 int i, count; | |
1137 int growth; | |
1138 | |
1139 for (cs = node->callers; cs != NULL; cs = cs->next_caller) | |
1140 if (cs->caller == node || !ipcp_need_redirect_p (cs)) | |
1141 redirectable_node_callers++; | |
1142 else | |
1143 need_original = true; | |
1144 | |
1145 /* If we will be able to fully replace original node, we never increase | |
1146 program size. */ | |
1147 if (!need_original) | |
1148 return 0; | |
1149 | |
1150 info = IPA_NODE_REF (node); | |
1151 count = ipa_get_param_count (info); | |
1152 if (node->local.can_change_signature) | |
1153 for (i = 0; i < count; i++) | |
1154 { | |
1155 struct ipcp_lattice *lat = ipcp_get_lattice (info, i); | |
1156 | |
1157 /* We can proactively remove obviously unused arguments. */ | |
1158 if (!ipa_is_param_used (info, i)) | |
1159 removable_args++; | |
1160 | |
1161 if (lat->type == IPA_CONST_VALUE) | |
1162 removable_args++; | |
1163 } | |
1164 | |
1165 /* We make just very simple estimate of savings for removal of operand from | |
1166 call site. Precise cost is difficult to get, as our size metric counts | |
1167 constants and moves as free. Generally we are looking for cases that | |
1168 small function is called very many times. */ | |
1169 growth = node->local.inline_summary.self_size | |
1170 - removable_args * redirectable_node_callers; | |
1171 if (growth < 0) | |
1172 return 0; | |
1173 return growth; | |
1174 } | |
1175 | |
1176 | |
1177 /* Estimate cost of cloning NODE. */ | |
1178 static long | |
1179 ipcp_estimate_cloning_cost (struct cgraph_node *node) | |
1180 { | |
1181 int freq_sum = 1; | |
1182 gcov_type count_sum = 1; | |
1183 struct cgraph_edge *e; | |
1184 int cost; | |
1185 | |
1186 cost = ipcp_estimate_growth (node) * 1000; | |
1187 if (!cost) | |
1188 { | |
1189 if (dump_file) | |
1190 fprintf (dump_file, "Versioning of %s will save code size\n", | |
1191 cgraph_node_name (node)); | |
1192 return 0; | |
1193 } | |
1194 | |
1195 for (e = node->callers; e; e = e->next_caller) | |
1196 if (!bitmap_bit_p (dead_nodes, e->caller->uid) | |
1197 && !ipcp_need_redirect_p (e)) | |
1198 { | |
1199 count_sum += e->count; | |
1200 freq_sum += e->frequency + 1; | |
1201 } | |
1202 | |
1203 if (max_count) | |
1204 cost /= count_sum * 1000 / max_count + 1; | |
1205 else | |
1206 cost /= freq_sum * 1000 / REG_BR_PROB_BASE + 1; | |
1207 if (dump_file) | |
1208 fprintf (dump_file, "Cost of versioning %s is %i, (size: %i, freq: %i)\n", | |
1209 cgraph_node_name (node), cost, node->local.inline_summary.self_size, | |
1210 freq_sum); | |
1211 return cost + 1; | |
1212 } | |
1213 | |
1214 /* Walk indirect calls of NODE and if any polymorphic can be turned into a | |
1215 direct one now, do so. */ | |
1216 | |
1217 static void | |
1218 ipcp_process_devirtualization_opportunities (struct cgraph_node *node) | |
1219 { | |
1220 struct ipa_node_params *info = IPA_NODE_REF (node); | |
1221 struct cgraph_edge *ie, *next_ie; | |
1222 | |
1223 for (ie = node->indirect_calls; ie; ie = next_ie) | |
1224 { | |
1225 int param_index, types_count, j; | |
1226 HOST_WIDE_INT token; | |
1227 tree target, delta; | |
1228 | |
1229 next_ie = ie->next_callee; | |
1230 if (!ie->indirect_info->polymorphic) | |
1231 continue; | |
1232 param_index = ie->indirect_info->param_index; | |
1233 if (param_index == -1 | |
1234 || ipa_param_cannot_devirtualize_p (info, param_index) | |
1235 || ipa_param_types_vec_empty (info, param_index)) | |
1236 continue; | |
1237 | |
1238 token = ie->indirect_info->otr_token; | |
1239 target = NULL_TREE; | |
1240 types_count = VEC_length (tree, info->params[param_index].types); | |
1241 for (j = 0; j < types_count; j++) | |
1242 { | |
1243 tree binfo = VEC_index (tree, info->params[param_index].types, j); | |
1244 tree d; | |
1245 tree t = gimple_get_virt_mehtod_for_binfo (token, binfo, &d, true); | |
1246 | |
1247 if (!t) | |
1248 { | |
1249 target = NULL_TREE; | |
1250 break; | |
1251 } | |
1252 else if (!target) | |
1253 { | |
1254 target = t; | |
1255 delta = d; | |
1256 } | |
1257 else if (target != t || !tree_int_cst_equal (delta, d)) | |
1258 { | |
1259 target = NULL_TREE; | |
1260 break; | |
1261 } | |
1262 } | |
1263 | |
1264 if (target) | |
1265 ipa_make_edge_direct_to_target (ie, target, delta); | |
1266 } | |
1267 } | |
1268 | |
1269 /* Return number of live constant parameters. */ | |
1270 static int | |
1271 ipcp_const_param_count (struct cgraph_node *node) | |
1272 { | |
1273 int const_param = 0; | |
1274 struct ipa_node_params *info = IPA_NODE_REF (node); | |
1275 int count = ipa_get_param_count (info); | |
1276 int i; | |
1277 | |
1278 for (i = 0; i < count; i++) | |
1279 { | |
1280 struct ipcp_lattice *lat = ipcp_get_lattice (info, i); | |
1281 if ((ipcp_lat_is_insertable (lat) | |
1282 /* Do not count obviously unused arguments. */ | |
1283 && ipa_is_param_used (info, i)) | |
1284 || (!ipa_param_cannot_devirtualize_p (info, i) | |
1285 && !ipa_param_types_vec_empty (info, i))) | |
1286 const_param++; | |
1287 } | |
1288 return const_param; | |
1289 } | |
1290 | |
1291 /* Given that a formal parameter of NODE given by INDEX is known to be constant | |
1292 CST, try to find any indirect edges that can be made direct and make them | |
1293 so. Note that INDEX is the number the parameter at the time of analyzing | |
1294 parameter uses and parameter removals should not be considered for it. (In | |
1295 fact, the parameter itself has just been removed.) */ | |
1296 | |
1297 static void | |
1298 ipcp_discover_new_direct_edges (struct cgraph_node *node, int index, tree cst) | |
1299 { | |
1300 struct cgraph_edge *ie, *next_ie; | |
1301 | |
1302 for (ie = node->indirect_calls; ie; ie = next_ie) | |
1303 { | |
1304 struct cgraph_indirect_call_info *ici = ie->indirect_info; | |
1305 | |
1306 next_ie = ie->next_callee; | |
1307 if (ici->param_index != index | |
1308 || ici->polymorphic) | |
1309 continue; | |
1310 | |
1311 ipa_make_edge_direct_to_target (ie, cst, NULL_TREE); | |
1312 } | |
1313 } | |
1314 | |
1315 | |
1316 /* Propagate the constant parameters found by ipcp_iterate_stage() | |
1317 to the function's code. */ | |
1318 static void | |
1319 ipcp_insert_stage (void) | |
1320 { | |
1321 struct cgraph_node *node, *node1 = NULL; | |
1322 int i; | |
1323 VEC (cgraph_edge_p, heap) * redirect_callers; | |
1324 VEC (ipa_replace_map_p,gc)* replace_trees; | |
1325 int node_callers, count; | |
1326 tree parm_tree; | |
1327 struct ipa_replace_map *replace_param; | |
1328 fibheap_t heap; | |
1329 long overall_size = 0, new_size = 0; | |
1330 long max_new_size; | |
1331 | |
1332 ipa_check_create_node_params (); | |
1333 ipa_check_create_edge_args (); | |
1334 if (dump_file) | |
1335 fprintf (dump_file, "\nIPA insert stage:\n\n"); | |
1336 | |
1337 dead_nodes = BITMAP_ALLOC (NULL); | |
1338 | |
1339 for (node = cgraph_nodes; node; node = node->next) | |
1340 if (node->analyzed) | |
1341 { | |
1342 if (node->count > max_count) | |
1343 max_count = node->count; | |
1344 overall_size += node->local.inline_summary.self_size; | |
1345 } | |
1346 | 3276 |
1347 max_new_size = overall_size; | 3277 max_new_size = overall_size; |
1348 if (max_new_size < PARAM_VALUE (PARAM_LARGE_UNIT_INSNS)) | 3278 if (max_new_size < PARAM_VALUE (PARAM_LARGE_UNIT_INSNS)) |
1349 max_new_size = PARAM_VALUE (PARAM_LARGE_UNIT_INSNS); | 3279 max_new_size = PARAM_VALUE (PARAM_LARGE_UNIT_INSNS); |
1350 max_new_size = max_new_size * PARAM_VALUE (PARAM_IPCP_UNIT_GROWTH) / 100 + 1; | 3280 max_new_size += max_new_size * PARAM_VALUE (PARAM_IPCP_UNIT_GROWTH) / 100 + 1; |
1351 | 3281 |
1352 /* First collect all functions we proved to have constant arguments to | 3282 if (dump_file) |
1353 heap. */ | 3283 fprintf (dump_file, "\noverall_size: %li, max_new_size: %li\n", |
1354 heap = fibheap_new (); | 3284 overall_size, max_new_size); |
1355 for (node = cgraph_nodes; node; node = node->next) | 3285 |
1356 { | 3286 propagate_constants_topo (topo); |
1357 struct ipa_node_params *info; | 3287 if (flag_checking) |
1358 /* Propagation of the constant is forbidden in certain conditions. */ | 3288 ipcp_verify_propagated_values (); |
1359 if (!node->analyzed || !ipcp_node_modifiable_p (node)) | 3289 topo->constants.propagate_effects (); |
3290 topo->contexts.propagate_effects (); | |
3291 | |
3292 if (dump_file) | |
3293 { | |
3294 fprintf (dump_file, "\nIPA lattices after all propagation:\n"); | |
3295 print_all_lattices (dump_file, (dump_flags & TDF_DETAILS), true); | |
3296 } | |
3297 } | |
3298 | |
3299 /* Discover newly direct outgoing edges from NODE which is a new clone with | |
3300 known KNOWN_CSTS and make them direct. */ | |
3301 | |
3302 static void | |
3303 ipcp_discover_new_direct_edges (struct cgraph_node *node, | |
3304 vec<tree> known_csts, | |
3305 vec<ipa_polymorphic_call_context> | |
3306 known_contexts, | |
3307 struct ipa_agg_replacement_value *aggvals) | |
3308 { | |
3309 struct cgraph_edge *ie, *next_ie; | |
3310 bool found = false; | |
3311 | |
3312 for (ie = node->indirect_calls; ie; ie = next_ie) | |
3313 { | |
3314 tree target; | |
3315 bool speculative; | |
3316 | |
3317 next_ie = ie->next_callee; | |
3318 target = ipa_get_indirect_edge_target_1 (ie, known_csts, known_contexts, | |
3319 vNULL, aggvals, &speculative); | |
3320 if (target) | |
3321 { | |
3322 bool agg_contents = ie->indirect_info->agg_contents; | |
3323 bool polymorphic = ie->indirect_info->polymorphic; | |
3324 int param_index = ie->indirect_info->param_index; | |
3325 struct cgraph_edge *cs = ipa_make_edge_direct_to_target (ie, target, | |
3326 speculative); | |
3327 found = true; | |
3328 | |
3329 if (cs && !agg_contents && !polymorphic) | |
3330 { | |
3331 struct ipa_node_params *info = IPA_NODE_REF (node); | |
3332 int c = ipa_get_controlled_uses (info, param_index); | |
3333 if (c != IPA_UNDESCRIBED_USE) | |
3334 { | |
3335 struct ipa_ref *to_del; | |
3336 | |
3337 c--; | |
3338 ipa_set_controlled_uses (info, param_index, c); | |
3339 if (dump_file && (dump_flags & TDF_DETAILS)) | |
3340 fprintf (dump_file, " controlled uses count of param " | |
3341 "%i bumped down to %i\n", param_index, c); | |
3342 if (c == 0 | |
3343 && (to_del = node->find_reference (cs->callee, NULL, 0))) | |
3344 { | |
3345 if (dump_file && (dump_flags & TDF_DETAILS)) | |
3346 fprintf (dump_file, " and even removing its " | |
3347 "cloning-created reference\n"); | |
3348 to_del->remove_reference (); | |
3349 } | |
3350 } | |
3351 } | |
3352 } | |
3353 } | |
3354 /* Turning calls to direct calls will improve overall summary. */ | |
3355 if (found) | |
3356 ipa_update_overall_fn_summary (node); | |
3357 } | |
3358 | |
3359 /* Vector of pointers which for linked lists of clones of an original crgaph | |
3360 edge. */ | |
3361 | |
3362 static vec<cgraph_edge *> next_edge_clone; | |
3363 static vec<cgraph_edge *> prev_edge_clone; | |
3364 | |
3365 static inline void | |
3366 grow_edge_clone_vectors (void) | |
3367 { | |
3368 if (next_edge_clone.length () | |
3369 <= (unsigned) symtab->edges_max_uid) | |
3370 next_edge_clone.safe_grow_cleared (symtab->edges_max_uid + 1); | |
3371 if (prev_edge_clone.length () | |
3372 <= (unsigned) symtab->edges_max_uid) | |
3373 prev_edge_clone.safe_grow_cleared (symtab->edges_max_uid + 1); | |
3374 } | |
3375 | |
3376 /* Edge duplication hook to grow the appropriate linked list in | |
3377 next_edge_clone. */ | |
3378 | |
3379 static void | |
3380 ipcp_edge_duplication_hook (struct cgraph_edge *src, struct cgraph_edge *dst, | |
3381 void *) | |
3382 { | |
3383 grow_edge_clone_vectors (); | |
3384 | |
3385 struct cgraph_edge *old_next = next_edge_clone[src->uid]; | |
3386 if (old_next) | |
3387 prev_edge_clone[old_next->uid] = dst; | |
3388 prev_edge_clone[dst->uid] = src; | |
3389 | |
3390 next_edge_clone[dst->uid] = old_next; | |
3391 next_edge_clone[src->uid] = dst; | |
3392 } | |
3393 | |
3394 /* Hook that is called by cgraph.c when an edge is removed. */ | |
3395 | |
3396 static void | |
3397 ipcp_edge_removal_hook (struct cgraph_edge *cs, void *) | |
3398 { | |
3399 grow_edge_clone_vectors (); | |
3400 | |
3401 struct cgraph_edge *prev = prev_edge_clone[cs->uid]; | |
3402 struct cgraph_edge *next = next_edge_clone[cs->uid]; | |
3403 if (prev) | |
3404 next_edge_clone[prev->uid] = next; | |
3405 if (next) | |
3406 prev_edge_clone[next->uid] = prev; | |
3407 } | |
3408 | |
3409 /* See if NODE is a clone with a known aggregate value at a given OFFSET of a | |
3410 parameter with the given INDEX. */ | |
3411 | |
3412 static tree | |
3413 get_clone_agg_value (struct cgraph_node *node, HOST_WIDE_INT offset, | |
3414 int index) | |
3415 { | |
3416 struct ipa_agg_replacement_value *aggval; | |
3417 | |
3418 aggval = ipa_get_agg_replacements_for_node (node); | |
3419 while (aggval) | |
3420 { | |
3421 if (aggval->offset == offset | |
3422 && aggval->index == index) | |
3423 return aggval->value; | |
3424 aggval = aggval->next; | |
3425 } | |
3426 return NULL_TREE; | |
3427 } | |
3428 | |
3429 /* Return true is NODE is DEST or its clone for all contexts. */ | |
3430 | |
3431 static bool | |
3432 same_node_or_its_all_contexts_clone_p (cgraph_node *node, cgraph_node *dest) | |
3433 { | |
3434 if (node == dest) | |
3435 return true; | |
3436 | |
3437 struct ipa_node_params *info = IPA_NODE_REF (node); | |
3438 return info->is_all_contexts_clone && info->ipcp_orig_node == dest; | |
3439 } | |
3440 | |
3441 /* Return true if edge CS does bring about the value described by SRC to node | |
3442 DEST or its clone for all contexts. */ | |
3443 | |
3444 static bool | |
3445 cgraph_edge_brings_value_p (cgraph_edge *cs, ipcp_value_source<tree> *src, | |
3446 cgraph_node *dest) | |
3447 { | |
3448 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller); | |
3449 enum availability availability; | |
3450 cgraph_node *real_dest = cs->callee->function_symbol (&availability); | |
3451 | |
3452 if (!same_node_or_its_all_contexts_clone_p (real_dest, dest) | |
3453 || availability <= AVAIL_INTERPOSABLE | |
3454 || caller_info->node_dead) | |
3455 return false; | |
3456 if (!src->val) | |
3457 return true; | |
3458 | |
3459 if (caller_info->ipcp_orig_node) | |
3460 { | |
3461 tree t; | |
3462 if (src->offset == -1) | |
3463 t = caller_info->known_csts[src->index]; | |
3464 else | |
3465 t = get_clone_agg_value (cs->caller, src->offset, src->index); | |
3466 return (t != NULL_TREE | |
3467 && values_equal_for_ipcp_p (src->val->value, t)); | |
3468 } | |
3469 else | |
3470 { | |
3471 struct ipcp_agg_lattice *aglat; | |
3472 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (caller_info, | |
3473 src->index); | |
3474 if (src->offset == -1) | |
3475 return (plats->itself.is_single_const () | |
3476 && values_equal_for_ipcp_p (src->val->value, | |
3477 plats->itself.values->value)); | |
3478 else | |
3479 { | |
3480 if (plats->aggs_bottom || plats->aggs_contain_variable) | |
3481 return false; | |
3482 for (aglat = plats->aggs; aglat; aglat = aglat->next) | |
3483 if (aglat->offset == src->offset) | |
3484 return (aglat->is_single_const () | |
3485 && values_equal_for_ipcp_p (src->val->value, | |
3486 aglat->values->value)); | |
3487 } | |
3488 return false; | |
3489 } | |
3490 } | |
3491 | |
3492 /* Return true if edge CS does bring about the value described by SRC to node | |
3493 DEST or its clone for all contexts. */ | |
3494 | |
3495 static bool | |
3496 cgraph_edge_brings_value_p (cgraph_edge *cs, | |
3497 ipcp_value_source<ipa_polymorphic_call_context> *src, | |
3498 cgraph_node *dest) | |
3499 { | |
3500 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller); | |
3501 cgraph_node *real_dest = cs->callee->function_symbol (); | |
3502 | |
3503 if (!same_node_or_its_all_contexts_clone_p (real_dest, dest) | |
3504 || caller_info->node_dead) | |
3505 return false; | |
3506 if (!src->val) | |
3507 return true; | |
3508 | |
3509 if (caller_info->ipcp_orig_node) | |
3510 return (caller_info->known_contexts.length () > (unsigned) src->index) | |
3511 && values_equal_for_ipcp_p (src->val->value, | |
3512 caller_info->known_contexts[src->index]); | |
3513 | |
3514 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (caller_info, | |
3515 src->index); | |
3516 return plats->ctxlat.is_single_const () | |
3517 && values_equal_for_ipcp_p (src->val->value, | |
3518 plats->ctxlat.values->value); | |
3519 } | |
3520 | |
3521 /* Get the next clone in the linked list of clones of an edge. */ | |
3522 | |
3523 static inline struct cgraph_edge * | |
3524 get_next_cgraph_edge_clone (struct cgraph_edge *cs) | |
3525 { | |
3526 return next_edge_clone[cs->uid]; | |
3527 } | |
3528 | |
3529 /* Given VAL that is intended for DEST, iterate over all its sources and if | |
3530 they still hold, add their edge frequency and their number into *FREQUENCY | |
3531 and *CALLER_COUNT respectively. */ | |
3532 | |
3533 template <typename valtype> | |
3534 static bool | |
3535 get_info_about_necessary_edges (ipcp_value<valtype> *val, cgraph_node *dest, | |
3536 int *freq_sum, | |
3537 profile_count *count_sum, int *caller_count) | |
3538 { | |
3539 ipcp_value_source<valtype> *src; | |
3540 int freq = 0, count = 0; | |
3541 profile_count cnt = profile_count::zero (); | |
3542 bool hot = false; | |
3543 | |
3544 for (src = val->sources; src; src = src->next) | |
3545 { | |
3546 struct cgraph_edge *cs = src->cs; | |
3547 while (cs) | |
3548 { | |
3549 if (cgraph_edge_brings_value_p (cs, src, dest)) | |
3550 { | |
3551 count++; | |
3552 freq += cs->frequency; | |
3553 if (cs->count.initialized_p ()) | |
3554 cnt += cs->count; | |
3555 hot |= cs->maybe_hot_p (); | |
3556 } | |
3557 cs = get_next_cgraph_edge_clone (cs); | |
3558 } | |
3559 } | |
3560 | |
3561 *freq_sum = freq; | |
3562 *count_sum = cnt; | |
3563 *caller_count = count; | |
3564 return hot; | |
3565 } | |
3566 | |
3567 /* Return a vector of incoming edges that do bring value VAL to node DEST. It | |
3568 is assumed their number is known and equal to CALLER_COUNT. */ | |
3569 | |
3570 template <typename valtype> | |
3571 static vec<cgraph_edge *> | |
3572 gather_edges_for_value (ipcp_value<valtype> *val, cgraph_node *dest, | |
3573 int caller_count) | |
3574 { | |
3575 ipcp_value_source<valtype> *src; | |
3576 vec<cgraph_edge *> ret; | |
3577 | |
3578 ret.create (caller_count); | |
3579 for (src = val->sources; src; src = src->next) | |
3580 { | |
3581 struct cgraph_edge *cs = src->cs; | |
3582 while (cs) | |
3583 { | |
3584 if (cgraph_edge_brings_value_p (cs, src, dest)) | |
3585 ret.quick_push (cs); | |
3586 cs = get_next_cgraph_edge_clone (cs); | |
3587 } | |
3588 } | |
3589 | |
3590 return ret; | |
3591 } | |
3592 | |
3593 /* Construct a replacement map for a know VALUE for a formal parameter PARAM. | |
3594 Return it or NULL if for some reason it cannot be created. */ | |
3595 | |
3596 static struct ipa_replace_map * | |
3597 get_replacement_map (struct ipa_node_params *info, tree value, int parm_num) | |
3598 { | |
3599 struct ipa_replace_map *replace_map; | |
3600 | |
3601 | |
3602 replace_map = ggc_alloc<ipa_replace_map> (); | |
3603 if (dump_file) | |
3604 { | |
3605 fprintf (dump_file, " replacing "); | |
3606 ipa_dump_param (dump_file, info, parm_num); | |
3607 | |
3608 fprintf (dump_file, " with const "); | |
3609 print_generic_expr (dump_file, value); | |
3610 fprintf (dump_file, "\n"); | |
3611 } | |
3612 replace_map->old_tree = NULL; | |
3613 replace_map->parm_num = parm_num; | |
3614 replace_map->new_tree = value; | |
3615 replace_map->replace_p = true; | |
3616 replace_map->ref_p = false; | |
3617 | |
3618 return replace_map; | |
3619 } | |
3620 | |
3621 /* Dump new profiling counts */ | |
3622 | |
3623 static void | |
3624 dump_profile_updates (struct cgraph_node *orig_node, | |
3625 struct cgraph_node *new_node) | |
3626 { | |
3627 struct cgraph_edge *cs; | |
3628 | |
3629 fprintf (dump_file, " setting count of the specialized node to "); | |
3630 new_node->count.dump (dump_file); | |
3631 fprintf (dump_file, "\n"); | |
3632 for (cs = new_node->callees; cs; cs = cs->next_callee) | |
3633 { | |
3634 fprintf (dump_file, " edge to %s has count ", | |
3635 cs->callee->name ()); | |
3636 cs->count.dump (dump_file); | |
3637 fprintf (dump_file, "\n"); | |
3638 } | |
3639 | |
3640 fprintf (dump_file, " setting count of the original node to "); | |
3641 orig_node->count.dump (dump_file); | |
3642 fprintf (dump_file, "\n"); | |
3643 for (cs = orig_node->callees; cs; cs = cs->next_callee) | |
3644 { | |
3645 fprintf (dump_file, " edge to %s is left with ", | |
3646 cs->callee->name ()); | |
3647 cs->count.dump (dump_file); | |
3648 fprintf (dump_file, "\n"); | |
3649 } | |
3650 } | |
3651 | |
3652 /* After a specialized NEW_NODE version of ORIG_NODE has been created, update | |
3653 their profile information to reflect this. */ | |
3654 | |
3655 static void | |
3656 update_profiling_info (struct cgraph_node *orig_node, | |
3657 struct cgraph_node *new_node) | |
3658 { | |
3659 struct cgraph_edge *cs; | |
3660 struct caller_statistics stats; | |
3661 profile_count new_sum, orig_sum; | |
3662 profile_count remainder, orig_node_count = orig_node->count; | |
3663 | |
3664 if (!(orig_node_count > profile_count::zero ())) | |
3665 return; | |
3666 | |
3667 init_caller_stats (&stats); | |
3668 orig_node->call_for_symbol_thunks_and_aliases (gather_caller_stats, &stats, | |
3669 false); | |
3670 orig_sum = stats.count_sum; | |
3671 init_caller_stats (&stats); | |
3672 new_node->call_for_symbol_thunks_and_aliases (gather_caller_stats, &stats, | |
3673 false); | |
3674 new_sum = stats.count_sum; | |
3675 | |
3676 if (orig_node_count < orig_sum + new_sum) | |
3677 { | |
3678 if (dump_file) | |
3679 { | |
3680 fprintf (dump_file, " Problem: node %s has too low count ", | |
3681 orig_node->dump_name ()); | |
3682 orig_node_count.dump (dump_file); | |
3683 fprintf (dump_file, "while the sum of incoming count is "); | |
3684 (orig_sum + new_sum).dump (dump_file); | |
3685 fprintf (dump_file, "\n"); | |
3686 } | |
3687 | |
3688 orig_node_count = (orig_sum + new_sum).apply_scale (12, 10); | |
3689 if (dump_file) | |
3690 { | |
3691 fprintf (dump_file, " proceeding by pretending it was "); | |
3692 orig_node_count.dump (dump_file); | |
3693 fprintf (dump_file, "\n"); | |
3694 } | |
3695 } | |
3696 | |
3697 new_node->count = new_sum; | |
3698 remainder = orig_node_count - new_sum; | |
3699 orig_node->count = remainder; | |
3700 | |
3701 for (cs = new_node->callees; cs; cs = cs->next_callee) | |
3702 /* FIXME: why we care about non-zero frequency here? */ | |
3703 if (cs->frequency) | |
3704 cs->count = cs->count.apply_scale (new_sum, orig_node_count); | |
3705 else | |
3706 cs->count = profile_count::zero (); | |
3707 | |
3708 for (cs = orig_node->callees; cs; cs = cs->next_callee) | |
3709 cs->count = cs->count.apply_scale (remainder, orig_node_count); | |
3710 | |
3711 if (dump_file) | |
3712 dump_profile_updates (orig_node, new_node); | |
3713 } | |
3714 | |
3715 /* Update the respective profile of specialized NEW_NODE and the original | |
3716 ORIG_NODE after additional edges with cumulative count sum REDIRECTED_SUM | |
3717 have been redirected to the specialized version. */ | |
3718 | |
3719 static void | |
3720 update_specialized_profile (struct cgraph_node *new_node, | |
3721 struct cgraph_node *orig_node, | |
3722 profile_count redirected_sum) | |
3723 { | |
3724 struct cgraph_edge *cs; | |
3725 profile_count new_node_count, orig_node_count = orig_node->count; | |
3726 | |
3727 if (dump_file) | |
3728 { | |
3729 fprintf (dump_file, " the sum of counts of redirected edges is "); | |
3730 redirected_sum.dump (dump_file); | |
3731 fprintf (dump_file, "\n"); | |
3732 } | |
3733 if (!(orig_node_count > profile_count::zero ())) | |
3734 return; | |
3735 | |
3736 gcc_assert (orig_node_count >= redirected_sum); | |
3737 | |
3738 new_node_count = new_node->count; | |
3739 new_node->count += redirected_sum; | |
3740 orig_node->count -= redirected_sum; | |
3741 | |
3742 for (cs = new_node->callees; cs; cs = cs->next_callee) | |
3743 if (cs->frequency) | |
3744 cs->count += cs->count.apply_scale (redirected_sum, new_node_count); | |
3745 else | |
3746 cs->count = profile_count::zero (); | |
3747 | |
3748 for (cs = orig_node->callees; cs; cs = cs->next_callee) | |
3749 { | |
3750 profile_count dec = cs->count.apply_scale (redirected_sum, | |
3751 orig_node_count); | |
3752 cs->count -= dec; | |
3753 } | |
3754 | |
3755 if (dump_file) | |
3756 dump_profile_updates (orig_node, new_node); | |
3757 } | |
3758 | |
3759 /* Create a specialized version of NODE with known constants in KNOWN_CSTS, | |
3760 known contexts in KNOWN_CONTEXTS and known aggregate values in AGGVALS and | |
3761 redirect all edges in CALLERS to it. */ | |
3762 | |
3763 static struct cgraph_node * | |
3764 create_specialized_node (struct cgraph_node *node, | |
3765 vec<tree> known_csts, | |
3766 vec<ipa_polymorphic_call_context> known_contexts, | |
3767 struct ipa_agg_replacement_value *aggvals, | |
3768 vec<cgraph_edge *> callers) | |
3769 { | |
3770 struct ipa_node_params *new_info, *info = IPA_NODE_REF (node); | |
3771 vec<ipa_replace_map *, va_gc> *replace_trees = NULL; | |
3772 struct ipa_agg_replacement_value *av; | |
3773 struct cgraph_node *new_node; | |
3774 int i, count = ipa_get_param_count (info); | |
3775 bitmap args_to_skip; | |
3776 | |
3777 gcc_assert (!info->ipcp_orig_node); | |
3778 | |
3779 if (node->local.can_change_signature) | |
3780 { | |
3781 args_to_skip = BITMAP_GGC_ALLOC (); | |
3782 for (i = 0; i < count; i++) | |
3783 { | |
3784 tree t = known_csts[i]; | |
3785 | |
3786 if (t || !ipa_is_param_used (info, i)) | |
3787 bitmap_set_bit (args_to_skip, i); | |
3788 } | |
3789 } | |
3790 else | |
3791 { | |
3792 args_to_skip = NULL; | |
3793 if (dump_file && (dump_flags & TDF_DETAILS)) | |
3794 fprintf (dump_file, " cannot change function signature\n"); | |
3795 } | |
3796 | |
3797 for (i = 0; i < count; i++) | |
3798 { | |
3799 tree t = known_csts[i]; | |
3800 if (t) | |
3801 { | |
3802 struct ipa_replace_map *replace_map; | |
3803 | |
3804 gcc_checking_assert (TREE_CODE (t) != TREE_BINFO); | |
3805 replace_map = get_replacement_map (info, t, i); | |
3806 if (replace_map) | |
3807 vec_safe_push (replace_trees, replace_map); | |
3808 } | |
3809 } | |
3810 | |
3811 new_node = node->create_virtual_clone (callers, replace_trees, | |
3812 args_to_skip, "constprop"); | |
3813 ipa_set_node_agg_value_chain (new_node, aggvals); | |
3814 for (av = aggvals; av; av = av->next) | |
3815 new_node->maybe_create_reference (av->value, NULL); | |
3816 | |
3817 if (dump_file && (dump_flags & TDF_DETAILS)) | |
3818 { | |
3819 fprintf (dump_file, " the new node is %s.\n", new_node->dump_name ()); | |
3820 if (known_contexts.exists ()) | |
3821 { | |
3822 for (i = 0; i < count; i++) | |
3823 if (!known_contexts[i].useless_p ()) | |
3824 { | |
3825 fprintf (dump_file, " known ctx %i is ", i); | |
3826 known_contexts[i].dump (dump_file); | |
3827 } | |
3828 } | |
3829 if (aggvals) | |
3830 ipa_dump_agg_replacement_values (dump_file, aggvals); | |
3831 } | |
3832 ipa_check_create_node_params (); | |
3833 update_profiling_info (node, new_node); | |
3834 new_info = IPA_NODE_REF (new_node); | |
3835 new_info->ipcp_orig_node = node; | |
3836 new_info->known_csts = known_csts; | |
3837 new_info->known_contexts = known_contexts; | |
3838 | |
3839 ipcp_discover_new_direct_edges (new_node, known_csts, known_contexts, aggvals); | |
3840 | |
3841 callers.release (); | |
3842 return new_node; | |
3843 } | |
3844 | |
3845 /* Given a NODE, and a subset of its CALLERS, try to populate blanks slots in | |
3846 KNOWN_CSTS with constants that are also known for all of the CALLERS. */ | |
3847 | |
3848 static void | |
3849 find_more_scalar_values_for_callers_subset (struct cgraph_node *node, | |
3850 vec<tree> known_csts, | |
3851 vec<cgraph_edge *> callers) | |
3852 { | |
3853 struct ipa_node_params *info = IPA_NODE_REF (node); | |
3854 int i, count = ipa_get_param_count (info); | |
3855 | |
3856 for (i = 0; i < count; i++) | |
3857 { | |
3858 struct cgraph_edge *cs; | |
3859 tree newval = NULL_TREE; | |
3860 int j; | |
3861 bool first = true; | |
3862 | |
3863 if (ipa_get_scalar_lat (info, i)->bottom || known_csts[i]) | |
3864 continue; | |
3865 | |
3866 FOR_EACH_VEC_ELT (callers, j, cs) | |
3867 { | |
3868 struct ipa_jump_func *jump_func; | |
3869 tree t; | |
3870 | |
3871 if (i >= ipa_get_cs_argument_count (IPA_EDGE_REF (cs)) | |
3872 || (i == 0 | |
3873 && call_passes_through_thunk_p (cs)) | |
3874 || (!cs->callee->instrumentation_clone | |
3875 && cs->callee->function_symbol ()->instrumentation_clone)) | |
3876 { | |
3877 newval = NULL_TREE; | |
3878 break; | |
3879 } | |
3880 jump_func = ipa_get_ith_jump_func (IPA_EDGE_REF (cs), i); | |
3881 t = ipa_value_from_jfunc (IPA_NODE_REF (cs->caller), jump_func); | |
3882 if (!t | |
3883 || (newval | |
3884 && !values_equal_for_ipcp_p (t, newval)) | |
3885 || (!first && !newval)) | |
3886 { | |
3887 newval = NULL_TREE; | |
3888 break; | |
3889 } | |
3890 else | |
3891 newval = t; | |
3892 first = false; | |
3893 } | |
3894 | |
3895 if (newval) | |
3896 { | |
3897 if (dump_file && (dump_flags & TDF_DETAILS)) | |
3898 { | |
3899 fprintf (dump_file, " adding an extra known scalar value "); | |
3900 print_ipcp_constant_value (dump_file, newval); | |
3901 fprintf (dump_file, " for "); | |
3902 ipa_dump_param (dump_file, info, i); | |
3903 fprintf (dump_file, "\n"); | |
3904 } | |
3905 | |
3906 known_csts[i] = newval; | |
3907 } | |
3908 } | |
3909 } | |
3910 | |
3911 /* Given a NODE and a subset of its CALLERS, try to populate plank slots in | |
3912 KNOWN_CONTEXTS with polymorphic contexts that are also known for all of the | |
3913 CALLERS. */ | |
3914 | |
3915 static void | |
3916 find_more_contexts_for_caller_subset (cgraph_node *node, | |
3917 vec<ipa_polymorphic_call_context> | |
3918 *known_contexts, | |
3919 vec<cgraph_edge *> callers) | |
3920 { | |
3921 ipa_node_params *info = IPA_NODE_REF (node); | |
3922 int i, count = ipa_get_param_count (info); | |
3923 | |
3924 for (i = 0; i < count; i++) | |
3925 { | |
3926 cgraph_edge *cs; | |
3927 | |
3928 if (ipa_get_poly_ctx_lat (info, i)->bottom | |
3929 || (known_contexts->exists () | |
3930 && !(*known_contexts)[i].useless_p ())) | |
3931 continue; | |
3932 | |
3933 ipa_polymorphic_call_context newval; | |
3934 bool first = true; | |
3935 int j; | |
3936 | |
3937 FOR_EACH_VEC_ELT (callers, j, cs) | |
3938 { | |
3939 if (i >= ipa_get_cs_argument_count (IPA_EDGE_REF (cs))) | |
3940 return; | |
3941 ipa_jump_func *jfunc = ipa_get_ith_jump_func (IPA_EDGE_REF (cs), | |
3942 i); | |
3943 ipa_polymorphic_call_context ctx; | |
3944 ctx = ipa_context_from_jfunc (IPA_NODE_REF (cs->caller), cs, i, | |
3945 jfunc); | |
3946 if (first) | |
3947 { | |
3948 newval = ctx; | |
3949 first = false; | |
3950 } | |
3951 else | |
3952 newval.meet_with (ctx); | |
3953 if (newval.useless_p ()) | |
3954 break; | |
3955 } | |
3956 | |
3957 if (!newval.useless_p ()) | |
3958 { | |
3959 if (dump_file && (dump_flags & TDF_DETAILS)) | |
3960 { | |
3961 fprintf (dump_file, " adding an extra known polymorphic " | |
3962 "context "); | |
3963 print_ipcp_constant_value (dump_file, newval); | |
3964 fprintf (dump_file, " for "); | |
3965 ipa_dump_param (dump_file, info, i); | |
3966 fprintf (dump_file, "\n"); | |
3967 } | |
3968 | |
3969 if (!known_contexts->exists ()) | |
3970 known_contexts->safe_grow_cleared (ipa_get_param_count (info)); | |
3971 (*known_contexts)[i] = newval; | |
3972 } | |
3973 | |
3974 } | |
3975 } | |
3976 | |
3977 /* Go through PLATS and create a vector of values consisting of values and | |
3978 offsets (minus OFFSET) of lattices that contain only a single value. */ | |
3979 | |
3980 static vec<ipa_agg_jf_item> | |
3981 copy_plats_to_inter (struct ipcp_param_lattices *plats, HOST_WIDE_INT offset) | |
3982 { | |
3983 vec<ipa_agg_jf_item> res = vNULL; | |
3984 | |
3985 if (!plats->aggs || plats->aggs_contain_variable || plats->aggs_bottom) | |
3986 return vNULL; | |
3987 | |
3988 for (struct ipcp_agg_lattice *aglat = plats->aggs; aglat; aglat = aglat->next) | |
3989 if (aglat->is_single_const ()) | |
3990 { | |
3991 struct ipa_agg_jf_item ti; | |
3992 ti.offset = aglat->offset - offset; | |
3993 ti.value = aglat->values->value; | |
3994 res.safe_push (ti); | |
3995 } | |
3996 return res; | |
3997 } | |
3998 | |
3999 /* Intersect all values in INTER with single value lattices in PLATS (while | |
4000 subtracting OFFSET). */ | |
4001 | |
4002 static void | |
4003 intersect_with_plats (struct ipcp_param_lattices *plats, | |
4004 vec<ipa_agg_jf_item> *inter, | |
4005 HOST_WIDE_INT offset) | |
4006 { | |
4007 struct ipcp_agg_lattice *aglat; | |
4008 struct ipa_agg_jf_item *item; | |
4009 int k; | |
4010 | |
4011 if (!plats->aggs || plats->aggs_contain_variable || plats->aggs_bottom) | |
4012 { | |
4013 inter->release (); | |
4014 return; | |
4015 } | |
4016 | |
4017 aglat = plats->aggs; | |
4018 FOR_EACH_VEC_ELT (*inter, k, item) | |
4019 { | |
4020 bool found = false; | |
4021 if (!item->value) | |
4022 continue; | |
4023 while (aglat) | |
4024 { | |
4025 if (aglat->offset - offset > item->offset) | |
4026 break; | |
4027 if (aglat->offset - offset == item->offset) | |
4028 { | |
4029 gcc_checking_assert (item->value); | |
4030 if (values_equal_for_ipcp_p (item->value, aglat->values->value)) | |
4031 found = true; | |
4032 break; | |
4033 } | |
4034 aglat = aglat->next; | |
4035 } | |
4036 if (!found) | |
4037 item->value = NULL_TREE; | |
4038 } | |
4039 } | |
4040 | |
4041 /* Copy aggregate replacement values of NODE (which is an IPA-CP clone) to the | |
4042 vector result while subtracting OFFSET from the individual value offsets. */ | |
4043 | |
4044 static vec<ipa_agg_jf_item> | |
4045 agg_replacements_to_vector (struct cgraph_node *node, int index, | |
4046 HOST_WIDE_INT offset) | |
4047 { | |
4048 struct ipa_agg_replacement_value *av; | |
4049 vec<ipa_agg_jf_item> res = vNULL; | |
4050 | |
4051 for (av = ipa_get_agg_replacements_for_node (node); av; av = av->next) | |
4052 if (av->index == index | |
4053 && (av->offset - offset) >= 0) | |
4054 { | |
4055 struct ipa_agg_jf_item item; | |
4056 gcc_checking_assert (av->value); | |
4057 item.offset = av->offset - offset; | |
4058 item.value = av->value; | |
4059 res.safe_push (item); | |
4060 } | |
4061 | |
4062 return res; | |
4063 } | |
4064 | |
4065 /* Intersect all values in INTER with those that we have already scheduled to | |
4066 be replaced in parameter number INDEX of NODE, which is an IPA-CP clone | |
4067 (while subtracting OFFSET). */ | |
4068 | |
4069 static void | |
4070 intersect_with_agg_replacements (struct cgraph_node *node, int index, | |
4071 vec<ipa_agg_jf_item> *inter, | |
4072 HOST_WIDE_INT offset) | |
4073 { | |
4074 struct ipa_agg_replacement_value *srcvals; | |
4075 struct ipa_agg_jf_item *item; | |
4076 int i; | |
4077 | |
4078 srcvals = ipa_get_agg_replacements_for_node (node); | |
4079 if (!srcvals) | |
4080 { | |
4081 inter->release (); | |
4082 return; | |
4083 } | |
4084 | |
4085 FOR_EACH_VEC_ELT (*inter, i, item) | |
4086 { | |
4087 struct ipa_agg_replacement_value *av; | |
4088 bool found = false; | |
4089 if (!item->value) | |
4090 continue; | |
4091 for (av = srcvals; av; av = av->next) | |
4092 { | |
4093 gcc_checking_assert (av->value); | |
4094 if (av->index == index | |
4095 && av->offset - offset == item->offset) | |
4096 { | |
4097 if (values_equal_for_ipcp_p (item->value, av->value)) | |
4098 found = true; | |
4099 break; | |
4100 } | |
4101 } | |
4102 if (!found) | |
4103 item->value = NULL_TREE; | |
4104 } | |
4105 } | |
4106 | |
4107 /* Intersect values in INTER with aggregate values that come along edge CS to | |
4108 parameter number INDEX and return it. If INTER does not actually exist yet, | |
4109 copy all incoming values to it. If we determine we ended up with no values | |
4110 whatsoever, return a released vector. */ | |
4111 | |
4112 static vec<ipa_agg_jf_item> | |
4113 intersect_aggregates_with_edge (struct cgraph_edge *cs, int index, | |
4114 vec<ipa_agg_jf_item> inter) | |
4115 { | |
4116 struct ipa_jump_func *jfunc; | |
4117 jfunc = ipa_get_ith_jump_func (IPA_EDGE_REF (cs), index); | |
4118 if (jfunc->type == IPA_JF_PASS_THROUGH | |
4119 && ipa_get_jf_pass_through_operation (jfunc) == NOP_EXPR) | |
4120 { | |
4121 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller); | |
4122 int src_idx = ipa_get_jf_pass_through_formal_id (jfunc); | |
4123 | |
4124 if (caller_info->ipcp_orig_node) | |
4125 { | |
4126 struct cgraph_node *orig_node = caller_info->ipcp_orig_node; | |
4127 struct ipcp_param_lattices *orig_plats; | |
4128 orig_plats = ipa_get_parm_lattices (IPA_NODE_REF (orig_node), | |
4129 src_idx); | |
4130 if (agg_pass_through_permissible_p (orig_plats, jfunc)) | |
4131 { | |
4132 if (!inter.exists ()) | |
4133 inter = agg_replacements_to_vector (cs->caller, src_idx, 0); | |
4134 else | |
4135 intersect_with_agg_replacements (cs->caller, src_idx, | |
4136 &inter, 0); | |
4137 } | |
4138 else | |
4139 { | |
4140 inter.release (); | |
4141 return vNULL; | |
4142 } | |
4143 } | |
4144 else | |
4145 { | |
4146 struct ipcp_param_lattices *src_plats; | |
4147 src_plats = ipa_get_parm_lattices (caller_info, src_idx); | |
4148 if (agg_pass_through_permissible_p (src_plats, jfunc)) | |
4149 { | |
4150 /* Currently we do not produce clobber aggregate jump | |
4151 functions, adjust when we do. */ | |
4152 gcc_checking_assert (!jfunc->agg.items); | |
4153 if (!inter.exists ()) | |
4154 inter = copy_plats_to_inter (src_plats, 0); | |
4155 else | |
4156 intersect_with_plats (src_plats, &inter, 0); | |
4157 } | |
4158 else | |
4159 { | |
4160 inter.release (); | |
4161 return vNULL; | |
4162 } | |
4163 } | |
4164 } | |
4165 else if (jfunc->type == IPA_JF_ANCESTOR | |
4166 && ipa_get_jf_ancestor_agg_preserved (jfunc)) | |
4167 { | |
4168 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller); | |
4169 int src_idx = ipa_get_jf_ancestor_formal_id (jfunc); | |
4170 struct ipcp_param_lattices *src_plats; | |
4171 HOST_WIDE_INT delta = ipa_get_jf_ancestor_offset (jfunc); | |
4172 | |
4173 if (caller_info->ipcp_orig_node) | |
4174 { | |
4175 if (!inter.exists ()) | |
4176 inter = agg_replacements_to_vector (cs->caller, src_idx, delta); | |
4177 else | |
4178 intersect_with_agg_replacements (cs->caller, src_idx, &inter, | |
4179 delta); | |
4180 } | |
4181 else | |
4182 { | |
4183 src_plats = ipa_get_parm_lattices (caller_info, src_idx);; | |
4184 /* Currently we do not produce clobber aggregate jump | |
4185 functions, adjust when we do. */ | |
4186 gcc_checking_assert (!src_plats->aggs || !jfunc->agg.items); | |
4187 if (!inter.exists ()) | |
4188 inter = copy_plats_to_inter (src_plats, delta); | |
4189 else | |
4190 intersect_with_plats (src_plats, &inter, delta); | |
4191 } | |
4192 } | |
4193 else if (jfunc->agg.items) | |
4194 { | |
4195 struct ipa_agg_jf_item *item; | |
4196 int k; | |
4197 | |
4198 if (!inter.exists ()) | |
4199 for (unsigned i = 0; i < jfunc->agg.items->length (); i++) | |
4200 inter.safe_push ((*jfunc->agg.items)[i]); | |
4201 else | |
4202 FOR_EACH_VEC_ELT (inter, k, item) | |
4203 { | |
4204 int l = 0; | |
4205 bool found = false;; | |
4206 | |
4207 if (!item->value) | |
4208 continue; | |
4209 | |
4210 while ((unsigned) l < jfunc->agg.items->length ()) | |
4211 { | |
4212 struct ipa_agg_jf_item *ti; | |
4213 ti = &(*jfunc->agg.items)[l]; | |
4214 if (ti->offset > item->offset) | |
4215 break; | |
4216 if (ti->offset == item->offset) | |
4217 { | |
4218 gcc_checking_assert (ti->value); | |
4219 if (values_equal_for_ipcp_p (item->value, | |
4220 ti->value)) | |
4221 found = true; | |
4222 break; | |
4223 } | |
4224 l++; | |
4225 } | |
4226 if (!found) | |
4227 item->value = NULL; | |
4228 } | |
4229 } | |
4230 else | |
4231 { | |
4232 inter.release (); | |
4233 return vec<ipa_agg_jf_item>(); | |
4234 } | |
4235 return inter; | |
4236 } | |
4237 | |
4238 /* Look at edges in CALLERS and collect all known aggregate values that arrive | |
4239 from all of them. */ | |
4240 | |
4241 static struct ipa_agg_replacement_value * | |
4242 find_aggregate_values_for_callers_subset (struct cgraph_node *node, | |
4243 vec<cgraph_edge *> callers) | |
4244 { | |
4245 struct ipa_node_params *dest_info = IPA_NODE_REF (node); | |
4246 struct ipa_agg_replacement_value *res; | |
4247 struct ipa_agg_replacement_value **tail = &res; | |
4248 struct cgraph_edge *cs; | |
4249 int i, j, count = ipa_get_param_count (dest_info); | |
4250 | |
4251 FOR_EACH_VEC_ELT (callers, j, cs) | |
4252 { | |
4253 int c = ipa_get_cs_argument_count (IPA_EDGE_REF (cs)); | |
4254 if (c < count) | |
4255 count = c; | |
4256 } | |
4257 | |
4258 for (i = 0; i < count; i++) | |
4259 { | |
4260 struct cgraph_edge *cs; | |
4261 vec<ipa_agg_jf_item> inter = vNULL; | |
4262 struct ipa_agg_jf_item *item; | |
4263 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (dest_info, i); | |
4264 int j; | |
4265 | |
4266 /* Among other things, the following check should deal with all by_ref | |
4267 mismatches. */ | |
4268 if (plats->aggs_bottom) | |
4269 continue; | |
4270 | |
4271 FOR_EACH_VEC_ELT (callers, j, cs) | |
4272 { | |
4273 inter = intersect_aggregates_with_edge (cs, i, inter); | |
4274 | |
4275 if (!inter.exists ()) | |
4276 goto next_param; | |
4277 } | |
4278 | |
4279 FOR_EACH_VEC_ELT (inter, j, item) | |
4280 { | |
4281 struct ipa_agg_replacement_value *v; | |
4282 | |
4283 if (!item->value) | |
4284 continue; | |
4285 | |
4286 v = ggc_alloc<ipa_agg_replacement_value> (); | |
4287 v->index = i; | |
4288 v->offset = item->offset; | |
4289 v->value = item->value; | |
4290 v->by_ref = plats->aggs_by_ref; | |
4291 *tail = v; | |
4292 tail = &v->next; | |
4293 } | |
4294 | |
4295 next_param: | |
4296 if (inter.exists ()) | |
4297 inter.release (); | |
4298 } | |
4299 *tail = NULL; | |
4300 return res; | |
4301 } | |
4302 | |
4303 /* Turn KNOWN_AGGS into a list of aggregate replacement values. */ | |
4304 | |
4305 static struct ipa_agg_replacement_value * | |
4306 known_aggs_to_agg_replacement_list (vec<ipa_agg_jump_function> known_aggs) | |
4307 { | |
4308 struct ipa_agg_replacement_value *res; | |
4309 struct ipa_agg_replacement_value **tail = &res; | |
4310 struct ipa_agg_jump_function *aggjf; | |
4311 struct ipa_agg_jf_item *item; | |
4312 int i, j; | |
4313 | |
4314 FOR_EACH_VEC_ELT (known_aggs, i, aggjf) | |
4315 FOR_EACH_VEC_SAFE_ELT (aggjf->items, j, item) | |
4316 { | |
4317 struct ipa_agg_replacement_value *v; | |
4318 v = ggc_alloc<ipa_agg_replacement_value> (); | |
4319 v->index = i; | |
4320 v->offset = item->offset; | |
4321 v->value = item->value; | |
4322 v->by_ref = aggjf->by_ref; | |
4323 *tail = v; | |
4324 tail = &v->next; | |
4325 } | |
4326 *tail = NULL; | |
4327 return res; | |
4328 } | |
4329 | |
4330 /* Determine whether CS also brings all scalar values that the NODE is | |
4331 specialized for. */ | |
4332 | |
4333 static bool | |
4334 cgraph_edge_brings_all_scalars_for_node (struct cgraph_edge *cs, | |
4335 struct cgraph_node *node) | |
4336 { | |
4337 struct ipa_node_params *dest_info = IPA_NODE_REF (node); | |
4338 int count = ipa_get_param_count (dest_info); | |
4339 struct ipa_node_params *caller_info; | |
4340 struct ipa_edge_args *args; | |
4341 int i; | |
4342 | |
4343 caller_info = IPA_NODE_REF (cs->caller); | |
4344 args = IPA_EDGE_REF (cs); | |
4345 for (i = 0; i < count; i++) | |
4346 { | |
4347 struct ipa_jump_func *jump_func; | |
4348 tree val, t; | |
4349 | |
4350 val = dest_info->known_csts[i]; | |
4351 if (!val) | |
4352 continue; | |
4353 | |
4354 if (i >= ipa_get_cs_argument_count (args)) | |
4355 return false; | |
4356 jump_func = ipa_get_ith_jump_func (args, i); | |
4357 t = ipa_value_from_jfunc (caller_info, jump_func); | |
4358 if (!t || !values_equal_for_ipcp_p (val, t)) | |
4359 return false; | |
4360 } | |
4361 return true; | |
4362 } | |
4363 | |
4364 /* Determine whether CS also brings all aggregate values that NODE is | |
4365 specialized for. */ | |
4366 static bool | |
4367 cgraph_edge_brings_all_agg_vals_for_node (struct cgraph_edge *cs, | |
4368 struct cgraph_node *node) | |
4369 { | |
4370 struct ipa_node_params *orig_caller_info = IPA_NODE_REF (cs->caller); | |
4371 struct ipa_node_params *orig_node_info; | |
4372 struct ipa_agg_replacement_value *aggval; | |
4373 int i, ec, count; | |
4374 | |
4375 aggval = ipa_get_agg_replacements_for_node (node); | |
4376 if (!aggval) | |
4377 return true; | |
4378 | |
4379 count = ipa_get_param_count (IPA_NODE_REF (node)); | |
4380 ec = ipa_get_cs_argument_count (IPA_EDGE_REF (cs)); | |
4381 if (ec < count) | |
4382 for (struct ipa_agg_replacement_value *av = aggval; av; av = av->next) | |
4383 if (aggval->index >= ec) | |
4384 return false; | |
4385 | |
4386 orig_node_info = IPA_NODE_REF (IPA_NODE_REF (node)->ipcp_orig_node); | |
4387 if (orig_caller_info->ipcp_orig_node) | |
4388 orig_caller_info = IPA_NODE_REF (orig_caller_info->ipcp_orig_node); | |
4389 | |
4390 for (i = 0; i < count; i++) | |
4391 { | |
4392 static vec<ipa_agg_jf_item> values = vec<ipa_agg_jf_item>(); | |
4393 struct ipcp_param_lattices *plats; | |
4394 bool interesting = false; | |
4395 for (struct ipa_agg_replacement_value *av = aggval; av; av = av->next) | |
4396 if (aggval->index == i) | |
4397 { | |
4398 interesting = true; | |
4399 break; | |
4400 } | |
4401 if (!interesting) | |
4402 continue; | |
4403 | |
4404 plats = ipa_get_parm_lattices (orig_node_info, aggval->index); | |
4405 if (plats->aggs_bottom) | |
4406 return false; | |
4407 | |
4408 values = intersect_aggregates_with_edge (cs, i, values); | |
4409 if (!values.exists ()) | |
4410 return false; | |
4411 | |
4412 for (struct ipa_agg_replacement_value *av = aggval; av; av = av->next) | |
4413 if (aggval->index == i) | |
4414 { | |
4415 struct ipa_agg_jf_item *item; | |
4416 int j; | |
4417 bool found = false; | |
4418 FOR_EACH_VEC_ELT (values, j, item) | |
4419 if (item->value | |
4420 && item->offset == av->offset | |
4421 && values_equal_for_ipcp_p (item->value, av->value)) | |
4422 { | |
4423 found = true; | |
4424 break; | |
4425 } | |
4426 if (!found) | |
4427 { | |
4428 values.release (); | |
4429 return false; | |
4430 } | |
4431 } | |
4432 } | |
4433 return true; | |
4434 } | |
4435 | |
4436 /* Given an original NODE and a VAL for which we have already created a | |
4437 specialized clone, look whether there are incoming edges that still lead | |
4438 into the old node but now also bring the requested value and also conform to | |
4439 all other criteria such that they can be redirected the special node. | |
4440 This function can therefore redirect the final edge in a SCC. */ | |
4441 | |
4442 template <typename valtype> | |
4443 static void | |
4444 perhaps_add_new_callers (cgraph_node *node, ipcp_value<valtype> *val) | |
4445 { | |
4446 ipcp_value_source<valtype> *src; | |
4447 profile_count redirected_sum = profile_count::zero (); | |
4448 | |
4449 for (src = val->sources; src; src = src->next) | |
4450 { | |
4451 struct cgraph_edge *cs = src->cs; | |
4452 while (cs) | |
4453 { | |
4454 if (cgraph_edge_brings_value_p (cs, src, node) | |
4455 && cgraph_edge_brings_all_scalars_for_node (cs, val->spec_node) | |
4456 && cgraph_edge_brings_all_agg_vals_for_node (cs, val->spec_node)) | |
4457 { | |
4458 if (dump_file) | |
4459 fprintf (dump_file, " - adding an extra caller %s of %s\n", | |
4460 cs->caller->dump_name (), | |
4461 val->spec_node->dump_name ()); | |
4462 | |
4463 cs->redirect_callee_duplicating_thunks (val->spec_node); | |
4464 val->spec_node->expand_all_artificial_thunks (); | |
4465 if (cs->count.initialized_p ()) | |
4466 redirected_sum = redirected_sum + cs->count; | |
4467 } | |
4468 cs = get_next_cgraph_edge_clone (cs); | |
4469 } | |
4470 } | |
4471 | |
4472 if (redirected_sum > profile_count::zero ()) | |
4473 update_specialized_profile (val->spec_node, node, redirected_sum); | |
4474 } | |
4475 | |
4476 /* Return true if KNOWN_CONTEXTS contain at least one useful context. */ | |
4477 | |
4478 static bool | |
4479 known_contexts_useful_p (vec<ipa_polymorphic_call_context> known_contexts) | |
4480 { | |
4481 ipa_polymorphic_call_context *ctx; | |
4482 int i; | |
4483 | |
4484 FOR_EACH_VEC_ELT (known_contexts, i, ctx) | |
4485 if (!ctx->useless_p ()) | |
4486 return true; | |
4487 return false; | |
4488 } | |
4489 | |
4490 /* Return a copy of KNOWN_CSTS if it is not empty, otherwise return vNULL. */ | |
4491 | |
4492 static vec<ipa_polymorphic_call_context> | |
4493 copy_useful_known_contexts (vec<ipa_polymorphic_call_context> known_contexts) | |
4494 { | |
4495 if (known_contexts_useful_p (known_contexts)) | |
4496 return known_contexts.copy (); | |
4497 else | |
4498 return vNULL; | |
4499 } | |
4500 | |
4501 /* Copy KNOWN_CSTS and modify the copy according to VAL and INDEX. If | |
4502 non-empty, replace KNOWN_CONTEXTS with its copy too. */ | |
4503 | |
4504 static void | |
4505 modify_known_vectors_with_val (vec<tree> *known_csts, | |
4506 vec<ipa_polymorphic_call_context> *known_contexts, | |
4507 ipcp_value<tree> *val, | |
4508 int index) | |
4509 { | |
4510 *known_csts = known_csts->copy (); | |
4511 *known_contexts = copy_useful_known_contexts (*known_contexts); | |
4512 (*known_csts)[index] = val->value; | |
4513 } | |
4514 | |
4515 /* Replace KNOWN_CSTS with its copy. Also copy KNOWN_CONTEXTS and modify the | |
4516 copy according to VAL and INDEX. */ | |
4517 | |
4518 static void | |
4519 modify_known_vectors_with_val (vec<tree> *known_csts, | |
4520 vec<ipa_polymorphic_call_context> *known_contexts, | |
4521 ipcp_value<ipa_polymorphic_call_context> *val, | |
4522 int index) | |
4523 { | |
4524 *known_csts = known_csts->copy (); | |
4525 *known_contexts = known_contexts->copy (); | |
4526 (*known_contexts)[index] = val->value; | |
4527 } | |
4528 | |
4529 /* Return true if OFFSET indicates this was not an aggregate value or there is | |
4530 a replacement equivalent to VALUE, INDEX and OFFSET among those in the | |
4531 AGGVALS list. */ | |
4532 | |
4533 DEBUG_FUNCTION bool | |
4534 ipcp_val_agg_replacement_ok_p (ipa_agg_replacement_value *aggvals, | |
4535 int index, HOST_WIDE_INT offset, tree value) | |
4536 { | |
4537 if (offset == -1) | |
4538 return true; | |
4539 | |
4540 while (aggvals) | |
4541 { | |
4542 if (aggvals->index == index | |
4543 && aggvals->offset == offset | |
4544 && values_equal_for_ipcp_p (aggvals->value, value)) | |
4545 return true; | |
4546 aggvals = aggvals->next; | |
4547 } | |
4548 return false; | |
4549 } | |
4550 | |
4551 /* Return true if offset is minus one because source of a polymorphic contect | |
4552 cannot be an aggregate value. */ | |
4553 | |
4554 DEBUG_FUNCTION bool | |
4555 ipcp_val_agg_replacement_ok_p (ipa_agg_replacement_value *, | |
4556 int , HOST_WIDE_INT offset, | |
4557 ipa_polymorphic_call_context) | |
4558 { | |
4559 return offset == -1; | |
4560 } | |
4561 | |
4562 /* Decide wheter to create a special version of NODE for value VAL of parameter | |
4563 at the given INDEX. If OFFSET is -1, the value is for the parameter itself, | |
4564 otherwise it is stored at the given OFFSET of the parameter. KNOWN_CSTS, | |
4565 KNOWN_CONTEXTS and KNOWN_AGGS describe the other already known values. */ | |
4566 | |
4567 template <typename valtype> | |
4568 static bool | |
4569 decide_about_value (struct cgraph_node *node, int index, HOST_WIDE_INT offset, | |
4570 ipcp_value<valtype> *val, vec<tree> known_csts, | |
4571 vec<ipa_polymorphic_call_context> known_contexts) | |
4572 { | |
4573 struct ipa_agg_replacement_value *aggvals; | |
4574 int freq_sum, caller_count; | |
4575 profile_count count_sum; | |
4576 vec<cgraph_edge *> callers; | |
4577 | |
4578 if (val->spec_node) | |
4579 { | |
4580 perhaps_add_new_callers (node, val); | |
4581 return false; | |
4582 } | |
4583 else if (val->local_size_cost + overall_size > max_new_size) | |
4584 { | |
4585 if (dump_file && (dump_flags & TDF_DETAILS)) | |
4586 fprintf (dump_file, " Ignoring candidate value because " | |
4587 "max_new_size would be reached with %li.\n", | |
4588 val->local_size_cost + overall_size); | |
4589 return false; | |
4590 } | |
4591 else if (!get_info_about_necessary_edges (val, node, &freq_sum, &count_sum, | |
4592 &caller_count)) | |
4593 return false; | |
4594 | |
4595 if (dump_file && (dump_flags & TDF_DETAILS)) | |
4596 { | |
4597 fprintf (dump_file, " - considering value "); | |
4598 print_ipcp_constant_value (dump_file, val->value); | |
4599 fprintf (dump_file, " for "); | |
4600 ipa_dump_param (dump_file, IPA_NODE_REF (node), index); | |
4601 if (offset != -1) | |
4602 fprintf (dump_file, ", offset: " HOST_WIDE_INT_PRINT_DEC, offset); | |
4603 fprintf (dump_file, " (caller_count: %i)\n", caller_count); | |
4604 } | |
4605 | |
4606 if (!good_cloning_opportunity_p (node, val->local_time_benefit, | |
4607 freq_sum, count_sum, | |
4608 val->local_size_cost) | |
4609 && !good_cloning_opportunity_p (node, | |
4610 val->local_time_benefit | |
4611 + val->prop_time_benefit, | |
4612 freq_sum, count_sum, | |
4613 val->local_size_cost | |
4614 + val->prop_size_cost)) | |
4615 return false; | |
4616 | |
4617 if (dump_file) | |
4618 fprintf (dump_file, " Creating a specialized node of %s.\n", | |
4619 node->dump_name ()); | |
4620 | |
4621 callers = gather_edges_for_value (val, node, caller_count); | |
4622 if (offset == -1) | |
4623 modify_known_vectors_with_val (&known_csts, &known_contexts, val, index); | |
4624 else | |
4625 { | |
4626 known_csts = known_csts.copy (); | |
4627 known_contexts = copy_useful_known_contexts (known_contexts); | |
4628 } | |
4629 find_more_scalar_values_for_callers_subset (node, known_csts, callers); | |
4630 find_more_contexts_for_caller_subset (node, &known_contexts, callers); | |
4631 aggvals = find_aggregate_values_for_callers_subset (node, callers); | |
4632 gcc_checking_assert (ipcp_val_agg_replacement_ok_p (aggvals, index, | |
4633 offset, val->value)); | |
4634 val->spec_node = create_specialized_node (node, known_csts, known_contexts, | |
4635 aggvals, callers); | |
4636 overall_size += val->local_size_cost; | |
4637 | |
4638 /* TODO: If for some lattice there is only one other known value | |
4639 left, make a special node for it too. */ | |
4640 | |
4641 return true; | |
4642 } | |
4643 | |
4644 /* Decide whether and what specialized clones of NODE should be created. */ | |
4645 | |
4646 static bool | |
4647 decide_whether_version_node (struct cgraph_node *node) | |
4648 { | |
4649 struct ipa_node_params *info = IPA_NODE_REF (node); | |
4650 int i, count = ipa_get_param_count (info); | |
4651 vec<tree> known_csts; | |
4652 vec<ipa_polymorphic_call_context> known_contexts; | |
4653 vec<ipa_agg_jump_function> known_aggs = vNULL; | |
4654 bool ret = false; | |
4655 | |
4656 if (count == 0) | |
4657 return false; | |
4658 | |
4659 if (dump_file && (dump_flags & TDF_DETAILS)) | |
4660 fprintf (dump_file, "\nEvaluating opportunities for %s.\n", | |
4661 node->dump_name ()); | |
4662 | |
4663 gather_context_independent_values (info, &known_csts, &known_contexts, | |
4664 info->do_clone_for_all_contexts ? &known_aggs | |
4665 : NULL, NULL); | |
4666 | |
4667 for (i = 0; i < count;i++) | |
4668 { | |
4669 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i); | |
4670 ipcp_lattice<tree> *lat = &plats->itself; | |
4671 ipcp_lattice<ipa_polymorphic_call_context> *ctxlat = &plats->ctxlat; | |
4672 | |
4673 if (!lat->bottom | |
4674 && !known_csts[i]) | |
4675 { | |
4676 ipcp_value<tree> *val; | |
4677 for (val = lat->values; val; val = val->next) | |
4678 ret |= decide_about_value (node, i, -1, val, known_csts, | |
4679 known_contexts); | |
4680 } | |
4681 | |
4682 if (!plats->aggs_bottom) | |
4683 { | |
4684 struct ipcp_agg_lattice *aglat; | |
4685 ipcp_value<tree> *val; | |
4686 for (aglat = plats->aggs; aglat; aglat = aglat->next) | |
4687 if (!aglat->bottom && aglat->values | |
4688 /* If the following is false, the one value is in | |
4689 known_aggs. */ | |
4690 && (plats->aggs_contain_variable | |
4691 || !aglat->is_single_const ())) | |
4692 for (val = aglat->values; val; val = val->next) | |
4693 ret |= decide_about_value (node, i, aglat->offset, val, | |
4694 known_csts, known_contexts); | |
4695 } | |
4696 | |
4697 if (!ctxlat->bottom | |
4698 && known_contexts[i].useless_p ()) | |
4699 { | |
4700 ipcp_value<ipa_polymorphic_call_context> *val; | |
4701 for (val = ctxlat->values; val; val = val->next) | |
4702 ret |= decide_about_value (node, i, -1, val, known_csts, | |
4703 known_contexts); | |
4704 } | |
4705 | |
4706 info = IPA_NODE_REF (node); | |
4707 } | |
4708 | |
4709 if (info->do_clone_for_all_contexts) | |
4710 { | |
4711 struct cgraph_node *clone; | |
4712 vec<cgraph_edge *> callers; | |
4713 | |
4714 if (dump_file) | |
4715 fprintf (dump_file, " - Creating a specialized node of %s " | |
4716 "for all known contexts.\n", node->dump_name ()); | |
4717 | |
4718 callers = node->collect_callers (); | |
4719 | |
4720 if (!known_contexts_useful_p (known_contexts)) | |
4721 { | |
4722 known_contexts.release (); | |
4723 known_contexts = vNULL; | |
4724 } | |
4725 clone = create_specialized_node (node, known_csts, known_contexts, | |
4726 known_aggs_to_agg_replacement_list (known_aggs), | |
4727 callers); | |
4728 info = IPA_NODE_REF (node); | |
4729 info->do_clone_for_all_contexts = false; | |
4730 IPA_NODE_REF (clone)->is_all_contexts_clone = true; | |
4731 for (i = 0; i < count; i++) | |
4732 vec_free (known_aggs[i].items); | |
4733 known_aggs.release (); | |
4734 ret = true; | |
4735 } | |
4736 else | |
4737 { | |
4738 known_csts.release (); | |
4739 known_contexts.release (); | |
4740 } | |
4741 | |
4742 return ret; | |
4743 } | |
4744 | |
4745 /* Transitively mark all callees of NODE within the same SCC as not dead. */ | |
4746 | |
4747 static void | |
4748 spread_undeadness (struct cgraph_node *node) | |
4749 { | |
4750 struct cgraph_edge *cs; | |
4751 | |
4752 for (cs = node->callees; cs; cs = cs->next_callee) | |
4753 if (ipa_edge_within_scc (cs)) | |
4754 { | |
4755 struct cgraph_node *callee; | |
4756 struct ipa_node_params *info; | |
4757 | |
4758 callee = cs->callee->function_symbol (NULL); | |
4759 info = IPA_NODE_REF (callee); | |
4760 | |
4761 if (info->node_dead) | |
4762 { | |
4763 info->node_dead = 0; | |
4764 spread_undeadness (callee); | |
4765 } | |
4766 } | |
4767 } | |
4768 | |
4769 /* Return true if NODE has a caller from outside of its SCC that is not | |
4770 dead. Worker callback for cgraph_for_node_and_aliases. */ | |
4771 | |
4772 static bool | |
4773 has_undead_caller_from_outside_scc_p (struct cgraph_node *node, | |
4774 void *data ATTRIBUTE_UNUSED) | |
4775 { | |
4776 struct cgraph_edge *cs; | |
4777 | |
4778 for (cs = node->callers; cs; cs = cs->next_caller) | |
4779 if (cs->caller->thunk.thunk_p | |
4780 && cs->caller->call_for_symbol_thunks_and_aliases | |
4781 (has_undead_caller_from_outside_scc_p, NULL, true)) | |
4782 return true; | |
4783 else if (!ipa_edge_within_scc (cs) | |
4784 && !IPA_NODE_REF (cs->caller)->node_dead) | |
4785 return true; | |
4786 return false; | |
4787 } | |
4788 | |
4789 | |
4790 /* Identify nodes within the same SCC as NODE which are no longer needed | |
4791 because of new clones and will be removed as unreachable. */ | |
4792 | |
4793 static void | |
4794 identify_dead_nodes (struct cgraph_node *node) | |
4795 { | |
4796 struct cgraph_node *v; | |
4797 for (v = node; v; v = ((struct ipa_dfs_info *) v->aux)->next_cycle) | |
4798 if (v->local.local | |
4799 && !v->call_for_symbol_thunks_and_aliases | |
4800 (has_undead_caller_from_outside_scc_p, NULL, true)) | |
4801 IPA_NODE_REF (v)->node_dead = 1; | |
4802 | |
4803 for (v = node; v; v = ((struct ipa_dfs_info *) v->aux)->next_cycle) | |
4804 if (!IPA_NODE_REF (v)->node_dead) | |
4805 spread_undeadness (v); | |
4806 | |
4807 if (dump_file && (dump_flags & TDF_DETAILS)) | |
4808 { | |
4809 for (v = node; v; v = ((struct ipa_dfs_info *) v->aux)->next_cycle) | |
4810 if (IPA_NODE_REF (v)->node_dead) | |
4811 fprintf (dump_file, " Marking node as dead: %s.\n", v->dump_name ()); | |
4812 } | |
4813 } | |
4814 | |
4815 /* The decision stage. Iterate over the topological order of call graph nodes | |
4816 TOPO and make specialized clones if deemed beneficial. */ | |
4817 | |
4818 static void | |
4819 ipcp_decision_stage (struct ipa_topo_info *topo) | |
4820 { | |
4821 int i; | |
4822 | |
4823 if (dump_file) | |
4824 fprintf (dump_file, "\nIPA decision stage:\n\n"); | |
4825 | |
4826 for (i = topo->nnodes - 1; i >= 0; i--) | |
4827 { | |
4828 struct cgraph_node *node = topo->order[i]; | |
4829 bool change = false, iterate = true; | |
4830 | |
4831 while (iterate) | |
4832 { | |
4833 struct cgraph_node *v; | |
4834 iterate = false; | |
4835 for (v = node; v; v = ((struct ipa_dfs_info *) v->aux)->next_cycle) | |
4836 if (v->has_gimple_body_p () | |
4837 && ipcp_versionable_function_p (v)) | |
4838 iterate |= decide_whether_version_node (v); | |
4839 | |
4840 change |= iterate; | |
4841 } | |
4842 if (change) | |
4843 identify_dead_nodes (node); | |
4844 } | |
4845 } | |
4846 | |
4847 /* Look up all the bits information that we have discovered and copy it over | |
4848 to the transformation summary. */ | |
4849 | |
4850 static void | |
4851 ipcp_store_bits_results (void) | |
4852 { | |
4853 cgraph_node *node; | |
4854 | |
4855 FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node) | |
4856 { | |
4857 ipa_node_params *info = IPA_NODE_REF (node); | |
4858 bool dumped_sth = false; | |
4859 bool found_useful_result = false; | |
4860 | |
4861 if (!opt_for_fn (node->decl, flag_ipa_bit_cp)) | |
4862 { | |
4863 if (dump_file) | |
4864 fprintf (dump_file, "Not considering %s for ipa bitwise propagation " | |
4865 "; -fipa-bit-cp: disabled.\n", | |
4866 node->name ()); | |
1360 continue; | 4867 continue; |
1361 info = IPA_NODE_REF (node); | 4868 } |
1362 if (ipa_is_called_with_var_arguments (info)) | 4869 |
4870 if (info->ipcp_orig_node) | |
4871 info = IPA_NODE_REF (info->ipcp_orig_node); | |
4872 | |
4873 unsigned count = ipa_get_param_count (info); | |
4874 for (unsigned i = 0; i < count; i++) | |
4875 { | |
4876 ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i); | |
4877 if (plats->bits_lattice.constant_p ()) | |
4878 { | |
4879 found_useful_result = true; | |
4880 break; | |
4881 } | |
4882 } | |
4883 | |
4884 if (!found_useful_result) | |
1363 continue; | 4885 continue; |
1364 if (ipcp_const_param_count (node)) | 4886 |
1365 node->aux = fibheap_insert (heap, ipcp_estimate_cloning_cost (node), | 4887 ipcp_grow_transformations_if_necessary (); |
1366 node); | 4888 ipcp_transformation_summary *ts = ipcp_get_transformation_summary (node); |
1367 } | 4889 vec_safe_reserve_exact (ts->bits, count); |
1368 | 4890 |
1369 /* Now clone in priority order until code size growth limits are met or | 4891 for (unsigned i = 0; i < count; i++) |
1370 heap is emptied. */ | 4892 { |
1371 while (!fibheap_empty (heap)) | 4893 ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i); |
1372 { | 4894 ipa_bits *jfbits; |
1373 struct ipa_node_params *info; | 4895 |
1374 int growth = 0; | 4896 if (plats->bits_lattice.constant_p ()) |
1375 bitmap args_to_skip; | 4897 jfbits |
1376 struct cgraph_edge *cs; | 4898 = ipa_get_ipa_bits_for_value (plats->bits_lattice.get_value (), |
1377 | 4899 plats->bits_lattice.get_mask ()); |
1378 node = (struct cgraph_node *)fibheap_extract_min (heap); | 4900 else |
1379 node->aux = NULL; | 4901 jfbits = NULL; |
1380 if (dump_file) | 4902 |
1381 fprintf (dump_file, "considering function %s\n", | 4903 ts->bits->quick_push (jfbits); |
1382 cgraph_node_name (node)); | 4904 if (!dump_file || !jfbits) |
1383 | 4905 continue; |
1384 growth = ipcp_estimate_growth (node); | 4906 if (!dumped_sth) |
1385 | 4907 { |
1386 if (new_size + growth > max_new_size) | 4908 fprintf (dump_file, "Propagated bits info for function %s:\n", |
1387 break; | 4909 node->dump_name ()); |
1388 if (growth | 4910 dumped_sth = true; |
1389 && optimize_function_for_size_p (DECL_STRUCT_FUNCTION (node->decl))) | 4911 } |
4912 fprintf (dump_file, " param %i: value = ", i); | |
4913 print_hex (jfbits->value, dump_file); | |
4914 fprintf (dump_file, ", mask = "); | |
4915 print_hex (jfbits->mask, dump_file); | |
4916 fprintf (dump_file, "\n"); | |
4917 } | |
4918 } | |
4919 } | |
4920 | |
4921 /* Look up all VR information that we have discovered and copy it over | |
4922 to the transformation summary. */ | |
4923 | |
4924 static void | |
4925 ipcp_store_vr_results (void) | |
4926 { | |
4927 cgraph_node *node; | |
4928 | |
4929 FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node) | |
4930 { | |
4931 ipa_node_params *info = IPA_NODE_REF (node); | |
4932 bool found_useful_result = false; | |
4933 | |
4934 if (!opt_for_fn (node->decl, flag_ipa_vrp)) | |
1390 { | 4935 { |
1391 if (dump_file) | 4936 if (dump_file) |
1392 fprintf (dump_file, "Not versioning, cold code would grow"); | 4937 fprintf (dump_file, "Not considering %s for VR discovery " |
4938 "and propagate; -fipa-ipa-vrp: disabled.\n", | |
4939 node->name ()); | |
1393 continue; | 4940 continue; |
1394 } | 4941 } |
1395 | 4942 |
1396 info = IPA_NODE_REF (node); | 4943 if (info->ipcp_orig_node) |
1397 count = ipa_get_param_count (info); | 4944 info = IPA_NODE_REF (info->ipcp_orig_node); |
1398 | 4945 |
1399 replace_trees = VEC_alloc (ipa_replace_map_p, gc, 1); | 4946 unsigned count = ipa_get_param_count (info); |
1400 | 4947 for (unsigned i = 0; i < count; i++) |
1401 if (node->local.can_change_signature) | 4948 { |
1402 args_to_skip = BITMAP_GGC_ALLOC (); | 4949 ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i); |
1403 else | 4950 if (!plats->m_value_range.bottom_p () |
1404 args_to_skip = NULL; | 4951 && !plats->m_value_range.top_p ()) |
1405 for (i = 0; i < count; i++) | |
1406 { | |
1407 struct ipcp_lattice *lat = ipcp_get_lattice (info, i); | |
1408 parm_tree = ipa_get_param (info, i); | |
1409 | |
1410 /* We can proactively remove obviously unused arguments. */ | |
1411 if (!ipa_is_param_used (info, i)) | |
1412 { | 4952 { |
1413 if (args_to_skip) | 4953 found_useful_result = true; |
1414 bitmap_set_bit (args_to_skip, i); | 4954 break; |
1415 continue; | |
1416 } | 4955 } |
1417 | 4956 } |
1418 if (lat->type == IPA_CONST_VALUE) | 4957 if (!found_useful_result) |
4958 continue; | |
4959 | |
4960 ipcp_grow_transformations_if_necessary (); | |
4961 ipcp_transformation_summary *ts = ipcp_get_transformation_summary (node); | |
4962 vec_safe_reserve_exact (ts->m_vr, count); | |
4963 | |
4964 for (unsigned i = 0; i < count; i++) | |
4965 { | |
4966 ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i); | |
4967 ipa_vr vr; | |
4968 | |
4969 if (!plats->m_value_range.bottom_p () | |
4970 && !plats->m_value_range.top_p ()) | |
1419 { | 4971 { |
1420 replace_param = | 4972 vr.known = true; |
1421 ipcp_create_replace_map (parm_tree, lat); | 4973 vr.type = plats->m_value_range.m_vr.type; |
1422 if (replace_param == NULL) | 4974 vr.min = wi::to_wide (plats->m_value_range.m_vr.min); |
1423 break; | 4975 vr.max = wi::to_wide (plats->m_value_range.m_vr.max); |
1424 VEC_safe_push (ipa_replace_map_p, gc, replace_trees, replace_param); | |
1425 if (args_to_skip) | |
1426 bitmap_set_bit (args_to_skip, i); | |
1427 } | 4976 } |
1428 } | 4977 else |
1429 if (i < count) | 4978 { |
1430 { | 4979 vr.known = false; |
1431 if (dump_file) | 4980 vr.type = VR_VARYING; |
1432 fprintf (dump_file, "Not versioning, some parameters couldn't be replaced"); | 4981 vr.min = vr.max = wi::zero (INT_TYPE_SIZE); |
1433 continue; | 4982 } |
1434 } | 4983 ts->m_vr->quick_push (vr); |
1435 | 4984 } |
1436 new_size += growth; | 4985 } |
1437 | |
1438 /* Look if original function becomes dead after cloning. */ | |
1439 for (cs = node->callers; cs != NULL; cs = cs->next_caller) | |
1440 if (cs->caller == node || ipcp_need_redirect_p (cs)) | |
1441 break; | |
1442 if (!cs && cgraph_will_be_removed_from_program_if_no_direct_calls (node)) | |
1443 bitmap_set_bit (dead_nodes, node->uid); | |
1444 | |
1445 /* Compute how many callers node has. */ | |
1446 node_callers = 0; | |
1447 for (cs = node->callers; cs != NULL; cs = cs->next_caller) | |
1448 node_callers++; | |
1449 redirect_callers = VEC_alloc (cgraph_edge_p, heap, node_callers); | |
1450 for (cs = node->callers; cs != NULL; cs = cs->next_caller) | |
1451 if (!cs->indirect_inlining_edge) | |
1452 VEC_quick_push (cgraph_edge_p, redirect_callers, cs); | |
1453 | |
1454 /* Redirecting all the callers of the node to the | |
1455 new versioned node. */ | |
1456 node1 = | |
1457 cgraph_create_virtual_clone (node, redirect_callers, replace_trees, | |
1458 args_to_skip, "constprop"); | |
1459 args_to_skip = NULL; | |
1460 VEC_free (cgraph_edge_p, heap, redirect_callers); | |
1461 replace_trees = NULL; | |
1462 | |
1463 if (node1 == NULL) | |
1464 continue; | |
1465 ipcp_process_devirtualization_opportunities (node1); | |
1466 | |
1467 if (dump_file) | |
1468 fprintf (dump_file, "versioned function %s with growth %i, overall %i\n", | |
1469 cgraph_node_name (node), (int)growth, (int)new_size); | |
1470 ipcp_init_cloned_node (node, node1); | |
1471 | |
1472 info = IPA_NODE_REF (node); | |
1473 for (i = 0; i < count; i++) | |
1474 { | |
1475 struct ipcp_lattice *lat = ipcp_get_lattice (info, i); | |
1476 if (lat->type == IPA_CONST_VALUE) | |
1477 ipcp_discover_new_direct_edges (node1, i, lat->constant); | |
1478 } | |
1479 | |
1480 if (dump_file) | |
1481 dump_function_to_file (node1->decl, dump_file, dump_flags); | |
1482 | |
1483 for (cs = node->callees; cs; cs = cs->next_callee) | |
1484 if (cs->callee->aux) | |
1485 { | |
1486 fibheap_delete_node (heap, (fibnode_t) cs->callee->aux); | |
1487 cs->callee->aux = fibheap_insert (heap, | |
1488 ipcp_estimate_cloning_cost (cs->callee), | |
1489 cs->callee); | |
1490 } | |
1491 } | |
1492 | |
1493 while (!fibheap_empty (heap)) | |
1494 { | |
1495 if (dump_file) | |
1496 fprintf (dump_file, "skipping function %s\n", | |
1497 cgraph_node_name (node)); | |
1498 node = (struct cgraph_node *) fibheap_extract_min (heap); | |
1499 node->aux = NULL; | |
1500 } | |
1501 fibheap_delete (heap); | |
1502 BITMAP_FREE (dead_nodes); | |
1503 ipcp_update_callgraph (); | |
1504 ipcp_update_profiling (); | |
1505 } | 4986 } |
1506 | 4987 |
1507 /* The IPCP driver. */ | 4988 /* The IPCP driver. */ |
4989 | |
1508 static unsigned int | 4990 static unsigned int |
1509 ipcp_driver (void) | 4991 ipcp_driver (void) |
1510 { | 4992 { |
1511 cgraph_remove_unreachable_nodes (true,dump_file); | 4993 struct cgraph_2edge_hook_list *edge_duplication_hook_holder; |
4994 struct cgraph_edge_hook_list *edge_removal_hook_holder; | |
4995 struct ipa_topo_info topo; | |
4996 | |
4997 ipa_check_create_node_params (); | |
4998 ipa_check_create_edge_args (); | |
4999 grow_edge_clone_vectors (); | |
5000 edge_duplication_hook_holder | |
5001 = symtab->add_edge_duplication_hook (&ipcp_edge_duplication_hook, NULL); | |
5002 edge_removal_hook_holder | |
5003 = symtab->add_edge_removal_hook (&ipcp_edge_removal_hook, NULL); | |
5004 | |
1512 if (dump_file) | 5005 if (dump_file) |
1513 { | 5006 { |
1514 fprintf (dump_file, "\nIPA structures before propagation:\n"); | 5007 fprintf (dump_file, "\nIPA structures before propagation:\n"); |
1515 if (dump_flags & TDF_DETAILS) | 5008 if (dump_flags & TDF_DETAILS) |
1516 ipa_print_all_params (dump_file); | 5009 ipa_print_all_params (dump_file); |
1517 ipa_print_all_jump_functions (dump_file); | 5010 ipa_print_all_jump_functions (dump_file); |
1518 } | 5011 } |
1519 /* 2. Do the interprocedural propagation. */ | 5012 |
1520 ipcp_iterate_stage (); | 5013 /* Topological sort. */ |
1521 /* 3. Insert the constants found to the functions. */ | 5014 build_toporder_info (&topo); |
1522 ipcp_insert_stage (); | 5015 /* Do the interprocedural propagation. */ |
1523 if (dump_file && (dump_flags & TDF_DETAILS)) | 5016 ipcp_propagate_stage (&topo); |
1524 { | 5017 /* Decide what constant propagation and cloning should be performed. */ |
1525 fprintf (dump_file, "\nProfiling info after insert stage:\n"); | 5018 ipcp_decision_stage (&topo); |
1526 ipcp_print_profile_data (dump_file); | 5019 /* Store results of bits propagation. */ |
1527 } | 5020 ipcp_store_bits_results (); |
5021 /* Store results of value range propagation. */ | |
5022 ipcp_store_vr_results (); | |
5023 | |
1528 /* Free all IPCP structures. */ | 5024 /* Free all IPCP structures. */ |
5025 free_toporder_info (&topo); | |
5026 next_edge_clone.release (); | |
5027 prev_edge_clone.release (); | |
5028 symtab->remove_edge_removal_hook (edge_removal_hook_holder); | |
5029 symtab->remove_edge_duplication_hook (edge_duplication_hook_holder); | |
1529 ipa_free_all_structures_after_ipa_cp (); | 5030 ipa_free_all_structures_after_ipa_cp (); |
1530 if (dump_file) | 5031 if (dump_file) |
1531 fprintf (dump_file, "\nIPA constant propagation end\n"); | 5032 fprintf (dump_file, "\nIPA constant propagation end\n"); |
1532 return 0; | 5033 return 0; |
1533 } | 5034 } |
1541 { | 5042 { |
1542 struct cgraph_node *node; | 5043 struct cgraph_node *node; |
1543 | 5044 |
1544 if (dump_file) | 5045 if (dump_file) |
1545 fprintf (dump_file, "\nIPA constant propagation start:\n"); | 5046 fprintf (dump_file, "\nIPA constant propagation start:\n"); |
1546 ipa_check_create_node_params (); | |
1547 ipa_check_create_edge_args (); | |
1548 ipa_register_cgraph_hooks (); | 5047 ipa_register_cgraph_hooks (); |
1549 | 5048 |
1550 for (node = cgraph_nodes; node; node = node->next) | 5049 FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node) |
1551 if (node->analyzed) | 5050 ipa_analyze_node (node); |
1552 { | |
1553 /* Unreachable nodes should have been eliminated before ipcp. */ | |
1554 gcc_assert (node->needed || node->reachable); | |
1555 | |
1556 node->local.versionable = tree_versionable_function_p (node->decl); | |
1557 ipa_analyze_node (node); | |
1558 } | |
1559 } | 5051 } |
1560 | 5052 |
1561 /* Write ipcp summary for nodes in SET. */ | 5053 /* Write ipcp summary for nodes in SET. */ |
5054 | |
1562 static void | 5055 static void |
1563 ipcp_write_summary (cgraph_node_set set, | 5056 ipcp_write_summary (void) |
1564 varpool_node_set vset ATTRIBUTE_UNUSED) | 5057 { |
1565 { | 5058 ipa_prop_write_jump_functions (); |
1566 ipa_prop_write_jump_functions (set); | |
1567 } | 5059 } |
1568 | 5060 |
1569 /* Read ipcp summary. */ | 5061 /* Read ipcp summary. */ |
5062 | |
1570 static void | 5063 static void |
1571 ipcp_read_summary (void) | 5064 ipcp_read_summary (void) |
1572 { | 5065 { |
1573 ipa_prop_read_jump_functions (); | 5066 ipa_prop_read_jump_functions (); |
1574 } | 5067 } |
1575 | 5068 |
1576 /* Gate for IPCP optimization. */ | 5069 namespace { |
1577 static bool | 5070 |
1578 cgraph_gate_cp (void) | 5071 const pass_data pass_data_ipa_cp = |
1579 { | 5072 { |
1580 /* FIXME: We should remove the optimize check after we ensure we never run | 5073 IPA_PASS, /* type */ |
1581 IPA passes when not optimizing. */ | 5074 "cp", /* name */ |
1582 return flag_ipa_cp && optimize; | 5075 OPTGROUP_NONE, /* optinfo_flags */ |
1583 } | 5076 TV_IPA_CONSTANT_PROP, /* tv_id */ |
1584 | 5077 0, /* properties_required */ |
1585 struct ipa_opt_pass_d pass_ipa_cp = | 5078 0, /* properties_provided */ |
1586 { | 5079 0, /* properties_destroyed */ |
1587 { | 5080 0, /* todo_flags_start */ |
1588 IPA_PASS, | 5081 ( TODO_dump_symtab | TODO_remove_functions ), /* todo_flags_finish */ |
1589 "cp", /* name */ | |
1590 cgraph_gate_cp, /* gate */ | |
1591 ipcp_driver, /* execute */ | |
1592 NULL, /* sub */ | |
1593 NULL, /* next */ | |
1594 0, /* static_pass_number */ | |
1595 TV_IPA_CONSTANT_PROP, /* tv_id */ | |
1596 0, /* properties_required */ | |
1597 0, /* properties_provided */ | |
1598 0, /* properties_destroyed */ | |
1599 0, /* todo_flags_start */ | |
1600 TODO_dump_cgraph | TODO_dump_func | | |
1601 TODO_remove_functions | TODO_ggc_collect /* todo_flags_finish */ | |
1602 }, | |
1603 ipcp_generate_summary, /* generate_summary */ | |
1604 ipcp_write_summary, /* write_summary */ | |
1605 ipcp_read_summary, /* read_summary */ | |
1606 NULL, /* write_optimization_summary */ | |
1607 NULL, /* read_optimization_summary */ | |
1608 NULL, /* stmt_fixup */ | |
1609 0, /* TODOs */ | |
1610 NULL, /* function_transform */ | |
1611 NULL, /* variable_transform */ | |
1612 }; | 5082 }; |
5083 | |
5084 class pass_ipa_cp : public ipa_opt_pass_d | |
5085 { | |
5086 public: | |
5087 pass_ipa_cp (gcc::context *ctxt) | |
5088 : ipa_opt_pass_d (pass_data_ipa_cp, ctxt, | |
5089 ipcp_generate_summary, /* generate_summary */ | |
5090 ipcp_write_summary, /* write_summary */ | |
5091 ipcp_read_summary, /* read_summary */ | |
5092 ipcp_write_transformation_summaries, /* | |
5093 write_optimization_summary */ | |
5094 ipcp_read_transformation_summaries, /* | |
5095 read_optimization_summary */ | |
5096 NULL, /* stmt_fixup */ | |
5097 0, /* function_transform_todo_flags_start */ | |
5098 ipcp_transform_function, /* function_transform */ | |
5099 NULL) /* variable_transform */ | |
5100 {} | |
5101 | |
5102 /* opt_pass methods: */ | |
5103 virtual bool gate (function *) | |
5104 { | |
5105 /* FIXME: We should remove the optimize check after we ensure we never run | |
5106 IPA passes when not optimizing. */ | |
5107 return (flag_ipa_cp && optimize) || in_lto_p; | |
5108 } | |
5109 | |
5110 virtual unsigned int execute (function *) { return ipcp_driver (); } | |
5111 | |
5112 }; // class pass_ipa_cp | |
5113 | |
5114 } // anon namespace | |
5115 | |
5116 ipa_opt_pass_d * | |
5117 make_pass_ipa_cp (gcc::context *ctxt) | |
5118 { | |
5119 return new pass_ipa_cp (ctxt); | |
5120 } | |
5121 | |
5122 /* Reset all state within ipa-cp.c so that we can rerun the compiler | |
5123 within the same process. For use by toplev::finalize. */ | |
5124 | |
5125 void | |
5126 ipa_cp_c_finalize (void) | |
5127 { | |
5128 max_count = profile_count::zero (); | |
5129 overall_size = 0; | |
5130 max_new_size = 0; | |
5131 } |