1 /* Interprocedural Identical Code Folding pass
2 Copyright (C) 2014 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"
51 #include "data-streamer.h"
52 #include "ipa-utils.h"
54 #include "tree-ssanames.h"
57 #include "ipa-icf-gimple.h"
60 namespace ipa_icf_gimple
{
62 /* Initialize internal structures for a given SOURCE_FUNC_DECL and
63 TARGET_FUNC_DECL. Strict polymorphic comparison is processed if
64 an option COMPARE_POLYMORPHIC is true. For special cases, one can
65 set IGNORE_LABELS to skip label comparison.
66 Similarly, IGNORE_SOURCE_DECLS and IGNORE_TARGET_DECLS are sets
67 of declarations that can be skipped. */
69 func_checker::func_checker (tree source_func_decl
, tree target_func_decl
,
70 bool compare_polymorphic
,
72 hash_set
<symtab_node
*> *ignored_source_nodes
,
73 hash_set
<symtab_node
*> *ignored_target_nodes
)
74 : m_source_func_decl (source_func_decl
), m_target_func_decl (target_func_decl
),
75 m_ignored_source_nodes (ignored_source_nodes
),
76 m_ignored_target_nodes (ignored_target_nodes
),
77 m_compare_polymorphic (compare_polymorphic
),
78 m_ignore_labels (ignore_labels
)
80 function
*source_func
= DECL_STRUCT_FUNCTION (source_func_decl
);
81 function
*target_func
= DECL_STRUCT_FUNCTION (target_func_decl
);
83 unsigned ssa_source
= SSANAMES (source_func
)->length ();
84 unsigned ssa_target
= SSANAMES (target_func
)->length ();
86 m_source_ssa_names
.create (ssa_source
);
87 m_target_ssa_names
.create (ssa_target
);
89 for (unsigned i
= 0; i
< ssa_source
; i
++)
90 m_source_ssa_names
.safe_push (-1);
92 for (unsigned i
= 0; i
< ssa_target
; i
++)
93 m_target_ssa_names
.safe_push (-1);
96 /* Memory release routine. */
98 func_checker::~func_checker ()
100 m_source_ssa_names
.release();
101 m_target_ssa_names
.release();
104 /* Verifies that trees T1 and T2 are equivalent from perspective of ICF. */
107 func_checker::compare_ssa_name (tree t1
, tree t2
)
109 unsigned i1
= SSA_NAME_VERSION (t1
);
110 unsigned i2
= SSA_NAME_VERSION (t2
);
112 if (m_source_ssa_names
[i1
] == -1)
113 m_source_ssa_names
[i1
] = i2
;
114 else if (m_source_ssa_names
[i1
] != (int) i2
)
117 if(m_target_ssa_names
[i2
] == -1)
118 m_target_ssa_names
[i2
] = i1
;
119 else if (m_target_ssa_names
[i2
] != (int) i1
)
125 /* Verification function for edges E1 and E2. */
128 func_checker::compare_edge (edge e1
, edge e2
)
130 if (e1
->flags
!= e2
->flags
)
135 edge
&slot
= m_edge_map
.get_or_insert (e1
, &existed_p
);
137 return return_with_debug (slot
== e2
);
141 /* TODO: filter edge probabilities for profile feedback match. */
146 /* Verification function for declaration trees T1 and T2 that
147 come from functions FUNC1 and FUNC2. */
150 func_checker::compare_decl (tree t1
, tree t2
)
152 if (!auto_var_in_fn_p (t1
, m_source_func_decl
)
153 || !auto_var_in_fn_p (t2
, m_target_func_decl
))
154 return return_with_debug (t1
== t2
);
156 tree_code t
= TREE_CODE (t1
);
157 if ((t
== VAR_DECL
|| t
== PARM_DECL
|| t
== RESULT_DECL
)
158 && DECL_BY_REFERENCE (t1
) != DECL_BY_REFERENCE (t2
))
159 return return_false_with_msg ("DECL_BY_REFERENCE flags are different");
161 if (!compatible_types_p (TREE_TYPE (t1
), TREE_TYPE (t2
),
162 m_compare_polymorphic
))
163 return return_false ();
167 tree
&slot
= m_decl_map
.get_or_insert (t1
, &existed_p
);
169 return return_with_debug (slot
== t2
);
176 /* Return true if types are compatible from perspective of ICF. */
177 bool func_checker::compatible_types_p (tree t1
, tree t2
,
178 bool compare_polymorphic
,
181 if (TREE_CODE (t1
) != TREE_CODE (t2
))
182 return return_false_with_msg ("different tree types");
184 if (!types_compatible_p (t1
, t2
))
185 return return_false_with_msg ("types are not compatible");
187 if (get_alias_set (t1
) != get_alias_set (t2
))
188 return return_false_with_msg ("alias sets are different");
190 /* We call contains_polymorphic_type_p with this pointer type. */
191 if (first_argument
&& TREE_CODE (t1
) == POINTER_TYPE
)
197 if (compare_polymorphic
)
198 if (contains_polymorphic_type_p (t1
) || contains_polymorphic_type_p (t2
))
200 if (!contains_polymorphic_type_p (t1
) || !contains_polymorphic_type_p (t2
))
201 return return_false_with_msg ("one type is not polymorphic");
203 if (!types_must_be_same_for_odr (t1
, t2
))
204 return return_false_with_msg ("types are not same for ODR");
210 /* Function responsible for comparison of handled components T1 and T2.
211 If these components, from functions FUNC1 and FUNC2, are equal, true
215 func_checker::compare_operand (tree t1
, tree t2
)
217 tree base1
, base2
, x1
, x2
, y1
, y2
, z1
, z2
;
218 HOST_WIDE_INT offset1
= 0, offset2
= 0;
226 tree tt1
= TREE_TYPE (t1
);
227 tree tt2
= TREE_TYPE (t2
);
229 if (!func_checker::compatible_types_p (tt1
, tt2
))
232 base1
= get_addr_base_and_unit_offset (t1
, &offset1
);
233 base2
= get_addr_base_and_unit_offset (t2
, &offset2
);
237 if (offset1
!= offset2
)
238 return return_false_with_msg ("base offsets are different");
244 if (TREE_CODE (t1
) != TREE_CODE (t2
))
245 return return_false ();
247 switch (TREE_CODE (t1
))
251 unsigned length1
= vec_safe_length (CONSTRUCTOR_ELTS (t1
));
252 unsigned length2
= vec_safe_length (CONSTRUCTOR_ELTS (t2
));
254 if (length1
!= length2
)
255 return return_false ();
257 for (unsigned i
= 0; i
< length1
; i
++)
258 if (!compare_operand (CONSTRUCTOR_ELT (t1
, i
)->value
,
259 CONSTRUCTOR_ELT (t2
, i
)->value
))
260 return return_false();
265 case ARRAY_RANGE_REF
:
266 x1
= TREE_OPERAND (t1
, 0);
267 x2
= TREE_OPERAND (t2
, 0);
268 y1
= TREE_OPERAND (t1
, 1);
269 y2
= TREE_OPERAND (t2
, 1);
271 if (!compare_operand (array_ref_low_bound (t1
),
272 array_ref_low_bound (t2
)))
273 return return_false_with_msg ("");
274 if (!compare_operand (array_ref_element_size (t1
),
275 array_ref_element_size (t2
)))
276 return return_false_with_msg ("");
277 if (!compare_operand (x1
, x2
))
278 return return_false_with_msg ("");
279 return compare_operand (y1
, y2
);
282 x1
= TREE_OPERAND (t1
, 0);
283 x2
= TREE_OPERAND (t2
, 0);
284 y1
= TREE_OPERAND (t1
, 1);
285 y2
= TREE_OPERAND (t2
, 1);
287 /* See if operand is an memory access (the test originate from
290 In this case the alias set of the function being replaced must
291 be subset of the alias set of the other function. At the moment
292 we seek for equivalency classes, so simply require inclussion in
295 if (!func_checker::compatible_types_p (TREE_TYPE (x1
), TREE_TYPE (x2
)))
296 return return_false ();
298 if (!compare_operand (x1
, x2
))
299 return return_false_with_msg ("");
301 if (get_alias_set (TREE_TYPE (y1
)) != get_alias_set (TREE_TYPE (y2
)))
302 return return_false_with_msg ("alias set for MEM_REF offsets are different");
305 ao_ref_init (&r1
, t1
);
306 ao_ref_init (&r2
, t2
);
307 if (ao_ref_alias_set (&r1
) != ao_ref_alias_set (&r2
)
308 || ao_ref_base_alias_set (&r1
) != ao_ref_base_alias_set (&r2
))
309 return return_false_with_msg ("ao alias sets are different");
311 /* Type of the offset on MEM_REF does not matter. */
312 return wi::to_offset (y1
) == wi::to_offset (y2
);
316 x1
= TREE_OPERAND (t1
, 0);
317 x2
= TREE_OPERAND (t2
, 0);
318 y1
= TREE_OPERAND (t1
, 1);
319 y2
= TREE_OPERAND (t2
, 1);
321 ret
= compare_operand (x1
, x2
)
322 && compare_operand (y1
, y2
);
324 return return_with_debug (ret
);
326 /* Virtual table call. */
329 x1
= TREE_OPERAND (t1
, 0);
330 x2
= TREE_OPERAND (t2
, 0);
331 y1
= TREE_OPERAND (t1
, 1);
332 y2
= TREE_OPERAND (t2
, 1);
333 z1
= TREE_OPERAND (t1
, 2);
334 z2
= TREE_OPERAND (t2
, 2);
336 ret
= compare_operand (x1
, x2
)
337 && compare_operand (y1
, y2
)
338 && compare_operand (z1
, z2
);
340 return return_with_debug (ret
);
344 x1
= TREE_OPERAND (t1
, 0);
345 x2
= TREE_OPERAND (t2
, 0);
347 ret
= compare_operand (x1
, x2
);
348 return return_with_debug (ret
);
352 ret
= compare_ssa_name (t1
, t2
);
355 return return_with_debug (ret
);
357 if (SSA_NAME_IS_DEFAULT_DEF (t1
))
359 tree b1
= SSA_NAME_VAR (t1
);
360 tree b2
= SSA_NAME_VAR (t2
);
362 if (b1
== NULL
&& b2
== NULL
)
365 if (b1
== NULL
|| b2
== NULL
|| TREE_CODE (b1
) != TREE_CODE (b2
))
366 return return_false ();
368 switch (TREE_CODE (b1
))
371 return return_with_debug (compare_variable_decl (t1
, t2
));
374 ret
= compare_decl (b1
, b2
);
375 return return_with_debug (ret
);
377 return return_false_with_msg ("Unknown TREE code reached");
385 ret
= compatible_types_p (TREE_TYPE (t1
), TREE_TYPE (t2
))
386 && wi::to_offset (t1
) == wi::to_offset (t2
);
388 return return_with_debug (ret
);
395 ret
= operand_equal_p (t1
, t2
, OEP_ONLY_CONST
);
396 return return_with_debug (ret
);
400 ret
= compare_function_decl (t1
, t2
);
401 return return_with_debug (ret
);
404 return return_with_debug (compare_variable_decl (t1
, t2
));
407 tree offset1
= DECL_FIELD_OFFSET (t1
);
408 tree offset2
= DECL_FIELD_OFFSET (t2
);
410 tree bit_offset1
= DECL_FIELD_BIT_OFFSET (t1
);
411 tree bit_offset2
= DECL_FIELD_BIT_OFFSET (t2
);
413 ret
= compare_operand (offset1
, offset2
)
414 && compare_operand (bit_offset1
, bit_offset2
);
416 return return_with_debug (ret
);
420 int *bb1
= m_label_bb_map
.get (t1
);
421 int *bb2
= m_label_bb_map
.get (t2
);
423 return return_with_debug (*bb1
== *bb2
);
430 ret
= compare_decl (t1
, t2
);
431 return return_with_debug (ret
);
434 return return_false_with_msg ("Unknown TREE code reached");
438 /* Compares two tree list operands T1 and T2 and returns true if these
439 two trees are semantically equivalent. */
442 func_checker::compare_tree_list_operand (tree t1
, tree t2
)
444 gcc_assert (TREE_CODE (t1
) == TREE_LIST
);
445 gcc_assert (TREE_CODE (t2
) == TREE_LIST
);
447 for (; t1
; t1
= TREE_CHAIN (t1
))
452 if (!compare_operand (TREE_VALUE (t1
), TREE_VALUE (t2
)))
453 return return_false ();
455 t2
= TREE_CHAIN (t2
);
459 return return_false ();
464 /* Verifies that trees T1 and T2, representing function declarations
465 are equivalent from perspective of ICF. */
468 func_checker::compare_function_decl (tree t1
, tree t2
)
475 symtab_node
*n1
= symtab_node::get (t1
);
476 symtab_node
*n2
= symtab_node::get (t2
);
478 if (m_ignored_source_nodes
!= NULL
&& m_ignored_target_nodes
!= NULL
)
480 ret
= m_ignored_source_nodes
->contains (n1
)
481 && m_ignored_target_nodes
->contains (n2
);
487 /* If function decl is WEAKREF, we compare targets. */
488 cgraph_node
*f1
= cgraph_node::get (t1
);
489 cgraph_node
*f2
= cgraph_node::get (t2
);
491 if(f1
&& f2
&& f1
->weakref
&& f2
->weakref
)
492 ret
= f1
->alias_target
== f2
->alias_target
;
497 /* Verifies that trees T1 and T2 do correspond. */
500 func_checker::compare_variable_decl (tree t1
, tree t2
)
507 if (TREE_CODE (t1
) == VAR_DECL
&& (DECL_EXTERNAL (t1
) || TREE_STATIC (t1
)))
509 symtab_node
*n1
= symtab_node::get (t1
);
510 symtab_node
*n2
= symtab_node::get (t2
);
512 if (m_ignored_source_nodes
!= NULL
&& m_ignored_target_nodes
!= NULL
)
514 ret
= m_ignored_source_nodes
->contains (n1
)
515 && m_ignored_target_nodes
->contains (n2
);
521 ret
= compare_decl (t1
, t2
);
523 return return_with_debug (ret
);
527 func_checker::parse_labels (sem_bb
*bb
)
529 for (gimple_stmt_iterator gsi
= gsi_start_bb (bb
->bb
); !gsi_end_p (gsi
);
532 gimple stmt
= gsi_stmt (gsi
);
534 if (gimple_code (stmt
) == GIMPLE_LABEL
)
536 tree t
= gimple_label_label (stmt
);
537 gcc_assert (TREE_CODE (t
) == LABEL_DECL
);
539 m_label_bb_map
.put (t
, bb
->bb
->index
);
544 /* Basic block equivalence comparison function that returns true if
545 basic blocks BB1 and BB2 (from functions FUNC1 and FUNC2) correspond.
547 In general, a collection of equivalence dictionaries is built for types
548 like SSA names, declarations (VAR_DECL, PARM_DECL, ..). This infrastructure
549 is utilized by every statement-by-stament comparison function. */
552 func_checker::compare_bb (sem_bb
*bb1
, sem_bb
*bb2
)
555 gimple_stmt_iterator gsi1
, gsi2
;
558 if (bb1
->nondbg_stmt_count
!= bb2
->nondbg_stmt_count
559 || bb1
->edge_count
!= bb2
->edge_count
)
560 return return_false ();
562 gsi1
= gsi_start_bb (bb1
->bb
);
563 gsi2
= gsi_start_bb (bb2
->bb
);
565 for (i
= 0; i
< bb1
->nondbg_stmt_count
; i
++)
567 if (is_gimple_debug (gsi_stmt (gsi1
)))
568 gsi_next_nondebug (&gsi1
);
570 if (is_gimple_debug (gsi_stmt (gsi2
)))
571 gsi_next_nondebug (&gsi2
);
573 s1
= gsi_stmt (gsi1
);
574 s2
= gsi_stmt (gsi2
);
576 int eh1
= lookup_stmt_eh_lp_fn
577 (DECL_STRUCT_FUNCTION (m_source_func_decl
), s1
);
578 int eh2
= lookup_stmt_eh_lp_fn
579 (DECL_STRUCT_FUNCTION (m_target_func_decl
), s2
);
582 return return_false_with_msg ("EH regions are different");
584 if (gimple_code (s1
) != gimple_code (s2
))
585 return return_false_with_msg ("gimple codes are different");
587 switch (gimple_code (s1
))
590 if (!compare_gimple_call (s1
, s2
))
591 return return_different_stmts (s1
, s2
, "GIMPLE_CALL");
594 if (!compare_gimple_assign (s1
, s2
))
595 return return_different_stmts (s1
, s2
, "GIMPLE_ASSIGN");
598 if (!compare_gimple_cond (s1
, s2
))
599 return return_different_stmts (s1
, s2
, "GIMPLE_COND");
602 if (!compare_gimple_switch (s1
, s2
))
603 return return_different_stmts (s1
, s2
, "GIMPLE_SWITCH");
606 case GIMPLE_EH_DISPATCH
:
609 if (!compare_gimple_resx (s1
, s2
))
610 return return_different_stmts (s1
, s2
, "GIMPLE_RESX");
613 if (!compare_gimple_label (s1
, s2
))
614 return return_different_stmts (s1
, s2
, "GIMPLE_LABEL");
617 if (!compare_gimple_return (s1
, s2
))
618 return return_different_stmts (s1
, s2
, "GIMPLE_RETURN");
621 if (!compare_gimple_goto (s1
, s2
))
622 return return_different_stmts (s1
, s2
, "GIMPLE_GOTO");
625 if (!compare_gimple_asm (s1
, s2
))
626 return return_different_stmts (s1
, s2
, "GIMPLE_ASM");
632 return return_false_with_msg ("Unknown GIMPLE code reached");
642 /* Verifies for given GIMPLEs S1 and S2 that
643 call statements are semantically equivalent. */
646 func_checker::compare_gimple_call (gimple s1
, gimple s2
)
651 if (gimple_call_num_args (s1
) != gimple_call_num_args (s2
))
654 t1
= gimple_call_fndecl (s1
);
655 t2
= gimple_call_fndecl (s2
);
657 /* Function pointer variables are not supported yet. */
658 if (!compare_operand (t1
, t2
))
659 return return_false();
661 /* Checking of argument. */
662 for (i
= 0; i
< gimple_call_num_args (s1
); ++i
)
664 t1
= gimple_call_arg (s1
, i
);
665 t2
= gimple_call_arg (s2
, i
);
667 if (!compare_operand (t1
, t2
))
671 /* Return value checking. */
672 t1
= gimple_get_lhs (s1
);
673 t2
= gimple_get_lhs (s2
);
675 return compare_operand (t1
, t2
);
679 /* Verifies for given GIMPLEs S1 and S2 that
680 assignment statements are semantically equivalent. */
683 func_checker::compare_gimple_assign (gimple s1
, gimple s2
)
686 tree_code code1
, code2
;
689 code1
= gimple_expr_code (s1
);
690 code2
= gimple_expr_code (s2
);
695 code1
= gimple_assign_rhs_code (s1
);
696 code2
= gimple_assign_rhs_code (s2
);
701 for (i
= 0; i
< gimple_num_ops (s1
); i
++)
703 arg1
= gimple_op (s1
, i
);
704 arg2
= gimple_op (s2
, i
);
706 if (!compare_operand (arg1
, arg2
))
714 /* Verifies for given GIMPLEs S1 and S2 that
715 condition statements are semantically equivalent. */
718 func_checker::compare_gimple_cond (gimple s1
, gimple s2
)
721 tree_code code1
, code2
;
723 code1
= gimple_expr_code (s1
);
724 code2
= gimple_expr_code (s2
);
729 t1
= gimple_cond_lhs (s1
);
730 t2
= gimple_cond_lhs (s2
);
732 if (!compare_operand (t1
, t2
))
735 t1
= gimple_cond_rhs (s1
);
736 t2
= gimple_cond_rhs (s2
);
738 return compare_operand (t1
, t2
);
741 /* Verifies that tree labels T1 and T2 correspond in FUNC1 and FUNC2. */
744 func_checker::compare_tree_ssa_label (tree t1
, tree t2
)
746 return compare_operand (t1
, t2
);
749 /* Verifies for given GIMPLEs S1 and S2 that
750 label statements are semantically equivalent. */
753 func_checker::compare_gimple_label (gimple g1
, gimple g2
)
758 tree t1
= gimple_label_label (g1
);
759 tree t2
= gimple_label_label (g2
);
761 if (FORCED_LABEL (t1
) || FORCED_LABEL (t2
))
762 return return_false_with_msg ("FORCED_LABEL");
764 return compare_tree_ssa_label (t1
, t2
);
767 /* Verifies for given GIMPLEs S1 and S2 that
768 switch statements are semantically equivalent. */
771 func_checker::compare_gimple_switch (gimple g1
, gimple g2
)
773 unsigned lsize1
, lsize2
, i
;
775 lsize1
= gimple_switch_num_labels (g1
);
776 lsize2
= gimple_switch_num_labels (g2
);
778 if (lsize1
!= lsize2
)
781 tree t1
= gimple_switch_index (g1
);
782 tree t2
= gimple_switch_index (g2
);
784 if (!compare_operand (t1
, t2
))
787 for (i
= 0; i
< lsize1
; i
++)
789 tree label1
= gimple_switch_label (g1
, i
);
790 tree label2
= gimple_switch_label (g2
, i
);
792 if (TREE_CODE (label1
) == CASE_LABEL_EXPR
793 && TREE_CODE (label2
) == CASE_LABEL_EXPR
)
795 label1
= CASE_LABEL (label1
);
796 label2
= CASE_LABEL (label2
);
798 if (!compare_operand (label1
, label2
))
799 return return_false_with_msg ("switch label_exprs are different");
801 else if (!tree_int_cst_equal (label1
, label2
))
802 return return_false_with_msg ("switch labels are different");
808 /* Verifies for given GIMPLEs S1 and S2 that
809 return statements are semantically equivalent. */
812 func_checker::compare_gimple_return (gimple g1
, gimple g2
)
816 t1
= gimple_return_retval (g1
);
817 t2
= gimple_return_retval (g2
);
819 /* Void return type. */
820 if (t1
== NULL
&& t2
== NULL
)
823 return compare_operand (t1
, t2
);
826 /* Verifies for given GIMPLEs S1 and S2 that
827 goto statements are semantically equivalent. */
830 func_checker::compare_gimple_goto (gimple g1
, gimple g2
)
834 dest1
= gimple_goto_dest (g1
);
835 dest2
= gimple_goto_dest (g2
);
837 if (TREE_CODE (dest1
) != TREE_CODE (dest2
) || TREE_CODE (dest1
) != SSA_NAME
)
840 return compare_operand (dest1
, dest2
);
843 /* Verifies for given GIMPLEs S1 and S2 that
844 resx statements are semantically equivalent. */
847 func_checker::compare_gimple_resx (gimple g1
, gimple g2
)
849 return gimple_resx_region (g1
) == gimple_resx_region (g2
);
852 /* Verifies for given GIMPLEs S1 and S2 that ASM statements are equivalent.
853 For the beginning, the pass only supports equality for
854 '__asm__ __volatile__ ("", "", "", "memory")'. */
857 func_checker::compare_gimple_asm (gimple g1
, gimple g2
)
859 if (gimple_asm_volatile_p (g1
) != gimple_asm_volatile_p (g2
))
862 if (gimple_asm_ninputs (g1
) != gimple_asm_ninputs (g2
))
865 if (gimple_asm_noutputs (g1
) != gimple_asm_noutputs (g2
))
868 /* We do not suppport goto ASM statement comparison. */
869 if (gimple_asm_nlabels (g1
) || gimple_asm_nlabels (g2
))
872 if (gimple_asm_nclobbers (g1
) != gimple_asm_nclobbers (g2
))
875 if (strcmp (gimple_asm_string (g1
), gimple_asm_string (g2
)) != 0)
876 return return_false_with_msg ("ASM strings are different");
878 for (unsigned i
= 0; i
< gimple_asm_ninputs (g1
); i
++)
880 tree input1
= gimple_asm_input_op (g1
, i
);
881 tree input2
= gimple_asm_input_op (g2
, i
);
883 if (!compare_tree_list_operand (input1
, input2
))
884 return return_false_with_msg ("ASM input is different");
887 for (unsigned i
= 0; i
< gimple_asm_noutputs (g1
); i
++)
889 tree output1
= gimple_asm_output_op (g1
, i
);
890 tree output2
= gimple_asm_output_op (g2
, i
);
892 if (!compare_tree_list_operand (output1
, output2
))
893 return return_false_with_msg ("ASM output is different");
896 for (unsigned i
= 0; i
< gimple_asm_nclobbers (g1
); i
++)
898 tree clobber1
= gimple_asm_clobber_op (g1
, i
);
899 tree clobber2
= gimple_asm_clobber_op (g2
, i
);
901 if (!operand_equal_p (TREE_VALUE (clobber1
), TREE_VALUE (clobber2
),
903 return return_false_with_msg ("ASM clobber is different");
909 } // ipa_icf_gimple namespace