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 40600378 : 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 40600378 : gimple_stmt_iterator gsi;
48 :
49 327843745 : for (gsi = gsi_start (*pseq); !gsi_end_p (gsi); )
50 : {
51 247748948 : tree ret = walk_gimple_stmt (&gsi, callback_stmt, callback_op, wi);
52 247748920 : if (ret)
53 : {
54 : /* If CALLBACK_STMT or CALLBACK_OP return a value, WI must exist
55 : to hold it. */
56 80061 : gcc_assert (wi);
57 80061 : wi->callback_result = ret;
58 :
59 80061 : gimple *g;
60 80061 : if (!wi->removed_stmt)
61 80061 : g = gsi_stmt (gsi);
62 : else
63 : {
64 0 : g = NULL;
65 0 : wi->removed_stmt = false;
66 : }
67 80061 : return g;
68 : }
69 :
70 247668859 : if (!wi->removed_stmt)
71 247666248 : gsi_next (&gsi);
72 : else
73 2611 : wi->removed_stmt = false;
74 : }
75 :
76 40520289 : if (wi)
77 40520289 : 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 33950043 : walk_gimple_seq (gimple_seq seq, walk_stmt_fn callback_stmt,
88 : walk_tree_fn callback_op, struct walk_stmt_info *wi)
89 : {
90 33950043 : gimple_seq seq2 = seq;
91 33950043 : gimple *ret = walk_gimple_seq_mod (&seq2, callback_stmt, callback_op, wi);
92 33950038 : gcc_assert (seq2 == seq);
93 33950038 : return ret;
94 : }
95 :
96 :
97 : /* Helper function for walk_gimple_stmt. Walk operands of a GIMPLE_ASM. */
98 :
99 : static tree
100 27423716 : walk_gimple_asm (gasm *stmt, walk_tree_fn callback_op,
101 : struct walk_stmt_info *wi)
102 : {
103 27423716 : tree ret, op;
104 27423716 : unsigned noutputs;
105 27423716 : const char **oconstraints;
106 27423716 : unsigned i, n;
107 27423716 : const char *constraint;
108 27423716 : bool allows_mem, allows_reg, is_inout;
109 :
110 27423716 : noutputs = gimple_asm_noutputs (stmt);
111 27423716 : oconstraints = (const char **) alloca ((noutputs) * sizeof (const char *));
112 :
113 49842611 : for (i = 0; i < noutputs; i++)
114 : {
115 22418905 : op = gimple_asm_output_op (stmt, i);
116 22418905 : constraint = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (op)));
117 22418905 : oconstraints[i] = constraint;
118 22418905 : if (wi)
119 : {
120 22418813 : if (parse_output_constraint (&constraint, i, 0, 0, &allows_mem,
121 : &allows_reg, &is_inout, nullptr))
122 22418813 : wi->val_only = (allows_reg || !allows_mem);
123 : }
124 22418813 : if (wi)
125 22418813 : wi->is_lhs = true;
126 22418905 : ret = walk_tree (&TREE_VALUE (op), callback_op, wi, NULL);
127 22418905 : if (ret)
128 : return ret;
129 : }
130 :
131 27423706 : n = gimple_asm_ninputs (stmt);
132 42511787 : for (i = 0; i < n; i++)
133 : {
134 15088087 : op = gimple_asm_input_op (stmt, i);
135 15088087 : constraint = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (op)));
136 :
137 15088087 : if (wi)
138 : {
139 15087991 : if (parse_input_constraint (&constraint, 0, 0, noutputs, 0,
140 : oconstraints, &allows_mem, &allows_reg,
141 : nullptr))
142 : {
143 15087991 : wi->val_only = (allows_reg || !allows_mem);
144 : /* Although input "m" is not really a LHS, we need a lvalue. */
145 15087991 : wi->is_lhs = !wi->val_only;
146 : }
147 : }
148 15088087 : ret = walk_tree (&TREE_VALUE (op), callback_op, wi, NULL);
149 15088087 : if (ret)
150 : return ret;
151 : }
152 :
153 27423700 : if (wi)
154 : {
155 27423627 : wi->is_lhs = false;
156 27423627 : wi->val_only = true;
157 : }
158 :
159 27423700 : n = gimple_asm_nlabels (stmt);
160 27632605 : 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 25466956414 : walk_gimple_op (gimple *stmt, walk_tree_fn callback_op,
189 : struct walk_stmt_info *wi)
190 : {
191 25466956414 : hash_set<tree> *pset = (wi) ? wi->pset : NULL;
192 25466003715 : unsigned i;
193 50932960129 : tree ret = NULL_TREE;
194 :
195 25466003715 : if (wi)
196 25466003715 : wi->stmt = stmt;
197 :
198 25466956414 : switch (gimple_code (stmt))
199 : {
200 8669624926 : 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 8669624926 : if (wi)
204 : {
205 8668969827 : tree lhs = gimple_assign_lhs (stmt);
206 8668969827 : wi->val_only
207 17337939654 : = (is_gimple_reg_type (TREE_TYPE (lhs)) && !is_gimple_reg (lhs))
208 15196385329 : || gimple_assign_rhs_class (stmt) != GIMPLE_SINGLE_RHS;
209 : }
210 :
211 19358207359 : for (i = 1; i < gimple_num_ops (stmt); i++)
212 : {
213 10688669114 : ret = walk_tree (gimple_op_ptr (stmt, i), callback_op, wi,
214 : pset);
215 10688669114 : 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 8669538245 : 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 8668954157 : tree rhs1 = gimple_assign_rhs1 (stmt);
226 8668954157 : wi->val_only
227 8668954157 : = (is_gimple_reg_type (TREE_TYPE (rhs1)) && !is_gimple_reg (rhs1))
228 13371841823 : || gimple_assign_rhs_class (stmt) != GIMPLE_SINGLE_RHS;
229 8668954157 : wi->is_lhs = true;
230 : }
231 :
232 8669538245 : ret = walk_tree (gimple_op_ptr (stmt, 0), callback_op, wi, pset);
233 8669538245 : if (ret)
234 : return ret;
235 :
236 8669510840 : if (wi)
237 : {
238 8668953520 : wi->val_only = true;
239 8668953520 : wi->is_lhs = false;
240 : }
241 : break;
242 :
243 2016465466 : case GIMPLE_CALL:
244 2016465466 : if (wi)
245 : {
246 2016395349 : wi->is_lhs = false;
247 2016395349 : wi->val_only = true;
248 : }
249 :
250 2016465466 : ret = walk_tree (gimple_call_chain_ptr (as_a <gcall *> (stmt)),
251 : callback_op, wi, pset);
252 2016465466 : if (ret)
253 : return ret;
254 :
255 2016465406 : ret = walk_tree (gimple_call_fn_ptr (stmt), callback_op, wi, pset);
256 2016465406 : if (ret)
257 : return ret;
258 :
259 6019136298 : for (i = 0; i < gimple_call_num_args (stmt); i++)
260 : {
261 4002675343 : if (wi)
262 4002557957 : wi->val_only
263 4002557957 : = is_gimple_reg_type (TREE_TYPE (gimple_call_arg (stmt, i)));
264 4002675343 : ret = walk_tree (gimple_call_arg_ptr (stmt, i), callback_op, wi,
265 : pset);
266 4002675343 : if (ret)
267 : return ret;
268 : }
269 :
270 2016460955 : if (gimple_call_lhs (stmt))
271 : {
272 799020158 : if (wi)
273 : {
274 798998992 : wi->is_lhs = true;
275 798998992 : wi->val_only
276 798998992 : = is_gimple_reg_type (TREE_TYPE (gimple_call_lhs (stmt)));
277 : }
278 :
279 799020158 : ret = walk_tree (gimple_call_lhs_ptr (stmt), callback_op, wi, pset);
280 799020158 : if (ret)
281 : return ret;
282 : }
283 :
284 2016460567 : if (wi)
285 : {
286 2016394121 : wi->is_lhs = false;
287 2016394121 : 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 27423716 : case GIMPLE_ASM:
306 27423716 : ret = walk_gimple_asm (as_a <gasm *> (stmt), callback_op, wi);
307 27423716 : if (ret)
308 : return ret;
309 : break;
310 :
311 196568 : case GIMPLE_OMP_CONTINUE:
312 196568 : {
313 196568 : gomp_continue *cont_stmt = as_a <gomp_continue *> (stmt);
314 196568 : ret = walk_tree (gimple_omp_continue_control_def_ptr (cont_stmt),
315 : callback_op, wi, pset);
316 196568 : if (ret)
317 : return ret;
318 :
319 196568 : ret = walk_tree (gimple_omp_continue_control_use_ptr (cont_stmt),
320 : callback_op, wi, pset);
321 196568 : 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 190977 : case GIMPLE_OMP_FOR:
361 190977 : ret = walk_tree (gimple_omp_for_clauses_ptr (stmt), callback_op, wi,
362 : pset);
363 190977 : if (ret)
364 : return ret;
365 467589 : for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
366 : {
367 276612 : ret = walk_tree (gimple_omp_for_index_ptr (stmt, i), callback_op,
368 : wi, pset);
369 276612 : if (ret)
370 : return ret;
371 276612 : ret = walk_tree (gimple_omp_for_initial_ptr (stmt, i), callback_op,
372 : wi, pset);
373 276612 : if (ret)
374 : return ret;
375 276612 : ret = walk_tree (gimple_omp_for_final_ptr (stmt, i), callback_op,
376 : wi, pset);
377 276612 : if (ret)
378 : return ret;
379 276612 : ret = walk_tree (gimple_omp_for_incr_ptr (stmt, i), callback_op,
380 : wi, pset);
381 276612 : if (ret)
382 : return ret;
383 : }
384 : break;
385 :
386 65764 : case GIMPLE_OMP_PARALLEL:
387 65764 : {
388 65764 : gomp_parallel *omp_par_stmt = as_a <gomp_parallel *> (stmt);
389 65764 : ret = walk_tree (gimple_omp_parallel_clauses_ptr (omp_par_stmt),
390 : callback_op, wi, pset);
391 65764 : if (ret)
392 : return ret;
393 65764 : ret = walk_tree (gimple_omp_parallel_child_fn_ptr (omp_par_stmt),
394 : callback_op, wi, pset);
395 65764 : if (ret)
396 : return ret;
397 65764 : ret = walk_tree (gimple_omp_parallel_data_arg_ptr (omp_par_stmt),
398 : callback_op, wi, pset);
399 65764 : if (ret)
400 : return ret;
401 : }
402 : break;
403 :
404 15737 : case GIMPLE_OMP_TASK:
405 15737 : ret = walk_tree (gimple_omp_task_clauses_ptr (stmt), callback_op,
406 : wi, pset);
407 15737 : if (ret)
408 : return ret;
409 15737 : ret = walk_tree (gimple_omp_task_child_fn_ptr (stmt), callback_op,
410 : wi, pset);
411 15737 : if (ret)
412 : return ret;
413 15737 : ret = walk_tree (gimple_omp_task_data_arg_ptr (stmt), callback_op,
414 : wi, pset);
415 15737 : if (ret)
416 : return ret;
417 15737 : ret = walk_tree (gimple_omp_task_copy_fn_ptr (stmt), callback_op,
418 : wi, pset);
419 15737 : if (ret)
420 : return ret;
421 15737 : ret = walk_tree (gimple_omp_task_arg_size_ptr (stmt), callback_op,
422 : wi, pset);
423 15737 : if (ret)
424 : return ret;
425 15737 : ret = walk_tree (gimple_omp_task_arg_align_ptr (stmt), callback_op,
426 : wi, pset);
427 15737 : 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 147707 : case GIMPLE_OMP_TARGET:
451 147707 : {
452 147707 : gomp_target *omp_stmt = as_a <gomp_target *> (stmt);
453 147707 : ret = walk_tree (gimple_omp_target_clauses_ptr (omp_stmt),
454 : callback_op, wi, pset);
455 147707 : if (ret)
456 : return ret;
457 147707 : ret = walk_tree (gimple_omp_target_child_fn_ptr (omp_stmt),
458 : callback_op, wi, pset);
459 147707 : if (ret)
460 : return ret;
461 147707 : ret = walk_tree (gimple_omp_target_data_arg_ptr (omp_stmt),
462 : callback_op, wi, pset);
463 147707 : 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 401808 : case GIMPLE_OMP_RETURN:
525 401808 : ret = walk_tree (gimple_omp_return_lhs_ptr (stmt), callback_op, wi,
526 : pset);
527 401808 : 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 14612660588 : default:
562 14612660588 : {
563 14612660588 : enum gimple_statement_structure_enum gss;
564 14612660588 : gss = gimple_statement_structure (stmt);
565 14612660588 : if (gss == GSS_WITH_OPS || gss == GSS_WITH_MEM_OPS)
566 40566434920 : for (i = 0; i < gimple_num_ops (stmt); i++)
567 : {
568 25960126950 : ret = walk_tree (gimple_op_ptr (stmt, i), callback_op, wi, pset);
569 25960126950 : 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 249832038 : 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 249832038 : gimple *ret;
600 249832038 : tree tree_ret;
601 249832038 : gimple *stmt = gsi_stmt (*gsi);
602 :
603 249832038 : if (wi)
604 : {
605 249829666 : wi->gsi = *gsi;
606 249829666 : wi->removed_stmt = false;
607 :
608 249829666 : if (wi->want_locations && gimple_has_location (stmt))
609 5442527 : input_location = gimple_location (stmt);
610 : }
611 :
612 249832038 : ret = NULL;
613 :
614 : /* Invoke the statement callback. Return if the callback handled
615 : all of STMT operands by itself. */
616 249832038 : if (callback_stmt)
617 : {
618 249794420 : bool handled_ops = false;
619 249794420 : tree_ret = callback_stmt (gsi, &handled_ops, wi);
620 249794406 : if (handled_ops)
621 36549904 : return tree_ret;
622 :
623 : /* If CALLBACK_STMT did not handle operands, it should not have
624 : a value to return. */
625 213244502 : gcc_assert (tree_ret == NULL);
626 :
627 213244502 : if (wi && wi->removed_stmt)
628 : return NULL;
629 :
630 : /* Re-read stmt in case the callback changed it. */
631 213244502 : stmt = gsi_stmt (*gsi);
632 : }
633 :
634 : /* If CALLBACK_OP is defined, invoke it on every operand of STMT. */
635 213282120 : if (callback_op)
636 : {
637 25692537 : tree_ret = walk_gimple_op (stmt, callback_op, wi);
638 25692537 : if (tree_ret)
639 : return tree_ret;
640 : }
641 :
642 : /* If STMT can have statements inside (e.g. GIMPLE_BIND), walk them. */
643 213282120 : switch (gimple_code (stmt))
644 : {
645 2818796 : case GIMPLE_BIND:
646 2818796 : ret = walk_gimple_seq_mod (gimple_bind_body_ptr (as_a <gbind *> (stmt)),
647 : callback_stmt, callback_op, wi);
648 2818787 : if (ret)
649 11225 : 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 655963 : case GIMPLE_TRY:
682 655963 : ret = walk_gimple_seq_mod (gimple_try_eval_ptr (stmt), callback_stmt, callback_op,
683 : wi);
684 655958 : if (ret)
685 226 : return wi->callback_result;
686 :
687 655732 : ret = walk_gimple_seq_mod (gimple_try_cleanup_ptr (stmt), callback_stmt,
688 : callback_op, wi);
689 655732 : if (ret)
690 0 : return wi->callback_result;
691 : break;
692 :
693 23618 : case GIMPLE_OMP_FOR:
694 23618 : ret = walk_gimple_seq_mod (gimple_omp_for_pre_body_ptr (stmt), callback_stmt,
695 : callback_op, wi);
696 23618 : if (ret)
697 0 : return wi->callback_result;
698 :
699 : /* FALL THROUGH. */
700 64078 : case GIMPLE_OMP_CRITICAL:
701 64078 : case GIMPLE_OMP_MASTER:
702 64078 : case GIMPLE_OMP_MASKED:
703 64078 : case GIMPLE_OMP_TASKGROUP:
704 64078 : case GIMPLE_OMP_ORDERED:
705 64078 : case GIMPLE_OMP_SCAN:
706 64078 : case GIMPLE_OMP_SECTION:
707 64078 : case GIMPLE_OMP_STRUCTURED_BLOCK:
708 64078 : case GIMPLE_OMP_PARALLEL:
709 64078 : case GIMPLE_OMP_TASK:
710 64078 : case GIMPLE_OMP_SCOPE:
711 64078 : case GIMPLE_OMP_DISPATCH:
712 64078 : case GIMPLE_OMP_SECTIONS:
713 64078 : case GIMPLE_OMP_SINGLE:
714 64078 : case GIMPLE_OMP_TARGET:
715 64078 : case GIMPLE_OMP_TEAMS:
716 64078 : ret = walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), callback_stmt,
717 : callback_op, wi);
718 64078 : 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 209706111 : default:
745 209706111 : 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 1143761832 : get_base_loadstore (tree op)
757 : {
758 1311417218 : while (handled_component_p (op))
759 167655386 : op = TREE_OPERAND (op, 0);
760 1143761832 : if (DECL_P (op)
761 911004621 : || INDIRECT_REF_P (op)
762 911004621 : || TREE_CODE (op) == MEM_REF
763 739008660 : || TREE_CODE (op) == TARGET_MEM_REF)
764 411145671 : 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 2334773206 : 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 2334773206 : bool ret = false;
784 2334773206 : unsigned i;
785 2334773206 : if (gimple_assign_single_p (stmt))
786 : {
787 593065340 : tree lhs, rhs, arg;
788 593065340 : if (visit_store)
789 : {
790 393517787 : arg = gimple_assign_lhs (stmt);
791 393517787 : lhs = get_base_loadstore (arg);
792 393517787 : if (lhs)
793 196144944 : ret |= visit_store (stmt, lhs, arg, data);
794 : }
795 593065340 : arg = gimple_assign_rhs1 (stmt);
796 593065340 : rhs = arg;
797 1405605942 : while (handled_component_p (rhs))
798 219475262 : rhs = TREE_OPERAND (rhs, 0);
799 593065340 : if (visit_addr)
800 : {
801 378951140 : if (TREE_CODE (rhs) == ADDR_EXPR)
802 33284901 : ret |= visit_addr (stmt, TREE_OPERAND (rhs, 0), arg, data);
803 345666239 : else if (TREE_CODE (rhs) == OBJ_TYPE_REF
804 345666239 : && 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 345665627 : else if (TREE_CODE (rhs) == CONSTRUCTOR)
808 : {
809 : unsigned int ix;
810 : tree val;
811 :
812 39260928 : FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (rhs), ix, val)
813 2797927 : if (TREE_CODE (val) == ADDR_EXPR)
814 0 : ret |= visit_addr (stmt, TREE_OPERAND (val, 0), arg, data);
815 2797927 : else if (TREE_CODE (val) == OBJ_TYPE_REF
816 2797927 : && 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 593065340 : if (visit_load)
823 : {
824 393515713 : rhs = get_base_loadstore (rhs);
825 393515713 : if (rhs)
826 176166623 : ret |= visit_load (stmt, rhs, arg, data);
827 : }
828 : }
829 1741707866 : else if (visit_addr
830 1741707866 : && (is_gimple_assign (stmt)
831 831926074 : || gimple_code (stmt) == GIMPLE_COND))
832 : {
833 1066130348 : for (i = 0; i < gimple_num_ops (stmt); ++i)
834 : {
835 809616648 : tree op = gimple_op (stmt, i);
836 809616648 : if (op == NULL_TREE)
837 : ;
838 634397268 : else if (TREE_CODE (op) == ADDR_EXPR)
839 6999848 : ret |= visit_addr (stmt, TREE_OPERAND (op, 0), op, data);
840 : }
841 : }
842 1485194166 : else if (gcall *call_stmt = dyn_cast <gcall *> (stmt))
843 : {
844 210275715 : if (visit_store)
845 : {
846 153748977 : tree arg = gimple_call_lhs (call_stmt);
847 153748977 : if (arg)
848 : {
849 61669423 : tree lhs = get_base_loadstore (arg);
850 61669423 : if (lhs)
851 11957254 : ret |= visit_store (stmt, lhs, arg, data);
852 : }
853 : }
854 210275715 : if (visit_load || visit_addr)
855 632115194 : for (i = 0; i < gimple_call_num_args (call_stmt); ++i)
856 : {
857 422183446 : tree arg = gimple_call_arg (call_stmt, i);
858 422183446 : if (visit_addr
859 242093144 : && TREE_CODE (arg) == ADDR_EXPR)
860 73077326 : ret |= visit_addr (stmt, TREE_OPERAND (arg, 0), arg, data);
861 349106120 : else if (visit_load)
862 : {
863 271906884 : tree rhs = get_base_loadstore (arg);
864 271906884 : if (rhs)
865 21654312 : ret |= visit_load (stmt, rhs, arg, data);
866 : }
867 : }
868 209931748 : if (visit_addr
869 121837779 : && gimple_call_chain (call_stmt)
870 210494322 : && TREE_CODE (gimple_call_chain (call_stmt)) == ADDR_EXPR)
871 233366 : ret |= visit_addr (stmt, TREE_OPERAND (gimple_call_chain (call_stmt), 0),
872 : gimple_call_chain (call_stmt), data);
873 210275715 : if (visit_addr
874 121837779 : && gimple_call_return_slot_opt_p (call_stmt)
875 4308472 : && gimple_call_lhs (call_stmt) != NULL_TREE
876 214405930 : && TREE_ADDRESSABLE (TREE_TYPE (gimple_call_lhs (call_stmt))))
877 855903 : ret |= visit_addr (stmt, gimple_call_lhs (call_stmt),
878 : gimple_call_lhs (call_stmt), data);
879 : }
880 1274918451 : else if (gasm *asm_stmt = dyn_cast <gasm *> (stmt))
881 : {
882 1821434 : unsigned noutputs;
883 1821434 : const char *constraint;
884 1821434 : const char **oconstraints;
885 1821434 : bool allows_mem, allows_reg, is_inout;
886 1821434 : noutputs = gimple_asm_noutputs (asm_stmt);
887 1821434 : oconstraints = XALLOCAVEC (const char *, noutputs);
888 1821434 : if (visit_store || visit_addr)
889 3455994 : for (i = 0; i < gimple_asm_noutputs (asm_stmt); ++i)
890 : {
891 1634560 : tree link = gimple_asm_output_op (asm_stmt, i);
892 1634560 : tree op = get_base_loadstore (TREE_VALUE (link));
893 1634560 : if (op && visit_store)
894 242172 : ret |= visit_store (stmt, op, TREE_VALUE (link), data);
895 1634560 : if (visit_addr)
896 : {
897 1125559 : constraint = TREE_STRING_POINTER
898 : (TREE_VALUE (TREE_PURPOSE (link)));
899 1125559 : oconstraints[i] = constraint;
900 1125559 : parse_output_constraint (&constraint, i, 0, 0, &allows_mem,
901 : &allows_reg, &is_inout, nullptr);
902 1125559 : if (op && !allows_reg && allows_mem)
903 84926 : ret |= visit_addr (stmt, op, TREE_VALUE (link), data);
904 : }
905 : }
906 1821434 : if (visit_load || visit_addr)
907 2887929 : for (i = 0; i < gimple_asm_ninputs (asm_stmt); ++i)
908 : {
909 1067643 : tree link = gimple_asm_input_op (asm_stmt, i);
910 1067643 : tree op = TREE_VALUE (link);
911 1067643 : if (visit_addr
912 768478 : && TREE_CODE (op) == ADDR_EXPR)
913 74686 : ret |= visit_addr (stmt, TREE_OPERAND (op, 0), op, data);
914 992957 : else if (visit_load || visit_addr)
915 : {
916 992957 : op = get_base_loadstore (op);
917 992957 : if (op)
918 : {
919 178323 : if (visit_load)
920 93364 : ret |= visit_load (stmt, op, TREE_VALUE (link), data);
921 178323 : if (visit_addr)
922 : {
923 149340 : constraint = TREE_STRING_POINTER
924 : (TREE_VALUE (TREE_PURPOSE (link)));
925 149340 : parse_input_constraint (&constraint, 0, 0, noutputs,
926 : 0, oconstraints, &allows_mem,
927 : &allows_reg, nullptr);
928 149340 : if (!allows_reg && allows_mem)
929 90281 : ret |= visit_addr (stmt, op, TREE_VALUE (link),
930 : data);
931 : }
932 : }
933 : }
934 : }
935 : }
936 1273097017 : else if (greturn *return_stmt = dyn_cast <greturn *> (stmt))
937 : {
938 51332393 : tree op = gimple_return_retval (return_stmt);
939 51332393 : if (op)
940 : {
941 27823698 : if (visit_addr
942 15281220 : && TREE_CODE (op) == ADDR_EXPR)
943 27404 : ret |= visit_addr (stmt, TREE_OPERAND (op, 0), op, data);
944 27796294 : else if (visit_load)
945 : {
946 20524508 : tree base = get_base_loadstore (op);
947 20524508 : if (base)
948 4622539 : ret |= visit_load (stmt, base, op, data);
949 : }
950 : }
951 : }
952 1221764624 : else if (visit_addr
953 1221764624 : && gimple_code (stmt) == GIMPLE_PHI)
954 : {
955 97227836 : for (i = 0; i < gimple_phi_num_args (stmt); ++i)
956 : {
957 70576625 : tree op = gimple_phi_arg_def (stmt, i);
958 70576625 : if (TREE_CODE (op) == ADDR_EXPR)
959 362312 : ret |= visit_addr (stmt, TREE_OPERAND (op, 0), op, data);
960 : }
961 : }
962 1195113413 : else if (visit_addr
963 1195113413 : && gimple_code (stmt) == GIMPLE_GOTO)
964 : {
965 5552 : tree op = gimple_goto_dest (stmt);
966 5552 : if (TREE_CODE (op) == ADDR_EXPR)
967 138 : ret |= visit_addr (stmt, TREE_OPERAND (op, 0), op, data);
968 : }
969 :
970 2334773206 : 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 954991982 : 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 954991982 : return walk_stmt_load_store_addr_ops (stmt, data,
982 954991982 : visit_load, visit_store, NULL);
983 : }
|