xref: /netbsd-src/external/gpl3/gcc.old/dist/gcc/ipa-icf-gimple.c (revision 8feb0f0b7eaff0608f8350bbfa3098827b4bb91b)
1 /* Interprocedural Identical Code Folding pass
2    Copyright (C) 2014-2020 Free Software Foundation, Inc.
3 
4    Contributed by Jan Hubicka <hubicka@ucw.cz> and Martin Liska <mliska@suse.cz>
5 
6 This file is part of GCC.
7 
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
11 version.
12 
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
16 for more details.
17 
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/>.  */
21 
22 #include "config.h"
23 #include "system.h"
24 #include "coretypes.h"
25 #include "backend.h"
26 #include "rtl.h"
27 #include "tree.h"
28 #include "gimple.h"
29 #include "tree-pass.h"
30 #include "ssa.h"
31 #include "cgraph.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"
37 #include "tree-eh.h"
38 #include "builtins.h"
39 #include "cfgloop.h"
40 #include "attribs.h"
41 
42 #include "ipa-icf-gimple.h"
43 
44 namespace ipa_icf_gimple {
45 
46 /* Initialize internal structures for a given SOURCE_FUNC_DECL and
47    TARGET_FUNC_DECL. Strict polymorphic comparison is processed if
48    an option COMPARE_POLYMORPHIC is true. For special cases, one can
49    set IGNORE_LABELS to skip label comparison.
50    Similarly, IGNORE_SOURCE_DECLS and IGNORE_TARGET_DECLS are sets
51    of declarations that can be skipped.  */
52 
func_checker(tree source_func_decl,tree target_func_decl,bool ignore_labels,hash_set<symtab_node * > * ignored_source_nodes,hash_set<symtab_node * > * ignored_target_nodes)53 func_checker::func_checker (tree source_func_decl, tree target_func_decl,
54 			    bool ignore_labels,
55 			    hash_set<symtab_node *> *ignored_source_nodes,
56 			    hash_set<symtab_node *> *ignored_target_nodes)
57   : m_source_func_decl (source_func_decl), m_target_func_decl (target_func_decl),
58     m_ignored_source_nodes (ignored_source_nodes),
59     m_ignored_target_nodes (ignored_target_nodes),
60     m_ignore_labels (ignore_labels)
61 {
62   function *source_func = DECL_STRUCT_FUNCTION (source_func_decl);
63   function *target_func = DECL_STRUCT_FUNCTION (target_func_decl);
64 
65   unsigned ssa_source = SSANAMES (source_func)->length ();
66   unsigned ssa_target = SSANAMES (target_func)->length ();
67 
68   m_source_ssa_names.create (ssa_source);
69   m_target_ssa_names.create (ssa_target);
70 
71   for (unsigned i = 0; i < ssa_source; i++)
72     m_source_ssa_names.safe_push (-1);
73 
74   for (unsigned i = 0; i < ssa_target; i++)
75     m_target_ssa_names.safe_push (-1);
76 }
77 
78 /* Memory release routine.  */
79 
~func_checker()80 func_checker::~func_checker ()
81 {
82   m_source_ssa_names.release();
83   m_target_ssa_names.release();
84 }
85 
86 /* Verifies that trees T1 and T2 are equivalent from perspective of ICF.  */
87 
88 bool
compare_ssa_name(const_tree t1,const_tree t2)89 func_checker::compare_ssa_name (const_tree t1, const_tree t2)
90 {
91   gcc_assert (TREE_CODE (t1) == SSA_NAME);
92   gcc_assert (TREE_CODE (t2) == SSA_NAME);
93 
94   unsigned i1 = SSA_NAME_VERSION (t1);
95   unsigned i2 = SSA_NAME_VERSION (t2);
96 
97   if (m_source_ssa_names[i1] == -1)
98     m_source_ssa_names[i1] = i2;
99   else if (m_source_ssa_names[i1] != (int) i2)
100     return false;
101 
102   if(m_target_ssa_names[i2] == -1)
103     m_target_ssa_names[i2] = i1;
104   else if (m_target_ssa_names[i2] != (int) i1)
105     return false;
106 
107   if (SSA_NAME_IS_DEFAULT_DEF (t1))
108     {
109       tree b1 = SSA_NAME_VAR (t1);
110       tree b2 = SSA_NAME_VAR (t2);
111 
112       return compare_operand (b1, b2);
113     }
114 
115   return true;
116 }
117 
118 /* Verification function for edges E1 and E2.  */
119 
120 bool
compare_edge(edge e1,edge e2)121 func_checker::compare_edge (edge e1, edge e2)
122 {
123   if (e1->flags != e2->flags)
124     return false;
125 
126   bool existed_p;
127 
128   edge &slot = m_edge_map.get_or_insert (e1, &existed_p);
129   if (existed_p)
130     return return_with_debug (slot == e2);
131   else
132     slot = e2;
133 
134   /* TODO: filter edge probabilities for profile feedback match.  */
135 
136   return true;
137 }
138 
139 /* Verification function for declaration trees T1 and T2 that
140    come from functions FUNC1 and FUNC2.  */
141 
142 bool
compare_decl(const_tree t1,const_tree t2)143 func_checker::compare_decl (const_tree t1, const_tree t2)
144 {
145   if (!auto_var_in_fn_p (t1, m_source_func_decl)
146       || !auto_var_in_fn_p (t2, m_target_func_decl))
147     return return_with_debug (t1 == t2);
148 
149   tree_code t = TREE_CODE (t1);
150   if ((t == VAR_DECL || t == PARM_DECL || t == RESULT_DECL)
151       && DECL_BY_REFERENCE (t1) != DECL_BY_REFERENCE (t2))
152     return return_false_with_msg ("DECL_BY_REFERENCE flags are different");
153 
154   if (!compatible_types_p (TREE_TYPE (t1), TREE_TYPE (t2)))
155     return return_false ();
156 
157   bool existed_p;
158   const_tree &slot = m_decl_map.get_or_insert (t1, &existed_p);
159   if (existed_p)
160     return return_with_debug (slot == t2);
161   else
162     slot = t2;
163 
164   return true;
165 }
166 
167 /* Return true if T1 and T2 are same for purposes of ipa-polymorphic-call
168    analysis.  COMPARE_PTR indicates if types of pointers needs to be
169    considered.  */
170 
171 bool
compatible_polymorphic_types_p(tree t1,tree t2,bool compare_ptr)172 func_checker::compatible_polymorphic_types_p (tree t1, tree t2,
173 					      bool compare_ptr)
174 {
175   gcc_assert (TREE_CODE (t1) != FUNCTION_TYPE && TREE_CODE (t1) != METHOD_TYPE);
176 
177   /* Pointer types generally give no information.  */
178   if (POINTER_TYPE_P (t1))
179     {
180       if (!compare_ptr)
181 	return true;
182       return func_checker::compatible_polymorphic_types_p (TREE_TYPE (t1),
183 							   TREE_TYPE (t2),
184 							   false);
185     }
186 
187   /* If types contain a polymorphic types, match them.  */
188   bool c1 = contains_polymorphic_type_p (t1);
189   bool c2 = contains_polymorphic_type_p (t2);
190   if (!c1 && !c2)
191     return true;
192   if (!c1 || !c2)
193     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");
196   return true;
197 }
198 
199 /* Return true if types are compatible from perspective of ICF.  */
200 bool
compatible_types_p(tree t1,tree t2)201 func_checker::compatible_types_p (tree t1, tree t2)
202 {
203   if (TREE_CODE (t1) != TREE_CODE (t2))
204     return return_false_with_msg ("different tree types");
205 
206   if (TYPE_RESTRICT (t1) != TYPE_RESTRICT (t2))
207     return return_false_with_msg ("restrict flags are different");
208 
209   if (!types_compatible_p (t1, t2))
210     return return_false_with_msg ("types are not compatible");
211 
212   return true;
213 }
214 
215 /* Function compare for equality given trees T1 and T2 which
216    can be either a constant or a declaration type.  */
217 
218 void
hash_operand(const_tree arg,inchash::hash & hstate,unsigned int flags)219 func_checker::hash_operand (const_tree arg, inchash::hash &hstate,
220 			    unsigned int flags)
221 {
222   if (arg == NULL_TREE)
223     {
224       hstate.merge_hash (0);
225       return;
226     }
227 
228   switch (TREE_CODE (arg))
229     {
230     case FUNCTION_DECL:
231     case VAR_DECL:
232     case LABEL_DECL:
233     case PARM_DECL:
234     case RESULT_DECL:
235     case CONST_DECL:
236     case SSA_NAME:
237       return;
238     case FIELD_DECL:
239       inchash::add_expr (DECL_FIELD_OFFSET (arg), hstate, flags);
240       inchash::add_expr (DECL_FIELD_BIT_OFFSET (arg), hstate, flags);
241       return;
242     default:
243       break;
244     }
245 
246   return operand_compare::hash_operand (arg, hstate, flags);
247 }
248 
249 bool
operand_equal_p(const_tree t1,const_tree t2,unsigned int flags)250 func_checker::operand_equal_p (const_tree t1, const_tree t2,
251 			       unsigned int flags)
252 {
253   bool r;
254   if (verify_hash_value (t1, t2, flags, &r))
255     return r;
256 
257   if (t1 == t2)
258     return true;
259   else if (!t1 || !t2)
260     return false;
261 
262   if (TREE_CODE (t1) != TREE_CODE (t2))
263     return return_false ();
264 
265   switch (TREE_CODE (t1))
266     {
267     case FUNCTION_DECL:
268       /* All function decls are in the symbol table and known to match
269 	 before we start comparing bodies.  */
270       return true;
271     case VAR_DECL:
272       return return_with_debug (compare_variable_decl (t1, t2));
273     case LABEL_DECL:
274       {
275 	int *bb1 = m_label_bb_map.get (t1);
276 	int *bb2 = m_label_bb_map.get (t2);
277 	/* Labels can point to another function (non-local GOTOs).  */
278 	return return_with_debug (bb1 != NULL && bb2 != NULL && *bb1 == *bb2);
279       }
280 
281     case PARM_DECL:
282     case RESULT_DECL:
283     case CONST_DECL:
284       return compare_decl (t1, t2);
285     case SSA_NAME:
286       return compare_ssa_name (t1, t2);
287     default:
288       break;
289     }
290 
291   return operand_compare::operand_equal_p (t1, t2, flags);
292 }
293 
294 /* Function responsible for comparison of various operands T1 and T2.
295    If these components, from functions FUNC1 and FUNC2, are equal, true
296    is returned.  */
297 
298 bool
compare_operand(tree t1,tree t2)299 func_checker::compare_operand (tree t1, tree t2)
300 {
301   if (!t1 && !t2)
302     return true;
303   else if (!t1 || !t2)
304     return false;
305   if (operand_equal_p (t1, t2, OEP_MATCH_SIDE_EFFECTS))
306     return true;
307   return return_false_with_msg ("operand_equal_p failed");
308 }
309 
310 bool
compare_asm_inputs_outputs(tree t1,tree t2)311 func_checker::compare_asm_inputs_outputs (tree t1, tree t2)
312 {
313   gcc_assert (TREE_CODE (t1) == TREE_LIST);
314   gcc_assert (TREE_CODE (t2) == TREE_LIST);
315 
316   for (; t1; t1 = TREE_CHAIN (t1))
317     {
318       if (!t2)
319 	return false;
320 
321       if (!compare_operand (TREE_VALUE (t1), TREE_VALUE (t2)))
322 	return return_false ();
323 
324       tree p1 = TREE_PURPOSE (t1);
325       tree p2 = TREE_PURPOSE (t2);
326 
327       gcc_assert (TREE_CODE (p1) == TREE_LIST);
328       gcc_assert (TREE_CODE (p2) == TREE_LIST);
329 
330       if (strcmp (TREE_STRING_POINTER (TREE_VALUE (p1)),
331 		  TREE_STRING_POINTER (TREE_VALUE (p2))) != 0)
332 	return return_false ();
333 
334       t2 = TREE_CHAIN (t2);
335     }
336 
337   if (t2)
338     return return_false ();
339 
340   return true;
341 }
342 
343 /* Verifies that trees T1 and T2 do correspond.  */
344 
345 bool
compare_variable_decl(const_tree t1,const_tree t2)346 func_checker::compare_variable_decl (const_tree t1, const_tree t2)
347 {
348   bool ret = false;
349 
350   if (t1 == t2)
351     return true;
352 
353   if (DECL_ALIGN (t1) != DECL_ALIGN (t2))
354     return return_false_with_msg ("alignments are different");
355 
356   if (DECL_HARD_REGISTER (t1) != DECL_HARD_REGISTER (t2))
357     return return_false_with_msg ("DECL_HARD_REGISTER are different");
358 
359   if (DECL_HARD_REGISTER (t1)
360       && DECL_ASSEMBLER_NAME_RAW (t1) != DECL_ASSEMBLER_NAME_RAW (t2))
361     return return_false_with_msg ("HARD REGISTERS are different");
362 
363   /* Symbol table variables are known to match before we start comparing
364      bodies.  */
365   if (decl_in_symtab_p (t1))
366     return decl_in_symtab_p (t2);
367   ret = compare_decl (t1, t2);
368 
369   return return_with_debug (ret);
370 }
371 
372 /* Compare loop information for basic blocks BB1 and BB2.  */
373 
374 bool
compare_loops(basic_block bb1,basic_block bb2)375 func_checker::compare_loops (basic_block bb1, basic_block bb2)
376 {
377   if ((bb1->loop_father == NULL) != (bb2->loop_father == NULL))
378     return return_false ();
379 
380   class loop *l1 = bb1->loop_father;
381   class loop *l2 = bb2->loop_father;
382   if (l1 == NULL)
383     return true;
384 
385   if ((bb1 == l1->header) != (bb2 == l2->header))
386     return return_false_with_msg ("header");
387   if ((bb1 == l1->latch) != (bb2 == l2->latch))
388     return return_false_with_msg ("latch");
389   if (l1->simdlen != l2->simdlen)
390     return return_false_with_msg ("simdlen");
391   if (l1->safelen != l2->safelen)
392     return return_false_with_msg ("safelen");
393   if (l1->can_be_parallel != l2->can_be_parallel)
394     return return_false_with_msg ("can_be_parallel");
395   if (l1->dont_vectorize != l2->dont_vectorize)
396     return return_false_with_msg ("dont_vectorize");
397   if (l1->force_vectorize != l2->force_vectorize)
398     return return_false_with_msg ("force_vectorize");
399   if (l1->finite_p != l2->finite_p)
400     return return_false_with_msg ("finite_p");
401   if (l1->unroll != l2->unroll)
402     return return_false_with_msg ("unroll");
403   if (!compare_variable_decl (l1->simduid, l2->simduid))
404     return return_false_with_msg ("simduid");
405 
406   return true;
407 }
408 
409 /* Function visits all gimple labels and creates corresponding
410    mapping between basic blocks and labels.  */
411 
412 void
parse_labels(sem_bb * bb)413 func_checker::parse_labels (sem_bb *bb)
414 {
415   for (gimple_stmt_iterator gsi = gsi_start_bb (bb->bb); !gsi_end_p (gsi);
416        gsi_next (&gsi))
417     {
418       gimple *stmt = gsi_stmt (gsi);
419 
420       if (glabel *label_stmt = dyn_cast <glabel *> (stmt))
421 	{
422 	  const_tree t = gimple_label_label (label_stmt);
423 	  gcc_assert (TREE_CODE (t) == LABEL_DECL);
424 
425 	  m_label_bb_map.put (t, bb->bb->index);
426 	}
427     }
428 }
429 
430 /* Basic block equivalence comparison function that returns true if
431    basic blocks BB1 and BB2 (from functions FUNC1 and FUNC2) correspond.
432 
433    In general, a collection of equivalence dictionaries is built for types
434    like SSA names, declarations (VAR_DECL, PARM_DECL, ..). This infrastructure
435    is utilized by every statement-by-statement comparison function.  */
436 
437 bool
compare_bb(sem_bb * bb1,sem_bb * bb2)438 func_checker::compare_bb (sem_bb *bb1, sem_bb *bb2)
439 {
440   gimple_stmt_iterator gsi1, gsi2;
441   gimple *s1, *s2;
442 
443   gsi1 = gsi_start_nondebug_bb (bb1->bb);
444   gsi2 = gsi_start_nondebug_bb (bb2->bb);
445 
446   while (!gsi_end_p (gsi1))
447     {
448       if (gsi_end_p (gsi2))
449 	return return_false ();
450 
451       s1 = gsi_stmt (gsi1);
452       s2 = gsi_stmt (gsi2);
453 
454       int eh1 = lookup_stmt_eh_lp_fn
455 		(DECL_STRUCT_FUNCTION (m_source_func_decl), s1);
456       int eh2 = lookup_stmt_eh_lp_fn
457 		(DECL_STRUCT_FUNCTION (m_target_func_decl), s2);
458 
459       if (eh1 != eh2)
460 	return return_false_with_msg ("EH regions are different");
461 
462       if (gimple_code (s1) != gimple_code (s2))
463 	return return_false_with_msg ("gimple codes are different");
464 
465       switch (gimple_code (s1))
466 	{
467 	case GIMPLE_CALL:
468 	  if (!compare_gimple_call (as_a <gcall *> (s1),
469 				    as_a <gcall *> (s2)))
470 	    return return_different_stmts (s1, s2, "GIMPLE_CALL");
471 	  break;
472 	case GIMPLE_ASSIGN:
473 	  if (!compare_gimple_assign (s1, s2))
474 	    return return_different_stmts (s1, s2, "GIMPLE_ASSIGN");
475 	  break;
476 	case GIMPLE_COND:
477 	  if (!compare_gimple_cond (s1, s2))
478 	    return return_different_stmts (s1, s2, "GIMPLE_COND");
479 	  break;
480 	case GIMPLE_SWITCH:
481 	  if (!compare_gimple_switch (as_a <gswitch *> (s1),
482 				      as_a <gswitch *> (s2)))
483 	    return return_different_stmts (s1, s2, "GIMPLE_SWITCH");
484 	  break;
485 	case GIMPLE_DEBUG:
486 	  break;
487 	case GIMPLE_EH_DISPATCH:
488 	  if (gimple_eh_dispatch_region (as_a <geh_dispatch *> (s1))
489 	      != gimple_eh_dispatch_region (as_a <geh_dispatch *> (s2)))
490 	    return return_different_stmts (s1, s2, "GIMPLE_EH_DISPATCH");
491 	  break;
492 	case GIMPLE_RESX:
493 	  if (!compare_gimple_resx (as_a <gresx *> (s1),
494 				    as_a <gresx *> (s2)))
495 	    return return_different_stmts (s1, s2, "GIMPLE_RESX");
496 	  break;
497 	case GIMPLE_LABEL:
498 	  if (!compare_gimple_label (as_a <glabel *> (s1),
499 				     as_a <glabel *> (s2)))
500 	    return return_different_stmts (s1, s2, "GIMPLE_LABEL");
501 	  break;
502 	case GIMPLE_RETURN:
503 	  if (!compare_gimple_return (as_a <greturn *> (s1),
504 				      as_a <greturn *> (s2)))
505 	    return return_different_stmts (s1, s2, "GIMPLE_RETURN");
506 	  break;
507 	case GIMPLE_GOTO:
508 	  if (!compare_gimple_goto (s1, s2))
509 	    return return_different_stmts (s1, s2, "GIMPLE_GOTO");
510 	  break;
511 	case GIMPLE_ASM:
512 	  if (!compare_gimple_asm (as_a <gasm *> (s1),
513 				   as_a <gasm *> (s2)))
514 	    return return_different_stmts (s1, s2, "GIMPLE_ASM");
515 	  break;
516 	case GIMPLE_PREDICT:
517 	case GIMPLE_NOP:
518 	  break;
519 	default:
520 	  return return_false_with_msg ("Unknown GIMPLE code reached");
521 	}
522 
523       gsi_next_nondebug (&gsi1);
524       gsi_next_nondebug (&gsi2);
525     }
526 
527   if (!gsi_end_p (gsi2))
528     return return_false ();
529 
530   if (!compare_loops (bb1->bb, bb2->bb))
531     return return_false ();
532 
533   return true;
534 }
535 
536 /* Verifies for given GIMPLEs S1 and S2 that
537    call statements are semantically equivalent.  */
538 
539 bool
compare_gimple_call(gcall * s1,gcall * s2)540 func_checker::compare_gimple_call (gcall *s1, gcall *s2)
541 {
542   unsigned i;
543   tree t1, t2;
544 
545   if (gimple_call_num_args (s1) != gimple_call_num_args (s2))
546     return false;
547 
548   t1 = gimple_call_fn (s1);
549   t2 = gimple_call_fn (s2);
550   if (!compare_operand (t1, t2))
551     return return_false ();
552 
553   /* Compare flags.  */
554   if (gimple_call_internal_p (s1) != gimple_call_internal_p (s2)
555       || gimple_call_ctrl_altering_p (s1) != gimple_call_ctrl_altering_p (s2)
556       || gimple_call_tail_p (s1) != gimple_call_tail_p (s2)
557       || gimple_call_return_slot_opt_p (s1) != gimple_call_return_slot_opt_p (s2)
558       || gimple_call_from_thunk_p (s1) != gimple_call_from_thunk_p (s2)
559       || gimple_call_va_arg_pack_p (s1) != gimple_call_va_arg_pack_p (s2)
560       || gimple_call_alloca_for_var_p (s1) != gimple_call_alloca_for_var_p (s2))
561     return false;
562 
563   if (gimple_call_internal_p (s1)
564       && gimple_call_internal_fn (s1) != gimple_call_internal_fn (s2))
565     return false;
566 
567   tree fntype1 = gimple_call_fntype (s1);
568   tree fntype2 = gimple_call_fntype (s2);
569   if ((fntype1 && !fntype2)
570       || (!fntype1 && fntype2)
571       || (fntype1 && !types_compatible_p (fntype1, fntype2)))
572     return return_false_with_msg ("call function types are not compatible");
573 
574   if (fntype1 && fntype2 && comp_type_attributes (fntype1, fntype2) != 1)
575     return return_false_with_msg ("different fntype attributes");
576 
577   tree chain1 = gimple_call_chain (s1);
578   tree chain2 = gimple_call_chain (s2);
579   if ((chain1 && !chain2)
580       || (!chain1 && chain2)
581       || !compare_operand (chain1, chain2))
582     return return_false_with_msg ("static call chains are different");
583 
584   /* Checking of argument.  */
585   for (i = 0; i < gimple_call_num_args (s1); ++i)
586     {
587       t1 = gimple_call_arg (s1, i);
588       t2 = gimple_call_arg (s2, i);
589 
590       if (!compare_operand (t1, t2))
591 	return return_false_with_msg ("GIMPLE call operands are different");
592     }
593 
594   /* Return value checking.  */
595   t1 = gimple_get_lhs (s1);
596   t2 = gimple_get_lhs (s2);
597 
598   /* For internal calls, lhs types need to be verified, as neither fntype nor
599      callee comparisons can catch that.  */
600   if (gimple_call_internal_p (s1)
601       && t1
602       && t2
603       && !compatible_types_p (TREE_TYPE (t1), TREE_TYPE (t2)))
604     return return_false_with_msg ("GIMPLE internal call LHS type mismatch");
605 
606   return compare_operand (t1, t2);
607 }
608 
609 
610 /* Verifies for given GIMPLEs S1 and S2 that
611    assignment statements are semantically equivalent.  */
612 
613 bool
compare_gimple_assign(gimple * s1,gimple * s2)614 func_checker::compare_gimple_assign (gimple *s1, gimple *s2)
615 {
616   tree arg1, arg2;
617   tree_code code1, code2;
618   unsigned i;
619 
620   code1 = gimple_expr_code (s1);
621   code2 = gimple_expr_code (s2);
622 
623   if (code1 != code2)
624     return false;
625 
626   code1 = gimple_assign_rhs_code (s1);
627   code2 = gimple_assign_rhs_code (s2);
628 
629   if (code1 != code2)
630     return false;
631 
632   for (i = 0; i < gimple_num_ops (s1); i++)
633     {
634       arg1 = gimple_op (s1, i);
635       arg2 = gimple_op (s2, i);
636 
637       /* Compare types for LHS.  */
638       if (i == 0)
639 	{
640 	  if (!compatible_types_p (TREE_TYPE (arg1), TREE_TYPE (arg2)))
641 	    return return_false_with_msg ("GIMPLE NOP LHS type mismatch");
642 	}
643 
644       if (!compare_operand (arg1, arg2))
645 	return return_false_with_msg ("GIMPLE assignment operands "
646 				      "are different");
647     }
648 
649 
650   return true;
651 }
652 
653 /* Verifies for given GIMPLEs S1 and S2 that
654    condition statements are semantically equivalent.  */
655 
656 bool
compare_gimple_cond(gimple * s1,gimple * s2)657 func_checker::compare_gimple_cond (gimple *s1, gimple *s2)
658 {
659   tree t1, t2;
660   tree_code code1, code2;
661 
662   code1 = gimple_expr_code (s1);
663   code2 = gimple_expr_code (s2);
664 
665   if (code1 != code2)
666     return false;
667 
668   t1 = gimple_cond_lhs (s1);
669   t2 = gimple_cond_lhs (s2);
670 
671   if (!compare_operand (t1, t2))
672     return false;
673 
674   t1 = gimple_cond_rhs (s1);
675   t2 = gimple_cond_rhs (s2);
676 
677   return compare_operand (t1, t2);
678 }
679 
680 /* Verifies for given GIMPLE_LABEL stmts S1 and S2 that
681    label statements are semantically equivalent.  */
682 
683 bool
compare_gimple_label(const glabel * g1,const glabel * g2)684 func_checker::compare_gimple_label (const glabel *g1, const glabel *g2)
685 {
686   if (m_ignore_labels)
687     return true;
688 
689   tree t1 = gimple_label_label (g1);
690   tree t2 = gimple_label_label (g2);
691 
692   if (FORCED_LABEL (t1) || FORCED_LABEL (t2))
693     return return_false_with_msg ("FORCED_LABEL");
694 
695   /* As the pass build BB to label mapping, no further check is needed.  */
696   return true;
697 }
698 
699 /* Verifies for given GIMPLE_SWITCH stmts S1 and S2 that
700    switch statements are semantically equivalent.  */
701 
702 bool
compare_gimple_switch(const gswitch * g1,const gswitch * g2)703 func_checker::compare_gimple_switch (const gswitch *g1, const gswitch *g2)
704 {
705   unsigned lsize1, lsize2, i;
706 
707   lsize1 = gimple_switch_num_labels (g1);
708   lsize2 = gimple_switch_num_labels (g2);
709 
710   if (lsize1 != lsize2)
711     return false;
712 
713   tree t1 = gimple_switch_index (g1);
714   tree t2 = gimple_switch_index (g2);
715 
716   if (!compare_operand (t1, t2))
717     return false;
718 
719   for (i = 0; i < lsize1; i++)
720     {
721       tree label1 = gimple_switch_label (g1, i);
722       tree label2 = gimple_switch_label (g2, i);
723 
724       /* Label LOW and HIGH comparison.  */
725       tree low1 = CASE_LOW (label1);
726       tree low2 = CASE_LOW (label2);
727 
728       if (!tree_int_cst_equal (low1, low2))
729 	return return_false_with_msg ("case low values are different");
730 
731       tree high1 = CASE_HIGH (label1);
732       tree high2 = CASE_HIGH (label2);
733 
734       if (!tree_int_cst_equal (high1, high2))
735 	return return_false_with_msg ("case high values are different");
736 
737       if (TREE_CODE (label1) == CASE_LABEL_EXPR
738 	  && TREE_CODE (label2) == CASE_LABEL_EXPR)
739 	{
740 	  label1 = CASE_LABEL (label1);
741 	  label2 = CASE_LABEL (label2);
742 
743 	  if (!compare_operand (label1, label2))
744 	    return return_false_with_msg ("switch label_exprs are different");
745 	}
746       else if (!tree_int_cst_equal (label1, label2))
747 	return return_false_with_msg ("switch labels are different");
748     }
749 
750   return true;
751 }
752 
753 /* Verifies for given GIMPLE_RETURN stmts S1 and S2 that
754    return statements are semantically equivalent.  */
755 
756 bool
compare_gimple_return(const greturn * g1,const greturn * g2)757 func_checker::compare_gimple_return (const greturn *g1, const greturn *g2)
758 {
759   tree t1, t2;
760 
761   t1 = gimple_return_retval (g1);
762   t2 = gimple_return_retval (g2);
763 
764   /* Void return type.  */
765   if (t1 == NULL && t2 == NULL)
766     return true;
767   else
768     return compare_operand (t1, t2);
769 }
770 
771 /* Verifies for given GIMPLEs S1 and S2 that
772    goto statements are semantically equivalent.  */
773 
774 bool
compare_gimple_goto(gimple * g1,gimple * g2)775 func_checker::compare_gimple_goto (gimple *g1, gimple *g2)
776 {
777   tree dest1, dest2;
778 
779   dest1 = gimple_goto_dest (g1);
780   dest2 = gimple_goto_dest (g2);
781 
782   if (TREE_CODE (dest1) != TREE_CODE (dest2) || TREE_CODE (dest1) != SSA_NAME)
783     return false;
784 
785   return compare_operand (dest1, dest2);
786 }
787 
788 /* Verifies for given GIMPLE_RESX stmts S1 and S2 that
789    resx statements are semantically equivalent.  */
790 
791 bool
compare_gimple_resx(const gresx * g1,const gresx * g2)792 func_checker::compare_gimple_resx (const gresx *g1, const gresx *g2)
793 {
794   return gimple_resx_region (g1) == gimple_resx_region (g2);
795 }
796 
797 /* Verifies for given GIMPLEs S1 and S2 that ASM statements are equivalent.
798    For the beginning, the pass only supports equality for
799    '__asm__ __volatile__ ("", "", "", "memory")'.  */
800 
801 bool
compare_gimple_asm(const gasm * g1,const gasm * g2)802 func_checker::compare_gimple_asm (const gasm *g1, const gasm *g2)
803 {
804   if (gimple_asm_volatile_p (g1) != gimple_asm_volatile_p (g2))
805     return false;
806 
807   if (gimple_asm_input_p (g1) != gimple_asm_input_p (g2))
808     return false;
809 
810   if (gimple_asm_inline_p (g1) != gimple_asm_inline_p (g2))
811     return false;
812 
813   if (gimple_asm_ninputs (g1) != gimple_asm_ninputs (g2))
814     return false;
815 
816   if (gimple_asm_noutputs (g1) != gimple_asm_noutputs (g2))
817     return false;
818 
819   /* We do not suppport goto ASM statement comparison.  */
820   if (gimple_asm_nlabels (g1) || gimple_asm_nlabels (g2))
821     return false;
822 
823   if (gimple_asm_nclobbers (g1) != gimple_asm_nclobbers (g2))
824     return false;
825 
826   if (strcmp (gimple_asm_string (g1), gimple_asm_string (g2)) != 0)
827     return return_false_with_msg ("ASM strings are different");
828 
829   for (unsigned i = 0; i < gimple_asm_ninputs (g1); i++)
830     {
831       tree input1 = gimple_asm_input_op (g1, i);
832       tree input2 = gimple_asm_input_op (g2, i);
833 
834       if (!compare_asm_inputs_outputs (input1, input2))
835 	return return_false_with_msg ("ASM input is different");
836     }
837 
838   for (unsigned i = 0; i < gimple_asm_noutputs (g1); i++)
839     {
840       tree output1 = gimple_asm_output_op (g1, i);
841       tree output2 = gimple_asm_output_op (g2, i);
842 
843       if (!compare_asm_inputs_outputs (output1, output2))
844 	return return_false_with_msg ("ASM output is different");
845     }
846 
847   for (unsigned i = 0; i < gimple_asm_nclobbers (g1); i++)
848     {
849       tree clobber1 = gimple_asm_clobber_op (g1, i);
850       tree clobber2 = gimple_asm_clobber_op (g2, i);
851 
852       if (!operand_equal_p (TREE_VALUE (clobber1), TREE_VALUE (clobber2),
853 			    OEP_ONLY_CONST))
854 	return return_false_with_msg ("ASM clobber is different");
855     }
856 
857   return true;
858 }
859 
860 } // ipa_icf_gimple namespace
861