1 /* Interprocedural Identical Code Folding pass
2 Copyright (C) 2014-2015 Free Software Foundation, Inc.
4 Contributed by Jan Hubicka <hubicka@ucw.cz> and Martin Liska <mliska@suse.cz>
6 This file is part of GCC.
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
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
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/>. */
22 /* Interprocedural Identical Code Folding for functions and
25 The goal of this transformation is to discover functions and read-only
26 variables which do have exactly the same semantics.
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
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
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.
56 #include "coretypes.h"
60 #include "double-int.h"
68 #include "fold-const.h"
71 #include "hard-reg-set.h"
73 #include "dominance.h"
75 #include "basic-block.h"
76 #include "tree-ssa-alias.h"
77 #include "internal-fn.h"
78 #include "gimple-expr.h"
84 #include "statistics.h"
86 #include "fixed-value.h"
87 #include "insn-config.h"
96 #include "gimple-iterator.h"
97 #include "gimple-ssa.h"
99 #include "tree-phinodes.h"
100 #include "stringpool.h"
101 #include "tree-ssanames.h"
102 #include "tree-dfa.h"
103 #include "tree-pass.h"
104 #include "gimple-pretty-print.h"
105 #include "hash-map.h"
106 #include "plugin-api.h"
109 #include "alloc-pool.h"
110 #include "symbol-summary.h"
111 #include "ipa-prop.h"
112 #include "ipa-inline.h"
115 #include "hash-table.h"
116 #include "coverage.h"
118 #include "print-tree.h"
119 #include "lto-streamer.h"
120 #include "data-streamer.h"
121 #include "ipa-utils.h"
123 #include "ipa-icf-gimple.h"
126 using namespace ipa_icf_gimple
;
132 symbol_compare_collection::symbol_compare_collection (symtab_node
*node
)
134 m_references
.create (0);
135 m_interposables
.create (0);
139 if (is_a
<varpool_node
*> (node
) && DECL_VIRTUAL_P (node
->decl
))
142 for (unsigned i
= 0; i
< node
->num_references (); i
++)
144 ref
= node
->iterate_reference (i
, ref
);
145 if (ref
->address_matters_p ())
146 m_references
.safe_push (ref
->referred
);
148 if (ref
->referred
->get_availability () <= AVAIL_INTERPOSABLE
)
150 if (ref
->use
== IPA_REF_ADDR
)
151 m_references
.safe_push (ref
->referred
);
153 m_interposables
.safe_push (ref
->referred
);
157 if (is_a
<cgraph_node
*> (node
))
159 cgraph_node
*cnode
= dyn_cast
<cgraph_node
*> (node
);
161 for (cgraph_edge
*e
= cnode
->callees
; e
; e
= e
->next_callee
)
162 if (e
->callee
->get_availability () <= AVAIL_INTERPOSABLE
)
163 m_interposables
.safe_push (e
->callee
);
167 /* Constructor for key value pair, where _ITEM is key and _INDEX is a target. */
169 sem_usage_pair::sem_usage_pair (sem_item
*_item
, unsigned int _index
):
170 item (_item
), index (_index
)
174 /* Semantic item constructor for a node of _TYPE, where STACK is used
175 for bitmap memory allocation. */
177 sem_item::sem_item (sem_item_type _type
,
178 bitmap_obstack
*stack
): type(_type
), hash(0)
183 /* Semantic item constructor for a node of _TYPE, where STACK is used
184 for bitmap memory allocation. The item is based on symtab node _NODE
185 with computed _HASH. */
187 sem_item::sem_item (sem_item_type _type
, symtab_node
*_node
,
188 hashval_t _hash
, bitmap_obstack
*stack
): type(_type
),
189 node (_node
), hash (_hash
)
195 /* Add reference to a semantic TARGET. */
198 sem_item::add_reference (sem_item
*target
)
200 refs
.safe_push (target
);
201 unsigned index
= refs
.length ();
202 target
->usages
.safe_push (new sem_usage_pair(this, index
));
203 bitmap_set_bit (target
->usage_index_bitmap
, index
);
204 refs_set
.add (target
->node
);
207 /* Initialize internal data structures. Bitmap STACK is used for
208 bitmap memory allocation process. */
211 sem_item::setup (bitmap_obstack
*stack
)
213 gcc_checking_assert (node
);
216 tree_refs
.create (0);
218 usage_index_bitmap
= BITMAP_ALLOC (stack
);
221 sem_item::~sem_item ()
223 for (unsigned i
= 0; i
< usages
.length (); i
++)
227 tree_refs
.release ();
230 BITMAP_FREE (usage_index_bitmap
);
233 /* Dump function for debugging purpose. */
236 sem_item::dump (void)
240 fprintf (dump_file
, "[%s] %s (%u) (tree:%p)\n", type
== FUNC
? "func" : "var",
241 name(), node
->order
, (void *) node
->decl
);
242 fprintf (dump_file
, " hash: %u\n", get_hash ());
243 fprintf (dump_file
, " references: ");
245 for (unsigned i
= 0; i
< refs
.length (); i
++)
246 fprintf (dump_file
, "%s%s ", refs
[i
]->name (),
247 i
< refs
.length() - 1 ? "," : "");
249 fprintf (dump_file
, "\n");
253 /* Return true if target supports alias symbols. */
256 sem_item::target_supports_symbol_aliases_p (void)
258 #if !defined (ASM_OUTPUT_DEF) || (!defined(ASM_OUTPUT_WEAK_ALIAS) && !defined (ASM_WEAKEN_DECL))
265 /* Semantic function constructor that uses STACK as bitmap memory stack. */
267 sem_function::sem_function (bitmap_obstack
*stack
): sem_item (FUNC
, stack
),
268 m_checker (NULL
), m_compared_func (NULL
)
270 arg_types
.create (0);
272 bb_sorted
.create (0);
275 /* Constructor based on callgraph node _NODE with computed hash _HASH.
276 Bitmap STACK is used for memory allocation. */
277 sem_function::sem_function (cgraph_node
*node
, hashval_t hash
,
278 bitmap_obstack
*stack
):
279 sem_item (FUNC
, node
, hash
, stack
),
280 m_checker (NULL
), m_compared_func (NULL
)
282 arg_types
.create (0);
284 bb_sorted
.create (0);
287 sem_function::~sem_function ()
289 for (unsigned i
= 0; i
< bb_sorted
.length (); i
++)
290 delete (bb_sorted
[i
]);
292 arg_types
.release ();
294 bb_sorted
.release ();
297 /* Calculates hash value based on a BASIC_BLOCK. */
300 sem_function::get_bb_hash (const sem_bb
*basic_block
)
302 inchash::hash hstate
;
304 hstate
.add_int (basic_block
->nondbg_stmt_count
);
305 hstate
.add_int (basic_block
->edge_count
);
307 return hstate
.end ();
310 /* References independent hash function. */
313 sem_function::get_hash (void)
317 inchash::hash hstate
;
318 hstate
.add_int (177454); /* Random number for function type. */
320 hstate
.add_int (arg_count
);
321 hstate
.add_int (cfg_checksum
);
322 hstate
.add_int (gcode_hash
);
324 for (unsigned i
= 0; i
< bb_sorted
.length (); i
++)
325 hstate
.merge_hash (get_bb_hash (bb_sorted
[i
]));
327 for (unsigned i
= 0; i
< bb_sizes
.length (); i
++)
328 hstate
.add_int (bb_sizes
[i
]);
330 hash
= hstate
.end ();
336 /* For a given symbol table nodes N1 and N2, we check that FUNCTION_DECLs
337 point to a same function. Comparison can be skipped if IGNORED_NODES
338 contains these nodes. */
341 sem_function::compare_cgraph_references (hash_map
<symtab_node
*, sem_item
*>
343 symtab_node
*n1
, symtab_node
*n2
)
345 if (n1
== n2
|| (ignored_nodes
.get (n1
) && ignored_nodes
.get (n2
)))
348 /* TODO: add more precise comparison for weakrefs, etc. */
350 return return_false_with_msg ("different references");
353 /* If cgraph edges E1 and E2 are indirect calls, verify that
354 ECF flags are the same. */
356 bool sem_function::compare_edge_flags (cgraph_edge
*e1
, cgraph_edge
*e2
)
358 if (e1
->indirect_info
&& e2
->indirect_info
)
360 int e1_flags
= e1
->indirect_info
->ecf_flags
;
361 int e2_flags
= e2
->indirect_info
->ecf_flags
;
363 if (e1_flags
!= e2_flags
)
364 return return_false_with_msg ("ICF flags are different");
366 else if (e1
->indirect_info
|| e2
->indirect_info
)
372 /* Fast equality function based on knowledge known in WPA. */
375 sem_function::equals_wpa (sem_item
*item
,
376 hash_map
<symtab_node
*, sem_item
*> &ignored_nodes
)
378 gcc_assert (item
->type
== FUNC
);
380 m_compared_func
= static_cast<sem_function
*> (item
);
382 if (arg_types
.length () != m_compared_func
->arg_types
.length ())
383 return return_false_with_msg ("different number of arguments");
385 /* Checking types of arguments. */
386 for (unsigned i
= 0; i
< arg_types
.length (); i
++)
388 /* This guard is here for function pointer with attributes (pr59927.c). */
389 if (!arg_types
[i
] || !m_compared_func
->arg_types
[i
])
390 return return_false_with_msg ("NULL argument type");
392 /* Polymorphic comparison is executed just for non-leaf functions. */
393 bool is_not_leaf
= get_node ()->callees
!= NULL
394 || get_node ()->indirect_calls
!= NULL
;
396 if (!func_checker::compatible_types_p (arg_types
[i
],
397 m_compared_func
->arg_types
[i
],
398 is_not_leaf
, i
== 0))
399 return return_false_with_msg ("argument type is different");
402 /* Result type checking. */
403 if (!func_checker::compatible_types_p (result_type
,
404 m_compared_func
->result_type
))
405 return return_false_with_msg ("result types are different");
407 if (node
->num_references () != item
->node
->num_references ())
408 return return_false_with_msg ("different number of references");
410 ipa_ref
*ref
= NULL
, *ref2
= NULL
;
411 for (unsigned i
= 0; node
->iterate_reference (i
, ref
); i
++)
413 item
->node
->iterate_reference (i
, ref2
);
415 if (!compare_cgraph_references (ignored_nodes
, ref
->referred
, ref2
->referred
))
419 cgraph_edge
*e1
= dyn_cast
<cgraph_node
*> (node
)->callees
;
420 cgraph_edge
*e2
= dyn_cast
<cgraph_node
*> (item
->node
)->callees
;
424 if (!compare_cgraph_references (ignored_nodes
, e1
->callee
, e2
->callee
))
427 e1
= e1
->next_callee
;
428 e2
= e2
->next_callee
;
432 return return_false_with_msg ("different number of edges");
437 /* Returns true if the item equals to ITEM given as argument. */
440 sem_function::equals (sem_item
*item
,
441 hash_map
<symtab_node
*, sem_item
*> &ignored_nodes
)
443 gcc_assert (item
->type
== FUNC
);
444 bool eq
= equals_private (item
, ignored_nodes
);
446 if (m_checker
!= NULL
)
452 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
454 "Equals called for:%s:%s (%u:%u) (%s:%s) with result: %s\n\n",
455 name(), item
->name (), node
->order
, item
->node
->order
, asm_name (),
456 item
->asm_name (), eq
? "true" : "false");
461 /* Processes function equality comparison. */
464 sem_function::equals_private (sem_item
*item
,
465 hash_map
<symtab_node
*, sem_item
*> &ignored_nodes
)
467 if (item
->type
!= FUNC
)
470 basic_block bb1
, bb2
;
472 edge_iterator ei1
, ei2
;
476 m_compared_func
= static_cast<sem_function
*> (item
);
478 gcc_assert (decl
!= item
->decl
);
480 if (bb_sorted
.length () != m_compared_func
->bb_sorted
.length ()
481 || edge_count
!= m_compared_func
->edge_count
482 || cfg_checksum
!= m_compared_func
->cfg_checksum
)
483 return return_false ();
485 if (!equals_wpa (item
, ignored_nodes
))
488 /* Checking function TARGET and OPTIMIZATION flags. */
489 cl_target_option
*tar1
= target_opts_for_fn (decl
);
490 cl_target_option
*tar2
= target_opts_for_fn (m_compared_func
->decl
);
492 if (tar1
!= NULL
&& tar2
!= NULL
)
494 if (!cl_target_option_eq (tar1
, tar2
))
496 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
498 fprintf (dump_file
, "target flags difference");
499 cl_target_option_print_diff (dump_file
, 2, tar1
, tar2
);
502 return return_false_with_msg ("Target flags are different");
505 else if (tar1
!= NULL
|| tar2
!= NULL
)
506 return return_false_with_msg ("Target flags are different");
508 cl_optimization
*opt1
= opts_for_fn (decl
);
509 cl_optimization
*opt2
= opts_for_fn (m_compared_func
->decl
);
511 if (opt1
!= NULL
&& opt2
!= NULL
)
513 if (memcmp (opt1
, opt2
, sizeof(cl_optimization
)))
515 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
517 fprintf (dump_file
, "optimization flags difference");
518 cl_optimization_print_diff (dump_file
, 2, opt1
, opt2
);
521 return return_false_with_msg ("optimization flags are different");
524 else if (opt1
!= NULL
|| opt2
!= NULL
)
525 return return_false_with_msg ("optimization flags are different");
527 /* Checking function arguments. */
528 tree decl1
= DECL_ATTRIBUTES (decl
);
529 tree decl2
= DECL_ATTRIBUTES (m_compared_func
->decl
);
531 m_checker
= new func_checker (decl
, m_compared_func
->decl
,
532 compare_polymorphic_p (),
535 &m_compared_func
->refs_set
);
539 return return_false ();
541 if (get_attribute_name (decl1
) != get_attribute_name (decl2
))
542 return return_false ();
544 tree attr_value1
= TREE_VALUE (decl1
);
545 tree attr_value2
= TREE_VALUE (decl2
);
547 if (attr_value1
&& attr_value2
)
549 bool ret
= m_checker
->compare_operand (TREE_VALUE (attr_value1
),
550 TREE_VALUE (attr_value2
));
552 return return_false_with_msg ("attribute values are different");
554 else if (!attr_value1
&& !attr_value2
)
557 return return_false ();
559 decl1
= TREE_CHAIN (decl1
);
560 decl2
= TREE_CHAIN (decl2
);
564 return return_false();
567 for (arg1
= DECL_ARGUMENTS (decl
),
568 arg2
= DECL_ARGUMENTS (m_compared_func
->decl
);
569 arg1
; arg1
= DECL_CHAIN (arg1
), arg2
= DECL_CHAIN (arg2
))
570 if (!m_checker
->compare_decl (arg1
, arg2
))
571 return return_false ();
573 /* Fill-up label dictionary. */
574 for (unsigned i
= 0; i
< bb_sorted
.length (); ++i
)
576 m_checker
->parse_labels (bb_sorted
[i
]);
577 m_checker
->parse_labels (m_compared_func
->bb_sorted
[i
]);
580 /* Checking all basic blocks. */
581 for (unsigned i
= 0; i
< bb_sorted
.length (); ++i
)
582 if(!m_checker
->compare_bb (bb_sorted
[i
], m_compared_func
->bb_sorted
[i
]))
583 return return_false();
585 dump_message ("All BBs are equal\n");
587 auto_vec
<int> bb_dict
;
589 /* Basic block edges check. */
590 for (unsigned i
= 0; i
< bb_sorted
.length (); ++i
)
592 bb1
= bb_sorted
[i
]->bb
;
593 bb2
= m_compared_func
->bb_sorted
[i
]->bb
;
595 ei2
= ei_start (bb2
->preds
);
597 for (ei1
= ei_start (bb1
->preds
); ei_cond (ei1
, &e1
); ei_next (&ei1
))
601 if (e1
->flags
!= e2
->flags
)
602 return return_false_with_msg ("flags comparison returns false");
604 if (!bb_dict_test (&bb_dict
, e1
->src
->index
, e2
->src
->index
))
605 return return_false_with_msg ("edge comparison returns false");
607 if (!bb_dict_test (&bb_dict
, e1
->dest
->index
, e2
->dest
->index
))
608 return return_false_with_msg ("BB comparison returns false");
610 if (!m_checker
->compare_edge (e1
, e2
))
611 return return_false_with_msg ("edge comparison returns false");
617 /* Basic block PHI nodes comparison. */
618 for (unsigned i
= 0; i
< bb_sorted
.length (); i
++)
619 if (!compare_phi_node (bb_sorted
[i
]->bb
, m_compared_func
->bb_sorted
[i
]->bb
))
620 return return_false_with_msg ("PHI node comparison returns false");
625 /* Set LOCAL_P of NODE to true if DATA is non-NULL.
626 Helper for call_for_symbol_thunks_and_aliases. */
629 set_local (cgraph_node
*node
, void *data
)
631 node
->local
.local
= data
!= NULL
;
635 /* Merges instance with an ALIAS_ITEM, where alias, thunk or redirection can
638 sem_function::merge (sem_item
*alias_item
)
640 gcc_assert (alias_item
->type
== FUNC
);
642 sem_function
*alias_func
= static_cast<sem_function
*> (alias_item
);
644 cgraph_node
*original
= get_node ();
645 cgraph_node
*local_original
= original
;
646 cgraph_node
*alias
= alias_func
->get_node ();
647 bool original_address_matters
;
648 bool alias_address_matters
;
650 bool create_thunk
= false;
651 bool create_alias
= false;
652 bool redirect_callers
= false;
653 bool original_discardable
= false;
655 /* Do not attempt to mix functions from different user sections;
656 we do not know what user intends with those. */
657 if (((DECL_SECTION_NAME (original
->decl
) && !original
->implicit_section
)
658 || (DECL_SECTION_NAME (alias
->decl
) && !alias
->implicit_section
))
659 && DECL_SECTION_NAME (original
->decl
) != DECL_SECTION_NAME (alias
->decl
))
663 "Not unifying; original and alias are in different sections.\n\n");
667 /* See if original is in a section that can be discarded if the main
668 symbol is not used. */
669 if (DECL_EXTERNAL (original
->decl
))
670 original_discardable
= true;
671 if (original
->resolution
== LDPR_PREEMPTED_REG
672 || original
->resolution
== LDPR_PREEMPTED_IR
)
673 original_discardable
= true;
674 if (original
->can_be_discarded_p ())
675 original_discardable
= true;
677 /* See if original and/or alias address can be compared for equality. */
678 original_address_matters
679 = (!DECL_VIRTUAL_P (original
->decl
)
680 && (original
->externally_visible
681 || original
->address_taken_from_non_vtable_p ()));
682 alias_address_matters
683 = (!DECL_VIRTUAL_P (alias
->decl
)
684 && (alias
->externally_visible
685 || alias
->address_taken_from_non_vtable_p ()));
687 /* If alias and original can be compared for address equality, we need
688 to create a thunk. Also we can not create extra aliases into discardable
689 section (or we risk link failures when section is discarded). */
690 if ((original_address_matters
691 && alias_address_matters
)
692 || original_discardable
693 || DECL_COMDAT_GROUP (alias
->decl
)
694 || !sem_item::target_supports_symbol_aliases_p ())
696 create_thunk
= !stdarg_p (TREE_TYPE (alias
->decl
));
697 create_alias
= false;
698 /* When both alias and original are not overwritable, we can save
699 the extra thunk wrapper for direct calls. */
701 = (!original_discardable
702 && !DECL_COMDAT_GROUP (alias
->decl
)
703 && alias
->get_availability () > AVAIL_INTERPOSABLE
704 && original
->get_availability () > AVAIL_INTERPOSABLE
705 && !alias
->instrumented_version
);
710 create_thunk
= false;
711 redirect_callers
= false;
714 /* We want thunk to always jump to the local function body
715 unless the body is comdat and may be optimized out. */
716 if ((create_thunk
|| redirect_callers
)
717 && (!original_discardable
718 || (DECL_COMDAT_GROUP (original
->decl
)
719 && (DECL_COMDAT_GROUP (original
->decl
)
720 == DECL_COMDAT_GROUP (alias
->decl
)))))
722 = dyn_cast
<cgraph_node
*> (original
->noninterposable_alias ());
727 fprintf (dump_file
, "Noninterposable alias cannot be created.\n\n");
732 if (!decl_binds_to_current_def_p (alias
->decl
))
735 fprintf (dump_file
, "Declaration does not bind to currect definition.\n\n");
739 if (redirect_callers
)
741 /* If alias is non-overwritable then
742 all direct calls are safe to be redirected to the original. */
743 bool redirected
= false;
744 while (alias
->callers
)
746 cgraph_edge
*e
= alias
->callers
;
747 e
->redirect_callee (local_original
);
748 push_cfun (DECL_STRUCT_FUNCTION (e
->caller
->decl
));
751 e
->redirect_call_stmt_to_callee ();
757 alias
->icf_merged
= true;
758 if (local_original
->lto_file_data
759 && alias
->lto_file_data
760 && local_original
->lto_file_data
!= alias
->lto_file_data
)
761 local_original
->merged
= true;
763 /* The alias function is removed if symbol address
765 if (!alias_address_matters
)
768 if (dump_file
&& redirected
)
769 fprintf (dump_file
, "Callgraph local calls have been redirected.\n\n");
771 /* If the condtion above is not met, we are lucky and can turn the
772 function into real alias. */
773 else if (create_alias
)
775 alias
->icf_merged
= true;
776 if (local_original
->lto_file_data
777 && alias
->lto_file_data
778 && local_original
->lto_file_data
!= alias
->lto_file_data
)
779 local_original
->merged
= true;
781 /* Remove the function's body. */
782 ipa_merge_profiles (original
, alias
);
783 alias
->release_body (true);
786 /* Create the alias. */
787 cgraph_node::create_alias (alias_func
->decl
, decl
);
788 alias
->resolve_alias (original
);
790 original
->call_for_symbol_thunks_and_aliases
791 (set_local
, (void *)(size_t) original
->local_p (), true);
794 fprintf (dump_file
, "Callgraph alias has been created.\n\n");
796 else if (create_thunk
)
798 if (DECL_COMDAT_GROUP (alias
->decl
))
801 fprintf (dump_file
, "Callgraph thunk cannot be created because of COMDAT\n");
806 if (DECL_STATIC_CHAIN (alias
->decl
))
809 fprintf (dump_file
, "Thunk creation is risky for static-chain functions.\n\n");
814 alias
->icf_merged
= true;
815 if (local_original
->lto_file_data
816 && alias
->lto_file_data
817 && local_original
->lto_file_data
!= alias
->lto_file_data
)
818 local_original
->merged
= true;
819 ipa_merge_profiles (local_original
, alias
, true);
820 alias
->create_wrapper (local_original
);
823 fprintf (dump_file
, "Callgraph thunk has been created.\n\n");
826 fprintf (dump_file
, "Callgraph merge operation cannot be performed.\n\n");
831 /* Semantic item initialization function. */
834 sem_function::init (void)
837 get_node ()->get_untransformed_body ();
839 tree fndecl
= node
->decl
;
840 function
*func
= DECL_STRUCT_FUNCTION (fndecl
);
843 gcc_assert (SSANAMES (func
));
845 ssa_names_size
= SSANAMES (func
)->length ();
849 region_tree
= func
->eh
->region_tree
;
851 /* iterating all function arguments. */
852 arg_count
= count_formal_params (fndecl
);
854 edge_count
= n_edges_for_fn (func
);
855 cfg_checksum
= coverage_compute_cfg_checksum (func
);
857 inchash::hash hstate
;
860 FOR_EACH_BB_FN (bb
, func
)
862 unsigned nondbg_stmt_count
= 0;
865 for (edge_iterator ei
= ei_start (bb
->preds
); ei_cond (ei
, &e
); ei_next (&ei
))
866 cfg_checksum
= iterative_hash_host_wide_int (e
->flags
,
869 for (gimple_stmt_iterator gsi
= gsi_start_bb (bb
); !gsi_end_p (gsi
);
872 gimple stmt
= gsi_stmt (gsi
);
874 if (gimple_code (stmt
) != GIMPLE_DEBUG
)
876 hash_stmt (&hstate
, stmt
);
881 gcode_hash
= hstate
.end ();
882 bb_sizes
.safe_push (nondbg_stmt_count
);
884 /* Inserting basic block to hash table. */
885 sem_bb
*semantic_bb
= new sem_bb (bb
, nondbg_stmt_count
,
886 EDGE_COUNT (bb
->preds
) + EDGE_COUNT (bb
->succs
));
888 bb_sorted
.safe_push (semantic_bb
);
894 /* Improve accumulated hash for HSTATE based on a gimple statement STMT. */
897 sem_function::hash_stmt (inchash::hash
*hstate
, gimple stmt
)
899 enum gimple_code code
= gimple_code (stmt
);
901 hstate
->add_int (code
);
903 if (code
== GIMPLE_CALL
)
905 /* Checking of argument. */
906 for (unsigned i
= 0; i
< gimple_call_num_args (stmt
); ++i
)
908 tree argument
= gimple_call_arg (stmt
, i
);
910 switch (TREE_CODE (argument
))
913 if (tree_fits_shwi_p (argument
))
914 hstate
->add_wide_int (tree_to_shwi (argument
));
915 else if (tree_fits_uhwi_p (argument
))
916 hstate
->add_wide_int (tree_to_uhwi (argument
));
922 c
= TREE_REAL_CST (argument
);
923 n
= real_to_integer (&c
);
925 hstate
->add_wide_int (n
);
929 tree addr_operand
= TREE_OPERAND (argument
, 0);
931 if (TREE_CODE (addr_operand
) == STRING_CST
)
932 hstate
->add (TREE_STRING_POINTER (addr_operand
),
933 TREE_STRING_LENGTH (addr_operand
));
944 /* Return true if polymorphic comparison must be processed. */
947 sem_function::compare_polymorphic_p (void)
949 return get_node ()->callees
!= NULL
950 || get_node ()->indirect_calls
!= NULL
951 || m_compared_func
->get_node ()->callees
!= NULL
952 || m_compared_func
->get_node ()->indirect_calls
!= NULL
;
955 /* For a given call graph NODE, the function constructs new
956 semantic function item. */
959 sem_function::parse (cgraph_node
*node
, bitmap_obstack
*stack
)
961 tree fndecl
= node
->decl
;
962 function
*func
= DECL_STRUCT_FUNCTION (fndecl
);
964 /* TODO: add support for thunks and aliases. */
966 if (!func
|| !node
->has_gimple_body_p ())
969 if (lookup_attribute_by_prefix ("omp ", DECL_ATTRIBUTES (node
->decl
)) != NULL
)
972 sem_function
*f
= new sem_function (node
, 0, stack
);
979 /* Parses function arguments and result type. */
982 sem_function::parse_tree_args (void)
986 if (arg_types
.exists ())
987 arg_types
.release ();
989 arg_types
.create (4);
990 tree fnargs
= DECL_ARGUMENTS (decl
);
992 for (tree parm
= fnargs
; parm
; parm
= DECL_CHAIN (parm
))
993 arg_types
.safe_push (DECL_ARG_TYPE (parm
));
995 /* Function result type. */
996 result
= DECL_RESULT (decl
);
997 result_type
= result
? TREE_TYPE (result
) : NULL
;
999 /* During WPA, we can get arguments by following method. */
1002 tree type
= TYPE_ARG_TYPES (TREE_TYPE (decl
));
1003 for (tree parm
= type
; parm
; parm
= TREE_CHAIN (parm
))
1004 arg_types
.safe_push (TYPE_CANONICAL (TREE_VALUE (parm
)));
1006 result_type
= TREE_TYPE (TREE_TYPE (decl
));
1010 /* For given basic blocks BB1 and BB2 (from functions FUNC1 and FUNC),
1011 return true if phi nodes are semantically equivalent in these blocks . */
1014 sem_function::compare_phi_node (basic_block bb1
, basic_block bb2
)
1016 gphi_iterator si1
, si2
;
1018 unsigned size1
, size2
, i
;
1022 gcc_assert (bb1
!= NULL
);
1023 gcc_assert (bb2
!= NULL
);
1025 si2
= gsi_start_phis (bb2
);
1026 for (si1
= gsi_start_phis (bb1
); !gsi_end_p (si1
);
1029 gsi_next_nonvirtual_phi (&si1
);
1030 gsi_next_nonvirtual_phi (&si2
);
1032 if (gsi_end_p (si1
) && gsi_end_p (si2
))
1035 if (gsi_end_p (si1
) || gsi_end_p (si2
))
1036 return return_false();
1041 tree phi_result1
= gimple_phi_result (phi1
);
1042 tree phi_result2
= gimple_phi_result (phi2
);
1044 if (!m_checker
->compare_operand (phi_result1
, phi_result2
))
1045 return return_false_with_msg ("PHI results are different");
1047 size1
= gimple_phi_num_args (phi1
);
1048 size2
= gimple_phi_num_args (phi2
);
1051 return return_false ();
1053 for (i
= 0; i
< size1
; ++i
)
1055 t1
= gimple_phi_arg (phi1
, i
)->def
;
1056 t2
= gimple_phi_arg (phi2
, i
)->def
;
1058 if (!m_checker
->compare_operand (t1
, t2
))
1059 return return_false ();
1061 e1
= gimple_phi_arg_edge (phi1
, i
);
1062 e2
= gimple_phi_arg_edge (phi2
, i
);
1064 if (!m_checker
->compare_edge (e1
, e2
))
1065 return return_false ();
1074 /* Returns true if tree T can be compared as a handled component. */
1077 sem_function::icf_handled_component_p (tree t
)
1079 tree_code tc
= TREE_CODE (t
);
1081 return ((handled_component_p (t
))
1082 || tc
== ADDR_EXPR
|| tc
== MEM_REF
|| tc
== REALPART_EXPR
1083 || tc
== IMAGPART_EXPR
|| tc
== OBJ_TYPE_REF
);
1086 /* Basic blocks dictionary BB_DICT returns true if SOURCE index BB
1087 corresponds to TARGET. */
1090 sem_function::bb_dict_test (vec
<int> *bb_dict
, int source
, int target
)
1095 if (bb_dict
->length () <= (unsigned)source
)
1096 bb_dict
->safe_grow_cleared (source
+ 1);
1098 if ((*bb_dict
)[source
] == 0)
1100 (*bb_dict
)[source
] = target
;
1104 return (*bb_dict
)[source
] == target
;
1107 /* Iterates all tree types in T1 and T2 and returns true if all types
1108 are compatible. If COMPARE_POLYMORPHIC is set to true,
1109 more strict comparison is executed. */
1112 sem_function::compare_type_list (tree t1
, tree t2
, bool compare_polymorphic
)
1120 while (t1
!= NULL
&& t2
!= NULL
)
1122 tv1
= TREE_VALUE (t1
);
1123 tv2
= TREE_VALUE (t2
);
1125 tc1
= TREE_CODE (tv1
);
1126 tc2
= TREE_CODE (tv2
);
1128 if (tc1
== NOP_EXPR
&& tc2
== NOP_EXPR
)
1130 else if (tc1
== NOP_EXPR
|| tc2
== NOP_EXPR
)
1132 else if (!func_checker::compatible_types_p (tv1
, tv2
, compare_polymorphic
))
1135 t1
= TREE_CHAIN (t1
);
1136 t2
= TREE_CHAIN (t2
);
1143 /* Semantic variable constructor that uses STACK as bitmap memory stack. */
1145 sem_variable::sem_variable (bitmap_obstack
*stack
): sem_item (VAR
, stack
)
1149 /* Constructor based on varpool node _NODE with computed hash _HASH.
1150 Bitmap STACK is used for memory allocation. */
1152 sem_variable::sem_variable (varpool_node
*node
, hashval_t _hash
,
1153 bitmap_obstack
*stack
): sem_item(VAR
,
1156 gcc_checking_assert (node
);
1157 gcc_checking_assert (get_node ());
1160 /* Returns true if the item equals to ITEM given as argument. */
1163 sem_variable::equals (sem_item
*item
,
1164 hash_map
<symtab_node
*, sem_item
*> & ARG_UNUSED (ignored_nodes
))
1166 gcc_assert (item
->type
== VAR
);
1168 sem_variable
*v
= static_cast<sem_variable
*>(item
);
1170 if (!ctor
|| !v
->ctor
)
1171 return return_false_with_msg ("ctor is missing for semantic variable");
1173 return sem_variable::equals (ctor
, v
->ctor
);
1176 /* Compares trees T1 and T2 for semantic equality. */
1179 sem_variable::equals (tree t1
, tree t2
)
1181 tree_code tc1
= TREE_CODE (t1
);
1182 tree_code tc2
= TREE_CODE (t2
);
1191 unsigned len1
= vec_safe_length (CONSTRUCTOR_ELTS (t1
));
1192 unsigned len2
= vec_safe_length (CONSTRUCTOR_ELTS (t2
));
1197 for (unsigned i
= 0; i
< len1
; i
++)
1198 if (!sem_variable::equals (CONSTRUCTOR_ELT (t1
, i
)->value
,
1199 CONSTRUCTOR_ELT (t2
, i
)->value
)
1200 || CONSTRUCTOR_ELT (t1
, i
)->index
!= CONSTRUCTOR_ELT (t2
, i
)->index
)
1207 tree x1
= TREE_OPERAND (t1
, 0);
1208 tree x2
= TREE_OPERAND (t2
, 0);
1209 tree y1
= TREE_OPERAND (t1
, 1);
1210 tree y2
= TREE_OPERAND (t2
, 1);
1212 if (!func_checker::compatible_types_p (TREE_TYPE (x1
), TREE_TYPE (x2
),
1214 return return_false ();
1216 /* Type of the offset on MEM_REF does not matter. */
1217 return sem_variable::equals (x1
, x2
)
1218 && wi::to_offset (y1
) == wi::to_offset (y2
);
1223 tree op1
= TREE_OPERAND (t1
, 0);
1224 tree op2
= TREE_OPERAND (t2
, 0);
1225 return sem_variable::equals (op1
, op2
);
1233 return func_checker::compatible_types_p (TREE_TYPE (t1
), TREE_TYPE (t2
),
1235 && wi::to_offset (t1
) == wi::to_offset (t2
);
1239 return operand_equal_p (t1
, t2
, OEP_ONLY_CONST
);
1242 case POINTER_PLUS_EXPR
:
1244 tree x1
= TREE_OPERAND (t1
, 0);
1245 tree x2
= TREE_OPERAND (t2
, 0);
1246 tree y1
= TREE_OPERAND (t1
, 1);
1247 tree y2
= TREE_OPERAND (t2
, 1);
1249 return sem_variable::equals (x1
, x2
) && sem_variable::equals (y1
, y2
);
1252 return return_false_with_msg ("ERROR_MARK");
1254 return return_false_with_msg ("Unknown TREE code reached");
1258 /* Parser function that visits a varpool NODE. */
1261 sem_variable::parse (varpool_node
*node
, bitmap_obstack
*stack
)
1263 tree decl
= node
->decl
;
1265 bool readonly
= TYPE_P (decl
) ? TYPE_READONLY (decl
) : TREE_READONLY (decl
);
1269 bool can_handle
= DECL_VIRTUAL_P (decl
)
1270 || flag_merge_constants
>= 2
1271 || (!TREE_ADDRESSABLE (decl
) && !node
->externally_visible
);
1273 if (!can_handle
|| DECL_EXTERNAL (decl
))
1276 tree ctor
= ctor_for_folding (decl
);
1280 sem_variable
*v
= new sem_variable (node
, 0, stack
);
1287 /* References independent hash function. */
1290 sem_variable::get_hash (void)
1295 inchash::hash hstate
;
1297 hstate
.add_int (456346417);
1298 hstate
.add_int (TREE_CODE (ctor
));
1300 if (TREE_CODE (ctor
) == CONSTRUCTOR
)
1302 unsigned length
= vec_safe_length (CONSTRUCTOR_ELTS (ctor
));
1303 hstate
.add_int (length
);
1306 hash
= hstate
.end ();
1311 /* Merges instance with an ALIAS_ITEM, where alias, thunk or redirection can
1315 sem_variable::merge (sem_item
*alias_item
)
1317 gcc_assert (alias_item
->type
== VAR
);
1319 if (!sem_item::target_supports_symbol_aliases_p ())
1322 fprintf (dump_file
, "Symbol aliases are not supported by target\n\n");
1326 sem_variable
*alias_var
= static_cast<sem_variable
*> (alias_item
);
1328 varpool_node
*original
= get_node ();
1329 varpool_node
*alias
= alias_var
->get_node ();
1330 bool original_discardable
= false;
1332 /* See if original is in a section that can be discarded if the main
1333 symbol is not used. */
1334 if (DECL_EXTERNAL (original
->decl
))
1335 original_discardable
= true;
1336 if (original
->resolution
== LDPR_PREEMPTED_REG
1337 || original
->resolution
== LDPR_PREEMPTED_IR
)
1338 original_discardable
= true;
1339 if (original
->can_be_discarded_p ())
1340 original_discardable
= true;
1342 gcc_assert (!TREE_ASM_WRITTEN (alias
->decl
));
1344 if (original_discardable
|| DECL_EXTERNAL (alias_var
->decl
) ||
1345 !compare_sections (alias_var
))
1348 fprintf (dump_file
, "Varpool alias cannot be created\n\n");
1354 // alias cycle creation check
1355 varpool_node
*n
= original
;
1359 n
= n
->get_alias_target ();
1363 fprintf (dump_file
, "Varpool alias cannot be created (alias cycle).\n\n");
1369 alias
->analyzed
= false;
1371 DECL_INITIAL (alias
->decl
) = NULL
;
1372 alias
->need_bounds_init
= false;
1373 alias
->remove_all_references ();
1375 varpool_node::create_alias (alias_var
->decl
, decl
);
1376 alias
->resolve_alias (original
);
1379 fprintf (dump_file
, "Varpool alias has been created.\n\n");
1386 sem_variable::compare_sections (sem_variable
*alias
)
1388 const char *source
= node
->get_section ();
1389 const char *target
= alias
->node
->get_section();
1391 if (source
== NULL
&& target
== NULL
)
1393 else if(!source
|| !target
)
1396 return strcmp (source
, target
) == 0;
1399 /* Dump symbol to FILE. */
1402 sem_variable::dump_to_file (FILE *file
)
1406 print_node (file
, "", decl
, 0);
1407 fprintf (file
, "\n\n");
1410 /* Iterates though a constructor and identifies tree references
1411 we are interested in semantic function equality. */
1414 sem_variable::parse_tree_refs (tree t
)
1416 switch (TREE_CODE (t
))
1420 unsigned length
= vec_safe_length (CONSTRUCTOR_ELTS (t
));
1422 for (unsigned i
= 0; i
< length
; i
++)
1423 parse_tree_refs(CONSTRUCTOR_ELT (t
, i
)->value
);
1430 tree op
= TREE_OPERAND (t
, 0);
1431 parse_tree_refs (op
);
1436 tree_refs
.safe_push (t
);
1444 unsigned int sem_item_optimizer::class_id
= 0;
1446 sem_item_optimizer::sem_item_optimizer (): worklist (0), m_classes (0),
1447 m_classes_count (0), m_cgraph_node_hooks (NULL
), m_varpool_node_hooks (NULL
)
1450 bitmap_obstack_initialize (&m_bmstack
);
1453 sem_item_optimizer::~sem_item_optimizer ()
1455 for (unsigned int i
= 0; i
< m_items
.length (); i
++)
1458 for (hash_table
<congruence_class_group_hash
>::iterator it
= m_classes
.begin ();
1459 it
!= m_classes
.end (); ++it
)
1461 for (unsigned int i
= 0; i
< (*it
)->classes
.length (); i
++)
1462 delete (*it
)->classes
[i
];
1464 (*it
)->classes
.release ();
1470 bitmap_obstack_release (&m_bmstack
);
1473 /* Write IPA ICF summary for symbols. */
1476 sem_item_optimizer::write_summary (void)
1478 unsigned int count
= 0;
1480 output_block
*ob
= create_output_block (LTO_section_ipa_icf
);
1481 lto_symtab_encoder_t encoder
= ob
->decl_state
->symtab_node_encoder
;
1484 /* Calculate number of symbols to be serialized. */
1485 for (lto_symtab_encoder_iterator lsei
= lsei_start_in_partition (encoder
);
1487 lsei_next_in_partition (&lsei
))
1489 symtab_node
*node
= lsei_node (lsei
);
1491 if (m_symtab_node_map
.get (node
))
1495 streamer_write_uhwi (ob
, count
);
1497 /* Process all of the symbols. */
1498 for (lto_symtab_encoder_iterator lsei
= lsei_start_in_partition (encoder
);
1500 lsei_next_in_partition (&lsei
))
1502 symtab_node
*node
= lsei_node (lsei
);
1504 sem_item
**item
= m_symtab_node_map
.get (node
);
1508 int node_ref
= lto_symtab_encoder_encode (encoder
, node
);
1509 streamer_write_uhwi_stream (ob
->main_stream
, node_ref
);
1511 streamer_write_uhwi (ob
, (*item
)->get_hash ());
1515 streamer_write_char_stream (ob
->main_stream
, 0);
1516 produce_asm (ob
, NULL
);
1517 destroy_output_block (ob
);
1520 /* Reads a section from LTO stream file FILE_DATA. Input block for DATA
1521 contains LEN bytes. */
1524 sem_item_optimizer::read_section (lto_file_decl_data
*file_data
,
1525 const char *data
, size_t len
)
1527 const lto_function_header
*header
=
1528 (const lto_function_header
*) data
;
1529 const int cfg_offset
= sizeof (lto_function_header
);
1530 const int main_offset
= cfg_offset
+ header
->cfg_size
;
1531 const int string_offset
= main_offset
+ header
->main_size
;
1536 lto_input_block
ib_main ((const char *) data
+ main_offset
, 0,
1537 header
->main_size
, file_data
->mode_table
);
1540 lto_data_in_create (file_data
, (const char *) data
+ string_offset
,
1541 header
->string_size
, vNULL
);
1543 count
= streamer_read_uhwi (&ib_main
);
1545 for (i
= 0; i
< count
; i
++)
1549 lto_symtab_encoder_t encoder
;
1551 index
= streamer_read_uhwi (&ib_main
);
1552 encoder
= file_data
->symtab_node_encoder
;
1553 node
= lto_symtab_encoder_deref (encoder
, index
);
1555 hashval_t hash
= streamer_read_uhwi (&ib_main
);
1557 gcc_assert (node
->definition
);
1560 fprintf (dump_file
, "Symbol added:%s (tree: %p, uid:%u)\n", node
->asm_name (),
1561 (void *) node
->decl
, node
->order
);
1563 if (is_a
<cgraph_node
*> (node
))
1565 cgraph_node
*cnode
= dyn_cast
<cgraph_node
*> (node
);
1567 m_items
.safe_push (new sem_function (cnode
, hash
, &m_bmstack
));
1571 varpool_node
*vnode
= dyn_cast
<varpool_node
*> (node
);
1573 m_items
.safe_push (new sem_variable (vnode
, hash
, &m_bmstack
));
1577 lto_free_section_data (file_data
, LTO_section_ipa_icf
, NULL
, data
,
1579 lto_data_in_delete (data_in
);
1582 /* Read IPA IPA ICF summary for symbols. */
1585 sem_item_optimizer::read_summary (void)
1587 lto_file_decl_data
**file_data_vec
= lto_get_file_decl_data ();
1588 lto_file_decl_data
*file_data
;
1591 while ((file_data
= file_data_vec
[j
++]))
1594 const char *data
= lto_get_section_data (file_data
,
1595 LTO_section_ipa_icf
, NULL
, &len
);
1598 read_section (file_data
, data
, len
);
1602 /* Register callgraph and varpool hooks. */
1605 sem_item_optimizer::register_hooks (void)
1607 if (!m_cgraph_node_hooks
)
1608 m_cgraph_node_hooks
= symtab
->add_cgraph_removal_hook
1609 (&sem_item_optimizer::cgraph_removal_hook
, this);
1611 if (!m_varpool_node_hooks
)
1612 m_varpool_node_hooks
= symtab
->add_varpool_removal_hook
1613 (&sem_item_optimizer::varpool_removal_hook
, this);
1616 /* Unregister callgraph and varpool hooks. */
1619 sem_item_optimizer::unregister_hooks (void)
1621 if (m_cgraph_node_hooks
)
1622 symtab
->remove_cgraph_removal_hook (m_cgraph_node_hooks
);
1624 if (m_varpool_node_hooks
)
1625 symtab
->remove_varpool_removal_hook (m_varpool_node_hooks
);
1628 /* Adds a CLS to hashtable associated by hash value. */
1631 sem_item_optimizer::add_class (congruence_class
*cls
)
1633 gcc_assert (cls
->members
.length ());
1635 congruence_class_group
*group
= get_group_by_hash (
1636 cls
->members
[0]->get_hash (),
1637 cls
->members
[0]->type
);
1638 group
->classes
.safe_push (cls
);
1641 /* Gets a congruence class group based on given HASH value and TYPE. */
1643 congruence_class_group
*
1644 sem_item_optimizer::get_group_by_hash (hashval_t hash
, sem_item_type type
)
1646 congruence_class_group
*item
= XNEW (congruence_class_group
);
1650 congruence_class_group
**slot
= m_classes
.find_slot (item
, INSERT
);
1656 item
->classes
.create (1);
1663 /* Callgraph removal hook called for a NODE with a custom DATA. */
1666 sem_item_optimizer::cgraph_removal_hook (cgraph_node
*node
, void *data
)
1668 sem_item_optimizer
*optimizer
= (sem_item_optimizer
*) data
;
1669 optimizer
->remove_symtab_node (node
);
1672 /* Varpool removal hook called for a NODE with a custom DATA. */
1675 sem_item_optimizer::varpool_removal_hook (varpool_node
*node
, void *data
)
1677 sem_item_optimizer
*optimizer
= (sem_item_optimizer
*) data
;
1678 optimizer
->remove_symtab_node (node
);
1681 /* Remove symtab NODE triggered by symtab removal hooks. */
1684 sem_item_optimizer::remove_symtab_node (symtab_node
*node
)
1686 gcc_assert (!m_classes
.elements());
1688 m_removed_items_set
.add (node
);
1692 sem_item_optimizer::remove_item (sem_item
*item
)
1694 if (m_symtab_node_map
.get (item
->node
))
1695 m_symtab_node_map
.remove (item
->node
);
1699 /* Removes all callgraph and varpool nodes that are marked by symtab
1703 sem_item_optimizer::filter_removed_items (void)
1705 auto_vec
<sem_item
*> filtered
;
1707 for (unsigned int i
= 0; i
< m_items
.length(); i
++)
1709 sem_item
*item
= m_items
[i
];
1711 if (m_removed_items_set
.contains (item
->node
))
1717 if (item
->type
== FUNC
)
1719 cgraph_node
*cnode
= static_cast <sem_function
*>(item
)->get_node ();
1721 bool no_body_function
= in_lto_p
&& (cnode
->alias
|| cnode
->body_removed
);
1722 if (no_body_function
|| !opt_for_fn (item
->decl
, flag_ipa_icf_functions
)
1723 || DECL_CXX_CONSTRUCTOR_P (item
->decl
)
1724 || DECL_CXX_DESTRUCTOR_P (item
->decl
))
1727 filtered
.safe_push (item
);
1731 if (!flag_ipa_icf_variables
)
1734 filtered
.safe_push (item
);
1738 /* Clean-up of released semantic items. */
1741 for (unsigned int i
= 0; i
< filtered
.length(); i
++)
1742 m_items
.safe_push (filtered
[i
]);
1745 /* Optimizer entry point. */
1748 sem_item_optimizer::execute (void)
1750 filter_removed_items ();
1751 unregister_hooks ();
1753 build_hash_based_classes ();
1756 fprintf (dump_file
, "Dump after hash based groups\n");
1757 dump_cong_classes ();
1759 for (unsigned int i
= 0; i
< m_items
.length(); i
++)
1760 m_items
[i
]->init_wpa ();
1764 subdivide_classes_by_equality (true);
1767 fprintf (dump_file
, "Dump after WPA based types groups\n");
1769 dump_cong_classes ();
1771 process_cong_reduction ();
1775 fprintf (dump_file
, "Dump after callgraph-based congruence reduction\n");
1777 dump_cong_classes ();
1779 parse_nonsingleton_classes ();
1780 subdivide_classes_by_equality ();
1783 fprintf (dump_file
, "Dump after full equality comparison of groups\n");
1785 dump_cong_classes ();
1787 unsigned int prev_class_count
= m_classes_count
;
1789 process_cong_reduction ();
1790 dump_cong_classes ();
1792 merge_classes (prev_class_count
);
1794 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
1795 symtab_node::dump_table (dump_file
);
1798 /* Function responsible for visiting all potential functions and
1799 read-only variables that can be merged. */
1802 sem_item_optimizer::parse_funcs_and_vars (void)
1806 if (flag_ipa_icf_functions
)
1807 FOR_EACH_DEFINED_FUNCTION (cnode
)
1809 sem_function
*f
= sem_function::parse (cnode
, &m_bmstack
);
1812 m_items
.safe_push (f
);
1813 m_symtab_node_map
.put (cnode
, f
);
1816 fprintf (dump_file
, "Parsed function:%s\n", f
->asm_name ());
1818 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
1819 f
->dump_to_file (dump_file
);
1822 fprintf (dump_file
, "Not parsed function:%s\n", cnode
->asm_name ());
1825 varpool_node
*vnode
;
1827 if (flag_ipa_icf_variables
)
1828 FOR_EACH_DEFINED_VARIABLE (vnode
)
1830 sem_variable
*v
= sem_variable::parse (vnode
, &m_bmstack
);
1834 m_items
.safe_push (v
);
1835 m_symtab_node_map
.put (vnode
, v
);
1840 /* Makes pairing between a congruence class CLS and semantic ITEM. */
1843 sem_item_optimizer::add_item_to_class (congruence_class
*cls
, sem_item
*item
)
1845 item
->index_in_class
= cls
->members
.length ();
1846 cls
->members
.safe_push (item
);
1850 /* Congruence classes are built by hash value. */
1853 sem_item_optimizer::build_hash_based_classes (void)
1855 for (unsigned i
= 0; i
< m_items
.length (); i
++)
1857 sem_item
*item
= m_items
[i
];
1859 congruence_class_group
*group
= get_group_by_hash (item
->get_hash (),
1862 if (!group
->classes
.length ())
1865 group
->classes
.safe_push (new congruence_class (class_id
++));
1868 add_item_to_class (group
->classes
[0], item
);
1872 /* Build references according to call graph. */
1875 sem_item_optimizer::build_graph (void)
1877 for (unsigned i
= 0; i
< m_items
.length (); i
++)
1879 sem_item
*item
= m_items
[i
];
1880 m_symtab_node_map
.put (item
->node
, item
);
1883 for (unsigned i
= 0; i
< m_items
.length (); i
++)
1885 sem_item
*item
= m_items
[i
];
1887 if (item
->type
== FUNC
)
1889 cgraph_node
*cnode
= dyn_cast
<cgraph_node
*> (item
->node
);
1891 cgraph_edge
*e
= cnode
->callees
;
1894 sem_item
**slot
= m_symtab_node_map
.get (e
->callee
);
1896 item
->add_reference (*slot
);
1902 ipa_ref
*ref
= NULL
;
1903 for (unsigned i
= 0; item
->node
->iterate_reference (i
, ref
); i
++)
1905 sem_item
**slot
= m_symtab_node_map
.get (ref
->referred
);
1907 item
->add_reference (*slot
);
1912 /* Semantic items in classes having more than one element and initialized.
1913 In case of WPA, we load function body. */
1916 sem_item_optimizer::parse_nonsingleton_classes (void)
1918 unsigned int init_called_count
= 0;
1920 for (unsigned i
= 0; i
< m_items
.length (); i
++)
1921 if (m_items
[i
]->cls
->members
.length () > 1)
1923 m_items
[i
]->init ();
1924 init_called_count
++;
1928 fprintf (dump_file
, "Init called for %u items (%.2f%%).\n", init_called_count
,
1929 m_items
.length () ? 100.0f
* init_called_count
/ m_items
.length (): 0.0f
);
1932 /* Equality function for semantic items is used to subdivide existing
1933 classes. If IN_WPA, fast equality function is invoked. */
1936 sem_item_optimizer::subdivide_classes_by_equality (bool in_wpa
)
1938 for (hash_table
<congruence_class_group_hash
>::iterator it
= m_classes
.begin ();
1939 it
!= m_classes
.end (); ++it
)
1941 unsigned int class_count
= (*it
)->classes
.length ();
1943 for (unsigned i
= 0; i
< class_count
; i
++)
1945 congruence_class
*c
= (*it
)->classes
[i
];
1947 if (c
->members
.length() > 1)
1949 auto_vec
<sem_item
*> new_vector
;
1951 sem_item
*first
= c
->members
[0];
1952 new_vector
.safe_push (first
);
1954 unsigned class_split_first
= (*it
)->classes
.length ();
1956 for (unsigned j
= 1; j
< c
->members
.length (); j
++)
1958 sem_item
*item
= c
->members
[j
];
1960 bool equals
= in_wpa
? first
->equals_wpa (item
,
1961 m_symtab_node_map
) : first
->equals (item
, m_symtab_node_map
);
1964 new_vector
.safe_push (item
);
1967 bool integrated
= false;
1969 for (unsigned k
= class_split_first
; k
< (*it
)->classes
.length (); k
++)
1971 sem_item
*x
= (*it
)->classes
[k
]->members
[0];
1972 bool equals
= in_wpa
? x
->equals_wpa (item
,
1973 m_symtab_node_map
) : x
->equals (item
, m_symtab_node_map
);
1978 add_item_to_class ((*it
)->classes
[k
], item
);
1986 congruence_class
*c
= new congruence_class (class_id
++);
1988 add_item_to_class (c
, item
);
1990 (*it
)->classes
.safe_push (c
);
1995 // we replace newly created new_vector for the class we've just splitted
1996 c
->members
.release ();
1997 c
->members
.create (new_vector
.length ());
1999 for (unsigned int j
= 0; j
< new_vector
.length (); j
++)
2000 add_item_to_class (c
, new_vector
[j
]);
2008 /* Subdivide classes by address references that members of the class
2009 reference. Example can be a pair of functions that have an address
2010 taken from a function. If these addresses are different the class
2014 sem_item_optimizer::subdivide_classes_by_sensitive_refs ()
2016 unsigned newly_created_classes
= 0;
2018 for (hash_table
<congruence_class_group_hash
>::iterator it
= m_classes
.begin ();
2019 it
!= m_classes
.end (); ++it
)
2021 unsigned int class_count
= (*it
)->classes
.length ();
2022 auto_vec
<congruence_class
*> new_classes
;
2024 for (unsigned i
= 0; i
< class_count
; i
++)
2026 congruence_class
*c
= (*it
)->classes
[i
];
2028 if (c
->members
.length() > 1)
2030 hash_map
<symbol_compare_collection
*, vec
<sem_item
*>,
2031 symbol_compare_hashmap_traits
> split_map
;
2033 for (unsigned j
= 0; j
< c
->members
.length (); j
++)
2035 sem_item
*source_node
= c
->members
[j
];
2037 symbol_compare_collection
*collection
= new symbol_compare_collection (source_node
->node
);
2039 vec
<sem_item
*> *slot
= &split_map
.get_or_insert (collection
);
2040 gcc_checking_assert (slot
);
2042 slot
->safe_push (source_node
);
2045 /* If the map contains more than one key, we have to split the map
2047 if (split_map
.elements () != 1)
2049 bool first_class
= true;
2051 hash_map
<symbol_compare_collection
*, vec
<sem_item
*>,
2052 symbol_compare_hashmap_traits
>::iterator it2
= split_map
.begin ();
2053 for (; it2
!= split_map
.end (); ++it2
)
2055 congruence_class
*new_cls
;
2056 new_cls
= new congruence_class (class_id
++);
2058 for (unsigned k
= 0; k
< (*it2
).second
.length (); k
++)
2059 add_item_to_class (new_cls
, (*it2
).second
[k
]);
2061 worklist_push (new_cls
);
2062 newly_created_classes
++;
2066 (*it
)->classes
[i
] = new_cls
;
2067 first_class
= false;
2071 new_classes
.safe_push (new_cls
);
2079 for (unsigned i
= 0; i
< new_classes
.length (); i
++)
2080 (*it
)->classes
.safe_push (new_classes
[i
]);
2083 return newly_created_classes
;
2086 /* Verify congruence classes if checking is enabled. */
2089 sem_item_optimizer::verify_classes (void)
2092 for (hash_table
<congruence_class_group_hash
>::iterator it
= m_classes
.begin ();
2093 it
!= m_classes
.end (); ++it
)
2095 for (unsigned int i
= 0; i
< (*it
)->classes
.length (); i
++)
2097 congruence_class
*cls
= (*it
)->classes
[i
];
2099 gcc_checking_assert (cls
);
2100 gcc_checking_assert (cls
->members
.length () > 0);
2102 for (unsigned int j
= 0; j
< cls
->members
.length (); j
++)
2104 sem_item
*item
= cls
->members
[j
];
2106 gcc_checking_assert (item
);
2107 gcc_checking_assert (item
->cls
== cls
);
2109 for (unsigned k
= 0; k
< item
->usages
.length (); k
++)
2111 sem_usage_pair
*usage
= item
->usages
[k
];
2112 gcc_checking_assert (usage
->item
->index_in_class
<
2113 usage
->item
->cls
->members
.length ());
2121 /* Disposes split map traverse function. CLS_PTR is pointer to congruence
2122 class, BSLOT is bitmap slot we want to release. DATA is mandatory,
2123 but unused argument. */
2126 sem_item_optimizer::release_split_map (congruence_class
* const &,
2127 bitmap
const &b
, traverse_split_pair
*)
2136 /* Process split operation for a class given as pointer CLS_PTR,
2137 where bitmap B splits congruence class members. DATA is used
2138 as argument of split pair. */
2141 sem_item_optimizer::traverse_congruence_split (congruence_class
* const &cls
,
2142 bitmap
const &b
, traverse_split_pair
*pair
)
2144 sem_item_optimizer
*optimizer
= pair
->optimizer
;
2145 const congruence_class
*splitter_cls
= pair
->cls
;
2147 /* If counted bits are greater than zero and less than the number of members
2148 a group will be splitted. */
2149 unsigned popcount
= bitmap_count_bits (b
);
2151 if (popcount
> 0 && popcount
< cls
->members
.length ())
2153 congruence_class
* newclasses
[2] = { new congruence_class (class_id
++), new congruence_class (class_id
++) };
2155 for (unsigned int i
= 0; i
< cls
->members
.length (); i
++)
2157 int target
= bitmap_bit_p (b
, i
);
2158 congruence_class
*tc
= newclasses
[target
];
2160 add_item_to_class (tc
, cls
->members
[i
]);
2163 #ifdef ENABLE_CHECKING
2164 for (unsigned int i
= 0; i
< 2; i
++)
2165 gcc_checking_assert (newclasses
[i
]->members
.length ());
2168 if (splitter_cls
== cls
)
2169 optimizer
->splitter_class_removed
= true;
2171 /* Remove old class from worklist if presented. */
2172 bool in_worklist
= cls
->in_worklist
;
2175 cls
->in_worklist
= false;
2177 congruence_class_group g
;
2178 g
.hash
= cls
->members
[0]->get_hash ();
2179 g
.type
= cls
->members
[0]->type
;
2181 congruence_class_group
*slot
= optimizer
->m_classes
.find(&g
);
2183 for (unsigned int i
= 0; i
< slot
->classes
.length (); i
++)
2184 if (slot
->classes
[i
] == cls
)
2186 slot
->classes
.ordered_remove (i
);
2190 /* New class will be inserted and integrated to work list. */
2191 for (unsigned int i
= 0; i
< 2; i
++)
2192 optimizer
->add_class (newclasses
[i
]);
2194 /* Two classes replace one, so that increment just by one. */
2195 optimizer
->m_classes_count
++;
2197 /* If OLD class was presented in the worklist, we remove the class
2198 and replace it will both newly created classes. */
2200 for (unsigned int i
= 0; i
< 2; i
++)
2201 optimizer
->worklist_push (newclasses
[i
]);
2202 else /* Just smaller class is inserted. */
2204 unsigned int smaller_index
= newclasses
[0]->members
.length () <
2205 newclasses
[1]->members
.length () ?
2207 optimizer
->worklist_push (newclasses
[smaller_index
]);
2210 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
2212 fprintf (dump_file
, " congruence class splitted:\n");
2213 cls
->dump (dump_file
, 4);
2215 fprintf (dump_file
, " newly created groups:\n");
2216 for (unsigned int i
= 0; i
< 2; i
++)
2217 newclasses
[i
]->dump (dump_file
, 4);
2220 /* Release class if not presented in work list. */
2229 /* Tests if a class CLS used as INDEXth splits any congruence classes.
2230 Bitmap stack BMSTACK is used for bitmap allocation. */
2233 sem_item_optimizer::do_congruence_step_for_index (congruence_class
*cls
,
2236 hash_map
<congruence_class
*, bitmap
> split_map
;
2238 for (unsigned int i
= 0; i
< cls
->members
.length (); i
++)
2240 sem_item
*item
= cls
->members
[i
];
2242 /* Iterate all usages that have INDEX as usage of the item. */
2243 for (unsigned int j
= 0; j
< item
->usages
.length (); j
++)
2245 sem_usage_pair
*usage
= item
->usages
[j
];
2247 if (usage
->index
!= index
)
2250 bitmap
*slot
= split_map
.get (usage
->item
->cls
);
2255 b
= BITMAP_ALLOC (&m_bmstack
);
2256 split_map
.put (usage
->item
->cls
, b
);
2262 gcc_checking_assert (usage
->item
->cls
);
2263 gcc_checking_assert (usage
->item
->index_in_class
<
2264 usage
->item
->cls
->members
.length ());
2267 bitmap_set_bit (b
, usage
->item
->index_in_class
);
2271 traverse_split_pair pair
;
2272 pair
.optimizer
= this;
2275 splitter_class_removed
= false;
2277 <traverse_split_pair
*, sem_item_optimizer::traverse_congruence_split
> (&pair
);
2279 /* Bitmap clean-up. */
2281 <traverse_split_pair
*, sem_item_optimizer::release_split_map
> (NULL
);
2284 /* Every usage of a congruence class CLS is a candidate that can split the
2285 collection of classes. Bitmap stack BMSTACK is used for bitmap
2289 sem_item_optimizer::do_congruence_step (congruence_class
*cls
)
2294 bitmap usage
= BITMAP_ALLOC (&m_bmstack
);
2296 for (unsigned int i
= 0; i
< cls
->members
.length (); i
++)
2297 bitmap_ior_into (usage
, cls
->members
[i
]->usage_index_bitmap
);
2299 EXECUTE_IF_SET_IN_BITMAP (usage
, 0, i
, bi
)
2301 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
2302 fprintf (dump_file
, " processing congruece step for class: %u, index: %u\n",
2305 do_congruence_step_for_index (cls
, i
);
2307 if (splitter_class_removed
)
2311 BITMAP_FREE (usage
);
2314 /* Adds a newly created congruence class CLS to worklist. */
2317 sem_item_optimizer::worklist_push (congruence_class
*cls
)
2319 /* Return if the class CLS is already presented in work list. */
2320 if (cls
->in_worklist
)
2323 cls
->in_worklist
= true;
2324 worklist
.push_back (cls
);
2327 /* Pops a class from worklist. */
2330 sem_item_optimizer::worklist_pop (void)
2332 congruence_class
*cls
;
2334 while (!worklist
.empty ())
2336 cls
= worklist
.front ();
2337 worklist
.pop_front ();
2338 if (cls
->in_worklist
)
2340 cls
->in_worklist
= false;
2346 /* Work list item was already intended to be removed.
2347 The only reason for doing it is to split a class.
2348 Thus, the class CLS is deleted. */
2356 /* Iterative congruence reduction function. */
2359 sem_item_optimizer::process_cong_reduction (void)
2361 for (hash_table
<congruence_class_group_hash
>::iterator it
= m_classes
.begin ();
2362 it
!= m_classes
.end (); ++it
)
2363 for (unsigned i
= 0; i
< (*it
)->classes
.length (); i
++)
2364 if ((*it
)->classes
[i
]->is_class_used ())
2365 worklist_push ((*it
)->classes
[i
]);
2368 fprintf (dump_file
, "Worklist has been filled with: %lu\n",
2369 (unsigned long) worklist
.size ());
2371 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
2372 fprintf (dump_file
, "Congruence class reduction\n");
2374 congruence_class
*cls
;
2376 /* Process complete congruence reduction. */
2377 while ((cls
= worklist_pop ()) != NULL
)
2378 do_congruence_step (cls
);
2380 /* Subdivide newly created classes according to references. */
2381 unsigned new_classes
= subdivide_classes_by_sensitive_refs ();
2384 fprintf (dump_file
, "Address reference subdivision created: %u "
2385 "new classes.\n", new_classes
);
2388 /* Debug function prints all informations about congruence classes. */
2391 sem_item_optimizer::dump_cong_classes (void)
2397 "Congruence classes: %u (unique hash values: %lu), with total: %u items\n",
2398 m_classes_count
, (unsigned long) m_classes
.elements(), m_items
.length ());
2400 /* Histogram calculation. */
2401 unsigned int max_index
= 0;
2402 unsigned int* histogram
= XCNEWVEC (unsigned int, m_items
.length () + 1);
2404 for (hash_table
<congruence_class_group_hash
>::iterator it
= m_classes
.begin ();
2405 it
!= m_classes
.end (); ++it
)
2407 for (unsigned i
= 0; i
< (*it
)->classes
.length (); i
++)
2409 unsigned int c
= (*it
)->classes
[i
]->members
.length ();
2417 "Class size histogram [num of members]: number of classe number of classess\n");
2419 for (unsigned int i
= 0; i
<= max_index
; i
++)
2421 fprintf (dump_file
, "[%u]: %u classes\n", i
, histogram
[i
]);
2423 fprintf (dump_file
, "\n\n");
2426 if (dump_flags
& TDF_DETAILS
)
2427 for (hash_table
<congruence_class_group_hash
>::iterator it
= m_classes
.begin ();
2428 it
!= m_classes
.end (); ++it
)
2430 fprintf (dump_file
, " group: with %u classes:\n", (*it
)->classes
.length ());
2432 for (unsigned i
= 0; i
< (*it
)->classes
.length (); i
++)
2434 (*it
)->classes
[i
]->dump (dump_file
, 4);
2436 if(i
< (*it
)->classes
.length () - 1)
2437 fprintf (dump_file
, " ");
2444 /* After reduction is done, we can declare all items in a group
2445 to be equal. PREV_CLASS_COUNT is start number of classes
2446 before reduction. */
2449 sem_item_optimizer::merge_classes (unsigned int prev_class_count
)
2451 unsigned int item_count
= m_items
.length ();
2452 unsigned int class_count
= m_classes_count
;
2453 unsigned int equal_items
= item_count
- class_count
;
2455 unsigned int non_singular_classes_count
= 0;
2456 unsigned int non_singular_classes_sum
= 0;
2458 for (hash_table
<congruence_class_group_hash
>::iterator it
= m_classes
.begin ();
2459 it
!= m_classes
.end (); ++it
)
2460 for (unsigned int i
= 0; i
< (*it
)->classes
.length (); i
++)
2462 congruence_class
*c
= (*it
)->classes
[i
];
2463 if (c
->members
.length () > 1)
2465 non_singular_classes_count
++;
2466 non_singular_classes_sum
+= c
->members
.length ();
2472 fprintf (dump_file
, "\nItem count: %u\n", item_count
);
2473 fprintf (dump_file
, "Congruent classes before: %u, after: %u\n",
2474 prev_class_count
, class_count
);
2475 fprintf (dump_file
, "Average class size before: %.2f, after: %.2f\n",
2476 prev_class_count
? 1.0f
* item_count
/ prev_class_count
: 0.0f
,
2477 class_count
? 1.0f
* item_count
/ class_count
: 0.0f
);
2478 fprintf (dump_file
, "Average non-singular class size: %.2f, count: %u\n",
2479 non_singular_classes_count
? 1.0f
* non_singular_classes_sum
/
2480 non_singular_classes_count
: 0.0f
,
2481 non_singular_classes_count
);
2482 fprintf (dump_file
, "Equal symbols: %u\n", equal_items
);
2483 fprintf (dump_file
, "Fraction of visited symbols: %.2f%%\n\n",
2484 item_count
? 100.0f
* equal_items
/ item_count
: 0.0f
);
2487 for (hash_table
<congruence_class_group_hash
>::iterator it
= m_classes
.begin ();
2488 it
!= m_classes
.end (); ++it
)
2489 for (unsigned int i
= 0; i
< (*it
)->classes
.length (); i
++)
2491 congruence_class
*c
= (*it
)->classes
[i
];
2493 if (c
->members
.length () == 1)
2496 gcc_assert (c
->members
.length ());
2498 sem_item
*source
= c
->members
[0];
2500 for (unsigned int j
= 1; j
< c
->members
.length (); j
++)
2502 sem_item
*alias
= c
->members
[j
];
2506 fprintf (dump_file
, "Semantic equality hit:%s->%s\n",
2507 source
->name (), alias
->name ());
2508 fprintf (dump_file
, "Assembler symbol names:%s->%s\n",
2509 source
->asm_name (), alias
->asm_name ());
2512 if (lookup_attribute ("no_icf", DECL_ATTRIBUTES (alias
->decl
)))
2516 "Merge operation is skipped due to no_icf "
2522 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
2524 source
->dump_to_file (dump_file
);
2525 alias
->dump_to_file (dump_file
);
2528 source
->merge (alias
);
2533 /* Dump function prints all class members to a FILE with an INDENT. */
2536 congruence_class::dump (FILE *file
, unsigned int indent
) const
2538 FPRINTF_SPACES (file
, indent
, "class with id: %u, hash: %u, items: %u\n",
2539 id
, members
[0]->get_hash (), members
.length ());
2541 FPUTS_SPACES (file
, indent
+ 2, "");
2542 for (unsigned i
= 0; i
< members
.length (); i
++)
2543 fprintf (file
, "%s(%p/%u) ", members
[i
]->asm_name (), (void *) members
[i
]->decl
,
2544 members
[i
]->node
->order
);
2546 fprintf (file
, "\n");
2549 /* Returns true if there's a member that is used from another group. */
2552 congruence_class::is_class_used (void)
2554 for (unsigned int i
= 0; i
< members
.length (); i
++)
2555 if (members
[i
]->usages
.length ())
2561 /* Initialization and computation of symtab node hash, there data
2562 are propagated later on. */
2564 static sem_item_optimizer
*optimizer
= NULL
;
2566 /* Generate pass summary for IPA ICF pass. */
2569 ipa_icf_generate_summary (void)
2572 optimizer
= new sem_item_optimizer ();
2574 optimizer
->register_hooks ();
2575 optimizer
->parse_funcs_and_vars ();
2578 /* Write pass summary for IPA ICF pass. */
2581 ipa_icf_write_summary (void)
2583 gcc_assert (optimizer
);
2585 optimizer
->write_summary ();
2588 /* Read pass summary for IPA ICF pass. */
2591 ipa_icf_read_summary (void)
2594 optimizer
= new sem_item_optimizer ();
2596 optimizer
->read_summary ();
2597 optimizer
->register_hooks ();
2600 /* Semantic equality exection function. */
2603 ipa_icf_driver (void)
2605 gcc_assert (optimizer
);
2607 optimizer
->execute ();
2615 const pass_data pass_data_ipa_icf
=
2617 IPA_PASS
, /* type */
2619 OPTGROUP_IPA
, /* optinfo_flags */
2620 TV_IPA_ICF
, /* tv_id */
2621 0, /* properties_required */
2622 0, /* properties_provided */
2623 0, /* properties_destroyed */
2624 0, /* todo_flags_start */
2625 0, /* todo_flags_finish */
2628 class pass_ipa_icf
: public ipa_opt_pass_d
2631 pass_ipa_icf (gcc::context
*ctxt
)
2632 : ipa_opt_pass_d (pass_data_ipa_icf
, ctxt
,
2633 ipa_icf_generate_summary
, /* generate_summary */
2634 ipa_icf_write_summary
, /* write_summary */
2635 ipa_icf_read_summary
, /* read_summary */
2637 write_optimization_summary */
2639 read_optimization_summary */
2640 NULL
, /* stmt_fixup */
2641 0, /* function_transform_todo_flags_start */
2642 NULL
, /* function_transform */
2643 NULL
) /* variable_transform */
2646 /* opt_pass methods: */
2647 virtual bool gate (function
*)
2649 return in_lto_p
|| flag_ipa_icf_variables
|| flag_ipa_icf_functions
;
2652 virtual unsigned int execute (function
*)
2654 return ipa_icf_driver();
2656 }; // class pass_ipa_icf
2658 } // ipa_icf namespace
2661 make_pass_ipa_icf (gcc::context
*ctxt
)
2663 return new ipa_icf::pass_ipa_icf (ctxt
);