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"
41 #include "basic-block.h"
42 #include "tree-ssa-alias.h"
43 #include "internal-fn.h"
44 #include "gimple-expr.h"
50 #include "statistics.h"
52 #include "fixed-value.h"
53 #include "insn-config.h"
62 #include "gimple-iterator.h"
63 #include "gimple-ssa.h"
65 #include "stringpool.h"
67 #include "tree-pass.h"
68 #include "gimple-pretty-print.h"
72 #include "plugin-api.h"
75 #include "data-streamer.h"
76 #include "ipa-utils.h"
78 #include "tree-ssanames.h"
81 #include "ipa-icf-gimple.h"
84 namespace ipa_icf_gimple
{
86 /* Initialize internal structures for a given SOURCE_FUNC_DECL and
87 TARGET_FUNC_DECL. Strict polymorphic comparison is processed if
88 an option COMPARE_POLYMORPHIC is true. For special cases, one can
89 set IGNORE_LABELS to skip label comparison.
90 Similarly, IGNORE_SOURCE_DECLS and IGNORE_TARGET_DECLS are sets
91 of declarations that can be skipped. */
93 func_checker::func_checker (tree source_func_decl
, tree target_func_decl
,
94 bool compare_polymorphic
,
96 hash_set
<symtab_node
*> *ignored_source_nodes
,
97 hash_set
<symtab_node
*> *ignored_target_nodes
)
98 : m_source_func_decl (source_func_decl
), m_target_func_decl (target_func_decl
),
99 m_ignored_source_nodes (ignored_source_nodes
),
100 m_ignored_target_nodes (ignored_target_nodes
),
101 m_compare_polymorphic (compare_polymorphic
),
102 m_ignore_labels (ignore_labels
)
104 function
*source_func
= DECL_STRUCT_FUNCTION (source_func_decl
);
105 function
*target_func
= DECL_STRUCT_FUNCTION (target_func_decl
);
107 unsigned ssa_source
= SSANAMES (source_func
)->length ();
108 unsigned ssa_target
= SSANAMES (target_func
)->length ();
110 m_source_ssa_names
.create (ssa_source
);
111 m_target_ssa_names
.create (ssa_target
);
113 for (unsigned i
= 0; i
< ssa_source
; i
++)
114 m_source_ssa_names
.safe_push (-1);
116 for (unsigned i
= 0; i
< ssa_target
; i
++)
117 m_target_ssa_names
.safe_push (-1);
120 /* Memory release routine. */
122 func_checker::~func_checker ()
124 m_source_ssa_names
.release();
125 m_target_ssa_names
.release();
128 /* Verifies that trees T1 and T2 are equivalent from perspective of ICF. */
131 func_checker::compare_ssa_name (tree t1
, tree t2
)
133 gcc_assert (TREE_CODE (t1
) == SSA_NAME
);
134 gcc_assert (TREE_CODE (t2
) == SSA_NAME
);
136 unsigned i1
= SSA_NAME_VERSION (t1
);
137 unsigned i2
= SSA_NAME_VERSION (t2
);
139 if (m_source_ssa_names
[i1
] == -1)
140 m_source_ssa_names
[i1
] = i2
;
141 else if (m_source_ssa_names
[i1
] != (int) i2
)
144 if(m_target_ssa_names
[i2
] == -1)
145 m_target_ssa_names
[i2
] = i1
;
146 else if (m_target_ssa_names
[i2
] != (int) i1
)
149 if (SSA_NAME_IS_DEFAULT_DEF (t1
))
151 tree b1
= SSA_NAME_VAR (t1
);
152 tree b2
= SSA_NAME_VAR (t2
);
154 if (b1
== NULL
&& b2
== NULL
)
157 if (b1
== NULL
|| b2
== NULL
|| TREE_CODE (b1
) != TREE_CODE (b2
))
158 return return_false ();
160 return compare_cst_or_decl (b1
, b2
);
166 /* Verification function for edges E1 and E2. */
169 func_checker::compare_edge (edge e1
, edge e2
)
171 if (e1
->flags
!= e2
->flags
)
176 edge
&slot
= m_edge_map
.get_or_insert (e1
, &existed_p
);
178 return return_with_debug (slot
== e2
);
182 /* TODO: filter edge probabilities for profile feedback match. */
187 /* Verification function for declaration trees T1 and T2 that
188 come from functions FUNC1 and FUNC2. */
191 func_checker::compare_decl (tree t1
, tree t2
)
193 if (!auto_var_in_fn_p (t1
, m_source_func_decl
)
194 || !auto_var_in_fn_p (t2
, m_target_func_decl
))
195 return return_with_debug (t1
== t2
);
197 tree_code t
= TREE_CODE (t1
);
198 if ((t
== VAR_DECL
|| t
== PARM_DECL
|| t
== RESULT_DECL
)
199 && DECL_BY_REFERENCE (t1
) != DECL_BY_REFERENCE (t2
))
200 return return_false_with_msg ("DECL_BY_REFERENCE flags are different");
202 if (!compatible_types_p (TREE_TYPE (t1
), TREE_TYPE (t2
),
203 m_compare_polymorphic
))
204 return return_false ();
208 tree
&slot
= m_decl_map
.get_or_insert (t1
, &existed_p
);
210 return return_with_debug (slot
== t2
);
217 /* Return true if types are compatible from perspective of ICF. */
219 func_checker::compatible_types_p (tree t1
, tree t2
,
220 bool compare_polymorphic
,
223 if (TREE_CODE (t1
) != TREE_CODE (t2
))
224 return return_false_with_msg ("different tree types");
226 if (TYPE_RESTRICT (t1
) != TYPE_RESTRICT (t2
))
227 return return_false_with_msg ("restrict flags are different");
229 if (!types_compatible_p (t1
, t2
))
230 return return_false_with_msg ("types are not compatible");
232 if (get_alias_set (t1
) != get_alias_set (t2
))
233 return return_false_with_msg ("alias sets are different");
235 /* We call contains_polymorphic_type_p with this pointer type. */
236 if (first_argument
&& TREE_CODE (t1
) == POINTER_TYPE
)
242 if (compare_polymorphic
)
243 if (contains_polymorphic_type_p (t1
) || contains_polymorphic_type_p (t2
))
245 if (!contains_polymorphic_type_p (t1
) || !contains_polymorphic_type_p (t2
))
246 return return_false_with_msg ("one type is not polymorphic");
248 if (!types_must_be_same_for_odr (t1
, t2
))
249 return return_false_with_msg ("types are not same for ODR");
255 /* Function compare for equality given memory operands T1 and T2. */
258 func_checker::compare_memory_operand (tree t1
, tree t2
)
266 ao_ref_init (&r1
, t1
);
267 ao_ref_init (&r2
, t2
);
269 tree b1
= ao_ref_base (&r1
);
270 tree b2
= ao_ref_base (&r2
);
272 bool source_is_memop
= DECL_P (b1
) || INDIRECT_REF_P (b1
)
273 || TREE_CODE (b1
) == MEM_REF
274 || TREE_CODE (b1
) == TARGET_MEM_REF
;
276 bool target_is_memop
= DECL_P (b2
) || INDIRECT_REF_P (b2
)
277 || TREE_CODE (b2
) == MEM_REF
278 || TREE_CODE (b2
) == TARGET_MEM_REF
;
280 /* Compare alias sets for memory operands. */
281 if (source_is_memop
&& target_is_memop
)
283 if (TREE_THIS_VOLATILE (t1
) != TREE_THIS_VOLATILE (t2
))
284 return return_false_with_msg ("different operand volatility");
286 if (ao_ref_alias_set (&r1
) != ao_ref_alias_set (&r2
)
287 || ao_ref_base_alias_set (&r1
) != ao_ref_base_alias_set (&r2
))
288 return return_false_with_msg ("ao alias sets are different");
291 return compare_operand (t1
, t2
);
294 /* Function compare for equality given trees T1 and T2 which
295 can be either a constant or a declaration type. */
298 func_checker::compare_cst_or_decl (tree t1
, tree t2
)
302 switch (TREE_CODE (t1
))
310 ret
= compatible_types_p (TREE_TYPE (t1
), TREE_TYPE (t2
))
311 && operand_equal_p (t1
, t2
, OEP_ONLY_CONST
);
312 return return_with_debug (ret
);
315 /* All function decls are in the symbol table and known to match
316 before we start comparing bodies. */
319 return return_with_debug (compare_variable_decl (t1
, t2
));
322 tree offset1
= DECL_FIELD_OFFSET (t1
);
323 tree offset2
= DECL_FIELD_OFFSET (t2
);
325 tree bit_offset1
= DECL_FIELD_BIT_OFFSET (t1
);
326 tree bit_offset2
= DECL_FIELD_BIT_OFFSET (t2
);
328 ret
= compare_operand (offset1
, offset2
)
329 && compare_operand (bit_offset1
, bit_offset2
);
331 return return_with_debug (ret
);
335 int *bb1
= m_label_bb_map
.get (t1
);
336 int *bb2
= m_label_bb_map
.get (t2
);
338 return return_with_debug (*bb1
== *bb2
);
344 ret
= compare_decl (t1
, t2
);
345 return return_with_debug (ret
);
352 /* Function responsible for comparison of various operands T1 and T2.
353 If these components, from functions FUNC1 and FUNC2, are equal, true
357 func_checker::compare_operand (tree t1
, tree t2
)
359 tree x1
, x2
, y1
, y2
, z1
, z2
;
367 tree tt1
= TREE_TYPE (t1
);
368 tree tt2
= TREE_TYPE (t2
);
370 if (!func_checker::compatible_types_p (tt1
, tt2
))
373 if (TREE_CODE (t1
) != TREE_CODE (t2
))
374 return return_false ();
376 switch (TREE_CODE (t1
))
380 unsigned length1
= vec_safe_length (CONSTRUCTOR_ELTS (t1
));
381 unsigned length2
= vec_safe_length (CONSTRUCTOR_ELTS (t2
));
383 if (length1
!= length2
)
384 return return_false ();
386 for (unsigned i
= 0; i
< length1
; i
++)
387 if (!compare_operand (CONSTRUCTOR_ELT (t1
, i
)->value
,
388 CONSTRUCTOR_ELT (t2
, i
)->value
))
389 return return_false();
394 case ARRAY_RANGE_REF
:
395 /* First argument is the array, second is the index. */
396 x1
= TREE_OPERAND (t1
, 0);
397 x2
= TREE_OPERAND (t2
, 0);
398 y1
= TREE_OPERAND (t1
, 1);
399 y2
= TREE_OPERAND (t2
, 1);
401 if (!compare_operand (array_ref_low_bound (t1
),
402 array_ref_low_bound (t2
)))
403 return return_false_with_msg ("");
404 if (!compare_operand (array_ref_element_size (t1
),
405 array_ref_element_size (t2
)))
406 return return_false_with_msg ("");
408 if (!compare_operand (x1
, x2
))
409 return return_false_with_msg ("");
410 return compare_operand (y1
, y2
);
413 x1
= TREE_OPERAND (t1
, 0);
414 x2
= TREE_OPERAND (t2
, 0);
415 y1
= TREE_OPERAND (t1
, 1);
416 y2
= TREE_OPERAND (t2
, 1);
418 /* See if operand is an memory access (the test originate from
421 In this case the alias set of the function being replaced must
422 be subset of the alias set of the other function. At the moment
423 we seek for equivalency classes, so simply require inclussion in
426 if (!func_checker::compatible_types_p (TREE_TYPE (x1
), TREE_TYPE (x2
)))
427 return return_false ();
429 if (!compare_operand (x1
, x2
))
430 return return_false_with_msg ("");
432 /* Type of the offset on MEM_REF does not matter. */
433 return wi::to_offset (y1
) == wi::to_offset (y2
);
437 x1
= TREE_OPERAND (t1
, 0);
438 x2
= TREE_OPERAND (t2
, 0);
439 y1
= TREE_OPERAND (t1
, 1);
440 y2
= TREE_OPERAND (t2
, 1);
442 ret
= compare_operand (x1
, x2
)
443 && compare_cst_or_decl (y1
, y2
);
445 return return_with_debug (ret
);
447 /* Virtual table call. */
450 if (!compare_ssa_name (OBJ_TYPE_REF_EXPR (t1
), OBJ_TYPE_REF_EXPR (t2
)))
451 return return_false ();
452 if (opt_for_fn (m_source_func_decl
, flag_devirtualize
)
453 && virtual_method_call_p (t1
))
455 if (tree_to_uhwi (OBJ_TYPE_REF_TOKEN (t1
))
456 != tree_to_uhwi (OBJ_TYPE_REF_TOKEN (t2
)))
457 return return_false_with_msg ("OBJ_TYPE_REF token mismatch");
458 if (!types_same_for_odr (obj_type_ref_class (t1
),
459 obj_type_ref_class (t2
)))
460 return return_false_with_msg ("OBJ_TYPE_REF OTR type mismatch");
461 if (!compare_ssa_name (OBJ_TYPE_REF_OBJECT (t1
),
462 OBJ_TYPE_REF_OBJECT (t2
)))
463 return return_false_with_msg ("OBJ_TYPE_REF object mismatch");
466 return return_with_debug (true);
472 x1
= TREE_OPERAND (t1
, 0);
473 x2
= TREE_OPERAND (t2
, 0);
475 ret
= compare_operand (x1
, x2
);
476 return return_with_debug (ret
);
480 x1
= TREE_OPERAND (t1
, 0);
481 x2
= TREE_OPERAND (t2
, 0);
482 y1
= TREE_OPERAND (t1
, 1);
483 y2
= TREE_OPERAND (t2
, 1);
484 z1
= TREE_OPERAND (t1
, 2);
485 z2
= TREE_OPERAND (t2
, 2);
487 ret
= compare_operand (x1
, x2
)
488 && compare_cst_or_decl (y1
, y2
)
489 && compare_cst_or_decl (z1
, z2
);
491 return return_with_debug (ret
);
494 return compare_ssa_name (t1
, t2
);
507 return compare_cst_or_decl (t1
, t2
);
509 return return_false_with_msg ("Unknown TREE code reached");
513 /* Compares two tree list operands T1 and T2 and returns true if these
514 two trees are semantically equivalent. */
517 func_checker::compare_tree_list_operand (tree t1
, tree t2
)
519 gcc_assert (TREE_CODE (t1
) == TREE_LIST
);
520 gcc_assert (TREE_CODE (t2
) == TREE_LIST
);
522 for (; t1
; t1
= TREE_CHAIN (t1
))
527 if (!compare_operand (TREE_VALUE (t1
), TREE_VALUE (t2
)))
528 return return_false ();
530 t2
= TREE_CHAIN (t2
);
534 return return_false ();
539 /* Verifies that trees T1 and T2 do correspond. */
542 func_checker::compare_variable_decl (tree t1
, tree t2
)
549 if (DECL_ALIGN (t1
) != DECL_ALIGN (t2
))
550 return return_false_with_msg ("alignments are different");
552 if (DECL_HARD_REGISTER (t1
) != DECL_HARD_REGISTER (t2
))
553 return return_false_with_msg ("DECL_HARD_REGISTER are different");
555 if (DECL_HARD_REGISTER (t1
)
556 && DECL_ASSEMBLER_NAME (t1
) != DECL_ASSEMBLER_NAME (t2
))
557 return return_false_with_msg ("HARD REGISTERS are different");
559 /* Symbol table variables are known to match before we start comparing
561 if (decl_in_symtab_p (t1
))
562 return decl_in_symtab_p (t2
);
563 ret
= compare_decl (t1
, t2
);
565 return return_with_debug (ret
);
569 /* Function visits all gimple labels and creates corresponding
570 mapping between basic blocks and labels. */
573 func_checker::parse_labels (sem_bb
*bb
)
575 for (gimple_stmt_iterator gsi
= gsi_start_bb (bb
->bb
); !gsi_end_p (gsi
);
578 gimple stmt
= gsi_stmt (gsi
);
580 if (glabel
*label_stmt
= dyn_cast
<glabel
*> (stmt
))
582 tree t
= gimple_label_label (label_stmt
);
583 gcc_assert (TREE_CODE (t
) == LABEL_DECL
);
585 m_label_bb_map
.put (t
, bb
->bb
->index
);
590 /* Basic block equivalence comparison function that returns true if
591 basic blocks BB1 and BB2 (from functions FUNC1 and FUNC2) correspond.
593 In general, a collection of equivalence dictionaries is built for types
594 like SSA names, declarations (VAR_DECL, PARM_DECL, ..). This infrastructure
595 is utilized by every statement-by-statement comparison function. */
598 func_checker::compare_bb (sem_bb
*bb1
, sem_bb
*bb2
)
600 gimple_stmt_iterator gsi1
, gsi2
;
603 gsi1
= gsi_start_bb_nondebug (bb1
->bb
);
604 gsi2
= gsi_start_bb_nondebug (bb2
->bb
);
606 while (!gsi_end_p (gsi1
))
608 if (gsi_end_p (gsi2
))
609 return return_false ();
611 s1
= gsi_stmt (gsi1
);
612 s2
= gsi_stmt (gsi2
);
614 int eh1
= lookup_stmt_eh_lp_fn
615 (DECL_STRUCT_FUNCTION (m_source_func_decl
), s1
);
616 int eh2
= lookup_stmt_eh_lp_fn
617 (DECL_STRUCT_FUNCTION (m_target_func_decl
), s2
);
620 return return_false_with_msg ("EH regions are different");
622 if (gimple_code (s1
) != gimple_code (s2
))
623 return return_false_with_msg ("gimple codes are different");
625 switch (gimple_code (s1
))
628 if (!compare_gimple_call (as_a
<gcall
*> (s1
),
629 as_a
<gcall
*> (s2
)))
630 return return_different_stmts (s1
, s2
, "GIMPLE_CALL");
633 if (!compare_gimple_assign (s1
, s2
))
634 return return_different_stmts (s1
, s2
, "GIMPLE_ASSIGN");
637 if (!compare_gimple_cond (s1
, s2
))
638 return return_different_stmts (s1
, s2
, "GIMPLE_COND");
641 if (!compare_gimple_switch (as_a
<gswitch
*> (s1
),
642 as_a
<gswitch
*> (s2
)))
643 return return_different_stmts (s1
, s2
, "GIMPLE_SWITCH");
646 case GIMPLE_EH_DISPATCH
:
649 if (!compare_gimple_resx (as_a
<gresx
*> (s1
),
650 as_a
<gresx
*> (s2
)))
651 return return_different_stmts (s1
, s2
, "GIMPLE_RESX");
654 if (!compare_gimple_label (as_a
<glabel
*> (s1
),
655 as_a
<glabel
*> (s2
)))
656 return return_different_stmts (s1
, s2
, "GIMPLE_LABEL");
659 if (!compare_gimple_return (as_a
<greturn
*> (s1
),
660 as_a
<greturn
*> (s2
)))
661 return return_different_stmts (s1
, s2
, "GIMPLE_RETURN");
664 if (!compare_gimple_goto (s1
, s2
))
665 return return_different_stmts (s1
, s2
, "GIMPLE_GOTO");
668 if (!compare_gimple_asm (as_a
<gasm
*> (s1
),
670 return return_different_stmts (s1
, s2
, "GIMPLE_ASM");
676 return return_false_with_msg ("Unknown GIMPLE code reached");
679 gsi_next_nondebug (&gsi1
);
680 gsi_next_nondebug (&gsi2
);
683 if (!gsi_end_p (gsi2
))
684 return return_false ();
689 /* Verifies for given GIMPLEs S1 and S2 that
690 call statements are semantically equivalent. */
693 func_checker::compare_gimple_call (gcall
*s1
, gcall
*s2
)
698 if (gimple_call_num_args (s1
) != gimple_call_num_args (s2
))
701 t1
= gimple_call_fn (s1
);
702 t2
= gimple_call_fn (s2
);
703 if (!compare_operand (t1
, t2
))
704 return return_false ();
707 if (gimple_call_internal_p (s1
) != gimple_call_internal_p (s2
)
708 || gimple_call_ctrl_altering_p (s1
) != gimple_call_ctrl_altering_p (s2
)
709 || gimple_call_tail_p (s1
) != gimple_call_tail_p (s2
)
710 || gimple_call_return_slot_opt_p (s1
) != gimple_call_return_slot_opt_p (s2
)
711 || gimple_call_from_thunk_p (s1
) != gimple_call_from_thunk_p (s2
)
712 || gimple_call_va_arg_pack_p (s1
) != gimple_call_va_arg_pack_p (s2
)
713 || gimple_call_alloca_for_var_p (s1
) != gimple_call_alloca_for_var_p (s2
)
714 || gimple_call_with_bounds_p (s1
) != gimple_call_with_bounds_p (s2
))
717 if (gimple_call_internal_p (s1
)
718 && gimple_call_internal_fn (s1
) != gimple_call_internal_fn (s2
))
721 tree fntype1
= gimple_call_fntype (s1
);
722 tree fntype2
= gimple_call_fntype (s2
);
723 if ((fntype1
&& !fntype2
)
724 || (!fntype1
&& fntype2
)
725 || (fntype1
&& !types_compatible_p (fntype1
, fntype2
)))
726 return return_false_with_msg ("call function types are not compatible");
728 tree chain1
= gimple_call_chain (s1
);
729 tree chain2
= gimple_call_chain (s2
);
730 if ((chain1
&& !chain2
)
731 || (!chain1
&& chain2
)
732 || !compare_operand (chain1
, chain2
))
733 return return_false_with_msg ("static call chains are different");
735 /* Checking of argument. */
736 for (i
= 0; i
< gimple_call_num_args (s1
); ++i
)
738 t1
= gimple_call_arg (s1
, i
);
739 t2
= gimple_call_arg (s2
, i
);
741 if (!compare_memory_operand (t1
, t2
))
742 return return_false_with_msg ("memory operands are different");
745 /* Return value checking. */
746 t1
= gimple_get_lhs (s1
);
747 t2
= gimple_get_lhs (s2
);
749 return compare_memory_operand (t1
, t2
);
753 /* Verifies for given GIMPLEs S1 and S2 that
754 assignment statements are semantically equivalent. */
757 func_checker::compare_gimple_assign (gimple s1
, gimple s2
)
760 tree_code code1
, code2
;
763 code1
= gimple_expr_code (s1
);
764 code2
= gimple_expr_code (s2
);
769 code1
= gimple_assign_rhs_code (s1
);
770 code2
= gimple_assign_rhs_code (s2
);
775 for (i
= 0; i
< gimple_num_ops (s1
); i
++)
777 arg1
= gimple_op (s1
, i
);
778 arg2
= gimple_op (s2
, i
);
780 if (!compare_memory_operand (arg1
, arg2
))
781 return return_false_with_msg ("memory operands are different");
788 /* Verifies for given GIMPLEs S1 and S2 that
789 condition statements are semantically equivalent. */
792 func_checker::compare_gimple_cond (gimple s1
, gimple s2
)
795 tree_code code1
, code2
;
797 code1
= gimple_expr_code (s1
);
798 code2
= gimple_expr_code (s2
);
803 t1
= gimple_cond_lhs (s1
);
804 t2
= gimple_cond_lhs (s2
);
806 if (!compare_operand (t1
, t2
))
809 t1
= gimple_cond_rhs (s1
);
810 t2
= gimple_cond_rhs (s2
);
812 return compare_operand (t1
, t2
);
815 /* Verifies that tree labels T1 and T2 correspond in FUNC1 and FUNC2. */
818 func_checker::compare_tree_ssa_label (tree t1
, tree t2
)
820 return compare_operand (t1
, t2
);
823 /* Verifies for given GIMPLE_LABEL stmts S1 and S2 that
824 label statements are semantically equivalent. */
827 func_checker::compare_gimple_label (const glabel
*g1
, const glabel
*g2
)
832 tree t1
= gimple_label_label (g1
);
833 tree t2
= gimple_label_label (g2
);
835 if (FORCED_LABEL (t1
) || FORCED_LABEL (t2
))
836 return return_false_with_msg ("FORCED_LABEL");
838 /* As the pass build BB to label mapping, no further check is needed. */
842 /* Verifies for given GIMPLE_SWITCH stmts S1 and S2 that
843 switch statements are semantically equivalent. */
846 func_checker::compare_gimple_switch (const gswitch
*g1
, const gswitch
*g2
)
848 unsigned lsize1
, lsize2
, i
;
850 lsize1
= gimple_switch_num_labels (g1
);
851 lsize2
= gimple_switch_num_labels (g2
);
853 if (lsize1
!= lsize2
)
856 tree t1
= gimple_switch_index (g1
);
857 tree t2
= gimple_switch_index (g2
);
859 if (!compare_operand (t1
, t2
))
862 for (i
= 0; i
< lsize1
; i
++)
864 tree label1
= gimple_switch_label (g1
, i
);
865 tree label2
= gimple_switch_label (g2
, i
);
867 /* Label LOW and HIGH comparison. */
868 tree low1
= CASE_LOW (label1
);
869 tree low2
= CASE_LOW (label2
);
871 if (!tree_int_cst_equal (low1
, low2
))
872 return return_false_with_msg ("case low values are different");
874 tree high1
= CASE_HIGH (label1
);
875 tree high2
= CASE_HIGH (label2
);
877 if (!tree_int_cst_equal (high1
, high2
))
878 return return_false_with_msg ("case high values are different");
880 if (TREE_CODE (label1
) == CASE_LABEL_EXPR
881 && TREE_CODE (label2
) == CASE_LABEL_EXPR
)
883 label1
= CASE_LABEL (label1
);
884 label2
= CASE_LABEL (label2
);
886 if (!compare_operand (label1
, label2
))
887 return return_false_with_msg ("switch label_exprs are different");
889 else if (!tree_int_cst_equal (label1
, label2
))
890 return return_false_with_msg ("switch labels are different");
896 /* Verifies for given GIMPLE_RETURN stmts S1 and S2 that
897 return statements are semantically equivalent. */
900 func_checker::compare_gimple_return (const greturn
*g1
, const greturn
*g2
)
904 t1
= gimple_return_retval (g1
);
905 t2
= gimple_return_retval (g2
);
907 /* Void return type. */
908 if (t1
== NULL
&& t2
== NULL
)
911 return compare_operand (t1
, t2
);
914 /* Verifies for given GIMPLEs S1 and S2 that
915 goto statements are semantically equivalent. */
918 func_checker::compare_gimple_goto (gimple g1
, gimple g2
)
922 dest1
= gimple_goto_dest (g1
);
923 dest2
= gimple_goto_dest (g2
);
925 if (TREE_CODE (dest1
) != TREE_CODE (dest2
) || TREE_CODE (dest1
) != SSA_NAME
)
928 return compare_operand (dest1
, dest2
);
931 /* Verifies for given GIMPLE_RESX stmts S1 and S2 that
932 resx statements are semantically equivalent. */
935 func_checker::compare_gimple_resx (const gresx
*g1
, const gresx
*g2
)
937 return gimple_resx_region (g1
) == gimple_resx_region (g2
);
940 /* Verifies for given GIMPLEs S1 and S2 that ASM statements are equivalent.
941 For the beginning, the pass only supports equality for
942 '__asm__ __volatile__ ("", "", "", "memory")'. */
945 func_checker::compare_gimple_asm (const gasm
*g1
, const gasm
*g2
)
947 if (gimple_asm_volatile_p (g1
) != gimple_asm_volatile_p (g2
))
950 if (gimple_asm_ninputs (g1
) != gimple_asm_ninputs (g2
))
953 if (gimple_asm_noutputs (g1
) != gimple_asm_noutputs (g2
))
956 /* We do not suppport goto ASM statement comparison. */
957 if (gimple_asm_nlabels (g1
) || gimple_asm_nlabels (g2
))
960 if (gimple_asm_nclobbers (g1
) != gimple_asm_nclobbers (g2
))
963 if (strcmp (gimple_asm_string (g1
), gimple_asm_string (g2
)) != 0)
964 return return_false_with_msg ("ASM strings are different");
966 for (unsigned i
= 0; i
< gimple_asm_ninputs (g1
); i
++)
968 tree input1
= gimple_asm_input_op (g1
, i
);
969 tree input2
= gimple_asm_input_op (g2
, i
);
971 if (!compare_tree_list_operand (input1
, input2
))
972 return return_false_with_msg ("ASM input is different");
975 for (unsigned i
= 0; i
< gimple_asm_noutputs (g1
); i
++)
977 tree output1
= gimple_asm_output_op (g1
, i
);
978 tree output2
= gimple_asm_output_op (g2
, i
);
980 if (!compare_tree_list_operand (output1
, output2
))
981 return return_false_with_msg ("ASM output is different");
984 for (unsigned i
= 0; i
< gimple_asm_nclobbers (g1
); i
++)
986 tree clobber1
= gimple_asm_clobber_op (g1
, i
);
987 tree clobber2
= gimple_asm_clobber_op (g2
, i
);
989 if (!operand_equal_p (TREE_VALUE (clobber1
), TREE_VALUE (clobber2
),
991 return return_false_with_msg ("ASM clobber is different");
997 } // ipa_icf_gimple namespace