1 /* Interprocedural Identical Code Folding pass
2 Copyright (C) 2014-2020 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"
29 #include "tree-pass.h"
32 #include "data-streamer.h"
33 #include "gimple-pretty-print.h"
34 #include "fold-const.h"
35 #include "gimple-iterator.h"
36 #include "ipa-utils.h"
41 #include "gimple-walk.h"
43 #include "tree-ssa-alias-compare.h"
44 #include "ipa-icf-gimple.h"
46 namespace ipa_icf_gimple
{
48 /* Initialize internal structures for a given SOURCE_FUNC_DECL and
49 TARGET_FUNC_DECL. Strict polymorphic comparison is processed if
50 an option COMPARE_POLYMORPHIC is true. For special cases, one can
51 set IGNORE_LABELS to skip label comparison.
52 Similarly, IGNORE_SOURCE_DECLS and IGNORE_TARGET_DECLS are sets
53 of declarations that can be skipped. */
55 func_checker::func_checker (tree source_func_decl
, tree target_func_decl
,
56 bool ignore_labels
, bool tbaa
,
57 hash_set
<symtab_node
*> *ignored_source_nodes
,
58 hash_set
<symtab_node
*> *ignored_target_nodes
)
59 : m_source_func_decl (source_func_decl
), m_target_func_decl (target_func_decl
),
60 m_ignored_source_nodes (ignored_source_nodes
),
61 m_ignored_target_nodes (ignored_target_nodes
),
62 m_ignore_labels (ignore_labels
), m_tbaa (tbaa
)
64 function
*source_func
= DECL_STRUCT_FUNCTION (source_func_decl
);
65 function
*target_func
= DECL_STRUCT_FUNCTION (target_func_decl
);
67 unsigned ssa_source
= SSANAMES (source_func
)->length ();
68 unsigned ssa_target
= SSANAMES (target_func
)->length ();
70 m_source_ssa_names
.create (ssa_source
);
71 m_target_ssa_names
.create (ssa_target
);
73 for (unsigned i
= 0; i
< ssa_source
; i
++)
74 m_source_ssa_names
.safe_push (-1);
76 for (unsigned i
= 0; i
< ssa_target
; i
++)
77 m_target_ssa_names
.safe_push (-1);
80 /* Memory release routine. */
82 func_checker::~func_checker ()
84 m_source_ssa_names
.release();
85 m_target_ssa_names
.release();
88 /* Verifies that trees T1 and T2 are equivalent from perspective of ICF. */
91 func_checker::compare_ssa_name (const_tree t1
, const_tree t2
)
93 gcc_assert (TREE_CODE (t1
) == SSA_NAME
);
94 gcc_assert (TREE_CODE (t2
) == SSA_NAME
);
96 unsigned i1
= SSA_NAME_VERSION (t1
);
97 unsigned i2
= SSA_NAME_VERSION (t2
);
99 if (m_source_ssa_names
[i1
] == -1)
100 m_source_ssa_names
[i1
] = i2
;
101 else if (m_source_ssa_names
[i1
] != (int) i2
)
104 if(m_target_ssa_names
[i2
] == -1)
105 m_target_ssa_names
[i2
] = i1
;
106 else if (m_target_ssa_names
[i2
] != (int) i1
)
109 if (SSA_NAME_IS_DEFAULT_DEF (t1
))
111 tree b1
= SSA_NAME_VAR (t1
);
112 tree b2
= SSA_NAME_VAR (t2
);
114 return compare_operand (b1
, b2
, OP_NORMAL
);
120 /* Verification function for edges E1 and E2. */
123 func_checker::compare_edge (edge e1
, edge e2
)
125 if (e1
->flags
!= e2
->flags
)
130 edge
&slot
= m_edge_map
.get_or_insert (e1
, &existed_p
);
132 return return_with_debug (slot
== e2
);
136 /* TODO: filter edge probabilities for profile feedback match. */
141 /* Verification function for declaration trees T1 and T2 that
142 come from functions FUNC1 and FUNC2. */
145 func_checker::compare_decl (const_tree t1
, const_tree t2
)
147 if (!auto_var_in_fn_p (t1
, m_source_func_decl
)
148 || !auto_var_in_fn_p (t2
, m_target_func_decl
))
149 return return_with_debug (t1
== t2
);
151 tree_code t
= TREE_CODE (t1
);
152 if ((t
== VAR_DECL
|| t
== PARM_DECL
|| t
== RESULT_DECL
)
153 && DECL_BY_REFERENCE (t1
) != DECL_BY_REFERENCE (t2
))
154 return return_false_with_msg ("DECL_BY_REFERENCE flags are different");
156 if (!compatible_types_p (TREE_TYPE (t1
), TREE_TYPE (t2
)))
157 return return_false ();
160 const_tree
&slot
= m_decl_map
.get_or_insert (t1
, &existed_p
);
162 return return_with_debug (slot
== t2
);
169 /* Return true if T1 and T2 are same for purposes of ipa-polymorphic-call
170 analysis. COMPARE_PTR indicates if types of pointers needs to be
174 func_checker::compatible_polymorphic_types_p (tree t1
, tree t2
,
177 gcc_assert (TREE_CODE (t1
) != FUNCTION_TYPE
&& TREE_CODE (t1
) != METHOD_TYPE
);
179 /* Pointer types generally give no information. */
180 if (POINTER_TYPE_P (t1
))
184 return func_checker::compatible_polymorphic_types_p (TREE_TYPE (t1
),
189 /* If types contain a polymorphic types, match them. */
190 bool c1
= contains_polymorphic_type_p (t1
);
191 bool c2
= contains_polymorphic_type_p (t2
);
195 return return_false_with_msg ("one type is not polymorphic");
196 if (!types_must_be_same_for_odr (t1
, t2
))
197 return return_false_with_msg ("types are not same for ODR");
201 /* Return true if types are compatible from perspective of ICF. */
203 func_checker::compatible_types_p (tree t1
, tree t2
)
205 if (TREE_CODE (t1
) != TREE_CODE (t2
))
206 return return_false_with_msg ("different tree types");
208 if (TYPE_RESTRICT (t1
) != TYPE_RESTRICT (t2
))
209 return return_false_with_msg ("restrict flags are different");
211 if (!types_compatible_p (t1
, t2
))
212 return return_false_with_msg ("types are not compatible");
217 /* Add hash of ARG to HSTATE. FLAGS have same meaning
218 as for operand_equal_p. Works only if operand acces type is OP_NORMAL. */
221 func_checker::hash_operand (const_tree arg
, inchash::hash
&hstate
,
224 if (arg
== NULL_TREE
)
226 hstate
.merge_hash (0);
230 switch (TREE_CODE (arg
))
241 inchash::add_expr (DECL_FIELD_OFFSET (arg
), hstate
, flags
);
242 inchash::add_expr (DECL_FIELD_BIT_OFFSET (arg
), hstate
, flags
);
248 return operand_compare::hash_operand (arg
, hstate
, flags
);
251 /* Add hash of ARG accesses according to ACCESS to HSTATE.
252 FLAGS have same meaning as for operand_equal_p. */
255 func_checker::hash_operand (const_tree arg
, inchash::hash
&hstate
,
256 unsigned int flags
, operand_access_type access
)
258 if (access
== OP_MEMORY
)
261 ao_ref_init (&ref
, const_cast <tree
> (arg
));
262 return hash_ao_ref (&ref
, lto_streaming_expected_p (), m_tbaa
, hstate
);
265 return hash_operand (arg
, hstate
, flags
);
269 func_checker::operand_equal_p (const_tree t1
, const_tree t2
,
273 if (verify_hash_value (t1
, t2
, flags
, &r
))
281 if (TREE_CODE (t1
) != TREE_CODE (t2
))
282 return return_false ();
284 switch (TREE_CODE (t1
))
287 /* All function decls are in the symbol table and known to match
288 before we start comparing bodies. */
291 return return_with_debug (compare_variable_decl (t1
, t2
));
294 int *bb1
= m_label_bb_map
.get (t1
);
295 int *bb2
= m_label_bb_map
.get (t2
);
296 /* Labels can point to another function (non-local GOTOs). */
297 return return_with_debug (bb1
!= NULL
&& bb2
!= NULL
&& *bb1
== *bb2
);
303 return compare_decl (t1
, t2
);
305 return compare_ssa_name (t1
, t2
);
310 return operand_compare::operand_equal_p (t1
, t2
, flags
);
313 /* Function responsible for comparison of various operands T1 and T2
314 which are accessed as ACCESS.
315 If these components, from functions FUNC1 and FUNC2, are equal, true
319 func_checker::compare_operand (tree t1
, tree t2
, operand_access_type access
)
325 if (access
== OP_MEMORY
)
328 ao_ref_init (&ref1
, const_cast <tree
> (t1
));
329 ao_ref_init (&ref2
, const_cast <tree
> (t2
));
330 int flags
= compare_ao_refs (&ref1
, &ref2
,
331 lto_streaming_expected_p (), m_tbaa
);
335 if (flags
& SEMANTICS
)
336 return return_false_with_msg
337 ("compare_ao_refs failed (semantic difference)");
338 if (flags
& BASE_ALIAS_SET
)
339 return return_false_with_msg
340 ("compare_ao_refs failed (base alias set difference)");
341 if (flags
& REF_ALIAS_SET
)
342 return return_false_with_msg
343 ("compare_ao_refs failed (ref alias set difference)");
344 if (flags
& ACCESS_PATH
)
345 return return_false_with_msg
346 ("compare_ao_refs failed (access path difference)");
347 if (flags
& DEPENDENCE_CLIQUE
)
348 return return_false_with_msg
349 ("compare_ao_refs failed (dependence clique difference)");
354 if (operand_equal_p (t1
, t2
, OEP_MATCH_SIDE_EFFECTS
))
356 return return_false_with_msg
357 ("operand_equal_p failed");
362 func_checker::compare_asm_inputs_outputs (tree t1
, tree t2
,
363 operand_access_type_map
*map
)
365 gcc_assert (TREE_CODE (t1
) == TREE_LIST
);
366 gcc_assert (TREE_CODE (t2
) == TREE_LIST
);
368 for (; t1
; t1
= TREE_CHAIN (t1
))
373 if (!compare_operand (TREE_VALUE (t1
), TREE_VALUE (t2
),
374 get_operand_access_type (map
, t1
)))
375 return return_false ();
377 tree p1
= TREE_PURPOSE (t1
);
378 tree p2
= TREE_PURPOSE (t2
);
380 gcc_assert (TREE_CODE (p1
) == TREE_LIST
);
381 gcc_assert (TREE_CODE (p2
) == TREE_LIST
);
383 if (strcmp (TREE_STRING_POINTER (TREE_VALUE (p1
)),
384 TREE_STRING_POINTER (TREE_VALUE (p2
))) != 0)
385 return return_false ();
387 t2
= TREE_CHAIN (t2
);
391 return return_false ();
396 /* Verifies that trees T1 and T2 do correspond. */
399 func_checker::compare_variable_decl (const_tree t1
, const_tree t2
)
406 if (DECL_ALIGN (t1
) != DECL_ALIGN (t2
))
407 return return_false_with_msg ("alignments are different");
409 if (DECL_HARD_REGISTER (t1
) != DECL_HARD_REGISTER (t2
))
410 return return_false_with_msg ("DECL_HARD_REGISTER are different");
412 if (DECL_HARD_REGISTER (t1
)
413 && DECL_ASSEMBLER_NAME_RAW (t1
) != DECL_ASSEMBLER_NAME_RAW (t2
))
414 return return_false_with_msg ("HARD REGISTERS are different");
416 /* Symbol table variables are known to match before we start comparing
418 if (decl_in_symtab_p (t1
))
419 return decl_in_symtab_p (t2
);
420 ret
= compare_decl (t1
, t2
);
422 return return_with_debug (ret
);
425 /* Compare loop information for basic blocks BB1 and BB2. */
428 func_checker::compare_loops (basic_block bb1
, basic_block bb2
)
430 if ((bb1
->loop_father
== NULL
) != (bb2
->loop_father
== NULL
))
431 return return_false ();
433 class loop
*l1
= bb1
->loop_father
;
434 class loop
*l2
= bb2
->loop_father
;
438 if ((bb1
== l1
->header
) != (bb2
== l2
->header
))
439 return return_false_with_msg ("header");
440 if ((bb1
== l1
->latch
) != (bb2
== l2
->latch
))
441 return return_false_with_msg ("latch");
442 if (l1
->simdlen
!= l2
->simdlen
)
443 return return_false_with_msg ("simdlen");
444 if (l1
->safelen
!= l2
->safelen
)
445 return return_false_with_msg ("safelen");
446 if (l1
->can_be_parallel
!= l2
->can_be_parallel
)
447 return return_false_with_msg ("can_be_parallel");
448 if (l1
->dont_vectorize
!= l2
->dont_vectorize
)
449 return return_false_with_msg ("dont_vectorize");
450 if (l1
->force_vectorize
!= l2
->force_vectorize
)
451 return return_false_with_msg ("force_vectorize");
452 if (l1
->finite_p
!= l2
->finite_p
)
453 return return_false_with_msg ("finite_p");
454 if (l1
->unroll
!= l2
->unroll
)
455 return return_false_with_msg ("unroll");
456 if (!compare_variable_decl (l1
->simduid
, l2
->simduid
))
457 return return_false_with_msg ("simduid");
462 /* Function visits all gimple labels and creates corresponding
463 mapping between basic blocks and labels. */
466 func_checker::parse_labels (sem_bb
*bb
)
468 for (gimple_stmt_iterator gsi
= gsi_start_bb (bb
->bb
); !gsi_end_p (gsi
);
471 gimple
*stmt
= gsi_stmt (gsi
);
473 if (glabel
*label_stmt
= dyn_cast
<glabel
*> (stmt
))
475 const_tree t
= gimple_label_label (label_stmt
);
476 gcc_assert (TREE_CODE (t
) == LABEL_DECL
);
478 m_label_bb_map
.put (t
, bb
->bb
->index
);
483 /* Basic block equivalence comparison function that returns true if
484 basic blocks BB1 and BB2 (from functions FUNC1 and FUNC2) correspond.
486 In general, a collection of equivalence dictionaries is built for types
487 like SSA names, declarations (VAR_DECL, PARM_DECL, ..). This infrastructure
488 is utilized by every statement-by-statement comparison function. */
491 func_checker::compare_bb (sem_bb
*bb1
, sem_bb
*bb2
)
493 gimple_stmt_iterator gsi1
, gsi2
;
496 gsi1
= gsi_start_nondebug_bb (bb1
->bb
);
497 gsi2
= gsi_start_nondebug_bb (bb2
->bb
);
499 while (!gsi_end_p (gsi1
))
501 if (gsi_end_p (gsi2
))
502 return return_false ();
504 s1
= gsi_stmt (gsi1
);
505 s2
= gsi_stmt (gsi2
);
507 int eh1
= lookup_stmt_eh_lp_fn
508 (DECL_STRUCT_FUNCTION (m_source_func_decl
), s1
);
509 int eh2
= lookup_stmt_eh_lp_fn
510 (DECL_STRUCT_FUNCTION (m_target_func_decl
), s2
);
513 return return_false_with_msg ("EH regions are different");
515 if (gimple_code (s1
) != gimple_code (s2
))
516 return return_false_with_msg ("gimple codes are different");
518 switch (gimple_code (s1
))
521 if (!compare_gimple_call (as_a
<gcall
*> (s1
),
522 as_a
<gcall
*> (s2
)))
523 return return_different_stmts (s1
, s2
, "GIMPLE_CALL");
526 if (!compare_gimple_assign (s1
, s2
))
527 return return_different_stmts (s1
, s2
, "GIMPLE_ASSIGN");
530 if (!compare_gimple_cond (s1
, s2
))
531 return return_different_stmts (s1
, s2
, "GIMPLE_COND");
534 if (!compare_gimple_switch (as_a
<gswitch
*> (s1
),
535 as_a
<gswitch
*> (s2
)))
536 return return_different_stmts (s1
, s2
, "GIMPLE_SWITCH");
540 case GIMPLE_EH_DISPATCH
:
541 if (gimple_eh_dispatch_region (as_a
<geh_dispatch
*> (s1
))
542 != gimple_eh_dispatch_region (as_a
<geh_dispatch
*> (s2
)))
543 return return_different_stmts (s1
, s2
, "GIMPLE_EH_DISPATCH");
546 if (!compare_gimple_resx (as_a
<gresx
*> (s1
),
547 as_a
<gresx
*> (s2
)))
548 return return_different_stmts (s1
, s2
, "GIMPLE_RESX");
551 if (!compare_gimple_label (as_a
<glabel
*> (s1
),
552 as_a
<glabel
*> (s2
)))
553 return return_different_stmts (s1
, s2
, "GIMPLE_LABEL");
556 if (!compare_gimple_return (as_a
<greturn
*> (s1
),
557 as_a
<greturn
*> (s2
)))
558 return return_different_stmts (s1
, s2
, "GIMPLE_RETURN");
561 if (!compare_gimple_goto (s1
, s2
))
562 return return_different_stmts (s1
, s2
, "GIMPLE_GOTO");
565 if (!compare_gimple_asm (as_a
<gasm
*> (s1
),
567 return return_different_stmts (s1
, s2
, "GIMPLE_ASM");
573 return return_false_with_msg ("Unknown GIMPLE code reached");
576 gsi_next_nondebug (&gsi1
);
577 gsi_next_nondebug (&gsi2
);
580 if (!gsi_end_p (gsi2
))
581 return return_false ();
583 if (!compare_loops (bb1
->bb
, bb2
->bb
))
584 return return_false ();
589 /* Verifies for given GIMPLEs S1 and S2 that
590 call statements are semantically equivalent. */
593 func_checker::compare_gimple_call (gcall
*s1
, gcall
*s2
)
598 if (gimple_call_num_args (s1
) != gimple_call_num_args (s2
))
601 operand_access_type_map
map (5);
602 classify_operands (s1
, &map
);
604 t1
= gimple_call_fn (s1
);
605 t2
= gimple_call_fn (s2
);
606 if (!compare_operand (t1
, t2
, get_operand_access_type (&map
, t1
)))
607 return return_false ();
610 if (gimple_call_internal_p (s1
) != gimple_call_internal_p (s2
)
611 || gimple_call_ctrl_altering_p (s1
) != gimple_call_ctrl_altering_p (s2
)
612 || gimple_call_tail_p (s1
) != gimple_call_tail_p (s2
)
613 || gimple_call_return_slot_opt_p (s1
) != gimple_call_return_slot_opt_p (s2
)
614 || gimple_call_from_thunk_p (s1
) != gimple_call_from_thunk_p (s2
)
615 || gimple_call_from_new_or_delete (s1
) != gimple_call_from_new_or_delete (s2
)
616 || gimple_call_va_arg_pack_p (s1
) != gimple_call_va_arg_pack_p (s2
)
617 || gimple_call_alloca_for_var_p (s1
) != gimple_call_alloca_for_var_p (s2
))
620 if (gimple_call_internal_p (s1
)
621 && gimple_call_internal_fn (s1
) != gimple_call_internal_fn (s2
))
624 tree fntype1
= gimple_call_fntype (s1
);
625 tree fntype2
= gimple_call_fntype (s2
);
627 /* For direct calls we verify that types are comopatible so if we matced
628 callees, callers must match, too. For indirect calls however verify
630 if (!gimple_call_fndecl (s1
))
632 if ((fntype1
&& !fntype2
)
633 || (!fntype1
&& fntype2
)
634 || (fntype1
&& !types_compatible_p (fntype1
, fntype2
)))
635 return return_false_with_msg ("call function types are not compatible");
638 if (fntype1
&& fntype2
&& comp_type_attributes (fntype1
, fntype2
) != 1)
639 return return_false_with_msg ("different fntype attributes");
641 tree chain1
= gimple_call_chain (s1
);
642 tree chain2
= gimple_call_chain (s2
);
643 if ((chain1
&& !chain2
)
644 || (!chain1
&& chain2
)
645 || !compare_operand (chain1
, chain2
,
646 get_operand_access_type (&map
, chain1
)))
647 return return_false_with_msg ("static call chains are different");
649 /* Checking of argument. */
650 for (i
= 0; i
< gimple_call_num_args (s1
); ++i
)
652 t1
= gimple_call_arg (s1
, i
);
653 t2
= gimple_call_arg (s2
, i
);
655 if (!compare_operand (t1
, t2
, get_operand_access_type (&map
, t1
)))
656 return return_false_with_msg ("GIMPLE call operands are different");
659 /* Return value checking. */
660 t1
= gimple_get_lhs (s1
);
661 t2
= gimple_get_lhs (s2
);
663 return compare_operand (t1
, t2
, get_operand_access_type (&map
, t1
));
667 /* Verifies for given GIMPLEs S1 and S2 that
668 assignment statements are semantically equivalent. */
671 func_checker::compare_gimple_assign (gimple
*s1
, gimple
*s2
)
674 tree_code code1
, code2
;
677 code1
= gimple_assign_rhs_code (s1
);
678 code2
= gimple_assign_rhs_code (s2
);
683 operand_access_type_map
map (5);
684 classify_operands (s1
, &map
);
686 for (i
= 0; i
< gimple_num_ops (s1
); i
++)
688 arg1
= gimple_op (s1
, i
);
689 arg2
= gimple_op (s2
, i
);
691 /* Compare types for LHS. */
692 if (i
== 0 && !gimple_store_p (s1
))
694 if (!compatible_types_p (TREE_TYPE (arg1
), TREE_TYPE (arg2
)))
695 return return_false_with_msg ("GIMPLE LHS type mismatch");
698 if (!compare_operand (arg1
, arg2
, get_operand_access_type (&map
, arg1
)))
699 return return_false_with_msg ("GIMPLE assignment operands "
707 /* Verifies for given GIMPLEs S1 and S2 that
708 condition statements are semantically equivalent. */
711 func_checker::compare_gimple_cond (gimple
*s1
, gimple
*s2
)
714 tree_code code1
, code2
;
716 code1
= gimple_cond_code (s1
);
717 code2
= gimple_cond_code (s2
);
722 t1
= gimple_cond_lhs (s1
);
723 t2
= gimple_cond_lhs (s2
);
725 if (!compare_operand (t1
, t2
, OP_NORMAL
))
728 t1
= gimple_cond_rhs (s1
);
729 t2
= gimple_cond_rhs (s2
);
731 return compare_operand (t1
, t2
, OP_NORMAL
);
734 /* Verifies for given GIMPLE_LABEL stmts S1 and S2 that
735 label statements are semantically equivalent. */
738 func_checker::compare_gimple_label (const glabel
*g1
, const glabel
*g2
)
743 tree t1
= gimple_label_label (g1
);
744 tree t2
= gimple_label_label (g2
);
746 if (FORCED_LABEL (t1
) || FORCED_LABEL (t2
))
747 return return_false_with_msg ("FORCED_LABEL");
749 /* As the pass build BB to label mapping, no further check is needed. */
753 /* Verifies for given GIMPLE_SWITCH stmts S1 and S2 that
754 switch statements are semantically equivalent. */
757 func_checker::compare_gimple_switch (const gswitch
*g1
, const gswitch
*g2
)
759 unsigned lsize1
, lsize2
, i
;
761 lsize1
= gimple_switch_num_labels (g1
);
762 lsize2
= gimple_switch_num_labels (g2
);
764 if (lsize1
!= lsize2
)
767 tree t1
= gimple_switch_index (g1
);
768 tree t2
= gimple_switch_index (g2
);
770 if (!compare_operand (t1
, t2
, OP_NORMAL
))
773 for (i
= 0; i
< lsize1
; i
++)
775 tree label1
= gimple_switch_label (g1
, i
);
776 tree label2
= gimple_switch_label (g2
, i
);
778 /* Label LOW and HIGH comparison. */
779 tree low1
= CASE_LOW (label1
);
780 tree low2
= CASE_LOW (label2
);
782 if (!tree_int_cst_equal (low1
, low2
))
783 return return_false_with_msg ("case low values are different");
785 tree high1
= CASE_HIGH (label1
);
786 tree high2
= CASE_HIGH (label2
);
788 if (!tree_int_cst_equal (high1
, high2
))
789 return return_false_with_msg ("case high values are different");
791 if (TREE_CODE (label1
) == CASE_LABEL_EXPR
792 && TREE_CODE (label2
) == CASE_LABEL_EXPR
)
794 label1
= CASE_LABEL (label1
);
795 label2
= CASE_LABEL (label2
);
797 if (!compare_operand (label1
, label2
, OP_NORMAL
))
798 return return_false_with_msg ("switch label_exprs are different");
800 else if (!tree_int_cst_equal (label1
, label2
))
801 return return_false_with_msg ("switch labels are different");
807 /* Verifies for given GIMPLE_RETURN stmts S1 and S2 that
808 return statements are semantically equivalent. */
811 func_checker::compare_gimple_return (const greturn
*g1
, const greturn
*g2
)
815 t1
= gimple_return_retval (g1
);
816 t2
= gimple_return_retval (g2
);
818 /* Void return type. */
819 if (t1
== NULL
&& t2
== NULL
)
823 operand_access_type_map
map (3);
824 return compare_operand (t1
, t2
, get_operand_access_type (&map
, t1
));
828 /* Verifies for given GIMPLEs S1 and S2 that
829 goto statements are semantically equivalent. */
832 func_checker::compare_gimple_goto (gimple
*g1
, gimple
*g2
)
836 dest1
= gimple_goto_dest (g1
);
837 dest2
= gimple_goto_dest (g2
);
839 if (TREE_CODE (dest1
) != TREE_CODE (dest2
) || TREE_CODE (dest1
) != SSA_NAME
)
842 return compare_operand (dest1
, dest2
, OP_NORMAL
);
845 /* Verifies for given GIMPLE_RESX stmts S1 and S2 that
846 resx statements are semantically equivalent. */
849 func_checker::compare_gimple_resx (const gresx
*g1
, const gresx
*g2
)
851 return gimple_resx_region (g1
) == gimple_resx_region (g2
);
854 /* Verifies for given GIMPLEs S1 and S2 that ASM statements are equivalent.
855 For the beginning, the pass only supports equality for
856 '__asm__ __volatile__ ("", "", "", "memory")'. */
859 func_checker::compare_gimple_asm (const gasm
*g1
, const gasm
*g2
)
861 if (gimple_asm_volatile_p (g1
) != gimple_asm_volatile_p (g2
))
864 if (gimple_asm_input_p (g1
) != gimple_asm_input_p (g2
))
867 if (gimple_asm_inline_p (g1
) != gimple_asm_inline_p (g2
))
870 if (gimple_asm_ninputs (g1
) != gimple_asm_ninputs (g2
))
873 if (gimple_asm_noutputs (g1
) != gimple_asm_noutputs (g2
))
876 /* We do not suppport goto ASM statement comparison. */
877 if (gimple_asm_nlabels (g1
) || gimple_asm_nlabels (g2
))
880 if (gimple_asm_nclobbers (g1
) != gimple_asm_nclobbers (g2
))
883 if (strcmp (gimple_asm_string (g1
), gimple_asm_string (g2
)) != 0)
884 return return_false_with_msg ("ASM strings are different");
886 operand_access_type_map
map (5);
887 classify_operands (g1
, &map
);
889 for (unsigned i
= 0; i
< gimple_asm_ninputs (g1
); i
++)
891 tree input1
= gimple_asm_input_op (g1
, i
);
892 tree input2
= gimple_asm_input_op (g2
, i
);
894 if (!compare_asm_inputs_outputs (input1
, input2
, &map
))
895 return return_false_with_msg ("ASM input is different");
898 for (unsigned i
= 0; i
< gimple_asm_noutputs (g1
); i
++)
900 tree output1
= gimple_asm_output_op (g1
, i
);
901 tree output2
= gimple_asm_output_op (g2
, i
);
903 if (!compare_asm_inputs_outputs (output1
, output2
, &map
))
904 return return_false_with_msg ("ASM output is different");
907 for (unsigned i
= 0; i
< gimple_asm_nclobbers (g1
); i
++)
909 tree clobber1
= gimple_asm_clobber_op (g1
, i
);
910 tree clobber2
= gimple_asm_clobber_op (g2
, i
);
912 if (!operand_equal_p (TREE_VALUE (clobber1
), TREE_VALUE (clobber2
),
914 return return_false_with_msg ("ASM clobber is different");
920 /* Helper for func_checker::classify_operands. Record that T is a load. */
923 visit_load_store (gimple
*, tree
, tree t
, void *data
)
925 func_checker::operand_access_type_map
*map
=
926 (func_checker::operand_access_type_map
*) data
;
931 /* Compute hash map determining access types of operands. */
934 func_checker::classify_operands (const gimple
*stmt
,
935 operand_access_type_map
*map
)
937 walk_stmt_load_store_ops (const_cast <gimple
*> (stmt
),
938 (void *)map
, visit_load_store
, visit_load_store
);
941 /* Return access type of a given operand. */
943 func_checker::operand_access_type
944 func_checker::get_operand_access_type (operand_access_type_map
*map
, tree t
)
946 if (map
->contains (t
))
951 } // ipa_icf_gimple namespace