1 /* Interprocedural Identical Code Folding pass
2 Copyright (C) 2014 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/>. */
24 #include "coretypes.h"
32 #include "hard-reg-set.h"
35 #include "basic-block.h"
36 #include "tree-ssa-alias.h"
37 #include "internal-fn.h"
38 #include "gimple-expr.h"
42 #include "gimple-iterator.h"
43 #include "gimple-ssa.h"
45 #include "stringpool.h"
47 #include "tree-pass.h"
48 #include "gimple-pretty-print.h"
52 #include "plugin-api.h"
55 #include "data-streamer.h"
56 #include "ipa-utils.h"
58 #include "tree-ssanames.h"
61 #include "ipa-icf-gimple.h"
64 namespace ipa_icf_gimple
{
66 /* Initialize internal structures for a given SOURCE_FUNC_DECL and
67 TARGET_FUNC_DECL. Strict polymorphic comparison is processed if
68 an option COMPARE_POLYMORPHIC is true. For special cases, one can
69 set IGNORE_LABELS to skip label comparison.
70 Similarly, IGNORE_SOURCE_DECLS and IGNORE_TARGET_DECLS are sets
71 of declarations that can be skipped. */
73 func_checker::func_checker (tree source_func_decl
, tree target_func_decl
,
74 bool compare_polymorphic
,
76 hash_set
<symtab_node
*> *ignored_source_nodes
,
77 hash_set
<symtab_node
*> *ignored_target_nodes
)
78 : m_source_func_decl (source_func_decl
), m_target_func_decl (target_func_decl
),
79 m_ignored_source_nodes (ignored_source_nodes
),
80 m_ignored_target_nodes (ignored_target_nodes
),
81 m_compare_polymorphic (compare_polymorphic
),
82 m_ignore_labels (ignore_labels
)
84 function
*source_func
= DECL_STRUCT_FUNCTION (source_func_decl
);
85 function
*target_func
= DECL_STRUCT_FUNCTION (target_func_decl
);
87 unsigned ssa_source
= SSANAMES (source_func
)->length ();
88 unsigned ssa_target
= SSANAMES (target_func
)->length ();
90 m_source_ssa_names
.create (ssa_source
);
91 m_target_ssa_names
.create (ssa_target
);
93 for (unsigned i
= 0; i
< ssa_source
; i
++)
94 m_source_ssa_names
.safe_push (-1);
96 for (unsigned i
= 0; i
< ssa_target
; i
++)
97 m_target_ssa_names
.safe_push (-1);
100 /* Memory release routine. */
102 func_checker::~func_checker ()
104 m_source_ssa_names
.release();
105 m_target_ssa_names
.release();
108 /* Verifies that trees T1 and T2 are equivalent from perspective of ICF. */
111 func_checker::compare_ssa_name (tree t1
, tree t2
)
113 unsigned i1
= SSA_NAME_VERSION (t1
);
114 unsigned i2
= SSA_NAME_VERSION (t2
);
116 if (m_source_ssa_names
[i1
] == -1)
117 m_source_ssa_names
[i1
] = i2
;
118 else if (m_source_ssa_names
[i1
] != (int) i2
)
121 if(m_target_ssa_names
[i2
] == -1)
122 m_target_ssa_names
[i2
] = i1
;
123 else if (m_target_ssa_names
[i2
] != (int) i1
)
129 /* Verification function for edges E1 and E2. */
132 func_checker::compare_edge (edge e1
, edge e2
)
134 if (e1
->flags
!= e2
->flags
)
139 edge
&slot
= m_edge_map
.get_or_insert (e1
, &existed_p
);
141 return return_with_debug (slot
== e2
);
145 /* TODO: filter edge probabilities for profile feedback match. */
150 /* Verification function for declaration trees T1 and T2 that
151 come from functions FUNC1 and FUNC2. */
154 func_checker::compare_decl (tree t1
, tree t2
)
156 if (!auto_var_in_fn_p (t1
, m_source_func_decl
)
157 || !auto_var_in_fn_p (t2
, m_target_func_decl
))
158 return return_with_debug (t1
== t2
);
160 tree_code t
= TREE_CODE (t1
);
161 if ((t
== VAR_DECL
|| t
== PARM_DECL
|| t
== RESULT_DECL
)
162 && DECL_BY_REFERENCE (t1
) != DECL_BY_REFERENCE (t2
))
163 return return_false_with_msg ("DECL_BY_REFERENCE flags are different");
165 if (!compatible_types_p (TREE_TYPE (t1
), TREE_TYPE (t2
),
166 m_compare_polymorphic
))
167 return return_false ();
171 tree
&slot
= m_decl_map
.get_or_insert (t1
, &existed_p
);
173 return return_with_debug (slot
== t2
);
180 /* Return true if types are compatible from perspective of ICF. */
181 bool func_checker::compatible_types_p (tree t1
, tree t2
,
182 bool compare_polymorphic
,
185 if (TREE_CODE (t1
) != TREE_CODE (t2
))
186 return return_false_with_msg ("different tree types");
188 if (!types_compatible_p (t1
, t2
))
189 return return_false_with_msg ("types are not compatible");
191 if (get_alias_set (t1
) != get_alias_set (t2
))
192 return return_false_with_msg ("alias sets are different");
194 /* We call contains_polymorphic_type_p with this pointer type. */
195 if (first_argument
&& TREE_CODE (t1
) == POINTER_TYPE
)
201 if (compare_polymorphic
)
202 if (contains_polymorphic_type_p (t1
) || contains_polymorphic_type_p (t2
))
204 if (!contains_polymorphic_type_p (t1
) || !contains_polymorphic_type_p (t2
))
205 return return_false_with_msg ("one type is not polymorphic");
207 if (!types_must_be_same_for_odr (t1
, t2
))
208 return return_false_with_msg ("types are not same for ODR");
214 /* Function responsible for comparison of handled components T1 and T2.
215 If these components, from functions FUNC1 and FUNC2, are equal, true
219 func_checker::compare_operand (tree t1
, tree t2
)
221 tree base1
, base2
, x1
, x2
, y1
, y2
, z1
, z2
;
222 HOST_WIDE_INT offset1
= 0, offset2
= 0;
230 tree tt1
= TREE_TYPE (t1
);
231 tree tt2
= TREE_TYPE (t2
);
233 if (!func_checker::compatible_types_p (tt1
, tt2
))
236 base1
= get_addr_base_and_unit_offset (t1
, &offset1
);
237 base2
= get_addr_base_and_unit_offset (t2
, &offset2
);
241 if (offset1
!= offset2
)
242 return return_false_with_msg ("base offsets are different");
248 if (TREE_CODE (t1
) != TREE_CODE (t2
))
249 return return_false ();
251 switch (TREE_CODE (t1
))
255 unsigned length1
= vec_safe_length (CONSTRUCTOR_ELTS (t1
));
256 unsigned length2
= vec_safe_length (CONSTRUCTOR_ELTS (t2
));
258 if (length1
!= length2
)
259 return return_false ();
261 for (unsigned i
= 0; i
< length1
; i
++)
262 if (!compare_operand (CONSTRUCTOR_ELT (t1
, i
)->value
,
263 CONSTRUCTOR_ELT (t2
, i
)->value
))
264 return return_false();
269 case ARRAY_RANGE_REF
:
270 x1
= TREE_OPERAND (t1
, 0);
271 x2
= TREE_OPERAND (t2
, 0);
272 y1
= TREE_OPERAND (t1
, 1);
273 y2
= TREE_OPERAND (t2
, 1);
275 if (!compare_operand (array_ref_low_bound (t1
),
276 array_ref_low_bound (t2
)))
277 return return_false_with_msg ("");
278 if (!compare_operand (array_ref_element_size (t1
),
279 array_ref_element_size (t2
)))
280 return return_false_with_msg ("");
281 if (!compare_operand (x1
, x2
))
282 return return_false_with_msg ("");
283 return compare_operand (y1
, y2
);
286 x1
= TREE_OPERAND (t1
, 0);
287 x2
= TREE_OPERAND (t2
, 0);
288 y1
= TREE_OPERAND (t1
, 1);
289 y2
= TREE_OPERAND (t2
, 1);
291 /* See if operand is an memory access (the test originate from
294 In this case the alias set of the function being replaced must
295 be subset of the alias set of the other function. At the moment
296 we seek for equivalency classes, so simply require inclussion in
299 if (!func_checker::compatible_types_p (TREE_TYPE (x1
), TREE_TYPE (x2
)))
300 return return_false ();
302 if (!compare_operand (x1
, x2
))
303 return return_false_with_msg ("");
305 if (get_alias_set (TREE_TYPE (y1
)) != get_alias_set (TREE_TYPE (y2
)))
306 return return_false_with_msg ("alias set for MEM_REF offsets are different");
309 ao_ref_init (&r1
, t1
);
310 ao_ref_init (&r2
, t2
);
311 if (ao_ref_alias_set (&r1
) != ao_ref_alias_set (&r2
)
312 || ao_ref_base_alias_set (&r1
) != ao_ref_base_alias_set (&r2
))
313 return return_false_with_msg ("ao alias sets are different");
315 /* Type of the offset on MEM_REF does not matter. */
316 return wi::to_offset (y1
) == wi::to_offset (y2
);
320 x1
= TREE_OPERAND (t1
, 0);
321 x2
= TREE_OPERAND (t2
, 0);
322 y1
= TREE_OPERAND (t1
, 1);
323 y2
= TREE_OPERAND (t2
, 1);
325 ret
= compare_operand (x1
, x2
)
326 && compare_operand (y1
, y2
);
328 return return_with_debug (ret
);
330 /* Virtual table call. */
333 x1
= TREE_OPERAND (t1
, 0);
334 x2
= TREE_OPERAND (t2
, 0);
335 y1
= TREE_OPERAND (t1
, 1);
336 y2
= TREE_OPERAND (t2
, 1);
337 z1
= TREE_OPERAND (t1
, 2);
338 z2
= TREE_OPERAND (t2
, 2);
340 ret
= compare_operand (x1
, x2
)
341 && compare_operand (y1
, y2
)
342 && compare_operand (z1
, z2
);
344 return return_with_debug (ret
);
348 x1
= TREE_OPERAND (t1
, 0);
349 x2
= TREE_OPERAND (t2
, 0);
351 ret
= compare_operand (x1
, x2
);
352 return return_with_debug (ret
);
356 ret
= compare_ssa_name (t1
, t2
);
359 return return_with_debug (ret
);
361 if (SSA_NAME_IS_DEFAULT_DEF (t1
))
363 tree b1
= SSA_NAME_VAR (t1
);
364 tree b2
= SSA_NAME_VAR (t2
);
366 if (b1
== NULL
&& b2
== NULL
)
369 if (b1
== NULL
|| b2
== NULL
|| TREE_CODE (b1
) != TREE_CODE (b2
))
370 return return_false ();
372 switch (TREE_CODE (b1
))
375 return return_with_debug (compare_variable_decl (t1
, t2
));
378 ret
= compare_decl (b1
, b2
);
379 return return_with_debug (ret
);
381 return return_false_with_msg ("Unknown TREE code reached");
389 ret
= compatible_types_p (TREE_TYPE (t1
), TREE_TYPE (t2
))
390 && wi::to_offset (t1
) == wi::to_offset (t2
);
392 return return_with_debug (ret
);
399 ret
= operand_equal_p (t1
, t2
, OEP_ONLY_CONST
);
400 return return_with_debug (ret
);
404 ret
= compare_function_decl (t1
, t2
);
405 return return_with_debug (ret
);
408 return return_with_debug (compare_variable_decl (t1
, t2
));
411 tree offset1
= DECL_FIELD_OFFSET (t1
);
412 tree offset2
= DECL_FIELD_OFFSET (t2
);
414 tree bit_offset1
= DECL_FIELD_BIT_OFFSET (t1
);
415 tree bit_offset2
= DECL_FIELD_BIT_OFFSET (t2
);
417 ret
= compare_operand (offset1
, offset2
)
418 && compare_operand (bit_offset1
, bit_offset2
);
420 return return_with_debug (ret
);
424 int *bb1
= m_label_bb_map
.get (t1
);
425 int *bb2
= m_label_bb_map
.get (t2
);
427 return return_with_debug (*bb1
== *bb2
);
434 ret
= compare_decl (t1
, t2
);
435 return return_with_debug (ret
);
438 return return_false_with_msg ("Unknown TREE code reached");
442 /* Compares two tree list operands T1 and T2 and returns true if these
443 two trees are semantically equivalent. */
446 func_checker::compare_tree_list_operand (tree t1
, tree t2
)
448 gcc_assert (TREE_CODE (t1
) == TREE_LIST
);
449 gcc_assert (TREE_CODE (t2
) == TREE_LIST
);
451 for (; t1
; t1
= TREE_CHAIN (t1
))
456 if (!compare_operand (TREE_VALUE (t1
), TREE_VALUE (t2
)))
457 return return_false ();
459 t2
= TREE_CHAIN (t2
);
463 return return_false ();
468 /* Verifies that trees T1 and T2, representing function declarations
469 are equivalent from perspective of ICF. */
472 func_checker::compare_function_decl (tree t1
, tree t2
)
479 symtab_node
*n1
= symtab_node::get (t1
);
480 symtab_node
*n2
= symtab_node::get (t2
);
482 if (m_ignored_source_nodes
!= NULL
&& m_ignored_target_nodes
!= NULL
)
484 ret
= m_ignored_source_nodes
->contains (n1
)
485 && m_ignored_target_nodes
->contains (n2
);
491 /* If function decl is WEAKREF, we compare targets. */
492 cgraph_node
*f1
= cgraph_node::get (t1
);
493 cgraph_node
*f2
= cgraph_node::get (t2
);
495 if(f1
&& f2
&& f1
->weakref
&& f2
->weakref
)
496 ret
= f1
->alias_target
== f2
->alias_target
;
501 /* Verifies that trees T1 and T2 do correspond. */
504 func_checker::compare_variable_decl (tree t1
, tree t2
)
511 if (TREE_CODE (t1
) == VAR_DECL
&& (DECL_EXTERNAL (t1
) || TREE_STATIC (t1
)))
513 symtab_node
*n1
= symtab_node::get (t1
);
514 symtab_node
*n2
= symtab_node::get (t2
);
516 if (m_ignored_source_nodes
!= NULL
&& m_ignored_target_nodes
!= NULL
)
518 ret
= m_ignored_source_nodes
->contains (n1
)
519 && m_ignored_target_nodes
->contains (n2
);
525 ret
= compare_decl (t1
, t2
);
527 return return_with_debug (ret
);
531 /* Function visits all gimple labels and creates corresponding
532 mapping between basic blocks and labels. */
535 func_checker::parse_labels (sem_bb
*bb
)
537 for (gimple_stmt_iterator gsi
= gsi_start_bb (bb
->bb
); !gsi_end_p (gsi
);
540 gimple stmt
= gsi_stmt (gsi
);
542 if (glabel
*label_stmt
= dyn_cast
<glabel
*> (stmt
))
544 tree t
= gimple_label_label (label_stmt
);
545 gcc_assert (TREE_CODE (t
) == LABEL_DECL
);
547 m_label_bb_map
.put (t
, bb
->bb
->index
);
552 /* Basic block equivalence comparison function that returns true if
553 basic blocks BB1 and BB2 (from functions FUNC1 and FUNC2) correspond.
555 In general, a collection of equivalence dictionaries is built for types
556 like SSA names, declarations (VAR_DECL, PARM_DECL, ..). This infrastructure
557 is utilized by every statement-by-statement comparison function. */
560 func_checker::compare_bb (sem_bb
*bb1
, sem_bb
*bb2
)
562 gimple_stmt_iterator gsi1
, gsi2
;
565 gsi1
= gsi_start_bb_nondebug (bb1
->bb
);
566 gsi2
= gsi_start_bb_nondebug (bb2
->bb
);
568 while (!gsi_end_p (gsi1
))
570 if (gsi_end_p (gsi2
))
571 return return_false ();
573 s1
= gsi_stmt (gsi1
);
574 s2
= gsi_stmt (gsi2
);
576 int eh1
= lookup_stmt_eh_lp_fn
577 (DECL_STRUCT_FUNCTION (m_source_func_decl
), s1
);
578 int eh2
= lookup_stmt_eh_lp_fn
579 (DECL_STRUCT_FUNCTION (m_target_func_decl
), s2
);
582 return return_false_with_msg ("EH regions are different");
584 if (gimple_code (s1
) != gimple_code (s2
))
585 return return_false_with_msg ("gimple codes are different");
587 switch (gimple_code (s1
))
590 if (!compare_gimple_call (as_a
<gcall
*> (s1
),
591 as_a
<gcall
*> (s2
)))
592 return return_different_stmts (s1
, s2
, "GIMPLE_CALL");
595 if (!compare_gimple_assign (s1
, s2
))
596 return return_different_stmts (s1
, s2
, "GIMPLE_ASSIGN");
599 if (!compare_gimple_cond (s1
, s2
))
600 return return_different_stmts (s1
, s2
, "GIMPLE_COND");
603 if (!compare_gimple_switch (as_a
<gswitch
*> (s1
),
604 as_a
<gswitch
*> (s2
)))
605 return return_different_stmts (s1
, s2
, "GIMPLE_SWITCH");
608 case GIMPLE_EH_DISPATCH
:
611 if (!compare_gimple_resx (as_a
<gresx
*> (s1
),
612 as_a
<gresx
*> (s2
)))
613 return return_different_stmts (s1
, s2
, "GIMPLE_RESX");
616 if (!compare_gimple_label (as_a
<glabel
*> (s1
),
617 as_a
<glabel
*> (s2
)))
618 return return_different_stmts (s1
, s2
, "GIMPLE_LABEL");
621 if (!compare_gimple_return (as_a
<greturn
*> (s1
),
622 as_a
<greturn
*> (s2
)))
623 return return_different_stmts (s1
, s2
, "GIMPLE_RETURN");
626 if (!compare_gimple_goto (s1
, s2
))
627 return return_different_stmts (s1
, s2
, "GIMPLE_GOTO");
630 if (!compare_gimple_asm (as_a
<gasm
*> (s1
),
632 return return_different_stmts (s1
, s2
, "GIMPLE_ASM");
638 return return_false_with_msg ("Unknown GIMPLE code reached");
641 gsi_next_nondebug (&gsi1
);
642 gsi_next_nondebug (&gsi2
);
645 if (!gsi_end_p (gsi2
))
646 return return_false ();
651 /* Verifies for given GIMPLEs S1 and S2 that
652 call statements are semantically equivalent. */
655 func_checker::compare_gimple_call (gcall
*s1
, gcall
*s2
)
660 if (gimple_call_num_args (s1
) != gimple_call_num_args (s2
))
663 t1
= gimple_call_fn (s1
);
664 t2
= gimple_call_fn (s2
);
665 if (!compare_operand (t1
, t2
))
666 return return_false ();
669 if (gimple_call_internal_p (s1
) != gimple_call_internal_p (s2
)
670 || gimple_call_ctrl_altering_p (s1
) != gimple_call_ctrl_altering_p (s2
)
671 || gimple_call_tail_p (s1
) != gimple_call_tail_p (s2
)
672 || gimple_call_return_slot_opt_p (s1
) != gimple_call_return_slot_opt_p (s2
)
673 || gimple_call_from_thunk_p (s1
) != gimple_call_from_thunk_p (s2
)
674 || gimple_call_va_arg_pack_p (s1
) != gimple_call_va_arg_pack_p (s2
)
675 || gimple_call_alloca_for_var_p (s1
) != gimple_call_alloca_for_var_p (s2
)
676 || gimple_call_with_bounds_p (s1
) != gimple_call_with_bounds_p (s2
))
679 if (gimple_call_internal_p (s1
)
680 && gimple_call_internal_fn (s1
) != gimple_call_internal_fn (s2
))
683 tree fntype1
= gimple_call_fntype (s1
);
684 tree fntype2
= gimple_call_fntype (s2
);
685 if ((fntype1
&& !fntype2
)
686 || (!fntype1
&& fntype2
)
687 || (fntype1
&& !types_compatible_p (fntype1
, fntype2
)))
688 return return_false_with_msg ("call function types are not compatible");
690 tree chain1
= gimple_call_chain (s1
);
691 tree chain2
= gimple_call_chain (s2
);
692 if ((chain1
&& !chain2
)
693 || (!chain1
&& chain2
)
694 || !compare_operand (chain1
, chain2
))
695 return return_false_with_msg ("static call chains are different");
697 /* Checking of argument. */
698 for (i
= 0; i
< gimple_call_num_args (s1
); ++i
)
700 t1
= gimple_call_arg (s1
, i
);
701 t2
= gimple_call_arg (s2
, i
);
703 if (!compare_operand (t1
, t2
))
707 /* Return value checking. */
708 t1
= gimple_get_lhs (s1
);
709 t2
= gimple_get_lhs (s2
);
711 return compare_operand (t1
, t2
);
715 /* Verifies for given GIMPLEs S1 and S2 that
716 assignment statements are semantically equivalent. */
719 func_checker::compare_gimple_assign (gimple s1
, gimple s2
)
722 tree_code code1
, code2
;
725 code1
= gimple_expr_code (s1
);
726 code2
= gimple_expr_code (s2
);
731 code1
= gimple_assign_rhs_code (s1
);
732 code2
= gimple_assign_rhs_code (s2
);
737 for (i
= 0; i
< gimple_num_ops (s1
); i
++)
739 arg1
= gimple_op (s1
, i
);
740 arg2
= gimple_op (s2
, i
);
742 if (!compare_operand (arg1
, arg2
))
750 /* Verifies for given GIMPLEs S1 and S2 that
751 condition statements are semantically equivalent. */
754 func_checker::compare_gimple_cond (gimple s1
, gimple s2
)
757 tree_code code1
, code2
;
759 code1
= gimple_expr_code (s1
);
760 code2
= gimple_expr_code (s2
);
765 t1
= gimple_cond_lhs (s1
);
766 t2
= gimple_cond_lhs (s2
);
768 if (!compare_operand (t1
, t2
))
771 t1
= gimple_cond_rhs (s1
);
772 t2
= gimple_cond_rhs (s2
);
774 return compare_operand (t1
, t2
);
777 /* Verifies that tree labels T1 and T2 correspond in FUNC1 and FUNC2. */
780 func_checker::compare_tree_ssa_label (tree t1
, tree t2
)
782 return compare_operand (t1
, t2
);
785 /* Verifies for given GIMPLE_LABEL stmts S1 and S2 that
786 label statements are semantically equivalent. */
789 func_checker::compare_gimple_label (const glabel
*g1
, const glabel
*g2
)
794 tree t1
= gimple_label_label (g1
);
795 tree t2
= gimple_label_label (g2
);
797 if (FORCED_LABEL (t1
) || FORCED_LABEL (t2
))
798 return return_false_with_msg ("FORCED_LABEL");
800 /* As the pass build BB to label mapping, no further check is needed. */
804 /* Verifies for given GIMPLE_SWITCH stmts S1 and S2 that
805 switch statements are semantically equivalent. */
808 func_checker::compare_gimple_switch (const gswitch
*g1
, const gswitch
*g2
)
810 unsigned lsize1
, lsize2
, i
;
812 lsize1
= gimple_switch_num_labels (g1
);
813 lsize2
= gimple_switch_num_labels (g2
);
815 if (lsize1
!= lsize2
)
818 tree t1
= gimple_switch_index (g1
);
819 tree t2
= gimple_switch_index (g2
);
821 if (!compare_operand (t1
, t2
))
824 for (i
= 0; i
< lsize1
; i
++)
826 tree label1
= gimple_switch_label (g1
, i
);
827 tree label2
= gimple_switch_label (g2
, i
);
829 /* Label LOW and HIGH comparison. */
830 tree low1
= CASE_LOW (label1
);
831 tree low2
= CASE_LOW (label2
);
833 if (!tree_int_cst_equal (low1
, low2
))
834 return return_false_with_msg ("case low values are different");
836 tree high1
= CASE_HIGH (label1
);
837 tree high2
= CASE_HIGH (label2
);
839 if (!tree_int_cst_equal (high1
, high2
))
840 return return_false_with_msg ("case high values are different");
842 if (TREE_CODE (label1
) == CASE_LABEL_EXPR
843 && TREE_CODE (label2
) == CASE_LABEL_EXPR
)
845 label1
= CASE_LABEL (label1
);
846 label2
= CASE_LABEL (label2
);
848 if (!compare_operand (label1
, label2
))
849 return return_false_with_msg ("switch label_exprs are different");
851 else if (!tree_int_cst_equal (label1
, label2
))
852 return return_false_with_msg ("switch labels are different");
858 /* Verifies for given GIMPLE_RETURN stmts S1 and S2 that
859 return statements are semantically equivalent. */
862 func_checker::compare_gimple_return (const greturn
*g1
, const greturn
*g2
)
866 t1
= gimple_return_retval (g1
);
867 t2
= gimple_return_retval (g2
);
869 /* Void return type. */
870 if (t1
== NULL
&& t2
== NULL
)
873 return compare_operand (t1
, t2
);
876 /* Verifies for given GIMPLEs S1 and S2 that
877 goto statements are semantically equivalent. */
880 func_checker::compare_gimple_goto (gimple g1
, gimple g2
)
884 dest1
= gimple_goto_dest (g1
);
885 dest2
= gimple_goto_dest (g2
);
887 if (TREE_CODE (dest1
) != TREE_CODE (dest2
) || TREE_CODE (dest1
) != SSA_NAME
)
890 return compare_operand (dest1
, dest2
);
893 /* Verifies for given GIMPLE_RESX stmts S1 and S2 that
894 resx statements are semantically equivalent. */
897 func_checker::compare_gimple_resx (const gresx
*g1
, const gresx
*g2
)
899 return gimple_resx_region (g1
) == gimple_resx_region (g2
);
902 /* Verifies for given GIMPLEs S1 and S2 that ASM statements are equivalent.
903 For the beginning, the pass only supports equality for
904 '__asm__ __volatile__ ("", "", "", "memory")'. */
907 func_checker::compare_gimple_asm (const gasm
*g1
, const gasm
*g2
)
909 if (gimple_asm_volatile_p (g1
) != gimple_asm_volatile_p (g2
))
912 if (gimple_asm_ninputs (g1
) != gimple_asm_ninputs (g2
))
915 if (gimple_asm_noutputs (g1
) != gimple_asm_noutputs (g2
))
918 /* We do not suppport goto ASM statement comparison. */
919 if (gimple_asm_nlabels (g1
) || gimple_asm_nlabels (g2
))
922 if (gimple_asm_nclobbers (g1
) != gimple_asm_nclobbers (g2
))
925 if (strcmp (gimple_asm_string (g1
), gimple_asm_string (g2
)) != 0)
926 return return_false_with_msg ("ASM strings are different");
928 for (unsigned i
= 0; i
< gimple_asm_ninputs (g1
); i
++)
930 tree input1
= gimple_asm_input_op (g1
, i
);
931 tree input2
= gimple_asm_input_op (g2
, i
);
933 if (!compare_tree_list_operand (input1
, input2
))
934 return return_false_with_msg ("ASM input is different");
937 for (unsigned i
= 0; i
< gimple_asm_noutputs (g1
); i
++)
939 tree output1
= gimple_asm_output_op (g1
, i
);
940 tree output2
= gimple_asm_output_op (g2
, i
);
942 if (!compare_tree_list_operand (output1
, output2
))
943 return return_false_with_msg ("ASM output is different");
946 for (unsigned i
= 0; i
< gimple_asm_nclobbers (g1
); i
++)
948 tree clobber1
= gimple_asm_clobber_op (g1
, i
);
949 tree clobber2
= gimple_asm_clobber_op (g2
, i
);
951 if (!operand_equal_p (TREE_VALUE (clobber1
), TREE_VALUE (clobber2
),
953 return return_false_with_msg ("ASM clobber is different");
959 } // ipa_icf_gimple namespace