]>
Commit | Line | Data |
---|---|---|
7bfefa9d | 1 | /* Write and read the cgraph to the memory mapped representation of a |
2 | .o file. | |
3 | ||
b6a800c7 | 4 | Copyright 2009, 2010, 2011 Free Software Foundation, Inc. |
7bfefa9d | 5 | Contributed by Kenneth Zadeck <zadeck@naturalbridge.com> |
6 | ||
7 | This file is part of GCC. | |
8 | ||
9 | GCC is free software; you can redistribute it and/or modify it under | |
10 | the terms of the GNU General Public License as published by the Free | |
11 | Software Foundation; either version 3, or (at your option) any later | |
12 | version. | |
13 | ||
14 | GCC is distributed in the hope that it will be useful, but WITHOUT ANY | |
15 | WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
16 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
17 | for more details. | |
18 | ||
19 | You should have received a copy of the GNU General Public License | |
20 | along with GCC; see the file COPYING3. If not see | |
21 | <http://www.gnu.org/licenses/>. */ | |
22 | ||
23 | #include "config.h" | |
24 | #include "system.h" | |
25 | #include "coretypes.h" | |
26 | #include "tm.h" | |
7bfefa9d | 27 | #include "tree.h" |
28 | #include "expr.h" | |
29 | #include "flags.h" | |
30 | #include "params.h" | |
31 | #include "input.h" | |
7bfefa9d | 32 | #include "hashtab.h" |
33 | #include "langhooks.h" | |
34 | #include "basic-block.h" | |
35 | #include "tree-flow.h" | |
36 | #include "cgraph.h" | |
37 | #include "function.h" | |
38 | #include "ggc.h" | |
852f689e | 39 | #include "diagnostic-core.h" |
7bfefa9d | 40 | #include "except.h" |
41 | #include "vec.h" | |
42 | #include "timevar.h" | |
7bfefa9d | 43 | #include "pointer-set.h" |
44 | #include "lto-streamer.h" | |
2541503d | 45 | #include "data-streamer.h" |
46 | #include "tree-streamer.h" | |
6c0782b1 | 47 | #include "gcov-io.h" |
7bfefa9d | 48 | |
eab36a5a | 49 | static void output_cgraph_opt_summary (void); |
70225339 | 50 | static void input_cgraph_opt_summary (VEC (symtab_node, heap) * nodes); |
1bf41320 | 51 | |
7857a7b7 | 52 | /* Number of LDPR values known to GCC. */ |
da722561 | 53 | #define LDPR_NUM_KNOWN (LDPR_PREVAILING_DEF_IRONLY_EXP + 1) |
a238367f | 54 | |
f1007c72 | 55 | /* All node orders are ofsetted by ORDER_BASE. */ |
56 | static int order_base; | |
57 | ||
b7e3aeb1 | 58 | /* Cgraph streaming is organized as set of record whose type |
59 | is indicated by a tag. */ | |
70225339 | 60 | enum LTO_symtab_tags |
b7e3aeb1 | 61 | { |
62 | /* Must leave 0 for the stopper. */ | |
63 | ||
64 | /* Cgraph node without body available. */ | |
70225339 | 65 | LTO_symtab_unavail_node = 1, |
b7e3aeb1 | 66 | /* Cgraph node with function body. */ |
70225339 | 67 | LTO_symtab_analyzed_node, |
b7e3aeb1 | 68 | /* Cgraph edges. */ |
70225339 | 69 | LTO_symtab_edge, |
70 | LTO_symtab_indirect_edge, | |
71 | LTO_symtab_variable, | |
72 | LTO_symtab_last_tag | |
b7e3aeb1 | 73 | }; |
74 | ||
70225339 | 75 | /* Create a new symtab encoder. */ |
7bfefa9d | 76 | |
70225339 | 77 | lto_symtab_encoder_t |
78 | lto_symtab_encoder_new (void) | |
7bfefa9d | 79 | { |
70225339 | 80 | lto_symtab_encoder_t encoder = XCNEW (struct lto_symtab_encoder_d); |
7bfefa9d | 81 | encoder->map = pointer_map_create (); |
82 | encoder->nodes = NULL; | |
02b2818c | 83 | encoder->body = pointer_set_create (); |
70225339 | 84 | encoder->initializer = pointer_set_create (); |
eab36a5a | 85 | encoder->in_partition = pointer_set_create (); |
7bfefa9d | 86 | return encoder; |
87 | } | |
88 | ||
89 | ||
90 | /* Delete ENCODER and its components. */ | |
91 | ||
92 | void | |
70225339 | 93 | lto_symtab_encoder_delete (lto_symtab_encoder_t encoder) |
7bfefa9d | 94 | { |
70225339 | 95 | VEC_free (symtab_node, heap, encoder->nodes); |
7bfefa9d | 96 | pointer_map_destroy (encoder->map); |
02b2818c | 97 | pointer_set_destroy (encoder->body); |
70225339 | 98 | pointer_set_destroy (encoder->initializer); |
eab36a5a | 99 | pointer_set_destroy (encoder->in_partition); |
7bfefa9d | 100 | free (encoder); |
101 | } | |
102 | ||
103 | ||
70225339 | 104 | /* Return the existing reference number of NODE in the symtab encoder in |
7bfefa9d | 105 | output block OB. Assign a new reference if this is the first time |
106 | NODE is encoded. */ | |
107 | ||
108 | int | |
70225339 | 109 | lto_symtab_encoder_encode (lto_symtab_encoder_t encoder, |
110 | symtab_node node) | |
7bfefa9d | 111 | { |
112 | int ref; | |
113 | void **slot; | |
48e1416a | 114 | |
7bfefa9d | 115 | slot = pointer_map_contains (encoder->map, node); |
116 | if (!slot) | |
117 | { | |
70225339 | 118 | ref = VEC_length (symtab_node, encoder->nodes); |
7bfefa9d | 119 | slot = pointer_map_insert (encoder->map, node); |
120 | *slot = (void *) (intptr_t) ref; | |
70225339 | 121 | VEC_safe_push (symtab_node, heap, encoder->nodes, node); |
7bfefa9d | 122 | } |
123 | else | |
124 | ref = (int) (intptr_t) *slot; | |
125 | ||
126 | return ref; | |
127 | } | |
128 | ||
129 | ||
130 | /* Look up NODE in encoder. Return NODE's reference if it has been encoded | |
131 | or LCC_NOT_FOUND if it is not there. */ | |
132 | ||
133 | int | |
70225339 | 134 | lto_symtab_encoder_lookup (lto_symtab_encoder_t encoder, |
135 | symtab_node node) | |
7bfefa9d | 136 | { |
137 | void **slot = pointer_map_contains (encoder->map, node); | |
138 | return (slot ? (int) (intptr_t) *slot : LCC_NOT_FOUND); | |
139 | } | |
140 | ||
141 | ||
02b2818c | 142 | /* Return TRUE if we should encode initializer of NODE (if any). */ |
7bfefa9d | 143 | |
02b2818c | 144 | bool |
70225339 | 145 | lto_symtab_encoder_encode_body_p (lto_symtab_encoder_t encoder, |
02b2818c | 146 | struct cgraph_node *node) |
147 | { | |
148 | return pointer_set_contains (encoder->body, node); | |
149 | } | |
150 | ||
151 | /* Return TRUE if we should encode body of NODE (if any). */ | |
152 | ||
153 | static void | |
70225339 | 154 | lto_set_symtab_encoder_encode_body (lto_symtab_encoder_t encoder, |
02b2818c | 155 | struct cgraph_node *node) |
7bfefa9d | 156 | { |
02b2818c | 157 | pointer_set_insert (encoder->body, node); |
7bfefa9d | 158 | } |
159 | ||
a238367f | 160 | /* Return TRUE if we should encode initializer of NODE (if any). */ |
161 | ||
162 | bool | |
70225339 | 163 | lto_symtab_encoder_encode_initializer_p (lto_symtab_encoder_t encoder, |
164 | struct varpool_node *node) | |
a238367f | 165 | { |
166 | return pointer_set_contains (encoder->initializer, node); | |
167 | } | |
168 | ||
169 | /* Return TRUE if we should encode initializer of NODE (if any). */ | |
170 | ||
171 | static void | |
70225339 | 172 | lto_set_symtab_encoder_encode_initializer (lto_symtab_encoder_t encoder, |
173 | struct varpool_node *node) | |
a238367f | 174 | { |
175 | pointer_set_insert (encoder->initializer, node); | |
176 | } | |
7bfefa9d | 177 | |
eab36a5a | 178 | /* Return TRUE if we should encode initializer of NODE (if any). */ |
179 | ||
180 | bool | |
181 | lto_symtab_encoder_in_partition_p (lto_symtab_encoder_t encoder, | |
182 | symtab_node node) | |
183 | { | |
184 | return pointer_set_contains (encoder->in_partition, node); | |
185 | } | |
186 | ||
187 | /* Return TRUE if we should encode body of NODE (if any). */ | |
188 | ||
189 | void | |
190 | lto_set_symtab_encoder_in_partition (lto_symtab_encoder_t encoder, | |
191 | symtab_node node) | |
192 | { | |
193 | lto_symtab_encoder_encode (encoder, (symtab_node)node); | |
194 | pointer_set_insert (encoder->in_partition, node); | |
195 | } | |
196 | ||
7bfefa9d | 197 | /* Output the cgraph EDGE to OB using ENCODER. */ |
198 | ||
199 | static void | |
200 | lto_output_edge (struct lto_simple_output_block *ob, struct cgraph_edge *edge, | |
70225339 | 201 | lto_symtab_encoder_t encoder) |
7bfefa9d | 202 | { |
203 | unsigned int uid; | |
204 | intptr_t ref; | |
30baba90 | 205 | struct bitpack_d bp; |
7bfefa9d | 206 | |
799c8711 | 207 | if (edge->indirect_unknown_callee) |
70225339 | 208 | streamer_write_enum (ob->main_stream, LTO_symtab_tags, LTO_symtab_last_tag, |
209 | LTO_symtab_indirect_edge); | |
799c8711 | 210 | else |
70225339 | 211 | streamer_write_enum (ob->main_stream, LTO_symtab_tags, LTO_symtab_last_tag, |
212 | LTO_symtab_edge); | |
7bfefa9d | 213 | |
70225339 | 214 | ref = lto_symtab_encoder_lookup (encoder, (symtab_node)edge->caller); |
48e1416a | 215 | gcc_assert (ref != LCC_NOT_FOUND); |
7f385784 | 216 | streamer_write_hwi_stream (ob->main_stream, ref); |
7bfefa9d | 217 | |
799c8711 | 218 | if (!edge->indirect_unknown_callee) |
219 | { | |
70225339 | 220 | ref = lto_symtab_encoder_lookup (encoder, (symtab_node)edge->callee); |
799c8711 | 221 | gcc_assert (ref != LCC_NOT_FOUND); |
7f385784 | 222 | streamer_write_hwi_stream (ob->main_stream, ref); |
799c8711 | 223 | } |
7bfefa9d | 224 | |
7f385784 | 225 | streamer_write_hwi_stream (ob->main_stream, edge->count); |
7bfefa9d | 226 | |
30baba90 | 227 | bp = bitpack_create (ob->main_stream); |
7d0d0ce1 | 228 | uid = (!gimple_has_body_p (edge->caller->symbol.decl) |
c5cc4842 | 229 | ? edge->lto_stmt_uid : gimple_uid (edge->call_stmt)); |
7857a7b7 | 230 | bp_pack_enum (&bp, cgraph_inline_failed_enum, |
231 | CIF_N_REASONS, edge->inline_failed); | |
232 | bp_pack_var_len_unsigned (&bp, uid); | |
233 | bp_pack_var_len_unsigned (&bp, edge->frequency); | |
30baba90 | 234 | bp_pack_value (&bp, edge->indirect_inlining_edge, 1); |
235 | bp_pack_value (&bp, edge->call_stmt_cannot_inline_p, 1); | |
236 | bp_pack_value (&bp, edge->can_throw_external, 1); | |
f8b7e3ec | 237 | if (edge->indirect_unknown_callee) |
238 | { | |
239 | int flags = edge->indirect_info->ecf_flags; | |
30baba90 | 240 | bp_pack_value (&bp, (flags & ECF_CONST) != 0, 1); |
241 | bp_pack_value (&bp, (flags & ECF_PURE) != 0, 1); | |
242 | bp_pack_value (&bp, (flags & ECF_NORETURN) != 0, 1); | |
243 | bp_pack_value (&bp, (flags & ECF_MALLOC) != 0, 1); | |
244 | bp_pack_value (&bp, (flags & ECF_NOTHROW) != 0, 1); | |
245 | bp_pack_value (&bp, (flags & ECF_RETURNS_TWICE) != 0, 1); | |
f8b7e3ec | 246 | /* Flags that should not appear on indirect calls. */ |
247 | gcc_assert (!(flags & (ECF_LOOPING_CONST_OR_PURE | |
248 | | ECF_MAY_BE_ALLOCA | |
249 | | ECF_SIBCALL | |
c470c5a9 | 250 | | ECF_LEAF |
f8b7e3ec | 251 | | ECF_NOVOPS))); |
252 | } | |
7f385784 | 253 | streamer_write_bitpack (&bp); |
7bfefa9d | 254 | } |
255 | ||
8d810329 | 256 | /* Return if LIST contain references from other partitions. */ |
d97be713 | 257 | |
8d810329 | 258 | bool |
eab36a5a | 259 | referenced_from_other_partition_p (struct ipa_ref_list *list, lto_symtab_encoder_t encoder) |
8d810329 | 260 | { |
261 | int i; | |
262 | struct ipa_ref *ref; | |
04ec15fa | 263 | for (i = 0; ipa_ref_list_referring_iterate (list, i, ref); i++) |
8d810329 | 264 | { |
eab36a5a | 265 | if (ref->referring->symbol.in_other_partition |
266 | || !lto_symtab_encoder_in_partition_p (encoder, ref->referring)) | |
267 | return true; | |
8d810329 | 268 | } |
269 | return false; | |
270 | } | |
271 | ||
08843223 | 272 | /* Return true when node is reachable from other partition. */ |
273 | ||
25429dc2 | 274 | bool |
eab36a5a | 275 | reachable_from_other_partition_p (struct cgraph_node *node, lto_symtab_encoder_t encoder) |
08843223 | 276 | { |
277 | struct cgraph_edge *e; | |
08843223 | 278 | if (!node->analyzed) |
279 | return false; | |
280 | if (node->global.inlined_to) | |
281 | return false; | |
282 | for (e = node->callers; e; e = e->next_caller) | |
7d0d0ce1 | 283 | if (e->caller->symbol.in_other_partition |
eab36a5a | 284 | || !lto_symtab_encoder_in_partition_p (encoder, (symtab_node)e->caller)) |
08843223 | 285 | return true; |
286 | return false; | |
287 | } | |
7bfefa9d | 288 | |
d97be713 | 289 | /* Return if LIST contain references from other partitions. */ |
290 | ||
291 | bool | |
eab36a5a | 292 | referenced_from_this_partition_p (struct ipa_ref_list *list, |
293 | lto_symtab_encoder_t encoder) | |
d97be713 | 294 | { |
295 | int i; | |
296 | struct ipa_ref *ref; | |
04ec15fa | 297 | for (i = 0; ipa_ref_list_referring_iterate (list, i, ref); i++) |
eab36a5a | 298 | if (lto_symtab_encoder_in_partition_p (encoder, ref->referring)) |
299 | return true; | |
d97be713 | 300 | return false; |
301 | } | |
302 | ||
303 | /* Return true when node is reachable from other partition. */ | |
304 | ||
305 | bool | |
eab36a5a | 306 | reachable_from_this_partition_p (struct cgraph_node *node, lto_symtab_encoder_t encoder) |
d97be713 | 307 | { |
308 | struct cgraph_edge *e; | |
d97be713 | 309 | for (e = node->callers; e; e = e->next_caller) |
eab36a5a | 310 | if (lto_symtab_encoder_in_partition_p (encoder, (symtab_node)e->caller)) |
d97be713 | 311 | return true; |
312 | return false; | |
313 | } | |
314 | ||
7bfefa9d | 315 | /* Output the cgraph NODE to OB. ENCODER is used to find the |
316 | reference number of NODE->inlined_to. SET is the set of nodes we | |
317 | are writing to the current file. If NODE is not in SET, then NODE | |
318 | is a boundary of a cgraph_node_set and we pretend NODE just has a | |
319 | decl and no callees. WRITTEN_DECLS is the set of FUNCTION_DECLs | |
320 | that have had their callgraph node written so far. This is used to | |
321 | determine if NODE is a clone of a previously written node. */ | |
322 | ||
323 | static void | |
324 | lto_output_node (struct lto_simple_output_block *ob, struct cgraph_node *node, | |
eab36a5a | 325 | lto_symtab_encoder_t encoder) |
7bfefa9d | 326 | { |
327 | unsigned int tag; | |
30baba90 | 328 | struct bitpack_d bp; |
02b2818c | 329 | bool boundary_p; |
7bfefa9d | 330 | intptr_t ref; |
08843223 | 331 | bool in_other_partition = false; |
02b2818c | 332 | struct cgraph_node *clone_of; |
7bfefa9d | 333 | |
eab36a5a | 334 | boundary_p = !lto_symtab_encoder_in_partition_p (encoder, (symtab_node)node); |
7bfefa9d | 335 | |
b7e3aeb1 | 336 | if (node->analyzed && !boundary_p) |
70225339 | 337 | tag = LTO_symtab_analyzed_node; |
b7e3aeb1 | 338 | else |
70225339 | 339 | tag = LTO_symtab_unavail_node; |
7bfefa9d | 340 | |
70225339 | 341 | streamer_write_enum (ob->main_stream, LTO_symtab_tags, LTO_symtab_last_tag, |
7f385784 | 342 | tag); |
7d0d0ce1 | 343 | streamer_write_hwi_stream (ob->main_stream, node->symbol.order); |
7bfefa9d | 344 | |
7bfefa9d | 345 | /* In WPA mode, we only output part of the call-graph. Also, we |
346 | fake cgraph node attributes. There are two cases that we care. | |
347 | ||
348 | Boundary nodes: There are nodes that are not part of SET but are | |
349 | called from within SET. We artificially make them look like | |
48e1416a | 350 | externally visible nodes with no function body. |
7bfefa9d | 351 | |
352 | Cherry-picked nodes: These are nodes we pulled from other | |
353 | translation units into SET during IPA-inlining. We make them as | |
354 | local static nodes to prevent clashes with other local statics. */ | |
aa419a52 | 355 | if (boundary_p && node->analyzed && !DECL_EXTERNAL (node->symbol.decl)) |
7bfefa9d | 356 | { |
08843223 | 357 | /* Inline clones can not be part of boundary. |
358 | gcc_assert (!node->global.inlined_to); | |
359 | ||
360 | FIXME: At the moment they can be, when partition contains an inline | |
361 | clone that is clone of inline clone from outside partition. We can | |
362 | reshape the clone tree and make other tree to be the root, but it | |
363 | needs a bit extra work and will be promplty done by cgraph_remove_node | |
364 | after reading back. */ | |
365 | in_other_partition = 1; | |
7bfefa9d | 366 | } |
7bfefa9d | 367 | |
02b2818c | 368 | clone_of = node->clone_of; |
369 | while (clone_of | |
70225339 | 370 | && (ref = lto_symtab_encoder_lookup (encoder, (symtab_node)clone_of)) == LCC_NOT_FOUND) |
02b2818c | 371 | if (clone_of->prev_sibling_clone) |
372 | clone_of = clone_of->prev_sibling_clone; | |
373 | else | |
374 | clone_of = clone_of->clone_of; | |
083e227a | 375 | |
70225339 | 376 | if (LTO_symtab_analyzed_node) |
083e227a | 377 | gcc_assert (clone_of || !node->clone_of); |
02b2818c | 378 | if (!clone_of) |
7f385784 | 379 | streamer_write_hwi_stream (ob->main_stream, LCC_NOT_FOUND); |
02b2818c | 380 | else |
7f385784 | 381 | streamer_write_hwi_stream (ob->main_stream, ref); |
7bfefa9d | 382 | |
7bfefa9d | 383 | |
7d0d0ce1 | 384 | lto_output_fn_decl_index (ob->decl_state, ob->main_stream, node->symbol.decl); |
7f385784 | 385 | streamer_write_hwi_stream (ob->main_stream, node->count); |
386 | streamer_write_hwi_stream (ob->main_stream, node->count_materialization_scale); | |
7bfefa9d | 387 | |
70225339 | 388 | if (tag == LTO_symtab_analyzed_node) |
7bfefa9d | 389 | { |
b7e3aeb1 | 390 | if (node->global.inlined_to) |
391 | { | |
70225339 | 392 | ref = lto_symtab_encoder_lookup (encoder, (symtab_node)node->global.inlined_to); |
b7e3aeb1 | 393 | gcc_assert (ref != LCC_NOT_FOUND); |
394 | } | |
395 | else | |
396 | ref = LCC_NOT_FOUND; | |
7bfefa9d | 397 | |
7f385784 | 398 | streamer_write_hwi_stream (ob->main_stream, ref); |
7bfefa9d | 399 | } |
7bfefa9d | 400 | |
7d0d0ce1 | 401 | if (node->symbol.same_comdat_group && !boundary_p) |
61c2c7b1 | 402 | { |
70225339 | 403 | ref = lto_symtab_encoder_lookup (encoder, |
404 | node->symbol.same_comdat_group); | |
61c2c7b1 | 405 | gcc_assert (ref != LCC_NOT_FOUND); |
406 | } | |
407 | else | |
408 | ref = LCC_NOT_FOUND; | |
7f385784 | 409 | streamer_write_hwi_stream (ob->main_stream, ref); |
61c2c7b1 | 410 | |
30baba90 | 411 | bp = bitpack_create (ob->main_stream); |
412 | bp_pack_value (&bp, node->local.local, 1); | |
7d0d0ce1 | 413 | bp_pack_value (&bp, node->symbol.externally_visible, 1); |
30baba90 | 414 | bp_pack_value (&bp, node->local.finalized, 1); |
c8d92fc1 | 415 | bp_pack_value (&bp, node->local.versionable, 1); |
3c97c75d | 416 | bp_pack_value (&bp, node->local.can_change_signature, 1); |
30baba90 | 417 | bp_pack_value (&bp, node->local.redefined_extern_inline, 1); |
8efa224a | 418 | bp_pack_value (&bp, node->symbol.force_output, 1); |
7d0d0ce1 | 419 | bp_pack_value (&bp, node->symbol.address_taken, 1); |
30baba90 | 420 | bp_pack_value (&bp, node->abstract_and_needed, 1); |
70225339 | 421 | bp_pack_value (&bp, tag == LTO_symtab_analyzed_node |
7d0d0ce1 | 422 | && !DECL_EXTERNAL (node->symbol.decl) |
423 | && !DECL_COMDAT (node->symbol.decl) | |
eab36a5a | 424 | && (reachable_from_other_partition_p (node, encoder) |
7d0d0ce1 | 425 | || referenced_from_other_partition_p (&node->symbol.ref_list, |
eab36a5a | 426 | encoder)), 1); |
30baba90 | 427 | bp_pack_value (&bp, node->lowered, 1); |
428 | bp_pack_value (&bp, in_other_partition, 1); | |
badeded8 | 429 | /* Real aliases in a boundary become non-aliases. However we still stream |
430 | alias info on weakrefs. | |
431 | TODO: We lose a bit of information here - when we know that variable is | |
432 | defined in other unit, we may use the info on aliases to resolve | |
433 | symbol1 != symbol2 type tests that we can do only for locally defined objects | |
434 | otherwise. */ | |
7d0d0ce1 | 435 | bp_pack_value (&bp, node->alias && (!boundary_p || DECL_EXTERNAL (node->symbol.decl)), 1); |
30baba90 | 436 | bp_pack_value (&bp, node->frequency, 2); |
0f9fb931 | 437 | bp_pack_value (&bp, node->only_called_at_startup, 1); |
438 | bp_pack_value (&bp, node->only_called_at_exit, 1); | |
ea0e88d1 | 439 | bp_pack_value (&bp, node->tm_clone, 1); |
91bf9d9a | 440 | bp_pack_value (&bp, node->thunk.thunk_p && !boundary_p, 1); |
7857a7b7 | 441 | bp_pack_enum (&bp, ld_plugin_symbol_resolution, |
7d0d0ce1 | 442 | LDPR_NUM_KNOWN, node->symbol.resolution); |
7f385784 | 443 | streamer_write_bitpack (&bp); |
30baba90 | 444 | |
91bf9d9a | 445 | if (node->thunk.thunk_p && !boundary_p) |
446 | { | |
7f385784 | 447 | streamer_write_uhwi_stream |
91bf9d9a | 448 | (ob->main_stream, |
449 | 1 + (node->thunk.this_adjusting != 0) * 2 | |
450 | + (node->thunk.virtual_offset_p != 0) * 4); | |
7f385784 | 451 | streamer_write_uhwi_stream (ob->main_stream, node->thunk.fixed_offset); |
452 | streamer_write_uhwi_stream (ob->main_stream, node->thunk.virtual_value); | |
91bf9d9a | 453 | } |
badeded8 | 454 | if ((node->alias || node->thunk.thunk_p) |
7d0d0ce1 | 455 | && (!boundary_p || (node->alias && DECL_EXTERNAL (node->symbol.decl)))) |
ed772161 | 456 | { |
7f385784 | 457 | streamer_write_hwi_in_range (ob->main_stream, 0, 1, |
458 | node->thunk.alias != NULL); | |
c70f46b0 | 459 | if (node->thunk.alias != NULL) |
460 | lto_output_fn_decl_index (ob->decl_state, ob->main_stream, | |
461 | node->thunk.alias); | |
ed772161 | 462 | } |
7bfefa9d | 463 | } |
464 | ||
0cddb138 | 465 | /* Output the varpool NODE to OB. |
466 | If NODE is not in SET, then NODE is a boundary. */ | |
467 | ||
468 | static void | |
469 | lto_output_varpool_node (struct lto_simple_output_block *ob, struct varpool_node *node, | |
eab36a5a | 470 | lto_symtab_encoder_t encoder) |
0cddb138 | 471 | { |
eab36a5a | 472 | bool boundary_p = (node->analyzed |
473 | && !lto_symtab_encoder_in_partition_p (encoder, (symtab_node)node)); | |
30baba90 | 474 | struct bitpack_d bp; |
933b10c6 | 475 | int ref; |
0cddb138 | 476 | |
70225339 | 477 | streamer_write_enum (ob->main_stream, LTO_symtab_tags, LTO_symtab_last_tag, |
478 | LTO_symtab_variable); | |
7d0d0ce1 | 479 | streamer_write_hwi_stream (ob->main_stream, node->symbol.order); |
480 | lto_output_var_decl_index (ob->decl_state, ob->main_stream, node->symbol.decl); | |
30baba90 | 481 | bp = bitpack_create (ob->main_stream); |
7d0d0ce1 | 482 | bp_pack_value (&bp, node->symbol.externally_visible, 1); |
8efa224a | 483 | bp_pack_value (&bp, node->symbol.force_output, 1); |
30baba90 | 484 | bp_pack_value (&bp, node->finalized, 1); |
485 | bp_pack_value (&bp, node->alias, 1); | |
e0eaac80 | 486 | bp_pack_value (&bp, node->alias_of != NULL, 1); |
0cddb138 | 487 | gcc_assert (node->finalized || !node->analyzed); |
da67d826 | 488 | /* Constant pool initializers can be de-unified into individual ltrans units. |
489 | FIXME: Alternatively at -Os we may want to avoid generating for them the local | |
490 | labels and share them across LTRANS partitions. */ | |
7d0d0ce1 | 491 | if (DECL_IN_CONSTANT_POOL (node->symbol.decl) |
aa419a52 | 492 | && !DECL_EXTERNAL (node->symbol.decl) |
7d0d0ce1 | 493 | && !DECL_COMDAT (node->symbol.decl)) |
da67d826 | 494 | { |
30baba90 | 495 | bp_pack_value (&bp, 0, 1); /* used_from_other_parition. */ |
496 | bp_pack_value (&bp, 0, 1); /* in_other_partition. */ | |
da67d826 | 497 | } |
498 | else | |
499 | { | |
30baba90 | 500 | bp_pack_value (&bp, node->analyzed |
7d0d0ce1 | 501 | && referenced_from_other_partition_p (&node->symbol.ref_list, |
eab36a5a | 502 | encoder), 1); |
aa419a52 | 503 | bp_pack_value (&bp, boundary_p && !DECL_EXTERNAL (node->symbol.decl), 1); |
504 | /* in_other_partition. */ | |
da67d826 | 505 | } |
7f385784 | 506 | streamer_write_bitpack (&bp); |
e0eaac80 | 507 | if (node->alias_of) |
508 | lto_output_var_decl_index (ob->decl_state, ob->main_stream, node->alias_of); | |
7d0d0ce1 | 509 | if (node->symbol.same_comdat_group && !boundary_p) |
933b10c6 | 510 | { |
70225339 | 511 | ref = lto_symtab_encoder_lookup (encoder, |
512 | node->symbol.same_comdat_group); | |
933b10c6 | 513 | gcc_assert (ref != LCC_NOT_FOUND); |
514 | } | |
515 | else | |
516 | ref = LCC_NOT_FOUND; | |
7f385784 | 517 | streamer_write_hwi_stream (ob->main_stream, ref); |
518 | streamer_write_enum (ob->main_stream, ld_plugin_symbol_resolution, | |
7d0d0ce1 | 519 | LDPR_NUM_KNOWN, node->symbol.resolution); |
0cddb138 | 520 | } |
521 | ||
8d810329 | 522 | /* Output the varpool NODE to OB. |
523 | If NODE is not in SET, then NODE is a boundary. */ | |
524 | ||
525 | static void | |
526 | lto_output_ref (struct lto_simple_output_block *ob, struct ipa_ref *ref, | |
70225339 | 527 | lto_symtab_encoder_t encoder) |
8d810329 | 528 | { |
30baba90 | 529 | struct bitpack_d bp; |
70225339 | 530 | int nref; |
531 | ||
30baba90 | 532 | bp = bitpack_create (ob->main_stream); |
30baba90 | 533 | bp_pack_value (&bp, ref->use, 2); |
7f385784 | 534 | streamer_write_bitpack (&bp); |
70225339 | 535 | nref = lto_symtab_encoder_lookup (encoder, ref->referred); |
536 | gcc_assert (nref != LCC_NOT_FOUND); | |
537 | streamer_write_hwi_stream (ob->main_stream, nref); | |
8d810329 | 538 | } |
539 | ||
6c0782b1 | 540 | /* Stream out profile_summary to OB. */ |
541 | ||
542 | static void | |
543 | output_profile_summary (struct lto_simple_output_block *ob) | |
544 | { | |
545 | if (profile_info) | |
546 | { | |
c470c5a9 | 547 | /* We do not output num, sum_all and run_max, they are not used by |
548 | GCC profile feedback and they are difficult to merge from multiple | |
549 | units. */ | |
6c0782b1 | 550 | gcc_assert (profile_info->runs); |
7f385784 | 551 | streamer_write_uhwi_stream (ob->main_stream, profile_info->runs); |
552 | streamer_write_uhwi_stream (ob->main_stream, profile_info->sum_max); | |
6c0782b1 | 553 | } |
554 | else | |
7f385784 | 555 | streamer_write_uhwi_stream (ob->main_stream, 0); |
6c0782b1 | 556 | } |
557 | ||
08843223 | 558 | /* Add NODE into encoder as well as nodes it is cloned from. |
559 | Do it in a way so clones appear first. */ | |
02b2818c | 560 | |
08843223 | 561 | static void |
70225339 | 562 | add_node_to (lto_symtab_encoder_t encoder, struct cgraph_node *node, |
02b2818c | 563 | bool include_body) |
08843223 | 564 | { |
565 | if (node->clone_of) | |
02b2818c | 566 | add_node_to (encoder, node->clone_of, include_body); |
567 | else if (include_body) | |
70225339 | 568 | lto_set_symtab_encoder_encode_body (encoder, node); |
569 | lto_symtab_encoder_encode (encoder, (symtab_node)node); | |
08843223 | 570 | } |
7bfefa9d | 571 | |
8d810329 | 572 | /* Add all references in LIST to encoders. */ |
573 | ||
574 | static void | |
70225339 | 575 | add_references (lto_symtab_encoder_t encoder, |
8d810329 | 576 | struct ipa_ref_list *list) |
577 | { | |
578 | int i; | |
579 | struct ipa_ref *ref; | |
580 | for (i = 0; ipa_ref_list_reference_iterate (list, i, ref); i++) | |
04ec15fa | 581 | if (symtab_function_p (ref->referred)) |
02b2818c | 582 | add_node_to (encoder, ipa_ref_node (ref), false); |
8d810329 | 583 | else |
584 | { | |
585 | struct varpool_node *vnode = ipa_ref_varpool_node (ref); | |
70225339 | 586 | lto_symtab_encoder_encode (encoder, (symtab_node)vnode); |
8d810329 | 587 | } |
588 | } | |
589 | ||
799c8711 | 590 | /* Output all callees or indirect outgoing edges. EDGE must be the first such |
591 | edge. */ | |
592 | ||
593 | static void | |
594 | output_outgoing_cgraph_edges (struct cgraph_edge *edge, | |
595 | struct lto_simple_output_block *ob, | |
70225339 | 596 | lto_symtab_encoder_t encoder) |
799c8711 | 597 | { |
598 | if (!edge) | |
599 | return; | |
600 | ||
601 | /* Output edges in backward direction, so the reconstructed callgraph match | |
602 | and it is easy to associate call sites in the IPA pass summaries. */ | |
603 | while (edge->next_callee) | |
604 | edge = edge->next_callee; | |
605 | for (; edge; edge = edge->prev_callee) | |
606 | lto_output_edge (ob, edge, encoder); | |
607 | } | |
608 | ||
8d810329 | 609 | /* Output the part of the cgraph in SET. */ |
610 | ||
611 | static void | |
eab36a5a | 612 | output_refs (lto_symtab_encoder_t encoder) |
8d810329 | 613 | { |
eab36a5a | 614 | lto_symtab_encoder_iterator lsei; |
8d810329 | 615 | struct lto_simple_output_block *ob; |
616 | int count; | |
617 | struct ipa_ref *ref; | |
618 | int i; | |
619 | ||
620 | ob = lto_create_simple_output_block (LTO_section_refs); | |
621 | ||
eab36a5a | 622 | for (lsei = lsei_start_in_partition (encoder); !lsei_end_p (lsei); |
623 | lsei_next_in_partition (&lsei)) | |
8d810329 | 624 | { |
eab36a5a | 625 | symtab_node node = lsei_node (lsei); |
8d810329 | 626 | |
7d0d0ce1 | 627 | count = ipa_ref_list_nreferences (&node->symbol.ref_list); |
8d810329 | 628 | if (count) |
629 | { | |
7f385784 | 630 | streamer_write_uhwi_stream (ob->main_stream, count); |
631 | streamer_write_uhwi_stream (ob->main_stream, | |
eab36a5a | 632 | lto_symtab_encoder_lookup (encoder, node)); |
7d0d0ce1 | 633 | for (i = 0; ipa_ref_list_reference_iterate (&node->symbol.ref_list, |
634 | i, ref); i++) | |
70225339 | 635 | lto_output_ref (ob, ref, encoder); |
8d810329 | 636 | } |
637 | } | |
638 | ||
7f385784 | 639 | streamer_write_uhwi_stream (ob->main_stream, 0); |
8d810329 | 640 | |
641 | lto_destroy_simple_output_block (ob); | |
642 | } | |
643 | ||
d97be713 | 644 | /* Find out all cgraph and varpool nodes we want to encode in current unit |
645 | and insert them to encoders. */ | |
7bfefa9d | 646 | void |
d97be713 | 647 | compute_ltrans_boundary (struct lto_out_decl_state *state, |
648 | cgraph_node_set set, varpool_node_set vset) | |
7bfefa9d | 649 | { |
650 | struct cgraph_node *node; | |
7bfefa9d | 651 | cgraph_node_set_iterator csi; |
a238367f | 652 | varpool_node_set_iterator vsi; |
7bfefa9d | 653 | struct cgraph_edge *edge; |
d97be713 | 654 | int i; |
70225339 | 655 | lto_symtab_encoder_t encoder; |
6c0782b1 | 656 | |
70225339 | 657 | encoder = state->symtab_node_encoder = lto_symtab_encoder_new (); |
7bfefa9d | 658 | |
659 | /* Go over all the nodes in SET and assign references. */ | |
660 | for (csi = csi_start (set); !csi_end_p (csi); csi_next (&csi)) | |
661 | { | |
662 | node = csi_node (csi); | |
02b2818c | 663 | add_node_to (encoder, node, true); |
eab36a5a | 664 | lto_set_symtab_encoder_in_partition (encoder, (symtab_node)node); |
70225339 | 665 | add_references (encoder, &node->symbol.ref_list); |
7bfefa9d | 666 | } |
a238367f | 667 | for (vsi = vsi_start (vset); !vsi_end_p (vsi); vsi_next (&vsi)) |
668 | { | |
669 | struct varpool_node *vnode = vsi_node (vsi); | |
e0eaac80 | 670 | gcc_assert (!vnode->alias || vnode->alias_of); |
eab36a5a | 671 | lto_set_symtab_encoder_in_partition (encoder, (symtab_node)vnode); |
70225339 | 672 | lto_set_symtab_encoder_encode_initializer (encoder, vnode); |
673 | add_references (encoder, &vnode->symbol.ref_list); | |
a238367f | 674 | } |
a238367f | 675 | /* Pickle in also the initializer of all referenced readonly variables |
676 | to help folding. Constant pool variables are not shared, so we must | |
677 | pickle those too. */ | |
70225339 | 678 | for (i = 0; i < lto_symtab_encoder_size (encoder); i++) |
a238367f | 679 | { |
70225339 | 680 | symtab_node node = lto_symtab_encoder_deref (encoder, i); |
681 | if (symtab_variable_p (node)) | |
a238367f | 682 | { |
70225339 | 683 | struct varpool_node *vnode = varpool (node); |
684 | if (DECL_INITIAL (vnode->symbol.decl) | |
685 | && !lto_symtab_encoder_encode_initializer_p (encoder, | |
686 | vnode) | |
687 | && const_value_known_p (vnode->symbol.decl)) | |
688 | { | |
689 | lto_set_symtab_encoder_encode_initializer (encoder, vnode); | |
690 | add_references (encoder, &vnode->symbol.ref_list); | |
691 | } | |
692 | else if (vnode->alias || vnode->alias_of) | |
693 | add_references (encoder, &vnode->symbol.ref_list); | |
694 | } | |
a238367f | 695 | } |
7bfefa9d | 696 | |
697 | /* Go over all the nodes again to include callees that are not in | |
698 | SET. */ | |
699 | for (csi = csi_start (set); !csi_end_p (csi); csi_next (&csi)) | |
700 | { | |
701 | node = csi_node (csi); | |
702 | for (edge = node->callees; edge; edge = edge->next_callee) | |
703 | { | |
704 | struct cgraph_node *callee = edge->callee; | |
705 | if (!cgraph_node_in_set_p (callee, set)) | |
706 | { | |
707 | /* We should have moved all the inlines. */ | |
708 | gcc_assert (!callee->global.inlined_to); | |
02b2818c | 709 | add_node_to (encoder, callee, false); |
7bfefa9d | 710 | } |
711 | } | |
712 | } | |
d97be713 | 713 | } |
714 | ||
02b699d5 | 715 | /* Output the part of the symtab in SET and VSET. */ |
d97be713 | 716 | |
717 | void | |
eab36a5a | 718 | output_symtab (void) |
d97be713 | 719 | { |
720 | struct cgraph_node *node; | |
721 | struct lto_simple_output_block *ob; | |
eab36a5a | 722 | lto_symtab_encoder_iterator lsei; |
d97be713 | 723 | int i, n_nodes; |
70225339 | 724 | lto_symtab_encoder_t encoder; |
14c5d106 | 725 | static bool asm_nodes_output = false; |
d97be713 | 726 | |
1bf41320 | 727 | if (flag_wpa) |
eab36a5a | 728 | output_cgraph_opt_summary (); |
1bf41320 | 729 | |
02b699d5 | 730 | ob = lto_create_simple_output_block (LTO_section_symtab_nodes); |
d97be713 | 731 | |
732 | output_profile_summary (ob); | |
733 | ||
734 | /* An encoder for cgraph nodes should have been created by | |
735 | ipa_write_summaries_1. */ | |
70225339 | 736 | gcc_assert (ob->decl_state->symtab_node_encoder); |
737 | encoder = ob->decl_state->symtab_node_encoder; | |
d97be713 | 738 | |
08843223 | 739 | /* Write out the nodes. We must first output a node and then its clones, |
740 | otherwise at a time reading back the node there would be nothing to clone | |
741 | from. */ | |
70225339 | 742 | n_nodes = lto_symtab_encoder_size (encoder); |
7bfefa9d | 743 | for (i = 0; i < n_nodes; i++) |
744 | { | |
70225339 | 745 | symtab_node node = lto_symtab_encoder_deref (encoder, i); |
746 | if (symtab_function_p (node)) | |
eab36a5a | 747 | lto_output_node (ob, cgraph (node), encoder); |
70225339 | 748 | else |
eab36a5a | 749 | lto_output_varpool_node (ob, varpool (node), encoder); |
70225339 | 750 | |
7bfefa9d | 751 | } |
752 | ||
7bfefa9d | 753 | /* Go over the nodes in SET again to write edges. */ |
eab36a5a | 754 | for (lsei = lsei_start_function_in_partition (encoder); !lsei_end_p (lsei); |
755 | lsei_next_function_in_partition (&lsei)) | |
7bfefa9d | 756 | { |
eab36a5a | 757 | node = lsei_cgraph_node (lsei); |
799c8711 | 758 | output_outgoing_cgraph_edges (node->callees, ob, encoder); |
759 | output_outgoing_cgraph_edges (node->indirect_calls, ob, encoder); | |
7bfefa9d | 760 | } |
761 | ||
7f385784 | 762 | streamer_write_uhwi_stream (ob->main_stream, 0); |
7bfefa9d | 763 | |
65d1b157 | 764 | lto_destroy_simple_output_block (ob); |
765 | ||
2b7c48a1 | 766 | /* Emit toplevel asms. |
767 | When doing WPA we must output every asm just once. Since we do not partition asm | |
768 | nodes at all, output them to first output. This is kind of hack, but should work | |
769 | well. */ | |
770 | if (!asm_nodes_output) | |
90f477a9 | 771 | { |
2b7c48a1 | 772 | asm_nodes_output = true; |
65d1b157 | 773 | lto_output_toplevel_asms (); |
90f477a9 | 774 | } |
775 | ||
eab36a5a | 776 | output_refs (encoder); |
7bfefa9d | 777 | } |
778 | ||
7bfefa9d | 779 | /* Overwrite the information in NODE based on FILE_DATA, TAG, FLAGS, |
780 | STACK_SIZE, SELF_TIME and SELF_SIZE. This is called either to initialize | |
781 | NODE or to replace the values in it, for instance because the first | |
782 | time we saw it, the function body was not available but now it | |
783 | is. BP is a bitpack with all the bitflags for NODE read from the | |
784 | stream. */ | |
785 | ||
786 | static void | |
787 | input_overwrite_node (struct lto_file_decl_data *file_data, | |
788 | struct cgraph_node *node, | |
70225339 | 789 | enum LTO_symtab_tags tag, |
7857a7b7 | 790 | struct bitpack_d *bp) |
7bfefa9d | 791 | { |
7d0d0ce1 | 792 | node->symbol.aux = (void *) tag; |
793 | node->symbol.lto_file_data = file_data; | |
7bfefa9d | 794 | |
795 | node->local.local = bp_unpack_value (bp, 1); | |
7d0d0ce1 | 796 | node->symbol.externally_visible = bp_unpack_value (bp, 1); |
7bfefa9d | 797 | node->local.finalized = bp_unpack_value (bp, 1); |
c8d92fc1 | 798 | node->local.versionable = bp_unpack_value (bp, 1); |
3c97c75d | 799 | node->local.can_change_signature = bp_unpack_value (bp, 1); |
7bfefa9d | 800 | node->local.redefined_extern_inline = bp_unpack_value (bp, 1); |
8efa224a | 801 | node->symbol.force_output = bp_unpack_value (bp, 1); |
7d0d0ce1 | 802 | node->symbol.address_taken = bp_unpack_value (bp, 1); |
7bfefa9d | 803 | node->abstract_and_needed = bp_unpack_value (bp, 1); |
7d0d0ce1 | 804 | node->symbol.used_from_other_partition = bp_unpack_value (bp, 1); |
7bfefa9d | 805 | node->lowered = bp_unpack_value (bp, 1); |
70225339 | 806 | node->analyzed = tag == LTO_symtab_analyzed_node; |
7d0d0ce1 | 807 | node->symbol.in_other_partition = bp_unpack_value (bp, 1); |
808 | if (node->symbol.in_other_partition | |
cdc58a66 | 809 | /* Avoid updating decl when we are seeing just inline clone. |
810 | When inlining function that has functions already inlined into it, | |
811 | we produce clones of inline clones. | |
812 | ||
813 | WPA partitioning might put each clone into different unit and | |
814 | we might end up streaming inline clone from other partition | |
815 | to support clone we are interested in. */ | |
816 | && (!node->clone_of | |
7d0d0ce1 | 817 | || node->clone_of->symbol.decl != node->symbol.decl)) |
eb0bc81b | 818 | { |
7d0d0ce1 | 819 | DECL_EXTERNAL (node->symbol.decl) = 1; |
820 | TREE_STATIC (node->symbol.decl) = 0; | |
eb0bc81b | 821 | } |
7bfefa9d | 822 | node->alias = bp_unpack_value (bp, 1); |
125b6d78 | 823 | node->frequency = (enum node_frequency)bp_unpack_value (bp, 2); |
0f9fb931 | 824 | node->only_called_at_startup = bp_unpack_value (bp, 1); |
825 | node->only_called_at_exit = bp_unpack_value (bp, 1); | |
ea0e88d1 | 826 | node->tm_clone = bp_unpack_value (bp, 1); |
91bf9d9a | 827 | node->thunk.thunk_p = bp_unpack_value (bp, 1); |
7d0d0ce1 | 828 | node->symbol.resolution = bp_unpack_enum (bp, ld_plugin_symbol_resolution, |
7857a7b7 | 829 | LDPR_NUM_KNOWN); |
7bfefa9d | 830 | } |
831 | ||
48e1416a | 832 | /* Read a node from input_block IB. TAG is the node's tag just read. |
7bfefa9d | 833 | Return the node read or overwriten. */ |
48e1416a | 834 | |
7bfefa9d | 835 | static struct cgraph_node * |
836 | input_node (struct lto_file_decl_data *file_data, | |
837 | struct lto_input_block *ib, | |
70225339 | 838 | enum LTO_symtab_tags tag, |
839 | VEC(symtab_node, heap) *nodes) | |
7bfefa9d | 840 | { |
841 | tree fn_decl; | |
842 | struct cgraph_node *node; | |
30baba90 | 843 | struct bitpack_d bp; |
7bfefa9d | 844 | unsigned decl_index; |
61c2c7b1 | 845 | int ref = LCC_NOT_FOUND, ref2 = LCC_NOT_FOUND; |
02b2818c | 846 | int clone_ref; |
f1007c72 | 847 | int order; |
7bfefa9d | 848 | |
f1007c72 | 849 | order = streamer_read_hwi (ib) + order_base; |
7f385784 | 850 | clone_ref = streamer_read_hwi (ib); |
7bfefa9d | 851 | |
7f385784 | 852 | decl_index = streamer_read_uhwi (ib); |
7bfefa9d | 853 | fn_decl = lto_file_decl_data_get_fn_decl (file_data, decl_index); |
854 | ||
02b2818c | 855 | if (clone_ref != LCC_NOT_FOUND) |
856 | { | |
70225339 | 857 | node = cgraph_clone_node (cgraph (VEC_index (symtab_node, nodes, clone_ref)), fn_decl, |
8bae3ea4 | 858 | 0, CGRAPH_FREQ_BASE, false, NULL, false); |
02b2818c | 859 | } |
7bfefa9d | 860 | else |
5a90471f | 861 | node = cgraph_get_create_node (fn_decl); |
7bfefa9d | 862 | |
7d0d0ce1 | 863 | node->symbol.order = order; |
0704fb2e | 864 | if (order >= symtab_order) |
865 | symtab_order = order + 1; | |
f1007c72 | 866 | |
7f385784 | 867 | node->count = streamer_read_hwi (ib); |
868 | node->count_materialization_scale = streamer_read_hwi (ib); | |
48e1416a | 869 | |
70225339 | 870 | if (tag == LTO_symtab_analyzed_node) |
7f385784 | 871 | ref = streamer_read_hwi (ib); |
7bfefa9d | 872 | |
7f385784 | 873 | ref2 = streamer_read_hwi (ib); |
7bfefa9d | 874 | |
875 | /* Make sure that we have not read this node before. Nodes that | |
876 | have already been read will have their tag stored in the 'aux' | |
877 | field. Since built-in functions can be referenced in multiple | |
878 | functions, they are expected to be read more than once. */ | |
7d0d0ce1 | 879 | if (node->symbol.aux && !DECL_BUILT_IN (node->symbol.decl)) |
7bfefa9d | 880 | internal_error ("bytecode stream: found multiple instances of cgraph " |
881 | "node %d", node->uid); | |
882 | ||
7f385784 | 883 | bp = streamer_read_bitpack (ib); |
7857a7b7 | 884 | input_overwrite_node (file_data, node, tag, &bp); |
7bfefa9d | 885 | |
7bfefa9d | 886 | /* Store a reference for now, and fix up later to be a pointer. */ |
887 | node->global.inlined_to = (cgraph_node_ptr) (intptr_t) ref; | |
888 | ||
61c2c7b1 | 889 | /* Store a reference for now, and fix up later to be a pointer. */ |
7d0d0ce1 | 890 | node->symbol.same_comdat_group = (symtab_node) (intptr_t) ref2; |
61c2c7b1 | 891 | |
91bf9d9a | 892 | if (node->thunk.thunk_p) |
893 | { | |
7f385784 | 894 | int type = streamer_read_uhwi (ib); |
895 | HOST_WIDE_INT fixed_offset = streamer_read_uhwi (ib); | |
896 | HOST_WIDE_INT virtual_value = streamer_read_uhwi (ib); | |
91bf9d9a | 897 | |
91bf9d9a | 898 | node->thunk.fixed_offset = fixed_offset; |
899 | node->thunk.this_adjusting = (type & 2); | |
900 | node->thunk.virtual_value = virtual_value; | |
901 | node->thunk.virtual_offset_p = (type & 4); | |
91bf9d9a | 902 | } |
c70f46b0 | 903 | if (node->thunk.thunk_p || node->alias) |
ed772161 | 904 | { |
7f385784 | 905 | if (streamer_read_hwi_in_range (ib, "alias nonzero flag", 0, 1)) |
c70f46b0 | 906 | { |
7f385784 | 907 | decl_index = streamer_read_uhwi (ib); |
c70f46b0 | 908 | node->thunk.alias = lto_file_decl_data_get_fn_decl (file_data, |
909 | decl_index); | |
910 | } | |
ed772161 | 911 | } |
7bfefa9d | 912 | return node; |
913 | } | |
914 | ||
0cddb138 | 915 | /* Read a node from input_block IB. TAG is the node's tag just read. |
916 | Return the node read or overwriten. */ | |
917 | ||
918 | static struct varpool_node * | |
919 | input_varpool_node (struct lto_file_decl_data *file_data, | |
920 | struct lto_input_block *ib) | |
921 | { | |
922 | int decl_index; | |
923 | tree var_decl; | |
924 | struct varpool_node *node; | |
30baba90 | 925 | struct bitpack_d bp; |
933b10c6 | 926 | int ref = LCC_NOT_FOUND; |
e0eaac80 | 927 | bool non_null_aliasof; |
f1007c72 | 928 | int order; |
0cddb138 | 929 | |
f1007c72 | 930 | order = streamer_read_hwi (ib) + order_base; |
7f385784 | 931 | decl_index = streamer_read_uhwi (ib); |
0cddb138 | 932 | var_decl = lto_file_decl_data_get_var_decl (file_data, decl_index); |
933 | node = varpool_node (var_decl); | |
7d0d0ce1 | 934 | node->symbol.order = order; |
0704fb2e | 935 | if (order >= symtab_order) |
936 | symtab_order = order + 1; | |
7d0d0ce1 | 937 | node->symbol.lto_file_data = file_data; |
0cddb138 | 938 | |
7f385784 | 939 | bp = streamer_read_bitpack (ib); |
7d0d0ce1 | 940 | node->symbol.externally_visible = bp_unpack_value (&bp, 1); |
8efa224a | 941 | node->symbol.force_output = bp_unpack_value (&bp, 1); |
30baba90 | 942 | node->finalized = bp_unpack_value (&bp, 1); |
943 | node->alias = bp_unpack_value (&bp, 1); | |
e0eaac80 | 944 | non_null_aliasof = bp_unpack_value (&bp, 1); |
7d0d0ce1 | 945 | node->symbol.used_from_other_partition = bp_unpack_value (&bp, 1); |
946 | node->symbol.in_other_partition = bp_unpack_value (&bp, 1); | |
ff2a5ada | 947 | node->analyzed = (node->finalized && (!node->alias || !node->symbol.in_other_partition)); |
7d0d0ce1 | 948 | if (node->symbol.in_other_partition) |
eb0bc81b | 949 | { |
7d0d0ce1 | 950 | DECL_EXTERNAL (node->symbol.decl) = 1; |
951 | TREE_STATIC (node->symbol.decl) = 0; | |
eb0bc81b | 952 | } |
e0eaac80 | 953 | if (non_null_aliasof) |
954 | { | |
7f385784 | 955 | decl_index = streamer_read_uhwi (ib); |
e0eaac80 | 956 | node->alias_of = lto_file_decl_data_get_var_decl (file_data, decl_index); |
957 | } | |
7f385784 | 958 | ref = streamer_read_hwi (ib); |
933b10c6 | 959 | /* Store a reference for now, and fix up later to be a pointer. */ |
7d0d0ce1 | 960 | node->symbol.same_comdat_group = (symtab_node) (intptr_t) ref; |
961 | node->symbol.resolution = streamer_read_enum (ib, ld_plugin_symbol_resolution, | |
962 | LDPR_NUM_KNOWN); | |
e0eaac80 | 963 | |
0cddb138 | 964 | return node; |
965 | } | |
966 | ||
8d810329 | 967 | /* Read a node from input_block IB. TAG is the node's tag just read. |
968 | Return the node read or overwriten. */ | |
969 | ||
970 | static void | |
971 | input_ref (struct lto_input_block *ib, | |
04ec15fa | 972 | symtab_node referring_node, |
70225339 | 973 | VEC(symtab_node, heap) *nodes) |
8d810329 | 974 | { |
70225339 | 975 | symtab_node node = NULL; |
30baba90 | 976 | struct bitpack_d bp; |
8d810329 | 977 | enum ipa_ref_use use; |
978 | ||
7f385784 | 979 | bp = streamer_read_bitpack (ib); |
30baba90 | 980 | use = (enum ipa_ref_use) bp_unpack_value (&bp, 2); |
70225339 | 981 | node = VEC_index (symtab_node, nodes, streamer_read_hwi (ib)); |
982 | ipa_record_reference (referring_node, node, use, NULL); | |
8d810329 | 983 | } |
7bfefa9d | 984 | |
799c8711 | 985 | /* Read an edge from IB. NODES points to a vector of previously read nodes for |
986 | decoding caller and callee of the edge to be read. If INDIRECT is true, the | |
987 | edge being read is indirect (in the sense that it has | |
988 | indirect_unknown_callee set). */ | |
7bfefa9d | 989 | |
990 | static void | |
70225339 | 991 | input_edge (struct lto_input_block *ib, VEC(symtab_node, heap) *nodes, |
799c8711 | 992 | bool indirect) |
7bfefa9d | 993 | { |
994 | struct cgraph_node *caller, *callee; | |
995 | struct cgraph_edge *edge; | |
996 | unsigned int stmt_id; | |
997 | gcov_type count; | |
998 | int freq; | |
7bfefa9d | 999 | cgraph_inline_failed_t inline_failed; |
30baba90 | 1000 | struct bitpack_d bp; |
f8b7e3ec | 1001 | int ecf_flags = 0; |
7bfefa9d | 1002 | |
70225339 | 1003 | caller = cgraph (VEC_index (symtab_node, nodes, streamer_read_hwi (ib))); |
7d0d0ce1 | 1004 | if (caller == NULL || caller->symbol.decl == NULL_TREE) |
7bfefa9d | 1005 | internal_error ("bytecode stream: no caller found while reading edge"); |
1006 | ||
799c8711 | 1007 | if (!indirect) |
1008 | { | |
70225339 | 1009 | callee = cgraph (VEC_index (symtab_node, nodes, streamer_read_hwi (ib))); |
7d0d0ce1 | 1010 | if (callee == NULL || callee->symbol.decl == NULL_TREE) |
799c8711 | 1011 | internal_error ("bytecode stream: no callee found while reading edge"); |
1012 | } | |
1013 | else | |
1014 | callee = NULL; | |
7bfefa9d | 1015 | |
7f385784 | 1016 | count = (gcov_type) streamer_read_hwi (ib); |
7bfefa9d | 1017 | |
7f385784 | 1018 | bp = streamer_read_bitpack (ib); |
7857a7b7 | 1019 | inline_failed = bp_unpack_enum (&bp, cgraph_inline_failed_enum, CIF_N_REASONS); |
1020 | stmt_id = bp_unpack_var_len_unsigned (&bp); | |
1021 | freq = (int) bp_unpack_var_len_unsigned (&bp); | |
7bfefa9d | 1022 | |
799c8711 | 1023 | if (indirect) |
0835ad03 | 1024 | edge = cgraph_create_indirect_edge (caller, NULL, 0, count, freq); |
799c8711 | 1025 | else |
0835ad03 | 1026 | edge = cgraph_create_edge (caller, callee, NULL, count, freq); |
799c8711 | 1027 | |
30baba90 | 1028 | edge->indirect_inlining_edge = bp_unpack_value (&bp, 1); |
7bfefa9d | 1029 | edge->lto_stmt_uid = stmt_id; |
1030 | edge->inline_failed = inline_failed; | |
30baba90 | 1031 | edge->call_stmt_cannot_inline_p = bp_unpack_value (&bp, 1); |
1032 | edge->can_throw_external = bp_unpack_value (&bp, 1); | |
f8b7e3ec | 1033 | if (indirect) |
1034 | { | |
30baba90 | 1035 | if (bp_unpack_value (&bp, 1)) |
f8b7e3ec | 1036 | ecf_flags |= ECF_CONST; |
30baba90 | 1037 | if (bp_unpack_value (&bp, 1)) |
f8b7e3ec | 1038 | ecf_flags |= ECF_PURE; |
30baba90 | 1039 | if (bp_unpack_value (&bp, 1)) |
f8b7e3ec | 1040 | ecf_flags |= ECF_NORETURN; |
30baba90 | 1041 | if (bp_unpack_value (&bp, 1)) |
f8b7e3ec | 1042 | ecf_flags |= ECF_MALLOC; |
30baba90 | 1043 | if (bp_unpack_value (&bp, 1)) |
f8b7e3ec | 1044 | ecf_flags |= ECF_NOTHROW; |
30baba90 | 1045 | if (bp_unpack_value (&bp, 1)) |
f8b7e3ec | 1046 | ecf_flags |= ECF_RETURNS_TWICE; |
1047 | edge->indirect_info->ecf_flags = ecf_flags; | |
1048 | } | |
7bfefa9d | 1049 | } |
1050 | ||
1051 | ||
1052 | /* Read a cgraph from IB using the info in FILE_DATA. */ | |
1053 | ||
70225339 | 1054 | static VEC(symtab_node, heap) * |
7bfefa9d | 1055 | input_cgraph_1 (struct lto_file_decl_data *file_data, |
1056 | struct lto_input_block *ib) | |
1057 | { | |
70225339 | 1058 | enum LTO_symtab_tags tag; |
1059 | VEC(symtab_node, heap) *nodes = NULL; | |
1060 | symtab_node node; | |
7bfefa9d | 1061 | unsigned i; |
1062 | ||
70225339 | 1063 | tag = streamer_read_enum (ib, LTO_symtab_tags, LTO_symtab_last_tag); |
0704fb2e | 1064 | order_base = symtab_order; |
7bfefa9d | 1065 | while (tag) |
1066 | { | |
70225339 | 1067 | if (tag == LTO_symtab_edge) |
799c8711 | 1068 | input_edge (ib, nodes, false); |
70225339 | 1069 | else if (tag == LTO_symtab_indirect_edge) |
799c8711 | 1070 | input_edge (ib, nodes, true); |
70225339 | 1071 | else if (tag == LTO_symtab_variable) |
1072 | { | |
1073 | node = (symtab_node)input_varpool_node (file_data, ib); | |
1074 | VEC_safe_push (symtab_node, heap, nodes, node); | |
1075 | lto_symtab_encoder_encode (file_data->symtab_node_encoder, node); | |
1076 | } | |
48e1416a | 1077 | else |
7bfefa9d | 1078 | { |
70225339 | 1079 | node = (symtab_node)input_node (file_data, ib, tag, nodes); |
7d0d0ce1 | 1080 | if (node == NULL || node->symbol.decl == NULL_TREE) |
7bfefa9d | 1081 | internal_error ("bytecode stream: found empty cgraph node"); |
70225339 | 1082 | VEC_safe_push (symtab_node, heap, nodes, node); |
1083 | lto_symtab_encoder_encode (file_data->symtab_node_encoder, node); | |
7bfefa9d | 1084 | } |
1085 | ||
70225339 | 1086 | tag = streamer_read_enum (ib, LTO_symtab_tags, LTO_symtab_last_tag); |
7bfefa9d | 1087 | } |
1088 | ||
f1007c72 | 1089 | lto_input_toplevel_asms (file_data, order_base); |
90f477a9 | 1090 | |
70225339 | 1091 | /* AUX pointers should be all non-zero for function nodes read from the stream. */ |
d47cadab | 1092 | #ifdef ENABLE_CHECKING |
70225339 | 1093 | FOR_EACH_VEC_ELT (symtab_node, nodes, i, node) |
1094 | gcc_assert (node->symbol.aux || !symtab_function_p (node)); | |
d47cadab | 1095 | #endif |
70225339 | 1096 | FOR_EACH_VEC_ELT (symtab_node, nodes, i, node) |
7bfefa9d | 1097 | { |
70225339 | 1098 | int ref; |
1099 | if (symtab_function_p (node)) | |
1100 | { | |
1101 | ref = (int) (intptr_t) cgraph (node)->global.inlined_to; | |
1102 | ||
1103 | /* We share declaration of builtins, so we may read same node twice. */ | |
1104 | if (!node->symbol.aux) | |
1105 | continue; | |
1106 | node->symbol.aux = NULL; | |
1107 | ||
1108 | /* Fixup inlined_to from reference to pointer. */ | |
1109 | if (ref != LCC_NOT_FOUND) | |
1110 | cgraph (node)->global.inlined_to = cgraph (VEC_index (symtab_node, nodes, ref)); | |
1111 | else | |
1112 | cgraph (node)->global.inlined_to = NULL; | |
1113 | } | |
61c2c7b1 | 1114 | |
7d0d0ce1 | 1115 | ref = (int) (intptr_t) node->symbol.same_comdat_group; |
61c2c7b1 | 1116 | |
1117 | /* Fixup same_comdat_group from reference to pointer. */ | |
1118 | if (ref != LCC_NOT_FOUND) | |
70225339 | 1119 | node->symbol.same_comdat_group = VEC_index (symtab_node, nodes, ref); |
61c2c7b1 | 1120 | else |
7d0d0ce1 | 1121 | node->symbol.same_comdat_group = NULL; |
7bfefa9d | 1122 | } |
70225339 | 1123 | FOR_EACH_VEC_ELT (symtab_node, nodes, i, node) |
1124 | node->symbol.aux = symtab_function_p (node) ? (void *)1 : NULL; | |
a238367f | 1125 | return nodes; |
7bfefa9d | 1126 | } |
1127 | ||
8d810329 | 1128 | /* Input ipa_refs. */ |
1129 | ||
1130 | static void | |
1131 | input_refs (struct lto_input_block *ib, | |
70225339 | 1132 | VEC(symtab_node, heap) *nodes) |
8d810329 | 1133 | { |
1134 | int count; | |
1135 | int idx; | |
1136 | while (true) | |
1137 | { | |
eab36a5a | 1138 | symtab_node node; |
7f385784 | 1139 | count = streamer_read_uhwi (ib); |
8d810329 | 1140 | if (!count) |
1141 | break; | |
7f385784 | 1142 | idx = streamer_read_uhwi (ib); |
eab36a5a | 1143 | node = VEC_index (symtab_node, nodes, idx); |
8d810329 | 1144 | while (count) |
1145 | { | |
eab36a5a | 1146 | input_ref (ib, node, nodes); |
8d810329 | 1147 | count--; |
1148 | } | |
1149 | } | |
1150 | } | |
1151 | ||
a238367f | 1152 | |
6c0782b1 | 1153 | static struct gcov_ctr_summary lto_gcov_summary; |
1154 | ||
1155 | /* Input profile_info from IB. */ | |
1156 | static void | |
c470c5a9 | 1157 | input_profile_summary (struct lto_input_block *ib, |
1158 | struct lto_file_decl_data *file_data) | |
6c0782b1 | 1159 | { |
7f385784 | 1160 | unsigned int runs = streamer_read_uhwi (ib); |
6c0782b1 | 1161 | if (runs) |
1162 | { | |
c470c5a9 | 1163 | file_data->profile_info.runs = runs; |
7f385784 | 1164 | file_data->profile_info.sum_max = streamer_read_uhwi (ib); |
6c0782b1 | 1165 | } |
1166 | ||
1167 | } | |
7bfefa9d | 1168 | |
c470c5a9 | 1169 | /* Rescale profile summaries to the same number of runs in the whole unit. */ |
1170 | ||
1171 | static void | |
1172 | merge_profile_summaries (struct lto_file_decl_data **file_data_vec) | |
1173 | { | |
1174 | struct lto_file_decl_data *file_data; | |
1175 | unsigned int j; | |
1176 | gcov_unsigned_t max_runs = 0; | |
1177 | struct cgraph_node *node; | |
1178 | struct cgraph_edge *edge; | |
1179 | ||
1180 | /* Find unit with maximal number of runs. If we ever get serious about | |
1181 | roundoff errors, we might also consider computing smallest common | |
1182 | multiply. */ | |
1183 | for (j = 0; (file_data = file_data_vec[j]) != NULL; j++) | |
1184 | if (max_runs < file_data->profile_info.runs) | |
1185 | max_runs = file_data->profile_info.runs; | |
1186 | ||
1187 | if (!max_runs) | |
1188 | return; | |
1189 | ||
1190 | /* Simple overflow check. We probably don't need to support that many train | |
1191 | runs. Such a large value probably imply data corruption anyway. */ | |
1192 | if (max_runs > INT_MAX / REG_BR_PROB_BASE) | |
1193 | { | |
1194 | sorry ("At most %i profile runs is supported. Perhaps corrupted profile?", | |
1195 | INT_MAX / REG_BR_PROB_BASE); | |
1196 | return; | |
1197 | } | |
1198 | ||
1199 | profile_info = <o_gcov_summary; | |
1200 | lto_gcov_summary.runs = max_runs; | |
1201 | lto_gcov_summary.sum_max = 0; | |
1202 | ||
1203 | /* Rescale all units to the maximal number of runs. | |
1204 | sum_max can not be easily merged, as we have no idea what files come from | |
1205 | the same run. We do not use the info anyway, so leave it 0. */ | |
1206 | for (j = 0; (file_data = file_data_vec[j]) != NULL; j++) | |
1207 | if (file_data->profile_info.runs) | |
1208 | { | |
1209 | int scale = ((REG_BR_PROB_BASE * max_runs | |
1210 | + file_data->profile_info.runs / 2) | |
1211 | / file_data->profile_info.runs); | |
1212 | lto_gcov_summary.sum_max = MAX (lto_gcov_summary.sum_max, | |
1213 | (file_data->profile_info.sum_max | |
1214 | * scale | |
1215 | + REG_BR_PROB_BASE / 2) | |
1216 | / REG_BR_PROB_BASE); | |
1217 | } | |
1218 | ||
1219 | /* Watch roundoff errors. */ | |
1220 | if (lto_gcov_summary.sum_max < max_runs) | |
1221 | lto_gcov_summary.sum_max = max_runs; | |
1222 | ||
1223 | /* If merging already happent at WPA time, we are done. */ | |
1224 | if (flag_ltrans) | |
1225 | return; | |
1226 | ||
1227 | /* Now compute count_materialization_scale of each node. | |
1228 | During LTRANS we already have values of count_materialization_scale | |
1229 | computed, so just update them. */ | |
7c455d87 | 1230 | FOR_EACH_FUNCTION (node) |
7d0d0ce1 | 1231 | if (node->symbol.lto_file_data |
1232 | && node->symbol.lto_file_data->profile_info.runs) | |
c470c5a9 | 1233 | { |
1234 | int scale; | |
555491e2 | 1235 | |
1236 | scale = | |
1237 | ((node->count_materialization_scale * max_runs | |
7d0d0ce1 | 1238 | + node->symbol.lto_file_data->profile_info.runs / 2) |
1239 | / node->symbol.lto_file_data->profile_info.runs); | |
c470c5a9 | 1240 | node->count_materialization_scale = scale; |
1241 | if (scale < 0) | |
1242 | fatal_error ("Profile information in %s corrupted", | |
1243 | file_data->file_name); | |
1244 | ||
1245 | if (scale == REG_BR_PROB_BASE) | |
1246 | continue; | |
1247 | for (edge = node->callees; edge; edge = edge->next_callee) | |
1248 | edge->count = ((edge->count * scale + REG_BR_PROB_BASE / 2) | |
1249 | / REG_BR_PROB_BASE); | |
1250 | node->count = ((node->count * scale + REG_BR_PROB_BASE / 2) | |
1251 | / REG_BR_PROB_BASE); | |
1252 | } | |
1253 | } | |
1254 | ||
02b699d5 | 1255 | /* Input and merge the symtab from each of the .o files passed to |
7bfefa9d | 1256 | lto1. */ |
1257 | ||
1258 | void | |
02b699d5 | 1259 | input_symtab (void) |
7bfefa9d | 1260 | { |
1261 | struct lto_file_decl_data **file_data_vec = lto_get_file_decl_data (); | |
1262 | struct lto_file_decl_data *file_data; | |
1263 | unsigned int j = 0; | |
1264 | struct cgraph_node *node; | |
1265 | ||
ff2a5ada | 1266 | cgraph_state = CGRAPH_STATE_IPA_SSA; |
1267 | ||
7bfefa9d | 1268 | while ((file_data = file_data_vec[j++])) |
1269 | { | |
1270 | const char *data; | |
1271 | size_t len; | |
1272 | struct lto_input_block *ib; | |
70225339 | 1273 | VEC(symtab_node, heap) *nodes; |
7bfefa9d | 1274 | |
02b699d5 | 1275 | ib = lto_create_simple_input_block (file_data, LTO_section_symtab_nodes, |
7bfefa9d | 1276 | &data, &len); |
fd30d60a | 1277 | if (!ib) |
bf776685 | 1278 | fatal_error ("cannot find LTO cgraph in %s", file_data->file_name); |
c470c5a9 | 1279 | input_profile_summary (ib, file_data); |
70225339 | 1280 | file_data->symtab_node_encoder = lto_symtab_encoder_new (); |
a238367f | 1281 | nodes = input_cgraph_1 (file_data, ib); |
02b699d5 | 1282 | lto_destroy_simple_input_block (file_data, LTO_section_symtab_nodes, |
7bfefa9d | 1283 | ib, data, len); |
48e1416a | 1284 | |
8d810329 | 1285 | ib = lto_create_simple_input_block (file_data, LTO_section_refs, |
1286 | &data, &len); | |
fd30d60a | 1287 | if (!ib) |
bf776685 | 1288 | fatal_error("cannot find LTO section refs in %s", file_data->file_name); |
70225339 | 1289 | input_refs (ib, nodes); |
8d810329 | 1290 | lto_destroy_simple_input_block (file_data, LTO_section_refs, |
1291 | ib, data, len); | |
1bf41320 | 1292 | if (flag_ltrans) |
1293 | input_cgraph_opt_summary (nodes); | |
70225339 | 1294 | VEC_free (symtab_node, heap, nodes); |
48e1416a | 1295 | } |
30f589a5 | 1296 | |
c470c5a9 | 1297 | merge_profile_summaries (file_data_vec); |
7bfefa9d | 1298 | |
1299 | /* Clear out the aux field that was used to store enough state to | |
1300 | tell which nodes should be overwritten. */ | |
7c455d87 | 1301 | FOR_EACH_FUNCTION (node) |
7bfefa9d | 1302 | { |
1303 | /* Some nodes may have been created by cgraph_node. This | |
1304 | happens when the callgraph contains nested functions. If the | |
1305 | node for the parent function was never emitted to the gimple | |
1306 | file, cgraph_node will create a node for it when setting the | |
1307 | context of the nested function. */ | |
7d0d0ce1 | 1308 | if (node->symbol.lto_file_data) |
1309 | node->symbol.aux = NULL; | |
7bfefa9d | 1310 | } |
1311 | } | |
1bf41320 | 1312 | |
1313 | /* True when we need optimization summary for NODE. */ | |
1314 | ||
1315 | static int | |
eab36a5a | 1316 | output_cgraph_opt_summary_p (struct cgraph_node *node) |
1bf41320 | 1317 | { |
2b36ac0b | 1318 | return (node->clone_of |
1319 | && (node->clone.tree_map | |
1320 | || node->clone.args_to_skip | |
1321 | || node->clone.combined_args_to_skip)); | |
1bf41320 | 1322 | } |
1323 | ||
9bab6a70 | 1324 | /* Output optimization summary for EDGE to OB. */ |
1325 | static void | |
d4e80e2b | 1326 | output_edge_opt_summary (struct output_block *ob ATTRIBUTE_UNUSED, |
1327 | struct cgraph_edge *edge ATTRIBUTE_UNUSED) | |
9bab6a70 | 1328 | { |
9bab6a70 | 1329 | } |
1330 | ||
1bf41320 | 1331 | /* Output optimization summary for NODE to OB. */ |
1332 | ||
1333 | static void | |
1334 | output_node_opt_summary (struct output_block *ob, | |
2b36ac0b | 1335 | struct cgraph_node *node, |
eab36a5a | 1336 | lto_symtab_encoder_t encoder) |
1bf41320 | 1337 | { |
1338 | unsigned int index; | |
1339 | bitmap_iterator bi; | |
1340 | struct ipa_replace_map *map; | |
30baba90 | 1341 | struct bitpack_d bp; |
1bf41320 | 1342 | int i; |
9bab6a70 | 1343 | struct cgraph_edge *e; |
1bf41320 | 1344 | |
29413d70 | 1345 | if (node->clone.args_to_skip) |
1346 | { | |
7f385784 | 1347 | streamer_write_uhwi (ob, bitmap_count_bits (node->clone.args_to_skip)); |
29413d70 | 1348 | EXECUTE_IF_SET_IN_BITMAP (node->clone.args_to_skip, 0, index, bi) |
7f385784 | 1349 | streamer_write_uhwi (ob, index); |
29413d70 | 1350 | } |
1351 | else | |
7f385784 | 1352 | streamer_write_uhwi (ob, 0); |
29413d70 | 1353 | if (node->clone.combined_args_to_skip) |
1354 | { | |
7f385784 | 1355 | streamer_write_uhwi (ob, bitmap_count_bits (node->clone.combined_args_to_skip)); |
29413d70 | 1356 | EXECUTE_IF_SET_IN_BITMAP (node->clone.combined_args_to_skip, 0, index, bi) |
7f385784 | 1357 | streamer_write_uhwi (ob, index); |
29413d70 | 1358 | } |
1359 | else | |
7f385784 | 1360 | streamer_write_uhwi (ob, 0); |
1361 | streamer_write_uhwi (ob, VEC_length (ipa_replace_map_p, | |
1362 | node->clone.tree_map)); | |
48148244 | 1363 | FOR_EACH_VEC_ELT (ipa_replace_map_p, node->clone.tree_map, i, map) |
1bf41320 | 1364 | { |
1365 | int parm_num; | |
1366 | tree parm; | |
1367 | ||
7d0d0ce1 | 1368 | for (parm_num = 0, parm = DECL_ARGUMENTS (node->symbol.decl); parm; |
1767a056 | 1369 | parm = DECL_CHAIN (parm), parm_num++) |
1bf41320 | 1370 | if (map->old_tree == parm) |
1371 | break; | |
1372 | /* At the moment we assume all old trees to be PARM_DECLs, because we have no | |
1373 | mechanism to store function local declarations into summaries. */ | |
1374 | gcc_assert (parm); | |
7f385784 | 1375 | streamer_write_uhwi (ob, parm_num); |
515cf651 | 1376 | stream_write_tree (ob, map->new_tree, true); |
30baba90 | 1377 | bp = bitpack_create (ob->main_stream); |
1378 | bp_pack_value (&bp, map->replace_p, 1); | |
1379 | bp_pack_value (&bp, map->ref_p, 1); | |
7f385784 | 1380 | streamer_write_bitpack (&bp); |
1bf41320 | 1381 | } |
2b36ac0b | 1382 | |
eab36a5a | 1383 | if (lto_symtab_encoder_in_partition_p (encoder, (symtab_node) node)) |
2b36ac0b | 1384 | { |
1385 | for (e = node->callees; e; e = e->next_callee) | |
1386 | output_edge_opt_summary (ob, e); | |
1387 | for (e = node->indirect_calls; e; e = e->next_callee) | |
1388 | output_edge_opt_summary (ob, e); | |
1389 | } | |
1bf41320 | 1390 | } |
1391 | ||
1392 | /* Output optimization summaries stored in callgraph. | |
1393 | At the moment it is the clone info structure. */ | |
1394 | ||
1395 | static void | |
eab36a5a | 1396 | output_cgraph_opt_summary (void) |
1bf41320 | 1397 | { |
70225339 | 1398 | symtab_node node; |
1bf41320 | 1399 | int i, n_nodes; |
70225339 | 1400 | lto_symtab_encoder_t encoder; |
1bf41320 | 1401 | struct output_block *ob = create_output_block (LTO_section_cgraph_opt_sum); |
1402 | unsigned count = 0; | |
1403 | ||
1404 | ob->cgraph_node = NULL; | |
70225339 | 1405 | encoder = ob->decl_state->symtab_node_encoder; |
1406 | n_nodes = lto_symtab_encoder_size (encoder); | |
1bf41320 | 1407 | for (i = 0; i < n_nodes; i++) |
70225339 | 1408 | if (symtab_function_p (node = lto_symtab_encoder_deref (encoder, i)) |
eab36a5a | 1409 | && output_cgraph_opt_summary_p (cgraph (node))) |
1bf41320 | 1410 | count++; |
7f385784 | 1411 | streamer_write_uhwi (ob, count); |
1bf41320 | 1412 | for (i = 0; i < n_nodes; i++) |
1413 | { | |
70225339 | 1414 | node = lto_symtab_encoder_deref (encoder, i); |
1415 | if (symtab_function_p (node) | |
eab36a5a | 1416 | && output_cgraph_opt_summary_p (cgraph (node))) |
1bf41320 | 1417 | { |
7f385784 | 1418 | streamer_write_uhwi (ob, i); |
eab36a5a | 1419 | output_node_opt_summary (ob, cgraph (node), encoder); |
1bf41320 | 1420 | } |
1421 | } | |
1422 | produce_asm (ob, NULL); | |
1423 | destroy_output_block (ob); | |
1424 | } | |
1425 | ||
9bab6a70 | 1426 | /* Input optimisation summary of EDGE. */ |
1427 | ||
1428 | static void | |
d4e80e2b | 1429 | input_edge_opt_summary (struct cgraph_edge *edge ATTRIBUTE_UNUSED, |
1430 | struct lto_input_block *ib_main ATTRIBUTE_UNUSED) | |
9bab6a70 | 1431 | { |
9bab6a70 | 1432 | } |
1433 | ||
1434 | /* Input optimisation summary of NODE. */ | |
1bf41320 | 1435 | |
1436 | static void | |
1437 | input_node_opt_summary (struct cgraph_node *node, | |
1438 | struct lto_input_block *ib_main, | |
1439 | struct data_in *data_in) | |
1440 | { | |
1441 | int i; | |
1442 | int count; | |
1443 | int bit; | |
30baba90 | 1444 | struct bitpack_d bp; |
9bab6a70 | 1445 | struct cgraph_edge *e; |
1bf41320 | 1446 | |
7f385784 | 1447 | count = streamer_read_uhwi (ib_main); |
1bf41320 | 1448 | if (count) |
1449 | node->clone.args_to_skip = BITMAP_GGC_ALLOC (); | |
1450 | for (i = 0; i < count; i++) | |
1451 | { | |
7f385784 | 1452 | bit = streamer_read_uhwi (ib_main); |
1bf41320 | 1453 | bitmap_set_bit (node->clone.args_to_skip, bit); |
1454 | } | |
7f385784 | 1455 | count = streamer_read_uhwi (ib_main); |
1bf41320 | 1456 | if (count) |
1457 | node->clone.combined_args_to_skip = BITMAP_GGC_ALLOC (); | |
1458 | for (i = 0; i < count; i++) | |
1459 | { | |
7f385784 | 1460 | bit = streamer_read_uhwi (ib_main); |
1bf41320 | 1461 | bitmap_set_bit (node->clone.combined_args_to_skip, bit); |
1462 | } | |
7f385784 | 1463 | count = streamer_read_uhwi (ib_main); |
1bf41320 | 1464 | for (i = 0; i < count; i++) |
1465 | { | |
1466 | int parm_num; | |
1467 | tree parm; | |
ba72912a | 1468 | struct ipa_replace_map *map = ggc_alloc_ipa_replace_map (); |
1bf41320 | 1469 | |
1470 | VEC_safe_push (ipa_replace_map_p, gc, node->clone.tree_map, map); | |
7d0d0ce1 | 1471 | for (parm_num = 0, parm = DECL_ARGUMENTS (node->symbol.decl); parm_num; |
1767a056 | 1472 | parm = DECL_CHAIN (parm)) |
1bf41320 | 1473 | parm_num --; |
7f385784 | 1474 | map->parm_num = streamer_read_uhwi (ib_main); |
1bf41320 | 1475 | map->old_tree = NULL; |
515cf651 | 1476 | map->new_tree = stream_read_tree (ib_main, data_in); |
7f385784 | 1477 | bp = streamer_read_bitpack (ib_main); |
30baba90 | 1478 | map->replace_p = bp_unpack_value (&bp, 1); |
1479 | map->ref_p = bp_unpack_value (&bp, 1); | |
1bf41320 | 1480 | } |
9bab6a70 | 1481 | for (e = node->callees; e; e = e->next_callee) |
1482 | input_edge_opt_summary (e, ib_main); | |
1483 | for (e = node->indirect_calls; e; e = e->next_callee) | |
1484 | input_edge_opt_summary (e, ib_main); | |
1bf41320 | 1485 | } |
1486 | ||
1487 | /* Read section in file FILE_DATA of length LEN with data DATA. */ | |
1488 | ||
1489 | static void | |
1490 | input_cgraph_opt_section (struct lto_file_decl_data *file_data, | |
70225339 | 1491 | const char *data, size_t len, VEC (symtab_node, |
1bf41320 | 1492 | heap) * nodes) |
1493 | { | |
1494 | const struct lto_function_header *header = | |
1495 | (const struct lto_function_header *) data; | |
949e5786 | 1496 | const int cfg_offset = sizeof (struct lto_function_header); |
1497 | const int main_offset = cfg_offset + header->cfg_size; | |
1498 | const int string_offset = main_offset + header->main_size; | |
1bf41320 | 1499 | struct data_in *data_in; |
1500 | struct lto_input_block ib_main; | |
1501 | unsigned int i; | |
1502 | unsigned int count; | |
1503 | ||
1504 | LTO_INIT_INPUT_BLOCK (ib_main, (const char *) data + main_offset, 0, | |
1505 | header->main_size); | |
1506 | ||
1507 | data_in = | |
1508 | lto_data_in_create (file_data, (const char *) data + string_offset, | |
1509 | header->string_size, NULL); | |
7f385784 | 1510 | count = streamer_read_uhwi (&ib_main); |
1bf41320 | 1511 | |
1512 | for (i = 0; i < count; i++) | |
1513 | { | |
7f385784 | 1514 | int ref = streamer_read_uhwi (&ib_main); |
70225339 | 1515 | input_node_opt_summary (cgraph (VEC_index (symtab_node, nodes, ref)), |
1bf41320 | 1516 | &ib_main, data_in); |
1517 | } | |
783bc09c | 1518 | lto_free_section_data (file_data, LTO_section_cgraph_opt_sum, NULL, data, |
1bf41320 | 1519 | len); |
1520 | lto_data_in_delete (data_in); | |
1521 | } | |
1522 | ||
1523 | /* Input optimization summary of cgraph. */ | |
1524 | ||
1525 | static void | |
70225339 | 1526 | input_cgraph_opt_summary (VEC (symtab_node, heap) * nodes) |
1bf41320 | 1527 | { |
1528 | struct lto_file_decl_data **file_data_vec = lto_get_file_decl_data (); | |
1529 | struct lto_file_decl_data *file_data; | |
1530 | unsigned int j = 0; | |
1531 | ||
1532 | while ((file_data = file_data_vec[j++])) | |
1533 | { | |
1534 | size_t len; | |
1535 | const char *data = | |
1536 | lto_get_section_data (file_data, LTO_section_cgraph_opt_sum, NULL, | |
1537 | &len); | |
1538 | ||
1539 | if (data) | |
1540 | input_cgraph_opt_section (file_data, data, len, nodes); | |
1541 | } | |
1542 | } |