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 : 39814441 : 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 : 39814441 : gimple_stmt_iterator gsi;
48 : :
49 : 311403671 : for (gsi = gsi_start (*pseq); !gsi_end_p (gsi); )
50 : : {
51 : 232938756 : tree ret = walk_gimple_stmt (&gsi, callback_stmt, callback_op, wi);
52 : 232938724 : if (ret)
53 : : {
54 : : /* If CALLBACK_STMT or CALLBACK_OP return a value, WI must exist
55 : : to hold it. */
56 : 82896 : gcc_assert (wi);
57 : 82896 : wi->callback_result = ret;
58 : :
59 : 82896 : gimple *g;
60 : 82896 : if (!wi->removed_stmt)
61 : 82896 : g = gsi_stmt (gsi);
62 : : else
63 : : {
64 : 0 : g = NULL;
65 : 0 : wi->removed_stmt = false;
66 : : }
67 : 82896 : return g;
68 : : }
69 : :
70 : 232855828 : if (!wi->removed_stmt)
71 : 232850476 : gsi_next (&gsi);
72 : : else
73 : 5352 : wi->removed_stmt = false;
74 : : }
75 : :
76 : 39731513 : if (wi)
77 : 39731513 : 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 : 34337959 : walk_gimple_seq (gimple_seq seq, walk_stmt_fn callback_stmt,
88 : : walk_tree_fn callback_op, struct walk_stmt_info *wi)
89 : : {
90 : 34337959 : gimple_seq seq2 = seq;
91 : 34337959 : gimple *ret = walk_gimple_seq_mod (&seq2, callback_stmt, callback_op, wi);
92 : 34337953 : gcc_assert (seq2 == seq);
93 : 34337953 : return ret;
94 : : }
95 : :
96 : :
97 : : /* Helper function for walk_gimple_stmt. Walk operands of a GIMPLE_ASM. */
98 : :
99 : : static tree
100 : 26285267 : walk_gimple_asm (gasm *stmt, walk_tree_fn callback_op,
101 : : struct walk_stmt_info *wi)
102 : : {
103 : 26285267 : tree ret, op;
104 : 26285267 : unsigned noutputs;
105 : 26285267 : const char **oconstraints;
106 : 26285267 : unsigned i, n;
107 : 26285267 : const char *constraint;
108 : 26285267 : bool allows_mem, allows_reg, is_inout;
109 : :
110 : 26285267 : noutputs = gimple_asm_noutputs (stmt);
111 : 26285267 : oconstraints = (const char **) alloca ((noutputs) * sizeof (const char *));
112 : :
113 : 47028915 : for (i = 0; i < noutputs; i++)
114 : : {
115 : 20743658 : op = gimple_asm_output_op (stmt, i);
116 : 20743658 : constraint = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (op)));
117 : 20743658 : oconstraints[i] = constraint;
118 : 20743658 : if (wi)
119 : : {
120 : 20743566 : if (parse_output_constraint (&constraint, i, 0, 0, &allows_mem,
121 : : &allows_reg, &is_inout))
122 : 20743566 : wi->val_only = (allows_reg || !allows_mem);
123 : : }
124 : 20743566 : if (wi)
125 : 20743566 : wi->is_lhs = true;
126 : 20743658 : ret = walk_tree (&TREE_VALUE (op), callback_op, wi, NULL);
127 : 20743658 : if (ret)
128 : : return ret;
129 : : }
130 : :
131 : 26285257 : n = gimple_asm_ninputs (stmt);
132 : 40172237 : for (i = 0; i < n; i++)
133 : : {
134 : 13886986 : op = gimple_asm_input_op (stmt, i);
135 : 13886986 : constraint = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (op)));
136 : :
137 : 13886986 : if (wi)
138 : : {
139 : 13886890 : if (parse_input_constraint (&constraint, 0, 0, noutputs, 0,
140 : : oconstraints, &allows_mem, &allows_reg))
141 : : {
142 : 13886890 : wi->val_only = (allows_reg || !allows_mem);
143 : : /* Although input "m" is not really a LHS, we need a lvalue. */
144 : 13886890 : wi->is_lhs = !wi->val_only;
145 : : }
146 : : }
147 : 13886986 : ret = walk_tree (&TREE_VALUE (op), callback_op, wi, NULL);
148 : 13886986 : if (ret)
149 : : return ret;
150 : : }
151 : :
152 : 26285251 : if (wi)
153 : : {
154 : 26285178 : wi->is_lhs = false;
155 : 26285178 : wi->val_only = true;
156 : : }
157 : :
158 : 26285251 : n = gimple_asm_nlabels (stmt);
159 : 26464401 : for (i = 0; i < n; i++)
160 : : {
161 : 179150 : op = gimple_asm_label_op (stmt, i);
162 : 179150 : ret = walk_tree (&TREE_VALUE (op), callback_op, wi, NULL);
163 : 179150 : if (ret)
164 : : return ret;
165 : : }
166 : :
167 : : return NULL_TREE;
168 : : }
169 : :
170 : :
171 : : /* Helper function of WALK_GIMPLE_STMT. Walk every tree operand in
172 : : STMT. CALLBACK_OP and WI are as in WALK_GIMPLE_STMT.
173 : :
174 : : CALLBACK_OP is called on each operand of STMT via walk_tree.
175 : : Additional parameters to walk_tree must be stored in WI. For each operand
176 : : OP, walk_tree is called as:
177 : :
178 : : walk_tree (&OP, CALLBACK_OP, WI, WI->PSET)
179 : :
180 : : If CALLBACK_OP returns non-NULL for an operand, the remaining
181 : : operands are not scanned.
182 : :
183 : : The return value is that returned by the last call to walk_tree, or
184 : : NULL_TREE if no CALLBACK_OP is specified. */
185 : :
186 : : tree
187 : 25441743422 : walk_gimple_op (gimple *stmt, walk_tree_fn callback_op,
188 : : struct walk_stmt_info *wi)
189 : : {
190 : 25441743422 : hash_set<tree> *pset = (wi) ? wi->pset : NULL;
191 : 25440806027 : unsigned i;
192 : 50882549449 : tree ret = NULL_TREE;
193 : :
194 : 25440806027 : if (wi)
195 : 25440806027 : wi->stmt = stmt;
196 : :
197 : 25441743422 : switch (gimple_code (stmt))
198 : : {
199 : 8757716647 : case GIMPLE_ASSIGN:
200 : : /* Walk the RHS operands. If the LHS is of a non-renamable type or
201 : : is a register variable, we may use a COMPONENT_REF on the RHS. */
202 : 8757716647 : if (wi)
203 : : {
204 : 8757073541 : tree lhs = gimple_assign_lhs (stmt);
205 : 8757073541 : wi->val_only
206 : 17514147082 : = (is_gimple_reg_type (TREE_TYPE (lhs)) && !is_gimple_reg (lhs))
207 : 15383906871 : || gimple_assign_rhs_class (stmt) != GIMPLE_SINGLE_RHS;
208 : : }
209 : :
210 : 19533319652 : for (i = 1; i < gimple_num_ops (stmt); i++)
211 : : {
212 : 10775676733 : ret = walk_tree (gimple_op_ptr (stmt, i), callback_op, wi,
213 : : pset);
214 : 10775676733 : if (ret)
215 : : return ret;
216 : : }
217 : :
218 : : /* Walk the LHS. If the RHS is appropriate for a memory, we
219 : : may use a COMPONENT_REF on the LHS. */
220 : 8757642919 : if (wi)
221 : : {
222 : : /* If the RHS is of a non-renamable type or is a register variable,
223 : : we may use a COMPONENT_REF on the LHS. */
224 : 8757066408 : tree rhs1 = gimple_assign_rhs1 (stmt);
225 : 8757066408 : wi->val_only
226 : 8757066408 : = (is_gimple_reg_type (TREE_TYPE (rhs1)) && !is_gimple_reg (rhs1))
227 : 13571704643 : || gimple_assign_rhs_class (stmt) != GIMPLE_SINGLE_RHS;
228 : 8757066408 : wi->is_lhs = true;
229 : : }
230 : :
231 : 8757642919 : ret = walk_tree (gimple_op_ptr (stmt, 0), callback_op, wi, pset);
232 : 8757642919 : if (ret)
233 : : return ret;
234 : :
235 : 8757616591 : if (wi)
236 : : {
237 : 8757065771 : wi->val_only = true;
238 : 8757065771 : wi->is_lhs = false;
239 : : }
240 : : break;
241 : :
242 : 1980117443 : case GIMPLE_CALL:
243 : 1980117443 : if (wi)
244 : : {
245 : 1980048660 : wi->is_lhs = false;
246 : 1980048660 : wi->val_only = true;
247 : : }
248 : :
249 : 1980117443 : ret = walk_tree (gimple_call_chain_ptr (as_a <gcall *> (stmt)),
250 : : callback_op, wi, pset);
251 : 1980117443 : if (ret)
252 : : return ret;
253 : :
254 : 1980117382 : ret = walk_tree (gimple_call_fn_ptr (stmt), callback_op, wi, pset);
255 : 1980117382 : if (ret)
256 : : return ret;
257 : :
258 : 5931925224 : for (i = 0; i < gimple_call_num_args (stmt); i++)
259 : : {
260 : 3951812285 : if (wi)
261 : 3951698281 : wi->val_only
262 : 3951698281 : = is_gimple_reg_type (TREE_TYPE (gimple_call_arg (stmt, i)));
263 : 3951812285 : ret = walk_tree (gimple_call_arg_ptr (stmt, i), callback_op, wi,
264 : : pset);
265 : 3951812285 : if (ret)
266 : : return ret;
267 : : }
268 : :
269 : 1980112939 : if (gimple_call_lhs (stmt))
270 : : {
271 : 787111389 : if (wi)
272 : : {
273 : 787091534 : wi->is_lhs = true;
274 : 787091534 : wi->val_only
275 : 787091534 : = is_gimple_reg_type (TREE_TYPE (gimple_call_lhs (stmt)));
276 : : }
277 : :
278 : 787111389 : ret = walk_tree (gimple_call_lhs_ptr (stmt), callback_op, wi, pset);
279 : 787111389 : if (ret)
280 : : return ret;
281 : : }
282 : :
283 : 1980112621 : if (wi)
284 : : {
285 : 1980047503 : wi->is_lhs = false;
286 : 1980047503 : wi->val_only = true;
287 : : }
288 : : break;
289 : :
290 : 17644 : case GIMPLE_CATCH:
291 : 17644 : ret = walk_tree (gimple_catch_types_ptr (as_a <gcatch *> (stmt)),
292 : : callback_op, wi, pset);
293 : 17644 : if (ret)
294 : : return ret;
295 : : break;
296 : :
297 : 71 : case GIMPLE_EH_FILTER:
298 : 71 : ret = walk_tree (gimple_eh_filter_types_ptr (stmt), callback_op, wi,
299 : : pset);
300 : 71 : if (ret)
301 : : return ret;
302 : : break;
303 : :
304 : 26285267 : case GIMPLE_ASM:
305 : 26285267 : ret = walk_gimple_asm (as_a <gasm *> (stmt), callback_op, wi);
306 : 26285267 : if (ret)
307 : : return ret;
308 : : break;
309 : :
310 : 195938 : case GIMPLE_OMP_CONTINUE:
311 : 195938 : {
312 : 195938 : gomp_continue *cont_stmt = as_a <gomp_continue *> (stmt);
313 : 195938 : ret = walk_tree (gimple_omp_continue_control_def_ptr (cont_stmt),
314 : : callback_op, wi, pset);
315 : 195938 : if (ret)
316 : : return ret;
317 : :
318 : 195938 : ret = walk_tree (gimple_omp_continue_control_use_ptr (cont_stmt),
319 : : callback_op, wi, pset);
320 : 195938 : if (ret)
321 : : return ret;
322 : : }
323 : : break;
324 : :
325 : 1352 : case GIMPLE_OMP_CRITICAL:
326 : 1352 : {
327 : 1352 : gomp_critical *omp_stmt = as_a <gomp_critical *> (stmt);
328 : 1352 : ret = walk_tree (gimple_omp_critical_name_ptr (omp_stmt),
329 : : callback_op, wi, pset);
330 : 1352 : if (ret)
331 : : return ret;
332 : 1352 : ret = walk_tree (gimple_omp_critical_clauses_ptr (omp_stmt),
333 : : callback_op, wi, pset);
334 : 1352 : if (ret)
335 : : return ret;
336 : : }
337 : : break;
338 : :
339 : 5431 : case GIMPLE_OMP_ORDERED:
340 : 5431 : {
341 : 5431 : gomp_ordered *omp_stmt = as_a <gomp_ordered *> (stmt);
342 : 5431 : ret = walk_tree (gimple_omp_ordered_clauses_ptr (omp_stmt),
343 : : callback_op, wi, pset);
344 : 5431 : if (ret)
345 : : return ret;
346 : : }
347 : : break;
348 : :
349 : 824 : case GIMPLE_OMP_SCAN:
350 : 824 : {
351 : 824 : gomp_scan *scan_stmt = as_a <gomp_scan *> (stmt);
352 : 824 : ret = walk_tree (gimple_omp_scan_clauses_ptr (scan_stmt),
353 : : callback_op, wi, pset);
354 : 824 : if (ret)
355 : : return ret;
356 : : }
357 : : break;
358 : :
359 : 190396 : case GIMPLE_OMP_FOR:
360 : 190396 : ret = walk_tree (gimple_omp_for_clauses_ptr (stmt), callback_op, wi,
361 : : pset);
362 : 190396 : if (ret)
363 : : return ret;
364 : 466183 : for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
365 : : {
366 : 275787 : ret = walk_tree (gimple_omp_for_index_ptr (stmt, i), callback_op,
367 : : wi, pset);
368 : 275787 : if (ret)
369 : : return ret;
370 : 275787 : ret = walk_tree (gimple_omp_for_initial_ptr (stmt, i), callback_op,
371 : : wi, pset);
372 : 275787 : if (ret)
373 : : return ret;
374 : 275787 : ret = walk_tree (gimple_omp_for_final_ptr (stmt, i), callback_op,
375 : : wi, pset);
376 : 275787 : if (ret)
377 : : return ret;
378 : 275787 : ret = walk_tree (gimple_omp_for_incr_ptr (stmt, i), callback_op,
379 : : wi, pset);
380 : 275787 : if (ret)
381 : : return ret;
382 : : }
383 : : break;
384 : :
385 : 65754 : case GIMPLE_OMP_PARALLEL:
386 : 65754 : {
387 : 65754 : gomp_parallel *omp_par_stmt = as_a <gomp_parallel *> (stmt);
388 : 65754 : ret = walk_tree (gimple_omp_parallel_clauses_ptr (omp_par_stmt),
389 : : callback_op, wi, pset);
390 : 65754 : if (ret)
391 : : return ret;
392 : 65754 : ret = walk_tree (gimple_omp_parallel_child_fn_ptr (omp_par_stmt),
393 : : callback_op, wi, pset);
394 : 65754 : if (ret)
395 : : return ret;
396 : 65754 : ret = walk_tree (gimple_omp_parallel_data_arg_ptr (omp_par_stmt),
397 : : callback_op, wi, pset);
398 : 65754 : if (ret)
399 : : return ret;
400 : : }
401 : : break;
402 : :
403 : 15673 : case GIMPLE_OMP_TASK:
404 : 15673 : ret = walk_tree (gimple_omp_task_clauses_ptr (stmt), callback_op,
405 : : wi, pset);
406 : 15673 : if (ret)
407 : : return ret;
408 : 15673 : ret = walk_tree (gimple_omp_task_child_fn_ptr (stmt), callback_op,
409 : : wi, pset);
410 : 15673 : if (ret)
411 : : return ret;
412 : 15673 : ret = walk_tree (gimple_omp_task_data_arg_ptr (stmt), callback_op,
413 : : wi, pset);
414 : 15673 : if (ret)
415 : : return ret;
416 : 15673 : ret = walk_tree (gimple_omp_task_copy_fn_ptr (stmt), callback_op,
417 : : wi, pset);
418 : 15673 : if (ret)
419 : : return ret;
420 : 15673 : ret = walk_tree (gimple_omp_task_arg_size_ptr (stmt), callback_op,
421 : : wi, pset);
422 : 15673 : if (ret)
423 : : return ret;
424 : 15673 : ret = walk_tree (gimple_omp_task_arg_align_ptr (stmt), callback_op,
425 : : wi, pset);
426 : 15673 : if (ret)
427 : : return ret;
428 : : break;
429 : :
430 : 1554 : case GIMPLE_OMP_SECTIONS:
431 : 1554 : ret = walk_tree (gimple_omp_sections_clauses_ptr (stmt), callback_op,
432 : : wi, pset);
433 : 1554 : if (ret)
434 : : return ret;
435 : 1554 : ret = walk_tree (gimple_omp_sections_control_ptr (stmt), callback_op,
436 : : wi, pset);
437 : 1554 : if (ret)
438 : : return ret;
439 : :
440 : : break;
441 : :
442 : 4662 : case GIMPLE_OMP_SINGLE:
443 : 4662 : ret = walk_tree (gimple_omp_single_clauses_ptr (stmt), callback_op, wi,
444 : : pset);
445 : 4662 : if (ret)
446 : : return ret;
447 : : break;
448 : :
449 : 144569 : case GIMPLE_OMP_TARGET:
450 : 144569 : {
451 : 144569 : gomp_target *omp_stmt = as_a <gomp_target *> (stmt);
452 : 144569 : ret = walk_tree (gimple_omp_target_clauses_ptr (omp_stmt),
453 : : callback_op, wi, pset);
454 : 144569 : if (ret)
455 : : return ret;
456 : 144569 : ret = walk_tree (gimple_omp_target_child_fn_ptr (omp_stmt),
457 : : callback_op, wi, pset);
458 : 144569 : if (ret)
459 : : return ret;
460 : 144569 : ret = walk_tree (gimple_omp_target_data_arg_ptr (omp_stmt),
461 : : callback_op, wi, pset);
462 : 144569 : if (ret)
463 : : return ret;
464 : : }
465 : : break;
466 : :
467 : 33882 : case GIMPLE_OMP_TEAMS:
468 : 33882 : ret = walk_tree (gimple_omp_teams_clauses_ptr (stmt), callback_op, wi,
469 : : pset);
470 : 33882 : if (ret)
471 : : return ret;
472 : : break;
473 : :
474 : 48373 : case GIMPLE_OMP_ATOMIC_LOAD:
475 : 48373 : {
476 : 48373 : gomp_atomic_load *omp_stmt = as_a <gomp_atomic_load *> (stmt);
477 : 48373 : ret = walk_tree (gimple_omp_atomic_load_lhs_ptr (omp_stmt),
478 : : callback_op, wi, pset);
479 : 48373 : if (ret)
480 : : return ret;
481 : 48373 : ret = walk_tree (gimple_omp_atomic_load_rhs_ptr (omp_stmt),
482 : : callback_op, wi, pset);
483 : 48373 : if (ret)
484 : : return ret;
485 : : }
486 : : break;
487 : :
488 : 49383 : case GIMPLE_OMP_ATOMIC_STORE:
489 : 49383 : {
490 : 49383 : gomp_atomic_store *omp_stmt = as_a <gomp_atomic_store *> (stmt);
491 : 49383 : ret = walk_tree (gimple_omp_atomic_store_val_ptr (omp_stmt),
492 : : callback_op, wi, pset);
493 : 49383 : if (ret)
494 : : return ret;
495 : : }
496 : : break;
497 : :
498 : 12 : case GIMPLE_ASSUME:
499 : 12 : ret = walk_tree (gimple_assume_guard_ptr (stmt), callback_op, wi, pset);
500 : 12 : if (ret)
501 : : return ret;
502 : : break;
503 : :
504 : 61988 : case GIMPLE_TRANSACTION:
505 : 61988 : {
506 : 61988 : gtransaction *txn = as_a <gtransaction *> (stmt);
507 : :
508 : 61988 : ret = walk_tree (gimple_transaction_label_norm_ptr (txn),
509 : : callback_op, wi, pset);
510 : 61988 : if (ret)
511 : : return ret;
512 : 61988 : ret = walk_tree (gimple_transaction_label_uninst_ptr (txn),
513 : : callback_op, wi, pset);
514 : 61988 : if (ret)
515 : : return ret;
516 : 61988 : ret = walk_tree (gimple_transaction_label_over_ptr (txn),
517 : : callback_op, wi, pset);
518 : 61988 : if (ret)
519 : : return ret;
520 : : }
521 : : break;
522 : :
523 : 399400 : case GIMPLE_OMP_RETURN:
524 : 399400 : ret = walk_tree (gimple_omp_return_lhs_ptr (stmt), callback_op, wi,
525 : : pset);
526 : 399400 : if (ret)
527 : : return ret;
528 : : break;
529 : :
530 : : /* Tuples that do not have operands. */
531 : : case GIMPLE_NOP:
532 : : case GIMPLE_RESX:
533 : : case GIMPLE_PREDICT:
534 : : break;
535 : :
536 : 11737 : case GIMPLE_PHI:
537 : : /* PHIs are not GSS_WITH_OPS so we need to handle them explicitely. */
538 : 11737 : {
539 : 11737 : gphi *phi = as_a <gphi *> (stmt);
540 : 11737 : if (wi)
541 : : {
542 : 10959 : wi->val_only = true;
543 : 10959 : wi->is_lhs = true;
544 : : }
545 : 11737 : ret = walk_tree (gimple_phi_result_ptr (phi), callback_op, wi, pset);
546 : 11737 : if (wi)
547 : 10959 : wi->is_lhs = false;
548 : 11737 : if (ret)
549 : : return ret;
550 : 34312 : for (unsigned i = 0; i < gimple_phi_num_args (phi); ++i)
551 : : {
552 : 22575 : ret = walk_tree (gimple_phi_arg_def_ptr (phi, i),
553 : : callback_op, wi, pset);
554 : 22575 : if (ret)
555 : : return ret;
556 : : }
557 : : break;
558 : : }
559 : :
560 : 14532162565 : default:
561 : 14532162565 : {
562 : 14532162565 : enum gimple_statement_structure_enum gss;
563 : 14532162565 : gss = gimple_statement_structure (stmt);
564 : 14532162565 : if (gss == GSS_WITH_OPS || gss == GSS_WITH_MEM_OPS)
565 : 39986837824 : for (i = 0; i < gimple_num_ops (stmt); i++)
566 : : {
567 : 25460818049 : ret = walk_tree (gimple_op_ptr (stmt, i), callback_op, wi, pset);
568 : 25460818049 : if (ret)
569 : : return ret;
570 : : }
571 : : }
572 : : break;
573 : : }
574 : :
575 : : return NULL_TREE;
576 : : }
577 : :
578 : :
579 : : /* Walk the current statement in GSI (optionally using traversal state
580 : : stored in WI). If WI is NULL, no state is kept during traversal.
581 : : The callback CALLBACK_STMT is called. If CALLBACK_STMT indicates
582 : : that it has handled all the operands of the statement, its return
583 : : value is returned. Otherwise, the return value from CALLBACK_STMT
584 : : is discarded and its operands are scanned.
585 : :
586 : : If CALLBACK_STMT is NULL or it didn't handle the operands,
587 : : CALLBACK_OP is called on each operand of the statement via
588 : : walk_gimple_op. If walk_gimple_op returns non-NULL for any
589 : : operand, the remaining operands are not scanned. In this case, the
590 : : return value from CALLBACK_OP is returned.
591 : :
592 : : In any other case, NULL_TREE is returned. */
593 : :
594 : : tree
595 : 234998955 : walk_gimple_stmt (gimple_stmt_iterator *gsi, walk_stmt_fn callback_stmt,
596 : : walk_tree_fn callback_op, struct walk_stmt_info *wi)
597 : : {
598 : 234998955 : gimple *ret;
599 : 234998955 : tree tree_ret;
600 : 234998955 : gimple *stmt = gsi_stmt (*gsi);
601 : :
602 : 234998955 : if (wi)
603 : : {
604 : 234995396 : wi->gsi = *gsi;
605 : 234995396 : wi->removed_stmt = false;
606 : :
607 : 234995396 : if (wi->want_locations && gimple_has_location (stmt))
608 : 5202134 : input_location = gimple_location (stmt);
609 : : }
610 : :
611 : 234998955 : ret = NULL;
612 : :
613 : : /* Invoke the statement callback. Return if the callback handled
614 : : all of STMT operands by itself. */
615 : 234998955 : if (callback_stmt)
616 : : {
617 : 234960715 : bool handled_ops = false;
618 : 234960715 : tree_ret = callback_stmt (gsi, &handled_ops, wi);
619 : 234960699 : if (handled_ops)
620 : 21450429 : return tree_ret;
621 : :
622 : : /* If CALLBACK_STMT did not handle operands, it should not have
623 : : a value to return. */
624 : 213510270 : gcc_assert (tree_ret == NULL);
625 : :
626 : 213510270 : if (wi && wi->removed_stmt)
627 : : return NULL;
628 : :
629 : : /* Re-read stmt in case the callback changed it. */
630 : 213510270 : stmt = gsi_stmt (*gsi);
631 : : }
632 : :
633 : : /* If CALLBACK_OP is defined, invoke it on every operand of STMT. */
634 : 213548510 : if (callback_op)
635 : : {
636 : 24867347 : tree_ret = walk_gimple_op (stmt, callback_op, wi);
637 : 24867347 : if (tree_ret)
638 : : return tree_ret;
639 : : }
640 : :
641 : : /* If STMT can have statements inside (e.g. GIMPLE_BIND), walk them. */
642 : 213548510 : switch (gimple_code (stmt))
643 : : {
644 : 2742042 : case GIMPLE_BIND:
645 : 2742042 : ret = walk_gimple_seq_mod (gimple_bind_body_ptr (as_a <gbind *> (stmt)),
646 : : callback_stmt, callback_op, wi);
647 : 2742032 : if (ret)
648 : 12476 : return wi->callback_result;
649 : : break;
650 : :
651 : 35390 : case GIMPLE_CATCH:
652 : 35390 : ret = walk_gimple_seq_mod (gimple_catch_handler_ptr (
653 : : as_a <gcatch *> (stmt)),
654 : : callback_stmt, callback_op, wi);
655 : 35390 : if (ret)
656 : 0 : return wi->callback_result;
657 : : break;
658 : :
659 : 161 : case GIMPLE_EH_FILTER:
660 : 161 : ret = walk_gimple_seq_mod (gimple_eh_filter_failure_ptr (stmt), callback_stmt,
661 : : callback_op, wi);
662 : 161 : if (ret)
663 : 0 : return wi->callback_result;
664 : : break;
665 : :
666 : 819 : case GIMPLE_EH_ELSE:
667 : 819 : {
668 : 819 : geh_else *eh_else_stmt = as_a <geh_else *> (stmt);
669 : 819 : ret = walk_gimple_seq_mod (gimple_eh_else_n_body_ptr (eh_else_stmt),
670 : : callback_stmt, callback_op, wi);
671 : 819 : if (ret)
672 : 0 : return wi->callback_result;
673 : 819 : ret = walk_gimple_seq_mod (gimple_eh_else_e_body_ptr (eh_else_stmt),
674 : : callback_stmt, callback_op, wi);
675 : 819 : if (ret)
676 : 0 : return wi->callback_result;
677 : : }
678 : : break;
679 : :
680 : 637380 : case GIMPLE_TRY:
681 : 637380 : ret = walk_gimple_seq_mod (gimple_try_eval_ptr (stmt), callback_stmt, callback_op,
682 : : wi);
683 : 637374 : if (ret)
684 : 204 : return wi->callback_result;
685 : :
686 : 637170 : ret = walk_gimple_seq_mod (gimple_try_cleanup_ptr (stmt), callback_stmt,
687 : : callback_op, wi);
688 : 637170 : if (ret)
689 : 0 : return wi->callback_result;
690 : : break;
691 : :
692 : 8787 : case GIMPLE_OMP_FOR:
693 : 8787 : ret = walk_gimple_seq_mod (gimple_omp_for_pre_body_ptr (stmt), callback_stmt,
694 : : callback_op, wi);
695 : 8787 : if (ret)
696 : 0 : return wi->callback_result;
697 : :
698 : : /* FALL THROUGH. */
699 : 28010 : case GIMPLE_OMP_CRITICAL:
700 : 28010 : case GIMPLE_OMP_MASTER:
701 : 28010 : case GIMPLE_OMP_MASKED:
702 : 28010 : case GIMPLE_OMP_TASKGROUP:
703 : 28010 : case GIMPLE_OMP_ORDERED:
704 : 28010 : case GIMPLE_OMP_SCAN:
705 : 28010 : case GIMPLE_OMP_SECTION:
706 : 28010 : case GIMPLE_OMP_STRUCTURED_BLOCK:
707 : 28010 : case GIMPLE_OMP_PARALLEL:
708 : 28010 : case GIMPLE_OMP_TASK:
709 : 28010 : case GIMPLE_OMP_SCOPE:
710 : 28010 : case GIMPLE_OMP_DISPATCH:
711 : 28010 : case GIMPLE_OMP_SECTIONS:
712 : 28010 : case GIMPLE_OMP_SINGLE:
713 : 28010 : case GIMPLE_OMP_TARGET:
714 : 28010 : case GIMPLE_OMP_TEAMS:
715 : 28010 : ret = walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), callback_stmt,
716 : : callback_op, wi);
717 : 28010 : if (ret)
718 : 0 : return wi->callback_result;
719 : : break;
720 : :
721 : 0 : case GIMPLE_WITH_CLEANUP_EXPR:
722 : 0 : ret = walk_gimple_seq_mod (gimple_wce_cleanup_ptr (stmt), callback_stmt,
723 : : callback_op, wi);
724 : 0 : if (ret)
725 : 0 : return wi->callback_result;
726 : : break;
727 : :
728 : 27 : case GIMPLE_ASSUME:
729 : 27 : ret = walk_gimple_seq_mod (gimple_assume_body_ptr (stmt),
730 : : callback_stmt, callback_op, wi);
731 : 27 : if (ret)
732 : 0 : return wi->callback_result;
733 : : break;
734 : :
735 : 688 : case GIMPLE_TRANSACTION:
736 : 688 : ret = walk_gimple_seq_mod (gimple_transaction_body_ptr (
737 : : as_a <gtransaction *> (stmt)),
738 : : callback_stmt, callback_op, wi);
739 : 688 : if (ret)
740 : 3 : return wi->callback_result;
741 : : break;
742 : :
743 : 210103993 : default:
744 : 210103993 : gcc_assert (!gimple_has_substatements (stmt));
745 : : break;
746 : : }
747 : :
748 : : return NULL;
749 : : }
750 : :
751 : : /* From a tree operand OP return the base of a load or store operation
752 : : or NULL_TREE if OP is not a load or a store. */
753 : :
754 : : static tree
755 : 1154525648 : get_base_loadstore (tree op)
756 : : {
757 : 1320223762 : while (handled_component_p (op))
758 : 165698114 : op = TREE_OPERAND (op, 0);
759 : 1154525648 : if (DECL_P (op)
760 : 915835378 : || INDIRECT_REF_P (op)
761 : 915835378 : || TREE_CODE (op) == MEM_REF
762 : 737866247 : || TREE_CODE (op) == TARGET_MEM_REF)
763 : 423033666 : return op;
764 : : return NULL_TREE;
765 : : }
766 : :
767 : :
768 : : /* For the statement STMT call the callbacks VISIT_LOAD, VISIT_STORE and
769 : : VISIT_ADDR if non-NULL on loads, store and address-taken operands
770 : : passing the STMT, the base of the operand, the operand itself containing
771 : : the base and DATA to it. The base will be either a decl, an indirect
772 : : reference (including TARGET_MEM_REF) or the argument of an address
773 : : expression.
774 : : Returns the results of these callbacks or'ed. */
775 : :
776 : : bool
777 : 2337606648 : walk_stmt_load_store_addr_ops (gimple *stmt, void *data,
778 : : walk_stmt_load_store_addr_fn visit_load,
779 : : walk_stmt_load_store_addr_fn visit_store,
780 : : walk_stmt_load_store_addr_fn visit_addr)
781 : : {
782 : 2337606648 : bool ret = false;
783 : 2337606648 : unsigned i;
784 : 2337606648 : if (gimple_assign_single_p (stmt))
785 : : {
786 : 605812774 : tree lhs, rhs, arg;
787 : 605812774 : if (visit_store)
788 : : {
789 : 400177975 : arg = gimple_assign_lhs (stmt);
790 : 400177975 : lhs = get_base_loadstore (arg);
791 : 400177975 : if (lhs)
792 : 201865926 : ret |= visit_store (stmt, lhs, arg, data);
793 : : }
794 : 605812774 : arg = gimple_assign_rhs1 (stmt);
795 : 605812774 : rhs = arg;
796 : 1435519488 : while (handled_component_p (rhs))
797 : 223893940 : rhs = TREE_OPERAND (rhs, 0);
798 : 605812774 : if (visit_addr)
799 : : {
800 : 386829160 : if (TREE_CODE (rhs) == ADDR_EXPR)
801 : 33584212 : ret |= visit_addr (stmt, TREE_OPERAND (rhs, 0), arg, data);
802 : 353244948 : else if (TREE_CODE (rhs) == OBJ_TYPE_REF
803 : 353244948 : && TREE_CODE (OBJ_TYPE_REF_OBJECT (rhs)) == ADDR_EXPR)
804 : 406 : ret |= visit_addr (stmt, TREE_OPERAND (OBJ_TYPE_REF_OBJECT (rhs),
805 : : 0), arg, data);
806 : 353244542 : else if (TREE_CODE (rhs) == CONSTRUCTOR)
807 : : {
808 : : unsigned int ix;
809 : : tree val;
810 : :
811 : 44567773 : FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (rhs), ix, val)
812 : 2662675 : if (TREE_CODE (val) == ADDR_EXPR)
813 : 0 : ret |= visit_addr (stmt, TREE_OPERAND (val, 0), arg, data);
814 : 2662675 : else if (TREE_CODE (val) == OBJ_TYPE_REF
815 : 2662675 : && TREE_CODE (OBJ_TYPE_REF_OBJECT (val)) == ADDR_EXPR)
816 : 0 : ret |= visit_addr (stmt,
817 : 0 : TREE_OPERAND (OBJ_TYPE_REF_OBJECT (val),
818 : : 0), arg, data);
819 : : }
820 : : }
821 : 605812774 : if (visit_load)
822 : : {
823 : 400175936 : rhs = get_base_loadstore (rhs);
824 : 400175936 : if (rhs)
825 : 179602592 : ret |= visit_load (stmt, rhs, arg, data);
826 : : }
827 : : }
828 : 1731793874 : else if (visit_addr
829 : 1731793874 : && (is_gimple_assign (stmt)
830 : 826090899 : || gimple_code (stmt) == GIMPLE_COND))
831 : : {
832 : 1069519503 : for (i = 0; i < gimple_num_ops (stmt); ++i)
833 : : {
834 : 811670092 : tree op = gimple_op (stmt, i);
835 : 811670092 : if (op == NULL_TREE)
836 : : ;
837 : 637990260 : else if (TREE_CODE (op) == ADDR_EXPR)
838 : 7244184 : ret |= visit_addr (stmt, TREE_OPERAND (op, 0), op, data);
839 : : }
840 : : }
841 : 1473944463 : else if (gcall *call_stmt = dyn_cast <gcall *> (stmt))
842 : : {
843 : 207850242 : if (visit_store)
844 : : {
845 : 152234189 : tree arg = gimple_call_lhs (call_stmt);
846 : 152234189 : if (arg)
847 : : {
848 : 61558681 : tree lhs = get_base_loadstore (arg);
849 : 61558681 : if (lhs)
850 : 13054505 : ret |= visit_store (stmt, lhs, arg, data);
851 : : }
852 : : }
853 : 207850242 : if (visit_load || visit_addr)
854 : 626306396 : for (i = 0; i < gimple_call_num_args (call_stmt); ++i)
855 : : {
856 : 418837230 : tree arg = gimple_call_arg (call_stmt, i);
857 : 418837230 : if (visit_addr
858 : 240141599 : && TREE_CODE (arg) == ADDR_EXPR)
859 : 72764241 : ret |= visit_addr (stmt, TREE_OPERAND (arg, 0), arg, data);
860 : 346072989 : else if (visit_load)
861 : : {
862 : 269687575 : tree rhs = get_base_loadstore (arg);
863 : 269687575 : if (rhs)
864 : 22988225 : ret |= visit_load (stmt, rhs, arg, data);
865 : : }
866 : : }
867 : 207469166 : if (visit_addr
868 : 120543064 : && gimple_call_chain (call_stmt)
869 : 208031038 : && TREE_CODE (gimple_call_chain (call_stmt)) == ADDR_EXPR)
870 : 232584 : ret |= visit_addr (stmt, TREE_OPERAND (gimple_call_chain (call_stmt), 0),
871 : : gimple_call_chain (call_stmt), data);
872 : 207850242 : if (visit_addr
873 : 120543064 : && gimple_call_return_slot_opt_p (call_stmt)
874 : 4464227 : && gimple_call_lhs (call_stmt) != NULL_TREE
875 : 212139049 : && TREE_ADDRESSABLE (TREE_TYPE (gimple_call_lhs (call_stmt))))
876 : 1042429 : ret |= visit_addr (stmt, gimple_call_lhs (call_stmt),
877 : : gimple_call_lhs (call_stmt), data);
878 : : }
879 : 1266094221 : else if (gasm *asm_stmt = dyn_cast <gasm *> (stmt))
880 : : {
881 : 1732781 : unsigned noutputs;
882 : 1732781 : const char *constraint;
883 : 1732781 : const char **oconstraints;
884 : 1732781 : bool allows_mem, allows_reg, is_inout;
885 : 1732781 : noutputs = gimple_asm_noutputs (asm_stmt);
886 : 1732781 : oconstraints = XALLOCAVEC (const char *, noutputs);
887 : 1732781 : if (visit_store || visit_addr)
888 : 3236721 : for (i = 0; i < gimple_asm_noutputs (asm_stmt); ++i)
889 : : {
890 : 1503940 : tree link = gimple_asm_output_op (asm_stmt, i);
891 : 1503940 : tree op = get_base_loadstore (TREE_VALUE (link));
892 : 1503940 : if (op && visit_store)
893 : 217412 : ret |= visit_store (stmt, op, TREE_VALUE (link), data);
894 : 1503940 : if (visit_addr)
895 : : {
896 : 1030318 : constraint = TREE_STRING_POINTER
897 : : (TREE_VALUE (TREE_PURPOSE (link)));
898 : 1030318 : oconstraints[i] = constraint;
899 : 1030318 : parse_output_constraint (&constraint, i, 0, 0, &allows_mem,
900 : : &allows_reg, &is_inout);
901 : 1030318 : if (op && !allows_reg && allows_mem)
902 : 57990 : ret |= visit_addr (stmt, op, TREE_VALUE (link), data);
903 : : }
904 : : }
905 : 1732781 : if (visit_load || visit_addr)
906 : 2706144 : for (i = 0; i < gimple_asm_ninputs (asm_stmt); ++i)
907 : : {
908 : 974483 : tree link = gimple_asm_input_op (asm_stmt, i);
909 : 974483 : tree op = TREE_VALUE (link);
910 : 974483 : if (visit_addr
911 : 695368 : && TREE_CODE (op) == ADDR_EXPR)
912 : 68436 : ret |= visit_addr (stmt, TREE_OPERAND (op, 0), op, data);
913 : 906047 : else if (visit_load || visit_addr)
914 : : {
915 : 906047 : op = get_base_loadstore (op);
916 : 906047 : if (op)
917 : : {
918 : 144175 : if (visit_load)
919 : 75506 : ret |= visit_load (stmt, op, TREE_VALUE (link), data);
920 : 144175 : if (visit_addr)
921 : : {
922 : 121072 : constraint = TREE_STRING_POINTER
923 : : (TREE_VALUE (TREE_PURPOSE (link)));
924 : 121072 : parse_input_constraint (&constraint, 0, 0, noutputs,
925 : : 0, oconstraints,
926 : : &allows_mem, &allows_reg);
927 : 121072 : if (!allows_reg && allows_mem)
928 : 64032 : ret |= visit_addr (stmt, op, TREE_VALUE (link),
929 : : data);
930 : : }
931 : : }
932 : : }
933 : : }
934 : : }
935 : 1264361440 : else if (greturn *return_stmt = dyn_cast <greturn *> (stmt))
936 : : {
937 : 51163647 : tree op = gimple_return_retval (return_stmt);
938 : 51163647 : if (op)
939 : : {
940 : 27795257 : if (visit_addr
941 : 15299712 : && TREE_CODE (op) == ADDR_EXPR)
942 : 26041 : ret |= visit_addr (stmt, TREE_OPERAND (op, 0), op, data);
943 : 27769216 : else if (visit_load)
944 : : {
945 : 20515494 : tree base = get_base_loadstore (op);
946 : 20515494 : if (base)
947 : 5002203 : ret |= visit_load (stmt, base, op, data);
948 : : }
949 : : }
950 : : }
951 : 1213197793 : else if (visit_addr
952 : 1213197793 : && gimple_code (stmt) == GIMPLE_PHI)
953 : : {
954 : 100295240 : for (i = 0; i < gimple_phi_num_args (stmt); ++i)
955 : : {
956 : 72321694 : tree op = gimple_phi_arg_def (stmt, i);
957 : 72321694 : if (TREE_CODE (op) == ADDR_EXPR)
958 : 474297 : ret |= visit_addr (stmt, TREE_OPERAND (op, 0), op, data);
959 : : }
960 : : }
961 : 1185224247 : else if (visit_addr
962 : 1185224247 : && gimple_code (stmt) == GIMPLE_GOTO)
963 : : {
964 : 5392 : tree op = gimple_goto_dest (stmt);
965 : 5392 : if (TREE_CODE (op) == ADDR_EXPR)
966 : 83 : ret |= visit_addr (stmt, TREE_OPERAND (op, 0), op, data);
967 : : }
968 : :
969 : 2337606648 : return ret;
970 : : }
971 : :
972 : : /* Like walk_stmt_load_store_addr_ops but with NULL visit_addr. IPA-CP
973 : : should make a faster clone for this case. */
974 : :
975 : : bool
976 : 953677094 : walk_stmt_load_store_ops (gimple *stmt, void *data,
977 : : walk_stmt_load_store_addr_fn visit_load,
978 : : walk_stmt_load_store_addr_fn visit_store)
979 : : {
980 : 953677094 : return walk_stmt_load_store_addr_ops (stmt, data,
981 : 953677094 : visit_load, visit_store, NULL);
982 : : }
|