Mercurial > hg > CbC > CbC_gcc
comparison gcc/ipa-icf-gimple.c @ 145:1830386684a0
gcc-9.2.0
author | anatofuz |
---|---|
date | Thu, 13 Feb 2020 11:34:05 +0900 |
parents | 84e7813d76e9 |
children |
comparison
equal
deleted
inserted
replaced
131:84e7813d76e9 | 145:1830386684a0 |
---|---|
1 /* Interprocedural Identical Code Folding pass | 1 /* Interprocedural Identical Code Folding pass |
2 Copyright (C) 2014-2018 Free Software Foundation, Inc. | 2 Copyright (C) 2014-2020 Free Software Foundation, Inc. |
3 | 3 |
4 Contributed by Jan Hubicka <hubicka@ucw.cz> and Martin Liska <mliska@suse.cz> | 4 Contributed by Jan Hubicka <hubicka@ucw.cz> and Martin Liska <mliska@suse.cz> |
5 | 5 |
6 This file is part of GCC. | 6 This file is part of GCC. |
7 | 7 |
29 #include "tree-pass.h" | 29 #include "tree-pass.h" |
30 #include "ssa.h" | 30 #include "ssa.h" |
31 #include "cgraph.h" | 31 #include "cgraph.h" |
32 #include "data-streamer.h" | 32 #include "data-streamer.h" |
33 #include "gimple-pretty-print.h" | 33 #include "gimple-pretty-print.h" |
34 #include "alias.h" | |
35 #include "fold-const.h" | 34 #include "fold-const.h" |
36 #include "gimple-iterator.h" | 35 #include "gimple-iterator.h" |
37 #include "ipa-utils.h" | 36 #include "ipa-utils.h" |
38 #include "tree-eh.h" | 37 #include "tree-eh.h" |
39 #include "builtins.h" | 38 #include "builtins.h" |
39 #include "cfgloop.h" | |
40 | 40 |
41 #include "ipa-icf-gimple.h" | 41 #include "ipa-icf-gimple.h" |
42 | 42 |
43 namespace ipa_icf_gimple { | 43 namespace ipa_icf_gimple { |
44 | 44 |
48 set IGNORE_LABELS to skip label comparison. | 48 set IGNORE_LABELS to skip label comparison. |
49 Similarly, IGNORE_SOURCE_DECLS and IGNORE_TARGET_DECLS are sets | 49 Similarly, IGNORE_SOURCE_DECLS and IGNORE_TARGET_DECLS are sets |
50 of declarations that can be skipped. */ | 50 of declarations that can be skipped. */ |
51 | 51 |
52 func_checker::func_checker (tree source_func_decl, tree target_func_decl, | 52 func_checker::func_checker (tree source_func_decl, tree target_func_decl, |
53 bool compare_polymorphic, | |
54 bool ignore_labels, | 53 bool ignore_labels, |
55 hash_set<symtab_node *> *ignored_source_nodes, | 54 hash_set<symtab_node *> *ignored_source_nodes, |
56 hash_set<symtab_node *> *ignored_target_nodes) | 55 hash_set<symtab_node *> *ignored_target_nodes) |
57 : m_source_func_decl (source_func_decl), m_target_func_decl (target_func_decl), | 56 : m_source_func_decl (source_func_decl), m_target_func_decl (target_func_decl), |
58 m_ignored_source_nodes (ignored_source_nodes), | 57 m_ignored_source_nodes (ignored_source_nodes), |
59 m_ignored_target_nodes (ignored_target_nodes), | 58 m_ignored_target_nodes (ignored_target_nodes), |
60 m_compare_polymorphic (compare_polymorphic), | |
61 m_ignore_labels (ignore_labels) | 59 m_ignore_labels (ignore_labels) |
62 { | 60 { |
63 function *source_func = DECL_STRUCT_FUNCTION (source_func_decl); | 61 function *source_func = DECL_STRUCT_FUNCTION (source_func_decl); |
64 function *target_func = DECL_STRUCT_FUNCTION (target_func_decl); | 62 function *target_func = DECL_STRUCT_FUNCTION (target_func_decl); |
65 | 63 |
85 } | 83 } |
86 | 84 |
87 /* Verifies that trees T1 and T2 are equivalent from perspective of ICF. */ | 85 /* Verifies that trees T1 and T2 are equivalent from perspective of ICF. */ |
88 | 86 |
89 bool | 87 bool |
90 func_checker::compare_ssa_name (tree t1, tree t2) | 88 func_checker::compare_ssa_name (const_tree t1, const_tree t2) |
91 { | 89 { |
92 gcc_assert (TREE_CODE (t1) == SSA_NAME); | 90 gcc_assert (TREE_CODE (t1) == SSA_NAME); |
93 gcc_assert (TREE_CODE (t2) == SSA_NAME); | 91 gcc_assert (TREE_CODE (t2) == SSA_NAME); |
94 | 92 |
95 unsigned i1 = SSA_NAME_VERSION (t1); | 93 unsigned i1 = SSA_NAME_VERSION (t1); |
108 if (SSA_NAME_IS_DEFAULT_DEF (t1)) | 106 if (SSA_NAME_IS_DEFAULT_DEF (t1)) |
109 { | 107 { |
110 tree b1 = SSA_NAME_VAR (t1); | 108 tree b1 = SSA_NAME_VAR (t1); |
111 tree b2 = SSA_NAME_VAR (t2); | 109 tree b2 = SSA_NAME_VAR (t2); |
112 | 110 |
113 if (b1 == NULL && b2 == NULL) | 111 return compare_operand (b1, b2); |
114 return true; | |
115 | |
116 if (b1 == NULL || b2 == NULL || TREE_CODE (b1) != TREE_CODE (b2)) | |
117 return return_false (); | |
118 | |
119 return compare_cst_or_decl (b1, b2); | |
120 } | 112 } |
121 | 113 |
122 return true; | 114 return true; |
123 } | 115 } |
124 | 116 |
145 | 137 |
146 /* Verification function for declaration trees T1 and T2 that | 138 /* Verification function for declaration trees T1 and T2 that |
147 come from functions FUNC1 and FUNC2. */ | 139 come from functions FUNC1 and FUNC2. */ |
148 | 140 |
149 bool | 141 bool |
150 func_checker::compare_decl (tree t1, tree t2) | 142 func_checker::compare_decl (const_tree t1, const_tree t2) |
151 { | 143 { |
152 if (!auto_var_in_fn_p (t1, m_source_func_decl) | 144 if (!auto_var_in_fn_p (t1, m_source_func_decl) |
153 || !auto_var_in_fn_p (t2, m_target_func_decl)) | 145 || !auto_var_in_fn_p (t2, m_target_func_decl)) |
154 return return_with_debug (t1 == t2); | 146 return return_with_debug (t1 == t2); |
155 | 147 |
159 return return_false_with_msg ("DECL_BY_REFERENCE flags are different"); | 151 return return_false_with_msg ("DECL_BY_REFERENCE flags are different"); |
160 | 152 |
161 if (!compatible_types_p (TREE_TYPE (t1), TREE_TYPE (t2))) | 153 if (!compatible_types_p (TREE_TYPE (t1), TREE_TYPE (t2))) |
162 return return_false (); | 154 return return_false (); |
163 | 155 |
164 /* TODO: we are actually too strict here. We only need to compare if | |
165 T1 can be used in polymorphic call. */ | |
166 if (TREE_ADDRESSABLE (t1) | |
167 && m_compare_polymorphic | |
168 && !compatible_polymorphic_types_p (TREE_TYPE (t1), TREE_TYPE (t2), | |
169 false)) | |
170 return return_false (); | |
171 | |
172 if ((t == VAR_DECL || t == PARM_DECL || t == RESULT_DECL) | |
173 && DECL_BY_REFERENCE (t1) | |
174 && m_compare_polymorphic | |
175 && !compatible_polymorphic_types_p (TREE_TYPE (t1), TREE_TYPE (t2), | |
176 true)) | |
177 return return_false (); | |
178 | |
179 bool existed_p; | 156 bool existed_p; |
180 | 157 const_tree &slot = m_decl_map.get_or_insert (t1, &existed_p); |
181 tree &slot = m_decl_map.get_or_insert (t1, &existed_p); | |
182 if (existed_p) | 158 if (existed_p) |
183 return return_with_debug (slot == t2); | 159 return return_with_debug (slot == t2); |
184 else | 160 else |
185 slot = t2; | 161 slot = t2; |
186 | 162 |
230 return return_false_with_msg ("restrict flags are different"); | 206 return return_false_with_msg ("restrict flags are different"); |
231 | 207 |
232 if (!types_compatible_p (t1, t2)) | 208 if (!types_compatible_p (t1, t2)) |
233 return return_false_with_msg ("types are not compatible"); | 209 return return_false_with_msg ("types are not compatible"); |
234 | 210 |
235 /* We do a lot of unnecesary matching of types that are not being | 211 return true; |
236 accessed and thus do not need to be compatible. In longer term we should | 212 } |
237 remove these checks on all types which are not accessed as memory | 213 |
238 locations. | 214 /* Function compare for equality given trees T1 and T2 which |
239 | 215 can be either a constant or a declaration type. */ |
240 For time being just avoid calling get_alias_set on types that are not | 216 |
241 having alias sets defined at all. */ | 217 void |
242 if (type_with_alias_set_p (t1) && type_with_alias_set_p (t2) | 218 func_checker::hash_operand (const_tree arg, inchash::hash &hstate, |
243 && get_alias_set (t1) != get_alias_set (t2)) | 219 unsigned int flags) |
244 return return_false_with_msg ("alias sets are different"); | 220 { |
245 | 221 if (arg == NULL_TREE) |
246 return true; | 222 { |
247 } | 223 hstate.merge_hash (0); |
248 | 224 return; |
249 /* Function compare for equality given memory operands T1 and T2. */ | 225 } |
250 | 226 |
251 bool | 227 switch (TREE_CODE (arg)) |
252 func_checker::compare_memory_operand (tree t1, tree t2) | 228 { |
253 { | 229 case FUNCTION_DECL: |
254 if (!t1 && !t2) | 230 case VAR_DECL: |
231 case LABEL_DECL: | |
232 case PARM_DECL: | |
233 case RESULT_DECL: | |
234 case CONST_DECL: | |
235 case SSA_NAME: | |
236 return; | |
237 case FIELD_DECL: | |
238 inchash::add_expr (DECL_FIELD_OFFSET (arg), hstate, flags); | |
239 inchash::add_expr (DECL_FIELD_BIT_OFFSET (arg), hstate, flags); | |
240 return; | |
241 default: | |
242 break; | |
243 } | |
244 | |
245 return operand_compare::hash_operand (arg, hstate, flags); | |
246 } | |
247 | |
248 bool | |
249 func_checker::operand_equal_p (const_tree t1, const_tree t2, | |
250 unsigned int flags) | |
251 { | |
252 bool r; | |
253 if (verify_hash_value (t1, t2, flags, &r)) | |
254 return r; | |
255 | |
256 if (t1 == t2) | |
255 return true; | 257 return true; |
256 else if (!t1 || !t2) | 258 else if (!t1 || !t2) |
257 return false; | 259 return false; |
258 | 260 |
259 ao_ref r1, r2; | 261 if (TREE_CODE (t1) != TREE_CODE (t2)) |
260 ao_ref_init (&r1, t1); | 262 return return_false (); |
261 ao_ref_init (&r2, t2); | |
262 | |
263 tree b1 = ao_ref_base (&r1); | |
264 tree b2 = ao_ref_base (&r2); | |
265 | |
266 bool source_is_memop = DECL_P (b1) || INDIRECT_REF_P (b1) | |
267 || TREE_CODE (b1) == MEM_REF | |
268 || TREE_CODE (b1) == TARGET_MEM_REF; | |
269 | |
270 bool target_is_memop = DECL_P (b2) || INDIRECT_REF_P (b2) | |
271 || TREE_CODE (b2) == MEM_REF | |
272 || TREE_CODE (b2) == TARGET_MEM_REF; | |
273 | |
274 /* Compare alias sets for memory operands. */ | |
275 if (source_is_memop && target_is_memop) | |
276 { | |
277 if (TREE_THIS_VOLATILE (t1) != TREE_THIS_VOLATILE (t2)) | |
278 return return_false_with_msg ("different operand volatility"); | |
279 | |
280 if (ao_ref_alias_set (&r1) != ao_ref_alias_set (&r2) | |
281 || ao_ref_base_alias_set (&r1) != ao_ref_base_alias_set (&r2)) | |
282 return return_false_with_msg ("ao alias sets are different"); | |
283 | |
284 /* We can't simply use get_object_alignment_1 on the full | |
285 reference as for accesses with variable indexes this reports | |
286 too conservative alignment. We also can't use the ao_ref_base | |
287 base objects as ao_ref_base happily strips MEM_REFs around | |
288 decls even though that may carry alignment info. */ | |
289 b1 = t1; | |
290 while (handled_component_p (b1)) | |
291 b1 = TREE_OPERAND (b1, 0); | |
292 b2 = t2; | |
293 while (handled_component_p (b2)) | |
294 b2 = TREE_OPERAND (b2, 0); | |
295 unsigned int align1, align2; | |
296 unsigned HOST_WIDE_INT tem; | |
297 get_object_alignment_1 (b1, &align1, &tem); | |
298 get_object_alignment_1 (b2, &align2, &tem); | |
299 if (align1 != align2) | |
300 return return_false_with_msg ("different access alignment"); | |
301 | |
302 /* Similarly we have to compare dependence info where equality | |
303 tells us we are safe (even some unequal values would be safe | |
304 but then we have to maintain a map of bases and cliques). */ | |
305 unsigned short clique1 = 0, base1 = 0, clique2 = 0, base2 = 0; | |
306 if (TREE_CODE (b1) == MEM_REF) | |
307 { | |
308 clique1 = MR_DEPENDENCE_CLIQUE (b1); | |
309 base1 = MR_DEPENDENCE_BASE (b1); | |
310 } | |
311 if (TREE_CODE (b2) == MEM_REF) | |
312 { | |
313 clique2 = MR_DEPENDENCE_CLIQUE (b2); | |
314 base2 = MR_DEPENDENCE_BASE (b2); | |
315 } | |
316 if (clique1 != clique2 || base1 != base2) | |
317 return return_false_with_msg ("different dependence info"); | |
318 } | |
319 | |
320 return compare_operand (t1, t2); | |
321 } | |
322 | |
323 /* Function compare for equality given trees T1 and T2 which | |
324 can be either a constant or a declaration type. */ | |
325 | |
326 bool | |
327 func_checker::compare_cst_or_decl (tree t1, tree t2) | |
328 { | |
329 bool ret; | |
330 | 263 |
331 switch (TREE_CODE (t1)) | 264 switch (TREE_CODE (t1)) |
332 { | 265 { |
333 case INTEGER_CST: | |
334 case COMPLEX_CST: | |
335 case VECTOR_CST: | |
336 case STRING_CST: | |
337 case REAL_CST: | |
338 { | |
339 ret = compatible_types_p (TREE_TYPE (t1), TREE_TYPE (t2)) | |
340 && operand_equal_p (t1, t2, OEP_ONLY_CONST); | |
341 return return_with_debug (ret); | |
342 } | |
343 case FUNCTION_DECL: | 266 case FUNCTION_DECL: |
344 /* All function decls are in the symbol table and known to match | 267 /* All function decls are in the symbol table and known to match |
345 before we start comparing bodies. */ | 268 before we start comparing bodies. */ |
346 return true; | 269 return true; |
347 case VAR_DECL: | 270 case VAR_DECL: |
348 return return_with_debug (compare_variable_decl (t1, t2)); | 271 return return_with_debug (compare_variable_decl (t1, t2)); |
349 case FIELD_DECL: | |
350 { | |
351 tree offset1 = DECL_FIELD_OFFSET (t1); | |
352 tree offset2 = DECL_FIELD_OFFSET (t2); | |
353 | |
354 tree bit_offset1 = DECL_FIELD_BIT_OFFSET (t1); | |
355 tree bit_offset2 = DECL_FIELD_BIT_OFFSET (t2); | |
356 | |
357 ret = compare_operand (offset1, offset2) | |
358 && compare_operand (bit_offset1, bit_offset2); | |
359 | |
360 return return_with_debug (ret); | |
361 } | |
362 case LABEL_DECL: | 272 case LABEL_DECL: |
363 { | 273 { |
364 if (t1 == t2) | |
365 return true; | |
366 | |
367 int *bb1 = m_label_bb_map.get (t1); | 274 int *bb1 = m_label_bb_map.get (t1); |
368 int *bb2 = m_label_bb_map.get (t2); | 275 int *bb2 = m_label_bb_map.get (t2); |
369 | |
370 /* Labels can point to another function (non-local GOTOs). */ | 276 /* Labels can point to another function (non-local GOTOs). */ |
371 return return_with_debug (bb1 != NULL && bb2 != NULL && *bb1 == *bb2); | 277 return return_with_debug (bb1 != NULL && bb2 != NULL && *bb1 == *bb2); |
372 } | 278 } |
279 | |
373 case PARM_DECL: | 280 case PARM_DECL: |
374 case RESULT_DECL: | 281 case RESULT_DECL: |
375 case CONST_DECL: | 282 case CONST_DECL: |
376 { | 283 return compare_decl (t1, t2); |
377 ret = compare_decl (t1, t2); | 284 case SSA_NAME: |
378 return return_with_debug (ret); | 285 return compare_ssa_name (t1, t2); |
379 } | |
380 default: | 286 default: |
381 gcc_unreachable (); | 287 break; |
382 } | 288 } |
289 | |
290 return operand_compare::operand_equal_p (t1, t2, flags); | |
383 } | 291 } |
384 | 292 |
385 /* Function responsible for comparison of various operands T1 and T2. | 293 /* Function responsible for comparison of various operands T1 and T2. |
386 If these components, from functions FUNC1 and FUNC2, are equal, true | 294 If these components, from functions FUNC1 and FUNC2, are equal, true |
387 is returned. */ | 295 is returned. */ |
388 | 296 |
389 bool | 297 bool |
390 func_checker::compare_operand (tree t1, tree t2) | 298 func_checker::compare_operand (tree t1, tree t2) |
391 { | 299 { |
392 tree x1, x2, y1, y2, z1, z2; | |
393 bool ret; | |
394 | |
395 if (!t1 && !t2) | 300 if (!t1 && !t2) |
396 return true; | 301 return true; |
397 else if (!t1 || !t2) | 302 else if (!t1 || !t2) |
398 return false; | 303 return false; |
399 | 304 if (operand_equal_p (t1, t2, OEP_MATCH_SIDE_EFFECTS)) |
400 tree tt1 = TREE_TYPE (t1); | 305 return true; |
401 tree tt2 = TREE_TYPE (t2); | 306 return return_false_with_msg ("operand_equal_p failed"); |
402 | |
403 if (!func_checker::compatible_types_p (tt1, tt2)) | |
404 return false; | |
405 | |
406 if (TREE_CODE (t1) != TREE_CODE (t2)) | |
407 return return_false (); | |
408 | |
409 switch (TREE_CODE (t1)) | |
410 { | |
411 case CONSTRUCTOR: | |
412 { | |
413 unsigned length1 = CONSTRUCTOR_NELTS (t1); | |
414 unsigned length2 = CONSTRUCTOR_NELTS (t2); | |
415 | |
416 if (length1 != length2) | |
417 return return_false (); | |
418 | |
419 for (unsigned i = 0; i < length1; i++) | |
420 if (!compare_operand (CONSTRUCTOR_ELT (t1, i)->value, | |
421 CONSTRUCTOR_ELT (t2, i)->value)) | |
422 return return_false(); | |
423 | |
424 return true; | |
425 } | |
426 case ARRAY_REF: | |
427 case ARRAY_RANGE_REF: | |
428 /* First argument is the array, second is the index. */ | |
429 x1 = TREE_OPERAND (t1, 0); | |
430 x2 = TREE_OPERAND (t2, 0); | |
431 y1 = TREE_OPERAND (t1, 1); | |
432 y2 = TREE_OPERAND (t2, 1); | |
433 | |
434 if (!compare_operand (array_ref_low_bound (t1), | |
435 array_ref_low_bound (t2))) | |
436 return return_false_with_msg (""); | |
437 if (!compare_operand (array_ref_element_size (t1), | |
438 array_ref_element_size (t2))) | |
439 return return_false_with_msg (""); | |
440 | |
441 if (!compare_operand (x1, x2)) | |
442 return return_false_with_msg (""); | |
443 return compare_operand (y1, y2); | |
444 case MEM_REF: | |
445 { | |
446 x1 = TREE_OPERAND (t1, 0); | |
447 x2 = TREE_OPERAND (t2, 0); | |
448 y1 = TREE_OPERAND (t1, 1); | |
449 y2 = TREE_OPERAND (t2, 1); | |
450 | |
451 /* See if operand is an memory access (the test originate from | |
452 gimple_load_p). | |
453 | |
454 In this case the alias set of the function being replaced must | |
455 be subset of the alias set of the other function. At the moment | |
456 we seek for equivalency classes, so simply require inclussion in | |
457 both directions. */ | |
458 | |
459 if (!func_checker::compatible_types_p (TREE_TYPE (x1), TREE_TYPE (x2))) | |
460 return return_false (); | |
461 | |
462 if (!compare_operand (x1, x2)) | |
463 return return_false_with_msg (""); | |
464 | |
465 /* Type of the offset on MEM_REF does not matter. */ | |
466 return known_eq (wi::to_poly_offset (y1), wi::to_poly_offset (y2)); | |
467 } | |
468 case COMPONENT_REF: | |
469 { | |
470 x1 = TREE_OPERAND (t1, 0); | |
471 x2 = TREE_OPERAND (t2, 0); | |
472 y1 = TREE_OPERAND (t1, 1); | |
473 y2 = TREE_OPERAND (t2, 1); | |
474 | |
475 ret = compare_operand (x1, x2) | |
476 && compare_cst_or_decl (y1, y2); | |
477 | |
478 return return_with_debug (ret); | |
479 } | |
480 /* Virtual table call. */ | |
481 case OBJ_TYPE_REF: | |
482 { | |
483 if (!compare_ssa_name (OBJ_TYPE_REF_EXPR (t1), OBJ_TYPE_REF_EXPR (t2))) | |
484 return return_false (); | |
485 if (opt_for_fn (m_source_func_decl, flag_devirtualize) | |
486 && virtual_method_call_p (t1)) | |
487 { | |
488 if (tree_to_uhwi (OBJ_TYPE_REF_TOKEN (t1)) | |
489 != tree_to_uhwi (OBJ_TYPE_REF_TOKEN (t2))) | |
490 return return_false_with_msg ("OBJ_TYPE_REF token mismatch"); | |
491 if (!types_same_for_odr (obj_type_ref_class (t1), | |
492 obj_type_ref_class (t2))) | |
493 return return_false_with_msg ("OBJ_TYPE_REF OTR type mismatch"); | |
494 if (!compare_operand (OBJ_TYPE_REF_OBJECT (t1), | |
495 OBJ_TYPE_REF_OBJECT (t2))) | |
496 return return_false_with_msg ("OBJ_TYPE_REF object mismatch"); | |
497 } | |
498 | |
499 return return_with_debug (true); | |
500 } | |
501 case IMAGPART_EXPR: | |
502 case REALPART_EXPR: | |
503 case ADDR_EXPR: | |
504 { | |
505 x1 = TREE_OPERAND (t1, 0); | |
506 x2 = TREE_OPERAND (t2, 0); | |
507 | |
508 ret = compare_operand (x1, x2); | |
509 return return_with_debug (ret); | |
510 } | |
511 case BIT_FIELD_REF: | |
512 { | |
513 x1 = TREE_OPERAND (t1, 0); | |
514 x2 = TREE_OPERAND (t2, 0); | |
515 y1 = TREE_OPERAND (t1, 1); | |
516 y2 = TREE_OPERAND (t2, 1); | |
517 z1 = TREE_OPERAND (t1, 2); | |
518 z2 = TREE_OPERAND (t2, 2); | |
519 | |
520 ret = compare_operand (x1, x2) | |
521 && compare_cst_or_decl (y1, y2) | |
522 && compare_cst_or_decl (z1, z2); | |
523 | |
524 return return_with_debug (ret); | |
525 } | |
526 case SSA_NAME: | |
527 return compare_ssa_name (t1, t2); | |
528 case INTEGER_CST: | |
529 case COMPLEX_CST: | |
530 case VECTOR_CST: | |
531 case STRING_CST: | |
532 case REAL_CST: | |
533 case FUNCTION_DECL: | |
534 case VAR_DECL: | |
535 case FIELD_DECL: | |
536 case LABEL_DECL: | |
537 case PARM_DECL: | |
538 case RESULT_DECL: | |
539 case CONST_DECL: | |
540 return compare_cst_or_decl (t1, t2); | |
541 default: | |
542 return return_false_with_msg ("Unknown TREE code reached"); | |
543 } | |
544 } | 307 } |
545 | 308 |
546 bool | 309 bool |
547 func_checker::compare_asm_inputs_outputs (tree t1, tree t2) | 310 func_checker::compare_asm_inputs_outputs (tree t1, tree t2) |
548 { | 311 { |
577 } | 340 } |
578 | 341 |
579 /* Verifies that trees T1 and T2 do correspond. */ | 342 /* Verifies that trees T1 and T2 do correspond. */ |
580 | 343 |
581 bool | 344 bool |
582 func_checker::compare_variable_decl (tree t1, tree t2) | 345 func_checker::compare_variable_decl (const_tree t1, const_tree t2) |
583 { | 346 { |
584 bool ret = false; | 347 bool ret = false; |
585 | 348 |
586 if (t1 == t2) | 349 if (t1 == t2) |
587 return true; | 350 return true; |
591 | 354 |
592 if (DECL_HARD_REGISTER (t1) != DECL_HARD_REGISTER (t2)) | 355 if (DECL_HARD_REGISTER (t1) != DECL_HARD_REGISTER (t2)) |
593 return return_false_with_msg ("DECL_HARD_REGISTER are different"); | 356 return return_false_with_msg ("DECL_HARD_REGISTER are different"); |
594 | 357 |
595 if (DECL_HARD_REGISTER (t1) | 358 if (DECL_HARD_REGISTER (t1) |
596 && DECL_ASSEMBLER_NAME (t1) != DECL_ASSEMBLER_NAME (t2)) | 359 && DECL_ASSEMBLER_NAME_RAW (t1) != DECL_ASSEMBLER_NAME_RAW (t2)) |
597 return return_false_with_msg ("HARD REGISTERS are different"); | 360 return return_false_with_msg ("HARD REGISTERS are different"); |
598 | 361 |
599 /* Symbol table variables are known to match before we start comparing | 362 /* Symbol table variables are known to match before we start comparing |
600 bodies. */ | 363 bodies. */ |
601 if (decl_in_symtab_p (t1)) | 364 if (decl_in_symtab_p (t1)) |
603 ret = compare_decl (t1, t2); | 366 ret = compare_decl (t1, t2); |
604 | 367 |
605 return return_with_debug (ret); | 368 return return_with_debug (ret); |
606 } | 369 } |
607 | 370 |
371 /* Compare loop information for basic blocks BB1 and BB2. */ | |
372 | |
373 bool | |
374 func_checker::compare_loops (basic_block bb1, basic_block bb2) | |
375 { | |
376 if ((bb1->loop_father == NULL) != (bb2->loop_father == NULL)) | |
377 return return_false (); | |
378 | |
379 class loop *l1 = bb1->loop_father; | |
380 class loop *l2 = bb2->loop_father; | |
381 if (l1 == NULL) | |
382 return true; | |
383 | |
384 if ((bb1 == l1->header) != (bb2 == l2->header)) | |
385 return return_false_with_msg ("header"); | |
386 if ((bb1 == l1->latch) != (bb2 == l2->latch)) | |
387 return return_false_with_msg ("latch"); | |
388 if (l1->simdlen != l2->simdlen) | |
389 return return_false_with_msg ("simdlen"); | |
390 if (l1->safelen != l2->safelen) | |
391 return return_false_with_msg ("safelen"); | |
392 if (l1->can_be_parallel != l2->can_be_parallel) | |
393 return return_false_with_msg ("can_be_parallel"); | |
394 if (l1->dont_vectorize != l2->dont_vectorize) | |
395 return return_false_with_msg ("dont_vectorize"); | |
396 if (l1->force_vectorize != l2->force_vectorize) | |
397 return return_false_with_msg ("force_vectorize"); | |
398 if (l1->unroll != l2->unroll) | |
399 return return_false_with_msg ("unroll"); | |
400 if (!compare_variable_decl (l1->simduid, l2->simduid)) | |
401 return return_false_with_msg ("simduid"); | |
402 | |
403 return true; | |
404 } | |
608 | 405 |
609 /* Function visits all gimple labels and creates corresponding | 406 /* Function visits all gimple labels and creates corresponding |
610 mapping between basic blocks and labels. */ | 407 mapping between basic blocks and labels. */ |
611 | 408 |
612 void | 409 void |
617 { | 414 { |
618 gimple *stmt = gsi_stmt (gsi); | 415 gimple *stmt = gsi_stmt (gsi); |
619 | 416 |
620 if (glabel *label_stmt = dyn_cast <glabel *> (stmt)) | 417 if (glabel *label_stmt = dyn_cast <glabel *> (stmt)) |
621 { | 418 { |
622 tree t = gimple_label_label (label_stmt); | 419 const_tree t = gimple_label_label (label_stmt); |
623 gcc_assert (TREE_CODE (t) == LABEL_DECL); | 420 gcc_assert (TREE_CODE (t) == LABEL_DECL); |
624 | 421 |
625 m_label_bb_map.put (t, bb->bb->index); | 422 m_label_bb_map.put (t, bb->bb->index); |
626 } | 423 } |
627 } | 424 } |
723 gsi_next_nondebug (&gsi1); | 520 gsi_next_nondebug (&gsi1); |
724 gsi_next_nondebug (&gsi2); | 521 gsi_next_nondebug (&gsi2); |
725 } | 522 } |
726 | 523 |
727 if (!gsi_end_p (gsi2)) | 524 if (!gsi_end_p (gsi2)) |
525 return return_false (); | |
526 | |
527 if (!compare_loops (bb1->bb, bb2->bb)) | |
728 return return_false (); | 528 return return_false (); |
729 | 529 |
730 return true; | 530 return true; |
731 } | 531 } |
732 | 532 |
779 for (i = 0; i < gimple_call_num_args (s1); ++i) | 579 for (i = 0; i < gimple_call_num_args (s1); ++i) |
780 { | 580 { |
781 t1 = gimple_call_arg (s1, i); | 581 t1 = gimple_call_arg (s1, i); |
782 t2 = gimple_call_arg (s2, i); | 582 t2 = gimple_call_arg (s2, i); |
783 | 583 |
784 if (!compare_memory_operand (t1, t2)) | 584 if (!compare_operand (t1, t2)) |
785 return return_false_with_msg ("memory operands are different"); | 585 return return_false_with_msg ("GIMPLE call operands are different"); |
786 } | 586 } |
787 | 587 |
788 /* Return value checking. */ | 588 /* Return value checking. */ |
789 t1 = gimple_get_lhs (s1); | 589 t1 = gimple_get_lhs (s1); |
790 t2 = gimple_get_lhs (s2); | 590 t2 = gimple_get_lhs (s2); |
791 | 591 |
792 return compare_memory_operand (t1, t2); | 592 return compare_operand (t1, t2); |
793 } | 593 } |
794 | 594 |
795 | 595 |
796 /* Verifies for given GIMPLEs S1 and S2 that | 596 /* Verifies for given GIMPLEs S1 and S2 that |
797 assignment statements are semantically equivalent. */ | 597 assignment statements are semantically equivalent. */ |
818 for (i = 0; i < gimple_num_ops (s1); i++) | 618 for (i = 0; i < gimple_num_ops (s1); i++) |
819 { | 619 { |
820 arg1 = gimple_op (s1, i); | 620 arg1 = gimple_op (s1, i); |
821 arg2 = gimple_op (s2, i); | 621 arg2 = gimple_op (s2, i); |
822 | 622 |
823 if (!compare_memory_operand (arg1, arg2)) | 623 /* LHS types of NOP_EXPR must be compatible. */ |
824 return return_false_with_msg ("memory operands are different"); | 624 if (CONVERT_EXPR_CODE_P (code1) && i == 0) |
625 { | |
626 if (!compatible_types_p (TREE_TYPE (arg1), TREE_TYPE (arg2))) | |
627 return return_false_with_msg ("GIMPLE NOP LHS type mismatch"); | |
628 } | |
629 | |
630 if (!compare_operand (arg1, arg2)) | |
631 return return_false_with_msg ("GIMPLE assignment operands " | |
632 "are different"); | |
825 } | 633 } |
826 | 634 |
827 | 635 |
828 return true; | 636 return true; |
829 } | 637 } |
850 return false; | 658 return false; |
851 | 659 |
852 t1 = gimple_cond_rhs (s1); | 660 t1 = gimple_cond_rhs (s1); |
853 t2 = gimple_cond_rhs (s2); | 661 t2 = gimple_cond_rhs (s2); |
854 | 662 |
855 return compare_operand (t1, t2); | |
856 } | |
857 | |
858 /* Verifies that tree labels T1 and T2 correspond in FUNC1 and FUNC2. */ | |
859 | |
860 bool | |
861 func_checker::compare_tree_ssa_label (tree t1, tree t2) | |
862 { | |
863 return compare_operand (t1, t2); | 663 return compare_operand (t1, t2); |
864 } | 664 } |
865 | 665 |
866 /* Verifies for given GIMPLE_LABEL stmts S1 and S2 that | 666 /* Verifies for given GIMPLE_LABEL stmts S1 and S2 that |
867 label statements are semantically equivalent. */ | 667 label statements are semantically equivalent. */ |
991 return false; | 791 return false; |
992 | 792 |
993 if (gimple_asm_input_p (g1) != gimple_asm_input_p (g2)) | 793 if (gimple_asm_input_p (g1) != gimple_asm_input_p (g2)) |
994 return false; | 794 return false; |
995 | 795 |
796 if (gimple_asm_inline_p (g1) != gimple_asm_inline_p (g2)) | |
797 return false; | |
798 | |
996 if (gimple_asm_ninputs (g1) != gimple_asm_ninputs (g2)) | 799 if (gimple_asm_ninputs (g1) != gimple_asm_ninputs (g2)) |
997 return false; | 800 return false; |
998 | 801 |
999 if (gimple_asm_noutputs (g1) != gimple_asm_noutputs (g2)) | 802 if (gimple_asm_noutputs (g1) != gimple_asm_noutputs (g2)) |
1000 return false; | 803 return false; |