111
|
1 /* Interprocedural Identical Code Folding pass
|
131
|
2 Copyright (C) 2014-2018 Free Software Foundation, Inc.
|
111
|
3
|
|
4 Contributed by Jan Hubicka <hubicka@ucw.cz> and Martin Liska <mliska@suse.cz>
|
|
5
|
|
6 This file is part of GCC.
|
|
7
|
|
8 GCC is free software; you can redistribute it and/or modify it under
|
|
9 the terms of the GNU General Public License as published by the Free
|
|
10 Software Foundation; either version 3, or (at your option) any later
|
|
11 version.
|
|
12
|
|
13 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
14 WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
16 for more details.
|
|
17
|
|
18 You should have received a copy of the GNU General Public License
|
|
19 along with GCC; see the file COPYING3. If not see
|
|
20 <http://www.gnu.org/licenses/>. */
|
|
21
|
|
22 /* Interprocedural Identical Code Folding for functions and
|
|
23 read-only variables.
|
|
24
|
|
25 The goal of this transformation is to discover functions and read-only
|
|
26 variables which do have exactly the same semantics.
|
|
27
|
|
28 In case of functions,
|
|
29 we could either create a virtual clone or do a simple function wrapper
|
|
30 that will call equivalent function. If the function is just locally visible,
|
|
31 all function calls can be redirected. For read-only variables, we create
|
|
32 aliases if possible.
|
|
33
|
|
34 Optimization pass arranges as follows:
|
|
35 1) All functions and read-only variables are visited and internal
|
|
36 data structure, either sem_function or sem_variables is created.
|
|
37 2) For every symbol from the previous step, VAR_DECL and FUNCTION_DECL are
|
|
38 saved and matched to corresponding sem_items.
|
|
39 3) These declaration are ignored for equality check and are solved
|
|
40 by Value Numbering algorithm published by Alpert, Zadeck in 1992.
|
|
41 4) We compute hash value for each symbol.
|
|
42 5) Congruence classes are created based on hash value. If hash value are
|
|
43 equal, equals function is called and symbols are deeply compared.
|
|
44 We must prove that all SSA names, declarations and other items
|
|
45 correspond.
|
|
46 6) Value Numbering is executed for these classes. At the end of the process
|
|
47 all symbol members in remaining classes can be merged.
|
|
48 7) Merge operation creates alias in case of read-only variables. For
|
|
49 callgraph node, we must decide if we can redirect local calls,
|
|
50 create an alias or a thunk.
|
|
51
|
|
52 */
|
|
53
|
|
54 #include "config.h"
|
|
55 #define INCLUDE_LIST
|
|
56 #include "system.h"
|
|
57 #include "coretypes.h"
|
|
58 #include "backend.h"
|
|
59 #include "target.h"
|
|
60 #include "rtl.h"
|
|
61 #include "tree.h"
|
|
62 #include "gimple.h"
|
|
63 #include "alloc-pool.h"
|
|
64 #include "tree-pass.h"
|
|
65 #include "ssa.h"
|
|
66 #include "cgraph.h"
|
|
67 #include "coverage.h"
|
|
68 #include "gimple-pretty-print.h"
|
|
69 #include "data-streamer.h"
|
|
70 #include "fold-const.h"
|
|
71 #include "calls.h"
|
|
72 #include "varasm.h"
|
|
73 #include "gimple-iterator.h"
|
|
74 #include "tree-cfg.h"
|
|
75 #include "symbol-summary.h"
|
|
76 #include "ipa-prop.h"
|
|
77 #include "ipa-fnsummary.h"
|
|
78 #include "except.h"
|
|
79 #include "attribs.h"
|
|
80 #include "print-tree.h"
|
|
81 #include "ipa-utils.h"
|
|
82 #include "ipa-icf-gimple.h"
|
|
83 #include "ipa-icf.h"
|
|
84 #include "stor-layout.h"
|
|
85 #include "dbgcnt.h"
|
131
|
86 #include "tree-vector-builder.h"
|
111
|
87
|
|
88 using namespace ipa_icf_gimple;
|
|
89
|
|
90 namespace ipa_icf {
|
|
91
|
|
92 /* Initialization and computation of symtab node hash, there data
|
|
93 are propagated later on. */
|
|
94
|
|
95 static sem_item_optimizer *optimizer = NULL;
|
|
96
|
|
97 /* Constructor. */
|
|
98
|
|
99 symbol_compare_collection::symbol_compare_collection (symtab_node *node)
|
|
100 {
|
|
101 m_references.create (0);
|
|
102 m_interposables.create (0);
|
|
103
|
|
104 ipa_ref *ref;
|
|
105
|
|
106 if (is_a <varpool_node *> (node) && DECL_VIRTUAL_P (node->decl))
|
|
107 return;
|
|
108
|
|
109 for (unsigned i = 0; node->iterate_reference (i, ref); i++)
|
|
110 {
|
|
111 if (ref->address_matters_p ())
|
|
112 m_references.safe_push (ref->referred);
|
|
113
|
|
114 if (ref->referred->get_availability () <= AVAIL_INTERPOSABLE)
|
|
115 {
|
|
116 if (ref->address_matters_p ())
|
|
117 m_references.safe_push (ref->referred);
|
|
118 else
|
|
119 m_interposables.safe_push (ref->referred);
|
|
120 }
|
|
121 }
|
|
122
|
|
123 if (is_a <cgraph_node *> (node))
|
|
124 {
|
|
125 cgraph_node *cnode = dyn_cast <cgraph_node *> (node);
|
|
126
|
|
127 for (cgraph_edge *e = cnode->callees; e; e = e->next_callee)
|
|
128 if (e->callee->get_availability () <= AVAIL_INTERPOSABLE)
|
|
129 m_interposables.safe_push (e->callee);
|
|
130 }
|
|
131 }
|
|
132
|
|
133 /* Constructor for key value pair, where _ITEM is key and _INDEX is a target. */
|
|
134
|
|
135 sem_usage_pair::sem_usage_pair (sem_item *_item, unsigned int _index)
|
|
136 : item (_item), index (_index)
|
|
137 {
|
|
138 }
|
|
139
|
|
140 sem_item::sem_item (sem_item_type _type, bitmap_obstack *stack)
|
|
141 : type (_type), m_hash (-1), m_hash_set (false)
|
|
142 {
|
|
143 setup (stack);
|
|
144 }
|
|
145
|
|
146 sem_item::sem_item (sem_item_type _type, symtab_node *_node,
|
|
147 bitmap_obstack *stack)
|
|
148 : type (_type), node (_node), m_hash (-1), m_hash_set (false)
|
|
149 {
|
|
150 decl = node->decl;
|
|
151 setup (stack);
|
|
152 }
|
|
153
|
|
154 /* Add reference to a semantic TARGET. */
|
|
155
|
|
156 void
|
|
157 sem_item::add_reference (sem_item *target)
|
|
158 {
|
|
159 refs.safe_push (target);
|
|
160 unsigned index = refs.length ();
|
|
161 target->usages.safe_push (new sem_usage_pair(this, index));
|
|
162 bitmap_set_bit (target->usage_index_bitmap, index);
|
|
163 refs_set.add (target->node);
|
|
164 }
|
|
165
|
|
166 /* Initialize internal data structures. Bitmap STACK is used for
|
|
167 bitmap memory allocation process. */
|
|
168
|
|
169 void
|
|
170 sem_item::setup (bitmap_obstack *stack)
|
|
171 {
|
|
172 gcc_checking_assert (node);
|
|
173
|
|
174 refs.create (0);
|
|
175 tree_refs.create (0);
|
|
176 usages.create (0);
|
|
177 usage_index_bitmap = BITMAP_ALLOC (stack);
|
|
178 }
|
|
179
|
|
180 sem_item::~sem_item ()
|
|
181 {
|
|
182 for (unsigned i = 0; i < usages.length (); i++)
|
|
183 delete usages[i];
|
|
184
|
|
185 refs.release ();
|
|
186 tree_refs.release ();
|
|
187 usages.release ();
|
|
188
|
|
189 BITMAP_FREE (usage_index_bitmap);
|
|
190 }
|
|
191
|
|
192 /* Dump function for debugging purpose. */
|
|
193
|
|
194 DEBUG_FUNCTION void
|
|
195 sem_item::dump (void)
|
|
196 {
|
|
197 if (dump_file)
|
|
198 {
|
|
199 fprintf (dump_file, "[%s] %s (tree:%p)\n", type == FUNC ? "func" : "var",
|
|
200 node->dump_name (), (void *) node->decl);
|
|
201 fprintf (dump_file, " hash: %u\n", get_hash ());
|
|
202 fprintf (dump_file, " references: ");
|
|
203
|
|
204 for (unsigned i = 0; i < refs.length (); i++)
|
|
205 fprintf (dump_file, "%s%s ", refs[i]->node->name (),
|
|
206 i < refs.length() - 1 ? "," : "");
|
|
207
|
|
208 fprintf (dump_file, "\n");
|
|
209 }
|
|
210 }
|
|
211
|
|
212 /* Return true if target supports alias symbols. */
|
|
213
|
|
214 bool
|
|
215 sem_item::target_supports_symbol_aliases_p (void)
|
|
216 {
|
|
217 #if !defined (ASM_OUTPUT_DEF) || (!defined(ASM_OUTPUT_WEAK_ALIAS) && !defined (ASM_WEAKEN_DECL))
|
|
218 return false;
|
|
219 #else
|
|
220 return true;
|
|
221 #endif
|
|
222 }
|
|
223
|
|
224 void sem_item::set_hash (hashval_t hash)
|
|
225 {
|
|
226 m_hash = hash;
|
|
227 m_hash_set = true;
|
|
228 }
|
|
229
|
131
|
230 hash_map<const_tree, hashval_t> sem_item::m_type_hash_cache;
|
|
231
|
111
|
232 /* Semantic function constructor that uses STACK as bitmap memory stack. */
|
|
233
|
|
234 sem_function::sem_function (bitmap_obstack *stack)
|
|
235 : sem_item (FUNC, stack), m_checker (NULL), m_compared_func (NULL)
|
|
236 {
|
|
237 bb_sizes.create (0);
|
|
238 bb_sorted.create (0);
|
|
239 }
|
|
240
|
|
241 sem_function::sem_function (cgraph_node *node, bitmap_obstack *stack)
|
|
242 : sem_item (FUNC, node, stack), m_checker (NULL), m_compared_func (NULL)
|
|
243 {
|
|
244 bb_sizes.create (0);
|
|
245 bb_sorted.create (0);
|
|
246 }
|
|
247
|
|
248 sem_function::~sem_function ()
|
|
249 {
|
|
250 for (unsigned i = 0; i < bb_sorted.length (); i++)
|
|
251 delete (bb_sorted[i]);
|
|
252
|
|
253 bb_sizes.release ();
|
|
254 bb_sorted.release ();
|
|
255 }
|
|
256
|
|
257 /* Calculates hash value based on a BASIC_BLOCK. */
|
|
258
|
|
259 hashval_t
|
|
260 sem_function::get_bb_hash (const sem_bb *basic_block)
|
|
261 {
|
|
262 inchash::hash hstate;
|
|
263
|
|
264 hstate.add_int (basic_block->nondbg_stmt_count);
|
|
265 hstate.add_int (basic_block->edge_count);
|
|
266
|
|
267 return hstate.end ();
|
|
268 }
|
|
269
|
|
270 /* References independent hash function. */
|
|
271
|
|
272 hashval_t
|
|
273 sem_function::get_hash (void)
|
|
274 {
|
|
275 if (!m_hash_set)
|
|
276 {
|
|
277 inchash::hash hstate;
|
|
278 hstate.add_int (177454); /* Random number for function type. */
|
|
279
|
|
280 hstate.add_int (arg_count);
|
|
281 hstate.add_int (cfg_checksum);
|
|
282 hstate.add_int (gcode_hash);
|
|
283
|
|
284 for (unsigned i = 0; i < bb_sorted.length (); i++)
|
|
285 hstate.merge_hash (get_bb_hash (bb_sorted[i]));
|
|
286
|
|
287 for (unsigned i = 0; i < bb_sizes.length (); i++)
|
|
288 hstate.add_int (bb_sizes[i]);
|
|
289
|
|
290 /* Add common features of declaration itself. */
|
|
291 if (DECL_FUNCTION_SPECIFIC_TARGET (decl))
|
|
292 hstate.add_hwi
|
|
293 (cl_target_option_hash
|
|
294 (TREE_TARGET_OPTION (DECL_FUNCTION_SPECIFIC_TARGET (decl))));
|
|
295 if (DECL_FUNCTION_SPECIFIC_OPTIMIZATION (decl))
|
|
296 hstate.add_hwi
|
|
297 (cl_optimization_hash
|
|
298 (TREE_OPTIMIZATION (DECL_FUNCTION_SPECIFIC_OPTIMIZATION (decl))));
|
|
299 hstate.add_flag (DECL_CXX_CONSTRUCTOR_P (decl));
|
|
300 hstate.add_flag (DECL_CXX_DESTRUCTOR_P (decl));
|
|
301
|
|
302 set_hash (hstate.end ());
|
|
303 }
|
|
304
|
|
305 return m_hash;
|
|
306 }
|
|
307
|
|
308 /* Compare properties of symbols N1 and N2 that does not affect semantics of
|
|
309 symbol itself but affects semantics of its references from USED_BY (which
|
|
310 may be NULL if it is unknown). If comparsion is false, symbols
|
|
311 can still be merged but any symbols referring them can't.
|
|
312
|
|
313 If ADDRESS is true, do extra checking needed for IPA_REF_ADDR.
|
|
314
|
|
315 TODO: We can also split attributes to those that determine codegen of
|
|
316 a function body/variable constructor itself and those that are used when
|
|
317 referring to it. */
|
|
318
|
|
319 bool
|
|
320 sem_item::compare_referenced_symbol_properties (symtab_node *used_by,
|
|
321 symtab_node *n1,
|
|
322 symtab_node *n2,
|
|
323 bool address)
|
|
324 {
|
|
325 if (is_a <cgraph_node *> (n1))
|
|
326 {
|
|
327 /* Inline properties matters: we do now want to merge uses of inline
|
|
328 function to uses of normal function because inline hint would be lost.
|
|
329 We however can merge inline function to noinline because the alias
|
|
330 will keep its DECL_DECLARED_INLINE flag.
|
|
331
|
|
332 Also ignore inline flag when optimizing for size or when function
|
|
333 is known to not be inlinable.
|
|
334
|
|
335 TODO: the optimize_size checks can also be assumed to be true if
|
|
336 unit has no !optimize_size functions. */
|
|
337
|
|
338 if ((!used_by || address || !is_a <cgraph_node *> (used_by)
|
|
339 || !opt_for_fn (used_by->decl, optimize_size))
|
|
340 && !opt_for_fn (n1->decl, optimize_size)
|
|
341 && n1->get_availability () > AVAIL_INTERPOSABLE
|
|
342 && (!DECL_UNINLINABLE (n1->decl) || !DECL_UNINLINABLE (n2->decl)))
|
|
343 {
|
|
344 if (DECL_DISREGARD_INLINE_LIMITS (n1->decl)
|
|
345 != DECL_DISREGARD_INLINE_LIMITS (n2->decl))
|
|
346 return return_false_with_msg
|
|
347 ("DECL_DISREGARD_INLINE_LIMITS are different");
|
|
348
|
|
349 if (DECL_DECLARED_INLINE_P (n1->decl)
|
|
350 != DECL_DECLARED_INLINE_P (n2->decl))
|
|
351 return return_false_with_msg ("inline attributes are different");
|
|
352 }
|
|
353
|
|
354 if (DECL_IS_OPERATOR_NEW (n1->decl)
|
|
355 != DECL_IS_OPERATOR_NEW (n2->decl))
|
|
356 return return_false_with_msg ("operator new flags are different");
|
|
357 }
|
|
358
|
|
359 /* Merging two definitions with a reference to equivalent vtables, but
|
|
360 belonging to a different type may result in ipa-polymorphic-call analysis
|
|
361 giving a wrong answer about the dynamic type of instance. */
|
|
362 if (is_a <varpool_node *> (n1))
|
|
363 {
|
|
364 if ((DECL_VIRTUAL_P (n1->decl) || DECL_VIRTUAL_P (n2->decl))
|
|
365 && (DECL_VIRTUAL_P (n1->decl) != DECL_VIRTUAL_P (n2->decl)
|
|
366 || !types_must_be_same_for_odr (DECL_CONTEXT (n1->decl),
|
|
367 DECL_CONTEXT (n2->decl)))
|
|
368 && (!used_by || !is_a <cgraph_node *> (used_by) || address
|
|
369 || opt_for_fn (used_by->decl, flag_devirtualize)))
|
|
370 return return_false_with_msg
|
|
371 ("references to virtual tables can not be merged");
|
|
372
|
|
373 if (address && DECL_ALIGN (n1->decl) != DECL_ALIGN (n2->decl))
|
|
374 return return_false_with_msg ("alignment mismatch");
|
|
375
|
|
376 /* For functions we compare attributes in equals_wpa, because we do
|
|
377 not know what attributes may cause codegen differences, but for
|
|
378 variables just compare attributes for references - the codegen
|
|
379 for constructors is affected only by those attributes that we lower
|
|
380 to explicit representation (such as DECL_ALIGN or DECL_SECTION). */
|
131
|
381 if (!attribute_list_equal (DECL_ATTRIBUTES (n1->decl),
|
|
382 DECL_ATTRIBUTES (n2->decl)))
|
111
|
383 return return_false_with_msg ("different var decl attributes");
|
|
384 if (comp_type_attributes (TREE_TYPE (n1->decl),
|
|
385 TREE_TYPE (n2->decl)) != 1)
|
|
386 return return_false_with_msg ("different var type attributes");
|
|
387 }
|
|
388
|
|
389 /* When matching virtual tables, be sure to also match information
|
|
390 relevant for polymorphic call analysis. */
|
|
391 if (used_by && is_a <varpool_node *> (used_by)
|
|
392 && DECL_VIRTUAL_P (used_by->decl))
|
|
393 {
|
|
394 if (DECL_VIRTUAL_P (n1->decl) != DECL_VIRTUAL_P (n2->decl))
|
|
395 return return_false_with_msg ("virtual flag mismatch");
|
|
396 if (DECL_VIRTUAL_P (n1->decl) && is_a <cgraph_node *> (n1)
|
|
397 && (DECL_FINAL_P (n1->decl) != DECL_FINAL_P (n2->decl)))
|
|
398 return return_false_with_msg ("final flag mismatch");
|
|
399 }
|
|
400 return true;
|
|
401 }
|
|
402
|
|
403 /* Hash properties that are compared by compare_referenced_symbol_properties. */
|
|
404
|
|
405 void
|
|
406 sem_item::hash_referenced_symbol_properties (symtab_node *ref,
|
|
407 inchash::hash &hstate,
|
|
408 bool address)
|
|
409 {
|
|
410 if (is_a <cgraph_node *> (ref))
|
|
411 {
|
|
412 if ((type != FUNC || address || !opt_for_fn (decl, optimize_size))
|
|
413 && !opt_for_fn (ref->decl, optimize_size)
|
|
414 && !DECL_UNINLINABLE (ref->decl))
|
|
415 {
|
|
416 hstate.add_flag (DECL_DISREGARD_INLINE_LIMITS (ref->decl));
|
|
417 hstate.add_flag (DECL_DECLARED_INLINE_P (ref->decl));
|
|
418 }
|
|
419 hstate.add_flag (DECL_IS_OPERATOR_NEW (ref->decl));
|
|
420 }
|
|
421 else if (is_a <varpool_node *> (ref))
|
|
422 {
|
|
423 hstate.add_flag (DECL_VIRTUAL_P (ref->decl));
|
|
424 if (address)
|
|
425 hstate.add_int (DECL_ALIGN (ref->decl));
|
|
426 }
|
|
427 }
|
|
428
|
|
429
|
|
430 /* For a given symbol table nodes N1 and N2, we check that FUNCTION_DECLs
|
|
431 point to a same function. Comparison can be skipped if IGNORED_NODES
|
|
432 contains these nodes. ADDRESS indicate if address is taken. */
|
|
433
|
|
434 bool
|
|
435 sem_item::compare_symbol_references (
|
|
436 hash_map <symtab_node *, sem_item *> &ignored_nodes,
|
|
437 symtab_node *n1, symtab_node *n2, bool address)
|
|
438 {
|
|
439 enum availability avail1, avail2;
|
|
440
|
|
441 if (n1 == n2)
|
|
442 return true;
|
|
443
|
|
444 /* Never match variable and function. */
|
|
445 if (is_a <varpool_node *> (n1) != is_a <varpool_node *> (n2))
|
|
446 return false;
|
|
447
|
|
448 if (!compare_referenced_symbol_properties (node, n1, n2, address))
|
|
449 return false;
|
|
450 if (address && n1->equal_address_to (n2) == 1)
|
|
451 return true;
|
|
452 if (!address && n1->semantically_equivalent_p (n2))
|
|
453 return true;
|
|
454
|
|
455 n1 = n1->ultimate_alias_target (&avail1);
|
|
456 n2 = n2->ultimate_alias_target (&avail2);
|
|
457
|
|
458 if (avail1 > AVAIL_INTERPOSABLE && ignored_nodes.get (n1)
|
|
459 && avail2 > AVAIL_INTERPOSABLE && ignored_nodes.get (n2))
|
|
460 return true;
|
|
461
|
|
462 return return_false_with_msg ("different references");
|
|
463 }
|
|
464
|
|
465 /* If cgraph edges E1 and E2 are indirect calls, verify that
|
|
466 ECF flags are the same. */
|
|
467
|
|
468 bool sem_function::compare_edge_flags (cgraph_edge *e1, cgraph_edge *e2)
|
|
469 {
|
|
470 if (e1->indirect_info && e2->indirect_info)
|
|
471 {
|
|
472 int e1_flags = e1->indirect_info->ecf_flags;
|
|
473 int e2_flags = e2->indirect_info->ecf_flags;
|
|
474
|
|
475 if (e1_flags != e2_flags)
|
|
476 return return_false_with_msg ("ICF flags are different");
|
|
477 }
|
|
478 else if (e1->indirect_info || e2->indirect_info)
|
|
479 return false;
|
|
480
|
|
481 return true;
|
|
482 }
|
|
483
|
|
484 /* Return true if parameter I may be used. */
|
|
485
|
|
486 bool
|
|
487 sem_function::param_used_p (unsigned int i)
|
|
488 {
|
|
489 if (ipa_node_params_sum == NULL)
|
|
490 return true;
|
|
491
|
|
492 struct ipa_node_params *parms_info = IPA_NODE_REF (get_node ());
|
|
493
|
|
494 if (vec_safe_length (parms_info->descriptors) <= i)
|
|
495 return true;
|
|
496
|
|
497 return ipa_is_param_used (IPA_NODE_REF (get_node ()), i);
|
|
498 }
|
|
499
|
|
500 /* Perform additional check needed to match types function parameters that are
|
|
501 used. Unlike for normal decls it matters if type is TYPE_RESTRICT and we
|
|
502 make an assumption that REFERENCE_TYPE parameters are always non-NULL. */
|
|
503
|
|
504 bool
|
|
505 sem_function::compatible_parm_types_p (tree parm1, tree parm2)
|
|
506 {
|
|
507 /* Be sure that parameters are TBAA compatible. */
|
|
508 if (!func_checker::compatible_types_p (parm1, parm2))
|
|
509 return return_false_with_msg ("parameter type is not compatible");
|
|
510
|
|
511 if (POINTER_TYPE_P (parm1)
|
|
512 && (TYPE_RESTRICT (parm1) != TYPE_RESTRICT (parm2)))
|
|
513 return return_false_with_msg ("argument restrict flag mismatch");
|
|
514
|
|
515 /* nonnull_arg_p implies non-zero range to REFERENCE types. */
|
|
516 if (POINTER_TYPE_P (parm1)
|
|
517 && TREE_CODE (parm1) != TREE_CODE (parm2)
|
|
518 && opt_for_fn (decl, flag_delete_null_pointer_checks))
|
|
519 return return_false_with_msg ("pointer wrt reference mismatch");
|
|
520
|
|
521 return true;
|
|
522 }
|
|
523
|
|
524 /* Fast equality function based on knowledge known in WPA. */
|
|
525
|
|
526 bool
|
|
527 sem_function::equals_wpa (sem_item *item,
|
|
528 hash_map <symtab_node *, sem_item *> &ignored_nodes)
|
|
529 {
|
|
530 gcc_assert (item->type == FUNC);
|
|
531 cgraph_node *cnode = dyn_cast <cgraph_node *> (node);
|
|
532 cgraph_node *cnode2 = dyn_cast <cgraph_node *> (item->node);
|
|
533
|
|
534 m_compared_func = static_cast<sem_function *> (item);
|
|
535
|
|
536 if (cnode->thunk.thunk_p != cnode2->thunk.thunk_p)
|
|
537 return return_false_with_msg ("thunk_p mismatch");
|
|
538
|
|
539 if (cnode->thunk.thunk_p)
|
|
540 {
|
|
541 if (cnode->thunk.fixed_offset != cnode2->thunk.fixed_offset)
|
|
542 return return_false_with_msg ("thunk fixed_offset mismatch");
|
|
543 if (cnode->thunk.virtual_value != cnode2->thunk.virtual_value)
|
|
544 return return_false_with_msg ("thunk virtual_value mismatch");
|
131
|
545 if (cnode->thunk.indirect_offset != cnode2->thunk.indirect_offset)
|
|
546 return return_false_with_msg ("thunk indirect_offset mismatch");
|
111
|
547 if (cnode->thunk.this_adjusting != cnode2->thunk.this_adjusting)
|
|
548 return return_false_with_msg ("thunk this_adjusting mismatch");
|
|
549 if (cnode->thunk.virtual_offset_p != cnode2->thunk.virtual_offset_p)
|
|
550 return return_false_with_msg ("thunk virtual_offset_p mismatch");
|
|
551 if (cnode->thunk.add_pointer_bounds_args
|
|
552 != cnode2->thunk.add_pointer_bounds_args)
|
|
553 return return_false_with_msg ("thunk add_pointer_bounds_args mismatch");
|
|
554 }
|
|
555
|
|
556 /* Compare special function DECL attributes. */
|
|
557 if (DECL_FUNCTION_PERSONALITY (decl)
|
|
558 != DECL_FUNCTION_PERSONALITY (item->decl))
|
|
559 return return_false_with_msg ("function personalities are different");
|
|
560
|
|
561 if (DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (decl)
|
|
562 != DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (item->decl))
|
|
563 return return_false_with_msg ("intrument function entry exit "
|
|
564 "attributes are different");
|
|
565
|
|
566 if (DECL_NO_LIMIT_STACK (decl) != DECL_NO_LIMIT_STACK (item->decl))
|
|
567 return return_false_with_msg ("no stack limit attributes are different");
|
|
568
|
|
569 if (DECL_CXX_CONSTRUCTOR_P (decl) != DECL_CXX_CONSTRUCTOR_P (item->decl))
|
|
570 return return_false_with_msg ("DECL_CXX_CONSTRUCTOR mismatch");
|
|
571
|
|
572 if (DECL_CXX_DESTRUCTOR_P (decl) != DECL_CXX_DESTRUCTOR_P (item->decl))
|
|
573 return return_false_with_msg ("DECL_CXX_DESTRUCTOR mismatch");
|
|
574
|
|
575 /* TODO: pure/const flags mostly matters only for references, except for
|
|
576 the fact that codegen takes LOOPING flag as a hint that loops are
|
|
577 finite. We may arrange the code to always pick leader that has least
|
|
578 specified flags and then this can go into comparing symbol properties. */
|
|
579 if (flags_from_decl_or_type (decl) != flags_from_decl_or_type (item->decl))
|
|
580 return return_false_with_msg ("decl_or_type flags are different");
|
|
581
|
|
582 /* Do not match polymorphic constructors of different types. They calls
|
|
583 type memory location for ipa-polymorphic-call and we do not want
|
|
584 it to get confused by wrong type. */
|
|
585 if (DECL_CXX_CONSTRUCTOR_P (decl)
|
|
586 && TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE)
|
|
587 {
|
|
588 if (TREE_CODE (TREE_TYPE (item->decl)) != METHOD_TYPE)
|
|
589 return return_false_with_msg ("DECL_CXX_CONSTURCTOR type mismatch");
|
|
590 else if (!func_checker::compatible_polymorphic_types_p
|
|
591 (TYPE_METHOD_BASETYPE (TREE_TYPE (decl)),
|
|
592 TYPE_METHOD_BASETYPE (TREE_TYPE (item->decl)), false))
|
|
593 return return_false_with_msg ("ctor polymorphic type mismatch");
|
|
594 }
|
|
595
|
|
596 /* Checking function TARGET and OPTIMIZATION flags. */
|
|
597 cl_target_option *tar1 = target_opts_for_fn (decl);
|
|
598 cl_target_option *tar2 = target_opts_for_fn (item->decl);
|
|
599
|
|
600 if (tar1 != tar2 && !cl_target_option_eq (tar1, tar2))
|
|
601 {
|
|
602 if (dump_file && (dump_flags & TDF_DETAILS))
|
|
603 {
|
|
604 fprintf (dump_file, "target flags difference");
|
|
605 cl_target_option_print_diff (dump_file, 2, tar1, tar2);
|
|
606 }
|
|
607
|
|
608 return return_false_with_msg ("Target flags are different");
|
|
609 }
|
|
610
|
|
611 cl_optimization *opt1 = opts_for_fn (decl);
|
|
612 cl_optimization *opt2 = opts_for_fn (item->decl);
|
|
613
|
131
|
614 if (opt1 != opt2 && !cl_optimization_option_eq (opt1, opt2))
|
111
|
615 {
|
|
616 if (dump_file && (dump_flags & TDF_DETAILS))
|
|
617 {
|
|
618 fprintf (dump_file, "optimization flags difference");
|
|
619 cl_optimization_print_diff (dump_file, 2, opt1, opt2);
|
|
620 }
|
|
621
|
|
622 return return_false_with_msg ("optimization flags are different");
|
|
623 }
|
|
624
|
|
625 /* Result type checking. */
|
|
626 if (!func_checker::compatible_types_p
|
|
627 (TREE_TYPE (TREE_TYPE (decl)),
|
|
628 TREE_TYPE (TREE_TYPE (m_compared_func->decl))))
|
|
629 return return_false_with_msg ("result types are different");
|
|
630
|
|
631 /* Checking types of arguments. */
|
|
632 tree list1 = TYPE_ARG_TYPES (TREE_TYPE (decl)),
|
|
633 list2 = TYPE_ARG_TYPES (TREE_TYPE (m_compared_func->decl));
|
|
634 for (unsigned i = 0; list1 && list2;
|
|
635 list1 = TREE_CHAIN (list1), list2 = TREE_CHAIN (list2), i++)
|
|
636 {
|
|
637 tree parm1 = TREE_VALUE (list1);
|
|
638 tree parm2 = TREE_VALUE (list2);
|
|
639
|
|
640 /* This guard is here for function pointer with attributes (pr59927.c). */
|
|
641 if (!parm1 || !parm2)
|
|
642 return return_false_with_msg ("NULL argument type");
|
|
643
|
|
644 /* Verify that types are compatible to ensure that both functions
|
|
645 have same calling conventions. */
|
|
646 if (!types_compatible_p (parm1, parm2))
|
|
647 return return_false_with_msg ("parameter types are not compatible");
|
|
648
|
|
649 if (!param_used_p (i))
|
|
650 continue;
|
|
651
|
|
652 /* Perform additional checks for used parameters. */
|
|
653 if (!compatible_parm_types_p (parm1, parm2))
|
|
654 return false;
|
|
655 }
|
|
656
|
|
657 if (list1 || list2)
|
|
658 return return_false_with_msg ("Mismatched number of parameters");
|
|
659
|
|
660 if (node->num_references () != item->node->num_references ())
|
|
661 return return_false_with_msg ("different number of references");
|
|
662
|
|
663 /* Checking function attributes.
|
|
664 This is quadratic in number of attributes */
|
|
665 if (comp_type_attributes (TREE_TYPE (decl),
|
|
666 TREE_TYPE (item->decl)) != 1)
|
|
667 return return_false_with_msg ("different type attributes");
|
131
|
668 if (!attribute_list_equal (DECL_ATTRIBUTES (decl),
|
|
669 DECL_ATTRIBUTES (item->decl)))
|
111
|
670 return return_false_with_msg ("different decl attributes");
|
|
671
|
|
672 /* The type of THIS pointer type memory location for
|
|
673 ipa-polymorphic-call-analysis. */
|
|
674 if (opt_for_fn (decl, flag_devirtualize)
|
|
675 && (TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE
|
|
676 || TREE_CODE (TREE_TYPE (item->decl)) == METHOD_TYPE)
|
|
677 && param_used_p (0)
|
|
678 && compare_polymorphic_p ())
|
|
679 {
|
|
680 if (TREE_CODE (TREE_TYPE (decl)) != TREE_CODE (TREE_TYPE (item->decl)))
|
|
681 return return_false_with_msg ("METHOD_TYPE and FUNCTION_TYPE mismatch");
|
|
682 if (!func_checker::compatible_polymorphic_types_p
|
|
683 (TYPE_METHOD_BASETYPE (TREE_TYPE (decl)),
|
|
684 TYPE_METHOD_BASETYPE (TREE_TYPE (item->decl)), false))
|
|
685 return return_false_with_msg ("THIS pointer ODR type mismatch");
|
|
686 }
|
|
687
|
|
688 ipa_ref *ref = NULL, *ref2 = NULL;
|
|
689 for (unsigned i = 0; node->iterate_reference (i, ref); i++)
|
|
690 {
|
|
691 item->node->iterate_reference (i, ref2);
|
|
692
|
|
693 if (ref->use != ref2->use)
|
|
694 return return_false_with_msg ("reference use mismatch");
|
|
695
|
|
696 if (!compare_symbol_references (ignored_nodes, ref->referred,
|
|
697 ref2->referred,
|
|
698 ref->address_matters_p ()))
|
|
699 return false;
|
|
700 }
|
|
701
|
|
702 cgraph_edge *e1 = dyn_cast <cgraph_node *> (node)->callees;
|
|
703 cgraph_edge *e2 = dyn_cast <cgraph_node *> (item->node)->callees;
|
|
704
|
|
705 while (e1 && e2)
|
|
706 {
|
|
707 if (!compare_symbol_references (ignored_nodes, e1->callee,
|
|
708 e2->callee, false))
|
|
709 return false;
|
|
710 if (!compare_edge_flags (e1, e2))
|
|
711 return false;
|
|
712
|
|
713 e1 = e1->next_callee;
|
|
714 e2 = e2->next_callee;
|
|
715 }
|
|
716
|
|
717 if (e1 || e2)
|
|
718 return return_false_with_msg ("different number of calls");
|
|
719
|
|
720 e1 = dyn_cast <cgraph_node *> (node)->indirect_calls;
|
|
721 e2 = dyn_cast <cgraph_node *> (item->node)->indirect_calls;
|
|
722
|
|
723 while (e1 && e2)
|
|
724 {
|
|
725 if (!compare_edge_flags (e1, e2))
|
|
726 return false;
|
|
727
|
|
728 e1 = e1->next_callee;
|
|
729 e2 = e2->next_callee;
|
|
730 }
|
|
731
|
|
732 if (e1 || e2)
|
|
733 return return_false_with_msg ("different number of indirect calls");
|
|
734
|
|
735 return true;
|
|
736 }
|
|
737
|
|
738 /* Update hash by address sensitive references. We iterate over all
|
|
739 sensitive references (address_matters_p) and we hash ultime alias
|
|
740 target of these nodes, which can improve a semantic item hash.
|
|
741
|
|
742 Also hash in referenced symbols properties. This can be done at any time
|
|
743 (as the properties should not change), but it is convenient to do it here
|
|
744 while we walk the references anyway. */
|
|
745
|
|
746 void
|
|
747 sem_item::update_hash_by_addr_refs (hash_map <symtab_node *,
|
|
748 sem_item *> &m_symtab_node_map)
|
|
749 {
|
|
750 ipa_ref* ref;
|
|
751 inchash::hash hstate (get_hash ());
|
|
752
|
|
753 for (unsigned i = 0; node->iterate_reference (i, ref); i++)
|
|
754 {
|
|
755 hstate.add_int (ref->use);
|
|
756 hash_referenced_symbol_properties (ref->referred, hstate,
|
|
757 ref->use == IPA_REF_ADDR);
|
|
758 if (ref->address_matters_p () || !m_symtab_node_map.get (ref->referred))
|
|
759 hstate.add_int (ref->referred->ultimate_alias_target ()->order);
|
|
760 }
|
|
761
|
|
762 if (is_a <cgraph_node *> (node))
|
|
763 {
|
|
764 for (cgraph_edge *e = dyn_cast <cgraph_node *> (node)->callers; e;
|
|
765 e = e->next_caller)
|
|
766 {
|
|
767 sem_item **result = m_symtab_node_map.get (e->callee);
|
|
768 hash_referenced_symbol_properties (e->callee, hstate, false);
|
|
769 if (!result)
|
|
770 hstate.add_int (e->callee->ultimate_alias_target ()->order);
|
|
771 }
|
|
772 }
|
|
773
|
|
774 set_hash (hstate.end ());
|
|
775 }
|
|
776
|
|
777 /* Update hash by computed local hash values taken from different
|
|
778 semantic items.
|
|
779 TODO: stronger SCC based hashing would be desirable here. */
|
|
780
|
|
781 void
|
|
782 sem_item::update_hash_by_local_refs (hash_map <symtab_node *,
|
|
783 sem_item *> &m_symtab_node_map)
|
|
784 {
|
|
785 ipa_ref* ref;
|
|
786 inchash::hash state (get_hash ());
|
|
787
|
|
788 for (unsigned j = 0; node->iterate_reference (j, ref); j++)
|
|
789 {
|
|
790 sem_item **result = m_symtab_node_map.get (ref->referring);
|
|
791 if (result)
|
|
792 state.merge_hash ((*result)->get_hash ());
|
|
793 }
|
|
794
|
|
795 if (type == FUNC)
|
|
796 {
|
|
797 for (cgraph_edge *e = dyn_cast <cgraph_node *> (node)->callees; e;
|
|
798 e = e->next_callee)
|
|
799 {
|
|
800 sem_item **result = m_symtab_node_map.get (e->caller);
|
|
801 if (result)
|
|
802 state.merge_hash ((*result)->get_hash ());
|
|
803 }
|
|
804 }
|
|
805
|
|
806 global_hash = state.end ();
|
|
807 }
|
|
808
|
|
809 /* Returns true if the item equals to ITEM given as argument. */
|
|
810
|
|
811 bool
|
|
812 sem_function::equals (sem_item *item,
|
|
813 hash_map <symtab_node *, sem_item *> &)
|
|
814 {
|
|
815 gcc_assert (item->type == FUNC);
|
|
816 bool eq = equals_private (item);
|
|
817
|
|
818 if (m_checker != NULL)
|
|
819 {
|
|
820 delete m_checker;
|
|
821 m_checker = NULL;
|
|
822 }
|
|
823
|
|
824 if (dump_file && (dump_flags & TDF_DETAILS))
|
|
825 fprintf (dump_file,
|
|
826 "Equals called for: %s:%s with result: %s\n\n",
|
|
827 node->dump_name (),
|
|
828 item->node->dump_name (),
|
|
829 eq ? "true" : "false");
|
|
830
|
|
831 return eq;
|
|
832 }
|
|
833
|
|
834 /* Processes function equality comparison. */
|
|
835
|
|
836 bool
|
|
837 sem_function::equals_private (sem_item *item)
|
|
838 {
|
|
839 if (item->type != FUNC)
|
|
840 return false;
|
|
841
|
|
842 basic_block bb1, bb2;
|
|
843 edge e1, e2;
|
|
844 edge_iterator ei1, ei2;
|
|
845 bool result = true;
|
|
846 tree arg1, arg2;
|
|
847
|
|
848 m_compared_func = static_cast<sem_function *> (item);
|
|
849
|
|
850 gcc_assert (decl != item->decl);
|
|
851
|
|
852 if (bb_sorted.length () != m_compared_func->bb_sorted.length ()
|
|
853 || edge_count != m_compared_func->edge_count
|
|
854 || cfg_checksum != m_compared_func->cfg_checksum)
|
|
855 return return_false ();
|
|
856
|
|
857 m_checker = new func_checker (decl, m_compared_func->decl,
|
|
858 compare_polymorphic_p (),
|
|
859 false,
|
|
860 &refs_set,
|
|
861 &m_compared_func->refs_set);
|
|
862 arg1 = DECL_ARGUMENTS (decl);
|
|
863 arg2 = DECL_ARGUMENTS (m_compared_func->decl);
|
|
864 for (unsigned i = 0;
|
|
865 arg1 && arg2; arg1 = DECL_CHAIN (arg1), arg2 = DECL_CHAIN (arg2), i++)
|
|
866 {
|
|
867 if (!types_compatible_p (TREE_TYPE (arg1), TREE_TYPE (arg2)))
|
|
868 return return_false_with_msg ("argument types are not compatible");
|
|
869 if (!param_used_p (i))
|
|
870 continue;
|
|
871 /* Perform additional checks for used parameters. */
|
|
872 if (!compatible_parm_types_p (TREE_TYPE (arg1), TREE_TYPE (arg2)))
|
|
873 return false;
|
|
874 if (!m_checker->compare_decl (arg1, arg2))
|
|
875 return return_false ();
|
|
876 }
|
|
877 if (arg1 || arg2)
|
|
878 return return_false_with_msg ("Mismatched number of arguments");
|
|
879
|
|
880 if (!dyn_cast <cgraph_node *> (node)->has_gimple_body_p ())
|
|
881 return true;
|
|
882
|
|
883 /* Fill-up label dictionary. */
|
|
884 for (unsigned i = 0; i < bb_sorted.length (); ++i)
|
|
885 {
|
|
886 m_checker->parse_labels (bb_sorted[i]);
|
|
887 m_checker->parse_labels (m_compared_func->bb_sorted[i]);
|
|
888 }
|
|
889
|
|
890 /* Checking all basic blocks. */
|
|
891 for (unsigned i = 0; i < bb_sorted.length (); ++i)
|
|
892 if(!m_checker->compare_bb (bb_sorted[i], m_compared_func->bb_sorted[i]))
|
|
893 return return_false();
|
|
894
|
|
895 dump_message ("All BBs are equal\n");
|
|
896
|
|
897 auto_vec <int> bb_dict;
|
|
898
|
|
899 /* Basic block edges check. */
|
|
900 for (unsigned i = 0; i < bb_sorted.length (); ++i)
|
|
901 {
|
|
902 bb1 = bb_sorted[i]->bb;
|
|
903 bb2 = m_compared_func->bb_sorted[i]->bb;
|
|
904
|
|
905 ei2 = ei_start (bb2->preds);
|
|
906
|
|
907 for (ei1 = ei_start (bb1->preds); ei_cond (ei1, &e1); ei_next (&ei1))
|
|
908 {
|
|
909 ei_cond (ei2, &e2);
|
|
910
|
|
911 if (e1->flags != e2->flags)
|
|
912 return return_false_with_msg ("flags comparison returns false");
|
|
913
|
|
914 if (!bb_dict_test (&bb_dict, e1->src->index, e2->src->index))
|
|
915 return return_false_with_msg ("edge comparison returns false");
|
|
916
|
|
917 if (!bb_dict_test (&bb_dict, e1->dest->index, e2->dest->index))
|
|
918 return return_false_with_msg ("BB comparison returns false");
|
|
919
|
|
920 if (!m_checker->compare_edge (e1, e2))
|
|
921 return return_false_with_msg ("edge comparison returns false");
|
|
922
|
|
923 ei_next (&ei2);
|
|
924 }
|
|
925 }
|
|
926
|
|
927 /* Basic block PHI nodes comparison. */
|
|
928 for (unsigned i = 0; i < bb_sorted.length (); i++)
|
|
929 if (!compare_phi_node (bb_sorted[i]->bb, m_compared_func->bb_sorted[i]->bb))
|
|
930 return return_false_with_msg ("PHI node comparison returns false");
|
|
931
|
|
932 return result;
|
|
933 }
|
|
934
|
|
935 /* Set LOCAL_P of NODE to true if DATA is non-NULL.
|
|
936 Helper for call_for_symbol_thunks_and_aliases. */
|
|
937
|
|
938 static bool
|
|
939 set_local (cgraph_node *node, void *data)
|
|
940 {
|
|
941 node->local.local = data != NULL;
|
|
942 return false;
|
|
943 }
|
|
944
|
|
945 /* TREE_ADDRESSABLE of NODE to true.
|
|
946 Helper for call_for_symbol_thunks_and_aliases. */
|
|
947
|
|
948 static bool
|
|
949 set_addressable (varpool_node *node, void *)
|
|
950 {
|
|
951 TREE_ADDRESSABLE (node->decl) = 1;
|
|
952 return false;
|
|
953 }
|
|
954
|
|
955 /* Clear DECL_RTL of NODE.
|
|
956 Helper for call_for_symbol_thunks_and_aliases. */
|
|
957
|
|
958 static bool
|
|
959 clear_decl_rtl (symtab_node *node, void *)
|
|
960 {
|
|
961 SET_DECL_RTL (node->decl, NULL);
|
|
962 return false;
|
|
963 }
|
|
964
|
|
965 /* Redirect all callers of N and its aliases to TO. Remove aliases if
|
|
966 possible. Return number of redirections made. */
|
|
967
|
|
968 static int
|
|
969 redirect_all_callers (cgraph_node *n, cgraph_node *to)
|
|
970 {
|
|
971 int nredirected = 0;
|
|
972 ipa_ref *ref;
|
|
973 cgraph_edge *e = n->callers;
|
|
974
|
|
975 while (e)
|
|
976 {
|
|
977 /* Redirecting thunks to interposable symbols or symbols in other sections
|
|
978 may not be supported by target output code. Play safe for now and
|
|
979 punt on redirection. */
|
|
980 if (!e->caller->thunk.thunk_p)
|
|
981 {
|
|
982 struct cgraph_edge *nexte = e->next_caller;
|
|
983 e->redirect_callee (to);
|
|
984 e = nexte;
|
|
985 nredirected++;
|
|
986 }
|
|
987 else
|
|
988 e = e->next_callee;
|
|
989 }
|
|
990 for (unsigned i = 0; n->iterate_direct_aliases (i, ref);)
|
|
991 {
|
|
992 bool removed = false;
|
|
993 cgraph_node *n_alias = dyn_cast <cgraph_node *> (ref->referring);
|
|
994
|
|
995 if ((DECL_COMDAT_GROUP (n->decl)
|
|
996 && (DECL_COMDAT_GROUP (n->decl)
|
|
997 == DECL_COMDAT_GROUP (n_alias->decl)))
|
|
998 || (n_alias->get_availability () > AVAIL_INTERPOSABLE
|
|
999 && n->get_availability () > AVAIL_INTERPOSABLE))
|
|
1000 {
|
|
1001 nredirected += redirect_all_callers (n_alias, to);
|
|
1002 if (n_alias->can_remove_if_no_direct_calls_p ()
|
|
1003 && !n_alias->call_for_symbol_and_aliases (cgraph_node::has_thunk_p,
|
|
1004 NULL, true)
|
|
1005 && !n_alias->has_aliases_p ())
|
|
1006 n_alias->remove ();
|
|
1007 }
|
|
1008 if (!removed)
|
|
1009 i++;
|
|
1010 }
|
|
1011 return nredirected;
|
|
1012 }
|
|
1013
|
|
1014 /* Merges instance with an ALIAS_ITEM, where alias, thunk or redirection can
|
|
1015 be applied. */
|
|
1016
|
|
1017 bool
|
|
1018 sem_function::merge (sem_item *alias_item)
|
|
1019 {
|
|
1020 gcc_assert (alias_item->type == FUNC);
|
|
1021
|
|
1022 sem_function *alias_func = static_cast<sem_function *> (alias_item);
|
|
1023
|
|
1024 cgraph_node *original = get_node ();
|
|
1025 cgraph_node *local_original = NULL;
|
|
1026 cgraph_node *alias = alias_func->get_node ();
|
|
1027
|
|
1028 bool create_wrapper = false;
|
|
1029 bool create_alias = false;
|
|
1030 bool redirect_callers = false;
|
|
1031 bool remove = false;
|
|
1032
|
|
1033 bool original_discardable = false;
|
|
1034 bool original_discarded = false;
|
|
1035
|
|
1036 bool original_address_matters = original->address_matters_p ();
|
|
1037 bool alias_address_matters = alias->address_matters_p ();
|
|
1038
|
|
1039 if (DECL_EXTERNAL (alias->decl))
|
|
1040 {
|
|
1041 if (dump_file)
|
|
1042 fprintf (dump_file, "Not unifying; alias is external.\n\n");
|
|
1043 return false;
|
|
1044 }
|
|
1045
|
|
1046 if (DECL_NO_INLINE_WARNING_P (original->decl)
|
|
1047 != DECL_NO_INLINE_WARNING_P (alias->decl))
|
|
1048 {
|
|
1049 if (dump_file)
|
|
1050 fprintf (dump_file,
|
|
1051 "Not unifying; "
|
|
1052 "DECL_NO_INLINE_WARNING mismatch.\n\n");
|
|
1053 return false;
|
|
1054 }
|
|
1055
|
|
1056 /* Do not attempt to mix functions from different user sections;
|
|
1057 we do not know what user intends with those. */
|
|
1058 if (((DECL_SECTION_NAME (original->decl) && !original->implicit_section)
|
|
1059 || (DECL_SECTION_NAME (alias->decl) && !alias->implicit_section))
|
|
1060 && DECL_SECTION_NAME (original->decl) != DECL_SECTION_NAME (alias->decl))
|
|
1061 {
|
|
1062 if (dump_file)
|
|
1063 fprintf (dump_file,
|
|
1064 "Not unifying; "
|
|
1065 "original and alias are in different sections.\n\n");
|
|
1066 return false;
|
|
1067 }
|
|
1068
|
131
|
1069 if (!original->in_same_comdat_group_p (alias)
|
|
1070 || original->comdat_local_p ())
|
|
1071 {
|
|
1072 if (dump_file)
|
|
1073 fprintf (dump_file,
|
|
1074 "Not unifying; alias nor wrapper cannot be created; "
|
|
1075 "across comdat group boundary\n\n");
|
|
1076
|
|
1077 return false;
|
|
1078 }
|
|
1079
|
111
|
1080 /* See if original is in a section that can be discarded if the main
|
|
1081 symbol is not used. */
|
|
1082
|
|
1083 if (original->can_be_discarded_p ())
|
|
1084 original_discardable = true;
|
|
1085 /* Also consider case where we have resolution info and we know that
|
|
1086 original's definition is not going to be used. In this case we can not
|
|
1087 create alias to original. */
|
|
1088 if (node->resolution != LDPR_UNKNOWN
|
|
1089 && !decl_binds_to_current_def_p (node->decl))
|
|
1090 original_discardable = original_discarded = true;
|
|
1091
|
|
1092 /* Creating a symtab alias is the optimal way to merge.
|
|
1093 It however can not be used in the following cases:
|
|
1094
|
|
1095 1) if ORIGINAL and ALIAS may be possibly compared for address equality.
|
|
1096 2) if ORIGINAL is in a section that may be discarded by linker or if
|
|
1097 it is an external functions where we can not create an alias
|
|
1098 (ORIGINAL_DISCARDABLE)
|
|
1099 3) if target do not support symbol aliases.
|
|
1100 4) original and alias lie in different comdat groups.
|
|
1101
|
|
1102 If we can not produce alias, we will turn ALIAS into WRAPPER of ORIGINAL
|
|
1103 and/or redirect all callers from ALIAS to ORIGINAL. */
|
|
1104 if ((original_address_matters && alias_address_matters)
|
|
1105 || (original_discardable
|
|
1106 && (!DECL_COMDAT_GROUP (alias->decl)
|
|
1107 || (DECL_COMDAT_GROUP (alias->decl)
|
|
1108 != DECL_COMDAT_GROUP (original->decl))))
|
|
1109 || original_discarded
|
|
1110 || !sem_item::target_supports_symbol_aliases_p ()
|
|
1111 || DECL_COMDAT_GROUP (alias->decl) != DECL_COMDAT_GROUP (original->decl))
|
|
1112 {
|
|
1113 /* First see if we can produce wrapper. */
|
|
1114
|
|
1115 /* Symbol properties that matter for references must be preserved.
|
|
1116 TODO: We can produce wrapper, but we need to produce alias of ORIGINAL
|
|
1117 with proper properties. */
|
|
1118 if (!sem_item::compare_referenced_symbol_properties (NULL, original, alias,
|
|
1119 alias->address_taken))
|
|
1120 {
|
|
1121 if (dump_file)
|
|
1122 fprintf (dump_file,
|
|
1123 "Wrapper cannot be created because referenced symbol "
|
|
1124 "properties mismatch\n");
|
|
1125 }
|
|
1126 /* Do not turn function in one comdat group into wrapper to another
|
|
1127 comdat group. Other compiler producing the body of the
|
|
1128 another comdat group may make opossite decision and with unfortunate
|
|
1129 linker choices this may close a loop. */
|
|
1130 else if (DECL_COMDAT_GROUP (original->decl)
|
|
1131 && DECL_COMDAT_GROUP (alias->decl)
|
|
1132 && (DECL_COMDAT_GROUP (alias->decl)
|
|
1133 != DECL_COMDAT_GROUP (original->decl)))
|
|
1134 {
|
|
1135 if (dump_file)
|
|
1136 fprintf (dump_file,
|
|
1137 "Wrapper cannot be created because of COMDAT\n");
|
|
1138 }
|
|
1139 else if (DECL_STATIC_CHAIN (alias->decl)
|
|
1140 || DECL_STATIC_CHAIN (original->decl))
|
|
1141 {
|
|
1142 if (dump_file)
|
|
1143 fprintf (dump_file,
|
|
1144 "Cannot create wrapper of nested function.\n");
|
|
1145 }
|
|
1146 /* TODO: We can also deal with variadic functions never calling
|
|
1147 VA_START. */
|
|
1148 else if (stdarg_p (TREE_TYPE (alias->decl)))
|
|
1149 {
|
|
1150 if (dump_file)
|
|
1151 fprintf (dump_file,
|
|
1152 "can not create wrapper of stdarg function.\n");
|
|
1153 }
|
|
1154 else if (ipa_fn_summaries
|
131
|
1155 && ipa_fn_summaries->get (alias) != NULL
|
111
|
1156 && ipa_fn_summaries->get (alias)->self_size <= 2)
|
|
1157 {
|
|
1158 if (dump_file)
|
|
1159 fprintf (dump_file, "Wrapper creation is not "
|
|
1160 "profitable (function is too small).\n");
|
|
1161 }
|
|
1162 /* If user paid attention to mark function noinline, assume it is
|
|
1163 somewhat special and do not try to turn it into a wrapper that can
|
|
1164 not be undone by inliner. */
|
|
1165 else if (lookup_attribute ("noinline", DECL_ATTRIBUTES (alias->decl)))
|
|
1166 {
|
|
1167 if (dump_file)
|
|
1168 fprintf (dump_file, "Wrappers are not created for noinline.\n");
|
|
1169 }
|
|
1170 else
|
|
1171 create_wrapper = true;
|
|
1172
|
|
1173 /* We can redirect local calls in the case both alias and orignal
|
|
1174 are not interposable. */
|
|
1175 redirect_callers
|
|
1176 = alias->get_availability () > AVAIL_INTERPOSABLE
|
131
|
1177 && original->get_availability () > AVAIL_INTERPOSABLE;
|
111
|
1178 /* TODO: We can redirect, but we need to produce alias of ORIGINAL
|
|
1179 with proper properties. */
|
|
1180 if (!sem_item::compare_referenced_symbol_properties (NULL, original, alias,
|
|
1181 alias->address_taken))
|
|
1182 redirect_callers = false;
|
|
1183
|
|
1184 if (!redirect_callers && !create_wrapper)
|
|
1185 {
|
|
1186 if (dump_file)
|
|
1187 fprintf (dump_file, "Not unifying; can not redirect callers nor "
|
|
1188 "produce wrapper\n\n");
|
|
1189 return false;
|
|
1190 }
|
|
1191
|
|
1192 /* Work out the symbol the wrapper should call.
|
|
1193 If ORIGINAL is interposable, we need to call a local alias.
|
|
1194 Also produce local alias (if possible) as an optimization.
|
|
1195
|
|
1196 Local aliases can not be created inside comdat groups because that
|
|
1197 prevents inlining. */
|
|
1198 if (!original_discardable && !original->get_comdat_group ())
|
|
1199 {
|
|
1200 local_original
|
|
1201 = dyn_cast <cgraph_node *> (original->noninterposable_alias ());
|
|
1202 if (!local_original
|
|
1203 && original->get_availability () > AVAIL_INTERPOSABLE)
|
|
1204 local_original = original;
|
|
1205 }
|
|
1206 /* If we can not use local alias, fallback to the original
|
|
1207 when possible. */
|
|
1208 else if (original->get_availability () > AVAIL_INTERPOSABLE)
|
|
1209 local_original = original;
|
|
1210
|
|
1211 /* If original is COMDAT local, we can not really redirect calls outside
|
|
1212 of its comdat group to it. */
|
|
1213 if (original->comdat_local_p ())
|
|
1214 redirect_callers = false;
|
|
1215 if (!local_original)
|
|
1216 {
|
|
1217 if (dump_file)
|
|
1218 fprintf (dump_file, "Not unifying; "
|
|
1219 "can not produce local alias.\n\n");
|
|
1220 return false;
|
|
1221 }
|
|
1222
|
|
1223 if (!redirect_callers && !create_wrapper)
|
|
1224 {
|
|
1225 if (dump_file)
|
|
1226 fprintf (dump_file, "Not unifying; "
|
|
1227 "can not redirect callers nor produce a wrapper\n\n");
|
|
1228 return false;
|
|
1229 }
|
|
1230 if (!create_wrapper
|
|
1231 && !alias->call_for_symbol_and_aliases (cgraph_node::has_thunk_p,
|
|
1232 NULL, true)
|
|
1233 && !alias->can_remove_if_no_direct_calls_p ())
|
|
1234 {
|
|
1235 if (dump_file)
|
|
1236 fprintf (dump_file, "Not unifying; can not make wrapper and "
|
|
1237 "function has other uses than direct calls\n\n");
|
|
1238 return false;
|
|
1239 }
|
|
1240 }
|
|
1241 else
|
|
1242 create_alias = true;
|
|
1243
|
|
1244 if (redirect_callers)
|
|
1245 {
|
|
1246 int nredirected = redirect_all_callers (alias, local_original);
|
|
1247
|
|
1248 if (nredirected)
|
|
1249 {
|
|
1250 alias->icf_merged = true;
|
|
1251 local_original->icf_merged = true;
|
|
1252
|
|
1253 if (dump_file && nredirected)
|
|
1254 fprintf (dump_file, "%i local calls have been "
|
|
1255 "redirected.\n", nredirected);
|
|
1256 }
|
|
1257
|
|
1258 /* If all callers was redirected, do not produce wrapper. */
|
|
1259 if (alias->can_remove_if_no_direct_calls_p ()
|
|
1260 && !DECL_VIRTUAL_P (alias->decl)
|
|
1261 && !alias->has_aliases_p ())
|
|
1262 {
|
|
1263 create_wrapper = false;
|
|
1264 remove = true;
|
|
1265 }
|
|
1266 gcc_assert (!create_alias);
|
|
1267 }
|
|
1268 else if (create_alias)
|
|
1269 {
|
|
1270 alias->icf_merged = true;
|
|
1271
|
|
1272 /* Remove the function's body. */
|
|
1273 ipa_merge_profiles (original, alias);
|
|
1274 alias->release_body (true);
|
|
1275 alias->reset ();
|
|
1276 /* Notice global symbol possibly produced RTL. */
|
|
1277 ((symtab_node *)alias)->call_for_symbol_and_aliases (clear_decl_rtl,
|
|
1278 NULL, true);
|
|
1279
|
|
1280 /* Create the alias. */
|
|
1281 cgraph_node::create_alias (alias_func->decl, decl);
|
|
1282 alias->resolve_alias (original);
|
|
1283
|
|
1284 original->call_for_symbol_thunks_and_aliases
|
|
1285 (set_local, (void *)(size_t) original->local_p (), true);
|
|
1286
|
|
1287 if (dump_file)
|
|
1288 fprintf (dump_file, "Unified; Function alias has been created.\n\n");
|
|
1289 }
|
|
1290 if (create_wrapper)
|
|
1291 {
|
|
1292 gcc_assert (!create_alias);
|
|
1293 alias->icf_merged = true;
|
|
1294 local_original->icf_merged = true;
|
|
1295
|
|
1296 /* FIXME update local_original counts. */
|
|
1297 ipa_merge_profiles (original, alias, true);
|
|
1298 alias->create_wrapper (local_original);
|
|
1299
|
|
1300 if (dump_file)
|
|
1301 fprintf (dump_file, "Unified; Wrapper has been created.\n\n");
|
|
1302 }
|
|
1303
|
|
1304 /* It's possible that redirection can hit thunks that block
|
|
1305 redirection opportunities. */
|
|
1306 gcc_assert (alias->icf_merged || remove || redirect_callers);
|
|
1307 original->icf_merged = true;
|
|
1308
|
|
1309 /* We use merged flag to track cases where COMDAT function is known to be
|
|
1310 compatible its callers. If we merged in non-COMDAT, we need to give up
|
|
1311 on this optimization. */
|
|
1312 if (original->merged_comdat && !alias->merged_comdat)
|
|
1313 {
|
|
1314 if (dump_file)
|
|
1315 fprintf (dump_file, "Dropping merged_comdat flag.\n\n");
|
|
1316 if (local_original)
|
|
1317 local_original->merged_comdat = false;
|
|
1318 original->merged_comdat = false;
|
|
1319 }
|
|
1320
|
|
1321 if (remove)
|
|
1322 {
|
|
1323 ipa_merge_profiles (original, alias);
|
|
1324 alias->release_body ();
|
|
1325 alias->reset ();
|
|
1326 alias->body_removed = true;
|
|
1327 alias->icf_merged = true;
|
|
1328 if (dump_file)
|
|
1329 fprintf (dump_file, "Unified; Function body was removed.\n");
|
|
1330 }
|
|
1331
|
|
1332 return true;
|
|
1333 }
|
|
1334
|
|
1335 /* Semantic item initialization function. */
|
|
1336
|
|
1337 void
|
|
1338 sem_function::init (void)
|
|
1339 {
|
|
1340 if (in_lto_p)
|
|
1341 get_node ()->get_untransformed_body ();
|
|
1342
|
|
1343 tree fndecl = node->decl;
|
|
1344 function *func = DECL_STRUCT_FUNCTION (fndecl);
|
|
1345
|
|
1346 gcc_assert (func);
|
|
1347 gcc_assert (SSANAMES (func));
|
|
1348
|
|
1349 ssa_names_size = SSANAMES (func)->length ();
|
|
1350 node = node;
|
|
1351
|
|
1352 decl = fndecl;
|
|
1353 region_tree = func->eh->region_tree;
|
|
1354
|
|
1355 /* iterating all function arguments. */
|
|
1356 arg_count = count_formal_params (fndecl);
|
|
1357
|
|
1358 edge_count = n_edges_for_fn (func);
|
|
1359 cgraph_node *cnode = dyn_cast <cgraph_node *> (node);
|
|
1360 if (!cnode->thunk.thunk_p)
|
|
1361 {
|
|
1362 cfg_checksum = coverage_compute_cfg_checksum (func);
|
|
1363
|
|
1364 inchash::hash hstate;
|
|
1365
|
|
1366 basic_block bb;
|
|
1367 FOR_EACH_BB_FN (bb, func)
|
|
1368 {
|
|
1369 unsigned nondbg_stmt_count = 0;
|
|
1370
|
|
1371 edge e;
|
|
1372 for (edge_iterator ei = ei_start (bb->preds); ei_cond (ei, &e);
|
|
1373 ei_next (&ei))
|
|
1374 cfg_checksum = iterative_hash_host_wide_int (e->flags,
|
|
1375 cfg_checksum);
|
|
1376
|
|
1377 for (gimple_stmt_iterator gsi = gsi_start_bb (bb); !gsi_end_p (gsi);
|
|
1378 gsi_next (&gsi))
|
|
1379 {
|
|
1380 gimple *stmt = gsi_stmt (gsi);
|
|
1381
|
|
1382 if (gimple_code (stmt) != GIMPLE_DEBUG
|
|
1383 && gimple_code (stmt) != GIMPLE_PREDICT)
|
|
1384 {
|
|
1385 hash_stmt (stmt, hstate);
|
|
1386 nondbg_stmt_count++;
|
|
1387 }
|
|
1388 }
|
|
1389
|
|
1390 hstate.commit_flag ();
|
|
1391 gcode_hash = hstate.end ();
|
|
1392 bb_sizes.safe_push (nondbg_stmt_count);
|
|
1393
|
|
1394 /* Inserting basic block to hash table. */
|
|
1395 sem_bb *semantic_bb = new sem_bb (bb, nondbg_stmt_count,
|
|
1396 EDGE_COUNT (bb->preds)
|
|
1397 + EDGE_COUNT (bb->succs));
|
|
1398
|
|
1399 bb_sorted.safe_push (semantic_bb);
|
|
1400 }
|
|
1401 }
|
|
1402 else
|
|
1403 {
|
|
1404 cfg_checksum = 0;
|
|
1405 inchash::hash hstate;
|
|
1406 hstate.add_hwi (cnode->thunk.fixed_offset);
|
|
1407 hstate.add_hwi (cnode->thunk.virtual_value);
|
|
1408 hstate.add_flag (cnode->thunk.this_adjusting);
|
|
1409 hstate.add_flag (cnode->thunk.virtual_offset_p);
|
|
1410 hstate.add_flag (cnode->thunk.add_pointer_bounds_args);
|
|
1411 gcode_hash = hstate.end ();
|
|
1412 }
|
|
1413 }
|
|
1414
|
|
1415 /* Accumulate to HSTATE a hash of expression EXP.
|
|
1416 Identical to inchash::add_expr, but guaranteed to be stable across LTO
|
|
1417 and DECL equality classes. */
|
|
1418
|
|
1419 void
|
|
1420 sem_item::add_expr (const_tree exp, inchash::hash &hstate)
|
|
1421 {
|
|
1422 if (exp == NULL_TREE)
|
|
1423 {
|
|
1424 hstate.merge_hash (0);
|
|
1425 return;
|
|
1426 }
|
|
1427
|
|
1428 /* Handled component can be matched in a cureful way proving equivalence
|
|
1429 even if they syntactically differ. Just skip them. */
|
|
1430 STRIP_NOPS (exp);
|
|
1431 while (handled_component_p (exp))
|
|
1432 exp = TREE_OPERAND (exp, 0);
|
|
1433
|
|
1434 enum tree_code code = TREE_CODE (exp);
|
|
1435 hstate.add_int (code);
|
|
1436
|
|
1437 switch (code)
|
|
1438 {
|
|
1439 /* Use inchash::add_expr for everything that is LTO stable. */
|
|
1440 case VOID_CST:
|
|
1441 case INTEGER_CST:
|
|
1442 case REAL_CST:
|
|
1443 case FIXED_CST:
|
|
1444 case STRING_CST:
|
|
1445 case COMPLEX_CST:
|
|
1446 case VECTOR_CST:
|
|
1447 inchash::add_expr (exp, hstate);
|
|
1448 break;
|
|
1449 case CONSTRUCTOR:
|
|
1450 {
|
|
1451 unsigned HOST_WIDE_INT idx;
|
|
1452 tree value;
|
|
1453
|
|
1454 hstate.add_hwi (int_size_in_bytes (TREE_TYPE (exp)));
|
|
1455
|
|
1456 FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (exp), idx, value)
|
|
1457 if (value)
|
|
1458 add_expr (value, hstate);
|
|
1459 break;
|
|
1460 }
|
|
1461 case ADDR_EXPR:
|
|
1462 case FDESC_EXPR:
|
|
1463 add_expr (get_base_address (TREE_OPERAND (exp, 0)), hstate);
|
|
1464 break;
|
|
1465 case SSA_NAME:
|
|
1466 case VAR_DECL:
|
|
1467 case CONST_DECL:
|
|
1468 case PARM_DECL:
|
|
1469 hstate.add_hwi (int_size_in_bytes (TREE_TYPE (exp)));
|
|
1470 break;
|
|
1471 case MEM_REF:
|
|
1472 case POINTER_PLUS_EXPR:
|
|
1473 case MINUS_EXPR:
|
|
1474 case RANGE_EXPR:
|
|
1475 add_expr (TREE_OPERAND (exp, 0), hstate);
|
|
1476 add_expr (TREE_OPERAND (exp, 1), hstate);
|
|
1477 break;
|
|
1478 case PLUS_EXPR:
|
|
1479 {
|
|
1480 inchash::hash one, two;
|
|
1481 add_expr (TREE_OPERAND (exp, 0), one);
|
|
1482 add_expr (TREE_OPERAND (exp, 1), two);
|
|
1483 hstate.add_commutative (one, two);
|
|
1484 }
|
|
1485 break;
|
|
1486 CASE_CONVERT:
|
|
1487 hstate.add_hwi (int_size_in_bytes (TREE_TYPE (exp)));
|
|
1488 return add_expr (TREE_OPERAND (exp, 0), hstate);
|
|
1489 default:
|
|
1490 break;
|
|
1491 }
|
|
1492 }
|
|
1493
|
|
1494 /* Accumulate to HSTATE a hash of type t.
|
|
1495 TYpes that may end up being compatible after LTO type merging needs to have
|
|
1496 the same hash. */
|
|
1497
|
|
1498 void
|
|
1499 sem_item::add_type (const_tree type, inchash::hash &hstate)
|
|
1500 {
|
|
1501 if (type == NULL_TREE)
|
|
1502 {
|
|
1503 hstate.merge_hash (0);
|
|
1504 return;
|
|
1505 }
|
|
1506
|
|
1507 type = TYPE_MAIN_VARIANT (type);
|
|
1508
|
|
1509 hstate.add_int (TYPE_MODE (type));
|
|
1510
|
|
1511 if (TREE_CODE (type) == COMPLEX_TYPE)
|
|
1512 {
|
|
1513 hstate.add_int (COMPLEX_TYPE);
|
|
1514 sem_item::add_type (TREE_TYPE (type), hstate);
|
|
1515 }
|
|
1516 else if (INTEGRAL_TYPE_P (type))
|
|
1517 {
|
|
1518 hstate.add_int (INTEGER_TYPE);
|
|
1519 hstate.add_flag (TYPE_UNSIGNED (type));
|
|
1520 hstate.add_int (TYPE_PRECISION (type));
|
|
1521 }
|
|
1522 else if (VECTOR_TYPE_P (type))
|
|
1523 {
|
|
1524 hstate.add_int (VECTOR_TYPE);
|
|
1525 hstate.add_int (TYPE_PRECISION (type));
|
|
1526 sem_item::add_type (TREE_TYPE (type), hstate);
|
|
1527 }
|
|
1528 else if (TREE_CODE (type) == ARRAY_TYPE)
|
|
1529 {
|
|
1530 hstate.add_int (ARRAY_TYPE);
|
|
1531 /* Do not hash size, so complete and incomplete types can match. */
|
|
1532 sem_item::add_type (TREE_TYPE (type), hstate);
|
|
1533 }
|
|
1534 else if (RECORD_OR_UNION_TYPE_P (type))
|
|
1535 {
|
131
|
1536 /* Incomplete types must be skipped here. */
|
|
1537 if (!COMPLETE_TYPE_P (type))
|
|
1538 {
|
|
1539 hstate.add_int (RECORD_TYPE);
|
|
1540 return;
|
|
1541 }
|
|
1542
|
|
1543 hashval_t *val = m_type_hash_cache.get (type);
|
111
|
1544
|
|
1545 if (!val)
|
|
1546 {
|
|
1547 inchash::hash hstate2;
|
|
1548 unsigned nf;
|
|
1549 tree f;
|
|
1550 hashval_t hash;
|
|
1551
|
|
1552 hstate2.add_int (RECORD_TYPE);
|
|
1553 for (f = TYPE_FIELDS (type), nf = 0; f; f = TREE_CHAIN (f))
|
|
1554 if (TREE_CODE (f) == FIELD_DECL)
|
|
1555 {
|
|
1556 add_type (TREE_TYPE (f), hstate2);
|
|
1557 nf++;
|
|
1558 }
|
|
1559
|
|
1560 hstate2.add_int (nf);
|
|
1561 hash = hstate2.end ();
|
|
1562 hstate.add_hwi (hash);
|
131
|
1563 m_type_hash_cache.put (type, hash);
|
111
|
1564 }
|
|
1565 else
|
|
1566 hstate.add_hwi (*val);
|
|
1567 }
|
|
1568 }
|
|
1569
|
|
1570 /* Improve accumulated hash for HSTATE based on a gimple statement STMT. */
|
|
1571
|
|
1572 void
|
|
1573 sem_function::hash_stmt (gimple *stmt, inchash::hash &hstate)
|
|
1574 {
|
|
1575 enum gimple_code code = gimple_code (stmt);
|
|
1576
|
|
1577 hstate.add_int (code);
|
|
1578
|
|
1579 switch (code)
|
|
1580 {
|
|
1581 case GIMPLE_SWITCH:
|
|
1582 add_expr (gimple_switch_index (as_a <gswitch *> (stmt)), hstate);
|
|
1583 break;
|
|
1584 case GIMPLE_ASSIGN:
|
|
1585 hstate.add_int (gimple_assign_rhs_code (stmt));
|
|
1586 if (commutative_tree_code (gimple_assign_rhs_code (stmt))
|
|
1587 || commutative_ternary_tree_code (gimple_assign_rhs_code (stmt)))
|
|
1588 {
|
|
1589 inchash::hash one, two;
|
|
1590
|
|
1591 add_expr (gimple_assign_rhs1 (stmt), one);
|
|
1592 add_type (TREE_TYPE (gimple_assign_rhs1 (stmt)), one);
|
|
1593 add_expr (gimple_assign_rhs2 (stmt), two);
|
|
1594 hstate.add_commutative (one, two);
|
|
1595 if (commutative_ternary_tree_code (gimple_assign_rhs_code (stmt)))
|
|
1596 {
|
|
1597 add_expr (gimple_assign_rhs3 (stmt), hstate);
|
|
1598 add_type (TREE_TYPE (gimple_assign_rhs3 (stmt)), hstate);
|
|
1599 }
|
|
1600 add_expr (gimple_assign_lhs (stmt), hstate);
|
|
1601 add_type (TREE_TYPE (gimple_assign_lhs (stmt)), two);
|
|
1602 break;
|
|
1603 }
|
|
1604 /* fall through */
|
|
1605 case GIMPLE_CALL:
|
|
1606 case GIMPLE_ASM:
|
|
1607 case GIMPLE_COND:
|
|
1608 case GIMPLE_GOTO:
|
|
1609 case GIMPLE_RETURN:
|
|
1610 /* All these statements are equivalent if their operands are. */
|
|
1611 for (unsigned i = 0; i < gimple_num_ops (stmt); ++i)
|
|
1612 {
|
|
1613 add_expr (gimple_op (stmt, i), hstate);
|
|
1614 if (gimple_op (stmt, i))
|
|
1615 add_type (TREE_TYPE (gimple_op (stmt, i)), hstate);
|
|
1616 }
|
|
1617 /* Consider nocf_check attribute in hash as it affects code
|
|
1618 generation. */
|
|
1619 if (code == GIMPLE_CALL
|
|
1620 && flag_cf_protection & CF_BRANCH)
|
|
1621 hstate.add_flag (gimple_call_nocf_check_p (as_a <gcall *> (stmt)));
|
|
1622 default:
|
|
1623 break;
|
|
1624 }
|
|
1625 }
|
|
1626
|
|
1627
|
|
1628 /* Return true if polymorphic comparison must be processed. */
|
|
1629
|
|
1630 bool
|
|
1631 sem_function::compare_polymorphic_p (void)
|
|
1632 {
|
|
1633 struct cgraph_edge *e;
|
|
1634
|
|
1635 if (!opt_for_fn (get_node ()->decl, flag_devirtualize))
|
|
1636 return false;
|
|
1637 if (get_node ()->indirect_calls != NULL)
|
|
1638 return true;
|
|
1639 /* TODO: We can do simple propagation determining what calls may lead to
|
|
1640 a polymorphic call. */
|
|
1641 for (e = get_node ()->callees; e; e = e->next_callee)
|
|
1642 if (e->callee->definition
|
|
1643 && opt_for_fn (e->callee->decl, flag_devirtualize))
|
|
1644 return true;
|
|
1645 return false;
|
|
1646 }
|
|
1647
|
|
1648 /* For a given call graph NODE, the function constructs new
|
|
1649 semantic function item. */
|
|
1650
|
|
1651 sem_function *
|
|
1652 sem_function::parse (cgraph_node *node, bitmap_obstack *stack)
|
|
1653 {
|
|
1654 tree fndecl = node->decl;
|
|
1655 function *func = DECL_STRUCT_FUNCTION (fndecl);
|
|
1656
|
|
1657 if (!func || (!node->has_gimple_body_p () && !node->thunk.thunk_p))
|
|
1658 return NULL;
|
|
1659
|
|
1660 if (lookup_attribute_by_prefix ("omp ", DECL_ATTRIBUTES (node->decl)) != NULL)
|
|
1661 return NULL;
|
|
1662
|
|
1663 if (lookup_attribute_by_prefix ("oacc ",
|
|
1664 DECL_ATTRIBUTES (node->decl)) != NULL)
|
|
1665 return NULL;
|
|
1666
|
|
1667 /* PR ipa/70306. */
|
|
1668 if (DECL_STATIC_CONSTRUCTOR (node->decl)
|
|
1669 || DECL_STATIC_DESTRUCTOR (node->decl))
|
|
1670 return NULL;
|
|
1671
|
|
1672 sem_function *f = new sem_function (node, stack);
|
|
1673
|
|
1674 f->init ();
|
|
1675
|
|
1676 return f;
|
|
1677 }
|
|
1678
|
|
1679 /* For given basic blocks BB1 and BB2 (from functions FUNC1 and FUNC),
|
|
1680 return true if phi nodes are semantically equivalent in these blocks . */
|
|
1681
|
|
1682 bool
|
|
1683 sem_function::compare_phi_node (basic_block bb1, basic_block bb2)
|
|
1684 {
|
|
1685 gphi_iterator si1, si2;
|
|
1686 gphi *phi1, *phi2;
|
|
1687 unsigned size1, size2, i;
|
|
1688 tree t1, t2;
|
|
1689 edge e1, e2;
|
|
1690
|
|
1691 gcc_assert (bb1 != NULL);
|
|
1692 gcc_assert (bb2 != NULL);
|
|
1693
|
|
1694 si2 = gsi_start_phis (bb2);
|
|
1695 for (si1 = gsi_start_phis (bb1); !gsi_end_p (si1);
|
|
1696 gsi_next (&si1))
|
|
1697 {
|
|
1698 gsi_next_nonvirtual_phi (&si1);
|
|
1699 gsi_next_nonvirtual_phi (&si2);
|
|
1700
|
|
1701 if (gsi_end_p (si1) && gsi_end_p (si2))
|
|
1702 break;
|
|
1703
|
|
1704 if (gsi_end_p (si1) || gsi_end_p (si2))
|
|
1705 return return_false();
|
|
1706
|
|
1707 phi1 = si1.phi ();
|
|
1708 phi2 = si2.phi ();
|
|
1709
|
|
1710 tree phi_result1 = gimple_phi_result (phi1);
|
|
1711 tree phi_result2 = gimple_phi_result (phi2);
|
|
1712
|
|
1713 if (!m_checker->compare_operand (phi_result1, phi_result2))
|
|
1714 return return_false_with_msg ("PHI results are different");
|
|
1715
|
|
1716 size1 = gimple_phi_num_args (phi1);
|
|
1717 size2 = gimple_phi_num_args (phi2);
|
|
1718
|
|
1719 if (size1 != size2)
|
|
1720 return return_false ();
|
|
1721
|
|
1722 for (i = 0; i < size1; ++i)
|
|
1723 {
|
|
1724 t1 = gimple_phi_arg (phi1, i)->def;
|
|
1725 t2 = gimple_phi_arg (phi2, i)->def;
|
|
1726
|
|
1727 if (!m_checker->compare_operand (t1, t2))
|
|
1728 return return_false ();
|
|
1729
|
|
1730 e1 = gimple_phi_arg_edge (phi1, i);
|
|
1731 e2 = gimple_phi_arg_edge (phi2, i);
|
|
1732
|
|
1733 if (!m_checker->compare_edge (e1, e2))
|
|
1734 return return_false ();
|
|
1735 }
|
|
1736
|
|
1737 gsi_next (&si2);
|
|
1738 }
|
|
1739
|
|
1740 return true;
|
|
1741 }
|
|
1742
|
|
1743 /* Returns true if tree T can be compared as a handled component. */
|
|
1744
|
|
1745 bool
|
|
1746 sem_function::icf_handled_component_p (tree t)
|
|
1747 {
|
|
1748 tree_code tc = TREE_CODE (t);
|
|
1749
|
|
1750 return (handled_component_p (t)
|
|
1751 || tc == ADDR_EXPR || tc == MEM_REF || tc == OBJ_TYPE_REF);
|
|
1752 }
|
|
1753
|
|
1754 /* Basic blocks dictionary BB_DICT returns true if SOURCE index BB
|
|
1755 corresponds to TARGET. */
|
|
1756
|
|
1757 bool
|
|
1758 sem_function::bb_dict_test (vec<int> *bb_dict, int source, int target)
|
|
1759 {
|
|
1760 source++;
|
|
1761 target++;
|
|
1762
|
|
1763 if (bb_dict->length () <= (unsigned)source)
|
|
1764 bb_dict->safe_grow_cleared (source + 1);
|
|
1765
|
|
1766 if ((*bb_dict)[source] == 0)
|
|
1767 {
|
|
1768 (*bb_dict)[source] = target;
|
|
1769 return true;
|
|
1770 }
|
|
1771 else
|
|
1772 return (*bb_dict)[source] == target;
|
|
1773 }
|
|
1774
|
|
1775 sem_variable::sem_variable (bitmap_obstack *stack): sem_item (VAR, stack)
|
|
1776 {
|
|
1777 }
|
|
1778
|
|
1779 sem_variable::sem_variable (varpool_node *node, bitmap_obstack *stack)
|
|
1780 : sem_item (VAR, node, stack)
|
|
1781 {
|
|
1782 gcc_checking_assert (node);
|
|
1783 gcc_checking_assert (get_node ());
|
|
1784 }
|
|
1785
|
|
1786 /* Fast equality function based on knowledge known in WPA. */
|
|
1787
|
|
1788 bool
|
|
1789 sem_variable::equals_wpa (sem_item *item,
|
|
1790 hash_map <symtab_node *, sem_item *> &ignored_nodes)
|
|
1791 {
|
|
1792 gcc_assert (item->type == VAR);
|
|
1793
|
|
1794 if (node->num_references () != item->node->num_references ())
|
|
1795 return return_false_with_msg ("different number of references");
|
|
1796
|
|
1797 if (DECL_TLS_MODEL (decl) || DECL_TLS_MODEL (item->decl))
|
|
1798 return return_false_with_msg ("TLS model");
|
|
1799
|
|
1800 /* DECL_ALIGN is safe to merge, because we will always chose the largest
|
|
1801 alignment out of all aliases. */
|
|
1802
|
|
1803 if (DECL_VIRTUAL_P (decl) != DECL_VIRTUAL_P (item->decl))
|
|
1804 return return_false_with_msg ("Virtual flag mismatch");
|
|
1805
|
|
1806 if (DECL_SIZE (decl) != DECL_SIZE (item->decl)
|
|
1807 && ((!DECL_SIZE (decl) || !DECL_SIZE (item->decl))
|
|
1808 || !operand_equal_p (DECL_SIZE (decl),
|
|
1809 DECL_SIZE (item->decl), OEP_ONLY_CONST)))
|
|
1810 return return_false_with_msg ("size mismatch");
|
|
1811
|
|
1812 /* Do not attempt to mix data from different user sections;
|
|
1813 we do not know what user intends with those. */
|
|
1814 if (((DECL_SECTION_NAME (decl) && !node->implicit_section)
|
|
1815 || (DECL_SECTION_NAME (item->decl) && !item->node->implicit_section))
|
|
1816 && DECL_SECTION_NAME (decl) != DECL_SECTION_NAME (item->decl))
|
|
1817 return return_false_with_msg ("user section mismatch");
|
|
1818
|
|
1819 if (DECL_IN_TEXT_SECTION (decl) != DECL_IN_TEXT_SECTION (item->decl))
|
|
1820 return return_false_with_msg ("text section");
|
|
1821
|
|
1822 ipa_ref *ref = NULL, *ref2 = NULL;
|
|
1823 for (unsigned i = 0; node->iterate_reference (i, ref); i++)
|
|
1824 {
|
|
1825 item->node->iterate_reference (i, ref2);
|
|
1826
|
|
1827 if (ref->use != ref2->use)
|
|
1828 return return_false_with_msg ("reference use mismatch");
|
|
1829
|
|
1830 if (!compare_symbol_references (ignored_nodes,
|
|
1831 ref->referred, ref2->referred,
|
|
1832 ref->address_matters_p ()))
|
|
1833 return false;
|
|
1834 }
|
|
1835
|
|
1836 return true;
|
|
1837 }
|
|
1838
|
|
1839 /* Returns true if the item equals to ITEM given as argument. */
|
|
1840
|
|
1841 bool
|
|
1842 sem_variable::equals (sem_item *item,
|
|
1843 hash_map <symtab_node *, sem_item *> &)
|
|
1844 {
|
|
1845 gcc_assert (item->type == VAR);
|
|
1846 bool ret;
|
|
1847
|
|
1848 if (DECL_INITIAL (decl) == error_mark_node && in_lto_p)
|
|
1849 dyn_cast <varpool_node *>(node)->get_constructor ();
|
|
1850 if (DECL_INITIAL (item->decl) == error_mark_node && in_lto_p)
|
|
1851 dyn_cast <varpool_node *>(item->node)->get_constructor ();
|
|
1852
|
|
1853 /* As seen in PR ipa/65303 we have to compare variables types. */
|
|
1854 if (!func_checker::compatible_types_p (TREE_TYPE (decl),
|
|
1855 TREE_TYPE (item->decl)))
|
|
1856 return return_false_with_msg ("variables types are different");
|
|
1857
|
|
1858 ret = sem_variable::equals (DECL_INITIAL (decl),
|
|
1859 DECL_INITIAL (item->node->decl));
|
|
1860 if (dump_file && (dump_flags & TDF_DETAILS))
|
|
1861 fprintf (dump_file,
|
|
1862 "Equals called for vars: %s:%s with result: %s\n\n",
|
|
1863 node->dump_name (), item->node->dump_name (),
|
|
1864 ret ? "true" : "false");
|
|
1865
|
|
1866 return ret;
|
|
1867 }
|
|
1868
|
|
1869 /* Compares trees T1 and T2 for semantic equality. */
|
|
1870
|
|
1871 bool
|
|
1872 sem_variable::equals (tree t1, tree t2)
|
|
1873 {
|
|
1874 if (!t1 || !t2)
|
|
1875 return return_with_debug (t1 == t2);
|
|
1876 if (t1 == t2)
|
|
1877 return true;
|
|
1878 tree_code tc1 = TREE_CODE (t1);
|
|
1879 tree_code tc2 = TREE_CODE (t2);
|
|
1880
|
|
1881 if (tc1 != tc2)
|
|
1882 return return_false_with_msg ("TREE_CODE mismatch");
|
|
1883
|
|
1884 switch (tc1)
|
|
1885 {
|
|
1886 case CONSTRUCTOR:
|
|
1887 {
|
|
1888 vec<constructor_elt, va_gc> *v1, *v2;
|
|
1889 unsigned HOST_WIDE_INT idx;
|
|
1890
|
|
1891 enum tree_code typecode = TREE_CODE (TREE_TYPE (t1));
|
|
1892 if (typecode != TREE_CODE (TREE_TYPE (t2)))
|
|
1893 return return_false_with_msg ("constructor type mismatch");
|
|
1894
|
|
1895 if (typecode == ARRAY_TYPE)
|
|
1896 {
|
|
1897 HOST_WIDE_INT size_1 = int_size_in_bytes (TREE_TYPE (t1));
|
|
1898 /* For arrays, check that the sizes all match. */
|
|
1899 if (TYPE_MODE (TREE_TYPE (t1)) != TYPE_MODE (TREE_TYPE (t2))
|
|
1900 || size_1 == -1
|
|
1901 || size_1 != int_size_in_bytes (TREE_TYPE (t2)))
|
|
1902 return return_false_with_msg ("constructor array size mismatch");
|
|
1903 }
|
|
1904 else if (!func_checker::compatible_types_p (TREE_TYPE (t1),
|
|
1905 TREE_TYPE (t2)))
|
|
1906 return return_false_with_msg ("constructor type incompatible");
|
|
1907
|
|
1908 v1 = CONSTRUCTOR_ELTS (t1);
|
|
1909 v2 = CONSTRUCTOR_ELTS (t2);
|
|
1910 if (vec_safe_length (v1) != vec_safe_length (v2))
|
|
1911 return return_false_with_msg ("constructor number of elts mismatch");
|
|
1912
|
|
1913 for (idx = 0; idx < vec_safe_length (v1); ++idx)
|
|
1914 {
|
|
1915 constructor_elt *c1 = &(*v1)[idx];
|
|
1916 constructor_elt *c2 = &(*v2)[idx];
|
|
1917
|
|
1918 /* Check that each value is the same... */
|
|
1919 if (!sem_variable::equals (c1->value, c2->value))
|
|
1920 return false;
|
|
1921 /* ... and that they apply to the same fields! */
|
|
1922 if (!sem_variable::equals (c1->index, c2->index))
|
|
1923 return false;
|
|
1924 }
|
|
1925 return true;
|
|
1926 }
|
|
1927 case MEM_REF:
|
|
1928 {
|
|
1929 tree x1 = TREE_OPERAND (t1, 0);
|
|
1930 tree x2 = TREE_OPERAND (t2, 0);
|
|
1931 tree y1 = TREE_OPERAND (t1, 1);
|
|
1932 tree y2 = TREE_OPERAND (t2, 1);
|
|
1933
|
|
1934 if (!func_checker::compatible_types_p (TREE_TYPE (x1), TREE_TYPE (x2)))
|
|
1935 return return_false ();
|
|
1936
|
|
1937 /* Type of the offset on MEM_REF does not matter. */
|
|
1938 return return_with_debug (sem_variable::equals (x1, x2)
|
131
|
1939 && known_eq (wi::to_poly_offset (y1),
|
|
1940 wi::to_poly_offset (y2)));
|
111
|
1941 }
|
|
1942 case ADDR_EXPR:
|
|
1943 case FDESC_EXPR:
|
|
1944 {
|
|
1945 tree op1 = TREE_OPERAND (t1, 0);
|
|
1946 tree op2 = TREE_OPERAND (t2, 0);
|
|
1947 return sem_variable::equals (op1, op2);
|
|
1948 }
|
|
1949 /* References to other vars/decls are compared using ipa-ref. */
|
|
1950 case FUNCTION_DECL:
|
|
1951 case VAR_DECL:
|
|
1952 if (decl_in_symtab_p (t1) && decl_in_symtab_p (t2))
|
|
1953 return true;
|
|
1954 return return_false_with_msg ("Declaration mismatch");
|
|
1955 case CONST_DECL:
|
|
1956 /* TODO: We can check CONST_DECL by its DECL_INITIAL, but for that we
|
|
1957 need to process its VAR/FUNCTION references without relying on ipa-ref
|
|
1958 compare. */
|
|
1959 case FIELD_DECL:
|
|
1960 case LABEL_DECL:
|
|
1961 return return_false_with_msg ("Declaration mismatch");
|
|
1962 case INTEGER_CST:
|
|
1963 /* Integer constants are the same only if the same width of type. */
|
|
1964 if (TYPE_PRECISION (TREE_TYPE (t1)) != TYPE_PRECISION (TREE_TYPE (t2)))
|
|
1965 return return_false_with_msg ("INTEGER_CST precision mismatch");
|
|
1966 if (TYPE_MODE (TREE_TYPE (t1)) != TYPE_MODE (TREE_TYPE (t2)))
|
|
1967 return return_false_with_msg ("INTEGER_CST mode mismatch");
|
|
1968 return return_with_debug (tree_int_cst_equal (t1, t2));
|
|
1969 case STRING_CST:
|
|
1970 if (TYPE_MODE (TREE_TYPE (t1)) != TYPE_MODE (TREE_TYPE (t2)))
|
|
1971 return return_false_with_msg ("STRING_CST mode mismatch");
|
|
1972 if (TREE_STRING_LENGTH (t1) != TREE_STRING_LENGTH (t2))
|
|
1973 return return_false_with_msg ("STRING_CST length mismatch");
|
|
1974 if (memcmp (TREE_STRING_POINTER (t1), TREE_STRING_POINTER (t2),
|
|
1975 TREE_STRING_LENGTH (t1)))
|
|
1976 return return_false_with_msg ("STRING_CST mismatch");
|
|
1977 return true;
|
|
1978 case FIXED_CST:
|
|
1979 /* Fixed constants are the same only if the same width of type. */
|
|
1980 if (TYPE_PRECISION (TREE_TYPE (t1)) != TYPE_PRECISION (TREE_TYPE (t2)))
|
|
1981 return return_false_with_msg ("FIXED_CST precision mismatch");
|
|
1982
|
|
1983 return return_with_debug (FIXED_VALUES_IDENTICAL (TREE_FIXED_CST (t1),
|
|
1984 TREE_FIXED_CST (t2)));
|
|
1985 case COMPLEX_CST:
|
|
1986 return (sem_variable::equals (TREE_REALPART (t1), TREE_REALPART (t2))
|
|
1987 && sem_variable::equals (TREE_IMAGPART (t1), TREE_IMAGPART (t2)));
|
|
1988 case REAL_CST:
|
|
1989 /* Real constants are the same only if the same width of type. */
|
|
1990 if (TYPE_PRECISION (TREE_TYPE (t1)) != TYPE_PRECISION (TREE_TYPE (t2)))
|
|
1991 return return_false_with_msg ("REAL_CST precision mismatch");
|
|
1992 return return_with_debug (real_identical (&TREE_REAL_CST (t1),
|
|
1993 &TREE_REAL_CST (t2)));
|
|
1994 case VECTOR_CST:
|
|
1995 {
|
131
|
1996 if (maybe_ne (VECTOR_CST_NELTS (t1), VECTOR_CST_NELTS (t2)))
|
|
1997 return return_false_with_msg ("VECTOR_CST nelts mismatch");
|
|
1998
|
|
1999 unsigned int count
|
|
2000 = tree_vector_builder::binary_encoded_nelts (t1, t2);
|
|
2001 for (unsigned int i = 0; i < count; ++i)
|
|
2002 if (!sem_variable::equals (VECTOR_CST_ENCODED_ELT (t1, i),
|
|
2003 VECTOR_CST_ENCODED_ELT (t2, i)))
|
|
2004 return false;
|
|
2005
|
|
2006 return true;
|
111
|
2007 }
|
|
2008 case ARRAY_REF:
|
|
2009 case ARRAY_RANGE_REF:
|
|
2010 {
|
|
2011 tree x1 = TREE_OPERAND (t1, 0);
|
|
2012 tree x2 = TREE_OPERAND (t2, 0);
|
|
2013 tree y1 = TREE_OPERAND (t1, 1);
|
|
2014 tree y2 = TREE_OPERAND (t2, 1);
|
|
2015
|
|
2016 if (!sem_variable::equals (x1, x2) || !sem_variable::equals (y1, y2))
|
|
2017 return false;
|
|
2018 if (!sem_variable::equals (array_ref_low_bound (t1),
|
|
2019 array_ref_low_bound (t2)))
|
|
2020 return false;
|
|
2021 if (!sem_variable::equals (array_ref_element_size (t1),
|
|
2022 array_ref_element_size (t2)))
|
|
2023 return false;
|
|
2024 return true;
|
|
2025 }
|
|
2026
|
|
2027 case COMPONENT_REF:
|
|
2028 case POINTER_PLUS_EXPR:
|
|
2029 case PLUS_EXPR:
|
|
2030 case MINUS_EXPR:
|
|
2031 case RANGE_EXPR:
|
|
2032 {
|
|
2033 tree x1 = TREE_OPERAND (t1, 0);
|
|
2034 tree x2 = TREE_OPERAND (t2, 0);
|
|
2035 tree y1 = TREE_OPERAND (t1, 1);
|
|
2036 tree y2 = TREE_OPERAND (t2, 1);
|
|
2037
|
|
2038 return sem_variable::equals (x1, x2) && sem_variable::equals (y1, y2);
|
|
2039 }
|
|
2040
|
|
2041 CASE_CONVERT:
|
|
2042 case VIEW_CONVERT_EXPR:
|
|
2043 if (!func_checker::compatible_types_p (TREE_TYPE (t1), TREE_TYPE (t2)))
|
|
2044 return return_false ();
|
|
2045 return sem_variable::equals (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0));
|
|
2046 case ERROR_MARK:
|
|
2047 return return_false_with_msg ("ERROR_MARK");
|
|
2048 default:
|
|
2049 return return_false_with_msg ("Unknown TREE code reached");
|
|
2050 }
|
|
2051 }
|
|
2052
|
|
2053 /* Parser function that visits a varpool NODE. */
|
|
2054
|
|
2055 sem_variable *
|
|
2056 sem_variable::parse (varpool_node *node, bitmap_obstack *stack)
|
|
2057 {
|
|
2058 if (TREE_THIS_VOLATILE (node->decl) || DECL_HARD_REGISTER (node->decl)
|
|
2059 || node->alias)
|
|
2060 return NULL;
|
|
2061
|
|
2062 sem_variable *v = new sem_variable (node, stack);
|
|
2063
|
|
2064 v->init ();
|
|
2065
|
|
2066 return v;
|
|
2067 }
|
|
2068
|
|
2069 /* References independent hash function. */
|
|
2070
|
|
2071 hashval_t
|
|
2072 sem_variable::get_hash (void)
|
|
2073 {
|
|
2074 if (m_hash_set)
|
|
2075 return m_hash;
|
|
2076
|
|
2077 /* All WPA streamed in symbols should have their hashes computed at compile
|
|
2078 time. At this point, the constructor may not be in memory at all.
|
|
2079 DECL_INITIAL (decl) would be error_mark_node in that case. */
|
|
2080 gcc_assert (!node->lto_file_data);
|
|
2081 tree ctor = DECL_INITIAL (decl);
|
|
2082 inchash::hash hstate;
|
|
2083
|
|
2084 hstate.add_int (456346417);
|
|
2085 if (DECL_SIZE (decl) && tree_fits_shwi_p (DECL_SIZE (decl)))
|
|
2086 hstate.add_hwi (tree_to_shwi (DECL_SIZE (decl)));
|
|
2087 add_expr (ctor, hstate);
|
|
2088 set_hash (hstate.end ());
|
|
2089
|
|
2090 return m_hash;
|
|
2091 }
|
|
2092
|
|
2093 /* Merges instance with an ALIAS_ITEM, where alias, thunk or redirection can
|
|
2094 be applied. */
|
|
2095
|
|
2096 bool
|
|
2097 sem_variable::merge (sem_item *alias_item)
|
|
2098 {
|
|
2099 gcc_assert (alias_item->type == VAR);
|
|
2100
|
|
2101 if (!sem_item::target_supports_symbol_aliases_p ())
|
|
2102 {
|
|
2103 if (dump_file)
|
|
2104 fprintf (dump_file, "Not unifying; "
|
|
2105 "Symbol aliases are not supported by target\n\n");
|
|
2106 return false;
|
|
2107 }
|
|
2108
|
|
2109 if (DECL_EXTERNAL (alias_item->decl))
|
|
2110 {
|
|
2111 if (dump_file)
|
|
2112 fprintf (dump_file, "Not unifying; alias is external.\n\n");
|
|
2113 return false;
|
|
2114 }
|
|
2115
|
|
2116 sem_variable *alias_var = static_cast<sem_variable *> (alias_item);
|
|
2117
|
|
2118 varpool_node *original = get_node ();
|
|
2119 varpool_node *alias = alias_var->get_node ();
|
|
2120 bool original_discardable = false;
|
|
2121
|
|
2122 bool alias_address_matters = alias->address_matters_p ();
|
|
2123
|
|
2124 /* See if original is in a section that can be discarded if the main
|
|
2125 symbol is not used.
|
|
2126 Also consider case where we have resolution info and we know that
|
|
2127 original's definition is not going to be used. In this case we can not
|
|
2128 create alias to original. */
|
|
2129 if (original->can_be_discarded_p ()
|
|
2130 || (node->resolution != LDPR_UNKNOWN
|
|
2131 && !decl_binds_to_current_def_p (node->decl)))
|
|
2132 original_discardable = true;
|
|
2133
|
|
2134 gcc_assert (!TREE_ASM_WRITTEN (alias->decl));
|
|
2135
|
|
2136 /* Constant pool machinery is not quite ready for aliases.
|
|
2137 TODO: varasm code contains logic for merging DECL_IN_CONSTANT_POOL.
|
|
2138 For LTO merging does not happen that is an important missing feature.
|
|
2139 We can enable merging with LTO if the DECL_IN_CONSTANT_POOL
|
|
2140 flag is dropped and non-local symbol name is assigned. */
|
|
2141 if (DECL_IN_CONSTANT_POOL (alias->decl)
|
|
2142 || DECL_IN_CONSTANT_POOL (original->decl))
|
|
2143 {
|
|
2144 if (dump_file)
|
|
2145 fprintf (dump_file,
|
|
2146 "Not unifying; constant pool variables.\n\n");
|
|
2147 return false;
|
|
2148 }
|
|
2149
|
|
2150 /* Do not attempt to mix functions from different user sections;
|
|
2151 we do not know what user intends with those. */
|
|
2152 if (((DECL_SECTION_NAME (original->decl) && !original->implicit_section)
|
|
2153 || (DECL_SECTION_NAME (alias->decl) && !alias->implicit_section))
|
|
2154 && DECL_SECTION_NAME (original->decl) != DECL_SECTION_NAME (alias->decl))
|
|
2155 {
|
|
2156 if (dump_file)
|
|
2157 fprintf (dump_file,
|
|
2158 "Not unifying; "
|
|
2159 "original and alias are in different sections.\n\n");
|
|
2160 return false;
|
|
2161 }
|
|
2162
|
|
2163 /* We can not merge if address comparsion metters. */
|
|
2164 if (alias_address_matters && flag_merge_constants < 2)
|
|
2165 {
|
|
2166 if (dump_file)
|
|
2167 fprintf (dump_file,
|
|
2168 "Not unifying; address of original may be compared.\n\n");
|
|
2169 return false;
|
|
2170 }
|
|
2171
|
|
2172 if (DECL_ALIGN (original->decl) < DECL_ALIGN (alias->decl))
|
|
2173 {
|
|
2174 if (dump_file)
|
|
2175 fprintf (dump_file, "Not unifying; "
|
|
2176 "original and alias have incompatible alignments\n\n");
|
|
2177
|
|
2178 return false;
|
|
2179 }
|
|
2180
|
|
2181 if (DECL_COMDAT_GROUP (original->decl) != DECL_COMDAT_GROUP (alias->decl))
|
|
2182 {
|
|
2183 if (dump_file)
|
|
2184 fprintf (dump_file, "Not unifying; alias cannot be created; "
|
|
2185 "across comdat group boundary\n\n");
|
|
2186
|
|
2187 return false;
|
|
2188 }
|
|
2189
|
|
2190 if (original_discardable)
|
|
2191 {
|
|
2192 if (dump_file)
|
|
2193 fprintf (dump_file, "Not unifying; alias cannot be created; "
|
|
2194 "target is discardable\n\n");
|
|
2195
|
|
2196 return false;
|
|
2197 }
|
|
2198 else
|
|
2199 {
|
|
2200 gcc_assert (!original->alias);
|
|
2201 gcc_assert (!alias->alias);
|
|
2202
|
|
2203 alias->analyzed = false;
|
|
2204
|
|
2205 DECL_INITIAL (alias->decl) = NULL;
|
|
2206 ((symtab_node *)alias)->call_for_symbol_and_aliases (clear_decl_rtl,
|
|
2207 NULL, true);
|
|
2208 alias->need_bounds_init = false;
|
|
2209 alias->remove_all_references ();
|
|
2210 if (TREE_ADDRESSABLE (alias->decl))
|
|
2211 original->call_for_symbol_and_aliases (set_addressable, NULL, true);
|
|
2212
|
|
2213 varpool_node::create_alias (alias_var->decl, decl);
|
|
2214 alias->resolve_alias (original);
|
|
2215
|
|
2216 if (dump_file)
|
|
2217 fprintf (dump_file, "Unified; Variable alias has been created.\n");
|
|
2218
|
|
2219 return true;
|
|
2220 }
|
|
2221 }
|
|
2222
|
|
2223 /* Dump symbol to FILE. */
|
|
2224
|
|
2225 void
|
|
2226 sem_variable::dump_to_file (FILE *file)
|
|
2227 {
|
|
2228 gcc_assert (file);
|
|
2229
|
|
2230 print_node (file, "", decl, 0);
|
|
2231 fprintf (file, "\n\n");
|
|
2232 }
|
|
2233
|
|
2234 unsigned int sem_item_optimizer::class_id = 0;
|
|
2235
|
|
2236 sem_item_optimizer::sem_item_optimizer ()
|
|
2237 : worklist (0), m_classes (0), m_classes_count (0), m_cgraph_node_hooks (NULL),
|
131
|
2238 m_varpool_node_hooks (NULL), m_merged_variables ()
|
111
|
2239 {
|
|
2240 m_items.create (0);
|
|
2241 bitmap_obstack_initialize (&m_bmstack);
|
|
2242 }
|
|
2243
|
|
2244 sem_item_optimizer::~sem_item_optimizer ()
|
|
2245 {
|
|
2246 for (unsigned int i = 0; i < m_items.length (); i++)
|
|
2247 delete m_items[i];
|
|
2248
|
|
2249
|
|
2250 for (hash_table<congruence_class_hash>::iterator it = m_classes.begin ();
|
|
2251 it != m_classes.end (); ++it)
|
|
2252 {
|
|
2253 for (unsigned int i = 0; i < (*it)->classes.length (); i++)
|
|
2254 delete (*it)->classes[i];
|
|
2255
|
|
2256 (*it)->classes.release ();
|
|
2257 free (*it);
|
|
2258 }
|
|
2259
|
|
2260 m_items.release ();
|
|
2261
|
|
2262 bitmap_obstack_release (&m_bmstack);
|
131
|
2263 m_merged_variables.release ();
|
111
|
2264 }
|
|
2265
|
|
2266 /* Write IPA ICF summary for symbols. */
|
|
2267
|
|
2268 void
|
|
2269 sem_item_optimizer::write_summary (void)
|
|
2270 {
|
|
2271 unsigned int count = 0;
|
|
2272
|
|
2273 output_block *ob = create_output_block (LTO_section_ipa_icf);
|
|
2274 lto_symtab_encoder_t encoder = ob->decl_state->symtab_node_encoder;
|
|
2275 ob->symbol = NULL;
|
|
2276
|
|
2277 /* Calculate number of symbols to be serialized. */
|
|
2278 for (lto_symtab_encoder_iterator lsei = lsei_start_in_partition (encoder);
|
|
2279 !lsei_end_p (lsei);
|
|
2280 lsei_next_in_partition (&lsei))
|
|
2281 {
|
|
2282 symtab_node *node = lsei_node (lsei);
|
|
2283
|
|
2284 if (m_symtab_node_map.get (node))
|
|
2285 count++;
|
|
2286 }
|
|
2287
|
|
2288 streamer_write_uhwi (ob, count);
|
|
2289
|
|
2290 /* Process all of the symbols. */
|
|
2291 for (lto_symtab_encoder_iterator lsei = lsei_start_in_partition (encoder);
|
|
2292 !lsei_end_p (lsei);
|
|
2293 lsei_next_in_partition (&lsei))
|
|
2294 {
|
|
2295 symtab_node *node = lsei_node (lsei);
|
|
2296
|
|
2297 sem_item **item = m_symtab_node_map.get (node);
|
|
2298
|
|
2299 if (item && *item)
|
|
2300 {
|
|
2301 int node_ref = lto_symtab_encoder_encode (encoder, node);
|
|
2302 streamer_write_uhwi_stream (ob->main_stream, node_ref);
|
|
2303
|
|
2304 streamer_write_uhwi (ob, (*item)->get_hash ());
|
|
2305 }
|
|
2306 }
|
|
2307
|
|
2308 streamer_write_char_stream (ob->main_stream, 0);
|
|
2309 produce_asm (ob, NULL);
|
|
2310 destroy_output_block (ob);
|
|
2311 }
|
|
2312
|
|
2313 /* Reads a section from LTO stream file FILE_DATA. Input block for DATA
|
|
2314 contains LEN bytes. */
|
|
2315
|
|
2316 void
|
|
2317 sem_item_optimizer::read_section (lto_file_decl_data *file_data,
|
|
2318 const char *data, size_t len)
|
|
2319 {
|
|
2320 const lto_function_header *header
|
|
2321 = (const lto_function_header *) data;
|
|
2322 const int cfg_offset = sizeof (lto_function_header);
|
|
2323 const int main_offset = cfg_offset + header->cfg_size;
|
|
2324 const int string_offset = main_offset + header->main_size;
|
|
2325 data_in *data_in;
|
|
2326 unsigned int i;
|
|
2327 unsigned int count;
|
|
2328
|
|
2329 lto_input_block ib_main ((const char *) data + main_offset, 0,
|
|
2330 header->main_size, file_data->mode_table);
|
|
2331
|
|
2332 data_in
|
|
2333 = lto_data_in_create (file_data, (const char *) data + string_offset,
|
|
2334 header->string_size, vNULL);
|
|
2335
|
|
2336 count = streamer_read_uhwi (&ib_main);
|
|
2337
|
|
2338 for (i = 0; i < count; i++)
|
|
2339 {
|
|
2340 unsigned int index;
|
|
2341 symtab_node *node;
|
|
2342 lto_symtab_encoder_t encoder;
|
|
2343
|
|
2344 index = streamer_read_uhwi (&ib_main);
|
|
2345 encoder = file_data->symtab_node_encoder;
|
|
2346 node = lto_symtab_encoder_deref (encoder, index);
|
|
2347
|
|
2348 hashval_t hash = streamer_read_uhwi (&ib_main);
|
|
2349
|
|
2350 gcc_assert (node->definition);
|
|
2351
|
|
2352 if (dump_file)
|
|
2353 fprintf (dump_file, "Symbol added: %s (tree: %p)\n",
|
|
2354 node->dump_asm_name (), (void *) node->decl);
|
|
2355
|
|
2356 if (is_a<cgraph_node *> (node))
|
|
2357 {
|
|
2358 cgraph_node *cnode = dyn_cast <cgraph_node *> (node);
|
|
2359
|
|
2360 sem_function *fn = new sem_function (cnode, &m_bmstack);
|
|
2361 fn->set_hash (hash);
|
|
2362 m_items.safe_push (fn);
|
|
2363 }
|
|
2364 else
|
|
2365 {
|
|
2366 varpool_node *vnode = dyn_cast <varpool_node *> (node);
|
|
2367
|
|
2368 sem_variable *var = new sem_variable (vnode, &m_bmstack);
|
|
2369 var->set_hash (hash);
|
|
2370 m_items.safe_push (var);
|
|
2371 }
|
|
2372 }
|
|
2373
|
|
2374 lto_free_section_data (file_data, LTO_section_ipa_icf, NULL, data,
|
|
2375 len);
|
|
2376 lto_data_in_delete (data_in);
|
|
2377 }
|
|
2378
|
|
2379 /* Read IPA ICF summary for symbols. */
|
|
2380
|
|
2381 void
|
|
2382 sem_item_optimizer::read_summary (void)
|
|
2383 {
|
|
2384 lto_file_decl_data **file_data_vec = lto_get_file_decl_data ();
|
|
2385 lto_file_decl_data *file_data;
|
|
2386 unsigned int j = 0;
|
|
2387
|
|
2388 while ((file_data = file_data_vec[j++]))
|
|
2389 {
|
|
2390 size_t len;
|
|
2391 const char *data = lto_get_section_data (file_data,
|
|
2392 LTO_section_ipa_icf, NULL, &len);
|
|
2393
|
|
2394 if (data)
|
|
2395 read_section (file_data, data, len);
|
|
2396 }
|
|
2397 }
|
|
2398
|
|
2399 /* Register callgraph and varpool hooks. */
|
|
2400
|
|
2401 void
|
|
2402 sem_item_optimizer::register_hooks (void)
|
|
2403 {
|
|
2404 if (!m_cgraph_node_hooks)
|
|
2405 m_cgraph_node_hooks = symtab->add_cgraph_removal_hook
|
|
2406 (&sem_item_optimizer::cgraph_removal_hook, this);
|
|
2407
|
|
2408 if (!m_varpool_node_hooks)
|
|
2409 m_varpool_node_hooks = symtab->add_varpool_removal_hook
|
|
2410 (&sem_item_optimizer::varpool_removal_hook, this);
|
|
2411 }
|
|
2412
|
|
2413 /* Unregister callgraph and varpool hooks. */
|
|
2414
|
|
2415 void
|
|
2416 sem_item_optimizer::unregister_hooks (void)
|
|
2417 {
|
|
2418 if (m_cgraph_node_hooks)
|
|
2419 symtab->remove_cgraph_removal_hook (m_cgraph_node_hooks);
|
|
2420
|
|
2421 if (m_varpool_node_hooks)
|
|
2422 symtab->remove_varpool_removal_hook (m_varpool_node_hooks);
|
|
2423 }
|
|
2424
|
|
2425 /* Adds a CLS to hashtable associated by hash value. */
|
|
2426
|
|
2427 void
|
|
2428 sem_item_optimizer::add_class (congruence_class *cls)
|
|
2429 {
|
|
2430 gcc_assert (cls->members.length ());
|
|
2431
|
|
2432 congruence_class_group *group
|
|
2433 = get_group_by_hash (cls->members[0]->get_hash (),
|
|
2434 cls->members[0]->type);
|
|
2435 group->classes.safe_push (cls);
|
|
2436 }
|
|
2437
|
|
2438 /* Gets a congruence class group based on given HASH value and TYPE. */
|
|
2439
|
|
2440 congruence_class_group *
|
|
2441 sem_item_optimizer::get_group_by_hash (hashval_t hash, sem_item_type type)
|
|
2442 {
|
|
2443 congruence_class_group *item = XNEW (congruence_class_group);
|
|
2444 item->hash = hash;
|
|
2445 item->type = type;
|
|
2446
|
|
2447 congruence_class_group **slot = m_classes.find_slot (item, INSERT);
|
|
2448
|
|
2449 if (*slot)
|
|
2450 free (item);
|
|
2451 else
|
|
2452 {
|
|
2453 item->classes.create (1);
|
|
2454 *slot = item;
|
|
2455 }
|
|
2456
|
|
2457 return *slot;
|
|
2458 }
|
|
2459
|
|
2460 /* Callgraph removal hook called for a NODE with a custom DATA. */
|
|
2461
|
|
2462 void
|
|
2463 sem_item_optimizer::cgraph_removal_hook (cgraph_node *node, void *data)
|
|
2464 {
|
|
2465 sem_item_optimizer *optimizer = (sem_item_optimizer *) data;
|
|
2466 optimizer->remove_symtab_node (node);
|
|
2467 }
|
|
2468
|
|
2469 /* Varpool removal hook called for a NODE with a custom DATA. */
|
|
2470
|
|
2471 void
|
|
2472 sem_item_optimizer::varpool_removal_hook (varpool_node *node, void *data)
|
|
2473 {
|
|
2474 sem_item_optimizer *optimizer = (sem_item_optimizer *) data;
|
|
2475 optimizer->remove_symtab_node (node);
|
|
2476 }
|
|
2477
|
|
2478 /* Remove symtab NODE triggered by symtab removal hooks. */
|
|
2479
|
|
2480 void
|
|
2481 sem_item_optimizer::remove_symtab_node (symtab_node *node)
|
|
2482 {
|
|
2483 gcc_assert (!m_classes.elements ());
|
|
2484
|
|
2485 m_removed_items_set.add (node);
|
|
2486 }
|
|
2487
|
|
2488 void
|
|
2489 sem_item_optimizer::remove_item (sem_item *item)
|
|
2490 {
|
|
2491 if (m_symtab_node_map.get (item->node))
|
|
2492 m_symtab_node_map.remove (item->node);
|
|
2493 delete item;
|
|
2494 }
|
|
2495
|
|
2496 /* Removes all callgraph and varpool nodes that are marked by symtab
|
|
2497 as deleted. */
|
|
2498
|
|
2499 void
|
|
2500 sem_item_optimizer::filter_removed_items (void)
|
|
2501 {
|
|
2502 auto_vec <sem_item *> filtered;
|
|
2503
|
|
2504 for (unsigned int i = 0; i < m_items.length(); i++)
|
|
2505 {
|
|
2506 sem_item *item = m_items[i];
|
|
2507
|
|
2508 if (m_removed_items_set.contains (item->node))
|
|
2509 {
|
|
2510 remove_item (item);
|
|
2511 continue;
|
|
2512 }
|
|
2513
|
|
2514 if (item->type == FUNC)
|
|
2515 {
|
|
2516 cgraph_node *cnode = static_cast <sem_function *>(item)->get_node ();
|
|
2517
|
|
2518 if (in_lto_p && (cnode->alias || cnode->body_removed))
|
|
2519 remove_item (item);
|
|
2520 else
|
|
2521 filtered.safe_push (item);
|
|
2522 }
|
|
2523 else /* VAR. */
|
|
2524 {
|
|
2525 if (!flag_ipa_icf_variables)
|
|
2526 remove_item (item);
|
|
2527 else
|
|
2528 {
|
|
2529 /* Filter out non-readonly variables. */
|
|
2530 tree decl = item->decl;
|
|
2531 if (TREE_READONLY (decl))
|
|
2532 filtered.safe_push (item);
|
|
2533 else
|
|
2534 remove_item (item);
|
|
2535 }
|
|
2536 }
|
|
2537 }
|
|
2538
|
|
2539 /* Clean-up of released semantic items. */
|
|
2540
|
|
2541 m_items.release ();
|
|
2542 for (unsigned int i = 0; i < filtered.length(); i++)
|
|
2543 m_items.safe_push (filtered[i]);
|
|
2544 }
|
|
2545
|
|
2546 /* Optimizer entry point which returns true in case it processes
|
|
2547 a merge operation. True is returned if there's a merge operation
|
|
2548 processed. */
|
|
2549
|
|
2550 bool
|
|
2551 sem_item_optimizer::execute (void)
|
|
2552 {
|
|
2553 filter_removed_items ();
|
|
2554 unregister_hooks ();
|
|
2555
|
|
2556 build_graph ();
|
|
2557 update_hash_by_addr_refs ();
|
|
2558 build_hash_based_classes ();
|
|
2559
|
|
2560 if (dump_file)
|
|
2561 fprintf (dump_file, "Dump after hash based groups\n");
|
|
2562 dump_cong_classes ();
|
|
2563
|
|
2564 for (unsigned int i = 0; i < m_items.length(); i++)
|
|
2565 m_items[i]->init_wpa ();
|
|
2566
|
|
2567 subdivide_classes_by_equality (true);
|
|
2568
|
|
2569 if (dump_file)
|
|
2570 fprintf (dump_file, "Dump after WPA based types groups\n");
|
|
2571
|
|
2572 dump_cong_classes ();
|
|
2573
|
|
2574 process_cong_reduction ();
|
|
2575 checking_verify_classes ();
|
|
2576
|
|
2577 if (dump_file)
|
|
2578 fprintf (dump_file, "Dump after callgraph-based congruence reduction\n");
|
|
2579
|
|
2580 dump_cong_classes ();
|
|
2581
|
|
2582 parse_nonsingleton_classes ();
|
|
2583 subdivide_classes_by_equality ();
|
|
2584
|
|
2585 if (dump_file)
|
|
2586 fprintf (dump_file, "Dump after full equality comparison of groups\n");
|
|
2587
|
|
2588 dump_cong_classes ();
|
|
2589
|
|
2590 unsigned int prev_class_count = m_classes_count;
|
|
2591
|
|
2592 process_cong_reduction ();
|
|
2593 dump_cong_classes ();
|
|
2594 checking_verify_classes ();
|
|
2595 bool merged_p = merge_classes (prev_class_count);
|
|
2596
|
|
2597 if (dump_file && (dump_flags & TDF_DETAILS))
|
|
2598 symtab->dump (dump_file);
|
|
2599
|
|
2600 return merged_p;
|
|
2601 }
|
|
2602
|
|
2603 /* Function responsible for visiting all potential functions and
|
|
2604 read-only variables that can be merged. */
|
|
2605
|
|
2606 void
|
|
2607 sem_item_optimizer::parse_funcs_and_vars (void)
|
|
2608 {
|
|
2609 cgraph_node *cnode;
|
|
2610
|
|
2611 if (flag_ipa_icf_functions)
|
|
2612 FOR_EACH_DEFINED_FUNCTION (cnode)
|
|
2613 {
|
|
2614 sem_function *f = sem_function::parse (cnode, &m_bmstack);
|
|
2615 if (f)
|
|
2616 {
|
|
2617 m_items.safe_push (f);
|
|
2618 m_symtab_node_map.put (cnode, f);
|
|
2619
|
|
2620 if (dump_file)
|
|
2621 fprintf (dump_file, "Parsed function:%s\n", f->node->asm_name ());
|
|
2622
|
|
2623 if (dump_file && (dump_flags & TDF_DETAILS))
|
|
2624 f->dump_to_file (dump_file);
|
|
2625 }
|
|
2626 else if (dump_file)
|
|
2627 fprintf (dump_file, "Not parsed function:%s\n", cnode->asm_name ());
|
|
2628 }
|
|
2629
|
|
2630 varpool_node *vnode;
|
|
2631
|
|
2632 if (flag_ipa_icf_variables)
|
|
2633 FOR_EACH_DEFINED_VARIABLE (vnode)
|
|
2634 {
|
|
2635 sem_variable *v = sem_variable::parse (vnode, &m_bmstack);
|
|
2636
|
|
2637 if (v)
|
|
2638 {
|
|
2639 m_items.safe_push (v);
|
|
2640 m_symtab_node_map.put (vnode, v);
|
|
2641 }
|
|
2642 }
|
|
2643 }
|
|
2644
|
|
2645 /* Makes pairing between a congruence class CLS and semantic ITEM. */
|
|
2646
|
|
2647 void
|
|
2648 sem_item_optimizer::add_item_to_class (congruence_class *cls, sem_item *item)
|
|
2649 {
|
|
2650 item->index_in_class = cls->members.length ();
|
|
2651 cls->members.safe_push (item);
|
|
2652 item->cls = cls;
|
|
2653 }
|
|
2654
|
|
2655 /* For each semantic item, append hash values of references. */
|
|
2656
|
|
2657 void
|
|
2658 sem_item_optimizer::update_hash_by_addr_refs ()
|
|
2659 {
|
|
2660 /* First, append to hash sensitive references and class type if it need to
|
|
2661 be matched for ODR. */
|
|
2662 for (unsigned i = 0; i < m_items.length (); i++)
|
|
2663 {
|
|
2664 m_items[i]->update_hash_by_addr_refs (m_symtab_node_map);
|
|
2665 if (m_items[i]->type == FUNC)
|
|
2666 {
|
|
2667 if (TREE_CODE (TREE_TYPE (m_items[i]->decl)) == METHOD_TYPE
|
|
2668 && contains_polymorphic_type_p
|
|
2669 (TYPE_METHOD_BASETYPE (TREE_TYPE (m_items[i]->decl)))
|
|
2670 && (DECL_CXX_CONSTRUCTOR_P (m_items[i]->decl)
|
|
2671 || (static_cast<sem_function *> (m_items[i])->param_used_p (0)
|
|
2672 && static_cast<sem_function *> (m_items[i])
|
|
2673 ->compare_polymorphic_p ())))
|
|
2674 {
|
|
2675 tree class_type
|
|
2676 = TYPE_METHOD_BASETYPE (TREE_TYPE (m_items[i]->decl));
|
|
2677 inchash::hash hstate (m_items[i]->get_hash ());
|
|
2678
|
|
2679 if (TYPE_NAME (class_type)
|
|
2680 && DECL_ASSEMBLER_NAME_SET_P (TYPE_NAME (class_type)))
|
|
2681 hstate.add_hwi
|
|
2682 (IDENTIFIER_HASH_VALUE
|
|
2683 (DECL_ASSEMBLER_NAME (TYPE_NAME (class_type))));
|
|
2684
|
|
2685 m_items[i]->set_hash (hstate.end ());
|
|
2686 }
|
|
2687 }
|
|
2688 }
|
|
2689
|
|
2690 /* Once all symbols have enhanced hash value, we can append
|
|
2691 hash values of symbols that are seen by IPA ICF and are
|
|
2692 references by a semantic item. Newly computed values
|
|
2693 are saved to global_hash member variable. */
|
|
2694 for (unsigned i = 0; i < m_items.length (); i++)
|
|
2695 m_items[i]->update_hash_by_local_refs (m_symtab_node_map);
|
|
2696
|
|
2697 /* Global hash value replace current hash values. */
|
|
2698 for (unsigned i = 0; i < m_items.length (); i++)
|
|
2699 m_items[i]->set_hash (m_items[i]->global_hash);
|
|
2700 }
|
|
2701
|
|
2702 /* Congruence classes are built by hash value. */
|
|
2703
|
|
2704 void
|
|
2705 sem_item_optimizer::build_hash_based_classes (void)
|
|
2706 {
|
|
2707 for (unsigned i = 0; i < m_items.length (); i++)
|
|
2708 {
|
|
2709 sem_item *item = m_items[i];
|
|
2710
|
|
2711 congruence_class_group *group
|
|
2712 = get_group_by_hash (item->get_hash (), item->type);
|
|
2713
|
|
2714 if (!group->classes.length ())
|
|
2715 {
|
|
2716 m_classes_count++;
|
|
2717 group->classes.safe_push (new congruence_class (class_id++));
|
|
2718 }
|
|
2719
|
|
2720 add_item_to_class (group->classes[0], item);
|
|
2721 }
|
|
2722 }
|
|
2723
|
|
2724 /* Build references according to call graph. */
|
|
2725
|
|
2726 void
|
|
2727 sem_item_optimizer::build_graph (void)
|
|
2728 {
|
|
2729 for (unsigned i = 0; i < m_items.length (); i++)
|
|
2730 {
|
|
2731 sem_item *item = m_items[i];
|
|
2732 m_symtab_node_map.put (item->node, item);
|
|
2733
|
|
2734 /* Initialize hash values if we are not in LTO mode. */
|
|
2735 if (!in_lto_p)
|
|
2736 item->get_hash ();
|
|
2737 }
|
|
2738
|
|
2739 for (unsigned i = 0; i < m_items.length (); i++)
|
|
2740 {
|
|
2741 sem_item *item = m_items[i];
|
|
2742
|
|
2743 if (item->type == FUNC)
|
|
2744 {
|
|
2745 cgraph_node *cnode = dyn_cast <cgraph_node *> (item->node);
|
|
2746
|
|
2747 cgraph_edge *e = cnode->callees;
|
|
2748 while (e)
|
|
2749 {
|
|
2750 sem_item **slot = m_symtab_node_map.get
|
|
2751 (e->callee->ultimate_alias_target ());
|
|
2752 if (slot)
|
|
2753 item->add_reference (*slot);
|
|
2754
|
|
2755 e = e->next_callee;
|
|
2756 }
|
|
2757 }
|
|
2758
|
|
2759 ipa_ref *ref = NULL;
|
|
2760 for (unsigned i = 0; item->node->iterate_reference (i, ref); i++)
|
|
2761 {
|
|
2762 sem_item **slot = m_symtab_node_map.get
|
|
2763 (ref->referred->ultimate_alias_target ());
|
|
2764 if (slot)
|
|
2765 item->add_reference (*slot);
|
|
2766 }
|
|
2767 }
|
|
2768 }
|
|
2769
|
|
2770 /* Semantic items in classes having more than one element and initialized.
|
|
2771 In case of WPA, we load function body. */
|
|
2772
|
|
2773 void
|
|
2774 sem_item_optimizer::parse_nonsingleton_classes (void)
|
|
2775 {
|
|
2776 unsigned int init_called_count = 0;
|
|
2777
|
|
2778 for (unsigned i = 0; i < m_items.length (); i++)
|
|
2779 if (m_items[i]->cls->members.length () > 1)
|
|
2780 {
|
|
2781 m_items[i]->init ();
|
|
2782 init_called_count++;
|
|
2783 }
|
|
2784
|
|
2785 if (dump_file)
|
|
2786 fprintf (dump_file, "Init called for %u items (%.2f%%).\n",
|
|
2787 init_called_count,
|
|
2788 m_items.length () ? 100.0f * init_called_count / m_items.length ()
|
|
2789 : 0.0f);
|
|
2790 }
|
|
2791
|
|
2792 /* Equality function for semantic items is used to subdivide existing
|
|
2793 classes. If IN_WPA, fast equality function is invoked. */
|
|
2794
|
|
2795 void
|
|
2796 sem_item_optimizer::subdivide_classes_by_equality (bool in_wpa)
|
|
2797 {
|
|
2798 for (hash_table <congruence_class_hash>::iterator it = m_classes.begin ();
|
|
2799 it != m_classes.end (); ++it)
|
|
2800 {
|
|
2801 unsigned int class_count = (*it)->classes.length ();
|
|
2802
|
|
2803 for (unsigned i = 0; i < class_count; i++)
|
|
2804 {
|
|
2805 congruence_class *c = (*it)->classes[i];
|
|
2806
|
|
2807 if (c->members.length() > 1)
|
|
2808 {
|
|
2809 auto_vec <sem_item *> new_vector;
|
|
2810
|
|
2811 sem_item *first = c->members[0];
|
|
2812 new_vector.safe_push (first);
|
|
2813
|
|
2814 unsigned class_split_first = (*it)->classes.length ();
|
|
2815
|
|
2816 for (unsigned j = 1; j < c->members.length (); j++)
|
|
2817 {
|
|
2818 sem_item *item = c->members[j];
|
|
2819
|
|
2820 bool equals
|
|
2821 = in_wpa ? first->equals_wpa (item, m_symtab_node_map)
|
|
2822 : first->equals (item, m_symtab_node_map);
|
|
2823
|
|
2824 if (equals)
|
|
2825 new_vector.safe_push (item);
|
|
2826 else
|
|
2827 {
|
|
2828 bool integrated = false;
|
|
2829
|
|
2830 for (unsigned k = class_split_first;
|
|
2831 k < (*it)->classes.length (); k++)
|
|
2832 {
|
|
2833 sem_item *x = (*it)->classes[k]->members[0];
|
|
2834 bool equals
|
|
2835 = in_wpa ? x->equals_wpa (item, m_symtab_node_map)
|
|
2836 : x->equals (item, m_symtab_node_map);
|
|
2837
|
|
2838 if (equals)
|
|
2839 {
|
|
2840 integrated = true;
|
|
2841 add_item_to_class ((*it)->classes[k], item);
|
|
2842
|
|
2843 break;
|
|
2844 }
|
|
2845 }
|
|
2846
|
|
2847 if (!integrated)
|
|
2848 {
|
|
2849 congruence_class *c
|
|
2850 = new congruence_class (class_id++);
|
|
2851 m_classes_count++;
|
|
2852 add_item_to_class (c, item);
|
|
2853
|
|
2854 (*it)->classes.safe_push (c);
|
|
2855 }
|
|
2856 }
|
|
2857 }
|
|
2858
|
|
2859 // We replace newly created new_vector for the class we've just
|
|
2860 // splitted.
|
|
2861 c->members.release ();
|
|
2862 c->members.create (new_vector.length ());
|
|
2863
|
|
2864 for (unsigned int j = 0; j < new_vector.length (); j++)
|
|
2865 add_item_to_class (c, new_vector[j]);
|
|
2866 }
|
|
2867 }
|
|
2868 }
|
|
2869
|
|
2870 checking_verify_classes ();
|
|
2871 }
|
|
2872
|
|
2873 /* Subdivide classes by address references that members of the class
|
|
2874 reference. Example can be a pair of functions that have an address
|
|
2875 taken from a function. If these addresses are different the class
|
|
2876 is split. */
|
|
2877
|
|
2878 unsigned
|
|
2879 sem_item_optimizer::subdivide_classes_by_sensitive_refs ()
|
|
2880 {
|
|
2881 typedef hash_map <symbol_compare_hash, vec <sem_item *> > subdivide_hash_map;
|
|
2882
|
|
2883 unsigned newly_created_classes = 0;
|
|
2884
|
|
2885 for (hash_table <congruence_class_hash>::iterator it = m_classes.begin ();
|
|
2886 it != m_classes.end (); ++it)
|
|
2887 {
|
|
2888 unsigned int class_count = (*it)->classes.length ();
|
|
2889 auto_vec<congruence_class *> new_classes;
|
|
2890
|
|
2891 for (unsigned i = 0; i < class_count; i++)
|
|
2892 {
|
|
2893 congruence_class *c = (*it)->classes[i];
|
|
2894
|
|
2895 if (c->members.length() > 1)
|
|
2896 {
|
|
2897 subdivide_hash_map split_map;
|
|
2898
|
|
2899 for (unsigned j = 0; j < c->members.length (); j++)
|
|
2900 {
|
|
2901 sem_item *source_node = c->members[j];
|
|
2902
|
|
2903 symbol_compare_collection *collection
|
|
2904 = new symbol_compare_collection (source_node->node);
|
|
2905
|
|
2906 bool existed;
|
|
2907 vec <sem_item *> *slot
|
|
2908 = &split_map.get_or_insert (collection, &existed);
|
|
2909 gcc_checking_assert (slot);
|
|
2910
|
|
2911 slot->safe_push (source_node);
|
|
2912
|
|
2913 if (existed)
|
|
2914 delete collection;
|
|
2915 }
|
|
2916
|
|
2917 /* If the map contains more than one key, we have to split
|
|
2918 the map appropriately. */
|
|
2919 if (split_map.elements () != 1)
|
|
2920 {
|
|
2921 bool first_class = true;
|
|
2922
|
|
2923 for (subdivide_hash_map::iterator it2 = split_map.begin ();
|
|
2924 it2 != split_map.end (); ++it2)
|
|
2925 {
|
|
2926 congruence_class *new_cls;
|
|
2927 new_cls = new congruence_class (class_id++);
|
|
2928
|
|
2929 for (unsigned k = 0; k < (*it2).second.length (); k++)
|
|
2930 add_item_to_class (new_cls, (*it2).second[k]);
|
|
2931
|
|
2932 worklist_push (new_cls);
|
|
2933 newly_created_classes++;
|
|
2934
|
|
2935 if (first_class)
|
|
2936 {
|
|
2937 (*it)->classes[i] = new_cls;
|
|
2938 first_class = false;
|
|
2939 }
|
|
2940 else
|
|
2941 {
|
|
2942 new_classes.safe_push (new_cls);
|
|
2943 m_classes_count++;
|
|
2944 }
|
|
2945 }
|
|
2946 }
|
|
2947
|
|
2948 /* Release memory. */
|
|
2949 for (subdivide_hash_map::iterator it2 = split_map.begin ();
|
|
2950 it2 != split_map.end (); ++it2)
|
|
2951 {
|
|
2952 delete (*it2).first;
|
|
2953 (*it2).second.release ();
|
|
2954 }
|
|
2955 }
|
|
2956 }
|
|
2957
|
|
2958 for (unsigned i = 0; i < new_classes.length (); i++)
|
|
2959 (*it)->classes.safe_push (new_classes[i]);
|
|
2960 }
|
|
2961
|
|
2962 return newly_created_classes;
|
|
2963 }
|
|
2964
|
|
2965 /* Verify congruence classes, if checking is enabled. */
|
|
2966
|
|
2967 void
|
|
2968 sem_item_optimizer::checking_verify_classes (void)
|
|
2969 {
|
|
2970 if (flag_checking)
|
|
2971 verify_classes ();
|
|
2972 }
|
|
2973
|
|
2974 /* Verify congruence classes. */
|
|
2975
|
|
2976 void
|
|
2977 sem_item_optimizer::verify_classes (void)
|
|
2978 {
|
|
2979 for (hash_table<congruence_class_hash>::iterator it = m_classes.begin ();
|
|
2980 it != m_classes.end (); ++it)
|
|
2981 {
|
|
2982 for (unsigned int i = 0; i < (*it)->classes.length (); i++)
|
|
2983 {
|
|
2984 congruence_class *cls = (*it)->classes[i];
|
|
2985
|
|
2986 gcc_assert (cls);
|
|
2987 gcc_assert (cls->members.length () > 0);
|
|
2988
|
|
2989 for (unsigned int j = 0; j < cls->members.length (); j++)
|
|
2990 {
|
|
2991 sem_item *item = cls->members[j];
|
|
2992
|
|
2993 gcc_assert (item);
|
|
2994 gcc_assert (item->cls == cls);
|
|
2995
|
|
2996 for (unsigned k = 0; k < item->usages.length (); k++)
|
|
2997 {
|
|
2998 sem_usage_pair *usage = item->usages[k];
|
|
2999 gcc_assert (usage->item->index_in_class
|
|
3000 < usage->item->cls->members.length ());
|
|
3001 }
|
|
3002 }
|
|
3003 }
|
|
3004 }
|
|
3005 }
|
|
3006
|
|
3007 /* Disposes split map traverse function. CLS_PTR is pointer to congruence
|
|
3008 class, BSLOT is bitmap slot we want to release. DATA is mandatory,
|
|
3009 but unused argument. */
|
|
3010
|
|
3011 bool
|
|
3012 sem_item_optimizer::release_split_map (congruence_class * const &,
|
|
3013 bitmap const &b, traverse_split_pair *)
|
|
3014 {
|
|
3015 bitmap bmp = b;
|
|
3016
|
|
3017 BITMAP_FREE (bmp);
|
|
3018
|
|
3019 return true;
|
|
3020 }
|
|
3021
|
|
3022 /* Process split operation for a class given as pointer CLS_PTR,
|
|
3023 where bitmap B splits congruence class members. DATA is used
|
|
3024 as argument of split pair. */
|
|
3025
|
|
3026 bool
|
|
3027 sem_item_optimizer::traverse_congruence_split (congruence_class * const &cls,
|
|
3028 bitmap const &b,
|
|
3029 traverse_split_pair *pair)
|
|
3030 {
|
|
3031 sem_item_optimizer *optimizer = pair->optimizer;
|
|
3032 const congruence_class *splitter_cls = pair->cls;
|
|
3033
|
|
3034 /* If counted bits are greater than zero and less than the number of members
|
|
3035 a group will be splitted. */
|
|
3036 unsigned popcount = bitmap_count_bits (b);
|
|
3037
|
|
3038 if (popcount > 0 && popcount < cls->members.length ())
|
|
3039 {
|
|
3040 auto_vec <congruence_class *, 2> newclasses;
|
|
3041 newclasses.quick_push (new congruence_class (class_id++));
|
|
3042 newclasses.quick_push (new congruence_class (class_id++));
|
|
3043
|
|
3044 for (unsigned int i = 0; i < cls->members.length (); i++)
|
|
3045 {
|
|
3046 int target = bitmap_bit_p (b, i);
|
|
3047 congruence_class *tc = newclasses[target];
|
|
3048
|
|
3049 add_item_to_class (tc, cls->members[i]);
|
|
3050 }
|
|
3051
|
|
3052 if (flag_checking)
|
|
3053 {
|
|
3054 for (unsigned int i = 0; i < 2; i++)
|
|
3055 gcc_assert (newclasses[i]->members.length ());
|
|
3056 }
|
|
3057
|
|
3058 if (splitter_cls == cls)
|
|
3059 optimizer->splitter_class_removed = true;
|
|
3060
|
|
3061 /* Remove old class from worklist if presented. */
|
|
3062 bool in_worklist = cls->in_worklist;
|
|
3063
|
|
3064 if (in_worklist)
|
|
3065 cls->in_worklist = false;
|
|
3066
|
|
3067 congruence_class_group g;
|
|
3068 g.hash = cls->members[0]->get_hash ();
|
|
3069 g.type = cls->members[0]->type;
|
|
3070
|
|
3071 congruence_class_group *slot = optimizer->m_classes.find (&g);
|
|
3072
|
|
3073 for (unsigned int i = 0; i < slot->classes.length (); i++)
|
|
3074 if (slot->classes[i] == cls)
|
|
3075 {
|
|
3076 slot->classes.ordered_remove (i);
|
|
3077 break;
|
|
3078 }
|
|
3079
|
|
3080 /* New class will be inserted and integrated to work list. */
|
|
3081 for (unsigned int i = 0; i < 2; i++)
|
|
3082 optimizer->add_class (newclasses[i]);
|
|
3083
|
|
3084 /* Two classes replace one, so that increment just by one. */
|
|
3085 optimizer->m_classes_count++;
|
|
3086
|
|
3087 /* If OLD class was presented in the worklist, we remove the class
|
|
3088 and replace it will both newly created classes. */
|
|
3089 if (in_worklist)
|
|
3090 for (unsigned int i = 0; i < 2; i++)
|
|
3091 optimizer->worklist_push (newclasses[i]);
|
|
3092 else /* Just smaller class is inserted. */
|
|
3093 {
|
|
3094 unsigned int smaller_index
|
|
3095 = (newclasses[0]->members.length ()
|
|
3096 < newclasses[1]->members.length ()
|
|
3097 ? 0 : 1);
|
|
3098 optimizer->worklist_push (newclasses[smaller_index]);
|
|
3099 }
|
|
3100
|
|
3101 if (dump_file && (dump_flags & TDF_DETAILS))
|
|
3102 {
|
|
3103 fprintf (dump_file, " congruence class splitted:\n");
|
|
3104 cls->dump (dump_file, 4);
|
|
3105
|
|
3106 fprintf (dump_file, " newly created groups:\n");
|
|
3107 for (unsigned int i = 0; i < 2; i++)
|
|
3108 newclasses[i]->dump (dump_file, 4);
|
|
3109 }
|
|
3110
|
|
3111 /* Release class if not presented in work list. */
|
|
3112 if (!in_worklist)
|
|
3113 delete cls;
|
|
3114 }
|
|
3115
|
|
3116
|
|
3117 return true;
|
|
3118 }
|
|
3119
|
|
3120 /* Tests if a class CLS used as INDEXth splits any congruence classes.
|
|
3121 Bitmap stack BMSTACK is used for bitmap allocation. */
|
|
3122
|
|
3123 void
|
|
3124 sem_item_optimizer::do_congruence_step_for_index (congruence_class *cls,
|
|
3125 unsigned int index)
|
|
3126 {
|
|
3127 hash_map <congruence_class *, bitmap> split_map;
|
|
3128
|
|
3129 for (unsigned int i = 0; i < cls->members.length (); i++)
|
|
3130 {
|
|
3131 sem_item *item = cls->members[i];
|
|
3132
|
|
3133 /* Iterate all usages that have INDEX as usage of the item. */
|
|
3134 for (unsigned int j = 0; j < item->usages.length (); j++)
|
|
3135 {
|
|
3136 sem_usage_pair *usage = item->usages[j];
|
|
3137
|
|
3138 if (usage->index != index)
|
|
3139 continue;
|
|
3140
|
|
3141 bitmap *slot = split_map.get (usage->item->cls);
|
|
3142 bitmap b;
|
|
3143
|
|
3144 if(!slot)
|
|
3145 {
|
|
3146 b = BITMAP_ALLOC (&m_bmstack);
|
|
3147 split_map.put (usage->item->cls, b);
|
|
3148 }
|
|
3149 else
|
|
3150 b = *slot;
|
|
3151
|
|
3152 gcc_checking_assert (usage->item->cls);
|
|
3153 gcc_checking_assert (usage->item->index_in_class
|
|
3154 < usage->item->cls->members.length ());
|
|
3155
|
|
3156 bitmap_set_bit (b, usage->item->index_in_class);
|
|
3157 }
|
|
3158 }
|
|
3159
|
|
3160 traverse_split_pair pair;
|
|
3161 pair.optimizer = this;
|
|
3162 pair.cls = cls;
|
|
3163
|
|
3164 splitter_class_removed = false;
|
|
3165 split_map.traverse <traverse_split_pair *,
|
|
3166 sem_item_optimizer::traverse_congruence_split> (&pair);
|
|
3167
|
|
3168 /* Bitmap clean-up. */
|
|
3169 split_map.traverse <traverse_split_pair *,
|
|
3170 sem_item_optimizer::release_split_map> (NULL);
|
|
3171 }
|
|
3172
|
|
3173 /* Every usage of a congruence class CLS is a candidate that can split the
|
|
3174 collection of classes. Bitmap stack BMSTACK is used for bitmap
|
|
3175 allocation. */
|
|
3176
|
|
3177 void
|
|
3178 sem_item_optimizer::do_congruence_step (congruence_class *cls)
|
|
3179 {
|
|
3180 bitmap_iterator bi;
|
|
3181 unsigned int i;
|
|
3182
|
|
3183 bitmap usage = BITMAP_ALLOC (&m_bmstack);
|
|
3184
|
|
3185 for (unsigned int i = 0; i < cls->members.length (); i++)
|
|
3186 bitmap_ior_into (usage, cls->members[i]->usage_index_bitmap);
|
|
3187
|
|
3188 EXECUTE_IF_SET_IN_BITMAP (usage, 0, i, bi)
|
|
3189 {
|
|
3190 if (dump_file && (dump_flags & TDF_DETAILS))
|
|
3191 fprintf (dump_file, " processing congruence step for class: %u, "
|
|
3192 "index: %u\n", cls->id, i);
|
|
3193
|
|
3194 do_congruence_step_for_index (cls, i);
|
|
3195
|
|
3196 if (splitter_class_removed)
|
|
3197 break;
|
|
3198 }
|
|
3199
|
|
3200 BITMAP_FREE (usage);
|
|
3201 }
|
|
3202
|
|
3203 /* Adds a newly created congruence class CLS to worklist. */
|
|
3204
|
|
3205 void
|
|
3206 sem_item_optimizer::worklist_push (congruence_class *cls)
|
|
3207 {
|
|
3208 /* Return if the class CLS is already presented in work list. */
|
|
3209 if (cls->in_worklist)
|
|
3210 return;
|
|
3211
|
|
3212 cls->in_worklist = true;
|
|
3213 worklist.push_back (cls);
|
|
3214 }
|
|
3215
|
|
3216 /* Pops a class from worklist. */
|
|
3217
|
|
3218 congruence_class *
|
|
3219 sem_item_optimizer::worklist_pop (void)
|
|
3220 {
|
|
3221 congruence_class *cls;
|
|
3222
|
|
3223 while (!worklist.empty ())
|
|
3224 {
|
|
3225 cls = worklist.front ();
|
|
3226 worklist.pop_front ();
|
|
3227 if (cls->in_worklist)
|
|
3228 {
|
|
3229 cls->in_worklist = false;
|
|
3230
|
|
3231 return cls;
|
|
3232 }
|
|
3233 else
|
|
3234 {
|
|
3235 /* Work list item was already intended to be removed.
|
|
3236 The only reason for doing it is to split a class.
|
|
3237 Thus, the class CLS is deleted. */
|
|
3238 delete cls;
|
|
3239 }
|
|
3240 }
|
|
3241
|
|
3242 return NULL;
|
|
3243 }
|
|
3244
|
|
3245 /* Iterative congruence reduction function. */
|
|
3246
|
|
3247 void
|
|
3248 sem_item_optimizer::process_cong_reduction (void)
|
|
3249 {
|
|
3250 for (hash_table<congruence_class_hash>::iterator it = m_classes.begin ();
|
|
3251 it != m_classes.end (); ++it)
|
|
3252 for (unsigned i = 0; i < (*it)->classes.length (); i++)
|
|
3253 if ((*it)->classes[i]->is_class_used ())
|
|
3254 worklist_push ((*it)->classes[i]);
|
|
3255
|
|
3256 if (dump_file)
|
|
3257 fprintf (dump_file, "Worklist has been filled with: %lu\n",
|
|
3258 (unsigned long) worklist.size ());
|
|
3259
|
|
3260 if (dump_file && (dump_flags & TDF_DETAILS))
|
|
3261 fprintf (dump_file, "Congruence class reduction\n");
|
|
3262
|
|
3263 congruence_class *cls;
|
|
3264
|
|
3265 /* Process complete congruence reduction. */
|
|
3266 while ((cls = worklist_pop ()) != NULL)
|
|
3267 do_congruence_step (cls);
|
|
3268
|
|
3269 /* Subdivide newly created classes according to references. */
|
|
3270 unsigned new_classes = subdivide_classes_by_sensitive_refs ();
|
|
3271
|
|
3272 if (dump_file)
|
|
3273 fprintf (dump_file, "Address reference subdivision created: %u "
|
|
3274 "new classes.\n", new_classes);
|
|
3275 }
|
|
3276
|
|
3277 /* Debug function prints all informations about congruence classes. */
|
|
3278
|
|
3279 void
|
|
3280 sem_item_optimizer::dump_cong_classes (void)
|
|
3281 {
|
|
3282 if (!dump_file)
|
|
3283 return;
|
|
3284
|
|
3285 fprintf (dump_file,
|
|
3286 "Congruence classes: %u (unique hash values: %lu), with total: "
|
|
3287 "%u items\n", m_classes_count,
|
|
3288 (unsigned long) m_classes.elements (), m_items.length ());
|
|
3289
|
|
3290 /* Histogram calculation. */
|
|
3291 unsigned int max_index = 0;
|
|
3292 unsigned int* histogram = XCNEWVEC (unsigned int, m_items.length () + 1);
|
|
3293
|
|
3294 for (hash_table<congruence_class_hash>::iterator it = m_classes.begin ();
|
|
3295 it != m_classes.end (); ++it)
|
|
3296 for (unsigned i = 0; i < (*it)->classes.length (); i++)
|
|
3297 {
|
|
3298 unsigned int c = (*it)->classes[i]->members.length ();
|
|
3299 histogram[c]++;
|
|
3300
|
|
3301 if (c > max_index)
|
|
3302 max_index = c;
|
|
3303 }
|
|
3304
|
|
3305 fprintf (dump_file,
|
|
3306 "Class size histogram [num of members]: number of classe number "
|
|
3307 "of classess\n");
|
|
3308
|
|
3309 for (unsigned int i = 0; i <= max_index; i++)
|
|
3310 if (histogram[i])
|
|
3311 fprintf (dump_file, "[%u]: %u classes\n", i, histogram[i]);
|
|
3312
|
|
3313 fprintf (dump_file, "\n\n");
|
|
3314
|
|
3315 if (dump_flags & TDF_DETAILS)
|
|
3316 for (hash_table<congruence_class_hash>::iterator it = m_classes.begin ();
|
|
3317 it != m_classes.end (); ++it)
|
|
3318 {
|
|
3319 fprintf (dump_file, " group: with %u classes:\n",
|
|
3320 (*it)->classes.length ());
|
|
3321
|
|
3322 for (unsigned i = 0; i < (*it)->classes.length (); i++)
|
|
3323 {
|
|
3324 (*it)->classes[i]->dump (dump_file, 4);
|
|
3325
|
|
3326 if (i < (*it)->classes.length () - 1)
|
|
3327 fprintf (dump_file, " ");
|
|
3328 }
|
|
3329 }
|
|
3330
|
|
3331 free (histogram);
|
|
3332 }
|
|
3333
|
|
3334 /* Sort pair of sem_items A and B by DECL_UID. */
|
|
3335
|
|
3336 static int
|
|
3337 sort_sem_items_by_decl_uid (const void *a, const void *b)
|
|
3338 {
|
|
3339 const sem_item *i1 = *(const sem_item * const *)a;
|
|
3340 const sem_item *i2 = *(const sem_item * const *)b;
|
|
3341
|
|
3342 int uid1 = DECL_UID (i1->decl);
|
|
3343 int uid2 = DECL_UID (i2->decl);
|
|
3344
|
|
3345 if (uid1 < uid2)
|
|
3346 return -1;
|
|
3347 else if (uid1 > uid2)
|
|
3348 return 1;
|
|
3349 else
|
|
3350 return 0;
|
|
3351 }
|
|
3352
|
|
3353 /* Sort pair of congruence_classes A and B by DECL_UID of the first member. */
|
|
3354
|
|
3355 static int
|
|
3356 sort_congruence_classes_by_decl_uid (const void *a, const void *b)
|
|
3357 {
|
|
3358 const congruence_class *c1 = *(const congruence_class * const *)a;
|
|
3359 const congruence_class *c2 = *(const congruence_class * const *)b;
|
|
3360
|
|
3361 int uid1 = DECL_UID (c1->members[0]->decl);
|
|
3362 int uid2 = DECL_UID (c2->members[0]->decl);
|
|
3363
|
|
3364 if (uid1 < uid2)
|
|
3365 return -1;
|
|
3366 else if (uid1 > uid2)
|
|
3367 return 1;
|
|
3368 else
|
|
3369 return 0;
|
|
3370 }
|
|
3371
|
|
3372 /* Sort pair of congruence_class_groups A and B by
|
|
3373 DECL_UID of the first member of a first group. */
|
|
3374
|
|
3375 static int
|
|
3376 sort_congruence_class_groups_by_decl_uid (const void *a, const void *b)
|
|
3377 {
|
|
3378 const congruence_class_group *g1
|
|
3379 = *(const congruence_class_group * const *)a;
|
|
3380 const congruence_class_group *g2
|
|
3381 = *(const congruence_class_group * const *)b;
|
|
3382
|
|
3383 int uid1 = DECL_UID (g1->classes[0]->members[0]->decl);
|
|
3384 int uid2 = DECL_UID (g2->classes[0]->members[0]->decl);
|
|
3385
|
|
3386 if (uid1 < uid2)
|
|
3387 return -1;
|
|
3388 else if (uid1 > uid2)
|
|
3389 return 1;
|
|
3390 else
|
|
3391 return 0;
|
|
3392 }
|
|
3393
|
|
3394 /* After reduction is done, we can declare all items in a group
|
|
3395 to be equal. PREV_CLASS_COUNT is start number of classes
|
|
3396 before reduction. True is returned if there's a merge operation
|
|
3397 processed. */
|
|
3398
|
|
3399 bool
|
|
3400 sem_item_optimizer::merge_classes (unsigned int prev_class_count)
|
|
3401 {
|
|
3402 unsigned int item_count = m_items.length ();
|
|
3403 unsigned int class_count = m_classes_count;
|
|
3404 unsigned int equal_items = item_count - class_count;
|
|
3405
|
|
3406 unsigned int non_singular_classes_count = 0;
|
|
3407 unsigned int non_singular_classes_sum = 0;
|
|
3408
|
|
3409 bool merged_p = false;
|
|
3410
|
|
3411 /* PR lto/78211
|
|
3412 Sort functions in congruence classes by DECL_UID and do the same
|
|
3413 for the classes to not to break -fcompare-debug. */
|
|
3414
|
|
3415 for (hash_table<congruence_class_hash>::iterator it = m_classes.begin ();
|
|
3416 it != m_classes.end (); ++it)
|
|
3417 {
|
|
3418 for (unsigned int i = 0; i < (*it)->classes.length (); i++)
|
|
3419 {
|
|
3420 congruence_class *c = (*it)->classes[i];
|
|
3421 c->members.qsort (sort_sem_items_by_decl_uid);
|
|
3422 }
|
|
3423
|
|
3424 (*it)->classes.qsort (sort_congruence_classes_by_decl_uid);
|
|
3425 }
|
|
3426
|
|
3427 for (hash_table<congruence_class_hash>::iterator it = m_classes.begin ();
|
|
3428 it != m_classes.end (); ++it)
|
|
3429 for (unsigned int i = 0; i < (*it)->classes.length (); i++)
|
|
3430 {
|
|
3431 congruence_class *c = (*it)->classes[i];
|
|
3432 if (c->members.length () > 1)
|
|
3433 {
|
|
3434 non_singular_classes_count++;
|
|
3435 non_singular_classes_sum += c->members.length ();
|
|
3436 }
|
|
3437 }
|
|
3438
|
|
3439 auto_vec <congruence_class_group *> classes (m_classes.elements ());
|
|
3440 for (hash_table<congruence_class_hash>::iterator it = m_classes.begin ();
|
|
3441 it != m_classes.end (); ++it)
|
|
3442 classes.quick_push (*it);
|
|
3443
|
|
3444 classes.qsort (sort_congruence_class_groups_by_decl_uid);
|
|
3445
|
|
3446 if (dump_file)
|
|
3447 {
|
|
3448 fprintf (dump_file, "\nItem count: %u\n", item_count);
|
|
3449 fprintf (dump_file, "Congruent classes before: %u, after: %u\n",
|
|
3450 prev_class_count, class_count);
|
|
3451 fprintf (dump_file, "Average class size before: %.2f, after: %.2f\n",
|
|
3452 prev_class_count ? 1.0f * item_count / prev_class_count : 0.0f,
|
|
3453 class_count ? 1.0f * item_count / class_count : 0.0f);
|
|
3454 fprintf (dump_file, "Average non-singular class size: %.2f, count: %u\n",
|
|
3455 non_singular_classes_count ? 1.0f * non_singular_classes_sum /
|
|
3456 non_singular_classes_count : 0.0f,
|
|
3457 non_singular_classes_count);
|
|
3458 fprintf (dump_file, "Equal symbols: %u\n", equal_items);
|
|
3459 fprintf (dump_file, "Fraction of visited symbols: %.2f%%\n\n",
|
|
3460 item_count ? 100.0f * equal_items / item_count : 0.0f);
|
|
3461 }
|
|
3462
|
|
3463 unsigned int l;
|
|
3464 congruence_class_group *it;
|
|
3465 FOR_EACH_VEC_ELT (classes, l, it)
|
|
3466 for (unsigned int i = 0; i < it->classes.length (); i++)
|
|
3467 {
|
|
3468 congruence_class *c = it->classes[i];
|
|
3469
|
|
3470 if (c->members.length () == 1)
|
|
3471 continue;
|
|
3472
|
|
3473 sem_item *source = c->members[0];
|
|
3474
|
|
3475 if (DECL_NAME (source->decl)
|
|
3476 && MAIN_NAME_P (DECL_NAME (source->decl)))
|
|
3477 /* If merge via wrappers, picking main as the target can be
|
|
3478 problematic. */
|
|
3479 source = c->members[1];
|
|
3480
|
|
3481 for (unsigned int j = 0; j < c->members.length (); j++)
|
|
3482 {
|
|
3483 sem_item *alias = c->members[j];
|
|
3484
|
|
3485 if (alias == source)
|
|
3486 continue;
|
|
3487
|
|
3488 if (dump_file)
|
|
3489 {
|
|
3490 fprintf (dump_file, "Semantic equality hit:%s->%s\n",
|
|
3491 xstrdup_for_dump (source->node->name ()),
|
|
3492 xstrdup_for_dump (alias->node->name ()));
|
|
3493 fprintf (dump_file, "Assembler symbol names:%s->%s\n",
|
|
3494 xstrdup_for_dump (source->node->asm_name ()),
|
|
3495 xstrdup_for_dump (alias->node->asm_name ()));
|
|
3496 }
|
|
3497
|
|
3498 if (lookup_attribute ("no_icf", DECL_ATTRIBUTES (alias->decl)))
|
|
3499 {
|
|
3500 if (dump_file)
|
|
3501 fprintf (dump_file,
|
|
3502 "Merge operation is skipped due to no_icf "
|
|
3503 "attribute.\n\n");
|
|
3504
|
|
3505 continue;
|
|
3506 }
|
|
3507
|
|
3508 if (dump_file && (dump_flags & TDF_DETAILS))
|
|
3509 {
|
|
3510 source->dump_to_file (dump_file);
|
|
3511 alias->dump_to_file (dump_file);
|
|
3512 }
|
|
3513
|
|
3514 if (dbg_cnt (merged_ipa_icf))
|
131
|
3515 {
|
|
3516 bool merged = source->merge (alias);
|
|
3517 merged_p |= merged;
|
|
3518
|
|
3519 if (merged && alias->type == VAR)
|
|
3520 {
|
|
3521 symtab_pair p = symtab_pair (source->node, alias->node);
|
|
3522 m_merged_variables.safe_push (p);
|
|
3523 }
|
|
3524 }
|
111
|
3525 }
|
|
3526 }
|
|
3527
|
131
|
3528 if (!m_merged_variables.is_empty ())
|
|
3529 fixup_points_to_sets ();
|
|
3530
|
111
|
3531 return merged_p;
|
|
3532 }
|
|
3533
|
131
|
3534 /* Fixup points to set PT. */
|
|
3535
|
|
3536 void
|
|
3537 sem_item_optimizer::fixup_pt_set (struct pt_solution *pt)
|
|
3538 {
|
|
3539 if (pt->vars == NULL)
|
|
3540 return;
|
|
3541
|
|
3542 unsigned i;
|
|
3543 symtab_pair *item;
|
|
3544 FOR_EACH_VEC_ELT (m_merged_variables, i, item)
|
|
3545 if (bitmap_bit_p (pt->vars, DECL_UID (item->second->decl)))
|
|
3546 bitmap_set_bit (pt->vars, DECL_UID (item->first->decl));
|
|
3547 }
|
|
3548
|
|
3549 /* Set all points-to UIDs of aliases pointing to node N as UID. */
|
|
3550
|
|
3551 static void
|
|
3552 set_alias_uids (symtab_node *n, int uid)
|
|
3553 {
|
|
3554 ipa_ref *ref;
|
|
3555 FOR_EACH_ALIAS (n, ref)
|
|
3556 {
|
|
3557 if (dump_file)
|
|
3558 fprintf (dump_file, " Setting points-to UID of [%s] as %d\n",
|
|
3559 xstrdup_for_dump (ref->referring->asm_name ()), uid);
|
|
3560
|
|
3561 SET_DECL_PT_UID (ref->referring->decl, uid);
|
|
3562 set_alias_uids (ref->referring, uid);
|
|
3563 }
|
|
3564 }
|
|
3565
|
|
3566 /* Fixup points to analysis info. */
|
|
3567
|
|
3568 void
|
|
3569 sem_item_optimizer::fixup_points_to_sets (void)
|
|
3570 {
|
|
3571 /* TODO: remove in GCC 9 and trigger PTA re-creation after IPA passes. */
|
|
3572 cgraph_node *cnode;
|
|
3573
|
|
3574 FOR_EACH_DEFINED_FUNCTION (cnode)
|
|
3575 {
|
|
3576 tree name;
|
|
3577 unsigned i;
|
|
3578 function *fn = DECL_STRUCT_FUNCTION (cnode->decl);
|
|
3579 if (!gimple_in_ssa_p (fn))
|
|
3580 continue;
|
|
3581
|
|
3582 FOR_EACH_SSA_NAME (i, name, fn)
|
|
3583 if (POINTER_TYPE_P (TREE_TYPE (name))
|
|
3584 && SSA_NAME_PTR_INFO (name))
|
|
3585 fixup_pt_set (&SSA_NAME_PTR_INFO (name)->pt);
|
|
3586 fixup_pt_set (&fn->gimple_df->escaped);
|
|
3587
|
|
3588 /* The above get's us to 99% I guess, at least catching the
|
|
3589 address compares. Below also gets us aliasing correct
|
|
3590 but as said we're giving leeway to the situation with
|
|
3591 readonly vars anyway, so ... */
|
|
3592 basic_block bb;
|
|
3593 FOR_EACH_BB_FN (bb, fn)
|
|
3594 for (gimple_stmt_iterator gsi = gsi_start_bb (bb); !gsi_end_p (gsi);
|
|
3595 gsi_next (&gsi))
|
|
3596 {
|
|
3597 gcall *call = dyn_cast<gcall *> (gsi_stmt (gsi));
|
|
3598 if (call)
|
|
3599 {
|
|
3600 fixup_pt_set (gimple_call_use_set (call));
|
|
3601 fixup_pt_set (gimple_call_clobber_set (call));
|
|
3602 }
|
|
3603 }
|
|
3604 }
|
|
3605
|
|
3606 unsigned i;
|
|
3607 symtab_pair *item;
|
|
3608 FOR_EACH_VEC_ELT (m_merged_variables, i, item)
|
|
3609 set_alias_uids (item->first, DECL_UID (item->first->decl));
|
|
3610 }
|
|
3611
|
111
|
3612 /* Dump function prints all class members to a FILE with an INDENT. */
|
|
3613
|
|
3614 void
|
|
3615 congruence_class::dump (FILE *file, unsigned int indent) const
|
|
3616 {
|
|
3617 FPRINTF_SPACES (file, indent, "class with id: %u, hash: %u, items: %u\n",
|
|
3618 id, members[0]->get_hash (), members.length ());
|
|
3619
|
|
3620 FPUTS_SPACES (file, indent + 2, "");
|
|
3621 for (unsigned i = 0; i < members.length (); i++)
|
|
3622 fprintf (file, "%s ", members[i]->node->dump_asm_name ());
|
|
3623
|
|
3624 fprintf (file, "\n");
|
|
3625 }
|
|
3626
|
|
3627 /* Returns true if there's a member that is used from another group. */
|
|
3628
|
|
3629 bool
|
|
3630 congruence_class::is_class_used (void)
|
|
3631 {
|
|
3632 for (unsigned int i = 0; i < members.length (); i++)
|
|
3633 if (members[i]->usages.length ())
|
|
3634 return true;
|
|
3635
|
|
3636 return false;
|
|
3637 }
|
|
3638
|
|
3639 /* Generate pass summary for IPA ICF pass. */
|
|
3640
|
|
3641 static void
|
|
3642 ipa_icf_generate_summary (void)
|
|
3643 {
|
|
3644 if (!optimizer)
|
|
3645 optimizer = new sem_item_optimizer ();
|
|
3646
|
|
3647 optimizer->register_hooks ();
|
|
3648 optimizer->parse_funcs_and_vars ();
|
|
3649 }
|
|
3650
|
|
3651 /* Write pass summary for IPA ICF pass. */
|
|
3652
|
|
3653 static void
|
|
3654 ipa_icf_write_summary (void)
|
|
3655 {
|
|
3656 gcc_assert (optimizer);
|
|
3657
|
|
3658 optimizer->write_summary ();
|
|
3659 }
|
|
3660
|
|
3661 /* Read pass summary for IPA ICF pass. */
|
|
3662
|
|
3663 static void
|
|
3664 ipa_icf_read_summary (void)
|
|
3665 {
|
|
3666 if (!optimizer)
|
|
3667 optimizer = new sem_item_optimizer ();
|
|
3668
|
|
3669 optimizer->read_summary ();
|
|
3670 optimizer->register_hooks ();
|
|
3671 }
|
|
3672
|
|
3673 /* Semantic equality exection function. */
|
|
3674
|
|
3675 static unsigned int
|
|
3676 ipa_icf_driver (void)
|
|
3677 {
|
|
3678 gcc_assert (optimizer);
|
|
3679
|
|
3680 bool merged_p = optimizer->execute ();
|
|
3681
|
|
3682 delete optimizer;
|
|
3683 optimizer = NULL;
|
|
3684
|
|
3685 return merged_p ? TODO_remove_functions : 0;
|
|
3686 }
|
|
3687
|
|
3688 const pass_data pass_data_ipa_icf =
|
|
3689 {
|
|
3690 IPA_PASS, /* type */
|
|
3691 "icf", /* name */
|
|
3692 OPTGROUP_IPA, /* optinfo_flags */
|
|
3693 TV_IPA_ICF, /* tv_id */
|
|
3694 0, /* properties_required */
|
|
3695 0, /* properties_provided */
|
|
3696 0, /* properties_destroyed */
|
|
3697 0, /* todo_flags_start */
|
|
3698 0, /* todo_flags_finish */
|
|
3699 };
|
|
3700
|
|
3701 class pass_ipa_icf : public ipa_opt_pass_d
|
|
3702 {
|
|
3703 public:
|
|
3704 pass_ipa_icf (gcc::context *ctxt)
|
|
3705 : ipa_opt_pass_d (pass_data_ipa_icf, ctxt,
|
|
3706 ipa_icf_generate_summary, /* generate_summary */
|
|
3707 ipa_icf_write_summary, /* write_summary */
|
|
3708 ipa_icf_read_summary, /* read_summary */
|
|
3709 NULL, /*
|
|
3710 write_optimization_summary */
|
|
3711 NULL, /*
|
|
3712 read_optimization_summary */
|
|
3713 NULL, /* stmt_fixup */
|
|
3714 0, /* function_transform_todo_flags_start */
|
|
3715 NULL, /* function_transform */
|
|
3716 NULL) /* variable_transform */
|
|
3717 {}
|
|
3718
|
|
3719 /* opt_pass methods: */
|
|
3720 virtual bool gate (function *)
|
|
3721 {
|
|
3722 return in_lto_p || flag_ipa_icf_variables || flag_ipa_icf_functions;
|
|
3723 }
|
|
3724
|
|
3725 virtual unsigned int execute (function *)
|
|
3726 {
|
|
3727 return ipa_icf_driver();
|
|
3728 }
|
|
3729 }; // class pass_ipa_icf
|
|
3730
|
|
3731 } // ipa_icf namespace
|
|
3732
|
|
3733 ipa_opt_pass_d *
|
|
3734 make_pass_ipa_icf (gcc::context *ctxt)
|
|
3735 {
|
|
3736 return new ipa_icf::pass_ipa_icf (ctxt);
|
|
3737 }
|