Line data Source code
1 : /* Gimple walk support.
2 :
3 : Copyright (C) 2007-2026 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 40509267 : 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 40509267 : gimple_stmt_iterator gsi;
48 :
49 326675649 : for (gsi = gsi_start (*pseq); !gsi_end_p (gsi); )
50 : {
51 246760568 : tree ret = walk_gimple_stmt (&gsi, callback_stmt, callback_op, wi);
52 246760540 : if (ret)
53 : {
54 : /* If CALLBACK_STMT or CALLBACK_OP return a value, WI must exist
55 : to hold it. */
56 81939 : gcc_assert (wi);
57 81939 : wi->callback_result = ret;
58 :
59 81939 : gimple *g;
60 81939 : if (!wi->removed_stmt)
61 81939 : g = gsi_stmt (gsi);
62 : else
63 : {
64 0 : g = NULL;
65 0 : wi->removed_stmt = false;
66 : }
67 81939 : return g;
68 : }
69 :
70 246678601 : if (!wi->removed_stmt)
71 246674555 : gsi_next (&gsi);
72 : else
73 4046 : wi->removed_stmt = false;
74 : }
75 :
76 40427300 : if (wi)
77 40427300 : 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 33890127 : walk_gimple_seq (gimple_seq seq, walk_stmt_fn callback_stmt,
88 : walk_tree_fn callback_op, struct walk_stmt_info *wi)
89 : {
90 33890127 : gimple_seq seq2 = seq;
91 33890127 : gimple *ret = walk_gimple_seq_mod (&seq2, callback_stmt, callback_op, wi);
92 33890122 : gcc_assert (seq2 == seq);
93 33890122 : return ret;
94 : }
95 :
96 :
97 : /* Helper function for walk_gimple_stmt. Walk operands of a GIMPLE_ASM. */
98 :
99 : static tree
100 27224059 : walk_gimple_asm (gasm *stmt, walk_tree_fn callback_op,
101 : struct walk_stmt_info *wi)
102 : {
103 27224059 : tree ret, op;
104 27224059 : unsigned noutputs;
105 27224059 : const char **oconstraints;
106 27224059 : unsigned i, n;
107 27224059 : const char *constraint;
108 27224059 : bool allows_mem, allows_reg, is_inout;
109 :
110 27224059 : noutputs = gimple_asm_noutputs (stmt);
111 27224059 : oconstraints = (const char **) alloca ((noutputs) * sizeof (const char *));
112 :
113 49226608 : for (i = 0; i < noutputs; i++)
114 : {
115 22002559 : op = gimple_asm_output_op (stmt, i);
116 22002559 : constraint = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (op)));
117 22002559 : oconstraints[i] = constraint;
118 22002559 : if (wi)
119 : {
120 22002467 : if (parse_output_constraint (&constraint, i, 0, 0, &allows_mem,
121 : &allows_reg, &is_inout, nullptr))
122 22002467 : wi->val_only = (allows_reg || !allows_mem);
123 : }
124 22002467 : if (wi)
125 22002467 : wi->is_lhs = true;
126 22002559 : ret = walk_tree (&TREE_VALUE (op), callback_op, wi, NULL);
127 22002559 : if (ret)
128 : return ret;
129 : }
130 :
131 27224049 : n = gimple_asm_ninputs (stmt);
132 41934503 : for (i = 0; i < n; i++)
133 : {
134 14710460 : op = gimple_asm_input_op (stmt, i);
135 14710460 : constraint = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (op)));
136 :
137 14710460 : if (wi)
138 : {
139 14710364 : if (parse_input_constraint (&constraint, 0, 0, noutputs, 0,
140 : oconstraints, &allows_mem, &allows_reg,
141 : nullptr))
142 : {
143 14710364 : wi->val_only = (allows_reg || !allows_mem);
144 : /* Although input "m" is not really a LHS, we need a lvalue. */
145 14710364 : wi->is_lhs = !wi->val_only;
146 : }
147 : }
148 14710460 : ret = walk_tree (&TREE_VALUE (op), callback_op, wi, NULL);
149 14710460 : if (ret)
150 : return ret;
151 : }
152 :
153 27224043 : if (wi)
154 : {
155 27223970 : wi->is_lhs = false;
156 27223970 : wi->val_only = true;
157 : }
158 :
159 27224043 : n = gimple_asm_nlabels (stmt);
160 27432948 : for (i = 0; i < n; i++)
161 : {
162 208905 : op = gimple_asm_label_op (stmt, i);
163 208905 : ret = walk_tree (&TREE_VALUE (op), callback_op, wi, NULL);
164 208905 : 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 25338894208 : walk_gimple_op (gimple *stmt, walk_tree_fn callback_op,
189 : struct walk_stmt_info *wi)
190 : {
191 25338894208 : hash_set<tree> *pset = (wi) ? wi->pset : NULL;
192 25337942504 : unsigned i;
193 50676836712 : tree ret = NULL_TREE;
194 :
195 25337942504 : if (wi)
196 25337942504 : wi->stmt = stmt;
197 :
198 25338894208 : switch (gimple_code (stmt))
199 : {
200 8672494876 : 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 8672494876 : if (wi)
204 : {
205 8671840761 : tree lhs = gimple_assign_lhs (stmt);
206 8671840761 : wi->val_only
207 17343681522 : = (is_gimple_reg_type (TREE_TYPE (lhs)) && !is_gimple_reg (lhs))
208 15208609269 : || gimple_assign_rhs_class (stmt) != GIMPLE_SINGLE_RHS;
209 : }
210 :
211 19372286415 : for (i = 1; i < gimple_num_ops (stmt); i++)
212 : {
213 10699873834 : ret = walk_tree (gimple_op_ptr (stmt, i), callback_op, wi,
214 : pset);
215 10699873834 : 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 8672412581 : 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 8671829448 : tree rhs1 = gimple_assign_rhs1 (stmt);
226 8671829448 : wi->val_only
227 8671829448 : = (is_gimple_reg_type (TREE_TYPE (rhs1)) && !is_gimple_reg (rhs1))
228 13380514292 : || gimple_assign_rhs_class (stmt) != GIMPLE_SINGLE_RHS;
229 8671829448 : wi->is_lhs = true;
230 : }
231 :
232 8672412581 : ret = walk_tree (gimple_op_ptr (stmt, 0), callback_op, wi, pset);
233 8672412581 : if (ret)
234 : return ret;
235 :
236 8672385195 : if (wi)
237 : {
238 8671828811 : wi->val_only = true;
239 8671828811 : wi->is_lhs = false;
240 : }
241 : break;
242 :
243 2004857290 : case GIMPLE_CALL:
244 2004857290 : if (wi)
245 : {
246 2004787183 : wi->is_lhs = false;
247 2004787183 : wi->val_only = true;
248 : }
249 :
250 2004857290 : ret = walk_tree (gimple_call_chain_ptr (as_a <gcall *> (stmt)),
251 : callback_op, wi, pset);
252 2004857290 : if (ret)
253 : return ret;
254 :
255 2004857230 : ret = walk_tree (gimple_call_fn_ptr (stmt), callback_op, wi, pset);
256 2004857230 : if (ret)
257 : return ret;
258 :
259 5991683169 : for (i = 0; i < gimple_call_num_args (stmt); i++)
260 : {
261 3986830390 : if (wi)
262 3986712985 : wi->val_only
263 3986712985 : = is_gimple_reg_type (TREE_TYPE (gimple_call_arg (stmt, i)));
264 3986830390 : ret = walk_tree (gimple_call_arg_ptr (stmt, i), callback_op, wi,
265 : pset);
266 3986830390 : if (ret)
267 : return ret;
268 : }
269 :
270 2004852779 : if (gimple_call_lhs (stmt))
271 : {
272 795413815 : if (wi)
273 : {
274 795392657 : wi->is_lhs = true;
275 795392657 : wi->val_only
276 795392657 : = is_gimple_reg_type (TREE_TYPE (gimple_call_lhs (stmt)));
277 : }
278 :
279 795413815 : ret = walk_tree (gimple_call_lhs_ptr (stmt), callback_op, wi, pset);
280 795413815 : if (ret)
281 : return ret;
282 : }
283 :
284 2004852392 : if (wi)
285 : {
286 2004785955 : wi->is_lhs = false;
287 2004785955 : wi->val_only = true;
288 : }
289 : break;
290 :
291 17635 : case GIMPLE_CATCH:
292 17635 : ret = walk_tree (gimple_catch_types_ptr (as_a <gcatch *> (stmt)),
293 : callback_op, wi, pset);
294 17635 : 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 27224059 : case GIMPLE_ASM:
306 27224059 : ret = walk_gimple_asm (as_a <gasm *> (stmt), callback_op, wi);
307 27224059 : if (ret)
308 : return ret;
309 : break;
310 :
311 196520 : case GIMPLE_OMP_CONTINUE:
312 196520 : {
313 196520 : gomp_continue *cont_stmt = as_a <gomp_continue *> (stmt);
314 196520 : ret = walk_tree (gimple_omp_continue_control_def_ptr (cont_stmt),
315 : callback_op, wi, pset);
316 196520 : if (ret)
317 : return ret;
318 :
319 196520 : ret = walk_tree (gimple_omp_continue_control_use_ptr (cont_stmt),
320 : callback_op, wi, pset);
321 196520 : 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 5463 : case GIMPLE_OMP_ORDERED:
341 5463 : {
342 5463 : gomp_ordered *omp_stmt = as_a <gomp_ordered *> (stmt);
343 5463 : ret = walk_tree (gimple_omp_ordered_clauses_ptr (omp_stmt),
344 : callback_op, wi, pset);
345 5463 : 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 190934 : case GIMPLE_OMP_FOR:
361 190934 : ret = walk_tree (gimple_omp_for_clauses_ptr (stmt), callback_op, wi,
362 : pset);
363 190934 : if (ret)
364 : return ret;
365 467499 : for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
366 : {
367 276565 : ret = walk_tree (gimple_omp_for_index_ptr (stmt, i), callback_op,
368 : wi, pset);
369 276565 : if (ret)
370 : return ret;
371 276565 : ret = walk_tree (gimple_omp_for_initial_ptr (stmt, i), callback_op,
372 : wi, pset);
373 276565 : if (ret)
374 : return ret;
375 276565 : ret = walk_tree (gimple_omp_for_final_ptr (stmt, i), callback_op,
376 : wi, pset);
377 276565 : if (ret)
378 : return ret;
379 276565 : ret = walk_tree (gimple_omp_for_incr_ptr (stmt, i), callback_op,
380 : wi, pset);
381 276565 : if (ret)
382 : return ret;
383 : }
384 : break;
385 :
386 65692 : case GIMPLE_OMP_PARALLEL:
387 65692 : {
388 65692 : gomp_parallel *omp_par_stmt = as_a <gomp_parallel *> (stmt);
389 65692 : ret = walk_tree (gimple_omp_parallel_clauses_ptr (omp_par_stmt),
390 : callback_op, wi, pset);
391 65692 : if (ret)
392 : return ret;
393 65692 : ret = walk_tree (gimple_omp_parallel_child_fn_ptr (omp_par_stmt),
394 : callback_op, wi, pset);
395 65692 : if (ret)
396 : return ret;
397 65692 : ret = walk_tree (gimple_omp_parallel_data_arg_ptr (omp_par_stmt),
398 : callback_op, wi, pset);
399 65692 : if (ret)
400 : return ret;
401 : }
402 : break;
403 :
404 15717 : case GIMPLE_OMP_TASK:
405 15717 : ret = walk_tree (gimple_omp_task_clauses_ptr (stmt), callback_op,
406 : wi, pset);
407 15717 : if (ret)
408 : return ret;
409 15717 : ret = walk_tree (gimple_omp_task_child_fn_ptr (stmt), callback_op,
410 : wi, pset);
411 15717 : if (ret)
412 : return ret;
413 15717 : ret = walk_tree (gimple_omp_task_data_arg_ptr (stmt), callback_op,
414 : wi, pset);
415 15717 : if (ret)
416 : return ret;
417 15717 : ret = walk_tree (gimple_omp_task_copy_fn_ptr (stmt), callback_op,
418 : wi, pset);
419 15717 : if (ret)
420 : return ret;
421 15717 : ret = walk_tree (gimple_omp_task_arg_size_ptr (stmt), callback_op,
422 : wi, pset);
423 15717 : if (ret)
424 : return ret;
425 15717 : ret = walk_tree (gimple_omp_task_arg_align_ptr (stmt), callback_op,
426 : wi, pset);
427 15717 : 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 4666 : case GIMPLE_OMP_SINGLE:
444 4666 : ret = walk_tree (gimple_omp_single_clauses_ptr (stmt), callback_op, wi,
445 : pset);
446 4666 : if (ret)
447 : return ret;
448 : break;
449 :
450 147553 : case GIMPLE_OMP_TARGET:
451 147553 : {
452 147553 : gomp_target *omp_stmt = as_a <gomp_target *> (stmt);
453 147553 : ret = walk_tree (gimple_omp_target_clauses_ptr (omp_stmt),
454 : callback_op, wi, pset);
455 147553 : if (ret)
456 : return ret;
457 147553 : ret = walk_tree (gimple_omp_target_child_fn_ptr (omp_stmt),
458 : callback_op, wi, pset);
459 147553 : if (ret)
460 : return ret;
461 147553 : ret = walk_tree (gimple_omp_target_data_arg_ptr (omp_stmt),
462 : callback_op, wi, pset);
463 147553 : if (ret)
464 : return ret;
465 : }
466 : break;
467 :
468 33705 : case GIMPLE_OMP_TEAMS:
469 33705 : ret = walk_tree (gimple_omp_teams_clauses_ptr (stmt), callback_op, wi,
470 : pset);
471 33705 : if (ret)
472 : return ret;
473 : break;
474 :
475 49006 : case GIMPLE_OMP_ATOMIC_LOAD:
476 49006 : {
477 49006 : gomp_atomic_load *omp_stmt = as_a <gomp_atomic_load *> (stmt);
478 49006 : ret = walk_tree (gimple_omp_atomic_load_lhs_ptr (omp_stmt),
479 : callback_op, wi, pset);
480 49006 : if (ret)
481 : return ret;
482 49006 : ret = walk_tree (gimple_omp_atomic_load_rhs_ptr (omp_stmt),
483 : callback_op, wi, pset);
484 49006 : if (ret)
485 : return ret;
486 : }
487 : break;
488 :
489 50012 : case GIMPLE_OMP_ATOMIC_STORE:
490 50012 : {
491 50012 : gomp_atomic_store *omp_stmt = as_a <gomp_atomic_store *> (stmt);
492 50012 : ret = walk_tree (gimple_omp_atomic_store_val_ptr (omp_stmt),
493 : callback_op, wi, pset);
494 50012 : 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 62324 : case GIMPLE_TRANSACTION:
506 62324 : {
507 62324 : gtransaction *txn = as_a <gtransaction *> (stmt);
508 :
509 62324 : ret = walk_tree (gimple_transaction_label_norm_ptr (txn),
510 : callback_op, wi, pset);
511 62324 : if (ret)
512 : return ret;
513 62324 : ret = walk_tree (gimple_transaction_label_uninst_ptr (txn),
514 : callback_op, wi, pset);
515 62324 : if (ret)
516 : return ret;
517 62324 : ret = walk_tree (gimple_transaction_label_over_ptr (txn),
518 : callback_op, wi, pset);
519 62324 : if (ret)
520 : return ret;
521 : }
522 : break;
523 :
524 401648 : case GIMPLE_OMP_RETURN:
525 401648 : ret = walk_tree (gimple_omp_return_lhs_ptr (stmt), callback_op, wi,
526 : pset);
527 401648 : 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 explicitly. */
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 7531 : for (unsigned i = 0; i < gimple_phi_num_args (phi); ++i)
552 : {
553 4757 : ret = walk_tree (gimple_phi_arg_def_ptr (phi, i),
554 : callback_op, wi, pset);
555 4757 : if (ret)
556 : return ret;
557 : }
558 : break;
559 : }
560 :
561 14494921806 : default:
562 14494921806 : {
563 14494921806 : enum gimple_statement_structure_enum gss;
564 14494921806 : gss = gimple_statement_structure (stmt);
565 14494921806 : if (gss == GSS_WITH_OPS || gss == GSS_WITH_MEM_OPS)
566 40287840232 : for (i = 0; i < gimple_num_ops (stmt); i++)
567 : {
568 25799241967 : ret = walk_tree (gimple_op_ptr (stmt, i), callback_op, wi, pset);
569 25799241967 : 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 248843028 : 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 248843028 : gimple *ret;
600 248843028 : tree tree_ret;
601 248843028 : gimple *stmt = gsi_stmt (*gsi);
602 :
603 248843028 : if (wi)
604 : {
605 248840523 : wi->gsi = *gsi;
606 248840523 : wi->removed_stmt = false;
607 :
608 248840523 : if (wi->want_locations && gimple_has_location (stmt))
609 5437452 : input_location = gimple_location (stmt);
610 : }
611 :
612 248843028 : ret = NULL;
613 :
614 : /* Invoke the statement callback. Return if the callback handled
615 : all of STMT operands by itself. */
616 248843028 : if (callback_stmt)
617 : {
618 248805273 : bool handled_ops = false;
619 248805273 : tree_ret = callback_stmt (gsi, &handled_ops, wi);
620 248805259 : if (handled_ops)
621 36812657 : return tree_ret;
622 :
623 : /* If CALLBACK_STMT did not handle operands, it should not have
624 : a value to return. */
625 211992602 : gcc_assert (tree_ret == NULL);
626 :
627 211992602 : if (wi && wi->removed_stmt)
628 : return NULL;
629 :
630 : /* Re-read stmt in case the callback changed it. */
631 211992602 : stmt = gsi_stmt (*gsi);
632 : }
633 :
634 : /* If CALLBACK_OP is defined, invoke it on every operand of STMT. */
635 212030357 : if (callback_op)
636 : {
637 25618526 : tree_ret = walk_gimple_op (stmt, callback_op, wi);
638 25618526 : if (tree_ret)
639 : return tree_ret;
640 : }
641 :
642 : /* If STMT can have statements inside (e.g. GIMPLE_BIND), walk them. */
643 212030357 : switch (gimple_code (stmt))
644 : {
645 2816773 : case GIMPLE_BIND:
646 2816773 : ret = walk_gimple_seq_mod (gimple_bind_body_ptr (as_a <gbind *> (stmt)),
647 : callback_stmt, callback_op, wi);
648 2816764 : if (ret)
649 11999 : return wi->callback_result;
650 : break;
651 :
652 35363 : case GIMPLE_CATCH:
653 35363 : ret = walk_gimple_seq_mod (gimple_catch_handler_ptr (
654 : as_a <gcatch *> (stmt)),
655 : callback_stmt, callback_op, wi);
656 35363 : 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 650720 : case GIMPLE_TRY:
682 650720 : ret = walk_gimple_seq_mod (gimple_try_eval_ptr (stmt), callback_stmt, callback_op,
683 : wi);
684 650715 : if (ret)
685 226 : return wi->callback_result;
686 :
687 650489 : ret = walk_gimple_seq_mod (gimple_try_cleanup_ptr (stmt), callback_stmt,
688 : callback_op, wi);
689 650489 : if (ret)
690 0 : return wi->callback_result;
691 : break;
692 :
693 23597 : case GIMPLE_OMP_FOR:
694 23597 : ret = walk_gimple_seq_mod (gimple_omp_for_pre_body_ptr (stmt), callback_stmt,
695 : callback_op, wi);
696 23597 : if (ret)
697 0 : return wi->callback_result;
698 :
699 : /* FALL THROUGH. */
700 64022 : case GIMPLE_OMP_CRITICAL:
701 64022 : case GIMPLE_OMP_MASTER:
702 64022 : case GIMPLE_OMP_MASKED:
703 64022 : case GIMPLE_OMP_TASKGROUP:
704 64022 : case GIMPLE_OMP_ORDERED:
705 64022 : case GIMPLE_OMP_SCAN:
706 64022 : case GIMPLE_OMP_SECTION:
707 64022 : case GIMPLE_OMP_STRUCTURED_BLOCK:
708 64022 : case GIMPLE_OMP_PARALLEL:
709 64022 : case GIMPLE_OMP_TASK:
710 64022 : case GIMPLE_OMP_SCOPE:
711 64022 : case GIMPLE_OMP_DISPATCH:
712 64022 : case GIMPLE_OMP_SECTIONS:
713 64022 : case GIMPLE_OMP_SINGLE:
714 64022 : case GIMPLE_OMP_TARGET:
715 64022 : case GIMPLE_OMP_TEAMS:
716 64022 : ret = walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), callback_stmt,
717 : callback_op, wi);
718 64022 : 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 802 : case GIMPLE_TRANSACTION:
737 802 : ret = walk_gimple_seq_mod (gimple_transaction_body_ptr (
738 : as_a <gtransaction *> (stmt)),
739 : callback_stmt, callback_op, wi);
740 802 : if (ret)
741 3 : return wi->callback_result;
742 : break;
743 :
744 208461670 : default:
745 208461670 : 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 1141239847 : get_base_loadstore (tree op)
757 : {
758 1308200027 : while (handled_component_p (op))
759 166960180 : op = TREE_OPERAND (op, 0);
760 1141239847 : if (DECL_P (op)
761 908144318 : || INDIRECT_REF_P (op)
762 908144318 : || TREE_CODE (op) == MEM_REF
763 736486068 : || TREE_CODE (op) == TARGET_MEM_REF)
764 411122629 : 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 2324795103 : 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 2324795103 : bool ret = false;
784 2324795103 : unsigned i;
785 2324795103 : if (gimple_assign_single_p (stmt))
786 : {
787 592011960 : tree lhs, rhs, arg;
788 592011960 : if (visit_store)
789 : {
790 392751247 : arg = gimple_assign_lhs (stmt);
791 392751247 : lhs = get_base_loadstore (arg);
792 392751247 : if (lhs)
793 195472847 : ret |= visit_store (stmt, lhs, arg, data);
794 : }
795 592011960 : arg = gimple_assign_rhs1 (stmt);
796 592011960 : rhs = arg;
797 1405024255 : while (handled_component_p (rhs))
798 221000335 : rhs = TREE_OPERAND (rhs, 0);
799 592011960 : if (visit_addr)
800 : {
801 378062271 : if (TREE_CODE (rhs) == ADDR_EXPR)
802 33030547 : ret |= visit_addr (stmt, TREE_OPERAND (rhs, 0), arg, data);
803 345031724 : else if (TREE_CODE (rhs) == OBJ_TYPE_REF
804 345031724 : && TREE_CODE (OBJ_TYPE_REF_OBJECT (rhs)) == ADDR_EXPR)
805 612 : ret |= visit_addr (stmt, TREE_OPERAND (OBJ_TYPE_REF_OBJECT (rhs),
806 : 0), arg, data);
807 345031112 : else if (TREE_CODE (rhs) == CONSTRUCTOR)
808 : {
809 : unsigned int ix;
810 : tree val;
811 :
812 38883679 : FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (rhs), ix, val)
813 2675838 : if (TREE_CODE (val) == ADDR_EXPR)
814 0 : ret |= visit_addr (stmt, TREE_OPERAND (val, 0), arg, data);
815 2675838 : else if (TREE_CODE (val) == OBJ_TYPE_REF
816 2675838 : && 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 592011960 : if (visit_load)
823 : {
824 392749176 : rhs = get_base_loadstore (rhs);
825 392749176 : if (rhs)
826 176744995 : ret |= visit_load (stmt, rhs, arg, data);
827 : }
828 : }
829 1732783143 : else if (visit_addr
830 1732783143 : && (is_gimple_assign (stmt)
831 824730982 : || gimple_code (stmt) == GIMPLE_COND))
832 : {
833 1068857825 : for (i = 0; i < gimple_num_ops (stmt); ++i)
834 : {
835 811573346 : tree op = gimple_op (stmt, i);
836 811573346 : if (op == NULL_TREE)
837 : ;
838 636344650 : else if (TREE_CODE (op) == ADDR_EXPR)
839 7006130 : ret |= visit_addr (stmt, TREE_OPERAND (op, 0), op, data);
840 : }
841 : }
842 1475498664 : else if (gcall *call_stmt = dyn_cast <gcall *> (stmt))
843 : {
844 208952077 : if (visit_store)
845 : {
846 152811410 : tree arg = gimple_call_lhs (call_stmt);
847 152811410 : if (arg)
848 : {
849 61414441 : tree lhs = get_base_loadstore (arg);
850 61414441 : if (lhs)
851 12118475 : ret |= visit_store (stmt, lhs, arg, data);
852 : }
853 : }
854 208952077 : if (visit_load || visit_addr)
855 629262105 : for (i = 0; i < gimple_call_num_args (call_stmt); ++i)
856 : {
857 420656978 : tree arg = gimple_call_arg (call_stmt, i);
858 420656978 : if (visit_addr
859 240770676 : && TREE_CODE (arg) == ADDR_EXPR)
860 72233617 : ret |= visit_addr (stmt, TREE_OPERAND (arg, 0), arg, data);
861 348423361 : else if (visit_load)
862 : {
863 271355631 : tree rhs = get_base_loadstore (arg);
864 271355631 : if (rhs)
865 21581593 : ret |= visit_load (stmt, rhs, arg, data);
866 : }
867 : }
868 208605127 : if (visit_addr
869 120907199 : && gimple_call_chain (call_stmt)
870 209167584 : && TREE_CODE (gimple_call_chain (call_stmt)) == ADDR_EXPR)
871 233249 : ret |= visit_addr (stmt, TREE_OPERAND (gimple_call_chain (call_stmt), 0),
872 : gimple_call_chain (call_stmt), data);
873 208952077 : if (visit_addr
874 120907199 : && gimple_call_return_slot_opt_p (call_stmt)
875 4304339 : && gimple_call_lhs (call_stmt) != NULL_TREE
876 213078420 : && TREE_ADDRESSABLE (TREE_TYPE (gimple_call_lhs (call_stmt))))
877 862930 : ret |= visit_addr (stmt, gimple_call_lhs (call_stmt),
878 : gimple_call_lhs (call_stmt), data);
879 : }
880 1266546587 : else if (gasm *asm_stmt = dyn_cast <gasm *> (stmt))
881 : {
882 1804241 : unsigned noutputs;
883 1804241 : const char *constraint;
884 1804241 : const char **oconstraints;
885 1804241 : bool allows_mem, allows_reg, is_inout;
886 1804241 : noutputs = gimple_asm_noutputs (asm_stmt);
887 1804241 : oconstraints = XALLOCAVEC (const char *, noutputs);
888 1804241 : if (visit_store || visit_addr)
889 3402745 : for (i = 0; i < gimple_asm_noutputs (asm_stmt); ++i)
890 : {
891 1598504 : tree link = gimple_asm_output_op (asm_stmt, i);
892 1598504 : tree op = get_base_loadstore (TREE_VALUE (link));
893 1598504 : if (op && visit_store)
894 232490 : ret |= visit_store (stmt, op, TREE_VALUE (link), data);
895 1598504 : if (visit_addr)
896 : {
897 1094787 : constraint = TREE_STRING_POINTER
898 : (TREE_VALUE (TREE_PURPOSE (link)));
899 1094787 : oconstraints[i] = constraint;
900 1094787 : parse_output_constraint (&constraint, i, 0, 0, &allows_mem,
901 : &allows_reg, &is_inout, nullptr);
902 1094787 : if (op && !allows_reg && allows_mem)
903 70892 : ret |= visit_addr (stmt, op, TREE_VALUE (link), data);
904 : }
905 : }
906 1804241 : if (visit_load || visit_addr)
907 2838017 : for (i = 0; i < gimple_asm_ninputs (asm_stmt); ++i)
908 : {
909 1034900 : tree link = gimple_asm_input_op (asm_stmt, i);
910 1034900 : tree op = TREE_VALUE (link);
911 1034900 : if (visit_addr
912 739574 : && TREE_CODE (op) == ADDR_EXPR)
913 74665 : ret |= visit_addr (stmt, TREE_OPERAND (op, 0), op, data);
914 960235 : else if (visit_load || visit_addr)
915 : {
916 960235 : op = get_base_loadstore (op);
917 960235 : if (op)
918 : {
919 161814 : if (visit_load)
920 84595 : ret |= visit_load (stmt, op, TREE_VALUE (link), data);
921 161814 : if (visit_addr)
922 : {
923 134898 : constraint = TREE_STRING_POINTER
924 : (TREE_VALUE (TREE_PURPOSE (link)));
925 134898 : parse_input_constraint (&constraint, 0, 0, noutputs,
926 : 0, oconstraints, &allows_mem,
927 : &allows_reg, nullptr);
928 134898 : if (!allows_reg && allows_mem)
929 76223 : ret |= visit_addr (stmt, op, TREE_VALUE (link),
930 : data);
931 : }
932 : }
933 : }
934 : }
935 : }
936 1264742346 : else if (greturn *return_stmt = dyn_cast <greturn *> (stmt))
937 : {
938 50992368 : tree op = gimple_return_retval (return_stmt);
939 50992368 : if (op)
940 : {
941 27671535 : if (visit_addr
942 15183801 : && TREE_CODE (op) == ADDR_EXPR)
943 27145 : ret |= visit_addr (stmt, TREE_OPERAND (op, 0), op, data);
944 27644390 : else if (visit_load)
945 : {
946 20410613 : tree base = get_base_loadstore (op);
947 20410613 : if (base)
948 4638847 : ret |= visit_load (stmt, base, op, data);
949 : }
950 : }
951 : }
952 1213749978 : else if (visit_addr
953 1213749978 : && gimple_code (stmt) == GIMPLE_PHI)
954 : {
955 98287643 : for (i = 0; i < gimple_phi_num_args (stmt); ++i)
956 : {
957 71348073 : tree op = gimple_phi_arg_def (stmt, i);
958 71348073 : if (TREE_CODE (op) == ADDR_EXPR)
959 419852 : ret |= visit_addr (stmt, TREE_OPERAND (op, 0), op, data);
960 : }
961 : }
962 1186810408 : else if (visit_addr
963 1186810408 : && gimple_code (stmt) == GIMPLE_GOTO)
964 : {
965 5529 : tree op = gimple_goto_dest (stmt);
966 5529 : if (TREE_CODE (op) == ADDR_EXPR)
967 138 : ret |= visit_addr (stmt, TREE_OPERAND (op, 0), op, data);
968 : }
969 :
970 2324795103 : 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 952331719 : 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 952331719 : return walk_stmt_load_store_addr_ops (stmt, data,
982 952331719 : visit_load, visit_store, NULL);
983 : }
|