]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/ipa-icf-gimple.c
[Ada] Improved support for aspect alignment in CCG
[thirdparty/gcc.git] / gcc / ipa-icf-gimple.c
CommitLineData
b84d4347 1/* Interprocedural Identical Code Folding pass
8d9254fc 2 Copyright (C) 2014-2020 Free Software Foundation, Inc.
b84d4347
ML
3
4 Contributed by Jan Hubicka <hubicka@ucw.cz> and Martin Liska <mliska@suse.cz>
5
6This file is part of GCC.
7
8GCC is free software; you can redistribute it and/or modify it under
9the terms of the GNU General Public License as published by the Free
10Software Foundation; either version 3, or (at your option) any later
11version.
12
13GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14WARRANTY; without even the implied warranty of MERCHANTABILITY or
15FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16for more details.
17
18You should have received a copy of the GNU General Public License
19along 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"
c7131fb2 25#include "backend.h"
957060b5 26#include "rtl.h"
40e23961 27#include "tree.h"
b84d4347 28#include "gimple.h"
957060b5 29#include "tree-pass.h"
c7131fb2 30#include "ssa.h"
957060b5
AM
31#include "cgraph.h"
32#include "data-streamer.h"
33#include "gimple-pretty-print.h"
c7131fb2 34#include "fold-const.h"
b84d4347 35#include "gimple-iterator.h"
b84d4347 36#include "ipa-utils.h"
b84d4347 37#include "tree-eh.h"
d366a1a7 38#include "builtins.h"
8d2a3107 39#include "cfgloop.h"
55a73802 40#include "attribs.h"
b84d4347
ML
41
42#include "ipa-icf-gimple.h"
b84d4347
ML
43
44namespace 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
53func_checker::func_checker (tree source_func_decl, tree target_func_decl,
b84d4347
ML
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),
b84d4347
ML
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
80func_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
88bool
3f85ff83 89func_checker::compare_ssa_name (const_tree t1, const_tree t2)
b84d4347 90{
520b3022
ML
91 gcc_assert (TREE_CODE (t1) == SSA_NAME);
92 gcc_assert (TREE_CODE (t2) == SSA_NAME);
93
b84d4347
ML
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
520b3022
ML
107 if (SSA_NAME_IS_DEFAULT_DEF (t1))
108 {
109 tree b1 = SSA_NAME_VAR (t1);
110 tree b2 = SSA_NAME_VAR (t2);
111
938bba61 112 return compare_operand (b1, b2);
520b3022
ML
113 }
114
b84d4347
ML
115 return true;
116}
117
118/* Verification function for edges E1 and E2. */
119
120bool
121func_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
142bool
3f85ff83 143func_checker::compare_decl (const_tree t1, const_tree t2)
b84d4347
ML
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
060cfff4
JH
154 if (!compatible_types_p (TREE_TYPE (t1), TREE_TYPE (t2)))
155 return return_false ();
156
b84d4347 157 bool existed_p;
3f85ff83 158 const_tree &slot = m_decl_map.get_or_insert (t1, &existed_p);
b84d4347
ML
159 if (existed_p)
160 return return_with_debug (slot == t2);
161 else
162 slot = t2;
163
164 return true;
165}
166
060cfff4
JH
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
171bool
172func_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
b84d4347 199/* Return true if types are compatible from perspective of ICF. */
520b3022 200bool
060cfff4 201func_checker::compatible_types_p (tree t1, tree t2)
b84d4347
ML
202{
203 if (TREE_CODE (t1) != TREE_CODE (t2))
204 return return_false_with_msg ("different tree types");
205
34b42fb0
ML
206 if (TYPE_RESTRICT (t1) != TYPE_RESTRICT (t2))
207 return return_false_with_msg ("restrict flags are different");
208
b84d4347
ML
209 if (!types_compatible_p (t1, t2))
210 return return_false_with_msg ("types are not compatible");
211
b84d4347
ML
212 return true;
213}
214
520b3022
ML
215/* Function compare for equality given trees T1 and T2 which
216 can be either a constant or a declaration type. */
217
8a319aa3
ML
218void
219func_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;
7edcaa0b
ML
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;
8a319aa3
ML
242 default:
243 break;
244 }
245
246 return operand_compare::hash_operand (arg, hstate, flags);
247}
248
b84d4347 249bool
8a319aa3
ML
250func_checker::operand_equal_p (const_tree t1, const_tree t2,
251 unsigned int flags)
b84d4347 252{
8a319aa3
ML
253 bool r;
254 if (verify_hash_value (t1, t2, flags, &r))
255 return r;
b84d4347 256
8a319aa3 257 if (t1 == t2)
b84d4347
ML
258 return true;
259 else if (!t1 || !t2)
260 return false;
261
b84d4347
ML
262 if (TREE_CODE (t1) != TREE_CODE (t2))
263 return return_false ();
264
265 switch (TREE_CODE (t1))
266 {
8a319aa3
ML
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:
3f85ff83 272 return return_with_debug (compare_variable_decl (t1, t2));
8a319aa3 273 case LABEL_DECL:
6d244704 274 {
3f85ff83
ML
275 int *bb1 = m_label_bb_map.get (t1);
276 int *bb2 = m_label_bb_map.get (t2);
8a319aa3
ML
277 /* Labels can point to another function (non-local GOTOs). */
278 return return_with_debug (bb1 != NULL && bb2 != NULL && *bb1 == *bb2);
6d244704 279 }
b84d4347 280
8a319aa3
ML
281 case PARM_DECL:
282 case RESULT_DECL:
283 case CONST_DECL:
3f85ff83 284 return compare_decl (t1, t2);
8a319aa3 285 case SSA_NAME:
3f85ff83 286 return compare_ssa_name (t1, t2);
8a319aa3
ML
287 default:
288 break;
289 }
b84d4347 290
8a319aa3
ML
291 return operand_compare::operand_equal_p (t1, t2, flags);
292}
217c08c5 293
8a319aa3
ML
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. */
217c08c5 297
8a319aa3
ML
298bool
299func_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");
b84d4347
ML
308}
309
b84d4347 310bool
6cc30cb4 311func_checker::compare_asm_inputs_outputs (tree t1, tree t2)
b84d4347
ML
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
6cc30cb4
ML
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
b84d4347
ML
334 t2 = TREE_CHAIN (t2);
335 }
336
337 if (t2)
338 return return_false ();
339
340 return true;
341}
342
b84d4347
ML
343/* Verifies that trees T1 and T2 do correspond. */
344
345bool
3f85ff83 346func_checker::compare_variable_decl (const_tree t1, const_tree t2)
b84d4347
ML
347{
348 bool ret = false;
349
350 if (t1 == t2)
351 return true;
352
e8fb91a8
ML
353 if (DECL_ALIGN (t1) != DECL_ALIGN (t2))
354 return return_false_with_msg ("alignments are different");
355
b4f26d91
ML
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)
3f85ff83 360 && DECL_ASSEMBLER_NAME_RAW (t1) != DECL_ASSEMBLER_NAME_RAW (t2))
b4f26d91
ML
361 return return_false_with_msg ("HARD REGISTERS are different");
362
b6cddc7f
ML
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);
b84d4347
ML
367 ret = compare_decl (t1, t2);
368
369 return return_with_debug (ret);
370}
371
8d2a3107
ML
372/* Compare loop information for basic blocks BB1 and BB2. */
373
374bool
375func_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
99b1c316
MS
380 class loop *l1 = bb1->loop_father;
381 class loop *l2 = bb2->loop_father;
8d2a3107
ML
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");
75efe9cb
RB
399 if (l1->finite_p != l2->finite_p)
400 return return_false_with_msg ("finite_p");
8d2a3107
ML
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}
47a668cd
ML
408
409/* Function visits all gimple labels and creates corresponding
410 mapping between basic blocks and labels. */
411
b84d4347
ML
412void
413func_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 {
355fe088 418 gimple *stmt = gsi_stmt (gsi);
b84d4347 419
538dd0b7 420 if (glabel *label_stmt = dyn_cast <glabel *> (stmt))
b84d4347 421 {
3f85ff83 422 const_tree t = gimple_label_label (label_stmt);
b84d4347
ML
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
b607f49b 435 is utilized by every statement-by-statement comparison function. */
b84d4347
ML
436
437bool
438func_checker::compare_bb (sem_bb *bb1, sem_bb *bb2)
439{
b84d4347 440 gimple_stmt_iterator gsi1, gsi2;
355fe088 441 gimple *s1, *s2;
b84d4347 442
65f4b875
AO
443 gsi1 = gsi_start_nondebug_bb (bb1->bb);
444 gsi2 = gsi_start_nondebug_bb (bb2->bb);
b84d4347 445
42c0b54d 446 while (!gsi_end_p (gsi1))
b84d4347 447 {
42c0b54d
ML
448 if (gsi_end_p (gsi2))
449 return return_false ();
b84d4347
ML
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:
538dd0b7
DM
468 if (!compare_gimple_call (as_a <gcall *> (s1),
469 as_a <gcall *> (s2)))
b84d4347
ML
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:
538dd0b7
DM
481 if (!compare_gimple_switch (as_a <gswitch *> (s1),
482 as_a <gswitch *> (s2)))
b84d4347
ML
483 return return_different_stmts (s1, s2, "GIMPLE_SWITCH");
484 break;
485 case GIMPLE_DEBUG:
366ee94b 486 break;
b84d4347 487 case GIMPLE_EH_DISPATCH:
366ee94b
JJ
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");
b84d4347
ML
491 break;
492 case GIMPLE_RESX:
538dd0b7
DM
493 if (!compare_gimple_resx (as_a <gresx *> (s1),
494 as_a <gresx *> (s2)))
b84d4347
ML
495 return return_different_stmts (s1, s2, "GIMPLE_RESX");
496 break;
497 case GIMPLE_LABEL:
538dd0b7
DM
498 if (!compare_gimple_label (as_a <glabel *> (s1),
499 as_a <glabel *> (s2)))
b84d4347
ML
500 return return_different_stmts (s1, s2, "GIMPLE_LABEL");
501 break;
502 case GIMPLE_RETURN:
538dd0b7
DM
503 if (!compare_gimple_return (as_a <greturn *> (s1),
504 as_a <greturn *> (s2)))
b84d4347
ML
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:
538dd0b7
DM
512 if (!compare_gimple_asm (as_a <gasm *> (s1),
513 as_a <gasm *> (s2)))
b84d4347
ML
514 return return_different_stmts (s1, s2, "GIMPLE_ASM");
515 break;
516 case GIMPLE_PREDICT:
517 case GIMPLE_NOP:
366ee94b 518 break;
b84d4347
ML
519 default:
520 return return_false_with_msg ("Unknown GIMPLE code reached");
521 }
522
42c0b54d
ML
523 gsi_next_nondebug (&gsi1);
524 gsi_next_nondebug (&gsi2);
b84d4347
ML
525 }
526
42c0b54d
ML
527 if (!gsi_end_p (gsi2))
528 return return_false ();
529
8d2a3107
ML
530 if (!compare_loops (bb1->bb, bb2->bb))
531 return return_false ();
532
b84d4347
ML
533 return true;
534}
535
536/* Verifies for given GIMPLEs S1 and S2 that
537 call statements are semantically equivalent. */
538
539bool
538dd0b7 540func_checker::compare_gimple_call (gcall *s1, gcall *s2)
b84d4347
ML
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
b607f49b
JJ
548 t1 = gimple_call_fn (s1);
549 t2 = gimple_call_fn (s2);
b84d4347 550 if (!compare_operand (t1, t2))
b607f49b
JJ
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)
31db0fe0 560 || gimple_call_alloca_for_var_p (s1) != gimple_call_alloca_for_var_p (s2))
b607f49b
JJ
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
55a73802
ML
574 if (fntype1 && fntype2 && comp_type_attributes (fntype1, fntype2) != 1)
575 return return_false_with_msg ("different fntype attributes");
576
b607f49b
JJ
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");
b84d4347
ML
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
938bba61 590 if (!compare_operand (t1, t2))
5d0152bf 591 return return_false_with_msg ("GIMPLE call operands are different");
b84d4347
ML
592 }
593
594 /* Return value checking. */
595 t1 = gimple_get_lhs (s1);
596 t2 = gimple_get_lhs (s2);
597
938bba61 598 return compare_operand (t1, t2);
b84d4347
ML
599}
600
601
602/* Verifies for given GIMPLEs S1 and S2 that
603 assignment statements are semantically equivalent. */
604
605bool
355fe088 606func_checker::compare_gimple_assign (gimple *s1, gimple *s2)
b84d4347
ML
607{
608 tree arg1, arg2;
609 tree_code code1, code2;
610 unsigned i;
611
612 code1 = gimple_expr_code (s1);
613 code2 = gimple_expr_code (s2);
614
615 if (code1 != code2)
616 return false;
617
618 code1 = gimple_assign_rhs_code (s1);
619 code2 = gimple_assign_rhs_code (s2);
620
621 if (code1 != code2)
622 return false;
623
624 for (i = 0; i < gimple_num_ops (s1); i++)
625 {
626 arg1 = gimple_op (s1, i);
627 arg2 = gimple_op (s2, i);
628
08afe87b
ML
629 /* Compare types for LHS. */
630 if (i == 0)
44609614
ML
631 {
632 if (!compatible_types_p (TREE_TYPE (arg1), TREE_TYPE (arg2)))
633 return return_false_with_msg ("GIMPLE NOP LHS type mismatch");
634 }
635
938bba61 636 if (!compare_operand (arg1, arg2))
5d0152bf
ML
637 return return_false_with_msg ("GIMPLE assignment operands "
638 "are different");
b84d4347
ML
639 }
640
641
642 return true;
643}
644
645/* Verifies for given GIMPLEs S1 and S2 that
646 condition statements are semantically equivalent. */
647
648bool
355fe088 649func_checker::compare_gimple_cond (gimple *s1, gimple *s2)
b84d4347
ML
650{
651 tree t1, t2;
652 tree_code code1, code2;
653
654 code1 = gimple_expr_code (s1);
655 code2 = gimple_expr_code (s2);
656
657 if (code1 != code2)
658 return false;
659
660 t1 = gimple_cond_lhs (s1);
661 t2 = gimple_cond_lhs (s2);
662
663 if (!compare_operand (t1, t2))
664 return false;
665
666 t1 = gimple_cond_rhs (s1);
667 t2 = gimple_cond_rhs (s2);
668
669 return compare_operand (t1, t2);
670}
671
538dd0b7 672/* Verifies for given GIMPLE_LABEL stmts S1 and S2 that
b84d4347
ML
673 label statements are semantically equivalent. */
674
675bool
538dd0b7 676func_checker::compare_gimple_label (const glabel *g1, const glabel *g2)
b84d4347
ML
677{
678 if (m_ignore_labels)
679 return true;
680
681 tree t1 = gimple_label_label (g1);
682 tree t2 = gimple_label_label (g2);
683
684 if (FORCED_LABEL (t1) || FORCED_LABEL (t2))
685 return return_false_with_msg ("FORCED_LABEL");
686
47a668cd
ML
687 /* As the pass build BB to label mapping, no further check is needed. */
688 return true;
b84d4347
ML
689}
690
538dd0b7 691/* Verifies for given GIMPLE_SWITCH stmts S1 and S2 that
b84d4347
ML
692 switch statements are semantically equivalent. */
693
694bool
538dd0b7 695func_checker::compare_gimple_switch (const gswitch *g1, const gswitch *g2)
b84d4347
ML
696{
697 unsigned lsize1, lsize2, i;
698
699 lsize1 = gimple_switch_num_labels (g1);
700 lsize2 = gimple_switch_num_labels (g2);
701
702 if (lsize1 != lsize2)
703 return false;
704
705 tree t1 = gimple_switch_index (g1);
706 tree t2 = gimple_switch_index (g2);
707
708 if (!compare_operand (t1, t2))
709 return false;
710
711 for (i = 0; i < lsize1; i++)
712 {
713 tree label1 = gimple_switch_label (g1, i);
714 tree label2 = gimple_switch_label (g2, i);
715
fdaaeea1
ML
716 /* Label LOW and HIGH comparison. */
717 tree low1 = CASE_LOW (label1);
718 tree low2 = CASE_LOW (label2);
719
720 if (!tree_int_cst_equal (low1, low2))
721 return return_false_with_msg ("case low values are different");
722
723 tree high1 = CASE_HIGH (label1);
724 tree high2 = CASE_HIGH (label2);
725
726 if (!tree_int_cst_equal (high1, high2))
727 return return_false_with_msg ("case high values are different");
728
b84d4347
ML
729 if (TREE_CODE (label1) == CASE_LABEL_EXPR
730 && TREE_CODE (label2) == CASE_LABEL_EXPR)
731 {
732 label1 = CASE_LABEL (label1);
733 label2 = CASE_LABEL (label2);
734
735 if (!compare_operand (label1, label2))
736 return return_false_with_msg ("switch label_exprs are different");
737 }
738 else if (!tree_int_cst_equal (label1, label2))
739 return return_false_with_msg ("switch labels are different");
740 }
741
742 return true;
743}
744
538dd0b7 745/* Verifies for given GIMPLE_RETURN stmts S1 and S2 that
b84d4347
ML
746 return statements are semantically equivalent. */
747
748bool
538dd0b7 749func_checker::compare_gimple_return (const greturn *g1, const greturn *g2)
b84d4347
ML
750{
751 tree t1, t2;
752
753 t1 = gimple_return_retval (g1);
754 t2 = gimple_return_retval (g2);
755
756 /* Void return type. */
757 if (t1 == NULL && t2 == NULL)
758 return true;
759 else
760 return compare_operand (t1, t2);
761}
762
763/* Verifies for given GIMPLEs S1 and S2 that
764 goto statements are semantically equivalent. */
765
766bool
355fe088 767func_checker::compare_gimple_goto (gimple *g1, gimple *g2)
b84d4347
ML
768{
769 tree dest1, dest2;
770
771 dest1 = gimple_goto_dest (g1);
772 dest2 = gimple_goto_dest (g2);
773
774 if (TREE_CODE (dest1) != TREE_CODE (dest2) || TREE_CODE (dest1) != SSA_NAME)
775 return false;
776
777 return compare_operand (dest1, dest2);
778}
779
538dd0b7 780/* Verifies for given GIMPLE_RESX stmts S1 and S2 that
b84d4347
ML
781 resx statements are semantically equivalent. */
782
783bool
538dd0b7 784func_checker::compare_gimple_resx (const gresx *g1, const gresx *g2)
b84d4347
ML
785{
786 return gimple_resx_region (g1) == gimple_resx_region (g2);
787}
788
789/* Verifies for given GIMPLEs S1 and S2 that ASM statements are equivalent.
790 For the beginning, the pass only supports equality for
791 '__asm__ __volatile__ ("", "", "", "memory")'. */
792
793bool
538dd0b7 794func_checker::compare_gimple_asm (const gasm *g1, const gasm *g2)
b84d4347
ML
795{
796 if (gimple_asm_volatile_p (g1) != gimple_asm_volatile_p (g2))
797 return false;
798
a20b6691
BE
799 if (gimple_asm_input_p (g1) != gimple_asm_input_p (g2))
800 return false;
801
5b76e75f
SB
802 if (gimple_asm_inline_p (g1) != gimple_asm_inline_p (g2))
803 return false;
804
b84d4347
ML
805 if (gimple_asm_ninputs (g1) != gimple_asm_ninputs (g2))
806 return false;
807
808 if (gimple_asm_noutputs (g1) != gimple_asm_noutputs (g2))
809 return false;
810
811 /* We do not suppport goto ASM statement comparison. */
812 if (gimple_asm_nlabels (g1) || gimple_asm_nlabels (g2))
813 return false;
814
815 if (gimple_asm_nclobbers (g1) != gimple_asm_nclobbers (g2))
816 return false;
817
13f659d4
ML
818 if (strcmp (gimple_asm_string (g1), gimple_asm_string (g2)) != 0)
819 return return_false_with_msg ("ASM strings are different");
820
b84d4347
ML
821 for (unsigned i = 0; i < gimple_asm_ninputs (g1); i++)
822 {
823 tree input1 = gimple_asm_input_op (g1, i);
824 tree input2 = gimple_asm_input_op (g2, i);
825
6cc30cb4 826 if (!compare_asm_inputs_outputs (input1, input2))
b84d4347
ML
827 return return_false_with_msg ("ASM input is different");
828 }
829
830 for (unsigned i = 0; i < gimple_asm_noutputs (g1); i++)
831 {
832 tree output1 = gimple_asm_output_op (g1, i);
833 tree output2 = gimple_asm_output_op (g2, i);
834
6cc30cb4 835 if (!compare_asm_inputs_outputs (output1, output2))
b84d4347
ML
836 return return_false_with_msg ("ASM output is different");
837 }
838
839 for (unsigned i = 0; i < gimple_asm_nclobbers (g1); i++)
840 {
841 tree clobber1 = gimple_asm_clobber_op (g1, i);
842 tree clobber2 = gimple_asm_clobber_op (g2, i);
843
844 if (!operand_equal_p (TREE_VALUE (clobber1), TREE_VALUE (clobber2),
845 OEP_ONLY_CONST))
846 return return_false_with_msg ("ASM clobber is different");
847 }
848
849 return true;
850}
851
852} // ipa_icf_gimple namespace