Branch data Line data Source code
1 : : /* Interprocedural Identical Code Folding pass
2 : : Copyright (C) 2014-2024 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 : : #include "gimple-walk.h"
42 : : #include "tree-sra.h"
43 : :
44 : : #include "tree-ssa-alias-compare.h"
45 : : #include "alloc-pool.h"
46 : : #include "symbol-summary.h"
47 : : #include "ipa-icf-gimple.h"
48 : : #include "sreal.h"
49 : : #include "ipa-cp.h"
50 : : #include "ipa-prop.h"
51 : :
52 : : namespace ipa_icf_gimple {
53 : :
54 : : /* Initialize internal structures for a given SOURCE_FUNC_DECL and
55 : : TARGET_FUNC_DECL. Strict polymorphic comparison is processed if
56 : : an option COMPARE_POLYMORPHIC is true. For special cases, one can
57 : : set IGNORE_LABELS to skip label comparison.
58 : : Similarly, IGNORE_SOURCE_DECLS and IGNORE_TARGET_DECLS are sets
59 : : of declarations that can be skipped. */
60 : :
61 : 118176 : func_checker::func_checker (tree source_func_decl, tree target_func_decl,
62 : : bool ignore_labels, bool tbaa,
63 : : hash_set<symtab_node *> *ignored_source_nodes,
64 : 118176 : hash_set<symtab_node *> *ignored_target_nodes)
65 : 118176 : : m_source_func_decl (source_func_decl), m_target_func_decl (target_func_decl),
66 : 118176 : m_ignored_source_nodes (ignored_source_nodes),
67 : 118176 : m_ignored_target_nodes (ignored_target_nodes),
68 : 118176 : m_ignore_labels (ignore_labels), m_tbaa (tbaa),
69 : 118176 : m_total_scalarization_limit_known_p (false)
70 : : {
71 : 118176 : function *source_func = DECL_STRUCT_FUNCTION (source_func_decl);
72 : 118176 : function *target_func = DECL_STRUCT_FUNCTION (target_func_decl);
73 : :
74 : 118176 : unsigned ssa_source = SSANAMES (source_func)->length ();
75 : 118176 : unsigned ssa_target = SSANAMES (target_func)->length ();
76 : :
77 : 118176 : m_source_ssa_names.create (ssa_source);
78 : 118176 : m_target_ssa_names.create (ssa_target);
79 : :
80 : 1017173 : for (unsigned i = 0; i < ssa_source; i++)
81 : 898997 : m_source_ssa_names.safe_push (-1);
82 : :
83 : 1016830 : for (unsigned i = 0; i < ssa_target; i++)
84 : 898654 : m_target_ssa_names.safe_push (-1);
85 : 118176 : }
86 : :
87 : : /* Memory release routine. */
88 : :
89 : 481537 : func_checker::~func_checker ()
90 : : {
91 : 363361 : m_source_ssa_names.release();
92 : 363361 : m_target_ssa_names.release();
93 : 481537 : }
94 : :
95 : : /* Verifies that trees T1 and T2 are equivalent from perspective of ICF. */
96 : :
97 : : bool
98 : 1141157 : func_checker::compare_ssa_name (const_tree t1, const_tree t2)
99 : : {
100 : 1141157 : gcc_assert (TREE_CODE (t1) == SSA_NAME);
101 : 1141157 : gcc_assert (TREE_CODE (t2) == SSA_NAME);
102 : :
103 : 1141157 : unsigned i1 = SSA_NAME_VERSION (t1);
104 : 1141157 : unsigned i2 = SSA_NAME_VERSION (t2);
105 : :
106 : 1141157 : if (SSA_NAME_IS_DEFAULT_DEF (t1) != SSA_NAME_IS_DEFAULT_DEF (t2))
107 : : return false;
108 : :
109 : 1141157 : if (m_source_ssa_names[i1] == -1)
110 : 338307 : m_source_ssa_names[i1] = i2;
111 : 802850 : else if (m_source_ssa_names[i1] != (int) i2)
112 : : return false;
113 : :
114 : 1140984 : if(m_target_ssa_names[i2] == -1)
115 : 338303 : m_target_ssa_names[i2] = i1;
116 : 802681 : else if (m_target_ssa_names[i2] != (int) i1)
117 : : return false;
118 : :
119 : 1140980 : if (SSA_NAME_IS_DEFAULT_DEF (t1))
120 : : {
121 : 239399 : tree b1 = SSA_NAME_VAR (t1);
122 : 239399 : tree b2 = SSA_NAME_VAR (t2);
123 : :
124 : 239399 : return compare_operand (b1, b2, OP_NORMAL);
125 : : }
126 : :
127 : : return true;
128 : : }
129 : :
130 : : /* Verification function for edges E1 and E2. */
131 : :
132 : : bool
133 : 488655 : func_checker::compare_edge (edge e1, edge e2)
134 : : {
135 : 488655 : if (e1->flags != e2->flags)
136 : : return false;
137 : :
138 : 488655 : bool existed_p;
139 : :
140 : 488655 : edge &slot = m_edge_map.get_or_insert (e1, &existed_p);
141 : 488655 : if (existed_p)
142 : 218804 : return return_with_debug (slot == e2);
143 : : else
144 : 269851 : slot = e2;
145 : :
146 : : /* TODO: filter edge probabilities for profile feedback match. */
147 : :
148 : 269851 : return true;
149 : : }
150 : :
151 : : /* Verification function for declaration trees T1 and T2 that
152 : : come from functions FUNC1 and FUNC2. */
153 : :
154 : : bool
155 : 485210 : func_checker::compare_decl (const_tree t1, const_tree t2)
156 : : {
157 : 485210 : if (!auto_var_in_fn_p (t1, m_source_func_decl)
158 : 485210 : || !auto_var_in_fn_p (t2, m_target_func_decl))
159 : 6 : return return_with_debug (t1 == t2);
160 : :
161 : 485204 : tree_code t = TREE_CODE (t1);
162 : 485204 : if ((t == VAR_DECL || t == PARM_DECL || t == RESULT_DECL)
163 : 485204 : && DECL_BY_REFERENCE (t1) != DECL_BY_REFERENCE (t2))
164 : 0 : return return_false_with_msg ("DECL_BY_REFERENCE flags are different");
165 : :
166 : : /* We do not really need to check types of variables, since they are just
167 : : blocks of memory and we verify types of the accesses to them.
168 : : However do compare types of other kinds of decls
169 : : (parm decls and result decl types may affect ABI convetions). */
170 : 485204 : if (t != VAR_DECL)
171 : : {
172 : 407753 : if (!compatible_types_p (TREE_TYPE (t1), TREE_TYPE (t2)))
173 : 0 : return return_false ();
174 : : }
175 : : else
176 : : {
177 : 77451 : if (!operand_equal_p (DECL_SIZE (t1), DECL_SIZE (t2),
178 : : OEP_MATCH_SIDE_EFFECTS))
179 : 0 : return return_false_with_msg ("DECL_SIZEs are different");
180 : : }
181 : :
182 : 485204 : bool existed_p;
183 : 485204 : const_tree &slot = m_decl_map.get_or_insert (t1, &existed_p);
184 : 485204 : if (existed_p)
185 : 315447 : return return_with_debug (slot == t2);
186 : : else
187 : 169757 : slot = t2;
188 : :
189 : 169757 : return true;
190 : : }
191 : :
192 : : /* Return true if T1 and T2 are same for purposes of ipa-polymorphic-call
193 : : analysis. COMPARE_PTR indicates if types of pointers needs to be
194 : : considered. */
195 : :
196 : : bool
197 : 10850 : func_checker::compatible_polymorphic_types_p (tree t1, tree t2,
198 : : bool compare_ptr)
199 : : {
200 : 10850 : gcc_assert (TREE_CODE (t1) != FUNCTION_TYPE && TREE_CODE (t1) != METHOD_TYPE);
201 : :
202 : : /* Pointer types generally give no information. */
203 : 10850 : if (POINTER_TYPE_P (t1))
204 : : {
205 : 0 : if (!compare_ptr)
206 : : return true;
207 : 0 : return func_checker::compatible_polymorphic_types_p (TREE_TYPE (t1),
208 : 0 : TREE_TYPE (t2),
209 : 0 : false);
210 : : }
211 : :
212 : : /* If types contain a polymorphic types, match them. */
213 : 10850 : bool c1 = contains_polymorphic_type_p (t1);
214 : 10850 : bool c2 = contains_polymorphic_type_p (t2);
215 : 10850 : if (!c1 && !c2)
216 : : return true;
217 : 789 : if (!c1 || !c2)
218 : 0 : return return_false_with_msg ("one type is not polymorphic");
219 : 789 : if (!types_must_be_same_for_odr (t1, t2))
220 : 0 : return return_false_with_msg ("types are not same for ODR");
221 : : return true;
222 : : }
223 : :
224 : : /* Return true if types are compatible from perspective of ICF. */
225 : : bool
226 : 3475383 : func_checker::compatible_types_p (tree t1, tree t2)
227 : : {
228 : 3475383 : if (TREE_CODE (t1) != TREE_CODE (t2))
229 : 70711 : return return_false_with_msg ("different tree types");
230 : :
231 : 3404672 : if (TYPE_RESTRICT (t1) != TYPE_RESTRICT (t2))
232 : 78 : return return_false_with_msg ("restrict flags are different");
233 : :
234 : 3404594 : if (!types_compatible_p (t1, t2))
235 : 479865 : return return_false_with_msg ("types are not compatible");
236 : :
237 : : return true;
238 : : }
239 : :
240 : : /* Add hash of ARG to HSTATE. FLAGS have same meaning
241 : : as for operand_equal_p. Works only if operand acces type is OP_NORMAL. */
242 : :
243 : : void
244 : 123619370 : func_checker::hash_operand (const_tree arg, inchash::hash &hstate,
245 : : unsigned int flags)
246 : : {
247 : 128170833 : if (arg == NULL_TREE)
248 : : {
249 : 14062754 : hstate.merge_hash (0);
250 : 14062754 : return;
251 : : }
252 : :
253 : 114108079 : switch (TREE_CODE (arg))
254 : : {
255 : 5127540 : case PARM_DECL:
256 : 5127540 : {
257 : 5127540 : unsigned int index = 0;
258 : 5127540 : if (DECL_CONTEXT (arg))
259 : 5127540 : for (tree p = DECL_ARGUMENTS (DECL_CONTEXT (arg));
260 : 10282634 : p && index < 32; p = DECL_CHAIN (p), index++)
261 : 10273594 : if (p == arg)
262 : : break;
263 : 5127540 : hstate.add_int (PARM_DECL);
264 : 5127540 : hstate.add_int (index);
265 : : }
266 : 5127540 : return;
267 : 13304780 : case FUNCTION_DECL:
268 : 13304780 : case VAR_DECL:
269 : 13304780 : case LABEL_DECL:
270 : 13304780 : case RESULT_DECL:
271 : 13304780 : case CONST_DECL:
272 : 13304780 : hstate.add_int (TREE_CODE (arg));
273 : 13304780 : return;
274 : 30874199 : case SSA_NAME:
275 : 30874199 : hstate.add_int (SSA_NAME);
276 : 30874199 : if (SSA_NAME_IS_DEFAULT_DEF (arg))
277 : 4551463 : hash_operand (SSA_NAME_VAR (arg), hstate, flags);
278 : : return;
279 : 237 : case FIELD_DECL:
280 : 237 : inchash::add_expr (DECL_FIELD_OFFSET (arg), hstate, flags);
281 : 237 : inchash::add_expr (DECL_FIELD_BIT_OFFSET (arg), hstate, flags);
282 : 237 : return;
283 : 64801323 : default:
284 : 64801323 : break;
285 : : }
286 : :
287 : : /* In gimple all clobbers can be considered equal: while comparaing two
288 : : gimple clobbers we match the left hand memory accesses. */
289 : 64801323 : if (TREE_CLOBBER_P (arg))
290 : : {
291 : 1098031 : hstate.add_int (0xc10bbe5);
292 : 1098031 : return;
293 : : }
294 : 63703292 : gcc_assert (!DECL_P (arg));
295 : 63703292 : gcc_assert (!TYPE_P (arg));
296 : :
297 : 63703292 : return operand_compare::hash_operand (arg, hstate, flags);
298 : : }
299 : :
300 : : /* Add hash of ARG accesses according to ACCESS to HSTATE.
301 : : FLAGS have same meaning as for operand_equal_p. */
302 : :
303 : : void
304 : 59588693 : func_checker::hash_operand (const_tree arg, inchash::hash &hstate,
305 : : unsigned int flags, operand_access_type access)
306 : : {
307 : 59588693 : if (access == OP_MEMORY)
308 : : {
309 : 7252274 : ao_ref ref;
310 : 7252274 : ao_ref_init (&ref, const_cast <tree> (arg));
311 : 7252274 : return hash_ao_ref (&ref, lto_streaming_expected_p (), m_tbaa, hstate);
312 : : }
313 : : else
314 : 52336419 : return hash_operand (arg, hstate, flags);
315 : : }
316 : :
317 : : bool
318 : 4544875 : func_checker::operand_equal_p (const_tree t1, const_tree t2,
319 : : unsigned int flags)
320 : : {
321 : 4544875 : bool r;
322 : 4544875 : if (verify_hash_value (t1, t2, flags, &r))
323 : 1999163 : return r;
324 : :
325 : 2545712 : if (t1 == t2)
326 : : return true;
327 : 1922457 : else if (!t1 || !t2)
328 : : return false;
329 : :
330 : 1922457 : if (TREE_CODE (t1) != TREE_CODE (t2))
331 : 3 : return return_false ();
332 : :
333 : 1922454 : switch (TREE_CODE (t1))
334 : : {
335 : : case FUNCTION_DECL:
336 : : /* All function decls are in the symbol table and known to match
337 : : before we start comparing bodies. */
338 : : return true;
339 : 77470 : case VAR_DECL:
340 : 77470 : return return_with_debug (compare_variable_decl (t1, t2));
341 : 2946 : case LABEL_DECL:
342 : 2946 : {
343 : 2946 : int *bb1 = m_label_bb_map.get (t1);
344 : 2946 : int *bb2 = m_label_bb_map.get (t2);
345 : : /* Labels can point to another function (non-local GOTOs). */
346 : 2951 : return return_with_debug (bb1 != NULL && bb2 != NULL && *bb1 == *bb2);
347 : : }
348 : :
349 : 251200 : case PARM_DECL:
350 : 251200 : case RESULT_DECL:
351 : 251200 : case CONST_DECL:
352 : 251200 : return compare_decl (t1, t2);
353 : 1141157 : case SSA_NAME:
354 : 1141157 : return compare_ssa_name (t1, t2);
355 : 436538 : default:
356 : 436538 : break;
357 : : }
358 : : /* In gimple all clobbers can be considered equal. We match the left hand
359 : : memory accesses. */
360 : 436538 : if (TREE_CLOBBER_P (t1) || TREE_CLOBBER_P (t2))
361 : 22980 : return TREE_CLOBBER_P (t1) == TREE_CLOBBER_P (t2);
362 : :
363 : 413558 : return operand_compare::operand_equal_p (t1, t2, flags);
364 : : }
365 : :
366 : : /* Return true if either T1 and T2 cannot be totally scalarized or if doing
367 : : so would result in copying the same memory. Otherwise return false. */
368 : :
369 : : bool
370 : 147465 : func_checker::safe_for_total_scalarization_p (tree t1, tree t2)
371 : : {
372 : 147465 : tree type1 = TREE_TYPE (t1);
373 : 147465 : tree type2 = TREE_TYPE (t2);
374 : :
375 : 147465 : if (!AGGREGATE_TYPE_P (type1)
376 : 38861 : || !AGGREGATE_TYPE_P (type2)
377 : 38861 : || !tree_fits_uhwi_p (TYPE_SIZE (type1))
378 : 186326 : || !tree_fits_uhwi_p (TYPE_SIZE (type2)))
379 : : return true;
380 : :
381 : 38861 : if (!m_total_scalarization_limit_known_p)
382 : : {
383 : 6392 : push_cfun (DECL_STRUCT_FUNCTION (m_target_func_decl));
384 : 6392 : m_total_scalarization_limit = sra_get_max_scalarization_size ();
385 : 6392 : pop_cfun ();
386 : 6392 : m_total_scalarization_limit_known_p = true;
387 : : }
388 : :
389 : 38861 : unsigned HOST_WIDE_INT sz = tree_to_uhwi (TYPE_SIZE (type1));
390 : 38861 : gcc_assert (sz == tree_to_uhwi (TYPE_SIZE (type2)));
391 : 38861 : if (sz > m_total_scalarization_limit)
392 : : return true;
393 : 38076 : return sra_total_scalarization_would_copy_same_data_p (type1, type2);
394 : : }
395 : :
396 : : /* Function responsible for comparison of various operands T1 and T2
397 : : which are accessed as ACCESS.
398 : : If these components, from functions FUNC1 and FUNC2, are equal, true
399 : : is returned. */
400 : :
401 : : bool
402 : 2302475 : func_checker::compare_operand (tree t1, tree t2, operand_access_type access)
403 : : {
404 : 2302475 : if (!t1 && !t2)
405 : : return true;
406 : 1906178 : else if (!t1 || !t2)
407 : : return false;
408 : 1906178 : if (access == OP_MEMORY)
409 : : {
410 : 149410 : ao_ref ref1, ref2;
411 : 149410 : ao_ref_init (&ref1, const_cast <tree> (t1));
412 : 149410 : ao_ref_init (&ref2, const_cast <tree> (t2));
413 : 298820 : int flags = compare_ao_refs (&ref1, &ref2,
414 : 149410 : lto_streaming_expected_p (), m_tbaa);
415 : :
416 : 149410 : if (!flags)
417 : : {
418 : 147465 : if (!safe_for_total_scalarization_p (t1, t2))
419 : 3 : return return_false_with_msg
420 : : ("total scalarization may not be equivalent");
421 : : return true;
422 : : }
423 : 1945 : if (flags & SEMANTICS)
424 : 273 : return return_false_with_msg
425 : : ("compare_ao_refs failed (semantic difference)");
426 : 1672 : if (flags & BASE_ALIAS_SET)
427 : 40 : return return_false_with_msg
428 : : ("compare_ao_refs failed (base alias set difference)");
429 : 1632 : if (flags & REF_ALIAS_SET)
430 : 1 : return return_false_with_msg
431 : : ("compare_ao_refs failed (ref alias set difference)");
432 : 1631 : if (flags & ACCESS_PATH)
433 : 1554 : return return_false_with_msg
434 : : ("compare_ao_refs failed (access path difference)");
435 : 77 : if (flags & DEPENDENCE_CLIQUE)
436 : 77 : return return_false_with_msg
437 : : ("compare_ao_refs failed (dependence clique difference)");
438 : 0 : gcc_unreachable ();
439 : : }
440 : : else
441 : : {
442 : 1756768 : if (operand_equal_p (t1, t2, OEP_MATCH_SIDE_EFFECTS))
443 : : return true;
444 : 190 : return return_false_with_msg
445 : : ("operand_equal_p failed");
446 : : }
447 : : }
448 : :
449 : : bool
450 : 924 : func_checker::compare_asm_inputs_outputs (tree t1, tree t2,
451 : : operand_access_type_map *map)
452 : : {
453 : 924 : gcc_assert (TREE_CODE (t1) == TREE_LIST);
454 : 924 : gcc_assert (TREE_CODE (t2) == TREE_LIST);
455 : :
456 : 1820 : for (; t1; t1 = TREE_CHAIN (t1))
457 : : {
458 : 924 : if (!t2)
459 : : return false;
460 : :
461 : 924 : if (!compare_operand (TREE_VALUE (t1), TREE_VALUE (t2),
462 : : get_operand_access_type (map, t1)))
463 : 5 : return return_false ();
464 : :
465 : 919 : tree p1 = TREE_PURPOSE (t1);
466 : 919 : tree p2 = TREE_PURPOSE (t2);
467 : :
468 : 919 : gcc_assert (TREE_CODE (p1) == TREE_LIST);
469 : 919 : gcc_assert (TREE_CODE (p2) == TREE_LIST);
470 : :
471 : 919 : if (strcmp (TREE_STRING_POINTER (TREE_VALUE (p1)),
472 : 919 : TREE_STRING_POINTER (TREE_VALUE (p2))) != 0)
473 : 23 : return return_false ();
474 : :
475 : 896 : t2 = TREE_CHAIN (t2);
476 : : }
477 : :
478 : 896 : if (t2)
479 : 0 : return return_false ();
480 : :
481 : : return true;
482 : : }
483 : :
484 : : /* Verifies that trees T1 and T2 do correspond. */
485 : :
486 : : bool
487 : 439712 : func_checker::compare_variable_decl (const_tree t1, const_tree t2)
488 : : {
489 : 439712 : bool ret = false;
490 : :
491 : 439712 : if (t1 == t2)
492 : : return true;
493 : :
494 : 77478 : if (DECL_ALIGN (t1) != DECL_ALIGN (t2))
495 : 6 : return return_false_with_msg ("alignments are different");
496 : :
497 : 77472 : if (DECL_HARD_REGISTER (t1) != DECL_HARD_REGISTER (t2))
498 : 0 : return return_false_with_msg ("DECL_HARD_REGISTER are different");
499 : :
500 : 77472 : if (DECL_HARD_REGISTER (t1)
501 : 77472 : && DECL_ASSEMBLER_NAME_RAW (t1) != DECL_ASSEMBLER_NAME_RAW (t2))
502 : 9 : return return_false_with_msg ("HARD REGISTERS are different");
503 : :
504 : : /* Symbol table variables are known to match before we start comparing
505 : : bodies. */
506 : 77463 : if (decl_in_symtab_p (t1))
507 : 12 : return decl_in_symtab_p (t2);
508 : 77451 : ret = compare_decl (t1, t2);
509 : :
510 : 77451 : return return_with_debug (ret);
511 : : }
512 : :
513 : : /* Compare loop information for basic blocks BB1 and BB2. */
514 : :
515 : : bool
516 : 362260 : func_checker::compare_loops (basic_block bb1, basic_block bb2)
517 : : {
518 : 362260 : if ((bb1->loop_father == NULL) != (bb2->loop_father == NULL))
519 : 0 : return return_false ();
520 : :
521 : 362260 : class loop *l1 = bb1->loop_father;
522 : 362260 : class loop *l2 = bb2->loop_father;
523 : 362260 : if (l1 == NULL)
524 : : return true;
525 : :
526 : 362260 : if ((bb1 == l1->header) != (bb2 == l2->header))
527 : 0 : return return_false_with_msg ("header");
528 : 362260 : if ((bb1 == l1->latch) != (bb2 == l2->latch))
529 : 0 : return return_false_with_msg ("latch");
530 : 362260 : if (l1->simdlen != l2->simdlen)
531 : 5 : return return_false_with_msg ("simdlen");
532 : 362255 : if (l1->safelen != l2->safelen)
533 : 10 : return return_false_with_msg ("safelen");
534 : 362245 : if (l1->can_be_parallel != l2->can_be_parallel)
535 : 0 : return return_false_with_msg ("can_be_parallel");
536 : 362245 : if (l1->dont_vectorize != l2->dont_vectorize)
537 : 0 : return return_false_with_msg ("dont_vectorize");
538 : 362245 : if (l1->force_vectorize != l2->force_vectorize)
539 : 0 : return return_false_with_msg ("force_vectorize");
540 : 362245 : if (l1->finite_p != l2->finite_p)
541 : 3 : return return_false_with_msg ("finite_p");
542 : 362242 : if (l1->unroll != l2->unroll)
543 : 0 : return return_false_with_msg ("unroll");
544 : 362242 : if (!compare_variable_decl (l1->simduid, l2->simduid))
545 : 0 : return return_false_with_msg ("simduid");
546 : 362242 : if ((l1->any_upper_bound != l2->any_upper_bound)
547 : 362242 : || (l1->any_upper_bound
548 : 5572 : && (l1->nb_iterations_upper_bound != l2->nb_iterations_upper_bound)))
549 : 7 : return return_false_with_msg ("nb_iterations_upper_bound");
550 : :
551 : : return true;
552 : : }
553 : :
554 : : /* Function visits all gimple labels and creates corresponding
555 : : mapping between basic blocks and labels. */
556 : :
557 : : void
558 : 1066500 : func_checker::parse_labels (sem_bb *bb)
559 : : {
560 : 6103072 : for (gimple_stmt_iterator gsi = gsi_start_bb (bb->bb); !gsi_end_p (gsi);
561 : 3970072 : gsi_next (&gsi))
562 : : {
563 : 3970072 : gimple *stmt = gsi_stmt (gsi);
564 : :
565 : 3986296 : if (glabel *label_stmt = dyn_cast <glabel *> (stmt))
566 : : {
567 : 16224 : const_tree t = gimple_label_label (label_stmt);
568 : 16224 : gcc_assert (TREE_CODE (t) == LABEL_DECL);
569 : :
570 : 16224 : m_label_bb_map.put (t, bb->bb->index);
571 : : }
572 : : }
573 : 1066500 : }
574 : :
575 : : /* Basic block equivalence comparison function that returns true if
576 : : basic blocks BB1 and BB2 (from functions FUNC1 and FUNC2) correspond.
577 : :
578 : : In general, a collection of equivalence dictionaries is built for types
579 : : like SSA names, declarations (VAR_DECL, PARM_DECL, ..). This infrastructure
580 : : is utilized by every statement-by-statement comparison function. */
581 : :
582 : : bool
583 : 398278 : func_checker::compare_bb (sem_bb *bb1, sem_bb *bb2)
584 : : {
585 : 398278 : gimple_stmt_iterator gsi1, gsi2;
586 : 398278 : gimple *s1, *s2;
587 : :
588 : 398278 : gsi1 = gsi_start_nondebug_bb (bb1->bb);
589 : 398278 : gsi2 = gsi_start_nondebug_bb (bb2->bb);
590 : :
591 : 1231470 : while (!gsi_end_p (gsi1))
592 : : {
593 : 869210 : if (gsi_end_p (gsi2))
594 : 0 : return return_false ();
595 : :
596 : 869210 : s1 = gsi_stmt (gsi1);
597 : 869210 : s2 = gsi_stmt (gsi2);
598 : :
599 : 869210 : int eh1 = lookup_stmt_eh_lp_fn
600 : 869210 : (DECL_STRUCT_FUNCTION (m_source_func_decl), s1);
601 : 869210 : int eh2 = lookup_stmt_eh_lp_fn
602 : 869210 : (DECL_STRUCT_FUNCTION (m_target_func_decl), s2);
603 : :
604 : 869210 : if (eh1 != eh2)
605 : 15 : return return_false_with_msg ("EH regions are different");
606 : :
607 : 869195 : if (gimple_code (s1) != gimple_code (s2))
608 : 0 : return return_false_with_msg ("gimple codes are different");
609 : :
610 : 869195 : switch (gimple_code (s1))
611 : : {
612 : 233650 : case GIMPLE_CALL:
613 : 233650 : if (!compare_gimple_call (as_a <gcall *> (s1),
614 : : as_a <gcall *> (s2)))
615 : 30360 : return return_different_stmts (s1, s2, "GIMPLE_CALL");
616 : : break;
617 : 372098 : case GIMPLE_ASSIGN:
618 : 372098 : if (!compare_gimple_assign (s1, s2))
619 : 3165 : return return_different_stmts (s1, s2, "GIMPLE_ASSIGN");
620 : : break;
621 : 104189 : case GIMPLE_COND:
622 : 104189 : if (!compare_gimple_cond (s1, s2))
623 : 2371 : return return_different_stmts (s1, s2, "GIMPLE_COND");
624 : : break;
625 : 376 : case GIMPLE_SWITCH:
626 : 376 : if (!compare_gimple_switch (as_a <gswitch *> (s1),
627 : 376 : as_a <gswitch *> (s2)))
628 : 2 : return return_different_stmts (s1, s2, "GIMPLE_SWITCH");
629 : : break;
630 : : case GIMPLE_DEBUG:
631 : : break;
632 : 182 : case GIMPLE_EH_DISPATCH:
633 : 182 : if (gimple_eh_dispatch_region (as_a <geh_dispatch *> (s1))
634 : 182 : != gimple_eh_dispatch_region (as_a <geh_dispatch *> (s2)))
635 : 0 : return return_different_stmts (s1, s2, "GIMPLE_EH_DISPATCH");
636 : : break;
637 : 3812 : case GIMPLE_RESX:
638 : 3812 : if (!compare_gimple_resx (as_a <gresx *> (s1),
639 : 3812 : as_a <gresx *> (s2)))
640 : 0 : return return_different_stmts (s1, s2, "GIMPLE_RESX");
641 : : break;
642 : 7726 : case GIMPLE_LABEL:
643 : 7726 : if (!compare_gimple_label (as_a <glabel *> (s1),
644 : 7726 : as_a <glabel *> (s2)))
645 : 15 : return return_different_stmts (s1, s2, "GIMPLE_LABEL");
646 : : break;
647 : 140761 : case GIMPLE_RETURN:
648 : 140761 : if (!compare_gimple_return (as_a <greturn *> (s1),
649 : 140761 : as_a <greturn *> (s2)))
650 : 36 : return return_different_stmts (s1, s2, "GIMPLE_RETURN");
651 : : break;
652 : 0 : case GIMPLE_GOTO:
653 : 0 : if (!compare_gimple_goto (s1, s2))
654 : 0 : return return_different_stmts (s1, s2, "GIMPLE_GOTO");
655 : : break;
656 : 5408 : case GIMPLE_ASM:
657 : 5408 : if (!compare_gimple_asm (as_a <gasm *> (s1),
658 : 5408 : as_a <gasm *> (s2)))
659 : 54 : return return_different_stmts (s1, s2, "GIMPLE_ASM");
660 : : break;
661 : : case GIMPLE_PREDICT:
662 : : case GIMPLE_NOP:
663 : : break;
664 : 0 : default:
665 : 0 : return return_false_with_msg ("Unknown GIMPLE code reached");
666 : : }
667 : :
668 : 833192 : gsi_next_nondebug (&gsi1);
669 : 833192 : gsi_next_nondebug (&gsi2);
670 : : }
671 : :
672 : 362260 : if (!gsi_end_p (gsi2))
673 : 0 : return return_false ();
674 : :
675 : 362260 : if (!compare_loops (bb1->bb, bb2->bb))
676 : 25 : return return_false ();
677 : :
678 : : return true;
679 : : }
680 : :
681 : : /* Verifies for given GIMPLEs S1 and S2 that
682 : : call statements are semantically equivalent. */
683 : :
684 : : bool
685 : 233650 : func_checker::compare_gimple_call (gcall *s1, gcall *s2)
686 : : {
687 : 233650 : unsigned i;
688 : 233650 : tree t1, t2;
689 : :
690 : 233650 : if (gimple_call_num_args (s1) != gimple_call_num_args (s2))
691 : : return false;
692 : :
693 : 233650 : operand_access_type_map map (5);
694 : 233650 : classify_operands (s1, &map);
695 : :
696 : 233650 : t1 = gimple_call_fn (s1);
697 : 233650 : t2 = gimple_call_fn (s2);
698 : 233650 : if (!compare_operand (t1, t2, get_operand_access_type (&map, t1)))
699 : 0 : return return_false ();
700 : :
701 : : /* Compare flags. */
702 : 233650 : if (gimple_call_internal_p (s1) != gimple_call_internal_p (s2)
703 : 233650 : || gimple_call_ctrl_altering_p (s1) != gimple_call_ctrl_altering_p (s2)
704 : 233650 : || gimple_call_tail_p (s1) != gimple_call_tail_p (s2)
705 : 233650 : || gimple_call_return_slot_opt_p (s1) != gimple_call_return_slot_opt_p (s2)
706 : 233650 : || gimple_call_from_thunk_p (s1) != gimple_call_from_thunk_p (s2)
707 : 233650 : || gimple_call_from_new_or_delete (s1) != gimple_call_from_new_or_delete (s2)
708 : 233650 : || gimple_call_va_arg_pack_p (s1) != gimple_call_va_arg_pack_p (s2)
709 : 467300 : || gimple_call_alloca_for_var_p (s1) != gimple_call_alloca_for_var_p (s2))
710 : : return false;
711 : :
712 : 233650 : if (gimple_call_internal_p (s1)
713 : 233650 : && gimple_call_internal_fn (s1) != gimple_call_internal_fn (s2))
714 : : return false;
715 : :
716 : 206238 : tree fntype1 = gimple_call_fntype (s1);
717 : 206238 : tree fntype2 = gimple_call_fntype (s2);
718 : :
719 : : /* For direct calls we verify that types are compatible so if we matched
720 : : callees, callers must match, too. For indirect calls however verify
721 : : function type. */
722 : 206238 : if (!gimple_call_fndecl (s1))
723 : : {
724 : 66337 : if ((fntype1 && !fntype2)
725 : 66337 : || (!fntype1 && fntype2)
726 : 66337 : || (fntype1 && !types_compatible_p (fntype1, fntype2)))
727 : 4 : return return_false_with_msg ("call function types are not compatible");
728 : : }
729 : :
730 : 206234 : if (fntype1 && fntype2 && comp_type_attributes (fntype1, fntype2) != 1)
731 : 0 : return return_false_with_msg ("different fntype attributes");
732 : :
733 : 206234 : tree chain1 = gimple_call_chain (s1);
734 : 206234 : tree chain2 = gimple_call_chain (s2);
735 : 206234 : if ((chain1 && !chain2)
736 : 206234 : || (!chain1 && chain2)
737 : 206234 : || !compare_operand (chain1, chain2,
738 : : get_operand_access_type (&map, chain1)))
739 : 0 : return return_false_with_msg ("static call chains are different");
740 : :
741 : : /* Checking of argument. */
742 : 473446 : for (i = 0; i < gimple_call_num_args (s1); ++i)
743 : : {
744 : 267251 : t1 = gimple_call_arg (s1, i);
745 : 267251 : t2 = gimple_call_arg (s2, i);
746 : :
747 : 267251 : if (!compare_operand (t1, t2, get_operand_access_type (&map, t1)))
748 : 39 : return return_false_with_msg ("GIMPLE call operands are different");
749 : : }
750 : :
751 : : /* Return value checking. */
752 : 206195 : t1 = gimple_get_lhs (s1);
753 : 206195 : t2 = gimple_get_lhs (s2);
754 : :
755 : : /* For internal calls, lhs types need to be verified, as neither fntype nor
756 : : callee comparisons can catch that. */
757 : 206195 : if (gimple_call_internal_p (s1)
758 : 58074 : && t1
759 : 58074 : && t2
760 : 264088 : && !compatible_types_p (TREE_TYPE (t1), TREE_TYPE (t2)))
761 : 2890 : return return_false_with_msg ("GIMPLE internal call LHS type mismatch");
762 : :
763 : 203305 : if (!gimple_call_internal_p (s1))
764 : : {
765 : 148121 : cgraph_edge *e1 = cgraph_node::get (m_source_func_decl)->get_edge (s1);
766 : 148121 : cgraph_edge *e2 = cgraph_node::get (m_target_func_decl)->get_edge (s2);
767 : 148121 : class ipa_edge_args *args1 = ipa_edge_args_sum->get (e1);
768 : 148121 : class ipa_edge_args *args2 = ipa_edge_args_sum->get (e2);
769 : 148121 : if ((args1 != nullptr) != (args2 != nullptr))
770 : 2 : return return_false_with_msg ("ipa_edge_args mismatch");
771 : 148119 : if (args1)
772 : : {
773 : 99401 : int n1 = ipa_get_cs_argument_count (args1);
774 : 99401 : int n2 = ipa_get_cs_argument_count (args2);
775 : 99401 : if (n1 != n2)
776 : 0 : return return_false_with_msg ("ipa_edge_args nargs mismatch");
777 : 208384 : for (int i = 0; i < n1; i++)
778 : : {
779 : 108990 : struct ipa_jump_func *jf1 = ipa_get_ith_jump_func (args1, i);
780 : 108990 : struct ipa_jump_func *jf2 = ipa_get_ith_jump_func (args2, i);
781 : 108990 : if (((jf1 != nullptr) != (jf2 != nullptr))
782 : 108990 : || (jf1 && !ipa_jump_functions_equivalent_p (jf1, jf2)))
783 : 7 : return return_false_with_msg ("jump function mismatch");
784 : : }
785 : : }
786 : : }
787 : :
788 : 203296 : return compare_operand (t1, t2, get_operand_access_type (&map, t1));
789 : 233650 : }
790 : :
791 : :
792 : : /* Verifies for given GIMPLEs S1 and S2 that
793 : : assignment statements are semantically equivalent. */
794 : :
795 : : bool
796 : 372098 : func_checker::compare_gimple_assign (gimple *s1, gimple *s2)
797 : : {
798 : 372098 : tree arg1, arg2;
799 : 372098 : tree_code code1, code2;
800 : 372098 : unsigned i;
801 : :
802 : 372098 : code1 = gimple_assign_rhs_code (s1);
803 : 372098 : code2 = gimple_assign_rhs_code (s2);
804 : :
805 : 372098 : if (code1 != code2)
806 : : return false;
807 : :
808 : 372098 : operand_access_type_map map (5);
809 : 372098 : classify_operands (s1, &map);
810 : :
811 : 1559409 : for (i = 0; i < gimple_num_ops (s1); i++)
812 : : {
813 : 818378 : arg1 = gimple_op (s1, i);
814 : 818378 : arg2 = gimple_op (s2, i);
815 : :
816 : : /* Compare types for LHS. */
817 : 818378 : if (i == 0 && !gimple_store_p (s1))
818 : : {
819 : 297436 : if (!compatible_types_p (TREE_TYPE (arg1), TREE_TYPE (arg2)))
820 : 1145 : return return_false_with_msg ("GIMPLE LHS type mismatch");
821 : : }
822 : :
823 : 817233 : if (!compare_operand (arg1, arg2, get_operand_access_type (&map, arg1)))
824 : 2020 : return return_false_with_msg ("GIMPLE assignment operands "
825 : : "are different");
826 : : }
827 : :
828 : :
829 : : return true;
830 : 372098 : }
831 : :
832 : : /* Verifies for given GIMPLEs S1 and S2 that
833 : : condition statements are semantically equivalent. */
834 : :
835 : : bool
836 : 104189 : func_checker::compare_gimple_cond (gimple *s1, gimple *s2)
837 : : {
838 : 104189 : tree t1, t2;
839 : 104189 : tree_code code1, code2;
840 : :
841 : 104189 : code1 = gimple_cond_code (s1);
842 : 104189 : code2 = gimple_cond_code (s2);
843 : :
844 : 104189 : if (code1 != code2)
845 : : return false;
846 : :
847 : 101818 : t1 = gimple_cond_lhs (s1);
848 : 101818 : t2 = gimple_cond_lhs (s2);
849 : :
850 : 101818 : if (!compare_operand (t1, t2, OP_NORMAL))
851 : : return false;
852 : :
853 : 101818 : t1 = gimple_cond_rhs (s1);
854 : 101818 : t2 = gimple_cond_rhs (s2);
855 : :
856 : 101818 : return compare_operand (t1, t2, OP_NORMAL);
857 : : }
858 : :
859 : : /* Verifies for given GIMPLE_LABEL stmts S1 and S2 that
860 : : label statements are semantically equivalent. */
861 : :
862 : : bool
863 : 7726 : func_checker::compare_gimple_label (const glabel *g1, const glabel *g2)
864 : : {
865 : 7726 : if (m_ignore_labels)
866 : : return true;
867 : :
868 : 7726 : tree t1 = gimple_label_label (g1);
869 : 7726 : tree t2 = gimple_label_label (g2);
870 : :
871 : 15437 : if (FORCED_LABEL (t1) || FORCED_LABEL (t2))
872 : 15 : return return_false_with_msg ("FORCED_LABEL");
873 : :
874 : : /* As the pass build BB to label mapping, no further check is needed. */
875 : : return true;
876 : : }
877 : :
878 : : /* Verifies for given GIMPLE_SWITCH stmts S1 and S2 that
879 : : switch statements are semantically equivalent. */
880 : :
881 : : bool
882 : 376 : func_checker::compare_gimple_switch (const gswitch *g1, const gswitch *g2)
883 : : {
884 : 376 : unsigned lsize1, lsize2, i;
885 : :
886 : 376 : lsize1 = gimple_switch_num_labels (g1);
887 : 376 : lsize2 = gimple_switch_num_labels (g2);
888 : :
889 : 376 : if (lsize1 != lsize2)
890 : : return false;
891 : :
892 : 375 : tree t1 = gimple_switch_index (g1);
893 : 375 : tree t2 = gimple_switch_index (g2);
894 : :
895 : 375 : if (!compare_operand (t1, t2, OP_NORMAL))
896 : : return false;
897 : :
898 : 3312 : for (i = 0; i < lsize1; i++)
899 : : {
900 : 2938 : tree label1 = gimple_switch_label (g1, i);
901 : 2938 : tree label2 = gimple_switch_label (g2, i);
902 : :
903 : : /* Label LOW and HIGH comparison. */
904 : 2938 : tree low1 = CASE_LOW (label1);
905 : 2938 : tree low2 = CASE_LOW (label2);
906 : :
907 : 2938 : if (!tree_int_cst_equal (low1, low2))
908 : 1 : return return_false_with_msg ("case low values are different");
909 : :
910 : 2937 : tree high1 = CASE_HIGH (label1);
911 : 2937 : tree high2 = CASE_HIGH (label2);
912 : :
913 : 2937 : if (!tree_int_cst_equal (high1, high2))
914 : 0 : return return_false_with_msg ("case high values are different");
915 : :
916 : 2937 : if (TREE_CODE (label1) == CASE_LABEL_EXPR
917 : 2937 : && TREE_CODE (label2) == CASE_LABEL_EXPR)
918 : : {
919 : 2937 : label1 = CASE_LABEL (label1);
920 : 2937 : label2 = CASE_LABEL (label2);
921 : :
922 : 2937 : if (!compare_operand (label1, label2, OP_NORMAL))
923 : 0 : return return_false_with_msg ("switch label_exprs are different");
924 : : }
925 : 0 : else if (!tree_int_cst_equal (label1, label2))
926 : 0 : return return_false_with_msg ("switch labels are different");
927 : : }
928 : :
929 : : return true;
930 : : }
931 : :
932 : : /* Verifies for given GIMPLE_RETURN stmts S1 and S2 that
933 : : return statements are semantically equivalent. */
934 : :
935 : : bool
936 : 140761 : func_checker::compare_gimple_return (const greturn *g1, const greturn *g2)
937 : : {
938 : 140761 : tree t1, t2;
939 : :
940 : 140761 : t1 = gimple_return_retval (g1);
941 : 140761 : t2 = gimple_return_retval (g2);
942 : :
943 : : /* Void return type. */
944 : 140761 : if (t1 == NULL && t2 == NULL)
945 : : return true;
946 : : else
947 : : {
948 : 76372 : operand_access_type_map map (3);
949 : 76372 : return compare_operand (t1, t2, get_operand_access_type (&map, t1));
950 : 76372 : }
951 : : }
952 : :
953 : : /* Verifies for given GIMPLEs S1 and S2 that
954 : : goto statements are semantically equivalent. */
955 : :
956 : : bool
957 : 0 : func_checker::compare_gimple_goto (gimple *g1, gimple *g2)
958 : : {
959 : 0 : tree dest1, dest2;
960 : :
961 : 0 : dest1 = gimple_goto_dest (g1);
962 : 0 : dest2 = gimple_goto_dest (g2);
963 : :
964 : 0 : if (TREE_CODE (dest1) != TREE_CODE (dest2) || TREE_CODE (dest1) != SSA_NAME)
965 : : return false;
966 : :
967 : 0 : return compare_operand (dest1, dest2, OP_NORMAL);
968 : : }
969 : :
970 : : /* Verifies for given GIMPLE_RESX stmts S1 and S2 that
971 : : resx statements are semantically equivalent. */
972 : :
973 : : bool
974 : 3812 : func_checker::compare_gimple_resx (const gresx *g1, const gresx *g2)
975 : : {
976 : 3812 : return gimple_resx_region (g1) == gimple_resx_region (g2);
977 : : }
978 : :
979 : : /* Verifies for given GIMPLEs S1 and S2 that ASM statements are equivalent.
980 : : For the beginning, the pass only supports equality for
981 : : '__asm__ __volatile__ ("", "", "", "memory")'. */
982 : :
983 : : bool
984 : 5408 : func_checker::compare_gimple_asm (const gasm *g1, const gasm *g2)
985 : : {
986 : 5408 : if (gimple_asm_volatile_p (g1) != gimple_asm_volatile_p (g2))
987 : : return false;
988 : :
989 : 5408 : if (gimple_asm_basic_p (g1) != gimple_asm_basic_p (g2))
990 : : return false;
991 : :
992 : 5408 : if (gimple_asm_inline_p (g1) != gimple_asm_inline_p (g2))
993 : : return false;
994 : :
995 : 5408 : if (gimple_asm_ninputs (g1) != gimple_asm_ninputs (g2))
996 : : return false;
997 : :
998 : 5406 : if (gimple_asm_noutputs (g1) != gimple_asm_noutputs (g2))
999 : : return false;
1000 : :
1001 : : /* We do not suppport goto ASM statement comparison. */
1002 : 5406 : if (gimple_asm_nlabels (g1) || gimple_asm_nlabels (g2))
1003 : : return false;
1004 : :
1005 : 5387 : if (gimple_asm_nclobbers (g1) != gimple_asm_nclobbers (g2))
1006 : : return false;
1007 : :
1008 : 5387 : if (strcmp (gimple_asm_string (g1), gimple_asm_string (g2)) != 0)
1009 : 5 : return return_false_with_msg ("ASM strings are different");
1010 : :
1011 : 5382 : operand_access_type_map map (5);
1012 : 5382 : classify_operands (g1, &map);
1013 : :
1014 : 5770 : for (unsigned i = 0; i < gimple_asm_ninputs (g1); i++)
1015 : : {
1016 : 415 : tree input1 = gimple_asm_input_op (g1, i);
1017 : 415 : tree input2 = gimple_asm_input_op (g2, i);
1018 : :
1019 : 415 : if (!compare_asm_inputs_outputs (input1, input2, &map))
1020 : 27 : return return_false_with_msg ("ASM input is different");
1021 : : }
1022 : :
1023 : 5863 : for (unsigned i = 0; i < gimple_asm_noutputs (g1); i++)
1024 : : {
1025 : 509 : tree output1 = gimple_asm_output_op (g1, i);
1026 : 509 : tree output2 = gimple_asm_output_op (g2, i);
1027 : :
1028 : 509 : if (!compare_asm_inputs_outputs (output1, output2, &map))
1029 : 1 : return return_false_with_msg ("ASM output is different");
1030 : : }
1031 : :
1032 : 18228 : for (unsigned i = 0; i < gimple_asm_nclobbers (g1); i++)
1033 : : {
1034 : 12874 : tree clobber1 = gimple_asm_clobber_op (g1, i);
1035 : 12874 : tree clobber2 = gimple_asm_clobber_op (g2, i);
1036 : :
1037 : 12874 : if (!operand_equal_p (TREE_VALUE (clobber1), TREE_VALUE (clobber2),
1038 : : OEP_ONLY_CONST))
1039 : 0 : return return_false_with_msg ("ASM clobber is different");
1040 : : }
1041 : :
1042 : : return true;
1043 : 5382 : }
1044 : :
1045 : : /* Helper for func_checker::classify_operands. Record that T is a load. */
1046 : :
1047 : : static bool
1048 : 7409679 : visit_load_store (gimple *, tree, tree t, void *data)
1049 : : {
1050 : 7409679 : func_checker::operand_access_type_map *map =
1051 : : (func_checker::operand_access_type_map *) data;
1052 : 7409679 : map->add (t);
1053 : 7409679 : return false;
1054 : : }
1055 : :
1056 : : /* Compute hash map determining access types of operands. */
1057 : :
1058 : : void
1059 : 19406008 : func_checker::classify_operands (const gimple *stmt,
1060 : : operand_access_type_map *map)
1061 : : {
1062 : 19406008 : walk_stmt_load_store_ops (const_cast <gimple *> (stmt),
1063 : : (void *)map, visit_load_store, visit_load_store);
1064 : 19406008 : }
1065 : :
1066 : : /* Return access type of a given operand. */
1067 : :
1068 : : func_checker::operand_access_type
1069 : 57936443 : func_checker::get_operand_access_type (operand_access_type_map *map, tree t)
1070 : : {
1071 : 57936443 : if (map->contains (t))
1072 : 7401684 : return OP_MEMORY;
1073 : : return OP_NORMAL;
1074 : : }
1075 : :
1076 : : } // ipa_icf_gimple namespace
|