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