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"
26 #include "basic-block.h"
27 #include "tree-ssa-alias.h"
28 #include "internal-fn.h"
29 #include "gimple-expr.h"
33 #include "gimple-iterator.h"
34 #include "gimple-ssa.h"
36 #include "stringpool.h"
38 #include "tree-pass.h"
39 #include "gimple-pretty-print.h"
42 #include "data-streamer.h"
43 #include "ipa-utils.h"
45 #include "tree-ssanames.h"
48 #include "ipa-icf-gimple.h"
51 namespace ipa_icf_gimple
{
53 /* Initialize internal structures for a given SOURCE_FUNC_DECL and
54 TARGET_FUNC_DECL. Strict polymorphic comparison is processed if
55 an option COMPARE_POLYMORPHIC is true. For special cases, one can
56 set IGNORE_LABELS to skip label comparison.
57 Similarly, IGNORE_SOURCE_DECLS and IGNORE_TARGET_DECLS are sets
58 of declarations that can be skipped. */
60 func_checker::func_checker (tree source_func_decl
, tree target_func_decl
,
61 bool compare_polymorphic
,
63 hash_set
<symtab_node
*> *ignored_source_nodes
,
64 hash_set
<symtab_node
*> *ignored_target_nodes
)
65 : m_source_func_decl (source_func_decl
), m_target_func_decl (target_func_decl
),
66 m_ignored_source_nodes (ignored_source_nodes
),
67 m_ignored_target_nodes (ignored_target_nodes
),
68 m_compare_polymorphic (compare_polymorphic
),
69 m_ignore_labels (ignore_labels
)
71 function
*source_func
= DECL_STRUCT_FUNCTION (source_func_decl
);
72 function
*target_func
= DECL_STRUCT_FUNCTION (target_func_decl
);
74 unsigned ssa_source
= SSANAMES (source_func
)->length ();
75 unsigned ssa_target
= SSANAMES (target_func
)->length ();
77 m_source_ssa_names
.create (ssa_source
);
78 m_target_ssa_names
.create (ssa_target
);
80 for (unsigned i
= 0; i
< ssa_source
; i
++)
81 m_source_ssa_names
.safe_push (-1);
83 for (unsigned i
= 0; i
< ssa_target
; i
++)
84 m_target_ssa_names
.safe_push (-1);
87 /* Memory release routine. */
89 func_checker::~func_checker ()
91 m_source_ssa_names
.release();
92 m_target_ssa_names
.release();
95 /* Verifies that trees T1 and T2 are equivalent from perspective of ICF. */
98 func_checker::compare_ssa_name (tree t1
, tree t2
)
100 unsigned i1
= SSA_NAME_VERSION (t1
);
101 unsigned i2
= SSA_NAME_VERSION (t2
);
103 if (m_source_ssa_names
[i1
] == -1)
104 m_source_ssa_names
[i1
] = i2
;
105 else if (m_source_ssa_names
[i1
] != (int) i2
)
108 if(m_target_ssa_names
[i2
] == -1)
109 m_target_ssa_names
[i2
] = i1
;
110 else if (m_target_ssa_names
[i2
] != (int) i1
)
116 /* Verification function for edges E1 and E2. */
119 func_checker::compare_edge (edge e1
, edge e2
)
121 if (e1
->flags
!= e2
->flags
)
126 edge
&slot
= m_edge_map
.get_or_insert (e1
, &existed_p
);
128 return return_with_debug (slot
== e2
);
132 /* TODO: filter edge probabilities for profile feedback match. */
137 /* Verification function for declaration trees T1 and T2 that
138 come from functions FUNC1 and FUNC2. */
141 func_checker::compare_decl (tree t1
, tree t2
)
143 if (!auto_var_in_fn_p (t1
, m_source_func_decl
)
144 || !auto_var_in_fn_p (t2
, m_target_func_decl
))
145 return return_with_debug (t1
== t2
);
147 tree_code t
= TREE_CODE (t1
);
148 if ((t
== VAR_DECL
|| t
== PARM_DECL
|| t
== RESULT_DECL
)
149 && DECL_BY_REFERENCE (t1
) != DECL_BY_REFERENCE (t2
))
150 return return_false_with_msg ("DECL_BY_REFERENCE flags are different");
152 if (!compatible_types_p (TREE_TYPE (t1
), TREE_TYPE (t2
),
153 m_compare_polymorphic
))
154 return return_false ();
158 tree
&slot
= m_decl_map
.get_or_insert (t1
, &existed_p
);
160 return return_with_debug (slot
== t2
);
167 /* Return true if types are compatible from perspective of ICF. */
168 bool func_checker::compatible_types_p (tree t1
, tree t2
,
169 bool compare_polymorphic
,
172 if (TREE_CODE (t1
) != TREE_CODE (t2
))
173 return return_false_with_msg ("different tree types");
175 if (!types_compatible_p (t1
, t2
))
176 return return_false_with_msg ("types are not compatible");
178 if (get_alias_set (t1
) != get_alias_set (t2
))
179 return return_false_with_msg ("alias sets are different");
181 /* We call contains_polymorphic_type_p with this pointer type. */
182 if (first_argument
&& TREE_CODE (t1
) == POINTER_TYPE
)
188 if (compare_polymorphic
)
189 if (contains_polymorphic_type_p (t1
) || contains_polymorphic_type_p (t2
))
191 if (!contains_polymorphic_type_p (t1
) || !contains_polymorphic_type_p (t2
))
192 return return_false_with_msg ("one type is not polymorphic");
194 if (!types_must_be_same_for_odr (t1
, t2
))
195 return return_false_with_msg ("types are not same for ODR");
201 /* Function responsible for comparison of handled components T1 and T2.
202 If these components, from functions FUNC1 and FUNC2, are equal, true
206 func_checker::compare_operand (tree t1
, tree t2
)
208 tree base1
, base2
, x1
, x2
, y1
, y2
, z1
, z2
;
209 HOST_WIDE_INT offset1
= 0, offset2
= 0;
217 tree tt1
= TREE_TYPE (t1
);
218 tree tt2
= TREE_TYPE (t2
);
220 if (!func_checker::compatible_types_p (tt1
, tt2
))
223 base1
= get_addr_base_and_unit_offset (t1
, &offset1
);
224 base2
= get_addr_base_and_unit_offset (t2
, &offset2
);
228 if (offset1
!= offset2
)
229 return return_false_with_msg ("base offsets are different");
235 if (TREE_CODE (t1
) != TREE_CODE (t2
))
236 return return_false ();
238 switch (TREE_CODE (t1
))
242 unsigned length1
= vec_safe_length (CONSTRUCTOR_ELTS (t1
));
243 unsigned length2
= vec_safe_length (CONSTRUCTOR_ELTS (t2
));
245 if (length1
!= length2
)
246 return return_false ();
248 for (unsigned i
= 0; i
< length1
; i
++)
249 if (!compare_operand (CONSTRUCTOR_ELT (t1
, i
)->value
,
250 CONSTRUCTOR_ELT (t2
, i
)->value
))
251 return return_false();
256 case ARRAY_RANGE_REF
:
257 x1
= TREE_OPERAND (t1
, 0);
258 x2
= TREE_OPERAND (t2
, 0);
259 y1
= TREE_OPERAND (t1
, 1);
260 y2
= TREE_OPERAND (t2
, 1);
262 if (!compare_operand (array_ref_low_bound (t1
),
263 array_ref_low_bound (t2
)))
264 return return_false_with_msg ("");
265 if (!compare_operand (array_ref_element_size (t1
),
266 array_ref_element_size (t2
)))
267 return return_false_with_msg ("");
268 if (!compare_operand (x1
, x2
))
269 return return_false_with_msg ("");
270 return compare_operand (y1
, y2
);
273 x1
= TREE_OPERAND (t1
, 0);
274 x2
= TREE_OPERAND (t2
, 0);
275 y1
= TREE_OPERAND (t1
, 1);
276 y2
= TREE_OPERAND (t2
, 1);
278 /* See if operand is an memory access (the test originate from
281 In this case the alias set of the function being replaced must
282 be subset of the alias set of the other function. At the moment
283 we seek for equivalency classes, so simply require inclussion in
286 if (!func_checker::compatible_types_p (TREE_TYPE (x1
), TREE_TYPE (x2
)))
287 return return_false ();
289 if (!compare_operand (x1
, x2
))
290 return return_false_with_msg ("");
292 if (get_alias_set (TREE_TYPE (y1
)) != get_alias_set (TREE_TYPE (y2
)))
293 return return_false_with_msg ("alias set for MEM_REF offsets are different");
296 ao_ref_init (&r1
, t1
);
297 ao_ref_init (&r2
, t2
);
298 if (ao_ref_alias_set (&r1
) != ao_ref_alias_set (&r2
)
299 || ao_ref_base_alias_set (&r1
) != ao_ref_base_alias_set (&r2
))
300 return return_false_with_msg ("ao alias sets are different");
302 /* Type of the offset on MEM_REF does not matter. */
303 return wi::to_offset (y1
) == wi::to_offset (y2
);
307 x1
= TREE_OPERAND (t1
, 0);
308 x2
= TREE_OPERAND (t2
, 0);
309 y1
= TREE_OPERAND (t1
, 1);
310 y2
= TREE_OPERAND (t2
, 1);
312 ret
= compare_operand (x1
, x2
)
313 && compare_operand (y1
, y2
);
315 return return_with_debug (ret
);
317 /* Virtual table call. */
320 x1
= TREE_OPERAND (t1
, 0);
321 x2
= TREE_OPERAND (t2
, 0);
322 y1
= TREE_OPERAND (t1
, 1);
323 y2
= TREE_OPERAND (t2
, 1);
324 z1
= TREE_OPERAND (t1
, 2);
325 z2
= TREE_OPERAND (t2
, 2);
327 ret
= compare_operand (x1
, x2
)
328 && compare_operand (y1
, y2
)
329 && compare_operand (z1
, z2
);
331 return return_with_debug (ret
);
335 x1
= TREE_OPERAND (t1
, 0);
336 x2
= TREE_OPERAND (t2
, 0);
338 ret
= compare_operand (x1
, x2
);
339 return return_with_debug (ret
);
343 ret
= compare_ssa_name (t1
, t2
);
346 return return_with_debug (ret
);
348 if (SSA_NAME_IS_DEFAULT_DEF (t1
))
350 tree b1
= SSA_NAME_VAR (t1
);
351 tree b2
= SSA_NAME_VAR (t2
);
353 if (b1
== NULL
&& b2
== NULL
)
356 if (b1
== NULL
|| b2
== NULL
|| TREE_CODE (b1
) != TREE_CODE (b2
))
357 return return_false ();
359 switch (TREE_CODE (b1
))
362 return return_with_debug (compare_variable_decl (t1
, t2
));
365 ret
= compare_decl (b1
, b2
);
366 return return_with_debug (ret
);
368 return return_false_with_msg ("Unknown TREE code reached");
376 ret
= compatible_types_p (TREE_TYPE (t1
), TREE_TYPE (t2
))
377 && wi::to_offset (t1
) == wi::to_offset (t2
);
379 return return_with_debug (ret
);
386 ret
= operand_equal_p (t1
, t2
, OEP_ONLY_CONST
);
387 return return_with_debug (ret
);
391 ret
= compare_function_decl (t1
, t2
);
392 return return_with_debug (ret
);
395 return return_with_debug (compare_variable_decl (t1
, t2
));
398 tree offset1
= DECL_FIELD_OFFSET (t1
);
399 tree offset2
= DECL_FIELD_OFFSET (t2
);
401 tree bit_offset1
= DECL_FIELD_BIT_OFFSET (t1
);
402 tree bit_offset2
= DECL_FIELD_BIT_OFFSET (t2
);
404 ret
= compare_operand (offset1
, offset2
)
405 && compare_operand (bit_offset1
, bit_offset2
);
407 return return_with_debug (ret
);
411 int *bb1
= m_label_bb_map
.get (t1
);
412 int *bb2
= m_label_bb_map
.get (t2
);
414 return return_with_debug (*bb1
== *bb2
);
421 ret
= compare_decl (t1
, t2
);
422 return return_with_debug (ret
);
425 return return_false_with_msg ("Unknown TREE code reached");
429 /* Compares two tree list operands T1 and T2 and returns true if these
430 two trees are semantically equivalent. */
433 func_checker::compare_tree_list_operand (tree t1
, tree t2
)
435 gcc_assert (TREE_CODE (t1
) == TREE_LIST
);
436 gcc_assert (TREE_CODE (t2
) == TREE_LIST
);
438 for (; t1
; t1
= TREE_CHAIN (t1
))
443 if (!compare_operand (TREE_VALUE (t1
), TREE_VALUE (t2
)))
444 return return_false ();
446 t2
= TREE_CHAIN (t2
);
450 return return_false ();
455 /* Verifies that trees T1 and T2, representing function declarations
456 are equivalent from perspective of ICF. */
459 func_checker::compare_function_decl (tree t1
, tree t2
)
466 symtab_node
*n1
= symtab_node::get (t1
);
467 symtab_node
*n2
= symtab_node::get (t2
);
469 if (m_ignored_source_nodes
!= NULL
&& m_ignored_target_nodes
!= NULL
)
471 ret
= m_ignored_source_nodes
->contains (n1
)
472 && m_ignored_target_nodes
->contains (n2
);
478 /* If function decl is WEAKREF, we compare targets. */
479 cgraph_node
*f1
= cgraph_node::get (t1
);
480 cgraph_node
*f2
= cgraph_node::get (t2
);
482 if(f1
&& f2
&& f1
->weakref
&& f2
->weakref
)
483 ret
= f1
->alias_target
== f2
->alias_target
;
488 /* Verifies that trees T1 and T2 do correspond. */
491 func_checker::compare_variable_decl (tree t1
, tree t2
)
498 if (TREE_CODE (t1
) == VAR_DECL
&& (DECL_EXTERNAL (t1
) || TREE_STATIC (t1
)))
500 symtab_node
*n1
= symtab_node::get (t1
);
501 symtab_node
*n2
= symtab_node::get (t2
);
503 if (m_ignored_source_nodes
!= NULL
&& m_ignored_target_nodes
!= NULL
)
505 ret
= m_ignored_source_nodes
->contains (n1
)
506 && m_ignored_target_nodes
->contains (n2
);
512 ret
= compare_decl (t1
, t2
);
514 return return_with_debug (ret
);
518 func_checker::parse_labels (sem_bb
*bb
)
520 for (gimple_stmt_iterator gsi
= gsi_start_bb (bb
->bb
); !gsi_end_p (gsi
);
523 gimple stmt
= gsi_stmt (gsi
);
525 if (gimple_code (stmt
) == GIMPLE_LABEL
)
527 tree t
= gimple_label_label (stmt
);
528 gcc_assert (TREE_CODE (t
) == LABEL_DECL
);
530 m_label_bb_map
.put (t
, bb
->bb
->index
);
535 /* Basic block equivalence comparison function that returns true if
536 basic blocks BB1 and BB2 (from functions FUNC1 and FUNC2) correspond.
538 In general, a collection of equivalence dictionaries is built for types
539 like SSA names, declarations (VAR_DECL, PARM_DECL, ..). This infrastructure
540 is utilized by every statement-by-stament comparison function. */
543 func_checker::compare_bb (sem_bb
*bb1
, sem_bb
*bb2
)
546 gimple_stmt_iterator gsi1
, gsi2
;
549 if (bb1
->nondbg_stmt_count
!= bb2
->nondbg_stmt_count
550 || bb1
->edge_count
!= bb2
->edge_count
)
551 return return_false ();
553 gsi1
= gsi_start_bb (bb1
->bb
);
554 gsi2
= gsi_start_bb (bb2
->bb
);
556 for (i
= 0; i
< bb1
->nondbg_stmt_count
; i
++)
558 if (is_gimple_debug (gsi_stmt (gsi1
)))
559 gsi_next_nondebug (&gsi1
);
561 if (is_gimple_debug (gsi_stmt (gsi2
)))
562 gsi_next_nondebug (&gsi2
);
564 s1
= gsi_stmt (gsi1
);
565 s2
= gsi_stmt (gsi2
);
567 int eh1
= lookup_stmt_eh_lp_fn
568 (DECL_STRUCT_FUNCTION (m_source_func_decl
), s1
);
569 int eh2
= lookup_stmt_eh_lp_fn
570 (DECL_STRUCT_FUNCTION (m_target_func_decl
), s2
);
573 return return_false_with_msg ("EH regions are different");
575 if (gimple_code (s1
) != gimple_code (s2
))
576 return return_false_with_msg ("gimple codes are different");
578 switch (gimple_code (s1
))
581 if (!compare_gimple_call (s1
, s2
))
582 return return_different_stmts (s1
, s2
, "GIMPLE_CALL");
585 if (!compare_gimple_assign (s1
, s2
))
586 return return_different_stmts (s1
, s2
, "GIMPLE_ASSIGN");
589 if (!compare_gimple_cond (s1
, s2
))
590 return return_different_stmts (s1
, s2
, "GIMPLE_COND");
593 if (!compare_gimple_switch (s1
, s2
))
594 return return_different_stmts (s1
, s2
, "GIMPLE_SWITCH");
597 case GIMPLE_EH_DISPATCH
:
600 if (!compare_gimple_resx (s1
, s2
))
601 return return_different_stmts (s1
, s2
, "GIMPLE_RESX");
604 if (!compare_gimple_label (s1
, s2
))
605 return return_different_stmts (s1
, s2
, "GIMPLE_LABEL");
608 if (!compare_gimple_return (s1
, s2
))
609 return return_different_stmts (s1
, s2
, "GIMPLE_RETURN");
612 if (!compare_gimple_goto (s1
, s2
))
613 return return_different_stmts (s1
, s2
, "GIMPLE_GOTO");
616 if (!compare_gimple_asm (s1
, s2
))
617 return return_different_stmts (s1
, s2
, "GIMPLE_ASM");
623 return return_false_with_msg ("Unknown GIMPLE code reached");
633 /* Verifies for given GIMPLEs S1 and S2 that
634 call statements are semantically equivalent. */
637 func_checker::compare_gimple_call (gimple s1
, gimple s2
)
642 if (gimple_call_num_args (s1
) != gimple_call_num_args (s2
))
645 t1
= gimple_call_fndecl (s1
);
646 t2
= gimple_call_fndecl (s2
);
648 /* Function pointer variables are not supported yet. */
649 if (!compare_operand (t1
, t2
))
650 return return_false();
652 /* Checking of argument. */
653 for (i
= 0; i
< gimple_call_num_args (s1
); ++i
)
655 t1
= gimple_call_arg (s1
, i
);
656 t2
= gimple_call_arg (s2
, i
);
658 if (!compare_operand (t1
, t2
))
662 /* Return value checking. */
663 t1
= gimple_get_lhs (s1
);
664 t2
= gimple_get_lhs (s2
);
666 return compare_operand (t1
, t2
);
670 /* Verifies for given GIMPLEs S1 and S2 that
671 assignment statements are semantically equivalent. */
674 func_checker::compare_gimple_assign (gimple s1
, gimple s2
)
677 tree_code code1
, code2
;
680 code1
= gimple_expr_code (s1
);
681 code2
= gimple_expr_code (s2
);
686 code1
= gimple_assign_rhs_code (s1
);
687 code2
= gimple_assign_rhs_code (s2
);
692 for (i
= 0; i
< gimple_num_ops (s1
); i
++)
694 arg1
= gimple_op (s1
, i
);
695 arg2
= gimple_op (s2
, i
);
697 if (!compare_operand (arg1
, arg2
))
705 /* Verifies for given GIMPLEs S1 and S2 that
706 condition statements are semantically equivalent. */
709 func_checker::compare_gimple_cond (gimple s1
, gimple s2
)
712 tree_code code1
, code2
;
714 code1
= gimple_expr_code (s1
);
715 code2
= gimple_expr_code (s2
);
720 t1
= gimple_cond_lhs (s1
);
721 t2
= gimple_cond_lhs (s2
);
723 if (!compare_operand (t1
, t2
))
726 t1
= gimple_cond_rhs (s1
);
727 t2
= gimple_cond_rhs (s2
);
729 return compare_operand (t1
, t2
);
732 /* Verifies that tree labels T1 and T2 correspond in FUNC1 and FUNC2. */
735 func_checker::compare_tree_ssa_label (tree t1
, tree t2
)
737 return compare_operand (t1
, t2
);
740 /* Verifies for given GIMPLEs S1 and S2 that
741 label statements are semantically equivalent. */
744 func_checker::compare_gimple_label (gimple g1
, gimple g2
)
749 tree t1
= gimple_label_label (g1
);
750 tree t2
= gimple_label_label (g2
);
752 if (FORCED_LABEL (t1
) || FORCED_LABEL (t2
))
753 return return_false_with_msg ("FORCED_LABEL");
755 return compare_tree_ssa_label (t1
, t2
);
758 /* Verifies for given GIMPLEs S1 and S2 that
759 switch statements are semantically equivalent. */
762 func_checker::compare_gimple_switch (gimple g1
, gimple g2
)
764 unsigned lsize1
, lsize2
, i
;
766 lsize1
= gimple_switch_num_labels (g1
);
767 lsize2
= gimple_switch_num_labels (g2
);
769 if (lsize1
!= lsize2
)
772 tree t1
= gimple_switch_index (g1
);
773 tree t2
= gimple_switch_index (g2
);
775 if (!compare_operand (t1
, t2
))
778 for (i
= 0; i
< lsize1
; i
++)
780 tree label1
= gimple_switch_label (g1
, i
);
781 tree label2
= gimple_switch_label (g2
, i
);
783 if (TREE_CODE (label1
) == CASE_LABEL_EXPR
784 && TREE_CODE (label2
) == CASE_LABEL_EXPR
)
786 label1
= CASE_LABEL (label1
);
787 label2
= CASE_LABEL (label2
);
789 if (!compare_operand (label1
, label2
))
790 return return_false_with_msg ("switch label_exprs are different");
792 else if (!tree_int_cst_equal (label1
, label2
))
793 return return_false_with_msg ("switch labels are different");
799 /* Verifies for given GIMPLEs S1 and S2 that
800 return statements are semantically equivalent. */
803 func_checker::compare_gimple_return (gimple g1
, gimple g2
)
807 t1
= gimple_return_retval (g1
);
808 t2
= gimple_return_retval (g2
);
810 /* Void return type. */
811 if (t1
== NULL
&& t2
== NULL
)
814 return compare_operand (t1
, t2
);
817 /* Verifies for given GIMPLEs S1 and S2 that
818 goto statements are semantically equivalent. */
821 func_checker::compare_gimple_goto (gimple g1
, gimple g2
)
825 dest1
= gimple_goto_dest (g1
);
826 dest2
= gimple_goto_dest (g2
);
828 if (TREE_CODE (dest1
) != TREE_CODE (dest2
) || TREE_CODE (dest1
) != SSA_NAME
)
831 return compare_operand (dest1
, dest2
);
834 /* Verifies for given GIMPLEs S1 and S2 that
835 resx statements are semantically equivalent. */
838 func_checker::compare_gimple_resx (gimple g1
, gimple g2
)
840 return gimple_resx_region (g1
) == gimple_resx_region (g2
);
843 /* Verifies for given GIMPLEs S1 and S2 that ASM statements are equivalent.
844 For the beginning, the pass only supports equality for
845 '__asm__ __volatile__ ("", "", "", "memory")'. */
848 func_checker::compare_gimple_asm (gimple g1
, gimple g2
)
850 if (gimple_asm_volatile_p (g1
) != gimple_asm_volatile_p (g2
))
853 if (gimple_asm_ninputs (g1
) != gimple_asm_ninputs (g2
))
856 if (gimple_asm_noutputs (g1
) != gimple_asm_noutputs (g2
))
859 /* We do not suppport goto ASM statement comparison. */
860 if (gimple_asm_nlabels (g1
) || gimple_asm_nlabels (g2
))
863 if (gimple_asm_nclobbers (g1
) != gimple_asm_nclobbers (g2
))
866 if (strcmp (gimple_asm_string (g1
), gimple_asm_string (g2
)) != 0)
867 return return_false_with_msg ("ASM strings are different");
869 for (unsigned i
= 0; i
< gimple_asm_ninputs (g1
); i
++)
871 tree input1
= gimple_asm_input_op (g1
, i
);
872 tree input2
= gimple_asm_input_op (g2
, i
);
874 if (!compare_tree_list_operand (input1
, input2
))
875 return return_false_with_msg ("ASM input is different");
878 for (unsigned i
= 0; i
< gimple_asm_noutputs (g1
); i
++)
880 tree output1
= gimple_asm_output_op (g1
, i
);
881 tree output2
= gimple_asm_output_op (g2
, i
);
883 if (!compare_tree_list_operand (output1
, output2
))
884 return return_false_with_msg ("ASM output is different");
887 for (unsigned i
= 0; i
< gimple_asm_nclobbers (g1
); i
++)
889 tree clobber1
= gimple_asm_clobber_op (g1
, i
);
890 tree clobber2
= gimple_asm_clobber_op (g2
, i
);
892 if (!operand_equal_p (TREE_VALUE (clobber1
), TREE_VALUE (clobber2
),
894 return return_false_with_msg ("ASM clobber is different");
900 } // ipa_icf_gimple namespace