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"
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 gcc_assert (TREE_CODE (t1
) == SSA_NAME
);
114 gcc_assert (TREE_CODE (t2
) == SSA_NAME
);
116 unsigned i1
= SSA_NAME_VERSION (t1
);
117 unsigned i2
= SSA_NAME_VERSION (t2
);
119 if (m_source_ssa_names
[i1
] == -1)
120 m_source_ssa_names
[i1
] = i2
;
121 else if (m_source_ssa_names
[i1
] != (int) i2
)
124 if(m_target_ssa_names
[i2
] == -1)
125 m_target_ssa_names
[i2
] = i1
;
126 else if (m_target_ssa_names
[i2
] != (int) i1
)
129 if (SSA_NAME_IS_DEFAULT_DEF (t1
))
131 tree b1
= SSA_NAME_VAR (t1
);
132 tree b2
= SSA_NAME_VAR (t2
);
134 if (b1
== NULL
&& b2
== NULL
)
137 if (b1
== NULL
|| b2
== NULL
|| TREE_CODE (b1
) != TREE_CODE (b2
))
138 return return_false ();
140 return compare_cst_or_decl (b1
, b2
);
146 /* Verification function for edges E1 and E2. */
149 func_checker::compare_edge (edge e1
, edge e2
)
151 if (e1
->flags
!= e2
->flags
)
156 edge
&slot
= m_edge_map
.get_or_insert (e1
, &existed_p
);
158 return return_with_debug (slot
== e2
);
162 /* TODO: filter edge probabilities for profile feedback match. */
167 /* Verification function for declaration trees T1 and T2 that
168 come from functions FUNC1 and FUNC2. */
171 func_checker::compare_decl (tree t1
, tree t2
)
173 if (!auto_var_in_fn_p (t1
, m_source_func_decl
)
174 || !auto_var_in_fn_p (t2
, m_target_func_decl
))
175 return return_with_debug (t1
== t2
);
177 tree_code t
= TREE_CODE (t1
);
178 if ((t
== VAR_DECL
|| t
== PARM_DECL
|| t
== RESULT_DECL
)
179 && DECL_BY_REFERENCE (t1
) != DECL_BY_REFERENCE (t2
))
180 return return_false_with_msg ("DECL_BY_REFERENCE flags are different");
182 if (!compatible_types_p (TREE_TYPE (t1
), TREE_TYPE (t2
),
183 m_compare_polymorphic
))
184 return return_false ();
188 tree
&slot
= m_decl_map
.get_or_insert (t1
, &existed_p
);
190 return return_with_debug (slot
== t2
);
197 /* Return true if types are compatible from perspective of ICF. */
199 func_checker::compatible_types_p (tree t1
, tree t2
,
200 bool compare_polymorphic
,
203 if (TREE_CODE (t1
) != TREE_CODE (t2
))
204 return return_false_with_msg ("different tree types");
206 if (TYPE_RESTRICT (t1
) != TYPE_RESTRICT (t2
))
207 return return_false_with_msg ("restrict flags are different");
209 if (!types_compatible_p (t1
, t2
))
210 return return_false_with_msg ("types are not compatible");
212 if (get_alias_set (t1
) != get_alias_set (t2
))
213 return return_false_with_msg ("alias sets are different");
215 /* We call contains_polymorphic_type_p with this pointer type. */
216 if (first_argument
&& TREE_CODE (t1
) == POINTER_TYPE
)
222 if (compare_polymorphic
)
223 if (contains_polymorphic_type_p (t1
) || contains_polymorphic_type_p (t2
))
225 if (!contains_polymorphic_type_p (t1
) || !contains_polymorphic_type_p (t2
))
226 return return_false_with_msg ("one type is not polymorphic");
228 if (!types_must_be_same_for_odr (t1
, t2
))
229 return return_false_with_msg ("types are not same for ODR");
235 /* Function compare for equality given memory operands T1 and T2. */
238 func_checker::compare_memory_operand (tree t1
, tree t2
)
246 ao_ref_init (&r1
, t1
);
247 ao_ref_init (&r2
, t2
);
249 tree b1
= ao_ref_base (&r1
);
250 tree b2
= ao_ref_base (&r2
);
252 bool source_is_memop
= DECL_P (b1
) || INDIRECT_REF_P (b1
)
253 || TREE_CODE (b1
) == MEM_REF
254 || TREE_CODE (b1
) == TARGET_MEM_REF
;
256 bool target_is_memop
= DECL_P (b2
) || INDIRECT_REF_P (b2
)
257 || TREE_CODE (b2
) == MEM_REF
258 || TREE_CODE (b2
) == TARGET_MEM_REF
;
260 /* Compare alias sets for memory operands. */
261 if (source_is_memop
&& target_is_memop
)
263 if (TREE_THIS_VOLATILE (b1
) != TREE_THIS_VOLATILE (b2
))
264 return return_false_with_msg ("different operand volatility");
266 if (ao_ref_alias_set (&r1
) != ao_ref_alias_set (&r2
)
267 || ao_ref_base_alias_set (&r1
) != ao_ref_base_alias_set (&r2
))
268 return return_false_with_msg ("ao alias sets are different");
271 return compare_operand (t1
, t2
);
274 /* Function compare for equality given trees T1 and T2 which
275 can be either a constant or a declaration type. */
278 func_checker::compare_cst_or_decl (tree t1
, tree t2
)
282 switch (TREE_CODE (t1
))
290 ret
= compatible_types_p (TREE_TYPE (t1
), TREE_TYPE (t2
))
291 && operand_equal_p (t1
, t2
, OEP_ONLY_CONST
);
292 return return_with_debug (ret
);
296 ret
= compare_function_decl (t1
, t2
);
297 return return_with_debug (ret
);
300 return return_with_debug (compare_variable_decl (t1
, t2
));
303 tree offset1
= DECL_FIELD_OFFSET (t1
);
304 tree offset2
= DECL_FIELD_OFFSET (t2
);
306 tree bit_offset1
= DECL_FIELD_BIT_OFFSET (t1
);
307 tree bit_offset2
= DECL_FIELD_BIT_OFFSET (t2
);
309 ret
= compare_operand (offset1
, offset2
)
310 && compare_operand (bit_offset1
, bit_offset2
);
312 return return_with_debug (ret
);
316 int *bb1
= m_label_bb_map
.get (t1
);
317 int *bb2
= m_label_bb_map
.get (t2
);
319 return return_with_debug (*bb1
== *bb2
);
325 ret
= compare_decl (t1
, t2
);
326 return return_with_debug (ret
);
333 /* Function responsible for comparison of various operands T1 and T2.
334 If these components, from functions FUNC1 and FUNC2, are equal, true
338 func_checker::compare_operand (tree t1
, tree t2
)
340 tree x1
, x2
, y1
, y2
, z1
, z2
;
348 tree tt1
= TREE_TYPE (t1
);
349 tree tt2
= TREE_TYPE (t2
);
351 if (!func_checker::compatible_types_p (tt1
, tt2
))
354 if (TREE_CODE (t1
) != TREE_CODE (t2
))
355 return return_false ();
357 switch (TREE_CODE (t1
))
361 unsigned length1
= vec_safe_length (CONSTRUCTOR_ELTS (t1
));
362 unsigned length2
= vec_safe_length (CONSTRUCTOR_ELTS (t2
));
364 if (length1
!= length2
)
365 return return_false ();
367 for (unsigned i
= 0; i
< length1
; i
++)
368 if (!compare_operand (CONSTRUCTOR_ELT (t1
, i
)->value
,
369 CONSTRUCTOR_ELT (t2
, i
)->value
))
370 return return_false();
375 case ARRAY_RANGE_REF
:
376 /* First argument is the array, second is the index. */
377 x1
= TREE_OPERAND (t1
, 0);
378 x2
= TREE_OPERAND (t2
, 0);
379 y1
= TREE_OPERAND (t1
, 1);
380 y2
= TREE_OPERAND (t2
, 1);
382 if (!compare_operand (array_ref_low_bound (t1
),
383 array_ref_low_bound (t2
)))
384 return return_false_with_msg ("");
385 if (!compare_operand (array_ref_element_size (t1
),
386 array_ref_element_size (t2
)))
387 return return_false_with_msg ("");
389 if (!compare_operand (x1
, x2
))
390 return return_false_with_msg ("");
391 return compare_operand (y1
, y2
);
394 x1
= TREE_OPERAND (t1
, 0);
395 x2
= TREE_OPERAND (t2
, 0);
396 y1
= TREE_OPERAND (t1
, 1);
397 y2
= TREE_OPERAND (t2
, 1);
399 /* See if operand is an memory access (the test originate from
402 In this case the alias set of the function being replaced must
403 be subset of the alias set of the other function. At the moment
404 we seek for equivalency classes, so simply require inclussion in
407 if (!func_checker::compatible_types_p (TREE_TYPE (x1
), TREE_TYPE (x2
)))
408 return return_false ();
410 if (!compare_operand (x1
, x2
))
411 return return_false_with_msg ("");
413 /* Type of the offset on MEM_REF does not matter. */
414 return wi::to_offset (y1
) == wi::to_offset (y2
);
418 x1
= TREE_OPERAND (t1
, 0);
419 x2
= TREE_OPERAND (t2
, 0);
420 y1
= TREE_OPERAND (t1
, 1);
421 y2
= TREE_OPERAND (t2
, 1);
423 ret
= compare_operand (x1
, x2
)
424 && compare_cst_or_decl (y1
, y2
);
426 return return_with_debug (ret
);
428 /* Virtual table call. */
431 x1
= TREE_OPERAND (t1
, 0);
432 x2
= TREE_OPERAND (t2
, 0);
433 y1
= TREE_OPERAND (t1
, 1);
434 y2
= TREE_OPERAND (t2
, 1);
435 z1
= TREE_OPERAND (t1
, 2);
436 z2
= TREE_OPERAND (t2
, 2);
438 ret
= compare_ssa_name (x1
, x2
)
439 && compare_ssa_name (y1
, y2
)
440 && compare_cst_or_decl (z1
, z2
);
442 return return_with_debug (ret
);
446 x1
= TREE_OPERAND (t1
, 0);
447 x2
= TREE_OPERAND (t2
, 0);
449 ret
= compare_operand (x1
, x2
);
450 return return_with_debug (ret
);
454 ret
= compare_decl (t1
, t2
);
455 return return_with_debug (ret
);
458 return compare_ssa_name (t1
, t2
);
471 return compare_cst_or_decl (t1
, t2
);
473 return return_false_with_msg ("Unknown TREE code reached");
477 /* Compares two tree list operands T1 and T2 and returns true if these
478 two trees are semantically equivalent. */
481 func_checker::compare_tree_list_operand (tree t1
, tree t2
)
483 gcc_assert (TREE_CODE (t1
) == TREE_LIST
);
484 gcc_assert (TREE_CODE (t2
) == TREE_LIST
);
486 for (; t1
; t1
= TREE_CHAIN (t1
))
491 if (!compare_operand (TREE_VALUE (t1
), TREE_VALUE (t2
)))
492 return return_false ();
494 t2
= TREE_CHAIN (t2
);
498 return return_false ();
503 /* Verifies that trees T1 and T2, representing function declarations
504 are equivalent from perspective of ICF. */
507 func_checker::compare_function_decl (tree t1
, tree t2
)
514 symtab_node
*n1
= symtab_node::get (t1
);
515 symtab_node
*n2
= symtab_node::get (t2
);
517 if (m_ignored_source_nodes
!= NULL
&& m_ignored_target_nodes
!= NULL
)
519 ret
= m_ignored_source_nodes
->contains (n1
)
520 && m_ignored_target_nodes
->contains (n2
);
526 /* If function decl is WEAKREF, we compare targets. */
527 cgraph_node
*f1
= cgraph_node::get (t1
);
528 cgraph_node
*f2
= cgraph_node::get (t2
);
530 if(f1
&& f2
&& f1
->weakref
&& f2
->weakref
)
531 ret
= f1
->alias_target
== f2
->alias_target
;
536 /* Verifies that trees T1 and T2 do correspond. */
539 func_checker::compare_variable_decl (tree t1
, tree t2
)
546 if (TREE_CODE (t1
) == VAR_DECL
&& (DECL_EXTERNAL (t1
) || TREE_STATIC (t1
)))
548 symtab_node
*n1
= symtab_node::get (t1
);
549 symtab_node
*n2
= symtab_node::get (t2
);
551 if (m_ignored_source_nodes
!= NULL
&& m_ignored_target_nodes
!= NULL
)
553 ret
= m_ignored_source_nodes
->contains (n1
)
554 && m_ignored_target_nodes
->contains (n2
);
560 ret
= compare_decl (t1
, t2
);
562 return return_with_debug (ret
);
566 /* Function visits all gimple labels and creates corresponding
567 mapping between basic blocks and labels. */
570 func_checker::parse_labels (sem_bb
*bb
)
572 for (gimple_stmt_iterator gsi
= gsi_start_bb (bb
->bb
); !gsi_end_p (gsi
);
575 gimple stmt
= gsi_stmt (gsi
);
577 if (glabel
*label_stmt
= dyn_cast
<glabel
*> (stmt
))
579 tree t
= gimple_label_label (label_stmt
);
580 gcc_assert (TREE_CODE (t
) == LABEL_DECL
);
582 m_label_bb_map
.put (t
, bb
->bb
->index
);
587 /* Basic block equivalence comparison function that returns true if
588 basic blocks BB1 and BB2 (from functions FUNC1 and FUNC2) correspond.
590 In general, a collection of equivalence dictionaries is built for types
591 like SSA names, declarations (VAR_DECL, PARM_DECL, ..). This infrastructure
592 is utilized by every statement-by-statement comparison function. */
595 func_checker::compare_bb (sem_bb
*bb1
, sem_bb
*bb2
)
597 gimple_stmt_iterator gsi1
, gsi2
;
600 gsi1
= gsi_start_bb_nondebug (bb1
->bb
);
601 gsi2
= gsi_start_bb_nondebug (bb2
->bb
);
603 while (!gsi_end_p (gsi1
))
605 if (gsi_end_p (gsi2
))
606 return return_false ();
608 s1
= gsi_stmt (gsi1
);
609 s2
= gsi_stmt (gsi2
);
611 int eh1
= lookup_stmt_eh_lp_fn
612 (DECL_STRUCT_FUNCTION (m_source_func_decl
), s1
);
613 int eh2
= lookup_stmt_eh_lp_fn
614 (DECL_STRUCT_FUNCTION (m_target_func_decl
), s2
);
617 return return_false_with_msg ("EH regions are different");
619 if (gimple_code (s1
) != gimple_code (s2
))
620 return return_false_with_msg ("gimple codes are different");
622 switch (gimple_code (s1
))
625 if (!compare_gimple_call (as_a
<gcall
*> (s1
),
626 as_a
<gcall
*> (s2
)))
627 return return_different_stmts (s1
, s2
, "GIMPLE_CALL");
630 if (!compare_gimple_assign (s1
, s2
))
631 return return_different_stmts (s1
, s2
, "GIMPLE_ASSIGN");
634 if (!compare_gimple_cond (s1
, s2
))
635 return return_different_stmts (s1
, s2
, "GIMPLE_COND");
638 if (!compare_gimple_switch (as_a
<gswitch
*> (s1
),
639 as_a
<gswitch
*> (s2
)))
640 return return_different_stmts (s1
, s2
, "GIMPLE_SWITCH");
643 case GIMPLE_EH_DISPATCH
:
646 if (!compare_gimple_resx (as_a
<gresx
*> (s1
),
647 as_a
<gresx
*> (s2
)))
648 return return_different_stmts (s1
, s2
, "GIMPLE_RESX");
651 if (!compare_gimple_label (as_a
<glabel
*> (s1
),
652 as_a
<glabel
*> (s2
)))
653 return return_different_stmts (s1
, s2
, "GIMPLE_LABEL");
656 if (!compare_gimple_return (as_a
<greturn
*> (s1
),
657 as_a
<greturn
*> (s2
)))
658 return return_different_stmts (s1
, s2
, "GIMPLE_RETURN");
661 if (!compare_gimple_goto (s1
, s2
))
662 return return_different_stmts (s1
, s2
, "GIMPLE_GOTO");
665 if (!compare_gimple_asm (as_a
<gasm
*> (s1
),
667 return return_different_stmts (s1
, s2
, "GIMPLE_ASM");
673 return return_false_with_msg ("Unknown GIMPLE code reached");
676 gsi_next_nondebug (&gsi1
);
677 gsi_next_nondebug (&gsi2
);
680 if (!gsi_end_p (gsi2
))
681 return return_false ();
686 /* Verifies for given GIMPLEs S1 and S2 that
687 call statements are semantically equivalent. */
690 func_checker::compare_gimple_call (gcall
*s1
, gcall
*s2
)
695 if (gimple_call_num_args (s1
) != gimple_call_num_args (s2
))
698 t1
= gimple_call_fn (s1
);
699 t2
= gimple_call_fn (s2
);
700 if (!compare_operand (t1
, t2
))
701 return return_false ();
704 if (gimple_call_internal_p (s1
) != gimple_call_internal_p (s2
)
705 || gimple_call_ctrl_altering_p (s1
) != gimple_call_ctrl_altering_p (s2
)
706 || gimple_call_tail_p (s1
) != gimple_call_tail_p (s2
)
707 || gimple_call_return_slot_opt_p (s1
) != gimple_call_return_slot_opt_p (s2
)
708 || gimple_call_from_thunk_p (s1
) != gimple_call_from_thunk_p (s2
)
709 || gimple_call_va_arg_pack_p (s1
) != gimple_call_va_arg_pack_p (s2
)
710 || gimple_call_alloca_for_var_p (s1
) != gimple_call_alloca_for_var_p (s2
)
711 || gimple_call_with_bounds_p (s1
) != gimple_call_with_bounds_p (s2
))
714 if (gimple_call_internal_p (s1
)
715 && gimple_call_internal_fn (s1
) != gimple_call_internal_fn (s2
))
718 tree fntype1
= gimple_call_fntype (s1
);
719 tree fntype2
= gimple_call_fntype (s2
);
720 if ((fntype1
&& !fntype2
)
721 || (!fntype1
&& fntype2
)
722 || (fntype1
&& !types_compatible_p (fntype1
, fntype2
)))
723 return return_false_with_msg ("call function types are not compatible");
725 tree chain1
= gimple_call_chain (s1
);
726 tree chain2
= gimple_call_chain (s2
);
727 if ((chain1
&& !chain2
)
728 || (!chain1
&& chain2
)
729 || !compare_operand (chain1
, chain2
))
730 return return_false_with_msg ("static call chains are different");
732 /* Checking of argument. */
733 for (i
= 0; i
< gimple_call_num_args (s1
); ++i
)
735 t1
= gimple_call_arg (s1
, i
);
736 t2
= gimple_call_arg (s2
, i
);
738 if (!compare_memory_operand (t1
, t2
))
739 return return_false_with_msg ("memory operands are different");
742 /* Return value checking. */
743 t1
= gimple_get_lhs (s1
);
744 t2
= gimple_get_lhs (s2
);
746 return compare_memory_operand (t1
, t2
);
750 /* Verifies for given GIMPLEs S1 and S2 that
751 assignment statements are semantically equivalent. */
754 func_checker::compare_gimple_assign (gimple s1
, gimple s2
)
757 tree_code code1
, code2
;
760 code1
= gimple_expr_code (s1
);
761 code2
= gimple_expr_code (s2
);
766 code1
= gimple_assign_rhs_code (s1
);
767 code2
= gimple_assign_rhs_code (s2
);
772 for (i
= 0; i
< gimple_num_ops (s1
); i
++)
774 arg1
= gimple_op (s1
, i
);
775 arg2
= gimple_op (s2
, i
);
777 if (!compare_memory_operand (arg1
, arg2
))
778 return return_false_with_msg ("memory operands are different");
785 /* Verifies for given GIMPLEs S1 and S2 that
786 condition statements are semantically equivalent. */
789 func_checker::compare_gimple_cond (gimple s1
, gimple s2
)
792 tree_code code1
, code2
;
794 code1
= gimple_expr_code (s1
);
795 code2
= gimple_expr_code (s2
);
800 t1
= gimple_cond_lhs (s1
);
801 t2
= gimple_cond_lhs (s2
);
803 if (!compare_operand (t1
, t2
))
806 t1
= gimple_cond_rhs (s1
);
807 t2
= gimple_cond_rhs (s2
);
809 return compare_operand (t1
, t2
);
812 /* Verifies that tree labels T1 and T2 correspond in FUNC1 and FUNC2. */
815 func_checker::compare_tree_ssa_label (tree t1
, tree t2
)
817 return compare_operand (t1
, t2
);
820 /* Verifies for given GIMPLE_LABEL stmts S1 and S2 that
821 label statements are semantically equivalent. */
824 func_checker::compare_gimple_label (const glabel
*g1
, const glabel
*g2
)
829 tree t1
= gimple_label_label (g1
);
830 tree t2
= gimple_label_label (g2
);
832 if (FORCED_LABEL (t1
) || FORCED_LABEL (t2
))
833 return return_false_with_msg ("FORCED_LABEL");
835 /* As the pass build BB to label mapping, no further check is needed. */
839 /* Verifies for given GIMPLE_SWITCH stmts S1 and S2 that
840 switch statements are semantically equivalent. */
843 func_checker::compare_gimple_switch (const gswitch
*g1
, const gswitch
*g2
)
845 unsigned lsize1
, lsize2
, i
;
847 lsize1
= gimple_switch_num_labels (g1
);
848 lsize2
= gimple_switch_num_labels (g2
);
850 if (lsize1
!= lsize2
)
853 tree t1
= gimple_switch_index (g1
);
854 tree t2
= gimple_switch_index (g2
);
856 if (!compare_operand (t1
, t2
))
859 for (i
= 0; i
< lsize1
; i
++)
861 tree label1
= gimple_switch_label (g1
, i
);
862 tree label2
= gimple_switch_label (g2
, i
);
864 /* Label LOW and HIGH comparison. */
865 tree low1
= CASE_LOW (label1
);
866 tree low2
= CASE_LOW (label2
);
868 if (!tree_int_cst_equal (low1
, low2
))
869 return return_false_with_msg ("case low values are different");
871 tree high1
= CASE_HIGH (label1
);
872 tree high2
= CASE_HIGH (label2
);
874 if (!tree_int_cst_equal (high1
, high2
))
875 return return_false_with_msg ("case high values are different");
877 if (TREE_CODE (label1
) == CASE_LABEL_EXPR
878 && TREE_CODE (label2
) == CASE_LABEL_EXPR
)
880 label1
= CASE_LABEL (label1
);
881 label2
= CASE_LABEL (label2
);
883 if (!compare_operand (label1
, label2
))
884 return return_false_with_msg ("switch label_exprs are different");
886 else if (!tree_int_cst_equal (label1
, label2
))
887 return return_false_with_msg ("switch labels are different");
893 /* Verifies for given GIMPLE_RETURN stmts S1 and S2 that
894 return statements are semantically equivalent. */
897 func_checker::compare_gimple_return (const greturn
*g1
, const greturn
*g2
)
901 t1
= gimple_return_retval (g1
);
902 t2
= gimple_return_retval (g2
);
904 /* Void return type. */
905 if (t1
== NULL
&& t2
== NULL
)
908 return compare_operand (t1
, t2
);
911 /* Verifies for given GIMPLEs S1 and S2 that
912 goto statements are semantically equivalent. */
915 func_checker::compare_gimple_goto (gimple g1
, gimple g2
)
919 dest1
= gimple_goto_dest (g1
);
920 dest2
= gimple_goto_dest (g2
);
922 if (TREE_CODE (dest1
) != TREE_CODE (dest2
) || TREE_CODE (dest1
) != SSA_NAME
)
925 return compare_operand (dest1
, dest2
);
928 /* Verifies for given GIMPLE_RESX stmts S1 and S2 that
929 resx statements are semantically equivalent. */
932 func_checker::compare_gimple_resx (const gresx
*g1
, const gresx
*g2
)
934 return gimple_resx_region (g1
) == gimple_resx_region (g2
);
937 /* Verifies for given GIMPLEs S1 and S2 that ASM statements are equivalent.
938 For the beginning, the pass only supports equality for
939 '__asm__ __volatile__ ("", "", "", "memory")'. */
942 func_checker::compare_gimple_asm (const gasm
*g1
, const gasm
*g2
)
944 if (gimple_asm_volatile_p (g1
) != gimple_asm_volatile_p (g2
))
947 if (gimple_asm_ninputs (g1
) != gimple_asm_ninputs (g2
))
950 if (gimple_asm_noutputs (g1
) != gimple_asm_noutputs (g2
))
953 /* We do not suppport goto ASM statement comparison. */
954 if (gimple_asm_nlabels (g1
) || gimple_asm_nlabels (g2
))
957 if (gimple_asm_nclobbers (g1
) != gimple_asm_nclobbers (g2
))
960 if (strcmp (gimple_asm_string (g1
), gimple_asm_string (g2
)) != 0)
961 return return_false_with_msg ("ASM strings are different");
963 for (unsigned i
= 0; i
< gimple_asm_ninputs (g1
); i
++)
965 tree input1
= gimple_asm_input_op (g1
, i
);
966 tree input2
= gimple_asm_input_op (g2
, i
);
968 if (!compare_tree_list_operand (input1
, input2
))
969 return return_false_with_msg ("ASM input is different");
972 for (unsigned i
= 0; i
< gimple_asm_noutputs (g1
); i
++)
974 tree output1
= gimple_asm_output_op (g1
, i
);
975 tree output2
= gimple_asm_output_op (g2
, i
);
977 if (!compare_tree_list_operand (output1
, output2
))
978 return return_false_with_msg ("ASM output is different");
981 for (unsigned i
= 0; i
< gimple_asm_nclobbers (g1
); i
++)
983 tree clobber1
= gimple_asm_clobber_op (g1
, i
);
984 tree clobber2
= gimple_asm_clobber_op (g2
, i
);
986 if (!operand_equal_p (TREE_VALUE (clobber1
), TREE_VALUE (clobber2
),
988 return return_false_with_msg ("ASM clobber is different");
994 } // ipa_icf_gimple namespace