Branch data Line data Source code
1 : : /* Gimple walk support.
2 : :
3 : : Copyright (C) 2007-2025 Free Software Foundation, Inc.
4 : : Contributed by Aldy Hernandez <aldyh@redhat.com>
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 "tree.h"
27 : : #include "gimple.h"
28 : : #include "gimple-iterator.h"
29 : : #include "gimple-walk.h"
30 : : #include "stmt.h"
31 : :
32 : : /* Walk all the statements in the sequence *PSEQ calling walk_gimple_stmt
33 : : on each one. WI is as in walk_gimple_stmt.
34 : :
35 : : If walk_gimple_stmt returns non-NULL, the walk is stopped, and the
36 : : value is stored in WI->CALLBACK_RESULT. Also, the statement that
37 : : produced the value is returned if this statement has not been
38 : : removed by a callback (wi->removed_stmt). If the statement has
39 : : been removed, NULL is returned.
40 : :
41 : : Otherwise, all the statements are walked and NULL returned. */
42 : :
43 : : gimple *
44 : 40240246 : walk_gimple_seq_mod (gimple_seq *pseq, walk_stmt_fn callback_stmt,
45 : : walk_tree_fn callback_op, struct walk_stmt_info *wi)
46 : : {
47 : 40240246 : gimple_stmt_iterator gsi;
48 : :
49 : 313911400 : for (gsi = gsi_start (*pseq); !gsi_end_p (gsi); )
50 : : {
51 : 234606906 : tree ret = walk_gimple_stmt (&gsi, callback_stmt, callback_op, wi);
52 : 234606874 : if (ret)
53 : : {
54 : : /* If CALLBACK_STMT or CALLBACK_OP return a value, WI must exist
55 : : to hold it. */
56 : 84036 : gcc_assert (wi);
57 : 84036 : wi->callback_result = ret;
58 : :
59 : 84036 : gimple *g;
60 : 84036 : if (!wi->removed_stmt)
61 : 84036 : g = gsi_stmt (gsi);
62 : : else
63 : : {
64 : 0 : g = NULL;
65 : 0 : wi->removed_stmt = false;
66 : : }
67 : 84036 : return g;
68 : : }
69 : :
70 : 234522838 : if (!wi->removed_stmt)
71 : 234517362 : gsi_next (&gsi);
72 : : else
73 : 5476 : wi->removed_stmt = false;
74 : : }
75 : :
76 : 40156178 : if (wi)
77 : 40156178 : wi->callback_result = NULL_TREE;
78 : :
79 : : return NULL;
80 : : }
81 : :
82 : :
83 : : /* Like walk_gimple_seq_mod, but ensure that the head of SEQ isn't
84 : : changed by the callbacks. */
85 : :
86 : : gimple *
87 : 34719165 : walk_gimple_seq (gimple_seq seq, walk_stmt_fn callback_stmt,
88 : : walk_tree_fn callback_op, struct walk_stmt_info *wi)
89 : : {
90 : 34719165 : gimple_seq seq2 = seq;
91 : 34719165 : gimple *ret = walk_gimple_seq_mod (&seq2, callback_stmt, callback_op, wi);
92 : 34719159 : gcc_assert (seq2 == seq);
93 : 34719159 : return ret;
94 : : }
95 : :
96 : :
97 : : /* Helper function for walk_gimple_stmt. Walk operands of a GIMPLE_ASM. */
98 : :
99 : : static tree
100 : 26419747 : walk_gimple_asm (gasm *stmt, walk_tree_fn callback_op,
101 : : struct walk_stmt_info *wi)
102 : : {
103 : 26419747 : tree ret, op;
104 : 26419747 : unsigned noutputs;
105 : 26419747 : const char **oconstraints;
106 : 26419747 : unsigned i, n;
107 : 26419747 : const char *constraint;
108 : 26419747 : bool allows_mem, allows_reg, is_inout;
109 : :
110 : 26419747 : noutputs = gimple_asm_noutputs (stmt);
111 : 26419747 : oconstraints = (const char **) alloca ((noutputs) * sizeof (const char *));
112 : :
113 : 47523910 : for (i = 0; i < noutputs; i++)
114 : : {
115 : 21104173 : op = gimple_asm_output_op (stmt, i);
116 : 21104173 : constraint = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (op)));
117 : 21104173 : oconstraints[i] = constraint;
118 : 21104173 : if (wi)
119 : : {
120 : 21104081 : if (parse_output_constraint (&constraint, i, 0, 0, &allows_mem,
121 : : &allows_reg, &is_inout, nullptr))
122 : 21104081 : wi->val_only = (allows_reg || !allows_mem);
123 : : }
124 : 21104081 : if (wi)
125 : 21104081 : wi->is_lhs = true;
126 : 21104173 : ret = walk_tree (&TREE_VALUE (op), callback_op, wi, NULL);
127 : 21104173 : if (ret)
128 : : return ret;
129 : : }
130 : :
131 : 26419737 : n = gimple_asm_ninputs (stmt);
132 : 40541891 : for (i = 0; i < n; i++)
133 : : {
134 : 14122160 : op = gimple_asm_input_op (stmt, i);
135 : 14122160 : constraint = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (op)));
136 : :
137 : 14122160 : if (wi)
138 : : {
139 : 14122064 : if (parse_input_constraint (&constraint, 0, 0, noutputs, 0,
140 : : oconstraints, &allows_mem, &allows_reg,
141 : : nullptr))
142 : : {
143 : 14122064 : wi->val_only = (allows_reg || !allows_mem);
144 : : /* Although input "m" is not really a LHS, we need a lvalue. */
145 : 14122064 : wi->is_lhs = !wi->val_only;
146 : : }
147 : : }
148 : 14122160 : ret = walk_tree (&TREE_VALUE (op), callback_op, wi, NULL);
149 : 14122160 : if (ret)
150 : : return ret;
151 : : }
152 : :
153 : 26419731 : if (wi)
154 : : {
155 : 26419658 : wi->is_lhs = false;
156 : 26419658 : wi->val_only = true;
157 : : }
158 : :
159 : 26419731 : n = gimple_asm_nlabels (stmt);
160 : 26609630 : for (i = 0; i < n; i++)
161 : : {
162 : 189899 : op = gimple_asm_label_op (stmt, i);
163 : 189899 : ret = walk_tree (&TREE_VALUE (op), callback_op, wi, NULL);
164 : 189899 : if (ret)
165 : : return ret;
166 : : }
167 : :
168 : : return NULL_TREE;
169 : : }
170 : :
171 : :
172 : : /* Helper function of WALK_GIMPLE_STMT. Walk every tree operand in
173 : : STMT. CALLBACK_OP and WI are as in WALK_GIMPLE_STMT.
174 : :
175 : : CALLBACK_OP is called on each operand of STMT via walk_tree.
176 : : Additional parameters to walk_tree must be stored in WI. For each operand
177 : : OP, walk_tree is called as:
178 : :
179 : : walk_tree (&OP, CALLBACK_OP, WI, WI->PSET)
180 : :
181 : : If CALLBACK_OP returns non-NULL for an operand, the remaining
182 : : operands are not scanned.
183 : :
184 : : The return value is that returned by the last call to walk_tree, or
185 : : NULL_TREE if no CALLBACK_OP is specified. */
186 : :
187 : : tree
188 : 26050357876 : walk_gimple_op (gimple *stmt, walk_tree_fn callback_op,
189 : : struct walk_stmt_info *wi)
190 : : {
191 : 26050357876 : hash_set<tree> *pset = (wi) ? wi->pset : NULL;
192 : 26049418391 : unsigned i;
193 : 52099776267 : tree ret = NULL_TREE;
194 : :
195 : 26049418391 : if (wi)
196 : 26049418391 : wi->stmt = stmt;
197 : :
198 : 26050357876 : switch (gimple_code (stmt))
199 : : {
200 : 8854115345 : case GIMPLE_ASSIGN:
201 : : /* Walk the RHS operands. If the LHS is of a non-renamable type or
202 : : is a register variable, we may use a COMPONENT_REF on the RHS. */
203 : 8854115345 : if (wi)
204 : : {
205 : 8853471379 : tree lhs = gimple_assign_lhs (stmt);
206 : 8853471379 : wi->val_only
207 : 17706942758 : = (is_gimple_reg_type (TREE_TYPE (lhs)) && !is_gimple_reg (lhs))
208 : 15535249556 : || gimple_assign_rhs_class (stmt) != GIMPLE_SINGLE_RHS;
209 : : }
210 : :
211 : 19728336495 : for (i = 1; i < gimple_num_ops (stmt); i++)
212 : : {
213 : 10874294606 : ret = walk_tree (gimple_op_ptr (stmt, i), callback_op, wi,
214 : : pset);
215 : 10874294606 : if (ret)
216 : : return ret;
217 : : }
218 : :
219 : : /* Walk the LHS. If the RHS is appropriate for a memory, we
220 : : may use a COMPONENT_REF on the LHS. */
221 : 8854041889 : if (wi)
222 : : {
223 : : /* If the RHS is of a non-renamable type or is a register variable,
224 : : we may use a COMPONENT_REF on the LHS. */
225 : 8853464310 : tree rhs1 = gimple_assign_rhs1 (stmt);
226 : 8853464310 : wi->val_only
227 : 8853464310 : = (is_gimple_reg_type (TREE_TYPE (rhs1)) && !is_gimple_reg (rhs1))
228 : 13682924799 : || gimple_assign_rhs_class (stmt) != GIMPLE_SINGLE_RHS;
229 : 8853464310 : wi->is_lhs = true;
230 : : }
231 : :
232 : 8854041889 : ret = walk_tree (gimple_op_ptr (stmt, 0), callback_op, wi, pset);
233 : 8854041889 : if (ret)
234 : : return ret;
235 : :
236 : 8854014964 : if (wi)
237 : : {
238 : 8853463673 : wi->val_only = true;
239 : 8853463673 : wi->is_lhs = false;
240 : : }
241 : : break;
242 : :
243 : 2008169832 : case GIMPLE_CALL:
244 : 2008169832 : if (wi)
245 : : {
246 : 2008101002 : wi->is_lhs = false;
247 : 2008101002 : wi->val_only = true;
248 : : }
249 : :
250 : 2008169832 : ret = walk_tree (gimple_call_chain_ptr (as_a <gcall *> (stmt)),
251 : : callback_op, wi, pset);
252 : 2008169832 : if (ret)
253 : : return ret;
254 : :
255 : 2008169771 : ret = walk_tree (gimple_call_fn_ptr (stmt), callback_op, wi, pset);
256 : 2008169771 : if (ret)
257 : : return ret;
258 : :
259 : 6002884707 : for (i = 0; i < gimple_call_num_args (stmt); i++)
260 : : {
261 : 3994719379 : if (wi)
262 : 3994605298 : wi->val_only
263 : 3994605298 : = is_gimple_reg_type (TREE_TYPE (gimple_call_arg (stmt, i)));
264 : 3994719379 : ret = walk_tree (gimple_call_arg_ptr (stmt, i), callback_op, wi,
265 : : pset);
266 : 3994719379 : if (ret)
267 : : return ret;
268 : : }
269 : :
270 : 2008165328 : if (gimple_call_lhs (stmt))
271 : : {
272 : 786130110 : if (wi)
273 : : {
274 : 786110246 : wi->is_lhs = true;
275 : 786110246 : wi->val_only
276 : 786110246 : = is_gimple_reg_type (TREE_TYPE (gimple_call_lhs (stmt)));
277 : : }
278 : :
279 : 786130110 : ret = walk_tree (gimple_call_lhs_ptr (stmt), callback_op, wi, pset);
280 : 786130110 : if (ret)
281 : : return ret;
282 : : }
283 : :
284 : 2008165010 : if (wi)
285 : : {
286 : 2008099845 : wi->is_lhs = false;
287 : 2008099845 : wi->val_only = true;
288 : : }
289 : : break;
290 : :
291 : 17644 : case GIMPLE_CATCH:
292 : 17644 : ret = walk_tree (gimple_catch_types_ptr (as_a <gcatch *> (stmt)),
293 : : callback_op, wi, pset);
294 : 17644 : if (ret)
295 : : return ret;
296 : : break;
297 : :
298 : 71 : case GIMPLE_EH_FILTER:
299 : 71 : ret = walk_tree (gimple_eh_filter_types_ptr (stmt), callback_op, wi,
300 : : pset);
301 : 71 : if (ret)
302 : : return ret;
303 : : break;
304 : :
305 : 26419747 : case GIMPLE_ASM:
306 : 26419747 : ret = walk_gimple_asm (as_a <gasm *> (stmt), callback_op, wi);
307 : 26419747 : if (ret)
308 : : return ret;
309 : : break;
310 : :
311 : 195998 : case GIMPLE_OMP_CONTINUE:
312 : 195998 : {
313 : 195998 : gomp_continue *cont_stmt = as_a <gomp_continue *> (stmt);
314 : 195998 : ret = walk_tree (gimple_omp_continue_control_def_ptr (cont_stmt),
315 : : callback_op, wi, pset);
316 : 195998 : if (ret)
317 : : return ret;
318 : :
319 : 195998 : ret = walk_tree (gimple_omp_continue_control_use_ptr (cont_stmt),
320 : : callback_op, wi, pset);
321 : 195998 : if (ret)
322 : : return ret;
323 : : }
324 : : break;
325 : :
326 : 1352 : case GIMPLE_OMP_CRITICAL:
327 : 1352 : {
328 : 1352 : gomp_critical *omp_stmt = as_a <gomp_critical *> (stmt);
329 : 1352 : ret = walk_tree (gimple_omp_critical_name_ptr (omp_stmt),
330 : : callback_op, wi, pset);
331 : 1352 : if (ret)
332 : : return ret;
333 : 1352 : ret = walk_tree (gimple_omp_critical_clauses_ptr (omp_stmt),
334 : : callback_op, wi, pset);
335 : 1352 : if (ret)
336 : : return ret;
337 : : }
338 : : break;
339 : :
340 : 5431 : case GIMPLE_OMP_ORDERED:
341 : 5431 : {
342 : 5431 : gomp_ordered *omp_stmt = as_a <gomp_ordered *> (stmt);
343 : 5431 : ret = walk_tree (gimple_omp_ordered_clauses_ptr (omp_stmt),
344 : : callback_op, wi, pset);
345 : 5431 : if (ret)
346 : : return ret;
347 : : }
348 : : break;
349 : :
350 : 824 : case GIMPLE_OMP_SCAN:
351 : 824 : {
352 : 824 : gomp_scan *scan_stmt = as_a <gomp_scan *> (stmt);
353 : 824 : ret = walk_tree (gimple_omp_scan_clauses_ptr (scan_stmt),
354 : : callback_op, wi, pset);
355 : 824 : if (ret)
356 : : return ret;
357 : : }
358 : : break;
359 : :
360 : 190444 : case GIMPLE_OMP_FOR:
361 : 190444 : ret = walk_tree (gimple_omp_for_clauses_ptr (stmt), callback_op, wi,
362 : : pset);
363 : 190444 : if (ret)
364 : : return ret;
365 : 466295 : for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
366 : : {
367 : 275851 : ret = walk_tree (gimple_omp_for_index_ptr (stmt, i), callback_op,
368 : : wi, pset);
369 : 275851 : if (ret)
370 : : return ret;
371 : 275851 : ret = walk_tree (gimple_omp_for_initial_ptr (stmt, i), callback_op,
372 : : wi, pset);
373 : 275851 : if (ret)
374 : : return ret;
375 : 275851 : ret = walk_tree (gimple_omp_for_final_ptr (stmt, i), callback_op,
376 : : wi, pset);
377 : 275851 : if (ret)
378 : : return ret;
379 : 275851 : ret = walk_tree (gimple_omp_for_incr_ptr (stmt, i), callback_op,
380 : : wi, pset);
381 : 275851 : if (ret)
382 : : return ret;
383 : : }
384 : : break;
385 : :
386 : 65770 : case GIMPLE_OMP_PARALLEL:
387 : 65770 : {
388 : 65770 : gomp_parallel *omp_par_stmt = as_a <gomp_parallel *> (stmt);
389 : 65770 : ret = walk_tree (gimple_omp_parallel_clauses_ptr (omp_par_stmt),
390 : : callback_op, wi, pset);
391 : 65770 : if (ret)
392 : : return ret;
393 : 65770 : ret = walk_tree (gimple_omp_parallel_child_fn_ptr (omp_par_stmt),
394 : : callback_op, wi, pset);
395 : 65770 : if (ret)
396 : : return ret;
397 : 65770 : ret = walk_tree (gimple_omp_parallel_data_arg_ptr (omp_par_stmt),
398 : : callback_op, wi, pset);
399 : 65770 : if (ret)
400 : : return ret;
401 : : }
402 : : break;
403 : :
404 : 15685 : case GIMPLE_OMP_TASK:
405 : 15685 : ret = walk_tree (gimple_omp_task_clauses_ptr (stmt), callback_op,
406 : : wi, pset);
407 : 15685 : if (ret)
408 : : return ret;
409 : 15685 : ret = walk_tree (gimple_omp_task_child_fn_ptr (stmt), callback_op,
410 : : wi, pset);
411 : 15685 : if (ret)
412 : : return ret;
413 : 15685 : ret = walk_tree (gimple_omp_task_data_arg_ptr (stmt), callback_op,
414 : : wi, pset);
415 : 15685 : if (ret)
416 : : return ret;
417 : 15685 : ret = walk_tree (gimple_omp_task_copy_fn_ptr (stmt), callback_op,
418 : : wi, pset);
419 : 15685 : if (ret)
420 : : return ret;
421 : 15685 : ret = walk_tree (gimple_omp_task_arg_size_ptr (stmt), callback_op,
422 : : wi, pset);
423 : 15685 : if (ret)
424 : : return ret;
425 : 15685 : ret = walk_tree (gimple_omp_task_arg_align_ptr (stmt), callback_op,
426 : : wi, pset);
427 : 15685 : if (ret)
428 : : return ret;
429 : : break;
430 : :
431 : 1554 : case GIMPLE_OMP_SECTIONS:
432 : 1554 : ret = walk_tree (gimple_omp_sections_clauses_ptr (stmt), callback_op,
433 : : wi, pset);
434 : 1554 : if (ret)
435 : : return ret;
436 : 1554 : ret = walk_tree (gimple_omp_sections_control_ptr (stmt), callback_op,
437 : : wi, pset);
438 : 1554 : if (ret)
439 : : return ret;
440 : :
441 : : break;
442 : :
443 : 4662 : case GIMPLE_OMP_SINGLE:
444 : 4662 : ret = walk_tree (gimple_omp_single_clauses_ptr (stmt), callback_op, wi,
445 : : pset);
446 : 4662 : if (ret)
447 : : return ret;
448 : : break;
449 : :
450 : 145157 : case GIMPLE_OMP_TARGET:
451 : 145157 : {
452 : 145157 : gomp_target *omp_stmt = as_a <gomp_target *> (stmt);
453 : 145157 : ret = walk_tree (gimple_omp_target_clauses_ptr (omp_stmt),
454 : : callback_op, wi, pset);
455 : 145157 : if (ret)
456 : : return ret;
457 : 145157 : ret = walk_tree (gimple_omp_target_child_fn_ptr (omp_stmt),
458 : : callback_op, wi, pset);
459 : 145157 : if (ret)
460 : : return ret;
461 : 145157 : ret = walk_tree (gimple_omp_target_data_arg_ptr (omp_stmt),
462 : : callback_op, wi, pset);
463 : 145157 : if (ret)
464 : : return ret;
465 : : }
466 : : break;
467 : :
468 : 33882 : case GIMPLE_OMP_TEAMS:
469 : 33882 : ret = walk_tree (gimple_omp_teams_clauses_ptr (stmt), callback_op, wi,
470 : : pset);
471 : 33882 : if (ret)
472 : : return ret;
473 : : break;
474 : :
475 : 48373 : case GIMPLE_OMP_ATOMIC_LOAD:
476 : 48373 : {
477 : 48373 : gomp_atomic_load *omp_stmt = as_a <gomp_atomic_load *> (stmt);
478 : 48373 : ret = walk_tree (gimple_omp_atomic_load_lhs_ptr (omp_stmt),
479 : : callback_op, wi, pset);
480 : 48373 : if (ret)
481 : : return ret;
482 : 48373 : ret = walk_tree (gimple_omp_atomic_load_rhs_ptr (omp_stmt),
483 : : callback_op, wi, pset);
484 : 48373 : if (ret)
485 : : return ret;
486 : : }
487 : : break;
488 : :
489 : 49383 : case GIMPLE_OMP_ATOMIC_STORE:
490 : 49383 : {
491 : 49383 : gomp_atomic_store *omp_stmt = as_a <gomp_atomic_store *> (stmt);
492 : 49383 : ret = walk_tree (gimple_omp_atomic_store_val_ptr (omp_stmt),
493 : : callback_op, wi, pset);
494 : 49383 : if (ret)
495 : : return ret;
496 : : }
497 : : break;
498 : :
499 : 12 : case GIMPLE_ASSUME:
500 : 12 : ret = walk_tree (gimple_assume_guard_ptr (stmt), callback_op, wi, pset);
501 : 12 : if (ret)
502 : : return ret;
503 : : break;
504 : :
505 : 61988 : case GIMPLE_TRANSACTION:
506 : 61988 : {
507 : 61988 : gtransaction *txn = as_a <gtransaction *> (stmt);
508 : :
509 : 61988 : ret = walk_tree (gimple_transaction_label_norm_ptr (txn),
510 : : callback_op, wi, pset);
511 : 61988 : if (ret)
512 : : return ret;
513 : 61988 : ret = walk_tree (gimple_transaction_label_uninst_ptr (txn),
514 : : callback_op, wi, pset);
515 : 61988 : if (ret)
516 : : return ret;
517 : 61988 : ret = walk_tree (gimple_transaction_label_over_ptr (txn),
518 : : callback_op, wi, pset);
519 : 61988 : if (ret)
520 : : return ret;
521 : : }
522 : : break;
523 : :
524 : 399748 : case GIMPLE_OMP_RETURN:
525 : 399748 : ret = walk_tree (gimple_omp_return_lhs_ptr (stmt), callback_op, wi,
526 : : pset);
527 : 399748 : if (ret)
528 : : return ret;
529 : : break;
530 : :
531 : : /* Tuples that do not have operands. */
532 : : case GIMPLE_NOP:
533 : : case GIMPLE_RESX:
534 : : case GIMPLE_PREDICT:
535 : : break;
536 : :
537 : 2774 : case GIMPLE_PHI:
538 : : /* PHIs are not GSS_WITH_OPS so we need to handle them explicitely. */
539 : 2774 : {
540 : 2774 : gphi *phi = as_a <gphi *> (stmt);
541 : 2774 : if (wi)
542 : : {
543 : 1996 : wi->val_only = true;
544 : 1996 : wi->is_lhs = true;
545 : : }
546 : 2774 : ret = walk_tree (gimple_phi_result_ptr (phi), callback_op, wi, pset);
547 : 2774 : if (wi)
548 : 1996 : wi->is_lhs = false;
549 : 2774 : if (ret)
550 : : return ret;
551 : 7430 : for (unsigned i = 0; i < gimple_phi_num_args (phi); ++i)
552 : : {
553 : 4656 : ret = walk_tree (gimple_phi_arg_def_ptr (phi, i),
554 : : callback_op, wi, pset);
555 : 4656 : if (ret)
556 : : return ret;
557 : : }
558 : : break;
559 : : }
560 : :
561 : 15014952146 : default:
562 : 15014952146 : {
563 : 15014952146 : enum gimple_statement_structure_enum gss;
564 : 15014952146 : gss = gimple_statement_structure (stmt);
565 : 15014952146 : if (gss == GSS_WITH_OPS || gss == GSS_WITH_MEM_OPS)
566 : 41433841982 : for (i = 0; i < gimple_num_ops (stmt); i++)
567 : : {
568 : 26425119037 : ret = walk_tree (gimple_op_ptr (stmt, i), callback_op, wi, pset);
569 : 26425119037 : if (ret)
570 : : return ret;
571 : : }
572 : : }
573 : : break;
574 : : }
575 : :
576 : : return NULL_TREE;
577 : : }
578 : :
579 : :
580 : : /* Walk the current statement in GSI (optionally using traversal state
581 : : stored in WI). If WI is NULL, no state is kept during traversal.
582 : : The callback CALLBACK_STMT is called. If CALLBACK_STMT indicates
583 : : that it has handled all the operands of the statement, its return
584 : : value is returned. Otherwise, the return value from CALLBACK_STMT
585 : : is discarded and its operands are scanned.
586 : :
587 : : If CALLBACK_STMT is NULL or it didn't handle the operands,
588 : : CALLBACK_OP is called on each operand of the statement via
589 : : walk_gimple_op. If walk_gimple_op returns non-NULL for any
590 : : operand, the remaining operands are not scanned. In this case, the
591 : : return value from CALLBACK_OP is returned.
592 : :
593 : : In any other case, NULL_TREE is returned. */
594 : :
595 : : tree
596 : 236670102 : walk_gimple_stmt (gimple_stmt_iterator *gsi, walk_stmt_fn callback_stmt,
597 : : walk_tree_fn callback_op, struct walk_stmt_info *wi)
598 : : {
599 : 236670102 : gimple *ret;
600 : 236670102 : tree tree_ret;
601 : 236670102 : gimple *stmt = gsi_stmt (*gsi);
602 : :
603 : 236670102 : if (wi)
604 : : {
605 : 236666542 : wi->gsi = *gsi;
606 : 236666542 : wi->removed_stmt = false;
607 : :
608 : 236666542 : if (wi->want_locations && gimple_has_location (stmt))
609 : 5201150 : input_location = gimple_location (stmt);
610 : : }
611 : :
612 : 236670102 : ret = NULL;
613 : :
614 : : /* Invoke the statement callback. Return if the callback handled
615 : : all of STMT operands by itself. */
616 : 236670102 : if (callback_stmt)
617 : : {
618 : 236631869 : bool handled_ops = false;
619 : 236631869 : tree_ret = callback_stmt (gsi, &handled_ops, wi);
620 : 236631853 : if (handled_ops)
621 : 20667574 : return tree_ret;
622 : :
623 : : /* If CALLBACK_STMT did not handle operands, it should not have
624 : : a value to return. */
625 : 215964279 : gcc_assert (tree_ret == NULL);
626 : :
627 : 215964279 : if (wi && wi->removed_stmt)
628 : : return NULL;
629 : :
630 : : /* Re-read stmt in case the callback changed it. */
631 : 215964279 : stmt = gsi_stmt (*gsi);
632 : : }
633 : :
634 : : /* If CALLBACK_OP is defined, invoke it on every operand of STMT. */
635 : 216002512 : if (callback_op)
636 : : {
637 : 24925467 : tree_ret = walk_gimple_op (stmt, callback_op, wi);
638 : 24925467 : if (tree_ret)
639 : : return tree_ret;
640 : : }
641 : :
642 : : /* If STMT can have statements inside (e.g. GIMPLE_BIND), walk them. */
643 : 216002512 : switch (gimple_code (stmt))
644 : : {
645 : 2767998 : case GIMPLE_BIND:
646 : 2767998 : ret = walk_gimple_seq_mod (gimple_bind_body_ptr (as_a <gbind *> (stmt)),
647 : : callback_stmt, callback_op, wi);
648 : 2767988 : if (ret)
649 : 12640 : return wi->callback_result;
650 : : break;
651 : :
652 : 35390 : case GIMPLE_CATCH:
653 : 35390 : ret = walk_gimple_seq_mod (gimple_catch_handler_ptr (
654 : : as_a <gcatch *> (stmt)),
655 : : callback_stmt, callback_op, wi);
656 : 35390 : if (ret)
657 : 0 : return wi->callback_result;
658 : : break;
659 : :
660 : 161 : case GIMPLE_EH_FILTER:
661 : 161 : ret = walk_gimple_seq_mod (gimple_eh_filter_failure_ptr (stmt), callback_stmt,
662 : : callback_op, wi);
663 : 161 : if (ret)
664 : 0 : return wi->callback_result;
665 : : break;
666 : :
667 : 819 : case GIMPLE_EH_ELSE:
668 : 819 : {
669 : 819 : geh_else *eh_else_stmt = as_a <geh_else *> (stmt);
670 : 819 : ret = walk_gimple_seq_mod (gimple_eh_else_n_body_ptr (eh_else_stmt),
671 : : callback_stmt, callback_op, wi);
672 : 819 : if (ret)
673 : 0 : return wi->callback_result;
674 : 819 : ret = walk_gimple_seq_mod (gimple_eh_else_e_body_ptr (eh_else_stmt),
675 : : callback_stmt, callback_op, wi);
676 : 819 : if (ret)
677 : 0 : return wi->callback_result;
678 : : }
679 : : break;
680 : :
681 : 641975 : case GIMPLE_TRY:
682 : 641975 : ret = walk_gimple_seq_mod (gimple_try_eval_ptr (stmt), callback_stmt, callback_op,
683 : : wi);
684 : 641969 : if (ret)
685 : 204 : return wi->callback_result;
686 : :
687 : 641765 : ret = walk_gimple_seq_mod (gimple_try_cleanup_ptr (stmt), callback_stmt,
688 : : callback_op, wi);
689 : 641765 : if (ret)
690 : 0 : return wi->callback_result;
691 : : break;
692 : :
693 : 8789 : case GIMPLE_OMP_FOR:
694 : 8789 : ret = walk_gimple_seq_mod (gimple_omp_for_pre_body_ptr (stmt), callback_stmt,
695 : : callback_op, wi);
696 : 8789 : if (ret)
697 : 0 : return wi->callback_result;
698 : :
699 : : /* FALL THROUGH. */
700 : 28026 : case GIMPLE_OMP_CRITICAL:
701 : 28026 : case GIMPLE_OMP_MASTER:
702 : 28026 : case GIMPLE_OMP_MASKED:
703 : 28026 : case GIMPLE_OMP_TASKGROUP:
704 : 28026 : case GIMPLE_OMP_ORDERED:
705 : 28026 : case GIMPLE_OMP_SCAN:
706 : 28026 : case GIMPLE_OMP_SECTION:
707 : 28026 : case GIMPLE_OMP_STRUCTURED_BLOCK:
708 : 28026 : case GIMPLE_OMP_PARALLEL:
709 : 28026 : case GIMPLE_OMP_TASK:
710 : 28026 : case GIMPLE_OMP_SCOPE:
711 : 28026 : case GIMPLE_OMP_DISPATCH:
712 : 28026 : case GIMPLE_OMP_SECTIONS:
713 : 28026 : case GIMPLE_OMP_SINGLE:
714 : 28026 : case GIMPLE_OMP_TARGET:
715 : 28026 : case GIMPLE_OMP_TEAMS:
716 : 28026 : ret = walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), callback_stmt,
717 : : callback_op, wi);
718 : 28026 : if (ret)
719 : 0 : return wi->callback_result;
720 : : break;
721 : :
722 : 0 : case GIMPLE_WITH_CLEANUP_EXPR:
723 : 0 : ret = walk_gimple_seq_mod (gimple_wce_cleanup_ptr (stmt), callback_stmt,
724 : : callback_op, wi);
725 : 0 : if (ret)
726 : 0 : return wi->callback_result;
727 : : break;
728 : :
729 : 27 : case GIMPLE_ASSUME:
730 : 27 : ret = walk_gimple_seq_mod (gimple_assume_body_ptr (stmt),
731 : : callback_stmt, callback_op, wi);
732 : 27 : if (ret)
733 : 0 : return wi->callback_result;
734 : : break;
735 : :
736 : 688 : case GIMPLE_TRANSACTION:
737 : 688 : ret = walk_gimple_seq_mod (gimple_transaction_body_ptr (
738 : : as_a <gtransaction *> (stmt)),
739 : : callback_stmt, callback_op, wi);
740 : 688 : if (ret)
741 : 3 : return wi->callback_result;
742 : : break;
743 : :
744 : 212527428 : default:
745 : 212527428 : gcc_assert (!gimple_has_substatements (stmt));
746 : : break;
747 : : }
748 : :
749 : : return NULL;
750 : : }
751 : :
752 : : /* From a tree operand OP return the base of a load or store operation
753 : : or NULL_TREE if OP is not a load or a store. */
754 : :
755 : : static tree
756 : 1171330707 : get_base_loadstore (tree op)
757 : : {
758 : 1340805965 : while (handled_component_p (op))
759 : 169475258 : op = TREE_OPERAND (op, 0);
760 : 1171330707 : if (DECL_P (op)
761 : 933985945 : || INDIRECT_REF_P (op)
762 : 933985945 : || TREE_CODE (op) == MEM_REF
763 : 752050390 : || TREE_CODE (op) == TARGET_MEM_REF)
764 : 425569234 : return op;
765 : : return NULL_TREE;
766 : : }
767 : :
768 : :
769 : : /* For the statement STMT call the callbacks VISIT_LOAD, VISIT_STORE and
770 : : VISIT_ADDR if non-NULL on loads, store and address-taken operands
771 : : passing the STMT, the base of the operand, the operand itself containing
772 : : the base and DATA to it. The base will be either a decl, an indirect
773 : : reference (including TARGET_MEM_REF) or the argument of an address
774 : : expression.
775 : : Returns the results of these callbacks or'ed. */
776 : :
777 : : bool
778 : 2386011326 : walk_stmt_load_store_addr_ops (gimple *stmt, void *data,
779 : : walk_stmt_load_store_addr_fn visit_load,
780 : : walk_stmt_load_store_addr_fn visit_store,
781 : : walk_stmt_load_store_addr_fn visit_addr)
782 : : {
783 : 2386011326 : bool ret = false;
784 : 2386011326 : unsigned i;
785 : 2386011326 : if (gimple_assign_single_p (stmt))
786 : : {
787 : 615270747 : tree lhs, rhs, arg;
788 : 615270747 : if (visit_store)
789 : : {
790 : 406728486 : arg = gimple_assign_lhs (stmt);
791 : 406728486 : lhs = get_base_loadstore (arg);
792 : 406728486 : if (lhs)
793 : 204089939 : ret |= visit_store (stmt, lhs, arg, data);
794 : : }
795 : 615270747 : arg = gimple_assign_rhs1 (stmt);
796 : 615270747 : rhs = arg;
797 : 1456510333 : while (handled_component_p (rhs))
798 : 225968839 : rhs = TREE_OPERAND (rhs, 0);
799 : 615270747 : if (visit_addr)
800 : : {
801 : 392580361 : if (TREE_CODE (rhs) == ADDR_EXPR)
802 : 34394083 : ret |= visit_addr (stmt, TREE_OPERAND (rhs, 0), arg, data);
803 : 358186278 : else if (TREE_CODE (rhs) == OBJ_TYPE_REF
804 : 358186278 : && TREE_CODE (OBJ_TYPE_REF_OBJECT (rhs)) == ADDR_EXPR)
805 : 406 : ret |= visit_addr (stmt, TREE_OPERAND (OBJ_TYPE_REF_OBJECT (rhs),
806 : : 0), arg, data);
807 : 358185872 : else if (TREE_CODE (rhs) == CONSTRUCTOR)
808 : : {
809 : : unsigned int ix;
810 : : tree val;
811 : :
812 : 45033481 : FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (rhs), ix, val)
813 : 2713594 : if (TREE_CODE (val) == ADDR_EXPR)
814 : 0 : ret |= visit_addr (stmt, TREE_OPERAND (val, 0), arg, data);
815 : 2713594 : else if (TREE_CODE (val) == OBJ_TYPE_REF
816 : 2713594 : && TREE_CODE (OBJ_TYPE_REF_OBJECT (val)) == ADDR_EXPR)
817 : 0 : ret |= visit_addr (stmt,
818 : 0 : TREE_OPERAND (OBJ_TYPE_REF_OBJECT (val),
819 : : 0), arg, data);
820 : : }
821 : : }
822 : 615270747 : if (visit_load)
823 : : {
824 : 406726436 : rhs = get_base_loadstore (rhs);
825 : 406726436 : if (rhs)
826 : 181403372 : ret |= visit_load (stmt, rhs, arg, data);
827 : : }
828 : : }
829 : 1770740579 : else if (visit_addr
830 : 1770740579 : && (is_gimple_assign (stmt)
831 : 848608249 : || gimple_code (stmt) == GIMPLE_COND))
832 : : {
833 : 1075875254 : for (i = 0; i < gimple_num_ops (stmt); ++i)
834 : : {
835 : 816827457 : tree op = gimple_op (stmt, i);
836 : 816827457 : if (op == NULL_TREE)
837 : : ;
838 : 640289449 : else if (TREE_CODE (op) == ADDR_EXPR)
839 : 7260474 : ret |= visit_addr (stmt, TREE_OPERAND (op, 0), op, data);
840 : : }
841 : : }
842 : 1511692782 : else if (gcall *call_stmt = dyn_cast <gcall *> (stmt))
843 : : {
844 : 210961191 : if (visit_store)
845 : : {
846 : 154538836 : tree arg = gimple_call_lhs (call_stmt);
847 : 154538836 : if (arg)
848 : : {
849 : 61363405 : tree lhs = get_base_loadstore (arg);
850 : 61363405 : if (lhs)
851 : 12089071 : ret |= visit_store (stmt, lhs, arg, data);
852 : : }
853 : : }
854 : 210961191 : if (visit_load || visit_addr)
855 : 634464501 : for (i = 0; i < gimple_call_num_args (call_stmt); ++i)
856 : : {
857 : 423898586 : tree arg = gimple_call_arg (call_stmt, i);
858 : 423898586 : if (visit_addr
859 : 243402900 : && TREE_CODE (arg) == ADDR_EXPR)
860 : 73478231 : ret |= visit_addr (stmt, TREE_OPERAND (arg, 0), arg, data);
861 : 350420355 : else if (visit_load)
862 : : {
863 : 273045498 : tree rhs = get_base_loadstore (arg);
864 : 273045498 : if (rhs)
865 : 22430921 : ret |= visit_load (stmt, rhs, arg, data);
866 : : }
867 : : }
868 : 210565915 : if (visit_addr
869 : 122485752 : && gimple_call_chain (call_stmt)
870 : 211127004 : && TREE_CODE (gimple_call_chain (call_stmt)) == ADDR_EXPR)
871 : 231318 : ret |= visit_addr (stmt, TREE_OPERAND (gimple_call_chain (call_stmt), 0),
872 : : gimple_call_chain (call_stmt), data);
873 : 210961191 : if (visit_addr
874 : 122485752 : && gimple_call_return_slot_opt_p (call_stmt)
875 : 4412095 : && gimple_call_lhs (call_stmt) != NULL_TREE
876 : 215194437 : && TREE_ADDRESSABLE (TREE_TYPE (gimple_call_lhs (call_stmt))))
877 : 956048 : ret |= visit_addr (stmt, gimple_call_lhs (call_stmt),
878 : : gimple_call_lhs (call_stmt), data);
879 : : }
880 : 1300731591 : else if (gasm *asm_stmt = dyn_cast <gasm *> (stmt))
881 : : {
882 : 1744055 : unsigned noutputs;
883 : 1744055 : const char *constraint;
884 : 1744055 : const char **oconstraints;
885 : 1744055 : bool allows_mem, allows_reg, is_inout;
886 : 1744055 : noutputs = gimple_asm_noutputs (asm_stmt);
887 : 1744055 : oconstraints = XALLOCAVEC (const char *, noutputs);
888 : 1744055 : if (visit_store || visit_addr)
889 : 3278602 : for (i = 0; i < gimple_asm_noutputs (asm_stmt); ++i)
890 : : {
891 : 1534547 : tree link = gimple_asm_output_op (asm_stmt, i);
892 : 1534547 : tree op = get_base_loadstore (TREE_VALUE (link));
893 : 1534547 : if (op && visit_store)
894 : 222305 : ret |= visit_store (stmt, op, TREE_VALUE (link), data);
895 : 1534547 : if (visit_addr)
896 : : {
897 : 1050409 : constraint = TREE_STRING_POINTER
898 : : (TREE_VALUE (TREE_PURPOSE (link)));
899 : 1050409 : oconstraints[i] = constraint;
900 : 1050409 : parse_output_constraint (&constraint, i, 0, 0, &allows_mem,
901 : : &allows_reg, &is_inout, nullptr);
902 : 1050409 : if (op && !allows_reg && allows_mem)
903 : 63324 : ret |= visit_addr (stmt, op, TREE_VALUE (link), data);
904 : : }
905 : : }
906 : 1744055 : if (visit_load || visit_addr)
907 : 2735772 : for (i = 0; i < gimple_asm_ninputs (asm_stmt); ++i)
908 : : {
909 : 992842 : tree link = gimple_asm_input_op (asm_stmt, i);
910 : 992842 : tree op = TREE_VALUE (link);
911 : 992842 : if (visit_addr
912 : 708777 : && TREE_CODE (op) == ADDR_EXPR)
913 : 72220 : ret |= visit_addr (stmt, TREE_OPERAND (op, 0), op, data);
914 : 920622 : else if (visit_load || visit_addr)
915 : : {
916 : 920622 : op = get_base_loadstore (op);
917 : 920622 : if (op)
918 : : {
919 : 151254 : if (visit_load)
920 : 79071 : ret |= visit_load (stmt, op, TREE_VALUE (link), data);
921 : 151254 : if (visit_addr)
922 : : {
923 : 126374 : constraint = TREE_STRING_POINTER
924 : : (TREE_VALUE (TREE_PURPOSE (link)));
925 : 126374 : parse_input_constraint (&constraint, 0, 0, noutputs,
926 : : 0, oconstraints, &allows_mem,
927 : : &allows_reg, nullptr);
928 : 126374 : if (!allows_reg && allows_mem)
929 : 69016 : ret |= visit_addr (stmt, op, TREE_VALUE (link),
930 : : data);
931 : : }
932 : : }
933 : : }
934 : : }
935 : : }
936 : 1298987536 : else if (greturn *return_stmt = dyn_cast <greturn *> (stmt))
937 : : {
938 : 52571642 : tree op = gimple_return_retval (return_stmt);
939 : 52571642 : if (op)
940 : : {
941 : 28445663 : if (visit_addr
942 : 15636844 : && TREE_CODE (op) == ADDR_EXPR)
943 : 26882 : ret |= visit_addr (stmt, TREE_OPERAND (op, 0), op, data);
944 : 28418781 : else if (visit_load)
945 : : {
946 : 21011713 : tree base = get_base_loadstore (op);
947 : 21011713 : if (base)
948 : 5019038 : ret |= visit_load (stmt, base, op, data);
949 : : }
950 : : }
951 : : }
952 : 1246415894 : else if (visit_addr
953 : 1246415894 : && gimple_code (stmt) == GIMPLE_PHI)
954 : : {
955 : 101694612 : for (i = 0; i < gimple_phi_num_args (stmt); ++i)
956 : : {
957 : 73402837 : tree op = gimple_phi_arg_def (stmt, i);
958 : 73402837 : if (TREE_CODE (op) == ADDR_EXPR)
959 : 483372 : ret |= visit_addr (stmt, TREE_OPERAND (op, 0), op, data);
960 : : }
961 : : }
962 : 1218124119 : else if (visit_addr
963 : 1218124119 : && gimple_code (stmt) == GIMPLE_GOTO)
964 : : {
965 : 5392 : tree op = gimple_goto_dest (stmt);
966 : 5392 : if (TREE_CODE (op) == ADDR_EXPR)
967 : 83 : ret |= visit_addr (stmt, TREE_OPERAND (op, 0), op, data);
968 : : }
969 : :
970 : 2386011326 : return ret;
971 : : }
972 : :
973 : : /* Like walk_stmt_load_store_addr_ops but with NULL visit_addr. IPA-CP
974 : : should make a faster clone for this case. */
975 : :
976 : : bool
977 : 974043923 : walk_stmt_load_store_ops (gimple *stmt, void *data,
978 : : walk_stmt_load_store_addr_fn visit_load,
979 : : walk_stmt_load_store_addr_fn visit_store)
980 : : {
981 : 974043923 : return walk_stmt_load_store_addr_ops (stmt, data,
982 : 974043923 : visit_load, visit_store, NULL);
983 : : }
|