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/>. */
24 #include "coretypes.h"
28 #include "double-int.h"
36 #include "fold-const.h"
39 #include "hard-reg-set.h"
42 #include "basic-block.h"
43 #include "tree-ssa-alias.h"
44 #include "internal-fn.h"
45 #include "gimple-expr.h"
49 #include "gimple-iterator.h"
50 #include "gimple-ssa.h"
52 #include "stringpool.h"
54 #include "tree-pass.h"
55 #include "gimple-pretty-print.h"
59 #include "plugin-api.h"
62 #include "data-streamer.h"
63 #include "ipa-utils.h"
65 #include "tree-ssanames.h"
68 #include "ipa-icf-gimple.h"
71 namespace ipa_icf_gimple
{
73 /* Initialize internal structures for a given SOURCE_FUNC_DECL and
74 TARGET_FUNC_DECL. Strict polymorphic comparison is processed if
75 an option COMPARE_POLYMORPHIC is true. For special cases, one can
76 set IGNORE_LABELS to skip label comparison.
77 Similarly, IGNORE_SOURCE_DECLS and IGNORE_TARGET_DECLS are sets
78 of declarations that can be skipped. */
80 func_checker::func_checker (tree source_func_decl
, tree target_func_decl
,
81 bool compare_polymorphic
,
83 hash_set
<symtab_node
*> *ignored_source_nodes
,
84 hash_set
<symtab_node
*> *ignored_target_nodes
)
85 : m_source_func_decl (source_func_decl
), m_target_func_decl (target_func_decl
),
86 m_ignored_source_nodes (ignored_source_nodes
),
87 m_ignored_target_nodes (ignored_target_nodes
),
88 m_compare_polymorphic (compare_polymorphic
),
89 m_ignore_labels (ignore_labels
)
91 function
*source_func
= DECL_STRUCT_FUNCTION (source_func_decl
);
92 function
*target_func
= DECL_STRUCT_FUNCTION (target_func_decl
);
94 unsigned ssa_source
= SSANAMES (source_func
)->length ();
95 unsigned ssa_target
= SSANAMES (target_func
)->length ();
97 m_source_ssa_names
.create (ssa_source
);
98 m_target_ssa_names
.create (ssa_target
);
100 for (unsigned i
= 0; i
< ssa_source
; i
++)
101 m_source_ssa_names
.safe_push (-1);
103 for (unsigned i
= 0; i
< ssa_target
; i
++)
104 m_target_ssa_names
.safe_push (-1);
107 /* Memory release routine. */
109 func_checker::~func_checker ()
111 m_source_ssa_names
.release();
112 m_target_ssa_names
.release();
115 /* Verifies that trees T1 and T2 are equivalent from perspective of ICF. */
118 func_checker::compare_ssa_name (tree t1
, tree t2
)
120 gcc_assert (TREE_CODE (t1
) == SSA_NAME
);
121 gcc_assert (TREE_CODE (t2
) == SSA_NAME
);
123 unsigned i1
= SSA_NAME_VERSION (t1
);
124 unsigned i2
= SSA_NAME_VERSION (t2
);
126 if (m_source_ssa_names
[i1
] == -1)
127 m_source_ssa_names
[i1
] = i2
;
128 else if (m_source_ssa_names
[i1
] != (int) i2
)
131 if(m_target_ssa_names
[i2
] == -1)
132 m_target_ssa_names
[i2
] = i1
;
133 else if (m_target_ssa_names
[i2
] != (int) i1
)
136 if (SSA_NAME_IS_DEFAULT_DEF (t1
))
138 tree b1
= SSA_NAME_VAR (t1
);
139 tree b2
= SSA_NAME_VAR (t2
);
141 if (b1
== NULL
&& b2
== NULL
)
144 if (b1
== NULL
|| b2
== NULL
|| TREE_CODE (b1
) != TREE_CODE (b2
))
145 return return_false ();
147 return compare_cst_or_decl (b1
, b2
);
153 /* Verification function for edges E1 and E2. */
156 func_checker::compare_edge (edge e1
, edge e2
)
158 if (e1
->flags
!= e2
->flags
)
163 edge
&slot
= m_edge_map
.get_or_insert (e1
, &existed_p
);
165 return return_with_debug (slot
== e2
);
169 /* TODO: filter edge probabilities for profile feedback match. */
174 /* Verification function for declaration trees T1 and T2 that
175 come from functions FUNC1 and FUNC2. */
178 func_checker::compare_decl (tree t1
, tree t2
)
180 if (!auto_var_in_fn_p (t1
, m_source_func_decl
)
181 || !auto_var_in_fn_p (t2
, m_target_func_decl
))
182 return return_with_debug (t1
== t2
);
184 tree_code t
= TREE_CODE (t1
);
185 if ((t
== VAR_DECL
|| t
== PARM_DECL
|| t
== RESULT_DECL
)
186 && DECL_BY_REFERENCE (t1
) != DECL_BY_REFERENCE (t2
))
187 return return_false_with_msg ("DECL_BY_REFERENCE flags are different");
189 if (!compatible_types_p (TREE_TYPE (t1
), TREE_TYPE (t2
),
190 m_compare_polymorphic
))
191 return return_false ();
195 tree
&slot
= m_decl_map
.get_or_insert (t1
, &existed_p
);
197 return return_with_debug (slot
== t2
);
204 /* Return true if types are compatible from perspective of ICF. */
206 func_checker::compatible_types_p (tree t1
, tree t2
,
207 bool compare_polymorphic
,
210 if (TREE_CODE (t1
) != TREE_CODE (t2
))
211 return return_false_with_msg ("different tree types");
213 if (TYPE_RESTRICT (t1
) != TYPE_RESTRICT (t2
))
214 return return_false_with_msg ("restrict flags are different");
216 if (!types_compatible_p (t1
, t2
))
217 return return_false_with_msg ("types are not compatible");
219 if (get_alias_set (t1
) != get_alias_set (t2
))
220 return return_false_with_msg ("alias sets are different");
222 /* We call contains_polymorphic_type_p with this pointer type. */
223 if (first_argument
&& TREE_CODE (t1
) == POINTER_TYPE
)
229 if (compare_polymorphic
)
230 if (contains_polymorphic_type_p (t1
) || contains_polymorphic_type_p (t2
))
232 if (!contains_polymorphic_type_p (t1
) || !contains_polymorphic_type_p (t2
))
233 return return_false_with_msg ("one type is not polymorphic");
235 if (!types_must_be_same_for_odr (t1
, t2
))
236 return return_false_with_msg ("types are not same for ODR");
242 /* Function compare for equality given memory operands T1 and T2. */
245 func_checker::compare_memory_operand (tree t1
, tree t2
)
253 ao_ref_init (&r1
, t1
);
254 ao_ref_init (&r2
, t2
);
256 tree b1
= ao_ref_base (&r1
);
257 tree b2
= ao_ref_base (&r2
);
259 bool source_is_memop
= DECL_P (b1
) || INDIRECT_REF_P (b1
)
260 || TREE_CODE (b1
) == MEM_REF
261 || TREE_CODE (b1
) == TARGET_MEM_REF
;
263 bool target_is_memop
= DECL_P (b2
) || INDIRECT_REF_P (b2
)
264 || TREE_CODE (b2
) == MEM_REF
265 || TREE_CODE (b2
) == TARGET_MEM_REF
;
267 /* Compare alias sets for memory operands. */
268 if (source_is_memop
&& target_is_memop
)
270 if (TREE_THIS_VOLATILE (b1
) != TREE_THIS_VOLATILE (b2
))
271 return return_false_with_msg ("different operand volatility");
273 if (ao_ref_alias_set (&r1
) != ao_ref_alias_set (&r2
)
274 || ao_ref_base_alias_set (&r1
) != ao_ref_base_alias_set (&r2
))
275 return return_false_with_msg ("ao alias sets are different");
278 return compare_operand (t1
, t2
);
281 /* Function compare for equality given trees T1 and T2 which
282 can be either a constant or a declaration type. */
285 func_checker::compare_cst_or_decl (tree t1
, tree t2
)
289 switch (TREE_CODE (t1
))
297 ret
= compatible_types_p (TREE_TYPE (t1
), TREE_TYPE (t2
))
298 && operand_equal_p (t1
, t2
, OEP_ONLY_CONST
);
299 return return_with_debug (ret
);
303 ret
= compare_function_decl (t1
, t2
);
304 return return_with_debug (ret
);
307 return return_with_debug (compare_variable_decl (t1
, t2
));
310 tree offset1
= DECL_FIELD_OFFSET (t1
);
311 tree offset2
= DECL_FIELD_OFFSET (t2
);
313 tree bit_offset1
= DECL_FIELD_BIT_OFFSET (t1
);
314 tree bit_offset2
= DECL_FIELD_BIT_OFFSET (t2
);
316 ret
= compare_operand (offset1
, offset2
)
317 && compare_operand (bit_offset1
, bit_offset2
);
319 return return_with_debug (ret
);
323 int *bb1
= m_label_bb_map
.get (t1
);
324 int *bb2
= m_label_bb_map
.get (t2
);
326 return return_with_debug (*bb1
== *bb2
);
332 ret
= compare_decl (t1
, t2
);
333 return return_with_debug (ret
);
340 /* Function responsible for comparison of various operands T1 and T2.
341 If these components, from functions FUNC1 and FUNC2, are equal, true
345 func_checker::compare_operand (tree t1
, tree t2
)
347 tree x1
, x2
, y1
, y2
, z1
, z2
;
355 tree tt1
= TREE_TYPE (t1
);
356 tree tt2
= TREE_TYPE (t2
);
358 if (!func_checker::compatible_types_p (tt1
, tt2
))
361 if (TREE_CODE (t1
) != TREE_CODE (t2
))
362 return return_false ();
364 switch (TREE_CODE (t1
))
368 unsigned length1
= vec_safe_length (CONSTRUCTOR_ELTS (t1
));
369 unsigned length2
= vec_safe_length (CONSTRUCTOR_ELTS (t2
));
371 if (length1
!= length2
)
372 return return_false ();
374 for (unsigned i
= 0; i
< length1
; i
++)
375 if (!compare_operand (CONSTRUCTOR_ELT (t1
, i
)->value
,
376 CONSTRUCTOR_ELT (t2
, i
)->value
))
377 return return_false();
382 case ARRAY_RANGE_REF
:
383 /* First argument is the array, second is the index. */
384 x1
= TREE_OPERAND (t1
, 0);
385 x2
= TREE_OPERAND (t2
, 0);
386 y1
= TREE_OPERAND (t1
, 1);
387 y2
= TREE_OPERAND (t2
, 1);
389 if (!compare_operand (array_ref_low_bound (t1
),
390 array_ref_low_bound (t2
)))
391 return return_false_with_msg ("");
392 if (!compare_operand (array_ref_element_size (t1
),
393 array_ref_element_size (t2
)))
394 return return_false_with_msg ("");
396 if (!compare_operand (x1
, x2
))
397 return return_false_with_msg ("");
398 return compare_operand (y1
, y2
);
401 x1
= TREE_OPERAND (t1
, 0);
402 x2
= TREE_OPERAND (t2
, 0);
403 y1
= TREE_OPERAND (t1
, 1);
404 y2
= TREE_OPERAND (t2
, 1);
406 /* See if operand is an memory access (the test originate from
409 In this case the alias set of the function being replaced must
410 be subset of the alias set of the other function. At the moment
411 we seek for equivalency classes, so simply require inclussion in
414 if (!func_checker::compatible_types_p (TREE_TYPE (x1
), TREE_TYPE (x2
)))
415 return return_false ();
417 if (!compare_operand (x1
, x2
))
418 return return_false_with_msg ("");
420 /* Type of the offset on MEM_REF does not matter. */
421 return wi::to_offset (y1
) == wi::to_offset (y2
);
425 x1
= TREE_OPERAND (t1
, 0);
426 x2
= TREE_OPERAND (t2
, 0);
427 y1
= TREE_OPERAND (t1
, 1);
428 y2
= TREE_OPERAND (t2
, 1);
430 ret
= compare_operand (x1
, x2
)
431 && compare_cst_or_decl (y1
, y2
);
433 return return_with_debug (ret
);
435 /* Virtual table call. */
438 x1
= TREE_OPERAND (t1
, 0);
439 x2
= TREE_OPERAND (t2
, 0);
440 y1
= TREE_OPERAND (t1
, 1);
441 y2
= TREE_OPERAND (t2
, 1);
442 z1
= TREE_OPERAND (t1
, 2);
443 z2
= TREE_OPERAND (t2
, 2);
445 ret
= compare_ssa_name (x1
, x2
)
446 && compare_ssa_name (y1
, y2
)
447 && compare_cst_or_decl (z1
, z2
);
449 return return_with_debug (ret
);
453 x1
= TREE_OPERAND (t1
, 0);
454 x2
= TREE_OPERAND (t2
, 0);
456 ret
= compare_operand (x1
, x2
);
457 return return_with_debug (ret
);
461 ret
= compare_decl (t1
, t2
);
462 return return_with_debug (ret
);
465 return compare_ssa_name (t1
, t2
);
478 return compare_cst_or_decl (t1
, t2
);
480 return return_false_with_msg ("Unknown TREE code reached");
484 /* Compares two tree list operands T1 and T2 and returns true if these
485 two trees are semantically equivalent. */
488 func_checker::compare_tree_list_operand (tree t1
, tree t2
)
490 gcc_assert (TREE_CODE (t1
) == TREE_LIST
);
491 gcc_assert (TREE_CODE (t2
) == TREE_LIST
);
493 for (; t1
; t1
= TREE_CHAIN (t1
))
498 if (!compare_operand (TREE_VALUE (t1
), TREE_VALUE (t2
)))
499 return return_false ();
501 t2
= TREE_CHAIN (t2
);
505 return return_false ();
510 /* Verifies that trees T1 and T2, representing function declarations
511 are equivalent from perspective of ICF. */
514 func_checker::compare_function_decl (tree t1
, tree t2
)
521 symtab_node
*n1
= symtab_node::get (t1
);
522 symtab_node
*n2
= symtab_node::get (t2
);
524 if (m_ignored_source_nodes
!= NULL
&& m_ignored_target_nodes
!= NULL
)
526 ret
= m_ignored_source_nodes
->contains (n1
)
527 && m_ignored_target_nodes
->contains (n2
);
533 /* If function decl is WEAKREF, we compare targets. */
534 cgraph_node
*f1
= cgraph_node::get (t1
);
535 cgraph_node
*f2
= cgraph_node::get (t2
);
537 if(f1
&& f2
&& f1
->weakref
&& f2
->weakref
)
538 ret
= f1
->alias_target
== f2
->alias_target
;
543 /* Verifies that trees T1 and T2 do correspond. */
546 func_checker::compare_variable_decl (tree t1
, tree t2
)
553 if (TREE_CODE (t1
) == VAR_DECL
&& (DECL_EXTERNAL (t1
) || TREE_STATIC (t1
)))
555 symtab_node
*n1
= symtab_node::get (t1
);
556 symtab_node
*n2
= symtab_node::get (t2
);
558 if (m_ignored_source_nodes
!= NULL
&& m_ignored_target_nodes
!= NULL
)
560 ret
= m_ignored_source_nodes
->contains (n1
)
561 && m_ignored_target_nodes
->contains (n2
);
567 ret
= compare_decl (t1
, t2
);
569 return return_with_debug (ret
);
573 /* Function visits all gimple labels and creates corresponding
574 mapping between basic blocks and labels. */
577 func_checker::parse_labels (sem_bb
*bb
)
579 for (gimple_stmt_iterator gsi
= gsi_start_bb (bb
->bb
); !gsi_end_p (gsi
);
582 gimple stmt
= gsi_stmt (gsi
);
584 if (glabel
*label_stmt
= dyn_cast
<glabel
*> (stmt
))
586 tree t
= gimple_label_label (label_stmt
);
587 gcc_assert (TREE_CODE (t
) == LABEL_DECL
);
589 m_label_bb_map
.put (t
, bb
->bb
->index
);
594 /* Basic block equivalence comparison function that returns true if
595 basic blocks BB1 and BB2 (from functions FUNC1 and FUNC2) correspond.
597 In general, a collection of equivalence dictionaries is built for types
598 like SSA names, declarations (VAR_DECL, PARM_DECL, ..). This infrastructure
599 is utilized by every statement-by-statement comparison function. */
602 func_checker::compare_bb (sem_bb
*bb1
, sem_bb
*bb2
)
604 gimple_stmt_iterator gsi1
, gsi2
;
607 gsi1
= gsi_start_bb_nondebug (bb1
->bb
);
608 gsi2
= gsi_start_bb_nondebug (bb2
->bb
);
610 while (!gsi_end_p (gsi1
))
612 if (gsi_end_p (gsi2
))
613 return return_false ();
615 s1
= gsi_stmt (gsi1
);
616 s2
= gsi_stmt (gsi2
);
618 int eh1
= lookup_stmt_eh_lp_fn
619 (DECL_STRUCT_FUNCTION (m_source_func_decl
), s1
);
620 int eh2
= lookup_stmt_eh_lp_fn
621 (DECL_STRUCT_FUNCTION (m_target_func_decl
), s2
);
624 return return_false_with_msg ("EH regions are different");
626 if (gimple_code (s1
) != gimple_code (s2
))
627 return return_false_with_msg ("gimple codes are different");
629 switch (gimple_code (s1
))
632 if (!compare_gimple_call (as_a
<gcall
*> (s1
),
633 as_a
<gcall
*> (s2
)))
634 return return_different_stmts (s1
, s2
, "GIMPLE_CALL");
637 if (!compare_gimple_assign (s1
, s2
))
638 return return_different_stmts (s1
, s2
, "GIMPLE_ASSIGN");
641 if (!compare_gimple_cond (s1
, s2
))
642 return return_different_stmts (s1
, s2
, "GIMPLE_COND");
645 if (!compare_gimple_switch (as_a
<gswitch
*> (s1
),
646 as_a
<gswitch
*> (s2
)))
647 return return_different_stmts (s1
, s2
, "GIMPLE_SWITCH");
650 case GIMPLE_EH_DISPATCH
:
653 if (!compare_gimple_resx (as_a
<gresx
*> (s1
),
654 as_a
<gresx
*> (s2
)))
655 return return_different_stmts (s1
, s2
, "GIMPLE_RESX");
658 if (!compare_gimple_label (as_a
<glabel
*> (s1
),
659 as_a
<glabel
*> (s2
)))
660 return return_different_stmts (s1
, s2
, "GIMPLE_LABEL");
663 if (!compare_gimple_return (as_a
<greturn
*> (s1
),
664 as_a
<greturn
*> (s2
)))
665 return return_different_stmts (s1
, s2
, "GIMPLE_RETURN");
668 if (!compare_gimple_goto (s1
, s2
))
669 return return_different_stmts (s1
, s2
, "GIMPLE_GOTO");
672 if (!compare_gimple_asm (as_a
<gasm
*> (s1
),
674 return return_different_stmts (s1
, s2
, "GIMPLE_ASM");
680 return return_false_with_msg ("Unknown GIMPLE code reached");
683 gsi_next_nondebug (&gsi1
);
684 gsi_next_nondebug (&gsi2
);
687 if (!gsi_end_p (gsi2
))
688 return return_false ();
693 /* Verifies for given GIMPLEs S1 and S2 that
694 call statements are semantically equivalent. */
697 func_checker::compare_gimple_call (gcall
*s1
, gcall
*s2
)
702 if (gimple_call_num_args (s1
) != gimple_call_num_args (s2
))
705 t1
= gimple_call_fn (s1
);
706 t2
= gimple_call_fn (s2
);
707 if (!compare_operand (t1
, t2
))
708 return return_false ();
711 if (gimple_call_internal_p (s1
) != gimple_call_internal_p (s2
)
712 || gimple_call_ctrl_altering_p (s1
) != gimple_call_ctrl_altering_p (s2
)
713 || gimple_call_tail_p (s1
) != gimple_call_tail_p (s2
)
714 || gimple_call_return_slot_opt_p (s1
) != gimple_call_return_slot_opt_p (s2
)
715 || gimple_call_from_thunk_p (s1
) != gimple_call_from_thunk_p (s2
)
716 || gimple_call_va_arg_pack_p (s1
) != gimple_call_va_arg_pack_p (s2
)
717 || gimple_call_alloca_for_var_p (s1
) != gimple_call_alloca_for_var_p (s2
)
718 || gimple_call_with_bounds_p (s1
) != gimple_call_with_bounds_p (s2
))
721 if (gimple_call_internal_p (s1
)
722 && gimple_call_internal_fn (s1
) != gimple_call_internal_fn (s2
))
725 tree fntype1
= gimple_call_fntype (s1
);
726 tree fntype2
= gimple_call_fntype (s2
);
727 if ((fntype1
&& !fntype2
)
728 || (!fntype1
&& fntype2
)
729 || (fntype1
&& !types_compatible_p (fntype1
, fntype2
)))
730 return return_false_with_msg ("call function types are not compatible");
732 tree chain1
= gimple_call_chain (s1
);
733 tree chain2
= gimple_call_chain (s2
);
734 if ((chain1
&& !chain2
)
735 || (!chain1
&& chain2
)
736 || !compare_operand (chain1
, chain2
))
737 return return_false_with_msg ("static call chains are different");
739 /* Checking of argument. */
740 for (i
= 0; i
< gimple_call_num_args (s1
); ++i
)
742 t1
= gimple_call_arg (s1
, i
);
743 t2
= gimple_call_arg (s2
, i
);
745 if (!compare_memory_operand (t1
, t2
))
746 return return_false_with_msg ("memory operands are different");
749 /* Return value checking. */
750 t1
= gimple_get_lhs (s1
);
751 t2
= gimple_get_lhs (s2
);
753 return compare_memory_operand (t1
, t2
);
757 /* Verifies for given GIMPLEs S1 and S2 that
758 assignment statements are semantically equivalent. */
761 func_checker::compare_gimple_assign (gimple s1
, gimple s2
)
764 tree_code code1
, code2
;
767 code1
= gimple_expr_code (s1
);
768 code2
= gimple_expr_code (s2
);
773 code1
= gimple_assign_rhs_code (s1
);
774 code2
= gimple_assign_rhs_code (s2
);
779 for (i
= 0; i
< gimple_num_ops (s1
); i
++)
781 arg1
= gimple_op (s1
, i
);
782 arg2
= gimple_op (s2
, i
);
784 if (!compare_memory_operand (arg1
, arg2
))
785 return return_false_with_msg ("memory operands are different");
792 /* Verifies for given GIMPLEs S1 and S2 that
793 condition statements are semantically equivalent. */
796 func_checker::compare_gimple_cond (gimple s1
, gimple s2
)
799 tree_code code1
, code2
;
801 code1
= gimple_expr_code (s1
);
802 code2
= gimple_expr_code (s2
);
807 t1
= gimple_cond_lhs (s1
);
808 t2
= gimple_cond_lhs (s2
);
810 if (!compare_operand (t1
, t2
))
813 t1
= gimple_cond_rhs (s1
);
814 t2
= gimple_cond_rhs (s2
);
816 return compare_operand (t1
, t2
);
819 /* Verifies that tree labels T1 and T2 correspond in FUNC1 and FUNC2. */
822 func_checker::compare_tree_ssa_label (tree t1
, tree t2
)
824 return compare_operand (t1
, t2
);
827 /* Verifies for given GIMPLE_LABEL stmts S1 and S2 that
828 label statements are semantically equivalent. */
831 func_checker::compare_gimple_label (const glabel
*g1
, const glabel
*g2
)
836 tree t1
= gimple_label_label (g1
);
837 tree t2
= gimple_label_label (g2
);
839 if (FORCED_LABEL (t1
) || FORCED_LABEL (t2
))
840 return return_false_with_msg ("FORCED_LABEL");
842 /* As the pass build BB to label mapping, no further check is needed. */
846 /* Verifies for given GIMPLE_SWITCH stmts S1 and S2 that
847 switch statements are semantically equivalent. */
850 func_checker::compare_gimple_switch (const gswitch
*g1
, const gswitch
*g2
)
852 unsigned lsize1
, lsize2
, i
;
854 lsize1
= gimple_switch_num_labels (g1
);
855 lsize2
= gimple_switch_num_labels (g2
);
857 if (lsize1
!= lsize2
)
860 tree t1
= gimple_switch_index (g1
);
861 tree t2
= gimple_switch_index (g2
);
863 if (!compare_operand (t1
, t2
))
866 for (i
= 0; i
< lsize1
; i
++)
868 tree label1
= gimple_switch_label (g1
, i
);
869 tree label2
= gimple_switch_label (g2
, i
);
871 /* Label LOW and HIGH comparison. */
872 tree low1
= CASE_LOW (label1
);
873 tree low2
= CASE_LOW (label2
);
875 if (!tree_int_cst_equal (low1
, low2
))
876 return return_false_with_msg ("case low values are different");
878 tree high1
= CASE_HIGH (label1
);
879 tree high2
= CASE_HIGH (label2
);
881 if (!tree_int_cst_equal (high1
, high2
))
882 return return_false_with_msg ("case high values are different");
884 if (TREE_CODE (label1
) == CASE_LABEL_EXPR
885 && TREE_CODE (label2
) == CASE_LABEL_EXPR
)
887 label1
= CASE_LABEL (label1
);
888 label2
= CASE_LABEL (label2
);
890 if (!compare_operand (label1
, label2
))
891 return return_false_with_msg ("switch label_exprs are different");
893 else if (!tree_int_cst_equal (label1
, label2
))
894 return return_false_with_msg ("switch labels are different");
900 /* Verifies for given GIMPLE_RETURN stmts S1 and S2 that
901 return statements are semantically equivalent. */
904 func_checker::compare_gimple_return (const greturn
*g1
, const greturn
*g2
)
908 t1
= gimple_return_retval (g1
);
909 t2
= gimple_return_retval (g2
);
911 /* Void return type. */
912 if (t1
== NULL
&& t2
== NULL
)
915 return compare_operand (t1
, t2
);
918 /* Verifies for given GIMPLEs S1 and S2 that
919 goto statements are semantically equivalent. */
922 func_checker::compare_gimple_goto (gimple g1
, gimple g2
)
926 dest1
= gimple_goto_dest (g1
);
927 dest2
= gimple_goto_dest (g2
);
929 if (TREE_CODE (dest1
) != TREE_CODE (dest2
) || TREE_CODE (dest1
) != SSA_NAME
)
932 return compare_operand (dest1
, dest2
);
935 /* Verifies for given GIMPLE_RESX stmts S1 and S2 that
936 resx statements are semantically equivalent. */
939 func_checker::compare_gimple_resx (const gresx
*g1
, const gresx
*g2
)
941 return gimple_resx_region (g1
) == gimple_resx_region (g2
);
944 /* Verifies for given GIMPLEs S1 and S2 that ASM statements are equivalent.
945 For the beginning, the pass only supports equality for
946 '__asm__ __volatile__ ("", "", "", "memory")'. */
949 func_checker::compare_gimple_asm (const gasm
*g1
, const gasm
*g2
)
951 if (gimple_asm_volatile_p (g1
) != gimple_asm_volatile_p (g2
))
954 if (gimple_asm_ninputs (g1
) != gimple_asm_ninputs (g2
))
957 if (gimple_asm_noutputs (g1
) != gimple_asm_noutputs (g2
))
960 /* We do not suppport goto ASM statement comparison. */
961 if (gimple_asm_nlabels (g1
) || gimple_asm_nlabels (g2
))
964 if (gimple_asm_nclobbers (g1
) != gimple_asm_nclobbers (g2
))
967 if (strcmp (gimple_asm_string (g1
), gimple_asm_string (g2
)) != 0)
968 return return_false_with_msg ("ASM strings are different");
970 for (unsigned i
= 0; i
< gimple_asm_ninputs (g1
); i
++)
972 tree input1
= gimple_asm_input_op (g1
, i
);
973 tree input2
= gimple_asm_input_op (g2
, i
);
975 if (!compare_tree_list_operand (input1
, input2
))
976 return return_false_with_msg ("ASM input is different");
979 for (unsigned i
= 0; i
< gimple_asm_noutputs (g1
); i
++)
981 tree output1
= gimple_asm_output_op (g1
, i
);
982 tree output2
= gimple_asm_output_op (g2
, i
);
984 if (!compare_tree_list_operand (output1
, output2
))
985 return return_false_with_msg ("ASM output is different");
988 for (unsigned i
= 0; i
< gimple_asm_nclobbers (g1
); i
++)
990 tree clobber1
= gimple_asm_clobber_op (g1
, i
);
991 tree clobber2
= gimple_asm_clobber_op (g2
, i
);
993 if (!operand_equal_p (TREE_VALUE (clobber1
), TREE_VALUE (clobber2
),
995 return return_false_with_msg ("ASM clobber is different");
1001 } // ipa_icf_gimple namespace