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