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 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 (TYPE_RESTRICT (t1
) != TYPE_RESTRICT (t2
))
189 return return_false_with_msg ("restrict flags are different");
191 if (!types_compatible_p (t1
, t2
))
192 return return_false_with_msg ("types are not compatible");
194 if (get_alias_set (t1
) != get_alias_set (t2
))
195 return return_false_with_msg ("alias sets are different");
197 /* We call contains_polymorphic_type_p with this pointer type. */
198 if (first_argument
&& TREE_CODE (t1
) == POINTER_TYPE
)
204 if (compare_polymorphic
)
205 if (contains_polymorphic_type_p (t1
) || contains_polymorphic_type_p (t2
))
207 if (!contains_polymorphic_type_p (t1
) || !contains_polymorphic_type_p (t2
))
208 return return_false_with_msg ("one type is not polymorphic");
210 if (!types_must_be_same_for_odr (t1
, t2
))
211 return return_false_with_msg ("types are not same for ODR");
217 /* Function responsible for comparison of handled components T1 and T2.
218 If these components, from functions FUNC1 and FUNC2, are equal, true
222 func_checker::compare_operand (tree t1
, tree t2
)
224 tree base1
, base2
, x1
, x2
, y1
, y2
, z1
, z2
;
225 HOST_WIDE_INT offset1
= 0, offset2
= 0;
233 tree tt1
= TREE_TYPE (t1
);
234 tree tt2
= TREE_TYPE (t2
);
236 if (TREE_THIS_VOLATILE (t1
) != TREE_THIS_VOLATILE (t2
))
237 return return_false_with_msg ("different operand volatility");
239 if (!func_checker::compatible_types_p (tt1
, tt2
))
242 base1
= get_addr_base_and_unit_offset (t1
, &offset1
);
243 base2
= get_addr_base_and_unit_offset (t2
, &offset2
);
247 if (offset1
!= offset2
)
248 return return_false_with_msg ("base offsets are different");
254 if (TREE_CODE (t1
) != TREE_CODE (t2
))
255 return return_false ();
257 switch (TREE_CODE (t1
))
261 unsigned length1
= vec_safe_length (CONSTRUCTOR_ELTS (t1
));
262 unsigned length2
= vec_safe_length (CONSTRUCTOR_ELTS (t2
));
264 if (length1
!= length2
)
265 return return_false ();
267 for (unsigned i
= 0; i
< length1
; i
++)
268 if (!compare_operand (CONSTRUCTOR_ELT (t1
, i
)->value
,
269 CONSTRUCTOR_ELT (t2
, i
)->value
))
270 return return_false();
275 case ARRAY_RANGE_REF
:
276 x1
= TREE_OPERAND (t1
, 0);
277 x2
= TREE_OPERAND (t2
, 0);
278 y1
= TREE_OPERAND (t1
, 1);
279 y2
= TREE_OPERAND (t2
, 1);
281 if (!compare_operand (array_ref_low_bound (t1
),
282 array_ref_low_bound (t2
)))
283 return return_false_with_msg ("");
284 if (!compare_operand (array_ref_element_size (t1
),
285 array_ref_element_size (t2
)))
286 return return_false_with_msg ("");
287 if (!compare_operand (x1
, x2
))
288 return return_false_with_msg ("");
289 return compare_operand (y1
, y2
);
292 x1
= TREE_OPERAND (t1
, 0);
293 x2
= TREE_OPERAND (t2
, 0);
294 y1
= TREE_OPERAND (t1
, 1);
295 y2
= TREE_OPERAND (t2
, 1);
297 /* See if operand is an memory access (the test originate from
300 In this case the alias set of the function being replaced must
301 be subset of the alias set of the other function. At the moment
302 we seek for equivalency classes, so simply require inclussion in
305 if (!func_checker::compatible_types_p (TREE_TYPE (x1
), TREE_TYPE (x2
)))
306 return return_false ();
308 if (!compare_operand (x1
, x2
))
309 return return_false_with_msg ("");
311 if (get_alias_set (TREE_TYPE (y1
)) != get_alias_set (TREE_TYPE (y2
)))
312 return return_false_with_msg ("alias set for MEM_REF offsets are different");
315 ao_ref_init (&r1
, t1
);
316 ao_ref_init (&r2
, t2
);
317 if (ao_ref_alias_set (&r1
) != ao_ref_alias_set (&r2
)
318 || ao_ref_base_alias_set (&r1
) != ao_ref_base_alias_set (&r2
))
319 return return_false_with_msg ("ao alias sets are different");
321 /* Type of the offset on MEM_REF does not matter. */
322 return wi::to_offset (y1
) == wi::to_offset (y2
);
326 x1
= TREE_OPERAND (t1
, 0);
327 x2
= TREE_OPERAND (t2
, 0);
328 y1
= TREE_OPERAND (t1
, 1);
329 y2
= TREE_OPERAND (t2
, 1);
331 ret
= compare_operand (x1
, x2
)
332 && compare_operand (y1
, y2
);
334 return return_with_debug (ret
);
336 /* Virtual table call. */
339 x1
= TREE_OPERAND (t1
, 0);
340 x2
= TREE_OPERAND (t2
, 0);
341 y1
= TREE_OPERAND (t1
, 1);
342 y2
= TREE_OPERAND (t2
, 1);
343 z1
= TREE_OPERAND (t1
, 2);
344 z2
= TREE_OPERAND (t2
, 2);
346 ret
= compare_operand (x1
, x2
)
347 && compare_operand (y1
, y2
)
348 && compare_operand (z1
, z2
);
350 return return_with_debug (ret
);
354 x1
= TREE_OPERAND (t1
, 0);
355 x2
= TREE_OPERAND (t2
, 0);
357 ret
= compare_operand (x1
, x2
);
358 return return_with_debug (ret
);
362 ret
= compare_ssa_name (t1
, t2
);
365 return return_with_debug (ret
);
367 if (SSA_NAME_IS_DEFAULT_DEF (t1
))
369 tree b1
= SSA_NAME_VAR (t1
);
370 tree b2
= SSA_NAME_VAR (t2
);
372 if (b1
== NULL
&& b2
== NULL
)
375 if (b1
== NULL
|| b2
== NULL
|| TREE_CODE (b1
) != TREE_CODE (b2
))
376 return return_false ();
378 switch (TREE_CODE (b1
))
381 return return_with_debug (compare_variable_decl (t1
, t2
));
384 ret
= compare_decl (b1
, b2
);
385 return return_with_debug (ret
);
387 return return_false_with_msg ("Unknown TREE code reached");
395 ret
= compatible_types_p (TREE_TYPE (t1
), TREE_TYPE (t2
))
396 && wi::to_offset (t1
) == wi::to_offset (t2
);
398 return return_with_debug (ret
);
405 ret
= operand_equal_p (t1
, t2
, OEP_ONLY_CONST
);
406 return return_with_debug (ret
);
410 ret
= compare_function_decl (t1
, t2
);
411 return return_with_debug (ret
);
414 return return_with_debug (compare_variable_decl (t1
, t2
));
417 tree offset1
= DECL_FIELD_OFFSET (t1
);
418 tree offset2
= DECL_FIELD_OFFSET (t2
);
420 tree bit_offset1
= DECL_FIELD_BIT_OFFSET (t1
);
421 tree bit_offset2
= DECL_FIELD_BIT_OFFSET (t2
);
423 ret
= compare_operand (offset1
, offset2
)
424 && compare_operand (bit_offset1
, bit_offset2
);
426 return return_with_debug (ret
);
430 int *bb1
= m_label_bb_map
.get (t1
);
431 int *bb2
= m_label_bb_map
.get (t2
);
433 return return_with_debug (*bb1
== *bb2
);
440 ret
= compare_decl (t1
, t2
);
441 return return_with_debug (ret
);
444 return return_false_with_msg ("Unknown TREE code reached");
448 /* Compares two tree list operands T1 and T2 and returns true if these
449 two trees are semantically equivalent. */
452 func_checker::compare_tree_list_operand (tree t1
, tree t2
)
454 gcc_assert (TREE_CODE (t1
) == TREE_LIST
);
455 gcc_assert (TREE_CODE (t2
) == TREE_LIST
);
457 for (; t1
; t1
= TREE_CHAIN (t1
))
462 if (!compare_operand (TREE_VALUE (t1
), TREE_VALUE (t2
)))
463 return return_false ();
465 t2
= TREE_CHAIN (t2
);
469 return return_false ();
474 /* Verifies that trees T1 and T2, representing function declarations
475 are equivalent from perspective of ICF. */
478 func_checker::compare_function_decl (tree t1
, tree t2
)
485 symtab_node
*n1
= symtab_node::get (t1
);
486 symtab_node
*n2
= symtab_node::get (t2
);
488 if (m_ignored_source_nodes
!= NULL
&& m_ignored_target_nodes
!= NULL
)
490 ret
= m_ignored_source_nodes
->contains (n1
)
491 && m_ignored_target_nodes
->contains (n2
);
497 /* If function decl is WEAKREF, we compare targets. */
498 cgraph_node
*f1
= cgraph_node::get (t1
);
499 cgraph_node
*f2
= cgraph_node::get (t2
);
501 if(f1
&& f2
&& f1
->weakref
&& f2
->weakref
)
502 ret
= f1
->alias_target
== f2
->alias_target
;
507 /* Verifies that trees T1 and T2 do correspond. */
510 func_checker::compare_variable_decl (tree t1
, tree t2
)
517 if (TREE_CODE (t1
) == VAR_DECL
&& (DECL_EXTERNAL (t1
) || TREE_STATIC (t1
)))
519 symtab_node
*n1
= symtab_node::get (t1
);
520 symtab_node
*n2
= symtab_node::get (t2
);
522 if (m_ignored_source_nodes
!= NULL
&& m_ignored_target_nodes
!= NULL
)
524 ret
= m_ignored_source_nodes
->contains (n1
)
525 && m_ignored_target_nodes
->contains (n2
);
531 ret
= compare_decl (t1
, t2
);
533 return return_with_debug (ret
);
537 /* Function visits all gimple labels and creates corresponding
538 mapping between basic blocks and labels. */
541 func_checker::parse_labels (sem_bb
*bb
)
543 for (gimple_stmt_iterator gsi
= gsi_start_bb (bb
->bb
); !gsi_end_p (gsi
);
546 gimple stmt
= gsi_stmt (gsi
);
548 if (glabel
*label_stmt
= dyn_cast
<glabel
*> (stmt
))
550 tree t
= gimple_label_label (label_stmt
);
551 gcc_assert (TREE_CODE (t
) == LABEL_DECL
);
553 m_label_bb_map
.put (t
, bb
->bb
->index
);
558 /* Basic block equivalence comparison function that returns true if
559 basic blocks BB1 and BB2 (from functions FUNC1 and FUNC2) correspond.
561 In general, a collection of equivalence dictionaries is built for types
562 like SSA names, declarations (VAR_DECL, PARM_DECL, ..). This infrastructure
563 is utilized by every statement-by-statement comparison function. */
566 func_checker::compare_bb (sem_bb
*bb1
, sem_bb
*bb2
)
568 gimple_stmt_iterator gsi1
, gsi2
;
571 gsi1
= gsi_start_bb_nondebug (bb1
->bb
);
572 gsi2
= gsi_start_bb_nondebug (bb2
->bb
);
574 while (!gsi_end_p (gsi1
))
576 if (gsi_end_p (gsi2
))
577 return return_false ();
579 s1
= gsi_stmt (gsi1
);
580 s2
= gsi_stmt (gsi2
);
582 int eh1
= lookup_stmt_eh_lp_fn
583 (DECL_STRUCT_FUNCTION (m_source_func_decl
), s1
);
584 int eh2
= lookup_stmt_eh_lp_fn
585 (DECL_STRUCT_FUNCTION (m_target_func_decl
), s2
);
588 return return_false_with_msg ("EH regions are different");
590 if (gimple_code (s1
) != gimple_code (s2
))
591 return return_false_with_msg ("gimple codes are different");
593 switch (gimple_code (s1
))
596 if (!compare_gimple_call (as_a
<gcall
*> (s1
),
597 as_a
<gcall
*> (s2
)))
598 return return_different_stmts (s1
, s2
, "GIMPLE_CALL");
601 if (!compare_gimple_assign (s1
, s2
))
602 return return_different_stmts (s1
, s2
, "GIMPLE_ASSIGN");
605 if (!compare_gimple_cond (s1
, s2
))
606 return return_different_stmts (s1
, s2
, "GIMPLE_COND");
609 if (!compare_gimple_switch (as_a
<gswitch
*> (s1
),
610 as_a
<gswitch
*> (s2
)))
611 return return_different_stmts (s1
, s2
, "GIMPLE_SWITCH");
614 case GIMPLE_EH_DISPATCH
:
617 if (!compare_gimple_resx (as_a
<gresx
*> (s1
),
618 as_a
<gresx
*> (s2
)))
619 return return_different_stmts (s1
, s2
, "GIMPLE_RESX");
622 if (!compare_gimple_label (as_a
<glabel
*> (s1
),
623 as_a
<glabel
*> (s2
)))
624 return return_different_stmts (s1
, s2
, "GIMPLE_LABEL");
627 if (!compare_gimple_return (as_a
<greturn
*> (s1
),
628 as_a
<greturn
*> (s2
)))
629 return return_different_stmts (s1
, s2
, "GIMPLE_RETURN");
632 if (!compare_gimple_goto (s1
, s2
))
633 return return_different_stmts (s1
, s2
, "GIMPLE_GOTO");
636 if (!compare_gimple_asm (as_a
<gasm
*> (s1
),
638 return return_different_stmts (s1
, s2
, "GIMPLE_ASM");
644 return return_false_with_msg ("Unknown GIMPLE code reached");
647 gsi_next_nondebug (&gsi1
);
648 gsi_next_nondebug (&gsi2
);
651 if (!gsi_end_p (gsi2
))
652 return return_false ();
657 /* Verifies for given GIMPLEs S1 and S2 that
658 call statements are semantically equivalent. */
661 func_checker::compare_gimple_call (gcall
*s1
, gcall
*s2
)
666 if (gimple_call_num_args (s1
) != gimple_call_num_args (s2
))
669 t1
= gimple_call_fn (s1
);
670 t2
= gimple_call_fn (s2
);
671 if (!compare_operand (t1
, t2
))
672 return return_false ();
675 if (gimple_call_internal_p (s1
) != gimple_call_internal_p (s2
)
676 || gimple_call_ctrl_altering_p (s1
) != gimple_call_ctrl_altering_p (s2
)
677 || gimple_call_tail_p (s1
) != gimple_call_tail_p (s2
)
678 || gimple_call_return_slot_opt_p (s1
) != gimple_call_return_slot_opt_p (s2
)
679 || gimple_call_from_thunk_p (s1
) != gimple_call_from_thunk_p (s2
)
680 || gimple_call_va_arg_pack_p (s1
) != gimple_call_va_arg_pack_p (s2
)
681 || gimple_call_alloca_for_var_p (s1
) != gimple_call_alloca_for_var_p (s2
)
682 || gimple_call_with_bounds_p (s1
) != gimple_call_with_bounds_p (s2
))
685 if (gimple_call_internal_p (s1
)
686 && gimple_call_internal_fn (s1
) != gimple_call_internal_fn (s2
))
689 tree fntype1
= gimple_call_fntype (s1
);
690 tree fntype2
= gimple_call_fntype (s2
);
691 if ((fntype1
&& !fntype2
)
692 || (!fntype1
&& fntype2
)
693 || (fntype1
&& !types_compatible_p (fntype1
, fntype2
)))
694 return return_false_with_msg ("call function types are not compatible");
696 tree chain1
= gimple_call_chain (s1
);
697 tree chain2
= gimple_call_chain (s2
);
698 if ((chain1
&& !chain2
)
699 || (!chain1
&& chain2
)
700 || !compare_operand (chain1
, chain2
))
701 return return_false_with_msg ("static call chains are different");
703 /* Checking of argument. */
704 for (i
= 0; i
< gimple_call_num_args (s1
); ++i
)
706 t1
= gimple_call_arg (s1
, i
);
707 t2
= gimple_call_arg (s2
, i
);
709 if (!compare_operand (t1
, t2
))
713 /* Return value checking. */
714 t1
= gimple_get_lhs (s1
);
715 t2
= gimple_get_lhs (s2
);
717 return compare_operand (t1
, t2
);
721 /* Verifies for given GIMPLEs S1 and S2 that
722 assignment statements are semantically equivalent. */
725 func_checker::compare_gimple_assign (gimple s1
, gimple s2
)
728 tree_code code1
, code2
;
731 code1
= gimple_expr_code (s1
);
732 code2
= gimple_expr_code (s2
);
737 code1
= gimple_assign_rhs_code (s1
);
738 code2
= gimple_assign_rhs_code (s2
);
743 for (i
= 0; i
< gimple_num_ops (s1
); i
++)
745 arg1
= gimple_op (s1
, i
);
746 arg2
= gimple_op (s2
, i
);
748 if (!compare_operand (arg1
, arg2
))
756 /* Verifies for given GIMPLEs S1 and S2 that
757 condition statements are semantically equivalent. */
760 func_checker::compare_gimple_cond (gimple s1
, gimple s2
)
763 tree_code code1
, code2
;
765 code1
= gimple_expr_code (s1
);
766 code2
= gimple_expr_code (s2
);
771 t1
= gimple_cond_lhs (s1
);
772 t2
= gimple_cond_lhs (s2
);
774 if (!compare_operand (t1
, t2
))
777 t1
= gimple_cond_rhs (s1
);
778 t2
= gimple_cond_rhs (s2
);
780 return compare_operand (t1
, t2
);
783 /* Verifies that tree labels T1 and T2 correspond in FUNC1 and FUNC2. */
786 func_checker::compare_tree_ssa_label (tree t1
, tree t2
)
788 return compare_operand (t1
, t2
);
791 /* Verifies for given GIMPLE_LABEL stmts S1 and S2 that
792 label statements are semantically equivalent. */
795 func_checker::compare_gimple_label (const glabel
*g1
, const glabel
*g2
)
800 tree t1
= gimple_label_label (g1
);
801 tree t2
= gimple_label_label (g2
);
803 if (FORCED_LABEL (t1
) || FORCED_LABEL (t2
))
804 return return_false_with_msg ("FORCED_LABEL");
806 /* As the pass build BB to label mapping, no further check is needed. */
810 /* Verifies for given GIMPLE_SWITCH stmts S1 and S2 that
811 switch statements are semantically equivalent. */
814 func_checker::compare_gimple_switch (const gswitch
*g1
, const gswitch
*g2
)
816 unsigned lsize1
, lsize2
, i
;
818 lsize1
= gimple_switch_num_labels (g1
);
819 lsize2
= gimple_switch_num_labels (g2
);
821 if (lsize1
!= lsize2
)
824 tree t1
= gimple_switch_index (g1
);
825 tree t2
= gimple_switch_index (g2
);
827 if (!compare_operand (t1
, t2
))
830 for (i
= 0; i
< lsize1
; i
++)
832 tree label1
= gimple_switch_label (g1
, i
);
833 tree label2
= gimple_switch_label (g2
, i
);
835 /* Label LOW and HIGH comparison. */
836 tree low1
= CASE_LOW (label1
);
837 tree low2
= CASE_LOW (label2
);
839 if (!tree_int_cst_equal (low1
, low2
))
840 return return_false_with_msg ("case low values are different");
842 tree high1
= CASE_HIGH (label1
);
843 tree high2
= CASE_HIGH (label2
);
845 if (!tree_int_cst_equal (high1
, high2
))
846 return return_false_with_msg ("case high values are different");
848 if (TREE_CODE (label1
) == CASE_LABEL_EXPR
849 && TREE_CODE (label2
) == CASE_LABEL_EXPR
)
851 label1
= CASE_LABEL (label1
);
852 label2
= CASE_LABEL (label2
);
854 if (!compare_operand (label1
, label2
))
855 return return_false_with_msg ("switch label_exprs are different");
857 else if (!tree_int_cst_equal (label1
, label2
))
858 return return_false_with_msg ("switch labels are different");
864 /* Verifies for given GIMPLE_RETURN stmts S1 and S2 that
865 return statements are semantically equivalent. */
868 func_checker::compare_gimple_return (const greturn
*g1
, const greturn
*g2
)
872 t1
= gimple_return_retval (g1
);
873 t2
= gimple_return_retval (g2
);
875 /* Void return type. */
876 if (t1
== NULL
&& t2
== NULL
)
879 return compare_operand (t1
, t2
);
882 /* Verifies for given GIMPLEs S1 and S2 that
883 goto statements are semantically equivalent. */
886 func_checker::compare_gimple_goto (gimple g1
, gimple g2
)
890 dest1
= gimple_goto_dest (g1
);
891 dest2
= gimple_goto_dest (g2
);
893 if (TREE_CODE (dest1
) != TREE_CODE (dest2
) || TREE_CODE (dest1
) != SSA_NAME
)
896 return compare_operand (dest1
, dest2
);
899 /* Verifies for given GIMPLE_RESX stmts S1 and S2 that
900 resx statements are semantically equivalent. */
903 func_checker::compare_gimple_resx (const gresx
*g1
, const gresx
*g2
)
905 return gimple_resx_region (g1
) == gimple_resx_region (g2
);
908 /* Verifies for given GIMPLEs S1 and S2 that ASM statements are equivalent.
909 For the beginning, the pass only supports equality for
910 '__asm__ __volatile__ ("", "", "", "memory")'. */
913 func_checker::compare_gimple_asm (const gasm
*g1
, const gasm
*g2
)
915 if (gimple_asm_volatile_p (g1
) != gimple_asm_volatile_p (g2
))
918 if (gimple_asm_ninputs (g1
) != gimple_asm_ninputs (g2
))
921 if (gimple_asm_noutputs (g1
) != gimple_asm_noutputs (g2
))
924 /* We do not suppport goto ASM statement comparison. */
925 if (gimple_asm_nlabels (g1
) || gimple_asm_nlabels (g2
))
928 if (gimple_asm_nclobbers (g1
) != gimple_asm_nclobbers (g2
))
931 if (strcmp (gimple_asm_string (g1
), gimple_asm_string (g2
)) != 0)
932 return return_false_with_msg ("ASM strings are different");
934 for (unsigned i
= 0; i
< gimple_asm_ninputs (g1
); i
++)
936 tree input1
= gimple_asm_input_op (g1
, i
);
937 tree input2
= gimple_asm_input_op (g2
, i
);
939 if (!compare_tree_list_operand (input1
, input2
))
940 return return_false_with_msg ("ASM input is different");
943 for (unsigned i
= 0; i
< gimple_asm_noutputs (g1
); i
++)
945 tree output1
= gimple_asm_output_op (g1
, i
);
946 tree output2
= gimple_asm_output_op (g2
, i
);
948 if (!compare_tree_list_operand (output1
, output2
))
949 return return_false_with_msg ("ASM output is different");
952 for (unsigned i
= 0; i
< gimple_asm_nclobbers (g1
); i
++)
954 tree clobber1
= gimple_asm_clobber_op (g1
, i
);
955 tree clobber2
= gimple_asm_clobber_op (g2
, i
);
957 if (!operand_equal_p (TREE_VALUE (clobber1
), TREE_VALUE (clobber2
),
959 return return_false_with_msg ("ASM clobber is different");
965 } // ipa_icf_gimple namespace