]>
Commit | Line | Data |
---|---|---|
ea900239 | 1 | /* Callgraph based analysis of static variables. |
c75c517d SB |
2 | Copyright (C) 2004, 2005, 2007, 2008, 2009, 2010 |
3 | Free Software Foundation, Inc. | |
ea900239 DB |
4 | Contributed by Kenneth Zadeck <zadeck@naturalbridge.com> |
5 | ||
6 | This file is part of GCC. | |
7 | ||
8 | 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 | |
9dcd6f09 | 10 | Software Foundation; either version 3, or (at your option) any later |
ea900239 DB |
11 | version. |
12 | ||
13 | GCC is distributed in the hope that it will be useful, but WITHOUT ANY | |
14 | WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
15 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
16 | for more details. | |
17 | ||
18 | You should have received a copy of the GNU General Public License | |
9dcd6f09 NC |
19 | along with GCC; see the file COPYING3. If not see |
20 | <http://www.gnu.org/licenses/>. */ | |
ea900239 DB |
21 | |
22 | /* This file gathers information about how variables whose scope is | |
b8698a0f | 23 | confined to the compilation unit are used. |
ea900239 | 24 | |
4a444e58 | 25 | The transitive call site specific clobber effects are computed |
ea900239 DB |
26 | for the variables whose scope is contained within this compilation |
27 | unit. | |
28 | ||
29 | First each function and static variable initialization is analyzed | |
30 | to determine which local static variables are either read, written, | |
31 | or have their address taken. Any local static that has its address | |
32 | taken is removed from consideration. Once the local read and | |
33 | writes are determined, a transitive closure of this information is | |
34 | performed over the call graph to determine the worst case set of | |
35 | side effects of each call. In later parts of the compiler, these | |
36 | local and global sets are examined to make the call clobbering less | |
37 | traumatic, promote some statics to registers, and improve aliasing | |
4a444e58 | 38 | information. */ |
ea900239 DB |
39 | |
40 | #include "config.h" | |
41 | #include "system.h" | |
42 | #include "coretypes.h" | |
43 | #include "tm.h" | |
44 | #include "tree.h" | |
45 | #include "tree-flow.h" | |
46 | #include "tree-inline.h" | |
47 | #include "tree-pass.h" | |
48 | #include "langhooks.h" | |
49 | #include "pointer-set.h" | |
ea264ca5 | 50 | #include "splay-tree.h" |
ea900239 DB |
51 | #include "ggc.h" |
52 | #include "ipa-utils.h" | |
53 | #include "ipa-reference.h" | |
726a989a | 54 | #include "gimple.h" |
ea900239 DB |
55 | #include "cgraph.h" |
56 | #include "output.h" | |
57 | #include "flags.h" | |
58 | #include "timevar.h" | |
59 | #include "diagnostic.h" | |
60 | #include "langhooks.h" | |
d7f09764 DN |
61 | #include "lto-streamer.h" |
62 | ||
d7f09764 DN |
63 | static void remove_node_data (struct cgraph_node *node, |
64 | void *data ATTRIBUTE_UNUSED); | |
65 | static void duplicate_node_data (struct cgraph_node *src, | |
66 | struct cgraph_node *dst, | |
67 | void *data ATTRIBUTE_UNUSED); | |
ea900239 | 68 | |
e2c9111c | 69 | /* The static variables defined within the compilation unit that are |
b8698a0f | 70 | loaded or stored directly by function that owns this structure. */ |
e2c9111c | 71 | |
b8698a0f | 72 | struct ipa_reference_local_vars_info_d |
e2c9111c JH |
73 | { |
74 | bitmap statics_read; | |
75 | bitmap statics_written; | |
e2c9111c JH |
76 | }; |
77 | ||
78 | /* Statics that are read and written by some set of functions. The | |
79 | local ones are based on the loads and stores local to the function. | |
80 | The global ones are based on the local info as well as the | |
46c30019 | 81 | transitive closure of the functions that are called. */ |
e2c9111c JH |
82 | |
83 | struct ipa_reference_global_vars_info_d | |
84 | { | |
85 | bitmap statics_read; | |
86 | bitmap statics_written; | |
46c30019 JH |
87 | }; |
88 | ||
61502ca8 | 89 | /* Information we save about every function after ipa-reference is completed. */ |
46c30019 JH |
90 | |
91 | struct ipa_reference_optimization_summary_d | |
92 | { | |
e2c9111c JH |
93 | bitmap statics_not_read; |
94 | bitmap statics_not_written; | |
95 | }; | |
96 | ||
97 | typedef struct ipa_reference_local_vars_info_d *ipa_reference_local_vars_info_t; | |
98 | typedef struct ipa_reference_global_vars_info_d *ipa_reference_global_vars_info_t; | |
46c30019 JH |
99 | typedef struct ipa_reference_optimization_summary_d *ipa_reference_optimization_summary_t; |
100 | ||
b8698a0f | 101 | struct ipa_reference_vars_info_d |
e2c9111c | 102 | { |
46c30019 JH |
103 | struct ipa_reference_local_vars_info_d local; |
104 | struct ipa_reference_global_vars_info_d global; | |
e2c9111c JH |
105 | }; |
106 | ||
107 | typedef struct ipa_reference_vars_info_d *ipa_reference_vars_info_t; | |
108 | ||
ea900239 | 109 | /* This splay tree contains all of the static variables that are |
46c30019 JH |
110 | being considered by the compilation level alias analysis. */ |
111 | static splay_tree reference_vars_to_consider; | |
ea900239 | 112 | |
ea900239 DB |
113 | /* A bit is set for every module static we are considering. This is |
114 | ored into the local info when asm code is found that clobbers all | |
115 | memory. */ | |
116 | static bitmap all_module_statics; | |
117 | ||
ebcf9dc8 JH |
118 | /* Obstack holding bitmaps of local analysis (live from analysis to |
119 | propagation) */ | |
120 | static bitmap_obstack local_info_obstack; | |
121 | /* Obstack holding global analysis live forever. */ | |
46c30019 | 122 | static bitmap_obstack optimization_summary_obstack; |
ea900239 | 123 | |
129a37fc | 124 | /* Holders of ipa cgraph hooks: */ |
e2c9111c JH |
125 | static struct cgraph_2node_hook_list *node_duplication_hook_holder; |
126 | static struct cgraph_node_hook_list *node_removal_hook_holder; | |
129a37fc | 127 | |
e2c9111c JH |
128 | /* Vector where the reference var infos are actually stored. */ |
129 | DEF_VEC_P (ipa_reference_vars_info_t); | |
130 | DEF_VEC_ALLOC_P (ipa_reference_vars_info_t, heap); | |
131 | static VEC (ipa_reference_vars_info_t, heap) *ipa_reference_vars_vector; | |
46c30019 JH |
132 | DEF_VEC_P (ipa_reference_optimization_summary_t); |
133 | DEF_VEC_ALLOC_P (ipa_reference_optimization_summary_t, heap); | |
134 | static VEC (ipa_reference_optimization_summary_t, heap) *ipa_reference_opt_sum_vector; | |
e2c9111c | 135 | |
ea900239 DB |
136 | /* Return the ipa_reference_vars structure starting from the cgraph NODE. */ |
137 | static inline ipa_reference_vars_info_t | |
e2c9111c JH |
138 | get_reference_vars_info (struct cgraph_node *node) |
139 | { | |
140 | if (!ipa_reference_vars_vector | |
46c30019 JH |
141 | || VEC_length (ipa_reference_vars_info_t, |
142 | ipa_reference_vars_vector) <= (unsigned int) node->uid) | |
e2c9111c | 143 | return NULL; |
46c30019 JH |
144 | return VEC_index (ipa_reference_vars_info_t, ipa_reference_vars_vector, |
145 | node->uid); | |
e2c9111c JH |
146 | } |
147 | ||
148 | /* Return the ipa_reference_vars structure starting from the cgraph NODE. */ | |
46c30019 JH |
149 | static inline ipa_reference_optimization_summary_t |
150 | get_reference_optimization_summary (struct cgraph_node *node) | |
ea900239 | 151 | { |
46c30019 JH |
152 | if (!ipa_reference_opt_sum_vector |
153 | || (VEC_length (ipa_reference_optimization_summary_t, | |
22a8d1e6 | 154 | ipa_reference_opt_sum_vector) |
46c30019 | 155 | <= (unsigned int) node->uid)) |
ea900239 | 156 | return NULL; |
46c30019 JH |
157 | return VEC_index (ipa_reference_optimization_summary_t, ipa_reference_opt_sum_vector, |
158 | node->uid); | |
ea900239 DB |
159 | } |
160 | ||
46c30019 JH |
161 | /* Return the ipa_reference_vars structure starting from the cgraph NODE. */ |
162 | static inline void | |
163 | set_reference_vars_info (struct cgraph_node *node, | |
164 | ipa_reference_vars_info_t info) | |
ea900239 | 165 | { |
46c30019 JH |
166 | if (!ipa_reference_vars_vector |
167 | || VEC_length (ipa_reference_vars_info_t, | |
168 | ipa_reference_vars_vector) <= (unsigned int) node->uid) | |
169 | VEC_safe_grow_cleared (ipa_reference_vars_info_t, heap, | |
170 | ipa_reference_vars_vector, node->uid + 1); | |
171 | VEC_replace (ipa_reference_vars_info_t, ipa_reference_vars_vector, | |
172 | node->uid, info); | |
ea900239 DB |
173 | } |
174 | ||
46c30019 JH |
175 | /* Return the ipa_reference_vars structure starting from the cgraph NODE. */ |
176 | static inline void | |
177 | set_reference_optimization_summary (struct cgraph_node *node, | |
178 | ipa_reference_optimization_summary_t info) | |
ea900239 | 179 | { |
46c30019 JH |
180 | if (!ipa_reference_opt_sum_vector |
181 | || (VEC_length (ipa_reference_optimization_summary_t, | |
182 | ipa_reference_opt_sum_vector) | |
183 | <= (unsigned int) node->uid)) | |
184 | VEC_safe_grow_cleared (ipa_reference_optimization_summary_t, | |
185 | heap, ipa_reference_opt_sum_vector, node->uid + 1); | |
186 | VEC_replace (ipa_reference_optimization_summary_t, | |
187 | ipa_reference_opt_sum_vector, node->uid, info); | |
ea900239 DB |
188 | } |
189 | ||
190 | /* Return a bitmap indexed by_DECL_UID uid for the static variables | |
191 | that are not read during the execution of the function FN. Returns | |
192 | NULL if no data is available. */ | |
193 | ||
b8698a0f L |
194 | bitmap |
195 | ipa_reference_get_not_read_global (struct cgraph_node *fn) | |
ea900239 | 196 | { |
46c30019 JH |
197 | ipa_reference_optimization_summary_t info; |
198 | ||
199 | info = get_reference_optimization_summary (fn); | |
200 | if (info) | |
201 | return info->statics_not_read; | |
46a4da10 JH |
202 | else if (flags_from_decl_or_type (fn->decl) & ECF_LEAF) |
203 | return all_module_statics; | |
ea900239 DB |
204 | else |
205 | return NULL; | |
206 | } | |
207 | ||
208 | /* Return a bitmap indexed by DECL_UID uid for the static variables | |
209 | that are not written during the execution of the function FN. Note | |
210 | that variables written may or may not be read during the function | |
211 | call. Returns NULL if no data is available. */ | |
212 | ||
b8698a0f L |
213 | bitmap |
214 | ipa_reference_get_not_written_global (struct cgraph_node *fn) | |
ea900239 | 215 | { |
46c30019 JH |
216 | ipa_reference_optimization_summary_t info; |
217 | ||
218 | info = get_reference_optimization_summary (fn); | |
219 | if (info) | |
220 | return info->statics_not_written; | |
46a4da10 JH |
221 | else if (flags_from_decl_or_type (fn->decl) & ECF_LEAF) |
222 | return all_module_statics; | |
ea900239 DB |
223 | else |
224 | return NULL; | |
225 | } | |
226 | ||
227 | \f | |
228 | ||
229 | /* Add VAR to all_module_statics and the two | |
230 | reference_vars_to_consider* sets. */ | |
231 | ||
b8698a0f L |
232 | static inline void |
233 | add_static_var (tree var) | |
ea900239 DB |
234 | { |
235 | int uid = DECL_UID (var); | |
ebcf9dc8 | 236 | gcc_assert (TREE_CODE (var) == VAR_DECL); |
df24c2b8 JH |
237 | if (dump_file) |
238 | splay_tree_insert (reference_vars_to_consider, | |
239 | uid, (splay_tree_value)var); | |
240 | bitmap_set_bit (all_module_statics, uid); | |
ea900239 DB |
241 | } |
242 | ||
243 | /* Return true if the variable T is the right kind of static variable to | |
244 | perform compilation unit scope escape analysis. */ | |
245 | ||
b8698a0f | 246 | static inline bool |
5f902d76 | 247 | is_proper_for_analysis (tree t) |
ea900239 | 248 | { |
46c30019 JH |
249 | /* We handle only variables whose address is never taken. */ |
250 | if (TREE_ADDRESSABLE (t)) | |
251 | return false; | |
22a8d1e6 | 252 | |
ea900239 DB |
253 | /* If the variable has the "used" attribute, treat it as if it had a |
254 | been touched by the devil. */ | |
b42186f1 | 255 | if (DECL_PRESERVE_P (t)) |
ea900239 DB |
256 | return false; |
257 | ||
258 | /* Do not want to do anything with volatile except mark any | |
259 | function that uses one to be not const or pure. */ | |
b8698a0f | 260 | if (TREE_THIS_VOLATILE (t)) |
ea900239 DB |
261 | return false; |
262 | ||
22a8d1e6 JH |
263 | /* We do not need to analyze readonly vars, we already know they do not |
264 | alias. */ | |
265 | if (TREE_READONLY (t)) | |
266 | return false; | |
267 | ||
2276d5ed AP |
268 | /* We cannot touch decls where the type needs constructing. */ |
269 | if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (t))) | |
270 | return false; | |
271 | ||
ea900239 DB |
272 | /* This is a variable we care about. Check if we have seen it |
273 | before, and if not add it the set of variables we care about. */ | |
f3380641 JH |
274 | if (all_module_statics |
275 | && !bitmap_bit_p (all_module_statics, DECL_UID (t))) | |
ea900239 DB |
276 | add_static_var (t); |
277 | ||
278 | return true; | |
279 | } | |
280 | ||
ea900239 | 281 | /* Lookup the tree node for the static variable that has UID and |
a4174ebf | 282 | convert the name to a string for debugging. */ |
ea900239 DB |
283 | |
284 | static const char * | |
285 | get_static_name (int index) | |
286 | { | |
b8698a0f | 287 | splay_tree_node stn = |
ea900239 DB |
288 | splay_tree_lookup (reference_vars_to_consider, index); |
289 | if (stn) | |
290 | return lang_hooks.decl_printable_name ((tree)(stn->value), 2); | |
291 | return NULL; | |
292 | } | |
293 | ||
e2c9111c JH |
294 | /* Or in all of the bits from every callee of X into X_GLOBAL, the caller's cycle, |
295 | bit vector. There are several cases to check to avoid the sparse | |
ea900239 DB |
296 | bitmap oring. */ |
297 | ||
298 | static void | |
e2c9111c | 299 | propagate_bits (ipa_reference_global_vars_info_t x_global, struct cgraph_node *x) |
ea900239 | 300 | { |
ea900239 | 301 | struct cgraph_edge *e; |
b8698a0f | 302 | for (e = x->callees; e; e = e->next_callee) |
ea900239 DB |
303 | { |
304 | struct cgraph_node *y = e->callee; | |
46a4da10 | 305 | enum availability avail; |
ea900239 | 306 | |
46a4da10 | 307 | avail = cgraph_function_body_availability (e->callee); |
c59f5d1b | 308 | /* Only look into nodes we can propagate something. */ |
46a4da10 JH |
309 | if (avail > AVAIL_OVERWRITABLE |
310 | || (avail == AVAIL_OVERWRITABLE | |
311 | && (flags_from_decl_or_type (e->callee->decl) & ECF_LEAF))) | |
ea900239 | 312 | { |
22a8d1e6 | 313 | int flags = flags_from_decl_or_type (e->callee->decl); |
e2c9111c | 314 | if (get_reference_vars_info (y)) |
ea900239 | 315 | { |
b8698a0f | 316 | ipa_reference_vars_info_t y_info |
e2c9111c | 317 | = get_reference_vars_info (y); |
46c30019 | 318 | ipa_reference_global_vars_info_t y_global = &y_info->global; |
e2c9111c JH |
319 | |
320 | /* Calls in current cycle do not have global computed yet. */ | |
46c30019 | 321 | if (!y_global->statics_read) |
e2c9111c | 322 | continue; |
b8698a0f | 323 | |
22a8d1e6 JH |
324 | /* If function is declared const, it reads no memory even if it |
325 | seems so to local analysis. */ | |
326 | if (flags & ECF_CONST) | |
327 | continue; | |
328 | ||
ea900239 DB |
329 | if (x_global->statics_read |
330 | != all_module_statics) | |
331 | { | |
b8698a0f | 332 | if (y_global->statics_read |
ea900239 DB |
333 | == all_module_statics) |
334 | { | |
335 | BITMAP_FREE (x_global->statics_read); | |
b8698a0f | 336 | x_global->statics_read |
ea900239 DB |
337 | = all_module_statics; |
338 | } | |
339 | /* Skip bitmaps that are pointer equal to node's bitmap | |
340 | (no reason to spin within the cycle). */ | |
b8698a0f | 341 | else if (x_global->statics_read |
ea900239 DB |
342 | != y_global->statics_read) |
343 | bitmap_ior_into (x_global->statics_read, | |
344 | y_global->statics_read); | |
345 | } | |
b8698a0f | 346 | |
22a8d1e6 JH |
347 | /* If function is declared pure, it has no stores even if it |
348 | seems so to local analysis; If we can not return from here, | |
349 | we can safely ignore the call. */ | |
350 | if ((flags & ECF_PURE) | |
351 | || cgraph_edge_cannot_lead_to_return (e)) | |
352 | continue; | |
353 | ||
b8698a0f | 354 | if (x_global->statics_written |
ea900239 DB |
355 | != all_module_statics) |
356 | { | |
b8698a0f | 357 | if (y_global->statics_written |
ea900239 DB |
358 | == all_module_statics) |
359 | { | |
360 | BITMAP_FREE (x_global->statics_written); | |
b8698a0f | 361 | x_global->statics_written |
ea900239 DB |
362 | = all_module_statics; |
363 | } | |
364 | /* Skip bitmaps that are pointer equal to node's bitmap | |
365 | (no reason to spin within the cycle). */ | |
b8698a0f | 366 | else if (x_global->statics_written |
ea900239 DB |
367 | != y_global->statics_written) |
368 | bitmap_ior_into (x_global->statics_written, | |
369 | y_global->statics_written); | |
370 | } | |
371 | } | |
b8698a0f | 372 | else |
ebcf9dc8 | 373 | gcc_unreachable (); |
ea900239 DB |
374 | } |
375 | } | |
376 | } | |
377 | ||
ea900239 DB |
378 | /* The init routine for analyzing global static variable usage. See |
379 | comments at top for description. */ | |
b8698a0f L |
380 | static void |
381 | ipa_init (void) | |
ea900239 | 382 | { |
d7f09764 DN |
383 | static bool init_p = false; |
384 | ||
385 | if (init_p) | |
386 | return; | |
387 | ||
388 | init_p = true; | |
389 | ||
46c30019 JH |
390 | if (dump_file) |
391 | reference_vars_to_consider = splay_tree_new (splay_tree_compare_ints, 0, 0); | |
ea900239 | 392 | |
ebcf9dc8 | 393 | bitmap_obstack_initialize (&local_info_obstack); |
46c30019 | 394 | bitmap_obstack_initialize (&optimization_summary_obstack); |
22a8d1e6 | 395 | all_module_statics = BITMAP_ALLOC (&optimization_summary_obstack); |
7dbca013 | 396 | |
d7f09764 DN |
397 | node_removal_hook_holder = |
398 | cgraph_add_node_removal_hook (&remove_node_data, NULL); | |
399 | node_duplication_hook_holder = | |
400 | cgraph_add_node_duplication_hook (&duplicate_node_data, NULL); | |
ea900239 DB |
401 | } |
402 | ||
d7f09764 | 403 | |
812dbce5 | 404 | /* Set up the persistent info for FN. */ |
ea900239 | 405 | |
812dbce5 JH |
406 | static ipa_reference_local_vars_info_t |
407 | init_function_info (struct cgraph_node *fn) | |
ea900239 | 408 | { |
b8698a0f | 409 | ipa_reference_vars_info_t info |
c5274326 | 410 | = XCNEW (struct ipa_reference_vars_info_d); |
ea900239 DB |
411 | |
412 | /* Add the info to the tree's annotation. */ | |
e2c9111c | 413 | set_reference_vars_info (fn, info); |
ea900239 | 414 | |
46c30019 JH |
415 | info->local.statics_read = BITMAP_ALLOC (&local_info_obstack); |
416 | info->local.statics_written = BITMAP_ALLOC (&local_info_obstack); | |
ea900239 | 417 | |
46c30019 | 418 | return &info->local; |
812dbce5 JH |
419 | } |
420 | ||
d7f09764 | 421 | |
812dbce5 JH |
422 | /* This is the main routine for finding the reference patterns for |
423 | global variables within a function FN. */ | |
d7f09764 | 424 | |
812dbce5 JH |
425 | static void |
426 | analyze_function (struct cgraph_node *fn) | |
427 | { | |
8b583a06 | 428 | ipa_reference_local_vars_info_t local; |
5f902d76 JH |
429 | struct ipa_ref *ref; |
430 | int i; | |
431 | tree var; | |
812dbce5 | 432 | |
5f902d76 | 433 | local = init_function_info (fn); |
5f902d76 | 434 | for (i = 0; ipa_ref_list_reference_iterate (&fn->ref_list, i, ref); i++) |
812dbce5 | 435 | { |
5f902d76 JH |
436 | if (ref->refered_type != IPA_REF_VARPOOL) |
437 | continue; | |
438 | var = ipa_ref_varpool_node (ref)->decl; | |
439 | if (ipa_ref_varpool_node (ref)->externally_visible | |
440 | || !ipa_ref_varpool_node (ref)->analyzed | |
441 | || !is_proper_for_analysis (var)) | |
442 | continue; | |
443 | switch (ref->use) | |
812dbce5 | 444 | { |
5f902d76 JH |
445 | case IPA_REF_LOAD: |
446 | bitmap_set_bit (local->statics_read, DECL_UID (var)); | |
447 | break; | |
448 | case IPA_REF_STORE: | |
f10ea640 JH |
449 | if (ipa_ref_cannot_lead_to_return (ref)) |
450 | break; | |
5f902d76 | 451 | bitmap_set_bit (local->statics_written, DECL_UID (var)); |
5f902d76 JH |
452 | break; |
453 | case IPA_REF_ADDR: | |
22a8d1e6 | 454 | gcc_unreachable (); |
5f902d76 | 455 | break; |
812dbce5 | 456 | } |
812dbce5 | 457 | } |
ea900239 | 458 | |
22a8d1e6 JH |
459 | if (cgraph_node_cannot_return (fn)) |
460 | bitmap_clear (local->statics_written); | |
ea900239 DB |
461 | } |
462 | ||
e2c9111c JH |
463 | static bitmap |
464 | copy_global_bitmap (bitmap src) | |
465 | { | |
466 | bitmap dst; | |
467 | if (!src) | |
468 | return NULL; | |
22a8d1e6 JH |
469 | if (src == all_module_statics) |
470 | return all_module_statics; | |
46c30019 | 471 | dst = BITMAP_ALLOC (&optimization_summary_obstack); |
e2c9111c JH |
472 | bitmap_copy (dst, src); |
473 | return dst; | |
474 | } | |
475 | ||
5f902d76 | 476 | |
e2c9111c JH |
477 | /* Called when new clone is inserted to callgraph late. */ |
478 | ||
479 | static void | |
480 | duplicate_node_data (struct cgraph_node *src, struct cgraph_node *dst, | |
481 | void *data ATTRIBUTE_UNUSED) | |
482 | { | |
46c30019 JH |
483 | ipa_reference_optimization_summary_t ginfo; |
484 | ipa_reference_optimization_summary_t dst_ginfo; | |
e2c9111c | 485 | |
46c30019 | 486 | ginfo = get_reference_optimization_summary (src); |
5f902d76 | 487 | if (!ginfo) |
e2c9111c | 488 | return; |
46c30019 JH |
489 | dst_ginfo = XCNEW (struct ipa_reference_optimization_summary_d); |
490 | set_reference_optimization_summary (dst, dst_ginfo); | |
491 | dst_ginfo->statics_not_read = copy_global_bitmap (ginfo->statics_not_read); | |
492 | dst_ginfo->statics_not_written = copy_global_bitmap (ginfo->statics_not_written); | |
e2c9111c JH |
493 | } |
494 | ||
495 | /* Called when node is removed. */ | |
496 | ||
497 | static void | |
498 | remove_node_data (struct cgraph_node *node, void *data ATTRIBUTE_UNUSED) | |
499 | { | |
46c30019 JH |
500 | ipa_reference_optimization_summary_t ginfo; |
501 | ginfo = get_reference_optimization_summary (node); | |
502 | if (ginfo) | |
503 | { | |
504 | if (ginfo->statics_not_read | |
505 | && ginfo->statics_not_read != all_module_statics) | |
506 | BITMAP_FREE (ginfo->statics_not_read); | |
507 | ||
508 | if (ginfo->statics_not_written | |
509 | && ginfo->statics_not_written != all_module_statics) | |
510 | BITMAP_FREE (ginfo->statics_not_written); | |
511 | free (ginfo); | |
512 | set_reference_optimization_summary (node, NULL); | |
513 | } | |
e2c9111c JH |
514 | } |
515 | ||
812dbce5 JH |
516 | /* Analyze each function in the cgraph to see which global or statics |
517 | are read or written. */ | |
518 | ||
b8698a0f | 519 | static void |
812dbce5 | 520 | generate_summary (void) |
ea900239 DB |
521 | { |
522 | struct cgraph_node *node; | |
812dbce5 JH |
523 | unsigned int index; |
524 | bitmap_iterator bi; | |
812dbce5 | 525 | bitmap bm_temp; |
b8698a0f | 526 | |
ea900239 | 527 | ipa_init (); |
ebcf9dc8 | 528 | bm_temp = BITMAP_ALLOC (&local_info_obstack); |
ea900239 | 529 | |
5f902d76 | 530 | /* Process all of the functions next. */ |
ea900239 | 531 | for (node = cgraph_nodes; node; node = node->next) |
5f902d76 | 532 | if (node->analyzed) |
ea900239 DB |
533 | analyze_function (node); |
534 | ||
812dbce5 | 535 | if (dump_file) |
ea900239 DB |
536 | EXECUTE_IF_SET_IN_BITMAP (all_module_statics, 0, index, bi) |
537 | { | |
812dbce5 JH |
538 | fprintf (dump_file, "\nPromotable global:%s", |
539 | get_static_name (index)); | |
ea900239 | 540 | } |
b8698a0f | 541 | |
812dbce5 | 542 | BITMAP_FREE(bm_temp); |
b8698a0f | 543 | |
ea900239 | 544 | if (dump_file) |
812dbce5 | 545 | for (node = cgraph_nodes; node; node = node->next) |
e2c9111c | 546 | if (cgraph_function_body_availability (node) >= AVAIL_OVERWRITABLE) |
ea900239 | 547 | { |
ea900239 | 548 | ipa_reference_local_vars_info_t l; |
812dbce5 | 549 | unsigned int index; |
ea900239 | 550 | bitmap_iterator bi; |
b8698a0f | 551 | |
46c30019 | 552 | l = &get_reference_vars_info (node)->local; |
b8698a0f L |
553 | fprintf (dump_file, |
554 | "\nFunction name:%s/%i:", | |
ea900239 DB |
555 | cgraph_node_name (node), node->uid); |
556 | fprintf (dump_file, "\n locals read: "); | |
8b583a06 JH |
557 | if (l->statics_read) |
558 | EXECUTE_IF_SET_IN_BITMAP (l->statics_read, | |
559 | 0, index, bi) | |
560 | { | |
561 | fprintf (dump_file, "%s ", | |
562 | get_static_name (index)); | |
563 | } | |
ea900239 | 564 | fprintf (dump_file, "\n locals written: "); |
8b583a06 JH |
565 | if (l->statics_written) |
566 | EXECUTE_IF_SET_IN_BITMAP (l->statics_written, | |
567 | 0, index, bi) | |
568 | { | |
569 | fprintf(dump_file, "%s ", | |
570 | get_static_name (index)); | |
571 | } | |
ea900239 | 572 | } |
812dbce5 JH |
573 | } |
574 | \f | |
22a8d1e6 | 575 | /* Set READ_ALL/WRITE_ALL based on decl flags of NODE. */ |
46c30019 | 576 | |
c59f5d1b | 577 | static void |
22a8d1e6 JH |
578 | read_write_all_from_decl (struct cgraph_node *node, bool * read_all, |
579 | bool * write_all) | |
c59f5d1b | 580 | { |
22a8d1e6 | 581 | tree decl = node->decl; |
c59f5d1b | 582 | int flags = flags_from_decl_or_type (decl); |
46a4da10 JH |
583 | if ((flags & ECF_LEAF) |
584 | && cgraph_function_body_availability (node) <= AVAIL_OVERWRITABLE) | |
585 | ; | |
586 | else if (flags & ECF_CONST) | |
c59f5d1b | 587 | ; |
22a8d1e6 JH |
588 | else if ((flags & ECF_PURE) |
589 | || cgraph_node_cannot_return (node)) | |
46a4da10 JH |
590 | { |
591 | *read_all = true; | |
592 | if (dump_file && (dump_flags & TDF_DETAILS)) | |
593 | fprintf (dump_file, " %s/%i -> read all\n", | |
594 | cgraph_node_name (node), node->uid); | |
595 | } | |
c59f5d1b JH |
596 | else |
597 | { | |
598 | /* TODO: To be able to produce sane results, we should also handle | |
46c30019 | 599 | common builtins, in particular throw. */ |
c59f5d1b | 600 | *read_all = true; |
22a8d1e6 | 601 | *write_all = true; |
46a4da10 JH |
602 | if (dump_file && (dump_flags & TDF_DETAILS)) |
603 | fprintf (dump_file, " %s/%i -> read all, write all\n", | |
604 | cgraph_node_name (node), node->uid); | |
c59f5d1b JH |
605 | } |
606 | } | |
607 | ||
812dbce5 | 608 | /* Produce the global information by preforming a transitive closure |
46c30019 | 609 | on the local information that was produced by ipa_analyze_function */ |
812dbce5 JH |
610 | |
611 | static unsigned int | |
612 | propagate (void) | |
613 | { | |
614 | struct cgraph_node *node; | |
615 | struct cgraph_node *w; | |
616 | struct cgraph_node **order = | |
617 | XCNEWVEC (struct cgraph_node *, cgraph_n_nodes); | |
2505c5ed | 618 | int order_pos = ipa_utils_reduced_inorder (order, false, true, NULL); |
812dbce5 JH |
619 | int i; |
620 | ||
b8698a0f | 621 | if (dump_file) |
812dbce5 | 622 | dump_cgraph (dump_file); |
ea900239 | 623 | |
46c30019 | 624 | ipa_discover_readonly_nonaddressable_vars (); |
5f902d76 JH |
625 | generate_summary (); |
626 | ||
ea900239 DB |
627 | /* Propagate the local information thru the call graph to produce |
628 | the global information. All the nodes within a cycle will have | |
629 | the same info so we collapse cycles first. Then we can do the | |
630 | propagation in one pass from the leaves to the roots. */ | |
2505c5ed | 631 | order_pos = ipa_utils_reduced_inorder (order, true, true, NULL); |
ea900239 DB |
632 | if (dump_file) |
633 | ipa_utils_print_order(dump_file, "reduced", order, order_pos); | |
634 | ||
635 | for (i = 0; i < order_pos; i++ ) | |
636 | { | |
637 | ipa_reference_vars_info_t node_info; | |
46c30019 | 638 | ipa_reference_global_vars_info_t node_g; |
ea900239 | 639 | ipa_reference_local_vars_info_t node_l; |
22a8d1e6 | 640 | struct cgraph_edge *e, *ie; |
b8698a0f | 641 | |
ea900239 DB |
642 | bool read_all; |
643 | bool write_all; | |
644 | struct ipa_dfs_info * w_info; | |
645 | ||
646 | node = order[i]; | |
e2c9111c | 647 | node_info = get_reference_vars_info (node); |
22a8d1e6 | 648 | gcc_assert (node_info); |
ea900239 | 649 | |
46a4da10 JH |
650 | |
651 | if (dump_file && (dump_flags & TDF_DETAILS)) | |
652 | fprintf (dump_file, "Starting cycle with %s/%i\n", | |
653 | cgraph_node_name (node), node->uid); | |
654 | ||
46c30019 JH |
655 | node_l = &node_info->local; |
656 | node_g = &node_info->global; | |
ea900239 | 657 | |
22a8d1e6 JH |
658 | read_all = false; |
659 | write_all = false; | |
ea900239 | 660 | |
61502ca8 | 661 | /* When function is overwritable, we can not assume anything. */ |
c59f5d1b | 662 | if (cgraph_function_body_availability (node) <= AVAIL_OVERWRITABLE) |
22a8d1e6 | 663 | read_write_all_from_decl (node, &read_all, &write_all); |
c59f5d1b | 664 | |
b8698a0f | 665 | for (e = node->callees; e; e = e->next_callee) |
c59f5d1b | 666 | if (cgraph_function_body_availability (e->callee) <= AVAIL_OVERWRITABLE) |
22a8d1e6 JH |
667 | read_write_all_from_decl (e->callee, &read_all, &write_all); |
668 | ||
669 | for (ie = node->indirect_calls; ie; ie = ie->next_callee) | |
670 | if (!(ie->indirect_info->ecf_flags & ECF_CONST)) | |
671 | { | |
672 | read_all = true; | |
46a4da10 JH |
673 | if (dump_file && (dump_flags & TDF_DETAILS)) |
674 | fprintf (dump_file, " indirect call -> read all\n"); | |
22a8d1e6 JH |
675 | if (!cgraph_edge_cannot_lead_to_return (ie) |
676 | && !(ie->indirect_info->ecf_flags & ECF_PURE)) | |
46a4da10 JH |
677 | { |
678 | if (dump_file && (dump_flags & TDF_DETAILS)) | |
679 | fprintf (dump_file, " indirect call -> write all\n"); | |
680 | write_all = true; | |
681 | } | |
22a8d1e6 | 682 | } |
c59f5d1b JH |
683 | |
684 | ||
22a8d1e6 | 685 | /* If any node in a cycle is read_all or write_all |
ea900239 | 686 | they all are. */ |
c5274326 | 687 | w_info = (struct ipa_dfs_info *) node->aux; |
ea900239 | 688 | w = w_info->next_cycle; |
22a8d1e6 | 689 | while (w && (!read_all || !write_all)) |
ea900239 | 690 | { |
46a4da10 JH |
691 | if (dump_file && (dump_flags & TDF_DETAILS)) |
692 | fprintf (dump_file, " Visiting %s/%i\n", | |
693 | cgraph_node_name (w), w->uid); | |
61502ca8 | 694 | /* When function is overwritable, we can not assume anything. */ |
c59f5d1b | 695 | if (cgraph_function_body_availability (w) <= AVAIL_OVERWRITABLE) |
22a8d1e6 | 696 | read_write_all_from_decl (w, &read_all, &write_all); |
c59f5d1b | 697 | |
b8698a0f | 698 | for (e = w->callees; e; e = e->next_callee) |
c59f5d1b | 699 | if (cgraph_function_body_availability (e->callee) <= AVAIL_OVERWRITABLE) |
22a8d1e6 | 700 | read_write_all_from_decl (e->callee, &read_all, &write_all); |
c59f5d1b | 701 | |
22a8d1e6 JH |
702 | for (ie = w->indirect_calls; ie; ie = ie->next_callee) |
703 | if (!(ie->indirect_info->ecf_flags & ECF_CONST)) | |
704 | { | |
705 | read_all = true; | |
46a4da10 JH |
706 | if (dump_file && (dump_flags & TDF_DETAILS)) |
707 | fprintf (dump_file, " indirect call -> read all\n"); | |
22a8d1e6 JH |
708 | if (!cgraph_edge_cannot_lead_to_return (ie) |
709 | && !(ie->indirect_info->ecf_flags & ECF_PURE)) | |
46a4da10 JH |
710 | { |
711 | write_all = true; | |
712 | if (dump_file && (dump_flags & TDF_DETAILS)) | |
713 | fprintf (dump_file, " indirect call -> write all\n"); | |
714 | } | |
22a8d1e6 | 715 | } |
ea900239 | 716 | |
c5274326 | 717 | w_info = (struct ipa_dfs_info *) w->aux; |
ea900239 DB |
718 | w = w_info->next_cycle; |
719 | } | |
720 | ||
c59f5d1b | 721 | |
ea900239 | 722 | /* Initialized the bitmaps for the reduced nodes */ |
b8698a0f | 723 | if (read_all) |
ea900239 | 724 | node_g->statics_read = all_module_statics; |
b8698a0f | 725 | else |
ea900239 | 726 | { |
46c30019 | 727 | node_g->statics_read = BITMAP_ALLOC (&local_info_obstack); |
b8698a0f | 728 | bitmap_copy (node_g->statics_read, |
ea900239 DB |
729 | node_l->statics_read); |
730 | } | |
b8698a0f | 731 | if (write_all) |
ea900239 DB |
732 | node_g->statics_written = all_module_statics; |
733 | else | |
734 | { | |
46c30019 | 735 | node_g->statics_written = BITMAP_ALLOC (&local_info_obstack); |
b8698a0f | 736 | bitmap_copy (node_g->statics_written, |
ea900239 DB |
737 | node_l->statics_written); |
738 | } | |
739 | ||
e2c9111c | 740 | propagate_bits (node_g, node); |
c5274326 | 741 | w_info = (struct ipa_dfs_info *) node->aux; |
ea900239 | 742 | w = w_info->next_cycle; |
22a8d1e6 | 743 | while (w && (!read_all || !write_all)) |
ea900239 | 744 | { |
b8698a0f | 745 | ipa_reference_vars_info_t w_ri = |
e2c9111c | 746 | get_reference_vars_info (w); |
46c30019 | 747 | ipa_reference_local_vars_info_t w_l = &w_ri->local; |
22a8d1e6 | 748 | int flags = flags_from_decl_or_type (w->decl); |
b8698a0f | 749 | |
ea900239 DB |
750 | /* These global bitmaps are initialized from the local info |
751 | of all of the nodes in the region. However there is no | |
752 | need to do any work if the bitmaps were set to | |
753 | all_module_statics. */ | |
22a8d1e6 | 754 | if (!read_all && !(flags & ECF_CONST)) |
ea900239 DB |
755 | bitmap_ior_into (node_g->statics_read, |
756 | w_l->statics_read); | |
22a8d1e6 JH |
757 | if (!write_all |
758 | && !(flags & ECF_PURE) | |
759 | && !cgraph_node_cannot_return (w)) | |
ea900239 DB |
760 | bitmap_ior_into (node_g->statics_written, |
761 | w_l->statics_written); | |
e2c9111c | 762 | propagate_bits (node_g, w); |
c5274326 | 763 | w_info = (struct ipa_dfs_info *) w->aux; |
ea900239 DB |
764 | w = w_info->next_cycle; |
765 | } | |
766 | ||
e2c9111c | 767 | /* All nodes within a cycle have the same global info bitmaps. */ |
46c30019 | 768 | node_info->global = *node_g; |
c5274326 | 769 | w_info = (struct ipa_dfs_info *) node->aux; |
ea900239 DB |
770 | w = w_info->next_cycle; |
771 | while (w) | |
772 | { | |
b8698a0f | 773 | ipa_reference_vars_info_t w_ri = |
e2c9111c JH |
774 | get_reference_vars_info (w); |
775 | ||
46c30019 | 776 | w_ri->global = *node_g; |
e2c9111c | 777 | |
c5274326 | 778 | w_info = (struct ipa_dfs_info *) w->aux; |
ea900239 DB |
779 | w = w_info->next_cycle; |
780 | } | |
781 | } | |
782 | ||
783 | if (dump_file) | |
784 | { | |
785 | for (i = 0; i < order_pos; i++ ) | |
786 | { | |
787 | ipa_reference_vars_info_t node_info; | |
788 | ipa_reference_global_vars_info_t node_g; | |
789 | ipa_reference_local_vars_info_t node_l; | |
790 | unsigned int index; | |
791 | bitmap_iterator bi; | |
792 | struct ipa_dfs_info * w_info; | |
793 | ||
794 | node = order[i]; | |
e2c9111c | 795 | node_info = get_reference_vars_info (node); |
46c30019 JH |
796 | node_g = &node_info->global; |
797 | node_l = &node_info->local; | |
b8698a0f L |
798 | fprintf (dump_file, |
799 | "\nFunction name:%s/%i:", | |
ea900239 DB |
800 | cgraph_node_name (node), node->uid); |
801 | fprintf (dump_file, "\n locals read: "); | |
8b583a06 JH |
802 | if (node_l->statics_read) |
803 | EXECUTE_IF_SET_IN_BITMAP (node_l->statics_read, | |
804 | 0, index, bi) | |
805 | { | |
806 | fprintf (dump_file, "%s ", | |
807 | get_static_name (index)); | |
808 | } | |
ea900239 | 809 | fprintf (dump_file, "\n locals written: "); |
8b583a06 JH |
810 | if (node_l->statics_written) |
811 | EXECUTE_IF_SET_IN_BITMAP (node_l->statics_written, | |
812 | 0, index, bi) | |
813 | { | |
814 | fprintf(dump_file, "%s ", | |
815 | get_static_name (index)); | |
816 | } | |
ea900239 | 817 | |
c5274326 | 818 | w_info = (struct ipa_dfs_info *) node->aux; |
ea900239 | 819 | w = w_info->next_cycle; |
b8698a0f | 820 | while (w) |
ea900239 | 821 | { |
b8698a0f | 822 | ipa_reference_vars_info_t w_ri = |
e2c9111c | 823 | get_reference_vars_info (w); |
46c30019 | 824 | ipa_reference_local_vars_info_t w_l = &w_ri->local; |
ea900239 DB |
825 | fprintf (dump_file, "\n next cycle: %s/%i ", |
826 | cgraph_node_name (w), w->uid); | |
40513dd3 JJ |
827 | fprintf (dump_file, "\n locals read: "); |
828 | if (w_l->statics_read) | |
829 | EXECUTE_IF_SET_IN_BITMAP (w_l->statics_read, | |
830 | 0, index, bi) | |
831 | { | |
832 | fprintf (dump_file, "%s ", | |
833 | get_static_name (index)); | |
834 | } | |
ea900239 DB |
835 | |
836 | fprintf (dump_file, "\n locals written: "); | |
40513dd3 JJ |
837 | if (w_l->statics_written) |
838 | EXECUTE_IF_SET_IN_BITMAP (w_l->statics_written, | |
839 | 0, index, bi) | |
840 | { | |
841 | fprintf (dump_file, "%s ", | |
842 | get_static_name (index)); | |
843 | } | |
ea900239 | 844 | |
c5274326 | 845 | w_info = (struct ipa_dfs_info *) w->aux; |
ea900239 DB |
846 | w = w_info->next_cycle; |
847 | } | |
848 | fprintf (dump_file, "\n globals read: "); | |
8b583a06 JH |
849 | if (node_g->statics_read == all_module_statics) |
850 | fprintf (dump_file, "ALL"); | |
851 | else | |
852 | EXECUTE_IF_SET_IN_BITMAP (node_g->statics_read, | |
853 | 0, index, bi) | |
854 | { | |
855 | fprintf (dump_file, "%s ", | |
856 | get_static_name (index)); | |
857 | } | |
ea900239 | 858 | fprintf (dump_file, "\n globals written: "); |
8b583a06 JH |
859 | if (node_g->statics_written == all_module_statics) |
860 | fprintf (dump_file, "ALL"); | |
861 | else | |
862 | EXECUTE_IF_SET_IN_BITMAP (node_g->statics_written, | |
863 | 0, index, bi) | |
864 | { | |
865 | fprintf (dump_file, "%s ", | |
866 | get_static_name (index)); | |
867 | } | |
ea900239 DB |
868 | } |
869 | } | |
870 | ||
871 | /* Cleanup. */ | |
58efc3ac | 872 | for (node = cgraph_nodes; node; node = node->next) |
ea900239 DB |
873 | { |
874 | ipa_reference_vars_info_t node_info; | |
875 | ipa_reference_global_vars_info_t node_g; | |
46c30019 JH |
876 | ipa_reference_optimization_summary_t opt; |
877 | ||
58efc3ac JH |
878 | if (!node->analyzed) |
879 | continue; | |
880 | ||
e2c9111c | 881 | node_info = get_reference_vars_info (node); |
46a4da10 JH |
882 | if (cgraph_function_body_availability (node) > AVAIL_OVERWRITABLE |
883 | || (flags_from_decl_or_type (node->decl) & ECF_LEAF)) | |
46c30019 JH |
884 | { |
885 | node_g = &node_info->global; | |
ea900239 | 886 | |
46c30019 JH |
887 | opt = XCNEW (struct ipa_reference_optimization_summary_d); |
888 | set_reference_optimization_summary (node, opt); | |
ea900239 | 889 | |
46c30019 | 890 | /* Create the complimentary sets. */ |
22a8d1e6 JH |
891 | |
892 | if (bitmap_empty_p (node_g->statics_read)) | |
893 | opt->statics_not_read = all_module_statics; | |
894 | else | |
895 | { | |
896 | opt->statics_not_read | |
897 | = BITMAP_ALLOC (&optimization_summary_obstack); | |
898 | if (node_g->statics_read != all_module_statics) | |
899 | bitmap_and_compl (opt->statics_not_read, | |
900 | all_module_statics, | |
901 | node_g->statics_read); | |
902 | } | |
903 | ||
904 | if (bitmap_empty_p (node_g->statics_written)) | |
905 | opt->statics_not_written = all_module_statics; | |
906 | else | |
907 | { | |
908 | opt->statics_not_written | |
909 | = BITMAP_ALLOC (&optimization_summary_obstack); | |
910 | if (node_g->statics_written != all_module_statics) | |
911 | bitmap_and_compl (opt->statics_not_written, | |
912 | all_module_statics, | |
913 | node_g->statics_written); | |
914 | } | |
46c30019 | 915 | } |
04695783 | 916 | free (node_info); |
ea900239 DB |
917 | if (node->aux) |
918 | { | |
919 | free (node->aux); | |
920 | node->aux = NULL; | |
921 | } | |
46c30019 JH |
922 | } |
923 | ||
924 | free (order); | |
b8698a0f | 925 | |
ebcf9dc8 | 926 | bitmap_obstack_release (&local_info_obstack); |
46c30019 JH |
927 | VEC_free (ipa_reference_vars_info_t, heap, ipa_reference_vars_vector); |
928 | ipa_reference_vars_vector = NULL; | |
929 | if (dump_file) | |
930 | splay_tree_delete (reference_vars_to_consider); | |
931 | reference_vars_to_consider = NULL; | |
c2924966 | 932 | return 0; |
ea900239 DB |
933 | } |
934 | ||
f3380641 JH |
935 | /* Return true if we need to write summary of NODE. */ |
936 | ||
937 | static bool | |
938 | write_node_summary_p (struct cgraph_node *node, | |
939 | cgraph_node_set set, | |
940 | varpool_node_set vset, | |
941 | bitmap ltrans_statics) | |
942 | { | |
943 | ipa_reference_optimization_summary_t info; | |
944 | ||
945 | /* See if we have (non-empty) info. */ | |
946 | if (!node->analyzed || node->global.inlined_to) | |
947 | return false; | |
948 | info = get_reference_optimization_summary (node); | |
949 | if (!info || (bitmap_empty_p (info->statics_not_read) | |
950 | && bitmap_empty_p (info->statics_not_written))) | |
951 | return false; | |
952 | ||
953 | /* See if we want to encode it. | |
954 | Encode also referenced functions since constant folding might turn it into | |
955 | a direct call. | |
956 | ||
957 | In future we might also want to include summaries of functions references | |
958 | by initializers of constant variables references in current unit. */ | |
959 | if (!reachable_from_this_partition_p (node, set) | |
960 | && !referenced_from_this_partition_p (&node->ref_list, set, vset)) | |
961 | return false; | |
962 | ||
963 | /* See if the info has non-empty intersections with vars we want to encode. */ | |
964 | if (!bitmap_intersect_p (info->statics_not_read, ltrans_statics) | |
965 | && !bitmap_intersect_p (info->statics_not_written, ltrans_statics)) | |
966 | return false; | |
967 | return true; | |
968 | } | |
969 | ||
22a8d1e6 JH |
970 | /* Stream out BITS<RANS_STATICS as list of decls to OB. |
971 | LTRANS_STATICS_BITCOUNT specify number of bits in LTRANS_STATICS | |
972 | or -1. When it is positive, just output -1 when | |
973 | BITS<RANS_STATICS == BITS<RANS_STATICS. */ | |
f3380641 JH |
974 | |
975 | static void | |
976 | stream_out_bitmap (struct lto_simple_output_block *ob, | |
22a8d1e6 JH |
977 | bitmap bits, bitmap ltrans_statics, |
978 | int ltrans_statics_bitcount) | |
f3380641 | 979 | { |
22a8d1e6 | 980 | int count = 0; |
f3380641 JH |
981 | unsigned int index; |
982 | bitmap_iterator bi; | |
22a8d1e6 JH |
983 | if (bits == all_module_statics) |
984 | { | |
985 | lto_output_sleb128_stream (ob->main_stream, -1); | |
986 | return; | |
987 | } | |
f3380641 JH |
988 | EXECUTE_IF_AND_IN_BITMAP (bits, ltrans_statics, 0, index, bi) |
989 | count ++; | |
22a8d1e6 JH |
990 | if (count == ltrans_statics_bitcount) |
991 | { | |
992 | lto_output_sleb128_stream (ob->main_stream, -1); | |
993 | return; | |
994 | } | |
995 | lto_output_sleb128_stream (ob->main_stream, count); | |
f3380641 JH |
996 | if (!count) |
997 | return; | |
998 | EXECUTE_IF_AND_IN_BITMAP (bits, ltrans_statics, 0, index, bi) | |
999 | { | |
1000 | tree decl = (tree)splay_tree_lookup (reference_vars_to_consider, index)->value; | |
1001 | lto_output_var_decl_index(ob->decl_state, ob->main_stream, decl); | |
1002 | } | |
1003 | } | |
1004 | ||
1005 | /* Serialize the ipa info for lto. */ | |
1006 | ||
1007 | static void | |
1008 | ipa_reference_write_optimization_summary (cgraph_node_set set, | |
1009 | varpool_node_set vset) | |
1010 | { | |
1011 | struct cgraph_node *node; | |
f3380641 JH |
1012 | struct lto_simple_output_block *ob |
1013 | = lto_create_simple_output_block (LTO_section_ipa_reference); | |
1014 | unsigned int count = 0; | |
22a8d1e6 | 1015 | int ltrans_statics_bitcount = 0; |
f3380641 | 1016 | lto_cgraph_encoder_t encoder = ob->decl_state->cgraph_node_encoder; |
22a8d1e6 | 1017 | lto_varpool_encoder_t varpool_encoder = ob->decl_state->varpool_node_encoder; |
f3380641 | 1018 | bitmap ltrans_statics = BITMAP_ALLOC (NULL); |
22a8d1e6 | 1019 | int i; |
f3380641 JH |
1020 | |
1021 | reference_vars_to_consider = splay_tree_new (splay_tree_compare_ints, 0, 0); | |
1022 | ||
1023 | /* See what variables we are interested in. */ | |
22a8d1e6 JH |
1024 | for (i = 0; i < lto_varpool_encoder_size (varpool_encoder); i++) |
1025 | { | |
1026 | struct varpool_node *vnode = lto_varpool_encoder_deref (varpool_encoder, i); | |
1027 | if (!vnode->externally_visible | |
1028 | && vnode->analyzed | |
1029 | && bitmap_bit_p (all_module_statics, DECL_UID (vnode->decl)) | |
1030 | && referenced_from_this_partition_p (&vnode->ref_list, set, vset)) | |
1031 | { | |
1032 | tree decl = vnode->decl; | |
1033 | bitmap_set_bit (ltrans_statics, DECL_UID (decl)); | |
1034 | splay_tree_insert (reference_vars_to_consider, | |
1035 | DECL_UID (decl), (splay_tree_value)decl); | |
1036 | ltrans_statics_bitcount ++; | |
1037 | } | |
1038 | } | |
f3380641 | 1039 | |
22a8d1e6 JH |
1040 | |
1041 | if (ltrans_statics_bitcount) | |
1042 | for (i = 0; i < lto_cgraph_encoder_size (encoder); i++) | |
1043 | if (write_node_summary_p (lto_cgraph_encoder_deref (encoder, i), | |
1044 | set, vset, ltrans_statics)) | |
1045 | count++; | |
f3380641 JH |
1046 | |
1047 | lto_output_uleb128_stream (ob->main_stream, count); | |
22a8d1e6 JH |
1048 | if (count) |
1049 | stream_out_bitmap (ob, ltrans_statics, ltrans_statics, | |
1050 | -1); | |
f3380641 JH |
1051 | |
1052 | /* Process all of the functions. */ | |
22a8d1e6 JH |
1053 | if (ltrans_statics_bitcount) |
1054 | for (i = 0; i < lto_cgraph_encoder_size (encoder); i++) | |
f3380641 | 1055 | { |
22a8d1e6 JH |
1056 | node = lto_cgraph_encoder_deref (encoder, i); |
1057 | if (write_node_summary_p (node, set, vset, ltrans_statics)) | |
1058 | { | |
1059 | ipa_reference_optimization_summary_t info; | |
1060 | int node_ref; | |
1061 | ||
1062 | info = get_reference_optimization_summary (node); | |
1063 | node_ref = lto_cgraph_encoder_encode (encoder, node); | |
1064 | lto_output_uleb128_stream (ob->main_stream, node_ref); | |
1065 | ||
1066 | stream_out_bitmap (ob, info->statics_not_read, ltrans_statics, | |
1067 | ltrans_statics_bitcount); | |
1068 | stream_out_bitmap (ob, info->statics_not_written, ltrans_statics, | |
1069 | ltrans_statics_bitcount); | |
1070 | } | |
f3380641 JH |
1071 | } |
1072 | BITMAP_FREE (ltrans_statics); | |
1073 | lto_destroy_simple_output_block (ob); | |
1074 | splay_tree_delete (reference_vars_to_consider); | |
1075 | } | |
1076 | ||
1077 | /* Deserialize the ipa info for lto. */ | |
1078 | ||
1079 | static void | |
1080 | ipa_reference_read_optimization_summary (void) | |
1081 | { | |
1082 | struct lto_file_decl_data ** file_data_vec | |
1083 | = lto_get_file_decl_data (); | |
1084 | struct lto_file_decl_data * file_data; | |
1085 | unsigned int j = 0; | |
1086 | bitmap_obstack_initialize (&optimization_summary_obstack); | |
1087 | ||
1088 | node_removal_hook_holder = | |
1089 | cgraph_add_node_removal_hook (&remove_node_data, NULL); | |
1090 | node_duplication_hook_holder = | |
1091 | cgraph_add_node_duplication_hook (&duplicate_node_data, NULL); | |
22a8d1e6 | 1092 | all_module_statics = BITMAP_ALLOC (&optimization_summary_obstack); |
f3380641 JH |
1093 | |
1094 | while ((file_data = file_data_vec[j++])) | |
1095 | { | |
1096 | const char *data; | |
1097 | size_t len; | |
1098 | struct lto_input_block *ib | |
1099 | = lto_create_simple_input_block (file_data, | |
1100 | LTO_section_ipa_reference, | |
1101 | &data, &len); | |
1102 | if (ib) | |
1103 | { | |
1104 | unsigned int i; | |
1105 | unsigned int f_count = lto_input_uleb128 (ib); | |
22a8d1e6 JH |
1106 | int b_count; |
1107 | if (!f_count) | |
1108 | continue; | |
1109 | b_count = lto_input_sleb128 (ib); | |
1110 | if (dump_file) | |
1111 | fprintf (dump_file, "all module statics:"); | |
1112 | for (i = 0; i < (unsigned int)b_count; i++) | |
1113 | { | |
1114 | unsigned int var_index = lto_input_uleb128 (ib); | |
1115 | tree v_decl = lto_file_decl_data_get_var_decl (file_data, | |
1116 | var_index); | |
1117 | bitmap_set_bit (all_module_statics, DECL_UID (v_decl)); | |
1118 | if (dump_file) | |
1119 | fprintf (dump_file, " %s", | |
1120 | lang_hooks.decl_printable_name (v_decl, 2)); | |
1121 | } | |
f3380641 JH |
1122 | |
1123 | for (i = 0; i < f_count; i++) | |
1124 | { | |
1125 | unsigned int j, index; | |
1126 | struct cgraph_node *node; | |
1127 | ipa_reference_optimization_summary_t info; | |
1128 | int v_count; | |
1129 | lto_cgraph_encoder_t encoder; | |
1130 | ||
1131 | index = lto_input_uleb128 (ib); | |
1132 | encoder = file_data->cgraph_node_encoder; | |
1133 | node = lto_cgraph_encoder_deref (encoder, index); | |
1134 | info = XCNEW (struct ipa_reference_optimization_summary_d); | |
1135 | set_reference_optimization_summary (node, info); | |
1136 | info->statics_not_read = BITMAP_ALLOC (&optimization_summary_obstack); | |
1137 | info->statics_not_written = BITMAP_ALLOC (&optimization_summary_obstack); | |
1138 | if (dump_file) | |
1139 | fprintf (dump_file, | |
1140 | "\nFunction name:%s/%i:\n static not read:", | |
1141 | cgraph_node_name (node), node->uid); | |
1142 | ||
1143 | /* Set the statics not read. */ | |
22a8d1e6 JH |
1144 | v_count = lto_input_sleb128 (ib); |
1145 | if (v_count == -1) | |
f3380641 | 1146 | { |
22a8d1e6 | 1147 | info->statics_not_read = all_module_statics; |
f3380641 | 1148 | if (dump_file) |
22a8d1e6 | 1149 | fprintf (dump_file, " all module statics"); |
f3380641 | 1150 | } |
22a8d1e6 JH |
1151 | else |
1152 | for (j = 0; j < (unsigned int)v_count; j++) | |
1153 | { | |
1154 | unsigned int var_index = lto_input_uleb128 (ib); | |
1155 | tree v_decl = lto_file_decl_data_get_var_decl (file_data, | |
1156 | var_index); | |
1157 | bitmap_set_bit (info->statics_not_read, DECL_UID (v_decl)); | |
1158 | if (dump_file) | |
1159 | fprintf (dump_file, " %s", | |
1160 | lang_hooks.decl_printable_name (v_decl, 2)); | |
1161 | } | |
f3380641 JH |
1162 | |
1163 | if (dump_file) | |
1164 | fprintf (dump_file, | |
1165 | "\n static not written:"); | |
1166 | /* Set the statics not written. */ | |
22a8d1e6 JH |
1167 | v_count = lto_input_sleb128 (ib); |
1168 | if (v_count == -1) | |
f3380641 | 1169 | { |
22a8d1e6 | 1170 | info->statics_not_written = all_module_statics; |
f3380641 | 1171 | if (dump_file) |
22a8d1e6 | 1172 | fprintf (dump_file, " all module statics"); |
f3380641 | 1173 | } |
22a8d1e6 JH |
1174 | else |
1175 | for (j = 0; j < (unsigned int)v_count; j++) | |
1176 | { | |
1177 | unsigned int var_index = lto_input_uleb128 (ib); | |
1178 | tree v_decl = lto_file_decl_data_get_var_decl (file_data, | |
1179 | var_index); | |
1180 | bitmap_set_bit (info->statics_not_written, DECL_UID (v_decl)); | |
1181 | if (dump_file) | |
1182 | fprintf (dump_file, " %s", | |
1183 | lang_hooks.decl_printable_name (v_decl, 2)); | |
1184 | } | |
f3380641 JH |
1185 | if (dump_file) |
1186 | fprintf (dump_file, "\n"); | |
1187 | } | |
1188 | ||
1189 | lto_destroy_simple_input_block (file_data, | |
1190 | LTO_section_ipa_reference, | |
1191 | ib, data, len); | |
1192 | } | |
1193 | else | |
1194 | /* Fatal error here. We do not want to support compiling ltrans units with | |
1195 | different version of compiler or different flags than the WPA unit, so | |
1196 | this should never happen. */ | |
1197 | fatal_error ("ipa reference summary is missing in ltrans unit"); | |
1198 | } | |
1199 | } | |
ea900239 DB |
1200 | |
1201 | static bool | |
1202 | gate_reference (void) | |
1203 | { | |
7e8b322a | 1204 | return (flag_ipa_reference |
ea900239 | 1205 | /* Don't bother doing anything if the program has errors. */ |
1da2ed5f | 1206 | && !seen_error ()); |
ea900239 DB |
1207 | } |
1208 | ||
7e5487a2 | 1209 | struct ipa_opt_pass_d pass_ipa_reference = |
ea900239 | 1210 | { |
8ddbbcae | 1211 | { |
812dbce5 | 1212 | IPA_PASS, |
ea900239 DB |
1213 | "static-var", /* name */ |
1214 | gate_reference, /* gate */ | |
812dbce5 | 1215 | propagate, /* execute */ |
ea900239 DB |
1216 | NULL, /* sub */ |
1217 | NULL, /* next */ | |
1218 | 0, /* static_pass_number */ | |
1219 | TV_IPA_REFERENCE, /* tv_id */ | |
1220 | 0, /* properties_required */ | |
1221 | 0, /* properties_provided */ | |
1222 | 0, /* properties_destroyed */ | |
1223 | 0, /* todo_flags_start */ | |
8ddbbcae | 1224 | 0 /* todo_flags_finish */ |
812dbce5 | 1225 | }, |
5f902d76 JH |
1226 | NULL, /* generate_summary */ |
1227 | NULL, /* write_summary */ | |
1228 | NULL, /* read_summary */ | |
f3380641 JH |
1229 | ipa_reference_write_optimization_summary,/* write_optimization_summary */ |
1230 | ipa_reference_read_optimization_summary,/* read_optimization_summary */ | |
2c5721d9 | 1231 | NULL, /* stmt_fixup */ |
812dbce5 JH |
1232 | 0, /* TODOs */ |
1233 | NULL, /* function_transform */ | |
1234 | NULL /* variable_transform */ | |
ea900239 | 1235 | }; |