Home | History | Annotate | Line # | Download | only in gcc
      1 /* Exception handling semantics and decomposition for trees.
      2    Copyright (C) 2003-2024 Free Software Foundation, Inc.
      3 
      4 This file is part of GCC.
      5 
      6 GCC is free software; you can redistribute it and/or modify
      7 it under the terms of the GNU General Public License as published by
      8 the Free Software Foundation; either version 3, or (at your option)
      9 any later version.
     10 
     11 GCC is distributed in the hope that it will be useful,
     12 but WITHOUT ANY WARRANTY; without even the implied warranty of
     13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     14 GNU General Public License for more details.
     15 
     16 You should have received a copy of the GNU General Public License
     17 along with GCC; see the file COPYING3.  If not see
     18 <http://www.gnu.org/licenses/>.  */
     19 
     20 #include "config.h"
     21 #include "system.h"
     22 #include "coretypes.h"
     23 #include "backend.h"
     24 #include "rtl.h"
     25 #include "tree.h"
     26 #include "gimple.h"
     27 #include "cfghooks.h"
     28 #include "tree-pass.h"
     29 #include "ssa.h"
     30 #include "cgraph.h"
     31 #include "diagnostic-core.h"
     32 #include "fold-const.h"
     33 #include "calls.h"
     34 #include "except.h"
     35 #include "cfganal.h"
     36 #include "cfgcleanup.h"
     37 #include "tree-eh.h"
     38 #include "gimple-iterator.h"
     39 #include "tree-cfg.h"
     40 #include "tree-into-ssa.h"
     41 #include "tree-ssa.h"
     42 #include "tree-inline.h"
     43 #include "langhooks.h"
     44 #include "cfgloop.h"
     45 #include "gimple-low.h"
     46 #include "stringpool.h"
     47 #include "attribs.h"
     48 #include "asan.h"
     49 #include "gimplify.h"
     50 
     51 /* In some instances a tree and a gimple need to be stored in a same table,
     52    i.e. in hash tables. This is a structure to do this. */
     53 typedef union {tree *tp; tree t; gimple *g;} treemple;
     54 
     55 /* Misc functions used in this file.  */
     56 
     57 /* Remember and lookup EH landing pad data for arbitrary statements.
     58    Really this means any statement that could_throw_p.  We could
     59    stuff this information into the stmt_ann data structure, but:
     60 
     61    (1) We absolutely rely on this information being kept until
     62    we get to rtl.  Once we're done with lowering here, if we lose
     63    the information there's no way to recover it!
     64 
     65    (2) There are many more statements that *cannot* throw as
     66    compared to those that can.  We should be saving some amount
     67    of space by only allocating memory for those that can throw.  */
     68 
     69 /* Add statement T in function IFUN to landing pad NUM.  */
     70 
     71 static void
     72 add_stmt_to_eh_lp_fn (struct function *ifun, gimple *t, int num)
     73 {
     74   gcc_assert (num != 0);
     75 
     76   if (!get_eh_throw_stmt_table (ifun))
     77     set_eh_throw_stmt_table (ifun, hash_map<gimple *, int>::create_ggc (31));
     78 
     79   bool existed = get_eh_throw_stmt_table (ifun)->put (t, num);
     80   gcc_assert (!existed);
     81 }
     82 
     83 /* Add statement T in the current function (cfun) to EH landing pad NUM.  */
     84 
     85 void
     86 add_stmt_to_eh_lp (gimple *t, int num)
     87 {
     88   add_stmt_to_eh_lp_fn (cfun, t, num);
     89 }
     90 
     91 /* Add statement T to the single EH landing pad in REGION.  */
     92 
     93 static void
     94 record_stmt_eh_region (eh_region region, gimple *t)
     95 {
     96   if (region == NULL)
     97     return;
     98   if (region->type == ERT_MUST_NOT_THROW)
     99     add_stmt_to_eh_lp_fn (cfun, t, -region->index);
    100   else
    101     {
    102       eh_landing_pad lp = region->landing_pads;
    103       if (lp == NULL)
    104 	lp = gen_eh_landing_pad (region);
    105       else
    106 	gcc_assert (lp->next_lp == NULL);
    107       add_stmt_to_eh_lp_fn (cfun, t, lp->index);
    108     }
    109 }
    110 
    111 
    112 /* Remove statement T in function IFUN from its EH landing pad.  */
    113 
    114 bool
    115 remove_stmt_from_eh_lp_fn (struct function *ifun, gimple *t)
    116 {
    117   if (!get_eh_throw_stmt_table (ifun))
    118     return false;
    119 
    120   if (!get_eh_throw_stmt_table (ifun)->get (t))
    121     return false;
    122 
    123   get_eh_throw_stmt_table (ifun)->remove (t);
    124       return true;
    125 }
    126 
    127 
    128 /* Remove statement T in the current function (cfun) from its
    129    EH landing pad.  */
    130 
    131 bool
    132 remove_stmt_from_eh_lp (gimple *t)
    133 {
    134   return remove_stmt_from_eh_lp_fn (cfun, t);
    135 }
    136 
    137 /* Determine if statement T is inside an EH region in function IFUN.
    138    Positive numbers indicate a landing pad index; negative numbers
    139    indicate a MUST_NOT_THROW region index; zero indicates that the
    140    statement is not recorded in the region table.  */
    141 
    142 int
    143 lookup_stmt_eh_lp_fn (struct function *ifun, const gimple *t)
    144 {
    145   if (ifun->eh->throw_stmt_table == NULL)
    146     return 0;
    147 
    148   int *lp_nr = ifun->eh->throw_stmt_table->get (const_cast <gimple *> (t));
    149   return lp_nr ? *lp_nr : 0;
    150 }
    151 
    152 /* Likewise, but always use the current function.  */
    153 
    154 int
    155 lookup_stmt_eh_lp (const gimple *t)
    156 {
    157   /* We can get called from initialized data when -fnon-call-exceptions
    158      is on; prevent crash.  */
    159   if (!cfun)
    160     return 0;
    161   return lookup_stmt_eh_lp_fn (cfun, t);
    162 }
    163 
    164 /* First pass of EH node decomposition.  Build up a tree of GIMPLE_TRY_FINALLY
    165    nodes and LABEL_DECL nodes.  We will use this during the second phase to
    166    determine if a goto leaves the body of a TRY_FINALLY_EXPR node.  */
    167 
    168 struct finally_tree_node
    169 {
    170   /* When storing a GIMPLE_TRY, we have to record a gimple.  However
    171      when deciding whether a GOTO to a certain LABEL_DECL (which is a
    172      tree) leaves the TRY block, its necessary to record a tree in
    173      this field.  Thus a treemple is used. */
    174   treemple child;
    175   gtry *parent;
    176 };
    177 
    178 /* Hashtable helpers.  */
    179 
    180 struct finally_tree_hasher : free_ptr_hash <finally_tree_node>
    181 {
    182   static inline hashval_t hash (const finally_tree_node *);
    183   static inline bool equal (const finally_tree_node *,
    184 			    const finally_tree_node *);
    185 };
    186 
    187 inline hashval_t
    188 finally_tree_hasher::hash (const finally_tree_node *v)
    189 {
    190   return (intptr_t)v->child.t >> 4;
    191 }
    192 
    193 inline bool
    194 finally_tree_hasher::equal (const finally_tree_node *v,
    195 			    const finally_tree_node *c)
    196 {
    197   return v->child.t == c->child.t;
    198 }
    199 
    200 /* Note that this table is *not* marked GTY.  It is short-lived.  */
    201 static hash_table<finally_tree_hasher> *finally_tree;
    202 
    203 static void
    204 record_in_finally_tree (treemple child, gtry *parent)
    205 {
    206   struct finally_tree_node *n;
    207   finally_tree_node **slot;
    208 
    209   n = XNEW (struct finally_tree_node);
    210   n->child = child;
    211   n->parent = parent;
    212 
    213   slot = finally_tree->find_slot (n, INSERT);
    214   gcc_assert (!*slot);
    215   *slot = n;
    216 }
    217 
    218 static void
    219 collect_finally_tree (gimple *stmt, gtry *region);
    220 
    221 /* Go through the gimple sequence.  Works with collect_finally_tree to
    222    record all GIMPLE_LABEL and GIMPLE_TRY statements. */
    223 
    224 static void
    225 collect_finally_tree_1 (gimple_seq seq, gtry *region)
    226 {
    227   gimple_stmt_iterator gsi;
    228 
    229   for (gsi = gsi_start (seq); !gsi_end_p (gsi); gsi_next (&gsi))
    230     collect_finally_tree (gsi_stmt (gsi), region);
    231 }
    232 
    233 static void
    234 collect_finally_tree (gimple *stmt, gtry *region)
    235 {
    236   treemple temp;
    237 
    238   switch (gimple_code (stmt))
    239     {
    240     case GIMPLE_LABEL:
    241       temp.t = gimple_label_label (as_a <glabel *> (stmt));
    242       record_in_finally_tree (temp, region);
    243       break;
    244 
    245     case GIMPLE_TRY:
    246       if (gimple_try_kind (stmt) == GIMPLE_TRY_FINALLY)
    247         {
    248           temp.g = stmt;
    249           record_in_finally_tree (temp, region);
    250           collect_finally_tree_1 (gimple_try_eval (stmt),
    251 				  as_a <gtry *> (stmt));
    252 	  collect_finally_tree_1 (gimple_try_cleanup (stmt), region);
    253         }
    254       else if (gimple_try_kind (stmt) == GIMPLE_TRY_CATCH)
    255         {
    256           collect_finally_tree_1 (gimple_try_eval (stmt), region);
    257           collect_finally_tree_1 (gimple_try_cleanup (stmt), region);
    258         }
    259       break;
    260 
    261     case GIMPLE_CATCH:
    262       collect_finally_tree_1 (gimple_catch_handler (
    263 				 as_a <gcatch *> (stmt)),
    264 			      region);
    265       break;
    266 
    267     case GIMPLE_EH_FILTER:
    268       collect_finally_tree_1 (gimple_eh_filter_failure (stmt), region);
    269       break;
    270 
    271     case GIMPLE_EH_ELSE:
    272       {
    273 	geh_else *eh_else_stmt = as_a <geh_else *> (stmt);
    274 	collect_finally_tree_1 (gimple_eh_else_n_body (eh_else_stmt), region);
    275 	collect_finally_tree_1 (gimple_eh_else_e_body (eh_else_stmt), region);
    276       }
    277       break;
    278 
    279     default:
    280       /* A type, a decl, or some kind of statement that we're not
    281 	 interested in.  Don't walk them.  */
    282       break;
    283     }
    284 }
    285 
    286 
    287 /* Use the finally tree to determine if a jump from START to TARGET
    288    would leave the try_finally node that START lives in.  */
    289 
    290 static bool
    291 outside_finally_tree (treemple start, gimple *target)
    292 {
    293   struct finally_tree_node n, *p;
    294 
    295   do
    296     {
    297       n.child = start;
    298       p = finally_tree->find (&n);
    299       if (!p)
    300 	return true;
    301       start.g = p->parent;
    302     }
    303   while (start.g != target);
    304 
    305   return false;
    306 }
    307 
    308 /* Second pass of EH node decomposition.  Actually transform the GIMPLE_TRY
    309    nodes into a set of gotos, magic labels, and eh regions.
    310    The eh region creation is straight-forward, but frobbing all the gotos
    311    and such into shape isn't.  */
    312 
    313 /* The sequence into which we record all EH stuff.  This will be
    314    placed at the end of the function when we're all done.  */
    315 static gimple_seq eh_seq;
    316 
    317 /* Record whether an EH region contains something that can throw,
    318    indexed by EH region number.  */
    319 static bitmap eh_region_may_contain_throw_map;
    320 
    321 /* The GOTO_QUEUE is an array of GIMPLE_GOTO and GIMPLE_RETURN
    322    statements that are seen to escape this GIMPLE_TRY_FINALLY node.
    323    The idea is to record a gimple statement for everything except for
    324    the conditionals, which get their labels recorded. Since labels are
    325    of type 'tree', we need this node to store both gimple and tree
    326    objects.  REPL_STMT is the sequence used to replace the goto/return
    327    statement.  CONT_STMT is used to store the statement that allows
    328    the return/goto to jump to the original destination. */
    329 
    330 struct goto_queue_node
    331 {
    332   treemple stmt;
    333   location_t location;
    334   gimple_seq repl_stmt;
    335   gimple *cont_stmt;
    336   int index;
    337   /* This is used when index >= 0 to indicate that stmt is a label (as
    338      opposed to a goto stmt).  */
    339   int is_label;
    340 };
    341 
    342 /* State of the world while lowering.  */
    343 
    344 struct leh_state
    345 {
    346   /* What's "current" while constructing the eh region tree.  These
    347      correspond to variables of the same name in cfun->eh, which we
    348      don't have easy access to.  */
    349   eh_region cur_region;
    350 
    351   /* What's "current" for the purposes of __builtin_eh_pointer.  For
    352      a CATCH, this is the associated TRY.  For an EH_FILTER, this is
    353      the associated ALLOWED_EXCEPTIONS, etc.  */
    354   eh_region ehp_region;
    355 
    356   /* Processing of TRY_FINALLY requires a bit more state.  This is
    357      split out into a separate structure so that we don't have to
    358      copy so much when processing other nodes.  */
    359   struct leh_tf_state *tf;
    360 
    361   /* Outer non-clean up region.  */
    362   eh_region outer_non_cleanup;
    363 };
    364 
    365 struct leh_tf_state
    366 {
    367   /* Pointer to the GIMPLE_TRY_FINALLY node under discussion.  The
    368      try_finally_expr is the original GIMPLE_TRY_FINALLY.  We need to retain
    369      this so that outside_finally_tree can reliably reference the tree used
    370      in the collect_finally_tree data structures.  */
    371   gtry *try_finally_expr;
    372   gtry *top_p;
    373 
    374   /* While lowering a top_p usually it is expanded into multiple statements,
    375      thus we need the following field to store them. */
    376   gimple_seq top_p_seq;
    377 
    378   /* The state outside this try_finally node.  */
    379   struct leh_state *outer;
    380 
    381   /* The exception region created for it.  */
    382   eh_region region;
    383 
    384   /* The goto queue.  */
    385   struct goto_queue_node *goto_queue;
    386   size_t goto_queue_size;
    387   size_t goto_queue_active;
    388 
    389   /* Pointer map to help in searching goto_queue when it is large.  */
    390   hash_map<gimple *, goto_queue_node *> *goto_queue_map;
    391 
    392   /* The set of unique labels seen as entries in the goto queue.  */
    393   vec<tree> dest_array;
    394 
    395   /* A label to be added at the end of the completed transformed
    396      sequence.  It will be set if may_fallthru was true *at one time*,
    397      though subsequent transformations may have cleared that flag.  */
    398   tree fallthru_label;
    399 
    400   /* True if it is possible to fall out the bottom of the try block.
    401      Cleared if the fallthru is converted to a goto.  */
    402   bool may_fallthru;
    403 
    404   /* True if any entry in goto_queue is a GIMPLE_RETURN.  */
    405   bool may_return;
    406 
    407   /* True if the finally block can receive an exception edge.
    408      Cleared if the exception case is handled by code duplication.  */
    409   bool may_throw;
    410 };
    411 
    412 static gimple_seq lower_eh_must_not_throw (struct leh_state *, gtry *);
    413 
    414 /* Search for STMT in the goto queue.  Return the replacement,
    415    or null if the statement isn't in the queue.  */
    416 
    417 #define LARGE_GOTO_QUEUE 20
    418 
    419 static void lower_eh_constructs_1 (struct leh_state *state, gimple_seq *seq);
    420 
    421 static gimple_seq
    422 find_goto_replacement (struct leh_tf_state *tf, treemple stmt)
    423 {
    424   unsigned int i;
    425 
    426   if (tf->goto_queue_active < LARGE_GOTO_QUEUE)
    427     {
    428       for (i = 0; i < tf->goto_queue_active; i++)
    429 	if ( tf->goto_queue[i].stmt.g == stmt.g)
    430 	  return tf->goto_queue[i].repl_stmt;
    431       return NULL;
    432     }
    433 
    434   /* If we have a large number of entries in the goto_queue, create a
    435      pointer map and use that for searching.  */
    436 
    437   if (!tf->goto_queue_map)
    438     {
    439       tf->goto_queue_map = new hash_map<gimple *, goto_queue_node *>;
    440       for (i = 0; i < tf->goto_queue_active; i++)
    441 	{
    442 	  bool existed = tf->goto_queue_map->put (tf->goto_queue[i].stmt.g,
    443 						  &tf->goto_queue[i]);
    444 	  gcc_assert (!existed);
    445 	}
    446     }
    447 
    448   goto_queue_node **slot = tf->goto_queue_map->get (stmt.g);
    449   if (slot != NULL)
    450     return ((*slot)->repl_stmt);
    451 
    452   return NULL;
    453 }
    454 
    455 /* A subroutine of replace_goto_queue_1.  Handles the sub-clauses of a
    456    lowered GIMPLE_COND.  If, by chance, the replacement is a simple goto,
    457    then we can just splat it in, otherwise we add the new stmts immediately
    458    after the GIMPLE_COND and redirect.  */
    459 
    460 static void
    461 replace_goto_queue_cond_clause (tree *tp, struct leh_tf_state *tf,
    462 				gimple_stmt_iterator *gsi)
    463 {
    464   tree label;
    465   gimple_seq new_seq;
    466   treemple temp;
    467   location_t loc = gimple_location (gsi_stmt (*gsi));
    468 
    469   temp.tp = tp;
    470   new_seq = find_goto_replacement (tf, temp);
    471   if (!new_seq)
    472     return;
    473 
    474   if (gimple_seq_singleton_p (new_seq)
    475       && gimple_code (gimple_seq_first_stmt (new_seq)) == GIMPLE_GOTO)
    476     {
    477       *tp = gimple_goto_dest (gimple_seq_first_stmt (new_seq));
    478       return;
    479     }
    480 
    481   label = create_artificial_label (loc);
    482   /* Set the new label for the GIMPLE_COND */
    483   *tp = label;
    484 
    485   gsi_insert_after (gsi, gimple_build_label (label), GSI_CONTINUE_LINKING);
    486   gsi_insert_seq_after (gsi, gimple_seq_copy (new_seq), GSI_CONTINUE_LINKING);
    487 }
    488 
    489 /* The real work of replace_goto_queue.  Returns with TSI updated to
    490    point to the next statement.  */
    491 
    492 static void replace_goto_queue_stmt_list (gimple_seq *, struct leh_tf_state *);
    493 
    494 static void
    495 replace_goto_queue_1 (gimple *stmt, struct leh_tf_state *tf,
    496 		      gimple_stmt_iterator *gsi)
    497 {
    498   gimple_seq seq;
    499   treemple temp;
    500   temp.g = NULL;
    501 
    502   switch (gimple_code (stmt))
    503     {
    504     case GIMPLE_GOTO:
    505     case GIMPLE_RETURN:
    506       temp.g = stmt;
    507       seq = find_goto_replacement (tf, temp);
    508       if (seq)
    509 	{
    510 	  gimple_stmt_iterator i;
    511 	  seq = gimple_seq_copy (seq);
    512 	  for (i = gsi_start (seq); !gsi_end_p (i); gsi_next (&i))
    513 	    gimple_set_location (gsi_stmt (i), gimple_location (stmt));
    514 	  gsi_insert_seq_before (gsi, seq, GSI_SAME_STMT);
    515 	  gsi_remove (gsi, false);
    516 	  return;
    517 	}
    518       break;
    519 
    520     case GIMPLE_COND:
    521       replace_goto_queue_cond_clause (gimple_op_ptr (stmt, 2), tf, gsi);
    522       replace_goto_queue_cond_clause (gimple_op_ptr (stmt, 3), tf, gsi);
    523       break;
    524 
    525     case GIMPLE_TRY:
    526       replace_goto_queue_stmt_list (gimple_try_eval_ptr (stmt), tf);
    527       replace_goto_queue_stmt_list (gimple_try_cleanup_ptr (stmt), tf);
    528       break;
    529     case GIMPLE_CATCH:
    530       replace_goto_queue_stmt_list (gimple_catch_handler_ptr (
    531 				      as_a <gcatch *> (stmt)),
    532 				    tf);
    533       break;
    534     case GIMPLE_EH_FILTER:
    535       replace_goto_queue_stmt_list (gimple_eh_filter_failure_ptr (stmt), tf);
    536       break;
    537     case GIMPLE_EH_ELSE:
    538       {
    539 	geh_else *eh_else_stmt = as_a <geh_else *> (stmt);
    540 	replace_goto_queue_stmt_list (gimple_eh_else_n_body_ptr (eh_else_stmt),
    541 				      tf);
    542 	replace_goto_queue_stmt_list (gimple_eh_else_e_body_ptr (eh_else_stmt),
    543 				      tf);
    544       }
    545       break;
    546 
    547     default:
    548       /* These won't have gotos in them.  */
    549       break;
    550     }
    551 
    552   gsi_next (gsi);
    553 }
    554 
    555 /* A subroutine of replace_goto_queue.  Handles GIMPLE_SEQ.  */
    556 
    557 static void
    558 replace_goto_queue_stmt_list (gimple_seq *seq, struct leh_tf_state *tf)
    559 {
    560   gimple_stmt_iterator gsi = gsi_start (*seq);
    561 
    562   while (!gsi_end_p (gsi))
    563     replace_goto_queue_1 (gsi_stmt (gsi), tf, &gsi);
    564 }
    565 
    566 /* Replace all goto queue members.  */
    567 
    568 static void
    569 replace_goto_queue (struct leh_tf_state *tf)
    570 {
    571   if (tf->goto_queue_active == 0)
    572     return;
    573   replace_goto_queue_stmt_list (&tf->top_p_seq, tf);
    574   replace_goto_queue_stmt_list (&eh_seq, tf);
    575 }
    576 
    577 /* Add a new record to the goto queue contained in TF. NEW_STMT is the
    578    data to be added, IS_LABEL indicates whether NEW_STMT is a label or
    579    a gimple return. */
    580 
    581 static void
    582 record_in_goto_queue (struct leh_tf_state *tf,
    583                       treemple new_stmt,
    584                       int index,
    585                       bool is_label,
    586 		      location_t location)
    587 {
    588   size_t active, size;
    589   struct goto_queue_node *q;
    590 
    591   gcc_assert (!tf->goto_queue_map);
    592 
    593   active = tf->goto_queue_active;
    594   size = tf->goto_queue_size;
    595   if (active >= size)
    596     {
    597       size = (size ? size * 2 : 32);
    598       tf->goto_queue_size = size;
    599       tf->goto_queue
    600          = XRESIZEVEC (struct goto_queue_node, tf->goto_queue, size);
    601     }
    602 
    603   q = &tf->goto_queue[active];
    604   tf->goto_queue_active = active + 1;
    605 
    606   memset (q, 0, sizeof (*q));
    607   q->stmt = new_stmt;
    608   q->index = index;
    609   q->location = location;
    610   q->is_label = is_label;
    611 }
    612 
    613 /* Record the LABEL label in the goto queue contained in TF.
    614    TF is not null.  */
    615 
    616 static void
    617 record_in_goto_queue_label (struct leh_tf_state *tf, treemple stmt, tree label,
    618 			    location_t location)
    619 {
    620   int index;
    621   treemple temp, new_stmt;
    622 
    623   if (!label)
    624     return;
    625 
    626   /* Computed and non-local gotos do not get processed.  Given
    627      their nature we can neither tell whether we've escaped the
    628      finally block nor redirect them if we knew.  */
    629   if (TREE_CODE (label) != LABEL_DECL)
    630     return;
    631 
    632   /* No need to record gotos that don't leave the try block.  */
    633   temp.t = label;
    634   if (!outside_finally_tree (temp, tf->try_finally_expr))
    635     return;
    636 
    637   if (! tf->dest_array.exists ())
    638     {
    639       tf->dest_array.create (10);
    640       tf->dest_array.quick_push (label);
    641       index = 0;
    642     }
    643   else
    644     {
    645       int n = tf->dest_array.length ();
    646       for (index = 0; index < n; ++index)
    647         if (tf->dest_array[index] == label)
    648           break;
    649       if (index == n)
    650         tf->dest_array.safe_push (label);
    651     }
    652 
    653   /* In the case of a GOTO we want to record the destination label,
    654      since with a GIMPLE_COND we have an easy access to the then/else
    655      labels. */
    656   new_stmt = stmt;
    657   record_in_goto_queue (tf, new_stmt, index, true, location);
    658 }
    659 
    660 /* For any GIMPLE_GOTO or GIMPLE_RETURN, decide whether it leaves a try_finally
    661    node, and if so record that fact in the goto queue associated with that
    662    try_finally node.  */
    663 
    664 static void
    665 maybe_record_in_goto_queue (struct leh_state *state, gimple *stmt)
    666 {
    667   struct leh_tf_state *tf = state->tf;
    668   treemple new_stmt;
    669 
    670   if (!tf)
    671     return;
    672 
    673   switch (gimple_code (stmt))
    674     {
    675     case GIMPLE_COND:
    676       {
    677 	gcond *cond_stmt = as_a <gcond *> (stmt);
    678 	new_stmt.tp = gimple_op_ptr (cond_stmt, 2);
    679 	record_in_goto_queue_label (tf, new_stmt,
    680 				    gimple_cond_true_label (cond_stmt),
    681 				    EXPR_LOCATION (*new_stmt.tp));
    682 	new_stmt.tp = gimple_op_ptr (cond_stmt, 3);
    683 	record_in_goto_queue_label (tf, new_stmt,
    684 				    gimple_cond_false_label (cond_stmt),
    685 				    EXPR_LOCATION (*new_stmt.tp));
    686       }
    687       break;
    688     case GIMPLE_GOTO:
    689       new_stmt.g = stmt;
    690       record_in_goto_queue_label (tf, new_stmt, gimple_goto_dest (stmt),
    691 				  gimple_location (stmt));
    692       break;
    693 
    694     case GIMPLE_RETURN:
    695       tf->may_return = true;
    696       new_stmt.g = stmt;
    697       record_in_goto_queue (tf, new_stmt, -1, false, gimple_location (stmt));
    698       break;
    699 
    700     default:
    701       gcc_unreachable ();
    702     }
    703 }
    704 
    705 
    706 #if CHECKING_P
    707 /* We do not process GIMPLE_SWITCHes for now.  As long as the original source
    708    was in fact structured, and we've not yet done jump threading, then none
    709    of the labels will leave outer GIMPLE_TRY_FINALLY nodes. Verify this.  */
    710 
    711 static void
    712 verify_norecord_switch_expr (struct leh_state *state,
    713 			     gswitch *switch_expr)
    714 {
    715   struct leh_tf_state *tf = state->tf;
    716   size_t i, n;
    717 
    718   if (!tf)
    719     return;
    720 
    721   n = gimple_switch_num_labels (switch_expr);
    722 
    723   for (i = 0; i < n; ++i)
    724     {
    725       treemple temp;
    726       tree lab = CASE_LABEL (gimple_switch_label (switch_expr, i));
    727       temp.t = lab;
    728       gcc_assert (!outside_finally_tree (temp, tf->try_finally_expr));
    729     }
    730 }
    731 #else
    732 #define verify_norecord_switch_expr(state, switch_expr)
    733 #endif
    734 
    735 /* Redirect a RETURN_EXPR pointed to by Q to FINLAB.  If MOD is
    736    non-null, insert it before the new branch.  */
    737 
    738 static void
    739 do_return_redirection (struct goto_queue_node *q, tree finlab, gimple_seq mod)
    740 {
    741   gimple *x;
    742 
    743   /* In the case of a return, the queue node must be a gimple statement.  */
    744   gcc_assert (!q->is_label);
    745 
    746   /* Note that the return value may have already been computed, e.g.,
    747 
    748 	int x;
    749 	int foo (void)
    750 	{
    751 	  x = 0;
    752 	  try {
    753 	    return x;
    754 	  } finally {
    755 	    x++;
    756 	  }
    757 	}
    758 
    759      should return 0, not 1.  We don't have to do anything to make
    760      this happens because the return value has been placed in the
    761      RESULT_DECL already.  */
    762 
    763   q->cont_stmt = q->stmt.g;
    764 
    765   if (mod)
    766     gimple_seq_add_seq (&q->repl_stmt, mod);
    767 
    768   x = gimple_build_goto (finlab);
    769   gimple_set_location (x, q->location);
    770   gimple_seq_add_stmt (&q->repl_stmt, x);
    771 }
    772 
    773 /* Similar, but easier, for GIMPLE_GOTO.  */
    774 
    775 static void
    776 do_goto_redirection (struct goto_queue_node *q, tree finlab, gimple_seq mod,
    777 		     struct leh_tf_state *tf)
    778 {
    779   ggoto *x;
    780 
    781   gcc_assert (q->is_label);
    782 
    783   q->cont_stmt = gimple_build_goto (tf->dest_array[q->index]);
    784 
    785   if (mod)
    786     gimple_seq_add_seq (&q->repl_stmt, mod);
    787 
    788   x = gimple_build_goto (finlab);
    789   gimple_set_location (x, q->location);
    790   gimple_seq_add_stmt (&q->repl_stmt, x);
    791 }
    792 
    793 /* Emit a standard landing pad sequence into SEQ for REGION.  */
    794 
    795 static void
    796 emit_post_landing_pad (gimple_seq *seq, eh_region region)
    797 {
    798   eh_landing_pad lp = region->landing_pads;
    799   glabel *x;
    800 
    801   if (lp == NULL)
    802     lp = gen_eh_landing_pad (region);
    803 
    804   lp->post_landing_pad = create_artificial_label (UNKNOWN_LOCATION);
    805   EH_LANDING_PAD_NR (lp->post_landing_pad) = lp->index;
    806 
    807   x = gimple_build_label (lp->post_landing_pad);
    808   gimple_seq_add_stmt (seq, x);
    809 }
    810 
    811 /* Emit a RESX statement into SEQ for REGION.  */
    812 
    813 static void
    814 emit_resx (gimple_seq *seq, eh_region region)
    815 {
    816   gresx *x = gimple_build_resx (region->index);
    817   gimple_seq_add_stmt (seq, x);
    818   if (region->outer)
    819     record_stmt_eh_region (region->outer, x);
    820 }
    821 
    822 /* Note that the current EH region may contain a throw, or a
    823    call to a function which itself may contain a throw.  */
    824 
    825 static void
    826 note_eh_region_may_contain_throw (eh_region region)
    827 {
    828   while (bitmap_set_bit (eh_region_may_contain_throw_map, region->index))
    829     {
    830       if (region->type == ERT_MUST_NOT_THROW)
    831 	break;
    832       region = region->outer;
    833       if (region == NULL)
    834 	break;
    835     }
    836 }
    837 
    838 /* Check if REGION has been marked as containing a throw.  If REGION is
    839    NULL, this predicate is false.  */
    840 
    841 static inline bool
    842 eh_region_may_contain_throw (eh_region r)
    843 {
    844   return r && bitmap_bit_p (eh_region_may_contain_throw_map, r->index);
    845 }
    846 
    847 /* We want to transform
    848 	try { body; } catch { stuff; }
    849    to
    850 	normal_sequence:
    851 	  body;
    852 	  over:
    853 	eh_sequence:
    854 	  landing_pad:
    855 	  stuff;
    856 	  goto over;
    857 
    858    TP is a GIMPLE_TRY node.  REGION is the region whose post_landing_pad
    859    should be placed before the second operand, or NULL.  OVER is
    860    an existing label that should be put at the exit, or NULL.  */
    861 
    862 static gimple_seq
    863 frob_into_branch_around (gtry *tp, eh_region region, tree over)
    864 {
    865   gimple *x;
    866   gimple_seq cleanup, result;
    867   location_t loc = gimple_location (tp);
    868 
    869   cleanup = gimple_try_cleanup (tp);
    870   result = gimple_try_eval (tp);
    871 
    872   if (region)
    873     emit_post_landing_pad (&eh_seq, region);
    874 
    875   if (gimple_seq_may_fallthru (cleanup))
    876     {
    877       if (!over)
    878 	over = create_artificial_label (loc);
    879       x = gimple_build_goto (over);
    880       gimple_set_location (x, loc);
    881       gimple_seq_add_stmt (&cleanup, x);
    882     }
    883   gimple_seq_add_seq (&eh_seq, cleanup);
    884 
    885   if (over)
    886     {
    887       x = gimple_build_label (over);
    888       gimple_seq_add_stmt (&result, x);
    889     }
    890   return result;
    891 }
    892 
    893 /* A subroutine of lower_try_finally.  Duplicate the tree rooted at T.
    894    Make sure to record all new labels found.  */
    895 
    896 static gimple_seq
    897 lower_try_finally_dup_block (gimple_seq seq, struct leh_state *outer_state,
    898 			     location_t loc)
    899 {
    900   gtry *region = NULL;
    901   gimple_seq new_seq;
    902   gimple_stmt_iterator gsi;
    903 
    904   new_seq = copy_gimple_seq_and_replace_locals (seq);
    905 
    906   for (gsi = gsi_start (new_seq); !gsi_end_p (gsi); gsi_next (&gsi))
    907     {
    908       gimple *stmt = gsi_stmt (gsi);
    909       if (LOCATION_LOCUS (gimple_location (stmt)) == UNKNOWN_LOCATION)
    910 	{
    911 	  tree block = gimple_block (stmt);
    912 	  gimple_set_location (stmt, loc);
    913 	  gimple_set_block (stmt, block);
    914 	}
    915     }
    916 
    917   if (outer_state->tf)
    918     region = outer_state->tf->try_finally_expr;
    919   collect_finally_tree_1 (new_seq, region);
    920 
    921   return new_seq;
    922 }
    923 
    924 /* A subroutine of lower_try_finally.  Create a fallthru label for
    925    the given try_finally state.  The only tricky bit here is that
    926    we have to make sure to record the label in our outer context.  */
    927 
    928 static tree
    929 lower_try_finally_fallthru_label (struct leh_tf_state *tf)
    930 {
    931   tree label = tf->fallthru_label;
    932   treemple temp;
    933 
    934   if (!label)
    935     {
    936       label = create_artificial_label (gimple_location (tf->try_finally_expr));
    937       tf->fallthru_label = label;
    938       if (tf->outer->tf)
    939         {
    940           temp.t = label;
    941           record_in_finally_tree (temp, tf->outer->tf->try_finally_expr);
    942         }
    943     }
    944   return label;
    945 }
    946 
    947 /* A subroutine of lower_try_finally.  If FINALLY consits of a
    948    GIMPLE_EH_ELSE node, return it.  */
    949 
    950 static inline geh_else *
    951 get_eh_else (gimple_seq finally)
    952 {
    953   gimple *x = gimple_seq_first_stmt (finally);
    954   if (x && gimple_code (x) == GIMPLE_EH_ELSE)
    955     {
    956       gcc_assert (gimple_seq_singleton_p (finally));
    957       return as_a <geh_else *> (x);
    958     }
    959   return NULL;
    960 }
    961 
    962 /* A subroutine of lower_try_finally.  If the eh_protect_cleanup_actions
    963    langhook returns non-null, then the language requires that the exception
    964    path out of a try_finally be treated specially.  To wit: the code within
    965    the finally block may not itself throw an exception.  We have two choices
    966    here. First we can duplicate the finally block and wrap it in a
    967    must_not_throw region.  Second, we can generate code like
    968 
    969 	try {
    970 	  finally_block;
    971 	} catch {
    972 	  if (fintmp == eh_edge)
    973 	    protect_cleanup_actions;
    974 	}
    975 
    976    where "fintmp" is the temporary used in the switch statement generation
    977    alternative considered below.  For the nonce, we always choose the first
    978    option.
    979 
    980    THIS_STATE may be null if this is a try-cleanup, not a try-finally.  */
    981 
    982 static void
    983 honor_protect_cleanup_actions (struct leh_state *outer_state,
    984 			       struct leh_state *this_state,
    985 			       struct leh_tf_state *tf)
    986 {
    987   gimple_seq finally = gimple_try_cleanup (tf->top_p);
    988 
    989   /* EH_ELSE doesn't come from user code; only compiler generated stuff.
    990      It does need to be handled here, so as to separate the (different)
    991      EH path from the normal path.  But we should not attempt to wrap
    992      it with a must-not-throw node (which indeed gets in the way).  */
    993   if (geh_else *eh_else = get_eh_else (finally))
    994     {
    995       gimple_try_set_cleanup (tf->top_p, gimple_eh_else_n_body (eh_else));
    996       finally = gimple_eh_else_e_body (eh_else);
    997 
    998       /* Let the ELSE see the exception that's being processed, but
    999 	 since the cleanup is outside the try block, process it with
   1000 	 outer_state, otherwise it may be used as a cleanup for
   1001 	 itself, and Bad Things (TM) ensue.  */
   1002       eh_region save_ehp = outer_state->ehp_region;
   1003       outer_state->ehp_region = this_state->cur_region;
   1004       lower_eh_constructs_1 (outer_state, &finally);
   1005       outer_state->ehp_region = save_ehp;
   1006     }
   1007   else
   1008     {
   1009       /* First check for nothing to do.  */
   1010       if (lang_hooks.eh_protect_cleanup_actions == NULL)
   1011 	return;
   1012       tree actions = lang_hooks.eh_protect_cleanup_actions ();
   1013       if (actions == NULL)
   1014 	return;
   1015 
   1016       if (this_state)
   1017 	finally = lower_try_finally_dup_block (finally, outer_state,
   1018 	  gimple_location (tf->try_finally_expr));
   1019 
   1020       /* If this cleanup consists of a TRY_CATCH_EXPR with TRY_CATCH_IS_CLEANUP
   1021 	 set, the handler of the TRY_CATCH_EXPR is another cleanup which ought
   1022 	 to be in an enclosing scope, but needs to be implemented at this level
   1023 	 to avoid a nesting violation (see wrap_temporary_cleanups in
   1024 	 cp/decl.cc).  Since it's logically at an outer level, we should call
   1025 	 terminate before we get to it, so strip it away before adding the
   1026 	 MUST_NOT_THROW filter.  */
   1027       gimple_stmt_iterator gsi = gsi_start (finally);
   1028       gimple *x = !gsi_end_p (gsi) ? gsi_stmt (gsi) : NULL;
   1029       if (x
   1030 	  && gimple_code (x) == GIMPLE_TRY
   1031 	  && gimple_try_kind (x) == GIMPLE_TRY_CATCH
   1032 	  && gimple_try_catch_is_cleanup (x))
   1033 	{
   1034 	  gsi_insert_seq_before (&gsi, gimple_try_eval (x), GSI_SAME_STMT);
   1035 	  gsi_remove (&gsi, false);
   1036 	}
   1037 
   1038       /* Wrap the block with protect_cleanup_actions as the action.  */
   1039       geh_mnt *eh_mnt = gimple_build_eh_must_not_throw (actions);
   1040       gtry *try_stmt = gimple_build_try (finally,
   1041 					 gimple_seq_alloc_with_stmt (eh_mnt),
   1042 					 GIMPLE_TRY_CATCH);
   1043       finally = lower_eh_must_not_throw (outer_state, try_stmt);
   1044     }
   1045 
   1046   /* Drop all of this into the exception sequence.  */
   1047   emit_post_landing_pad (&eh_seq, tf->region);
   1048   gimple_seq_add_seq (&eh_seq, finally);
   1049   if (gimple_seq_may_fallthru (finally))
   1050     emit_resx (&eh_seq, tf->region);
   1051 
   1052   /* Having now been handled, EH isn't to be considered with
   1053      the rest of the outgoing edges.  */
   1054   tf->may_throw = false;
   1055 }
   1056 
   1057 /* A subroutine of lower_try_finally.  We have determined that there is
   1058    no fallthru edge out of the finally block.  This means that there is
   1059    no outgoing edge corresponding to any incoming edge.  Restructure the
   1060    try_finally node for this special case.  */
   1061 
   1062 static void
   1063 lower_try_finally_nofallthru (struct leh_state *state,
   1064 			      struct leh_tf_state *tf)
   1065 {
   1066   tree lab;
   1067   gimple *x;
   1068   geh_else *eh_else;
   1069   gimple_seq finally;
   1070   struct goto_queue_node *q, *qe;
   1071 
   1072   lab = create_artificial_label (gimple_location (tf->try_finally_expr));
   1073 
   1074   /* We expect that tf->top_p is a GIMPLE_TRY. */
   1075   finally = gimple_try_cleanup (tf->top_p);
   1076   tf->top_p_seq = gimple_try_eval (tf->top_p);
   1077 
   1078   x = gimple_build_label (lab);
   1079   gimple_seq_add_stmt (&tf->top_p_seq, x);
   1080 
   1081   q = tf->goto_queue;
   1082   qe = q + tf->goto_queue_active;
   1083   for (; q < qe; ++q)
   1084     if (q->index < 0)
   1085       do_return_redirection (q, lab, NULL);
   1086     else
   1087       do_goto_redirection (q, lab, NULL, tf);
   1088 
   1089   replace_goto_queue (tf);
   1090 
   1091   /* Emit the finally block into the stream.  Lower EH_ELSE at this time.  */
   1092   eh_else = get_eh_else (finally);
   1093   if (eh_else)
   1094     {
   1095       finally = gimple_eh_else_n_body (eh_else);
   1096       lower_eh_constructs_1 (state, &finally);
   1097       gimple_seq_add_seq (&tf->top_p_seq, finally);
   1098 
   1099       if (tf->may_throw)
   1100 	{
   1101 	  finally = gimple_eh_else_e_body (eh_else);
   1102 	  lower_eh_constructs_1 (state, &finally);
   1103 
   1104 	  emit_post_landing_pad (&eh_seq, tf->region);
   1105 	  gimple_seq_add_seq (&eh_seq, finally);
   1106 	}
   1107     }
   1108   else
   1109     {
   1110       lower_eh_constructs_1 (state, &finally);
   1111       gimple_seq_add_seq (&tf->top_p_seq, finally);
   1112 
   1113       if (tf->may_throw)
   1114 	{
   1115 	  emit_post_landing_pad (&eh_seq, tf->region);
   1116 
   1117 	  x = gimple_build_goto (lab);
   1118 	  gimple_set_location (x, gimple_location (tf->try_finally_expr));
   1119 	  gimple_seq_add_stmt (&eh_seq, x);
   1120 	}
   1121     }
   1122 }
   1123 
   1124 /* A subroutine of lower_try_finally.  We have determined that there is
   1125    exactly one destination of the finally block.  Restructure the
   1126    try_finally node for this special case.  */
   1127 
   1128 static void
   1129 lower_try_finally_onedest (struct leh_state *state, struct leh_tf_state *tf)
   1130 {
   1131   struct goto_queue_node *q, *qe;
   1132   geh_else *eh_else;
   1133   glabel *label_stmt;
   1134   gimple *x;
   1135   gimple_seq finally;
   1136   gimple_stmt_iterator gsi;
   1137   tree finally_label;
   1138   location_t loc = gimple_location (tf->try_finally_expr);
   1139 
   1140   finally = gimple_try_cleanup (tf->top_p);
   1141   tf->top_p_seq = gimple_try_eval (tf->top_p);
   1142 
   1143   /* Since there's only one destination, and the destination edge can only
   1144      either be EH or non-EH, that implies that all of our incoming edges
   1145      are of the same type.  Therefore we can lower EH_ELSE immediately.  */
   1146   eh_else = get_eh_else (finally);
   1147   if (eh_else)
   1148     {
   1149       if (tf->may_throw)
   1150 	finally = gimple_eh_else_e_body (eh_else);
   1151       else
   1152 	finally = gimple_eh_else_n_body (eh_else);
   1153     }
   1154 
   1155   lower_eh_constructs_1 (state, &finally);
   1156 
   1157   for (gsi = gsi_start (finally); !gsi_end_p (gsi); gsi_next (&gsi))
   1158     {
   1159       gimple *stmt = gsi_stmt (gsi);
   1160       if (LOCATION_LOCUS (gimple_location (stmt)) == UNKNOWN_LOCATION)
   1161 	{
   1162 	  tree block = gimple_block (stmt);
   1163 	  gimple_set_location (stmt, gimple_location (tf->try_finally_expr));
   1164 	  gimple_set_block (stmt, block);
   1165 	}
   1166     }
   1167 
   1168   if (tf->may_throw)
   1169     {
   1170       /* Only reachable via the exception edge.  Add the given label to
   1171          the head of the FINALLY block.  Append a RESX at the end.  */
   1172       emit_post_landing_pad (&eh_seq, tf->region);
   1173       gimple_seq_add_seq (&eh_seq, finally);
   1174       emit_resx (&eh_seq, tf->region);
   1175       return;
   1176     }
   1177 
   1178   if (tf->may_fallthru)
   1179     {
   1180       /* Only reachable via the fallthru edge.  Do nothing but let
   1181 	 the two blocks run together; we'll fall out the bottom.  */
   1182       gimple_seq_add_seq (&tf->top_p_seq, finally);
   1183       return;
   1184     }
   1185 
   1186   finally_label = create_artificial_label (loc);
   1187   label_stmt = gimple_build_label (finally_label);
   1188   gimple_seq_add_stmt (&tf->top_p_seq, label_stmt);
   1189 
   1190   gimple_seq_add_seq (&tf->top_p_seq, finally);
   1191 
   1192   q = tf->goto_queue;
   1193   qe = q + tf->goto_queue_active;
   1194 
   1195   if (tf->may_return)
   1196     {
   1197       /* Reachable by return expressions only.  Redirect them.  */
   1198       for (; q < qe; ++q)
   1199 	do_return_redirection (q, finally_label, NULL);
   1200       replace_goto_queue (tf);
   1201     }
   1202   else
   1203     {
   1204       /* Reachable by goto expressions only.  Redirect them.  */
   1205       for (; q < qe; ++q)
   1206 	do_goto_redirection (q, finally_label, NULL, tf);
   1207       replace_goto_queue (tf);
   1208 
   1209       if (tf->dest_array[0] == tf->fallthru_label)
   1210 	{
   1211 	  /* Reachable by goto to fallthru label only.  Redirect it
   1212 	     to the new label (already created, sadly), and do not
   1213 	     emit the final branch out, or the fallthru label.  */
   1214 	  tf->fallthru_label = NULL;
   1215 	  return;
   1216 	}
   1217     }
   1218 
   1219   /* Place the original return/goto to the original destination
   1220      immediately after the finally block. */
   1221   x = tf->goto_queue[0].cont_stmt;
   1222   gimple_seq_add_stmt (&tf->top_p_seq, x);
   1223   maybe_record_in_goto_queue (state, x);
   1224 }
   1225 
   1226 /* A subroutine of lower_try_finally.  There are multiple edges incoming
   1227    and outgoing from the finally block.  Implement this by duplicating the
   1228    finally block for every destination.  */
   1229 
   1230 static void
   1231 lower_try_finally_copy (struct leh_state *state, struct leh_tf_state *tf)
   1232 {
   1233   gimple_seq finally;
   1234   gimple_seq new_stmt;
   1235   gimple_seq seq;
   1236   gimple *x;
   1237   geh_else *eh_else;
   1238   tree tmp;
   1239   location_t tf_loc = gimple_location (tf->try_finally_expr);
   1240 
   1241   finally = gimple_try_cleanup (tf->top_p);
   1242 
   1243   /* Notice EH_ELSE, and simplify some of the remaining code
   1244      by considering FINALLY to be the normal return path only.  */
   1245   eh_else = get_eh_else (finally);
   1246   if (eh_else)
   1247     finally = gimple_eh_else_n_body (eh_else);
   1248 
   1249   tf->top_p_seq = gimple_try_eval (tf->top_p);
   1250   new_stmt = NULL;
   1251 
   1252   if (tf->may_fallthru)
   1253     {
   1254       seq = lower_try_finally_dup_block (finally, state, tf_loc);
   1255       lower_eh_constructs_1 (state, &seq);
   1256       gimple_seq_add_seq (&new_stmt, seq);
   1257 
   1258       tmp = lower_try_finally_fallthru_label (tf);
   1259       x = gimple_build_goto (tmp);
   1260       gimple_set_location (x, tf_loc);
   1261       gimple_seq_add_stmt (&new_stmt, x);
   1262     }
   1263 
   1264   if (tf->may_throw)
   1265     {
   1266       /* We don't need to copy the EH path of EH_ELSE,
   1267 	 since it is only emitted once.  */
   1268       if (eh_else)
   1269 	seq = gimple_eh_else_e_body (eh_else);
   1270       else
   1271 	seq = lower_try_finally_dup_block (finally, state, tf_loc);
   1272       lower_eh_constructs_1 (state, &seq);
   1273 
   1274       emit_post_landing_pad (&eh_seq, tf->region);
   1275       gimple_seq_add_seq (&eh_seq, seq);
   1276       emit_resx (&eh_seq, tf->region);
   1277     }
   1278 
   1279   if (tf->goto_queue)
   1280     {
   1281       struct goto_queue_node *q, *qe;
   1282       int return_index, index;
   1283       struct labels_s
   1284       {
   1285 	struct goto_queue_node *q;
   1286 	tree label;
   1287       } *labels;
   1288 
   1289       return_index = tf->dest_array.length ();
   1290       labels = XCNEWVEC (struct labels_s, return_index + 1);
   1291 
   1292       q = tf->goto_queue;
   1293       qe = q + tf->goto_queue_active;
   1294       for (; q < qe; q++)
   1295 	{
   1296 	  index = q->index < 0 ? return_index : q->index;
   1297 
   1298 	  if (!labels[index].q)
   1299 	    labels[index].q = q;
   1300 	}
   1301 
   1302       for (index = 0; index < return_index + 1; index++)
   1303 	{
   1304 	  tree lab;
   1305 
   1306 	  q = labels[index].q;
   1307 	  if (! q)
   1308 	    continue;
   1309 
   1310 	  lab = labels[index].label
   1311 	    = create_artificial_label (tf_loc);
   1312 
   1313 	  if (index == return_index)
   1314 	    do_return_redirection (q, lab, NULL);
   1315 	  else
   1316 	    do_goto_redirection (q, lab, NULL, tf);
   1317 
   1318 	  x = gimple_build_label (lab);
   1319           gimple_seq_add_stmt (&new_stmt, x);
   1320 
   1321 	  seq = lower_try_finally_dup_block (finally, state, q->location);
   1322 	  lower_eh_constructs_1 (state, &seq);
   1323           gimple_seq_add_seq (&new_stmt, seq);
   1324 
   1325           gimple_seq_add_stmt (&new_stmt, q->cont_stmt);
   1326 	  maybe_record_in_goto_queue (state, q->cont_stmt);
   1327 	}
   1328 
   1329       for (q = tf->goto_queue; q < qe; q++)
   1330 	{
   1331 	  tree lab;
   1332 
   1333 	  index = q->index < 0 ? return_index : q->index;
   1334 
   1335 	  if (labels[index].q == q)
   1336 	    continue;
   1337 
   1338 	  lab = labels[index].label;
   1339 
   1340 	  if (index == return_index)
   1341 	    do_return_redirection (q, lab, NULL);
   1342 	  else
   1343 	    do_goto_redirection (q, lab, NULL, tf);
   1344 	}
   1345 
   1346       replace_goto_queue (tf);
   1347       free (labels);
   1348     }
   1349 
   1350   /* Need to link new stmts after running replace_goto_queue due
   1351      to not wanting to process the same goto stmts twice.  */
   1352   gimple_seq_add_seq (&tf->top_p_seq, new_stmt);
   1353 }
   1354 
   1355 /* A subroutine of lower_try_finally.  There are multiple edges incoming
   1356    and outgoing from the finally block.  Implement this by instrumenting
   1357    each incoming edge and creating a switch statement at the end of the
   1358    finally block that branches to the appropriate destination.  */
   1359 
   1360 static void
   1361 lower_try_finally_switch (struct leh_state *state, struct leh_tf_state *tf)
   1362 {
   1363   struct goto_queue_node *q, *qe;
   1364   tree finally_tmp, finally_label;
   1365   int return_index, eh_index, fallthru_index;
   1366   int nlabels, ndests, j, last_case_index;
   1367   tree last_case;
   1368   auto_vec<tree> case_label_vec;
   1369   gimple_seq switch_body = NULL;
   1370   gimple *x;
   1371   geh_else *eh_else;
   1372   tree tmp;
   1373   gimple *switch_stmt;
   1374   gimple_seq finally;
   1375   hash_map<tree, gimple *> *cont_map = NULL;
   1376   /* The location of the TRY_FINALLY stmt.  */
   1377   location_t tf_loc = gimple_location (tf->try_finally_expr);
   1378   /* The location of the finally block.  */
   1379   location_t finally_loc;
   1380 
   1381   finally = gimple_try_cleanup (tf->top_p);
   1382   eh_else = get_eh_else (finally);
   1383 
   1384   /* Mash the TRY block to the head of the chain.  */
   1385   tf->top_p_seq = gimple_try_eval (tf->top_p);
   1386 
   1387   /* The location of the finally is either the last stmt in the finally
   1388      block or the location of the TRY_FINALLY itself.  */
   1389   x = gimple_seq_last_stmt (finally);
   1390   finally_loc = x ? gimple_location (x) : tf_loc;
   1391 
   1392   /* Prepare for switch statement generation.  */
   1393   nlabels = tf->dest_array.length ();
   1394   return_index = nlabels;
   1395   eh_index = return_index + tf->may_return;
   1396   fallthru_index = eh_index + (tf->may_throw && !eh_else);
   1397   ndests = fallthru_index + tf->may_fallthru;
   1398 
   1399   finally_tmp = create_tmp_var (integer_type_node, "finally_tmp");
   1400   finally_label = create_artificial_label (finally_loc);
   1401 
   1402   /* We use vec::quick_push on case_label_vec throughout this function,
   1403      since we know the size in advance and allocate precisely as muce
   1404      space as needed.  */
   1405   case_label_vec.create (ndests);
   1406   last_case = NULL;
   1407   last_case_index = 0;
   1408 
   1409   /* Begin inserting code for getting to the finally block.  Things
   1410      are done in this order to correspond to the sequence the code is
   1411      laid out.  */
   1412 
   1413   if (tf->may_fallthru)
   1414     {
   1415       x = gimple_build_assign (finally_tmp,
   1416 			       build_int_cst (integer_type_node,
   1417 					      fallthru_index));
   1418       gimple_set_location (x, finally_loc);
   1419       gimple_seq_add_stmt (&tf->top_p_seq, x);
   1420 
   1421       tmp = build_int_cst (integer_type_node, fallthru_index);
   1422       last_case = build_case_label (tmp, NULL,
   1423 				    create_artificial_label (finally_loc));
   1424       case_label_vec.quick_push (last_case);
   1425       last_case_index++;
   1426 
   1427       x = gimple_build_label (CASE_LABEL (last_case));
   1428       gimple_seq_add_stmt (&switch_body, x);
   1429 
   1430       tmp = lower_try_finally_fallthru_label (tf);
   1431       x = gimple_build_goto (tmp);
   1432       gimple_set_location (x, finally_loc);
   1433       gimple_seq_add_stmt (&switch_body, x);
   1434     }
   1435 
   1436   /* For EH_ELSE, emit the exception path (plus resx) now, then
   1437      subsequently we only need consider the normal path.  */
   1438   if (eh_else)
   1439     {
   1440       if (tf->may_throw)
   1441 	{
   1442 	  finally = gimple_eh_else_e_body (eh_else);
   1443 	  lower_eh_constructs_1 (state, &finally);
   1444 
   1445 	  emit_post_landing_pad (&eh_seq, tf->region);
   1446 	  gimple_seq_add_seq (&eh_seq, finally);
   1447 	  emit_resx (&eh_seq, tf->region);
   1448 	}
   1449 
   1450       finally = gimple_eh_else_n_body (eh_else);
   1451     }
   1452   else if (tf->may_throw)
   1453     {
   1454       emit_post_landing_pad (&eh_seq, tf->region);
   1455 
   1456       x = gimple_build_assign (finally_tmp,
   1457 			       build_int_cst (integer_type_node, eh_index));
   1458       gimple_seq_add_stmt (&eh_seq, x);
   1459 
   1460       x = gimple_build_goto (finally_label);
   1461       gimple_set_location (x, tf_loc);
   1462       gimple_seq_add_stmt (&eh_seq, x);
   1463 
   1464       tmp = build_int_cst (integer_type_node, eh_index);
   1465       last_case = build_case_label (tmp, NULL,
   1466 				    create_artificial_label (tf_loc));
   1467       case_label_vec.quick_push (last_case);
   1468       last_case_index++;
   1469 
   1470       x = gimple_build_label (CASE_LABEL (last_case));
   1471       gimple_seq_add_stmt (&eh_seq, x);
   1472       emit_resx (&eh_seq, tf->region);
   1473     }
   1474 
   1475   x = gimple_build_label (finally_label);
   1476   gimple_seq_add_stmt (&tf->top_p_seq, x);
   1477 
   1478   lower_eh_constructs_1 (state, &finally);
   1479   gimple_seq_add_seq (&tf->top_p_seq, finally);
   1480 
   1481   /* Redirect each incoming goto edge.  */
   1482   q = tf->goto_queue;
   1483   qe = q + tf->goto_queue_active;
   1484   j = last_case_index + tf->may_return;
   1485   /* Prepare the assignments to finally_tmp that are executed upon the
   1486      entrance through a particular edge. */
   1487   for (; q < qe; ++q)
   1488     {
   1489       gimple_seq mod = NULL;
   1490       int switch_id;
   1491       unsigned int case_index;
   1492 
   1493       if (q->index < 0)
   1494 	{
   1495 	  x = gimple_build_assign (finally_tmp,
   1496 				   build_int_cst (integer_type_node,
   1497 						  return_index));
   1498 	  gimple_seq_add_stmt (&mod, x);
   1499 	  do_return_redirection (q, finally_label, mod);
   1500 	  switch_id = return_index;
   1501 	}
   1502       else
   1503 	{
   1504 	  x = gimple_build_assign (finally_tmp,
   1505 				   build_int_cst (integer_type_node, q->index));
   1506 	  gimple_seq_add_stmt (&mod, x);
   1507 	  do_goto_redirection (q, finally_label, mod, tf);
   1508 	  switch_id = q->index;
   1509 	}
   1510 
   1511       case_index = j + q->index;
   1512       if (case_label_vec.length () <= case_index || !case_label_vec[case_index])
   1513         {
   1514           tree case_lab;
   1515 	  tmp = build_int_cst (integer_type_node, switch_id);
   1516           case_lab = build_case_label (tmp, NULL,
   1517 				       create_artificial_label (tf_loc));
   1518           /* We store the cont_stmt in the pointer map, so that we can recover
   1519              it in the loop below.  */
   1520           if (!cont_map)
   1521 	    cont_map = new hash_map<tree, gimple *>;
   1522           cont_map->put (case_lab, q->cont_stmt);
   1523           case_label_vec.quick_push (case_lab);
   1524         }
   1525     }
   1526   for (j = last_case_index; j < last_case_index + nlabels; j++)
   1527     {
   1528       gimple *cont_stmt;
   1529 
   1530       last_case = case_label_vec[j];
   1531 
   1532       gcc_assert (last_case);
   1533       gcc_assert (cont_map);
   1534 
   1535       cont_stmt = *cont_map->get (last_case);
   1536 
   1537       x = gimple_build_label (CASE_LABEL (last_case));
   1538       gimple_seq_add_stmt (&switch_body, x);
   1539       gimple_seq_add_stmt (&switch_body, cont_stmt);
   1540       maybe_record_in_goto_queue (state, cont_stmt);
   1541     }
   1542   if (cont_map)
   1543     delete cont_map;
   1544 
   1545   replace_goto_queue (tf);
   1546 
   1547   /* Make sure that the last case is the default label, as one is required.
   1548      Then sort the labels, which is also required in GIMPLE.  */
   1549   CASE_LOW (last_case) = NULL;
   1550   tree tem = case_label_vec.pop ();
   1551   gcc_assert (tem == last_case);
   1552   sort_case_labels (case_label_vec);
   1553 
   1554   /* Build the switch statement, setting last_case to be the default
   1555      label.  */
   1556   switch_stmt = gimple_build_switch (finally_tmp, last_case,
   1557 				     case_label_vec);
   1558   gimple_set_location (switch_stmt, finally_loc);
   1559 
   1560   /* Need to link SWITCH_STMT after running replace_goto_queue
   1561      due to not wanting to process the same goto stmts twice.  */
   1562   gimple_seq_add_stmt (&tf->top_p_seq, switch_stmt);
   1563   gimple_seq_add_seq (&tf->top_p_seq, switch_body);
   1564 }
   1565 
   1566 /* Decide whether or not we are going to duplicate the finally block.
   1567    There are several considerations.
   1568 
   1569    Second, we'd like to prevent egregious code growth.  One way to
   1570    do this is to estimate the size of the finally block, multiply
   1571    that by the number of copies we'd need to make, and compare against
   1572    the estimate of the size of the switch machinery we'd have to add.  */
   1573 
   1574 static bool
   1575 decide_copy_try_finally (int ndests, bool may_throw, gimple_seq finally)
   1576 {
   1577   int f_estimate, sw_estimate;
   1578   geh_else *eh_else;
   1579 
   1580   /* If there's an EH_ELSE involved, the exception path is separate
   1581      and really doesn't come into play for this computation.  */
   1582   eh_else = get_eh_else (finally);
   1583   if (eh_else)
   1584     {
   1585       ndests -= may_throw;
   1586       finally = gimple_eh_else_n_body (eh_else);
   1587     }
   1588 
   1589   if (!optimize)
   1590     {
   1591       gimple_stmt_iterator gsi;
   1592 
   1593       if (ndests == 1)
   1594         return true;
   1595 
   1596       for (gsi = gsi_start (finally); !gsi_end_p (gsi); gsi_next (&gsi))
   1597 	{
   1598 	  /* Duplicate __builtin_stack_restore in the hope of eliminating it
   1599 	     on the EH paths and, consequently, useless cleanups.  */
   1600 	  gimple *stmt = gsi_stmt (gsi);
   1601 	  if (!is_gimple_debug (stmt)
   1602 	      && !gimple_clobber_p (stmt)
   1603 	      && !gimple_call_builtin_p (stmt, BUILT_IN_STACK_RESTORE))
   1604 	    return false;
   1605 	}
   1606       return true;
   1607     }
   1608 
   1609   /* Finally estimate N times, plus N gotos.  */
   1610   f_estimate = estimate_num_insns_seq (finally, &eni_size_weights);
   1611   f_estimate = (f_estimate + 1) * ndests;
   1612 
   1613   /* Switch statement (cost 10), N variable assignments, N gotos.  */
   1614   sw_estimate = 10 + 2 * ndests;
   1615 
   1616   /* Optimize for size clearly wants our best guess.  */
   1617   if (optimize_function_for_size_p (cfun))
   1618     return f_estimate < sw_estimate;
   1619 
   1620   /* ??? These numbers are completely made up so far.  */
   1621   if (optimize > 1)
   1622     return f_estimate < 100 || f_estimate < sw_estimate * 2;
   1623   else
   1624     return f_estimate < 40 || f_estimate * 2 < sw_estimate * 3;
   1625 }
   1626 
   1627 /* REG is current region of a LEH state.
   1628    is the enclosing region for a possible cleanup region, or the region
   1629    itself.  Returns TRUE if such a region would be unreachable.
   1630 
   1631    Cleanup regions within a must-not-throw region aren't actually reachable
   1632    even if there are throwing stmts within them, because the personality
   1633    routine will call terminate before unwinding.  */
   1634 
   1635 static bool
   1636 cleanup_is_dead_in (leh_state *state)
   1637 {
   1638   if (flag_checking)
   1639     {
   1640       eh_region reg = state->cur_region;
   1641       while (reg && reg->type == ERT_CLEANUP)
   1642 	reg = reg->outer;
   1643 
   1644       gcc_assert (reg == state->outer_non_cleanup);
   1645     }
   1646 
   1647   eh_region reg = state->outer_non_cleanup;
   1648   return (reg && reg->type == ERT_MUST_NOT_THROW);
   1649 }
   1650 
   1651 /* A subroutine of lower_eh_constructs_1.  Lower a GIMPLE_TRY_FINALLY nodes
   1652    to a sequence of labels and blocks, plus the exception region trees
   1653    that record all the magic.  This is complicated by the need to
   1654    arrange for the FINALLY block to be executed on all exits.  */
   1655 
   1656 static gimple_seq
   1657 lower_try_finally (struct leh_state *state, gtry *tp)
   1658 {
   1659   struct leh_tf_state this_tf;
   1660   struct leh_state this_state;
   1661   int ndests;
   1662   gimple_seq old_eh_seq;
   1663 
   1664   /* Process the try block.  */
   1665 
   1666   memset (&this_tf, 0, sizeof (this_tf));
   1667   this_tf.try_finally_expr = tp;
   1668   this_tf.top_p = tp;
   1669   this_tf.outer = state;
   1670   if (using_eh_for_cleanups_p () && !cleanup_is_dead_in (state))
   1671     {
   1672       this_tf.region = gen_eh_region_cleanup (state->cur_region);
   1673       this_state.cur_region = this_tf.region;
   1674     }
   1675   else
   1676     {
   1677       this_tf.region = NULL;
   1678       this_state.cur_region = state->cur_region;
   1679     }
   1680 
   1681   this_state.outer_non_cleanup = state->outer_non_cleanup;
   1682   this_state.ehp_region = state->ehp_region;
   1683   this_state.tf = &this_tf;
   1684 
   1685   old_eh_seq = eh_seq;
   1686   eh_seq = NULL;
   1687 
   1688   lower_eh_constructs_1 (&this_state, gimple_try_eval_ptr (tp));
   1689 
   1690   /* Determine if the try block is escaped through the bottom.  */
   1691   this_tf.may_fallthru = gimple_seq_may_fallthru (gimple_try_eval (tp));
   1692 
   1693   /* Determine if any exceptions are possible within the try block.  */
   1694   if (this_tf.region)
   1695     this_tf.may_throw = eh_region_may_contain_throw (this_tf.region);
   1696   if (this_tf.may_throw)
   1697     honor_protect_cleanup_actions (state, &this_state, &this_tf);
   1698 
   1699   /* Determine how many edges (still) reach the finally block.  Or rather,
   1700      how many destinations are reached by the finally block.  Use this to
   1701      determine how we process the finally block itself.  */
   1702 
   1703   ndests = this_tf.dest_array.length ();
   1704   ndests += this_tf.may_fallthru;
   1705   ndests += this_tf.may_return;
   1706   ndests += this_tf.may_throw;
   1707 
   1708   /* If the FINALLY block is not reachable, dike it out.  */
   1709   if (ndests == 0)
   1710     {
   1711       gimple_seq_add_seq (&this_tf.top_p_seq, gimple_try_eval (tp));
   1712       gimple_try_set_cleanup (tp, NULL);
   1713     }
   1714   /* If the finally block doesn't fall through, then any destination
   1715      we might try to impose there isn't reached either.  There may be
   1716      some minor amount of cleanup and redirection still needed.  */
   1717   else if (!gimple_seq_may_fallthru (gimple_try_cleanup (tp)))
   1718     lower_try_finally_nofallthru (state, &this_tf);
   1719 
   1720   /* We can easily special-case redirection to a single destination.  */
   1721   else if (ndests == 1)
   1722     lower_try_finally_onedest (state, &this_tf);
   1723   else if (decide_copy_try_finally (ndests, this_tf.may_throw,
   1724 				    gimple_try_cleanup (tp)))
   1725     lower_try_finally_copy (state, &this_tf);
   1726   else
   1727     lower_try_finally_switch (state, &this_tf);
   1728 
   1729   /* If someone requested we add a label at the end of the transformed
   1730      block, do so.  */
   1731   if (this_tf.fallthru_label)
   1732     {
   1733       /* This must be reached only if ndests == 0. */
   1734       gimple *x = gimple_build_label (this_tf.fallthru_label);
   1735       gimple_seq_add_stmt (&this_tf.top_p_seq, x);
   1736     }
   1737 
   1738   this_tf.dest_array.release ();
   1739   free (this_tf.goto_queue);
   1740   if (this_tf.goto_queue_map)
   1741     delete this_tf.goto_queue_map;
   1742 
   1743   /* If there was an old (aka outer) eh_seq, append the current eh_seq.
   1744      If there was no old eh_seq, then the append is trivially already done.  */
   1745   if (old_eh_seq)
   1746     {
   1747       if (eh_seq == NULL)
   1748 	eh_seq = old_eh_seq;
   1749       else
   1750 	{
   1751 	  gimple_seq new_eh_seq = eh_seq;
   1752 	  eh_seq = old_eh_seq;
   1753 	  gimple_seq_add_seq (&eh_seq, new_eh_seq);
   1754 	}
   1755     }
   1756 
   1757   return this_tf.top_p_seq;
   1758 }
   1759 
   1760 /* A subroutine of lower_eh_constructs_1.  Lower a GIMPLE_TRY_CATCH with a
   1761    list of GIMPLE_CATCH to a sequence of labels and blocks, plus the
   1762    exception region trees that records all the magic.  */
   1763 
   1764 static gimple_seq
   1765 lower_catch (struct leh_state *state, gtry *tp)
   1766 {
   1767   eh_region try_region = NULL;
   1768   struct leh_state this_state = *state;
   1769   gimple_stmt_iterator gsi;
   1770   tree out_label;
   1771   gimple_seq new_seq, cleanup;
   1772   gimple *x;
   1773   geh_dispatch *eh_dispatch;
   1774   location_t try_catch_loc = gimple_location (tp);
   1775   location_t catch_loc = UNKNOWN_LOCATION;
   1776 
   1777   if (flag_exceptions)
   1778     {
   1779       try_region = gen_eh_region_try (state->cur_region);
   1780       this_state.cur_region = try_region;
   1781       this_state.outer_non_cleanup = this_state.cur_region;
   1782     }
   1783 
   1784   lower_eh_constructs_1 (&this_state, gimple_try_eval_ptr (tp));
   1785 
   1786   if (!eh_region_may_contain_throw (try_region))
   1787     return gimple_try_eval (tp);
   1788 
   1789   new_seq = NULL;
   1790   eh_dispatch = gimple_build_eh_dispatch (try_region->index);
   1791   gimple_seq_add_stmt (&new_seq, eh_dispatch);
   1792   emit_resx (&new_seq, try_region);
   1793 
   1794   this_state.cur_region = state->cur_region;
   1795   this_state.outer_non_cleanup = state->outer_non_cleanup;
   1796   this_state.ehp_region = try_region;
   1797 
   1798   /* Add eh_seq from lowering EH in the cleanup sequence after the cleanup
   1799      itself, so that e.g. for coverage purposes the nested cleanups don't
   1800      appear before the cleanup body.  See PR64634 for details.  */
   1801   gimple_seq old_eh_seq = eh_seq;
   1802   eh_seq = NULL;
   1803 
   1804   out_label = NULL;
   1805   cleanup = gimple_try_cleanup (tp);
   1806   for (gsi = gsi_start (cleanup);
   1807        !gsi_end_p (gsi);
   1808        gsi_next (&gsi))
   1809     {
   1810       eh_catch c;
   1811       gcatch *catch_stmt;
   1812       gimple_seq handler;
   1813 
   1814       catch_stmt = as_a <gcatch *> (gsi_stmt (gsi));
   1815       if (catch_loc == UNKNOWN_LOCATION)
   1816 	catch_loc = gimple_location (catch_stmt);
   1817       c = gen_eh_region_catch (try_region, gimple_catch_types (catch_stmt));
   1818 
   1819       handler = gimple_catch_handler (catch_stmt);
   1820       lower_eh_constructs_1 (&this_state, &handler);
   1821 
   1822       c->label = create_artificial_label (UNKNOWN_LOCATION);
   1823       x = gimple_build_label (c->label);
   1824       gimple_seq_add_stmt (&new_seq, x);
   1825 
   1826       gimple_seq_add_seq (&new_seq, handler);
   1827 
   1828       if (gimple_seq_may_fallthru (new_seq))
   1829 	{
   1830 	  if (!out_label)
   1831 	    out_label = create_artificial_label (try_catch_loc);
   1832 
   1833 	  x = gimple_build_goto (out_label);
   1834 	  gimple_seq_add_stmt (&new_seq, x);
   1835 	}
   1836       if (!c->type_list)
   1837 	break;
   1838     }
   1839 
   1840   /* Try to set a location on the dispatching construct to avoid inheriting
   1841      the location of the previous statement.  */
   1842   gimple_set_location (eh_dispatch, catch_loc);
   1843 
   1844   gimple_try_set_cleanup (tp, new_seq);
   1845 
   1846   gimple_seq new_eh_seq = eh_seq;
   1847   eh_seq = old_eh_seq;
   1848   gimple_seq ret_seq = frob_into_branch_around (tp, try_region, out_label);
   1849   gimple_seq_add_seq (&eh_seq, new_eh_seq);
   1850   return ret_seq;
   1851 }
   1852 
   1853 /* A subroutine of lower_eh_constructs_1.  Lower a GIMPLE_TRY with a
   1854    GIMPLE_EH_FILTER to a sequence of labels and blocks, plus the exception
   1855    region trees that record all the magic.  */
   1856 
   1857 static gimple_seq
   1858 lower_eh_filter (struct leh_state *state, gtry *tp)
   1859 {
   1860   struct leh_state this_state = *state;
   1861   eh_region this_region = NULL;
   1862   gimple *inner, *x;
   1863   gimple_seq new_seq;
   1864 
   1865   inner = gimple_seq_first_stmt (gimple_try_cleanup (tp));
   1866 
   1867   if (flag_exceptions)
   1868     {
   1869       this_region = gen_eh_region_allowed (state->cur_region,
   1870 				           gimple_eh_filter_types (inner));
   1871       this_state.cur_region = this_region;
   1872       this_state.outer_non_cleanup = this_state.cur_region;
   1873     }
   1874 
   1875   lower_eh_constructs_1 (&this_state, gimple_try_eval_ptr (tp));
   1876 
   1877   if (!eh_region_may_contain_throw (this_region))
   1878     return gimple_try_eval (tp);
   1879 
   1880   this_state.cur_region = state->cur_region;
   1881   this_state.ehp_region = this_region;
   1882 
   1883   new_seq = NULL;
   1884   x = gimple_build_eh_dispatch (this_region->index);
   1885   gimple_set_location (x, gimple_location (tp));
   1886   gimple_seq_add_stmt (&new_seq, x);
   1887   emit_resx (&new_seq, this_region);
   1888 
   1889   this_region->u.allowed.label = create_artificial_label (UNKNOWN_LOCATION);
   1890   x = gimple_build_label (this_region->u.allowed.label);
   1891   gimple_seq_add_stmt (&new_seq, x);
   1892 
   1893   lower_eh_constructs_1 (&this_state, gimple_eh_filter_failure_ptr (inner));
   1894   gimple_seq_add_seq (&new_seq, gimple_eh_filter_failure (inner));
   1895 
   1896   gimple_try_set_cleanup (tp, new_seq);
   1897 
   1898   return frob_into_branch_around (tp, this_region, NULL);
   1899 }
   1900 
   1901 /* A subroutine of lower_eh_constructs_1.  Lower a GIMPLE_TRY with
   1902    an GIMPLE_EH_MUST_NOT_THROW to a sequence of labels and blocks,
   1903    plus the exception region trees that record all the magic.  */
   1904 
   1905 static gimple_seq
   1906 lower_eh_must_not_throw (struct leh_state *state, gtry *tp)
   1907 {
   1908   struct leh_state this_state = *state;
   1909 
   1910   if (flag_exceptions)
   1911     {
   1912       gimple *inner = gimple_seq_first_stmt (gimple_try_cleanup (tp));
   1913       eh_region this_region;
   1914 
   1915       this_region = gen_eh_region_must_not_throw (state->cur_region);
   1916       this_region->u.must_not_throw.failure_decl
   1917 	= gimple_eh_must_not_throw_fndecl (
   1918 	    as_a <geh_mnt *> (inner));
   1919       this_region->u.must_not_throw.failure_loc
   1920 	= LOCATION_LOCUS (gimple_location (tp));
   1921 
   1922       /* In order to get mangling applied to this decl, we must mark it
   1923 	 used now.  Otherwise, pass_ipa_free_lang_data won't think it
   1924 	 needs to happen.  */
   1925       TREE_USED (this_region->u.must_not_throw.failure_decl) = 1;
   1926 
   1927       this_state.cur_region = this_region;
   1928       this_state.outer_non_cleanup = this_state.cur_region;
   1929     }
   1930 
   1931   lower_eh_constructs_1 (&this_state, gimple_try_eval_ptr (tp));
   1932 
   1933   return gimple_try_eval (tp);
   1934 }
   1935 
   1936 /* Implement a cleanup expression.  This is similar to try-finally,
   1937    except that we only execute the cleanup block for exception edges.  */
   1938 
   1939 static gimple_seq
   1940 lower_cleanup (struct leh_state *state, gtry *tp)
   1941 {
   1942   struct leh_state this_state = *state;
   1943   eh_region this_region = NULL;
   1944   struct leh_tf_state fake_tf;
   1945   gimple_seq result;
   1946   bool cleanup_dead = cleanup_is_dead_in (state);
   1947 
   1948   if (flag_exceptions && !cleanup_dead)
   1949     {
   1950       this_region = gen_eh_region_cleanup (state->cur_region);
   1951       this_state.cur_region = this_region;
   1952       this_state.outer_non_cleanup = state->outer_non_cleanup;
   1953     }
   1954 
   1955   lower_eh_constructs_1 (&this_state, gimple_try_eval_ptr (tp));
   1956 
   1957   if (cleanup_dead || !eh_region_may_contain_throw (this_region))
   1958     return gimple_try_eval (tp);
   1959 
   1960   /* Build enough of a try-finally state so that we can reuse
   1961      honor_protect_cleanup_actions.  */
   1962   memset (&fake_tf, 0, sizeof (fake_tf));
   1963   fake_tf.top_p = fake_tf.try_finally_expr = tp;
   1964   fake_tf.outer = state;
   1965   fake_tf.region = this_region;
   1966   fake_tf.may_fallthru = gimple_seq_may_fallthru (gimple_try_eval (tp));
   1967   fake_tf.may_throw = true;
   1968 
   1969   honor_protect_cleanup_actions (state, NULL, &fake_tf);
   1970 
   1971   if (fake_tf.may_throw)
   1972     {
   1973       /* In this case honor_protect_cleanup_actions had nothing to do,
   1974 	 and we should process this normally.  */
   1975       lower_eh_constructs_1 (state, gimple_try_cleanup_ptr (tp));
   1976       result = frob_into_branch_around (tp, this_region,
   1977                                         fake_tf.fallthru_label);
   1978     }
   1979   else
   1980     {
   1981       /* In this case honor_protect_cleanup_actions did nearly all of
   1982 	 the work.  All we have left is to append the fallthru_label.  */
   1983 
   1984       result = gimple_try_eval (tp);
   1985       if (fake_tf.fallthru_label)
   1986 	{
   1987 	  gimple *x = gimple_build_label (fake_tf.fallthru_label);
   1988 	  gimple_seq_add_stmt (&result, x);
   1989 	}
   1990     }
   1991   return result;
   1992 }
   1993 
   1994 /* Main loop for lowering eh constructs. Also moves gsi to the next
   1995    statement. */
   1996 
   1997 static void
   1998 lower_eh_constructs_2 (struct leh_state *state, gimple_stmt_iterator *gsi)
   1999 {
   2000   gimple_seq replace;
   2001   gimple *x;
   2002   gimple *stmt = gsi_stmt (*gsi);
   2003 
   2004   switch (gimple_code (stmt))
   2005     {
   2006     case GIMPLE_CALL:
   2007       {
   2008 	tree fndecl = gimple_call_fndecl (stmt);
   2009 	tree rhs, lhs;
   2010 
   2011 	if (fndecl && fndecl_built_in_p (fndecl, BUILT_IN_NORMAL))
   2012 	  switch (DECL_FUNCTION_CODE (fndecl))
   2013 	    {
   2014 	    case BUILT_IN_EH_POINTER:
   2015 	      /* The front end may have generated a call to
   2016 		 __builtin_eh_pointer (0) within a catch region.  Replace
   2017 		 this zero argument with the current catch region number.  */
   2018 	      if (state->ehp_region)
   2019 		{
   2020 		  tree nr = build_int_cst (integer_type_node,
   2021 					   state->ehp_region->index);
   2022 		  gimple_call_set_arg (stmt, 0, nr);
   2023 		}
   2024 	      else
   2025 		{
   2026 		  /* The user has dome something silly.  Remove it.  */
   2027 		  rhs = null_pointer_node;
   2028 		  goto do_replace;
   2029 		}
   2030 	      break;
   2031 
   2032 	    case BUILT_IN_EH_FILTER:
   2033 	      /* ??? This should never appear, but since it's a builtin it
   2034 		 is accessible to abuse by users.  Just remove it and
   2035 		 replace the use with the arbitrary value zero.  */
   2036 	      rhs = build_int_cst (TREE_TYPE (TREE_TYPE (fndecl)), 0);
   2037 	    do_replace:
   2038 	      lhs = gimple_call_lhs (stmt);
   2039 	      x = gimple_build_assign (lhs, rhs);
   2040 	      gsi_insert_before (gsi, x, GSI_SAME_STMT);
   2041 	      /* FALLTHRU */
   2042 
   2043 	    case BUILT_IN_EH_COPY_VALUES:
   2044 	      /* Likewise this should not appear.  Remove it.  */
   2045 	      gsi_remove (gsi, true);
   2046 	      return;
   2047 
   2048 	    default:
   2049 	      break;
   2050 	    }
   2051       }
   2052       /* FALLTHRU */
   2053 
   2054     case GIMPLE_ASSIGN:
   2055       /* If the stmt can throw, use a new temporary for the assignment
   2056          to a LHS.  This makes sure the old value of the LHS is
   2057 	 available on the EH edge.  Only do so for statements that
   2058 	 potentially fall through (no noreturn calls e.g.), otherwise
   2059 	 this new assignment might create fake fallthru regions.  */
   2060       if (stmt_could_throw_p (cfun, stmt)
   2061 	  && gimple_has_lhs (stmt)
   2062 	  && gimple_stmt_may_fallthru (stmt)
   2063 	  && !tree_could_throw_p (gimple_get_lhs (stmt))
   2064 	  && is_gimple_reg_type (TREE_TYPE (gimple_get_lhs (stmt))))
   2065 	{
   2066 	  tree lhs = gimple_get_lhs (stmt);
   2067 	  tree tmp = create_tmp_var (TREE_TYPE (lhs));
   2068 	  gimple *s = gimple_build_assign (lhs, tmp);
   2069 	  gimple_set_location (s, gimple_location (stmt));
   2070 	  gimple_set_block (s, gimple_block (stmt));
   2071 	  gimple_set_lhs (stmt, tmp);
   2072 	  gsi_insert_after (gsi, s, GSI_SAME_STMT);
   2073 	}
   2074       /* Look for things that can throw exceptions, and record them.  */
   2075       if (state->cur_region && stmt_could_throw_p (cfun, stmt))
   2076 	{
   2077 	  record_stmt_eh_region (state->cur_region, stmt);
   2078 	  note_eh_region_may_contain_throw (state->cur_region);
   2079 	}
   2080       break;
   2081 
   2082     case GIMPLE_COND:
   2083     case GIMPLE_GOTO:
   2084     case GIMPLE_RETURN:
   2085       maybe_record_in_goto_queue (state, stmt);
   2086       break;
   2087 
   2088     case GIMPLE_SWITCH:
   2089       verify_norecord_switch_expr (state, as_a <gswitch *> (stmt));
   2090       break;
   2091 
   2092     case GIMPLE_TRY:
   2093       {
   2094 	gtry *try_stmt = as_a <gtry *> (stmt);
   2095 	if (gimple_try_kind (try_stmt) == GIMPLE_TRY_FINALLY)
   2096 	  replace = lower_try_finally (state, try_stmt);
   2097 	else
   2098 	  {
   2099 	    x = gimple_seq_first_stmt (gimple_try_cleanup (try_stmt));
   2100 	    if (!x)
   2101 	      {
   2102 		replace = gimple_try_eval (try_stmt);
   2103 		lower_eh_constructs_1 (state, &replace);
   2104 	      }
   2105 	    else
   2106 	      switch (gimple_code (x))
   2107 		{
   2108 		case GIMPLE_CATCH:
   2109 		  replace = lower_catch (state, try_stmt);
   2110 		  break;
   2111 		case GIMPLE_EH_FILTER:
   2112 		  replace = lower_eh_filter (state, try_stmt);
   2113 		  break;
   2114 		case GIMPLE_EH_MUST_NOT_THROW:
   2115 		  replace = lower_eh_must_not_throw (state, try_stmt);
   2116 		  break;
   2117 		case GIMPLE_EH_ELSE:
   2118 		  /* This code is only valid with GIMPLE_TRY_FINALLY.  */
   2119 		  gcc_unreachable ();
   2120 		default:
   2121 		  replace = lower_cleanup (state, try_stmt);
   2122 		  break;
   2123 		}
   2124 	  }
   2125       }
   2126 
   2127       /* Remove the old stmt and insert the transformed sequence
   2128 	 instead. */
   2129       gsi_insert_seq_before (gsi, replace, GSI_SAME_STMT);
   2130       gsi_remove (gsi, true);
   2131 
   2132       /* Return since we don't want gsi_next () */
   2133       return;
   2134 
   2135     case GIMPLE_EH_ELSE:
   2136       /* We should be eliminating this in lower_try_finally et al.  */
   2137       gcc_unreachable ();
   2138 
   2139     default:
   2140       /* A type, a decl, or some kind of statement that we're not
   2141 	 interested in.  Don't walk them.  */
   2142       break;
   2143     }
   2144 
   2145   gsi_next (gsi);
   2146 }
   2147 
   2148 /* A helper to unwrap a gimple_seq and feed stmts to lower_eh_constructs_2. */
   2149 
   2150 static void
   2151 lower_eh_constructs_1 (struct leh_state *state, gimple_seq *pseq)
   2152 {
   2153   gimple_stmt_iterator gsi;
   2154   for (gsi = gsi_start (*pseq); !gsi_end_p (gsi);)
   2155     lower_eh_constructs_2 (state, &gsi);
   2156 }
   2157 
   2158 namespace {
   2159 
   2160 const pass_data pass_data_lower_eh =
   2161 {
   2162   GIMPLE_PASS, /* type */
   2163   "eh", /* name */
   2164   OPTGROUP_NONE, /* optinfo_flags */
   2165   TV_TREE_EH, /* tv_id */
   2166   PROP_gimple_lcf, /* properties_required */
   2167   PROP_gimple_leh, /* properties_provided */
   2168   0, /* properties_destroyed */
   2169   0, /* todo_flags_start */
   2170   0, /* todo_flags_finish */
   2171 };
   2172 
   2173 class pass_lower_eh : public gimple_opt_pass
   2174 {
   2175 public:
   2176   pass_lower_eh (gcc::context *ctxt)
   2177     : gimple_opt_pass (pass_data_lower_eh, ctxt)
   2178   {}
   2179 
   2180   /* opt_pass methods: */
   2181   unsigned int execute (function *) final override;
   2182 
   2183 }; // class pass_lower_eh
   2184 
   2185 unsigned int
   2186 pass_lower_eh::execute (function *fun)
   2187 {
   2188   struct leh_state null_state;
   2189   gimple_seq bodyp;
   2190 
   2191   bodyp = gimple_body (current_function_decl);
   2192   if (bodyp == NULL)
   2193     return 0;
   2194 
   2195   finally_tree = new hash_table<finally_tree_hasher> (31);
   2196   eh_region_may_contain_throw_map = BITMAP_ALLOC (NULL);
   2197   memset (&null_state, 0, sizeof (null_state));
   2198 
   2199   collect_finally_tree_1 (bodyp, NULL);
   2200   lower_eh_constructs_1 (&null_state, &bodyp);
   2201   gimple_set_body (current_function_decl, bodyp);
   2202 
   2203   /* We assume there's a return statement, or something, at the end of
   2204      the function, and thus ploping the EH sequence afterward won't
   2205      change anything.  */
   2206   gcc_assert (!gimple_seq_may_fallthru (bodyp));
   2207   gimple_seq_add_seq (&bodyp, eh_seq);
   2208 
   2209   /* We assume that since BODYP already existed, adding EH_SEQ to it
   2210      didn't change its value, and we don't have to re-set the function.  */
   2211   gcc_assert (bodyp == gimple_body (current_function_decl));
   2212 
   2213   delete finally_tree;
   2214   finally_tree = NULL;
   2215   BITMAP_FREE (eh_region_may_contain_throw_map);
   2216   eh_seq = NULL;
   2217 
   2218   /* If this function needs a language specific EH personality routine
   2219      and the frontend didn't already set one do so now.  */
   2220   if (function_needs_eh_personality (fun) == eh_personality_lang
   2221       && !DECL_FUNCTION_PERSONALITY (current_function_decl))
   2222     DECL_FUNCTION_PERSONALITY (current_function_decl)
   2223       = lang_hooks.eh_personality ();
   2224 
   2225   return 0;
   2226 }
   2227 
   2228 } // anon namespace
   2229 
   2230 gimple_opt_pass *
   2231 make_pass_lower_eh (gcc::context *ctxt)
   2232 {
   2233   return new pass_lower_eh (ctxt);
   2234 }
   2235 
   2236 /* Create the multiple edges from an EH_DISPATCH statement to all of
   2238    the possible handlers for its EH region.  Return true if there's
   2239    no fallthru edge; false if there is.  */
   2240 
   2241 bool
   2242 make_eh_dispatch_edges (geh_dispatch *stmt)
   2243 {
   2244   eh_region r;
   2245   eh_catch c;
   2246   basic_block src, dst;
   2247 
   2248   r = get_eh_region_from_number (gimple_eh_dispatch_region (stmt));
   2249   src = gimple_bb (stmt);
   2250 
   2251   switch (r->type)
   2252     {
   2253     case ERT_TRY:
   2254       for (c = r->u.eh_try.first_catch; c ; c = c->next_catch)
   2255 	{
   2256 	  dst = label_to_block (cfun, c->label);
   2257 	  make_edge (src, dst, 0);
   2258 
   2259 	  /* A catch-all handler doesn't have a fallthru.  */
   2260 	  if (c->type_list == NULL)
   2261 	    return false;
   2262 	}
   2263       break;
   2264 
   2265     case ERT_ALLOWED_EXCEPTIONS:
   2266       dst = label_to_block (cfun, r->u.allowed.label);
   2267       make_edge (src, dst, 0);
   2268       break;
   2269 
   2270     default:
   2271       gcc_unreachable ();
   2272     }
   2273 
   2274   return true;
   2275 }
   2276 
   2277 /* Create the single EH edge from STMT to its nearest landing pad,
   2278    if there is such a landing pad within the current function.  */
   2279 
   2280 edge
   2281 make_eh_edge (gimple *stmt)
   2282 {
   2283   basic_block src, dst;
   2284   eh_landing_pad lp;
   2285   int lp_nr;
   2286 
   2287   lp_nr = lookup_stmt_eh_lp (stmt);
   2288   if (lp_nr <= 0)
   2289     return NULL;
   2290 
   2291   lp = get_eh_landing_pad_from_number (lp_nr);
   2292   gcc_assert (lp != NULL);
   2293 
   2294   src = gimple_bb (stmt);
   2295   dst = label_to_block (cfun, lp->post_landing_pad);
   2296   return make_edge (src, dst, EDGE_EH);
   2297 }
   2298 
   2299 /* Do the work in redirecting EDGE_IN to NEW_BB within the EH region tree;
   2300    do not actually perform the final edge redirection.
   2301 
   2302    CHANGE_REGION is true when we're being called from cleanup_empty_eh and
   2303    we intend to change the destination EH region as well; this means
   2304    EH_LANDING_PAD_NR must already be set on the destination block label.
   2305    If false, we're being called from generic cfg manipulation code and we
   2306    should preserve our place within the region tree.  */
   2307 
   2308 static void
   2309 redirect_eh_edge_1 (edge edge_in, basic_block new_bb, bool change_region)
   2310 {
   2311   eh_landing_pad old_lp, new_lp;
   2312   basic_block old_bb;
   2313   gimple *throw_stmt;
   2314   int old_lp_nr, new_lp_nr;
   2315   tree old_label, new_label;
   2316   edge_iterator ei;
   2317   edge e;
   2318 
   2319   old_bb = edge_in->dest;
   2320   old_label = gimple_block_label (old_bb);
   2321   old_lp_nr = EH_LANDING_PAD_NR (old_label);
   2322   gcc_assert (old_lp_nr > 0);
   2323   old_lp = get_eh_landing_pad_from_number (old_lp_nr);
   2324 
   2325   throw_stmt = *gsi_last_bb (edge_in->src);
   2326   gcc_checking_assert (lookup_stmt_eh_lp (throw_stmt) == old_lp_nr);
   2327 
   2328   new_label = gimple_block_label (new_bb);
   2329 
   2330   /* Look for an existing region that might be using NEW_BB already.  */
   2331   new_lp_nr = EH_LANDING_PAD_NR (new_label);
   2332   if (new_lp_nr)
   2333     {
   2334       new_lp = get_eh_landing_pad_from_number (new_lp_nr);
   2335       gcc_assert (new_lp);
   2336 
   2337       /* Unless CHANGE_REGION is true, the new and old landing pad
   2338 	 had better be associated with the same EH region.  */
   2339       gcc_assert (change_region || new_lp->region == old_lp->region);
   2340     }
   2341   else
   2342     {
   2343       new_lp = NULL;
   2344       gcc_assert (!change_region);
   2345     }
   2346 
   2347   /* Notice when we redirect the last EH edge away from OLD_BB.  */
   2348   FOR_EACH_EDGE (e, ei, old_bb->preds)
   2349     if (e != edge_in && (e->flags & EDGE_EH))
   2350       break;
   2351 
   2352   if (new_lp)
   2353     {
   2354       /* NEW_LP already exists.  If there are still edges into OLD_LP,
   2355 	 there's nothing to do with the EH tree.  If there are no more
   2356 	 edges into OLD_LP, then we want to remove OLD_LP as it is unused.
   2357 	 If CHANGE_REGION is true, then our caller is expecting to remove
   2358 	 the landing pad.  */
   2359       if (e == NULL && !change_region)
   2360 	remove_eh_landing_pad (old_lp);
   2361     }
   2362   else
   2363     {
   2364       /* No correct landing pad exists.  If there are no more edges
   2365 	 into OLD_LP, then we can simply re-use the existing landing pad.
   2366 	 Otherwise, we have to create a new landing pad.  */
   2367       if (e == NULL)
   2368 	{
   2369 	  EH_LANDING_PAD_NR (old_lp->post_landing_pad) = 0;
   2370 	  new_lp = old_lp;
   2371 	}
   2372       else
   2373 	new_lp = gen_eh_landing_pad (old_lp->region);
   2374       new_lp->post_landing_pad = new_label;
   2375       EH_LANDING_PAD_NR (new_label) = new_lp->index;
   2376     }
   2377 
   2378   /* Maybe move the throwing statement to the new region.  */
   2379   if (old_lp != new_lp)
   2380     {
   2381       remove_stmt_from_eh_lp (throw_stmt);
   2382       add_stmt_to_eh_lp (throw_stmt, new_lp->index);
   2383     }
   2384 }
   2385 
   2386 /* Redirect EH edge E to NEW_BB.  */
   2387 
   2388 edge
   2389 redirect_eh_edge (edge edge_in, basic_block new_bb)
   2390 {
   2391   redirect_eh_edge_1 (edge_in, new_bb, false);
   2392   return ssa_redirect_edge (edge_in, new_bb);
   2393 }
   2394 
   2395 /* This is a subroutine of gimple_redirect_edge_and_branch.  Update the
   2396    labels for redirecting a non-fallthru EH_DISPATCH edge E to NEW_BB.
   2397    The actual edge update will happen in the caller.  */
   2398 
   2399 void
   2400 redirect_eh_dispatch_edge (geh_dispatch *stmt, edge e, basic_block new_bb)
   2401 {
   2402   tree new_lab = gimple_block_label (new_bb);
   2403   bool any_changed = false;
   2404   basic_block old_bb;
   2405   eh_region r;
   2406   eh_catch c;
   2407 
   2408   r = get_eh_region_from_number (gimple_eh_dispatch_region (stmt));
   2409   switch (r->type)
   2410     {
   2411     case ERT_TRY:
   2412       for (c = r->u.eh_try.first_catch; c ; c = c->next_catch)
   2413 	{
   2414 	  old_bb = label_to_block (cfun, c->label);
   2415 	  if (old_bb == e->dest)
   2416 	    {
   2417 	      c->label = new_lab;
   2418 	      any_changed = true;
   2419 	    }
   2420 	}
   2421       break;
   2422 
   2423     case ERT_ALLOWED_EXCEPTIONS:
   2424       old_bb = label_to_block (cfun, r->u.allowed.label);
   2425       gcc_assert (old_bb == e->dest);
   2426       r->u.allowed.label = new_lab;
   2427       any_changed = true;
   2428       break;
   2429 
   2430     default:
   2431       gcc_unreachable ();
   2432     }
   2433 
   2434   gcc_assert (any_changed);
   2435 }
   2436 
   2437 /* Helper function for operation_could_trap_p and stmt_could_throw_p.  */
   2439 
   2440 bool
   2441 operation_could_trap_helper_p (enum tree_code op,
   2442 			       bool fp_operation,
   2443 			       bool honor_trapv,
   2444 			       bool honor_nans,
   2445 			       bool honor_snans,
   2446 			       tree divisor,
   2447 			       bool *handled)
   2448 {
   2449   *handled = true;
   2450   switch (op)
   2451     {
   2452     case TRUNC_DIV_EXPR:
   2453     case CEIL_DIV_EXPR:
   2454     case FLOOR_DIV_EXPR:
   2455     case ROUND_DIV_EXPR:
   2456     case EXACT_DIV_EXPR:
   2457     case CEIL_MOD_EXPR:
   2458     case FLOOR_MOD_EXPR:
   2459     case ROUND_MOD_EXPR:
   2460     case TRUNC_MOD_EXPR:
   2461       if (!TREE_CONSTANT (divisor) || integer_zerop (divisor))
   2462         return true;
   2463       if (TREE_CODE (divisor) == VECTOR_CST)
   2464 	{
   2465 	  /* Inspired by initializer_each_zero_or_onep.  */
   2466 	  unsigned HOST_WIDE_INT nelts = vector_cst_encoded_nelts (divisor);
   2467 	  if (VECTOR_CST_STEPPED_P (divisor)
   2468 	      && !TYPE_VECTOR_SUBPARTS (TREE_TYPE (divisor))
   2469 		    .is_constant (&nelts))
   2470 	    return true;
   2471 	  for (unsigned int i = 0; i < nelts; ++i)
   2472 	    {
   2473 	      tree elt = vector_cst_elt (divisor, i);
   2474 	      if (integer_zerop (elt))
   2475 		return true;
   2476 	    }
   2477 	}
   2478       return false;
   2479 
   2480     case RDIV_EXPR:
   2481       if (fp_operation)
   2482 	{
   2483 	  if (honor_snans)
   2484 	    return true;
   2485 	  return flag_trapping_math;
   2486 	}
   2487       /* Fixed point operations also use RDIV_EXPR.  */
   2488       if (!TREE_CONSTANT (divisor) || fixed_zerop (divisor))
   2489 	return true;
   2490       return false;
   2491 
   2492     case LT_EXPR:
   2493     case LE_EXPR:
   2494     case GT_EXPR:
   2495     case GE_EXPR:
   2496     case LTGT_EXPR:
   2497     /* MIN/MAX similar as LT/LE/GT/GE. */
   2498     case MIN_EXPR:
   2499     case MAX_EXPR:
   2500       /* Some floating point comparisons may trap.  */
   2501       return honor_nans;
   2502 
   2503     case EQ_EXPR:
   2504     case NE_EXPR:
   2505     case UNORDERED_EXPR:
   2506     case ORDERED_EXPR:
   2507     case UNLT_EXPR:
   2508     case UNLE_EXPR:
   2509     case UNGT_EXPR:
   2510     case UNGE_EXPR:
   2511     case UNEQ_EXPR:
   2512       return honor_snans;
   2513 
   2514     case NEGATE_EXPR:
   2515     case ABS_EXPR:
   2516     case CONJ_EXPR:
   2517       /* These operations don't trap with floating point.  */
   2518       if (honor_trapv)
   2519 	return true;
   2520       return false;
   2521 
   2522     case ABSU_EXPR:
   2523       /* ABSU_EXPR never traps.  */
   2524       return false;
   2525 
   2526     case PLUS_EXPR:
   2527     case MINUS_EXPR:
   2528     case MULT_EXPR:
   2529       /* Any floating arithmetic may trap.  */
   2530       if (fp_operation && flag_trapping_math)
   2531 	return true;
   2532       if (honor_trapv)
   2533 	return true;
   2534       return false;
   2535 
   2536     case COMPLEX_EXPR:
   2537     case CONSTRUCTOR:
   2538       /* Constructing an object cannot trap.  */
   2539       return false;
   2540 
   2541     case COND_EXPR:
   2542     case VEC_COND_EXPR:
   2543       /* Whether *COND_EXPR can trap depends on whether the
   2544 	 first argument can trap, so signal it as not handled.
   2545 	 Whether lhs is floating or not doesn't matter.  */
   2546       *handled = false;
   2547       return false;
   2548 
   2549     default:
   2550       /* Any floating arithmetic may trap.  */
   2551       if (fp_operation && flag_trapping_math)
   2552 	return true;
   2553 
   2554       *handled = false;
   2555       return false;
   2556     }
   2557 }
   2558 
   2559 /* Return true if operation OP may trap.  FP_OPERATION is true if OP is applied
   2560    on floating-point values.  HONOR_TRAPV is true if OP is applied on integer
   2561    type operands that may trap.  If OP is a division operator, DIVISOR contains
   2562    the value of the divisor.  */
   2563 
   2564 bool
   2565 operation_could_trap_p (enum tree_code op, bool fp_operation, bool honor_trapv,
   2566 			tree divisor)
   2567 {
   2568   bool honor_nans = (fp_operation && flag_trapping_math
   2569 		     && !flag_finite_math_only);
   2570   bool honor_snans = fp_operation && flag_signaling_nans != 0;
   2571   bool handled;
   2572 
   2573   /* This function cannot tell whether or not COND_EXPR could trap,
   2574      because that depends on its condition op.  */
   2575   gcc_assert (op != COND_EXPR);
   2576 
   2577   if (TREE_CODE_CLASS (op) != tcc_comparison
   2578       && TREE_CODE_CLASS (op) != tcc_unary
   2579       && TREE_CODE_CLASS (op) != tcc_binary)
   2580     return false;
   2581 
   2582   return operation_could_trap_helper_p (op, fp_operation, honor_trapv,
   2583 					honor_nans, honor_snans, divisor,
   2584 					&handled);
   2585 }
   2586 
   2587 
   2588 /* Returns true if it is possible to prove that the index of
   2589    an array access REF (an ARRAY_REF expression) falls into the
   2590    array bounds.  */
   2591 
   2592 static bool
   2593 in_array_bounds_p (tree ref)
   2594 {
   2595   tree idx = TREE_OPERAND (ref, 1);
   2596   tree min, max;
   2597 
   2598   if (TREE_CODE (idx) != INTEGER_CST)
   2599     return false;
   2600 
   2601   min = array_ref_low_bound (ref);
   2602   max = array_ref_up_bound (ref);
   2603   if (!min
   2604       || !max
   2605       || TREE_CODE (min) != INTEGER_CST
   2606       || TREE_CODE (max) != INTEGER_CST)
   2607     return false;
   2608 
   2609   if (tree_int_cst_lt (idx, min)
   2610       || tree_int_cst_lt (max, idx))
   2611     return false;
   2612 
   2613   return true;
   2614 }
   2615 
   2616 /* Returns true if it is possible to prove that the range of
   2617    an array access REF (an ARRAY_RANGE_REF expression) falls
   2618    into the array bounds.  */
   2619 
   2620 static bool
   2621 range_in_array_bounds_p (tree ref)
   2622 {
   2623   tree domain_type = TYPE_DOMAIN (TREE_TYPE (ref));
   2624   tree range_min, range_max, min, max;
   2625 
   2626   range_min = TYPE_MIN_VALUE (domain_type);
   2627   range_max = TYPE_MAX_VALUE (domain_type);
   2628   if (!range_min
   2629       || !range_max
   2630       || TREE_CODE (range_min) != INTEGER_CST
   2631       || TREE_CODE (range_max) != INTEGER_CST)
   2632     return false;
   2633 
   2634   min = array_ref_low_bound (ref);
   2635   max = array_ref_up_bound (ref);
   2636   if (!min
   2637       || !max
   2638       || TREE_CODE (min) != INTEGER_CST
   2639       || TREE_CODE (max) != INTEGER_CST)
   2640     return false;
   2641 
   2642   if (tree_int_cst_lt (range_min, min)
   2643       || tree_int_cst_lt (max, range_max))
   2644     return false;
   2645 
   2646   return true;
   2647 }
   2648 
   2649 /* Return true if EXPR can trap, as in dereferencing an invalid pointer
   2650    location or floating point arithmetic.  C.f. the rtl version, may_trap_p.
   2651    This routine expects only GIMPLE lhs or rhs input.  */
   2652 
   2653 bool
   2654 tree_could_trap_p (tree expr)
   2655 {
   2656   enum tree_code code;
   2657   bool fp_operation = false;
   2658   bool honor_trapv = false;
   2659   tree t, base, div = NULL_TREE;
   2660 
   2661   if (!expr)
   2662     return false;
   2663 
   2664   /* In COND_EXPR and VEC_COND_EXPR only the condition may trap, but
   2665      they won't appear as operands in GIMPLE form, so this is just for the
   2666      GENERIC uses where it needs to recurse on the operands and so
   2667      *COND_EXPR itself doesn't trap.  */
   2668   if (TREE_CODE (expr) == COND_EXPR || TREE_CODE (expr) == VEC_COND_EXPR)
   2669     return false;
   2670 
   2671   code = TREE_CODE (expr);
   2672   t = TREE_TYPE (expr);
   2673 
   2674   if (t)
   2675     {
   2676       if (COMPARISON_CLASS_P (expr))
   2677 	fp_operation = FLOAT_TYPE_P (TREE_TYPE (TREE_OPERAND (expr, 0)));
   2678       else
   2679 	fp_operation = FLOAT_TYPE_P (t);
   2680       honor_trapv = INTEGRAL_TYPE_P (t) && TYPE_OVERFLOW_TRAPS (t);
   2681     }
   2682 
   2683   if (TREE_CODE_CLASS (code) == tcc_binary)
   2684     div = TREE_OPERAND (expr, 1);
   2685   if (operation_could_trap_p (code, fp_operation, honor_trapv, div))
   2686     return true;
   2687 
   2688  restart:
   2689   switch (code)
   2690     {
   2691     case COMPONENT_REF:
   2692     case REALPART_EXPR:
   2693     case IMAGPART_EXPR:
   2694     case BIT_FIELD_REF:
   2695     case VIEW_CONVERT_EXPR:
   2696     case WITH_SIZE_EXPR:
   2697       expr = TREE_OPERAND (expr, 0);
   2698       code = TREE_CODE (expr);
   2699       goto restart;
   2700 
   2701     case ARRAY_RANGE_REF:
   2702       base = TREE_OPERAND (expr, 0);
   2703       if (tree_could_trap_p (base))
   2704 	return true;
   2705       if (TREE_THIS_NOTRAP (expr))
   2706 	return false;
   2707       return !range_in_array_bounds_p (expr);
   2708 
   2709     case ARRAY_REF:
   2710       base = TREE_OPERAND (expr, 0);
   2711       if (tree_could_trap_p (base))
   2712 	return true;
   2713       if (TREE_THIS_NOTRAP (expr))
   2714 	return false;
   2715       return !in_array_bounds_p (expr);
   2716 
   2717     case TARGET_MEM_REF:
   2718     case MEM_REF:
   2719       if (TREE_CODE (TREE_OPERAND (expr, 0)) == ADDR_EXPR
   2720 	  && tree_could_trap_p (TREE_OPERAND (TREE_OPERAND (expr, 0), 0)))
   2721 	return true;
   2722       if (TREE_THIS_NOTRAP (expr))
   2723 	return false;
   2724       /* We cannot prove that the access is in-bounds when we have
   2725          variable-index TARGET_MEM_REFs.  */
   2726       if (code == TARGET_MEM_REF
   2727 	  && (TMR_INDEX (expr) || TMR_INDEX2 (expr)))
   2728 	return true;
   2729       if (TREE_CODE (TREE_OPERAND (expr, 0)) == ADDR_EXPR)
   2730 	{
   2731 	  tree base = TREE_OPERAND (TREE_OPERAND (expr, 0), 0);
   2732 	  poly_offset_int off = mem_ref_offset (expr);
   2733 	  if (maybe_lt (off, 0))
   2734 	    return true;
   2735 	  if (TREE_CODE (base) == STRING_CST)
   2736 	    return maybe_le (TREE_STRING_LENGTH (base), off);
   2737 	  tree size = DECL_SIZE_UNIT (base);
   2738 	  tree refsz = TYPE_SIZE_UNIT (TREE_TYPE (expr));
   2739 	  if (size == NULL_TREE
   2740 	      || refsz == NULL_TREE
   2741 	      || !poly_int_tree_p (size)
   2742 	      || !poly_int_tree_p (refsz)
   2743 	      || maybe_le (wi::to_poly_offset (size), off)
   2744 	      || maybe_gt (off + wi::to_poly_offset (refsz),
   2745 			   wi::to_poly_offset (size)))
   2746 	    return true;
   2747 	  /* Now we are sure the whole base of the access is inside
   2748 	     the object.  */
   2749 	  return false;
   2750 	}
   2751       return true;
   2752 
   2753     case INDIRECT_REF:
   2754       return !TREE_THIS_NOTRAP (expr);
   2755 
   2756     case ASM_EXPR:
   2757       return TREE_THIS_VOLATILE (expr);
   2758 
   2759     case CALL_EXPR:
   2760       /* Internal function calls do not trap.  */
   2761       if (CALL_EXPR_FN (expr) == NULL_TREE)
   2762 	return false;
   2763       t = get_callee_fndecl (expr);
   2764       /* Assume that indirect and calls to weak functions may trap.  */
   2765       if (!t || !DECL_P (t))
   2766 	return true;
   2767       if (DECL_WEAK (t))
   2768 	return tree_could_trap_p (t);
   2769       return false;
   2770 
   2771     case FUNCTION_DECL:
   2772       /* Assume that accesses to weak functions may trap, unless we know
   2773 	 they are certainly defined in current TU or in some other
   2774 	 LTO partition.  */
   2775       if (DECL_WEAK (expr) && !DECL_COMDAT (expr) && DECL_EXTERNAL (expr))
   2776 	{
   2777 	  cgraph_node *node = cgraph_node::get (expr);
   2778 	  if (node)
   2779 	    node = node->function_symbol ();
   2780 	  return !(node && node->in_other_partition);
   2781 	}
   2782       return false;
   2783 
   2784     case VAR_DECL:
   2785       /* Assume that accesses to weak vars may trap, unless we know
   2786 	 they are certainly defined in current TU or in some other
   2787 	 LTO partition.  */
   2788       if (DECL_WEAK (expr) && !DECL_COMDAT (expr) && DECL_EXTERNAL (expr))
   2789 	{
   2790 	  varpool_node *node = varpool_node::get (expr);
   2791 	  if (node)
   2792 	    node = node->ultimate_alias_target ();
   2793 	  return !(node && node->in_other_partition);
   2794 	}
   2795       return false;
   2796 
   2797     default:
   2798       return false;
   2799     }
   2800 }
   2801 
   2802 /* Return non-NULL if there is an integer operation with trapping overflow
   2803    we can rewrite into non-trapping.  Called via walk_tree from
   2804    rewrite_to_non_trapping_overflow.  */
   2805 
   2806 static tree
   2807 find_trapping_overflow (tree *tp, int *walk_subtrees, void *data)
   2808 {
   2809   if (EXPR_P (*tp)
   2810       && ANY_INTEGRAL_TYPE_P (TREE_TYPE (*tp))
   2811       && !operation_no_trapping_overflow (TREE_TYPE (*tp), TREE_CODE (*tp)))
   2812     return *tp;
   2813   if (IS_TYPE_OR_DECL_P (*tp)
   2814       || (TREE_CODE (*tp) == SAVE_EXPR && data == NULL))
   2815     *walk_subtrees = 0;
   2816   return NULL_TREE;
   2817 }
   2818 
   2819 /* Rewrite selected operations into unsigned arithmetics, so that they
   2820    don't trap on overflow.  */
   2821 
   2822 static tree
   2823 replace_trapping_overflow (tree *tp, int *walk_subtrees, void *data)
   2824 {
   2825   if (find_trapping_overflow (tp, walk_subtrees, data))
   2826     {
   2827       tree type = TREE_TYPE (*tp);
   2828       tree utype = unsigned_type_for (type);
   2829       *walk_subtrees = 0;
   2830       int len = TREE_OPERAND_LENGTH (*tp);
   2831       for (int i = 0; i < len; ++i)
   2832 	walk_tree (&TREE_OPERAND (*tp, i), replace_trapping_overflow,
   2833 		   data, (hash_set<tree> *) data);
   2834 
   2835       if (TREE_CODE (*tp) == ABS_EXPR)
   2836 	{
   2837 	  TREE_SET_CODE (*tp, ABSU_EXPR);
   2838 	  TREE_TYPE (*tp) = utype;
   2839 	  *tp = fold_convert (type, *tp);
   2840 	}
   2841       else
   2842 	{
   2843 	  TREE_TYPE (*tp) = utype;
   2844 	  len = TREE_OPERAND_LENGTH (*tp);
   2845 	  for (int i = 0; i < len; ++i)
   2846 	    TREE_OPERAND (*tp, i)
   2847 	      = fold_convert (utype, TREE_OPERAND (*tp, i));
   2848 	  *tp = fold_convert (type, *tp);
   2849 	}
   2850     }
   2851   return NULL_TREE;
   2852 }
   2853 
   2854 /* If any subexpression of EXPR can trap due to -ftrapv, rewrite it
   2855    using unsigned arithmetics to avoid traps in it.  */
   2856 
   2857 tree
   2858 rewrite_to_non_trapping_overflow (tree expr)
   2859 {
   2860   if (!flag_trapv)
   2861     return expr;
   2862   hash_set<tree> pset;
   2863   if (!walk_tree (&expr, find_trapping_overflow, &pset, &pset))
   2864     return expr;
   2865   expr = unshare_expr (expr);
   2866   pset.empty ();
   2867   walk_tree (&expr, replace_trapping_overflow, &pset, &pset);
   2868   return expr;
   2869 }
   2870 
   2871 /* Helper for stmt_could_throw_p.  Return true if STMT (assumed to be a
   2872    an assignment or a conditional) may throw.  */
   2873 
   2874 static bool
   2875 stmt_could_throw_1_p (gassign *stmt)
   2876 {
   2877   enum tree_code code = gimple_assign_rhs_code (stmt);
   2878   bool honor_nans = false;
   2879   bool honor_snans = false;
   2880   bool fp_operation = false;
   2881   bool honor_trapv = false;
   2882   tree t;
   2883   size_t i;
   2884   bool handled, ret;
   2885 
   2886   if (TREE_CODE_CLASS (code) == tcc_comparison
   2887       || TREE_CODE_CLASS (code) == tcc_unary
   2888       || TREE_CODE_CLASS (code) == tcc_binary)
   2889     {
   2890       if (TREE_CODE_CLASS (code) == tcc_comparison)
   2891 	t = TREE_TYPE (gimple_assign_rhs1 (stmt));
   2892       else
   2893 	t = TREE_TYPE (gimple_assign_lhs (stmt));
   2894       fp_operation = FLOAT_TYPE_P (t);
   2895       if (fp_operation)
   2896 	{
   2897 	  honor_nans = flag_trapping_math && !flag_finite_math_only;
   2898 	  honor_snans = flag_signaling_nans != 0;
   2899 	}
   2900       else if (INTEGRAL_TYPE_P (t) && TYPE_OVERFLOW_TRAPS (t))
   2901 	honor_trapv = true;
   2902     }
   2903 
   2904   /* First check the LHS.  */
   2905   if (tree_could_trap_p (gimple_assign_lhs (stmt)))
   2906     return true;
   2907 
   2908   /* Check if the main expression may trap.  */
   2909   ret = operation_could_trap_helper_p (code, fp_operation, honor_trapv,
   2910 				       honor_nans, honor_snans,
   2911 				       gimple_assign_rhs2 (stmt),
   2912 				       &handled);
   2913   if (handled)
   2914     return ret;
   2915 
   2916   /* If the expression does not trap, see if any of the individual operands may
   2917      trap.  */
   2918   for (i = 1; i < gimple_num_ops (stmt); i++)
   2919     if (tree_could_trap_p (gimple_op (stmt, i)))
   2920       return true;
   2921 
   2922   return false;
   2923 }
   2924 
   2925 
   2926 /* Return true if statement STMT within FUN could throw an exception.  */
   2927 
   2928 bool
   2929 stmt_could_throw_p (function *fun, gimple *stmt)
   2930 {
   2931   if (!flag_exceptions)
   2932     return false;
   2933 
   2934   /* The only statements that can throw an exception are assignments,
   2935      conditionals, calls, resx, and asms.  */
   2936   switch (gimple_code (stmt))
   2937     {
   2938     case GIMPLE_RESX:
   2939       return true;
   2940 
   2941     case GIMPLE_CALL:
   2942       return !gimple_call_nothrow_p (as_a <gcall *> (stmt));
   2943 
   2944     case GIMPLE_COND:
   2945       {
   2946 	if (fun && !fun->can_throw_non_call_exceptions)
   2947 	  return false;
   2948 	gcond *cond = as_a <gcond *> (stmt);
   2949 	tree lhs = gimple_cond_lhs (cond);
   2950 	return operation_could_trap_p (gimple_cond_code (cond),
   2951 				       FLOAT_TYPE_P (TREE_TYPE (lhs)),
   2952 				       false, NULL_TREE);
   2953       }
   2954 
   2955     case GIMPLE_ASSIGN:
   2956       if ((fun && !fun->can_throw_non_call_exceptions)
   2957 	  || gimple_clobber_p (stmt))
   2958         return false;
   2959       return stmt_could_throw_1_p (as_a <gassign *> (stmt));
   2960 
   2961     case GIMPLE_ASM:
   2962       if (fun && !fun->can_throw_non_call_exceptions)
   2963         return false;
   2964       return gimple_asm_volatile_p (as_a <gasm *> (stmt));
   2965 
   2966     default:
   2967       return false;
   2968     }
   2969 }
   2970 
   2971 /* Return true if STMT in function FUN must be assumed necessary because of
   2972    non-call exceptions.  */
   2973 
   2974 bool
   2975 stmt_unremovable_because_of_non_call_eh_p (function *fun, gimple *stmt)
   2976 {
   2977   return (fun->can_throw_non_call_exceptions
   2978 	  && !fun->can_delete_dead_exceptions
   2979 	  && stmt_could_throw_p (fun, stmt));
   2980 }
   2981 
   2982 /* Return true if expression T could throw an exception.  */
   2983 
   2984 bool
   2985 tree_could_throw_p (tree t)
   2986 {
   2987   if (!flag_exceptions)
   2988     return false;
   2989   if (TREE_CODE (t) == MODIFY_EXPR)
   2990     {
   2991       if (cfun->can_throw_non_call_exceptions
   2992           && tree_could_trap_p (TREE_OPERAND (t, 0)))
   2993         return true;
   2994       t = TREE_OPERAND (t, 1);
   2995     }
   2996 
   2997   if (TREE_CODE (t) == WITH_SIZE_EXPR)
   2998     t = TREE_OPERAND (t, 0);
   2999   if (TREE_CODE (t) == CALL_EXPR)
   3000     return (call_expr_flags (t) & ECF_NOTHROW) == 0;
   3001   if (cfun->can_throw_non_call_exceptions)
   3002     return tree_could_trap_p (t);
   3003   return false;
   3004 }
   3005 
   3006 /* Return true if STMT can throw an exception that is not caught within its
   3007    function FUN.  FUN can be NULL but the function is extra conservative
   3008    then.  */
   3009 
   3010 bool
   3011 stmt_can_throw_external (function *fun, gimple *stmt)
   3012 {
   3013   int lp_nr;
   3014 
   3015   if (!stmt_could_throw_p (fun, stmt))
   3016     return false;
   3017   if (!fun)
   3018     return true;
   3019 
   3020   lp_nr = lookup_stmt_eh_lp_fn (fun, stmt);
   3021   return lp_nr == 0;
   3022 }
   3023 
   3024 /* Return true if STMT can throw an exception that is caught within its
   3025    function FUN.  */
   3026 
   3027 bool
   3028 stmt_can_throw_internal (function *fun, gimple *stmt)
   3029 {
   3030   int lp_nr;
   3031 
   3032   gcc_checking_assert (fun);
   3033   if (!stmt_could_throw_p (fun, stmt))
   3034     return false;
   3035 
   3036   lp_nr = lookup_stmt_eh_lp_fn (fun, stmt);
   3037   return lp_nr > 0;
   3038 }
   3039 
   3040 /* Given a statement STMT in IFUN, if STMT can no longer throw, then
   3041    remove any entry it might have from the EH table.  Return true if
   3042    any change was made.  */
   3043 
   3044 bool
   3045 maybe_clean_eh_stmt_fn (struct function *ifun, gimple *stmt)
   3046 {
   3047   if (stmt_could_throw_p (ifun, stmt))
   3048     return false;
   3049   return remove_stmt_from_eh_lp_fn (ifun, stmt);
   3050 }
   3051 
   3052 /* Likewise, but always use the current function.  */
   3053 
   3054 bool
   3055 maybe_clean_eh_stmt (gimple *stmt)
   3056 {
   3057   return maybe_clean_eh_stmt_fn (cfun, stmt);
   3058 }
   3059 
   3060 /* Given a statement OLD_STMT and a new statement NEW_STMT that has replaced
   3061    OLD_STMT in the function, remove OLD_STMT from the EH table and put NEW_STMT
   3062    in the table if it should be in there.  Return TRUE if a replacement was
   3063    done that my require an EH edge purge.  */
   3064 
   3065 bool
   3066 maybe_clean_or_replace_eh_stmt (gimple *old_stmt, gimple *new_stmt)
   3067 {
   3068   int lp_nr = lookup_stmt_eh_lp (old_stmt);
   3069 
   3070   if (lp_nr != 0)
   3071     {
   3072       bool new_stmt_could_throw = stmt_could_throw_p (cfun, new_stmt);
   3073 
   3074       if (new_stmt == old_stmt && new_stmt_could_throw)
   3075 	return false;
   3076 
   3077       remove_stmt_from_eh_lp (old_stmt);
   3078       if (new_stmt_could_throw)
   3079 	{
   3080 	  add_stmt_to_eh_lp (new_stmt, lp_nr);
   3081 	  return false;
   3082 	}
   3083       else
   3084 	return true;
   3085     }
   3086 
   3087   return false;
   3088 }
   3089 
   3090 /* Given a statement OLD_STMT in OLD_FUN and a duplicate statement NEW_STMT
   3091    in NEW_FUN, copy the EH table data from OLD_STMT to NEW_STMT.  The MAP
   3092    operand is the return value of duplicate_eh_regions.  */
   3093 
   3094 bool
   3095 maybe_duplicate_eh_stmt_fn (struct function *new_fun, gimple *new_stmt,
   3096 			    struct function *old_fun, gimple *old_stmt,
   3097 			    hash_map<void *, void *> *map,
   3098 			    int default_lp_nr)
   3099 {
   3100   int old_lp_nr, new_lp_nr;
   3101 
   3102   if (!stmt_could_throw_p (new_fun, new_stmt))
   3103     return false;
   3104 
   3105   old_lp_nr = lookup_stmt_eh_lp_fn (old_fun, old_stmt);
   3106   if (old_lp_nr == 0)
   3107     {
   3108       if (default_lp_nr == 0)
   3109 	return false;
   3110       new_lp_nr = default_lp_nr;
   3111     }
   3112   else if (old_lp_nr > 0)
   3113     {
   3114       eh_landing_pad old_lp, new_lp;
   3115 
   3116       old_lp = (*old_fun->eh->lp_array)[old_lp_nr];
   3117       new_lp = static_cast<eh_landing_pad> (*map->get (old_lp));
   3118       new_lp_nr = new_lp->index;
   3119     }
   3120   else
   3121     {
   3122       eh_region old_r, new_r;
   3123 
   3124       old_r = (*old_fun->eh->region_array)[-old_lp_nr];
   3125       new_r = static_cast<eh_region> (*map->get (old_r));
   3126       new_lp_nr = -new_r->index;
   3127     }
   3128 
   3129   add_stmt_to_eh_lp_fn (new_fun, new_stmt, new_lp_nr);
   3130   return true;
   3131 }
   3132 
   3133 /* Similar, but both OLD_STMT and NEW_STMT are within the current function,
   3134    and thus no remapping is required.  */
   3135 
   3136 bool
   3137 maybe_duplicate_eh_stmt (gimple *new_stmt, gimple *old_stmt)
   3138 {
   3139   int lp_nr;
   3140 
   3141   if (!stmt_could_throw_p (cfun, new_stmt))
   3142     return false;
   3143 
   3144   lp_nr = lookup_stmt_eh_lp (old_stmt);
   3145   if (lp_nr == 0)
   3146     return false;
   3147 
   3148   add_stmt_to_eh_lp (new_stmt, lp_nr);
   3149   return true;
   3150 }
   3151 
   3152 /* Returns TRUE if oneh and twoh are exception handlers (gimple_try_cleanup of
   3154    GIMPLE_TRY) that are similar enough to be considered the same.  Currently
   3155    this only handles handlers consisting of a single call, as that's the
   3156    important case for C++: a destructor call for a particular object showing
   3157    up in multiple handlers.  */
   3158 
   3159 static bool
   3160 same_handler_p (gimple_seq oneh, gimple_seq twoh)
   3161 {
   3162   gimple_stmt_iterator gsi;
   3163   gimple *ones, *twos;
   3164   unsigned int ai;
   3165 
   3166   gsi = gsi_start (oneh);
   3167   if (!gsi_one_before_end_p (gsi))
   3168     return false;
   3169   ones = gsi_stmt (gsi);
   3170 
   3171   gsi = gsi_start (twoh);
   3172   if (!gsi_one_before_end_p (gsi))
   3173     return false;
   3174   twos = gsi_stmt (gsi);
   3175 
   3176   if (!is_gimple_call (ones)
   3177       || !is_gimple_call (twos)
   3178       || gimple_call_lhs (ones)
   3179       || gimple_call_lhs (twos)
   3180       || gimple_call_chain (ones)
   3181       || gimple_call_chain (twos)
   3182       || !gimple_call_same_target_p (ones, twos)
   3183       || gimple_call_num_args (ones) != gimple_call_num_args (twos))
   3184     return false;
   3185 
   3186   for (ai = 0; ai < gimple_call_num_args (ones); ++ai)
   3187     if (!operand_equal_p (gimple_call_arg (ones, ai),
   3188                           gimple_call_arg (twos, ai), 0))
   3189       return false;
   3190 
   3191   return true;
   3192 }
   3193 
   3194 /* Optimize
   3195     try { A() } finally { try { ~B() } catch { ~A() } }
   3196     try { ... } finally { ~A() }
   3197    into
   3198     try { A() } catch { ~B() }
   3199     try { ~B() ... } finally { ~A() }
   3200 
   3201    This occurs frequently in C++, where A is a local variable and B is a
   3202    temporary used in the initializer for A.  */
   3203 
   3204 static void
   3205 optimize_double_finally (gtry *one, gtry *two)
   3206 {
   3207   gimple *oneh;
   3208   gimple_stmt_iterator gsi;
   3209   gimple_seq cleanup;
   3210 
   3211   cleanup = gimple_try_cleanup (one);
   3212   gsi = gsi_start (cleanup);
   3213   if (!gsi_one_before_end_p (gsi))
   3214     return;
   3215 
   3216   oneh = gsi_stmt (gsi);
   3217   if (gimple_code (oneh) != GIMPLE_TRY
   3218       || gimple_try_kind (oneh) != GIMPLE_TRY_CATCH)
   3219     return;
   3220 
   3221   if (same_handler_p (gimple_try_cleanup (oneh), gimple_try_cleanup (two)))
   3222     {
   3223       gimple_seq seq = gimple_try_eval (oneh);
   3224 
   3225       gimple_try_set_cleanup (one, seq);
   3226       gimple_try_set_kind (one, GIMPLE_TRY_CATCH);
   3227       seq = copy_gimple_seq_and_replace_locals (seq);
   3228       gimple_seq_add_seq (&seq, gimple_try_eval (two));
   3229       gimple_try_set_eval (two, seq);
   3230     }
   3231 }
   3232 
   3233 /* Perform EH refactoring optimizations that are simpler to do when code
   3234    flow has been lowered but EH structures haven't.  */
   3235 
   3236 static void
   3237 refactor_eh_r (gimple_seq seq)
   3238 {
   3239   gimple_stmt_iterator gsi;
   3240   gimple *one, *two;
   3241 
   3242   one = NULL;
   3243   two = NULL;
   3244   gsi = gsi_start (seq);
   3245   while (1)
   3246     {
   3247       one = two;
   3248       if (gsi_end_p (gsi))
   3249 	two = NULL;
   3250       else
   3251 	two = gsi_stmt (gsi);
   3252       if (one && two)
   3253 	if (gtry *try_one = dyn_cast <gtry *> (one))
   3254 	  if (gtry *try_two = dyn_cast <gtry *> (two))
   3255 	    if (gimple_try_kind (try_one) == GIMPLE_TRY_FINALLY
   3256 		&& gimple_try_kind (try_two) == GIMPLE_TRY_FINALLY)
   3257 	      optimize_double_finally (try_one, try_two);
   3258       if (one)
   3259 	switch (gimple_code (one))
   3260 	  {
   3261 	  case GIMPLE_TRY:
   3262 	    refactor_eh_r (gimple_try_eval (one));
   3263 	    refactor_eh_r (gimple_try_cleanup (one));
   3264 	    break;
   3265 	  case GIMPLE_CATCH:
   3266 	    refactor_eh_r (gimple_catch_handler (as_a <gcatch *> (one)));
   3267 	    break;
   3268 	  case GIMPLE_EH_FILTER:
   3269 	    refactor_eh_r (gimple_eh_filter_failure (one));
   3270 	    break;
   3271 	  case GIMPLE_EH_ELSE:
   3272 	    {
   3273 	      geh_else *eh_else_stmt = as_a <geh_else *> (one);
   3274 	      refactor_eh_r (gimple_eh_else_n_body (eh_else_stmt));
   3275 	      refactor_eh_r (gimple_eh_else_e_body (eh_else_stmt));
   3276 	    }
   3277 	    break;
   3278 	  default:
   3279 	    break;
   3280 	  }
   3281       if (two)
   3282 	gsi_next (&gsi);
   3283       else
   3284 	break;
   3285     }
   3286 }
   3287 
   3288 namespace {
   3289 
   3290 const pass_data pass_data_refactor_eh =
   3291 {
   3292   GIMPLE_PASS, /* type */
   3293   "ehopt", /* name */
   3294   OPTGROUP_NONE, /* optinfo_flags */
   3295   TV_TREE_EH, /* tv_id */
   3296   PROP_gimple_lcf, /* properties_required */
   3297   0, /* properties_provided */
   3298   0, /* properties_destroyed */
   3299   0, /* todo_flags_start */
   3300   0, /* todo_flags_finish */
   3301 };
   3302 
   3303 class pass_refactor_eh : public gimple_opt_pass
   3304 {
   3305 public:
   3306   pass_refactor_eh (gcc::context *ctxt)
   3307     : gimple_opt_pass (pass_data_refactor_eh, ctxt)
   3308   {}
   3309 
   3310   /* opt_pass methods: */
   3311   bool gate (function *) final override { return flag_exceptions != 0; }
   3312   unsigned int execute (function *) final override
   3313     {
   3314       refactor_eh_r (gimple_body (current_function_decl));
   3315       return 0;
   3316     }
   3317 
   3318 }; // class pass_refactor_eh
   3319 
   3320 } // anon namespace
   3321 
   3322 gimple_opt_pass *
   3323 make_pass_refactor_eh (gcc::context *ctxt)
   3324 {
   3325   return new pass_refactor_eh (ctxt);
   3326 }
   3327 
   3328 /* At the end of gimple optimization, we can lower RESX.  */
   3330 
   3331 static bool
   3332 lower_resx (basic_block bb, gresx *stmt,
   3333 	    hash_map<eh_region, tree> *mnt_map)
   3334 {
   3335   int lp_nr;
   3336   eh_region src_r, dst_r;
   3337   gimple_stmt_iterator gsi;
   3338   gcall *x;
   3339   tree fn, src_nr;
   3340   bool ret = false;
   3341 
   3342   lp_nr = lookup_stmt_eh_lp (stmt);
   3343   if (lp_nr != 0)
   3344     dst_r = get_eh_region_from_lp_number (lp_nr);
   3345   else
   3346     dst_r = NULL;
   3347 
   3348   src_r = get_eh_region_from_number (gimple_resx_region (stmt));
   3349   gsi = gsi_last_bb (bb);
   3350 
   3351   if (src_r == NULL)
   3352     {
   3353       /* We can wind up with no source region when pass_cleanup_eh shows
   3354 	 that there are no entries into an eh region and deletes it, but
   3355 	 then the block that contains the resx isn't removed.  This can
   3356 	 happen without optimization when the switch statement created by
   3357 	 lower_try_finally_switch isn't simplified to remove the eh case.
   3358 
   3359 	 Resolve this by expanding the resx node to an abort.  */
   3360 
   3361       fn = builtin_decl_implicit (BUILT_IN_TRAP);
   3362       x = gimple_build_call (fn, 0);
   3363       gimple_call_set_ctrl_altering (x, true);
   3364       gsi_insert_before (&gsi, x, GSI_SAME_STMT);
   3365 
   3366       while (EDGE_COUNT (bb->succs) > 0)
   3367 	remove_edge (EDGE_SUCC (bb, 0));
   3368     }
   3369   else if (dst_r)
   3370     {
   3371       /* When we have a destination region, we resolve this by copying
   3372 	 the excptr and filter values into place, and changing the edge
   3373 	 to immediately after the landing pad.  */
   3374       edge e;
   3375 
   3376       if (lp_nr < 0)
   3377 	{
   3378 	  basic_block new_bb;
   3379 	  tree lab;
   3380 
   3381 	  /* We are resuming into a MUST_NOT_CALL region.  Expand a call to
   3382 	     the failure decl into a new block, if needed.  */
   3383 	  gcc_assert (dst_r->type == ERT_MUST_NOT_THROW);
   3384 
   3385 	  tree *slot = mnt_map->get (dst_r);
   3386 	  if (slot == NULL)
   3387 	    {
   3388 	      gimple_stmt_iterator gsi2;
   3389 
   3390 	      new_bb = create_empty_bb (bb);
   3391 	      new_bb->count = bb->count;
   3392 	      add_bb_to_loop (new_bb, bb->loop_father);
   3393 	      lab = gimple_block_label (new_bb);
   3394 	      gsi2 = gsi_start_bb (new_bb);
   3395 
   3396 	      /* Handle failure fns that expect either no arguments or the
   3397 		 exception pointer.  */
   3398 	      fn = dst_r->u.must_not_throw.failure_decl;
   3399 	      if (TYPE_ARG_TYPES (TREE_TYPE (fn)) != void_list_node)
   3400 		{
   3401 		  tree epfn = builtin_decl_implicit (BUILT_IN_EH_POINTER);
   3402 		  src_nr = build_int_cst (integer_type_node, src_r->index);
   3403 		  x = gimple_build_call (epfn, 1, src_nr);
   3404 		  tree var = create_tmp_var (ptr_type_node);
   3405 		  var = make_ssa_name (var, x);
   3406 		  gimple_call_set_lhs (x, var);
   3407 		  gsi_insert_after (&gsi2, x, GSI_CONTINUE_LINKING);
   3408 		  x = gimple_build_call (fn, 1, var);
   3409 		}
   3410 	      else
   3411 		x = gimple_build_call (fn, 0);
   3412 	      gimple_set_location (x, dst_r->u.must_not_throw.failure_loc);
   3413 	      gsi_insert_after (&gsi2, x, GSI_CONTINUE_LINKING);
   3414 
   3415 	      mnt_map->put (dst_r, lab);
   3416 	    }
   3417 	  else
   3418 	    {
   3419 	      lab = *slot;
   3420 	      new_bb = label_to_block (cfun, lab);
   3421 	    }
   3422 
   3423 	  gcc_assert (EDGE_COUNT (bb->succs) == 0);
   3424 	  e = make_single_succ_edge (bb, new_bb, EDGE_FALLTHRU);
   3425 	}
   3426       else
   3427 	{
   3428 	  edge_iterator ei;
   3429 	  tree dst_nr = build_int_cst (integer_type_node, dst_r->index);
   3430 
   3431 	  fn = builtin_decl_implicit (BUILT_IN_EH_COPY_VALUES);
   3432 	  src_nr = build_int_cst (integer_type_node, src_r->index);
   3433 	  x = gimple_build_call (fn, 2, dst_nr, src_nr);
   3434 	  gsi_insert_before (&gsi, x, GSI_SAME_STMT);
   3435 
   3436 	  /* Update the flags for the outgoing edge.  */
   3437 	  e = single_succ_edge (bb);
   3438 	  gcc_assert (e->flags & EDGE_EH);
   3439 	  e->flags = (e->flags & ~EDGE_EH) | EDGE_FALLTHRU;
   3440 	  e->probability = profile_probability::always ();
   3441 
   3442 	  /* If there are no more EH users of the landing pad, delete it.  */
   3443 	  FOR_EACH_EDGE (e, ei, e->dest->preds)
   3444 	    if (e->flags & EDGE_EH)
   3445 	      break;
   3446 	  if (e == NULL)
   3447 	    {
   3448 	      eh_landing_pad lp = get_eh_landing_pad_from_number (lp_nr);
   3449 	      remove_eh_landing_pad (lp);
   3450 	    }
   3451 	}
   3452 
   3453       ret = true;
   3454     }
   3455   else
   3456     {
   3457       tree var;
   3458 
   3459       /* When we don't have a destination region, this exception escapes
   3460 	 up the call chain.  We resolve this by generating a call to the
   3461 	 _Unwind_Resume library function.  */
   3462 
   3463       /* The ARM EABI redefines _Unwind_Resume as __cxa_end_cleanup
   3464 	 with no arguments for C++.  Check for that.  */
   3465       if (src_r->use_cxa_end_cleanup)
   3466 	{
   3467 	  fn = builtin_decl_implicit (BUILT_IN_CXA_END_CLEANUP);
   3468 	  x = gimple_build_call (fn, 0);
   3469 	  gsi_insert_before (&gsi, x, GSI_SAME_STMT);
   3470 	}
   3471       else
   3472 	{
   3473 	  fn = builtin_decl_implicit (BUILT_IN_EH_POINTER);
   3474 	  src_nr = build_int_cst (integer_type_node, src_r->index);
   3475 	  x = gimple_build_call (fn, 1, src_nr);
   3476 	  var = create_tmp_var (ptr_type_node);
   3477 	  var = make_ssa_name (var, x);
   3478 	  gimple_call_set_lhs (x, var);
   3479 	  gsi_insert_before (&gsi, x, GSI_SAME_STMT);
   3480 
   3481 	  /* When exception handling is delegated to a caller function, we
   3482 	     have to guarantee that shadow memory variables living on stack
   3483 	     will be cleaner before control is given to a parent function.  */
   3484 	  if (sanitize_flags_p (SANITIZE_ADDRESS))
   3485 	    {
   3486 	      tree decl
   3487 		= builtin_decl_implicit (BUILT_IN_ASAN_HANDLE_NO_RETURN);
   3488 	      gimple *g = gimple_build_call (decl, 0);
   3489 	      gimple_set_location (g, gimple_location (stmt));
   3490 	      gsi_insert_before (&gsi, g, GSI_SAME_STMT);
   3491 	    }
   3492 
   3493 	  fn = builtin_decl_implicit (BUILT_IN_UNWIND_RESUME);
   3494 	  x = gimple_build_call (fn, 1, var);
   3495 	  gimple_call_set_ctrl_altering (x, true);
   3496 	  gsi_insert_before (&gsi, x, GSI_SAME_STMT);
   3497 	}
   3498 
   3499       gcc_assert (EDGE_COUNT (bb->succs) == 0);
   3500     }
   3501 
   3502   gsi_remove (&gsi, true);
   3503 
   3504   return ret;
   3505 }
   3506 
   3507 namespace {
   3508 
   3509 const pass_data pass_data_lower_resx =
   3510 {
   3511   GIMPLE_PASS, /* type */
   3512   "resx", /* name */
   3513   OPTGROUP_NONE, /* optinfo_flags */
   3514   TV_TREE_EH, /* tv_id */
   3515   PROP_gimple_lcf, /* properties_required */
   3516   0, /* properties_provided */
   3517   0, /* properties_destroyed */
   3518   0, /* todo_flags_start */
   3519   0, /* todo_flags_finish */
   3520 };
   3521 
   3522 class pass_lower_resx : public gimple_opt_pass
   3523 {
   3524 public:
   3525   pass_lower_resx (gcc::context *ctxt)
   3526     : gimple_opt_pass (pass_data_lower_resx, ctxt)
   3527   {}
   3528 
   3529   /* opt_pass methods: */
   3530   bool gate (function *) final override { return flag_exceptions != 0; }
   3531   unsigned int execute (function *) final override;
   3532 
   3533 }; // class pass_lower_resx
   3534 
   3535 unsigned
   3536 pass_lower_resx::execute (function *fun)
   3537 {
   3538   basic_block bb;
   3539   bool dominance_invalidated = false;
   3540   bool any_rewritten = false;
   3541 
   3542   hash_map<eh_region, tree> mnt_map;
   3543 
   3544   FOR_EACH_BB_FN (bb, fun)
   3545     {
   3546       if (gresx *last = safe_dyn_cast <gresx *> (*gsi_last_bb (bb)))
   3547 	{
   3548 	  dominance_invalidated |= lower_resx (bb, last, &mnt_map);
   3549 	  any_rewritten = true;
   3550 	}
   3551     }
   3552 
   3553   if (dominance_invalidated)
   3554     {
   3555       free_dominance_info (CDI_DOMINATORS);
   3556       free_dominance_info (CDI_POST_DOMINATORS);
   3557     }
   3558 
   3559   return any_rewritten ? TODO_update_ssa_only_virtuals : 0;
   3560 }
   3561 
   3562 } // anon namespace
   3563 
   3564 gimple_opt_pass *
   3565 make_pass_lower_resx (gcc::context *ctxt)
   3566 {
   3567   return new pass_lower_resx (ctxt);
   3568 }
   3569 
   3570 /* Try to optimize var = {v} {CLOBBER} stmts followed just by
   3571    external throw.  */
   3572 
   3573 static void
   3574 optimize_clobbers (basic_block bb)
   3575 {
   3576   gimple_stmt_iterator gsi = gsi_last_bb (bb);
   3577   bool any_clobbers = false;
   3578   bool seen_stack_restore = false;
   3579   edge_iterator ei;
   3580   edge e;
   3581 
   3582   /* Only optimize anything if the bb contains at least one clobber,
   3583      ends with resx (checked by caller), optionally contains some
   3584      debug stmts or labels, or at most one __builtin_stack_restore
   3585      call, and has an incoming EH edge.  */
   3586   for (gsi_prev (&gsi); !gsi_end_p (gsi); gsi_prev (&gsi))
   3587     {
   3588       gimple *stmt = gsi_stmt (gsi);
   3589       if (is_gimple_debug (stmt))
   3590 	continue;
   3591       if (gimple_clobber_p (stmt))
   3592 	{
   3593 	  any_clobbers = true;
   3594 	  continue;
   3595 	}
   3596       if (!seen_stack_restore
   3597 	  && gimple_call_builtin_p (stmt, BUILT_IN_STACK_RESTORE))
   3598 	{
   3599 	  seen_stack_restore = true;
   3600 	  continue;
   3601 	}
   3602       if (gimple_code (stmt) == GIMPLE_LABEL)
   3603 	break;
   3604       return;
   3605     }
   3606   if (!any_clobbers)
   3607     return;
   3608   FOR_EACH_EDGE (e, ei, bb->preds)
   3609     if (e->flags & EDGE_EH)
   3610       break;
   3611   if (e == NULL)
   3612     return;
   3613   gsi = gsi_last_bb (bb);
   3614   for (gsi_prev (&gsi); !gsi_end_p (gsi); gsi_prev (&gsi))
   3615     {
   3616       gimple *stmt = gsi_stmt (gsi);
   3617       if (!gimple_clobber_p (stmt))
   3618 	continue;
   3619       unlink_stmt_vdef (stmt);
   3620       gsi_remove (&gsi, true);
   3621       release_defs (stmt);
   3622     }
   3623 }
   3624 
   3625 /* Try to sink var = {v} {CLOBBER} stmts followed just by
   3626    internal throw to successor BB.
   3627    SUNK, if not NULL, is an array of sequences indexed by basic-block
   3628    index to sink to and to pick up sinking opportunities from.
   3629    If FOUND_OPPORTUNITY is not NULL then do not perform the optimization
   3630    but set *FOUND_OPPORTUNITY to true.  */
   3631 
   3632 static int
   3633 sink_clobbers (basic_block bb,
   3634 	       gimple_seq *sunk = NULL, bool *found_opportunity = NULL)
   3635 {
   3636   edge e;
   3637   edge_iterator ei;
   3638   gimple_stmt_iterator gsi, dgsi;
   3639   basic_block succbb;
   3640   bool any_clobbers = false;
   3641   unsigned todo = 0;
   3642 
   3643   /* Only optimize if BB has a single EH successor and
   3644      all predecessor edges are EH too.  */
   3645   if (!single_succ_p (bb)
   3646       || (single_succ_edge (bb)->flags & EDGE_EH) == 0)
   3647     return 0;
   3648 
   3649   FOR_EACH_EDGE (e, ei, bb->preds)
   3650     {
   3651       if ((e->flags & EDGE_EH) == 0)
   3652 	return 0;
   3653     }
   3654 
   3655   /* And BB contains only CLOBBER stmts before the final
   3656      RESX.  */
   3657   gsi = gsi_last_bb (bb);
   3658   for (gsi_prev (&gsi); !gsi_end_p (gsi); gsi_prev (&gsi))
   3659     {
   3660       gimple *stmt = gsi_stmt (gsi);
   3661       if (is_gimple_debug (stmt))
   3662 	continue;
   3663       if (gimple_code (stmt) == GIMPLE_LABEL)
   3664 	break;
   3665       if (!gimple_clobber_p (stmt))
   3666 	return 0;
   3667       any_clobbers = true;
   3668     }
   3669   if (!any_clobbers && (!sunk || gimple_seq_empty_p (sunk[bb->index])))
   3670     return 0;
   3671 
   3672   /* If this was a dry run, tell it we found clobbers to sink.  */
   3673   if (found_opportunity)
   3674     {
   3675       *found_opportunity = true;
   3676       return 0;
   3677     }
   3678 
   3679   edge succe = single_succ_edge (bb);
   3680   succbb = succe->dest;
   3681 
   3682   /* See if there is a virtual PHI node to take an updated virtual
   3683      operand from.  */
   3684   gphi *vphi = NULL;
   3685   for (gphi_iterator gpi = gsi_start_phis (succbb);
   3686        !gsi_end_p (gpi); gsi_next (&gpi))
   3687     {
   3688       tree res = gimple_phi_result (gpi.phi ());
   3689       if (virtual_operand_p (res))
   3690 	{
   3691 	  vphi = gpi.phi ();
   3692 	  break;
   3693 	}
   3694     }
   3695 
   3696   gimple *first_sunk = NULL;
   3697   gimple *last_sunk = NULL;
   3698   if (sunk && !(succbb->flags & BB_VISITED))
   3699     dgsi = gsi_start (sunk[succbb->index]);
   3700   else
   3701     dgsi = gsi_after_labels (succbb);
   3702   gsi = gsi_last_bb (bb);
   3703   for (gsi_prev (&gsi); !gsi_end_p (gsi); gsi_prev (&gsi))
   3704     {
   3705       gimple *stmt = gsi_stmt (gsi);
   3706       tree lhs;
   3707       if (is_gimple_debug (stmt))
   3708 	continue;
   3709       if (gimple_code (stmt) == GIMPLE_LABEL)
   3710 	break;
   3711       lhs = gimple_assign_lhs (stmt);
   3712       /* Unfortunately we don't have dominance info updated at this
   3713 	 point, so checking if
   3714 	 dominated_by_p (CDI_DOMINATORS, succbb,
   3715 			 gimple_bb (SSA_NAME_DEF_STMT (TREE_OPERAND (lhs, 0)))
   3716 	 would be too costly.  Thus, avoid sinking any clobbers that
   3717 	 refer to non-(D) SSA_NAMEs.  */
   3718       if (TREE_CODE (lhs) == MEM_REF
   3719 	  && TREE_CODE (TREE_OPERAND (lhs, 0)) == SSA_NAME
   3720 	  && !SSA_NAME_IS_DEFAULT_DEF (TREE_OPERAND (lhs, 0)))
   3721 	{
   3722 	  unlink_stmt_vdef (stmt);
   3723 	  gsi_remove (&gsi, true);
   3724 	  release_defs (stmt);
   3725 	  continue;
   3726 	}
   3727 
   3728       /* As we do not change stmt order when sinking across a
   3729          forwarder edge we can keep virtual operands in place.  */
   3730       gsi_remove (&gsi, false);
   3731       gsi_insert_before (&dgsi, stmt, GSI_NEW_STMT);
   3732       if (!first_sunk)
   3733 	first_sunk = stmt;
   3734       last_sunk = stmt;
   3735     }
   3736   if (sunk && !gimple_seq_empty_p (sunk[bb->index]))
   3737     {
   3738       if (!first_sunk)
   3739 	first_sunk = gsi_stmt (gsi_last (sunk[bb->index]));
   3740       last_sunk = gsi_stmt (gsi_start (sunk[bb->index]));
   3741       gsi_insert_seq_before_without_update (&dgsi,
   3742 					    sunk[bb->index], GSI_NEW_STMT);
   3743       sunk[bb->index] = NULL;
   3744     }
   3745   if (first_sunk)
   3746     {
   3747       /* Adjust virtual operands if we sunk across a virtual PHI.  */
   3748       if (vphi)
   3749 	{
   3750 	  imm_use_iterator iter;
   3751 	  use_operand_p use_p;
   3752 	  gimple *use_stmt;
   3753 	  tree phi_def = gimple_phi_result (vphi);
   3754 	  FOR_EACH_IMM_USE_STMT (use_stmt, iter, phi_def)
   3755 	    FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
   3756               SET_USE (use_p, gimple_vdef (first_sunk));
   3757 	  if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (phi_def))
   3758 	    {
   3759 	      SSA_NAME_OCCURS_IN_ABNORMAL_PHI (gimple_vdef (first_sunk)) = 1;
   3760 	      SSA_NAME_OCCURS_IN_ABNORMAL_PHI (phi_def) = 0;
   3761 	    }
   3762 	  SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (vphi, succe),
   3763 		   gimple_vuse (last_sunk));
   3764 	  SET_USE (gimple_vuse_op (last_sunk), phi_def);
   3765 	}
   3766       /* If there isn't a single predecessor but no virtual PHI node
   3767          arrange for virtual operands to be renamed.  */
   3768       else if (!single_pred_p (succbb)
   3769 	       && TREE_CODE (gimple_vuse (last_sunk)) == SSA_NAME)
   3770 	{
   3771 	  mark_virtual_operand_for_renaming (gimple_vuse (last_sunk));
   3772 	  todo |= TODO_update_ssa_only_virtuals;
   3773 	}
   3774     }
   3775 
   3776   return todo;
   3777 }
   3778 
   3779 /* At the end of inlining, we can lower EH_DISPATCH.  Return true when
   3780    we have found some duplicate labels and removed some edges.  */
   3781 
   3782 static bool
   3783 lower_eh_dispatch (basic_block src, geh_dispatch *stmt)
   3784 {
   3785   gimple_stmt_iterator gsi;
   3786   int region_nr;
   3787   eh_region r;
   3788   tree filter, fn;
   3789   gimple *x;
   3790   bool redirected = false;
   3791 
   3792   region_nr = gimple_eh_dispatch_region (stmt);
   3793   r = get_eh_region_from_number (region_nr);
   3794 
   3795   gsi = gsi_last_bb (src);
   3796 
   3797   switch (r->type)
   3798     {
   3799     case ERT_TRY:
   3800       {
   3801 	auto_vec<tree> labels;
   3802 	tree default_label = NULL;
   3803 	eh_catch c;
   3804 	edge_iterator ei;
   3805 	edge e;
   3806 	hash_set<tree> seen_values;
   3807 
   3808 	/* Collect the labels for a switch.  Zero the post_landing_pad
   3809 	   field becase we'll no longer have anything keeping these labels
   3810 	   in existence and the optimizer will be free to merge these
   3811 	   blocks at will.  */
   3812 	for (c = r->u.eh_try.first_catch; c ; c = c->next_catch)
   3813 	  {
   3814 	    tree tp_node, flt_node, lab = c->label;
   3815 	    bool have_label = false;
   3816 
   3817 	    c->label = NULL;
   3818 	    tp_node = c->type_list;
   3819 	    flt_node = c->filter_list;
   3820 
   3821 	    if (tp_node == NULL)
   3822 	      {
   3823 	        default_label = lab;
   3824 		break;
   3825 	      }
   3826 	    do
   3827 	      {
   3828 		/* Filter out duplicate labels that arise when this handler
   3829 		   is shadowed by an earlier one.  When no labels are
   3830 		   attached to the handler anymore, we remove
   3831 		   the corresponding edge and then we delete unreachable
   3832 		   blocks at the end of this pass.  */
   3833 		if (! seen_values.contains (TREE_VALUE (flt_node)))
   3834 		  {
   3835 		    tree t = build_case_label (TREE_VALUE (flt_node),
   3836 					       NULL, lab);
   3837 		    labels.safe_push (t);
   3838 		    seen_values.add (TREE_VALUE (flt_node));
   3839 		    have_label = true;
   3840 		  }
   3841 
   3842 		tp_node = TREE_CHAIN (tp_node);
   3843 		flt_node = TREE_CHAIN (flt_node);
   3844 	      }
   3845 	    while (tp_node);
   3846 	    if (! have_label)
   3847 	      {
   3848 		remove_edge (find_edge (src, label_to_block (cfun, lab)));
   3849 	        redirected = true;
   3850 	      }
   3851 	  }
   3852 
   3853 	/* Clean up the edge flags.  */
   3854 	FOR_EACH_EDGE (e, ei, src->succs)
   3855 	  {
   3856 	    if (e->flags & EDGE_FALLTHRU)
   3857 	      {
   3858 		/* If there was no catch-all, use the fallthru edge.  */
   3859 		if (default_label == NULL)
   3860 		  default_label = gimple_block_label (e->dest);
   3861 		e->flags &= ~EDGE_FALLTHRU;
   3862 	      }
   3863 	  }
   3864 	gcc_assert (default_label != NULL);
   3865 
   3866 	/* Don't generate a switch if there's only a default case.
   3867 	   This is common in the form of try { A; } catch (...) { B; }.  */
   3868 	if (!labels.exists ())
   3869 	  {
   3870 	    e = single_succ_edge (src);
   3871 	    e->flags |= EDGE_FALLTHRU;
   3872 	  }
   3873 	else
   3874 	  {
   3875 	    fn = builtin_decl_implicit (BUILT_IN_EH_FILTER);
   3876 	    x = gimple_build_call (fn, 1, build_int_cst (integer_type_node,
   3877 							 region_nr));
   3878 	    filter = create_tmp_var (TREE_TYPE (TREE_TYPE (fn)));
   3879 	    filter = make_ssa_name (filter, x);
   3880 	    gimple_call_set_lhs (x, filter);
   3881 	    gimple_set_location (x, gimple_location (stmt));
   3882 	    gsi_insert_before (&gsi, x, GSI_SAME_STMT);
   3883 
   3884 	    /* Turn the default label into a default case.  */
   3885 	    default_label = build_case_label (NULL, NULL, default_label);
   3886 	    sort_case_labels (labels);
   3887 
   3888 	    x = gimple_build_switch (filter, default_label, labels);
   3889 	    gimple_set_location (x, gimple_location (stmt));
   3890 	    gsi_insert_before (&gsi, x, GSI_SAME_STMT);
   3891 	  }
   3892       }
   3893       break;
   3894 
   3895     case ERT_ALLOWED_EXCEPTIONS:
   3896       {
   3897 	edge b_e = BRANCH_EDGE (src);
   3898 	edge f_e = FALLTHRU_EDGE (src);
   3899 
   3900 	fn = builtin_decl_implicit (BUILT_IN_EH_FILTER);
   3901 	x = gimple_build_call (fn, 1, build_int_cst (integer_type_node,
   3902 						     region_nr));
   3903 	filter = create_tmp_var (TREE_TYPE (TREE_TYPE (fn)));
   3904 	filter = make_ssa_name (filter, x);
   3905 	gimple_call_set_lhs (x, filter);
   3906 	gimple_set_location (x, gimple_location (stmt));
   3907 	gsi_insert_before (&gsi, x, GSI_SAME_STMT);
   3908 
   3909 	r->u.allowed.label = NULL;
   3910 	x = gimple_build_cond (EQ_EXPR, filter,
   3911 			       build_int_cst (TREE_TYPE (filter),
   3912 					      r->u.allowed.filter),
   3913 			       NULL_TREE, NULL_TREE);
   3914 	gsi_insert_before (&gsi, x, GSI_SAME_STMT);
   3915 
   3916 	b_e->flags = b_e->flags | EDGE_TRUE_VALUE;
   3917         f_e->flags = (f_e->flags & ~EDGE_FALLTHRU) | EDGE_FALSE_VALUE;
   3918       }
   3919       break;
   3920 
   3921     default:
   3922       gcc_unreachable ();
   3923     }
   3924 
   3925   /* Replace the EH_DISPATCH with the SWITCH or COND generated above.  */
   3926   gsi_remove (&gsi, true);
   3927   return redirected;
   3928 }
   3929 
   3930 namespace {
   3931 
   3932 const pass_data pass_data_lower_eh_dispatch =
   3933 {
   3934   GIMPLE_PASS, /* type */
   3935   "ehdisp", /* name */
   3936   OPTGROUP_NONE, /* optinfo_flags */
   3937   TV_TREE_EH, /* tv_id */
   3938   PROP_gimple_lcf, /* properties_required */
   3939   0, /* properties_provided */
   3940   0, /* properties_destroyed */
   3941   0, /* todo_flags_start */
   3942   0, /* todo_flags_finish */
   3943 };
   3944 
   3945 class pass_lower_eh_dispatch : public gimple_opt_pass
   3946 {
   3947 public:
   3948   pass_lower_eh_dispatch (gcc::context *ctxt)
   3949     : gimple_opt_pass (pass_data_lower_eh_dispatch, ctxt)
   3950   {}
   3951 
   3952   /* opt_pass methods: */
   3953   bool gate (function *fun) final override
   3954   {
   3955     return fun->eh->region_tree != NULL;
   3956   }
   3957   unsigned int execute (function *) final override;
   3958 
   3959 }; // class pass_lower_eh_dispatch
   3960 
   3961 unsigned
   3962 pass_lower_eh_dispatch::execute (function *fun)
   3963 {
   3964   basic_block bb;
   3965   int flags = 0;
   3966   bool redirected = false;
   3967   bool any_resx_to_process = false;
   3968 
   3969   assign_filter_values ();
   3970 
   3971   FOR_EACH_BB_FN (bb, fun)
   3972     {
   3973       gimple *last = *gsi_last_bb (bb);
   3974       if (last == NULL)
   3975 	continue;
   3976       if (gimple_code (last) == GIMPLE_EH_DISPATCH)
   3977 	{
   3978 	  redirected |= lower_eh_dispatch (bb,
   3979 					   as_a <geh_dispatch *> (last));
   3980 	  flags |= TODO_update_ssa_only_virtuals;
   3981 	}
   3982       else if (gimple_code (last) == GIMPLE_RESX)
   3983 	{
   3984 	  if (stmt_can_throw_external (fun, last))
   3985 	    optimize_clobbers (bb);
   3986 	  else if (!any_resx_to_process)
   3987 	    sink_clobbers (bb, NULL, &any_resx_to_process);
   3988 	}
   3989       bb->flags &= ~BB_VISITED;
   3990     }
   3991   if (redirected)
   3992     {
   3993       free_dominance_info (CDI_DOMINATORS);
   3994       delete_unreachable_blocks ();
   3995     }
   3996 
   3997   if (any_resx_to_process)
   3998     {
   3999       /* Make sure to catch all secondary sinking opportunities by processing
   4000 	 blocks in RPO order and after all CFG modifications from lowering
   4001 	 and unreachable block removal.  */
   4002       int *rpo = XNEWVEC  (int, n_basic_blocks_for_fn (fun));
   4003       int rpo_n = pre_and_rev_post_order_compute_fn (fun, NULL, rpo, false);
   4004       gimple_seq *sunk = XCNEWVEC (gimple_seq, last_basic_block_for_fn (fun));
   4005       for (int i = 0; i < rpo_n; ++i)
   4006 	{
   4007 	  bb = BASIC_BLOCK_FOR_FN (fun, rpo[i]);
   4008 	  gimple *last = *gsi_last_bb (bb);
   4009 	  if (last
   4010 	      && gimple_code (last) == GIMPLE_RESX
   4011 	      && !stmt_can_throw_external (fun, last))
   4012 	    flags |= sink_clobbers (bb, sunk);
   4013 	  /* If there were any clobbers sunk into this BB, insert them now.  */
   4014 	  if (!gimple_seq_empty_p (sunk[bb->index]))
   4015 	    {
   4016 	      gimple_stmt_iterator gsi = gsi_after_labels (bb);
   4017 	      gsi_insert_seq_before (&gsi, sunk[bb->index], GSI_NEW_STMT);
   4018 	      sunk[bb->index] = NULL;
   4019 	    }
   4020 	  bb->flags |= BB_VISITED;
   4021 	}
   4022       free (rpo);
   4023       free (sunk);
   4024     }
   4025 
   4026   return flags;
   4027 }
   4028 
   4029 } // anon namespace
   4030 
   4031 gimple_opt_pass *
   4032 make_pass_lower_eh_dispatch (gcc::context *ctxt)
   4033 {
   4034   return new pass_lower_eh_dispatch (ctxt);
   4035 }
   4036 
   4037 /* Walk statements, see what regions and, optionally, landing pads
   4039    are really referenced.
   4040 
   4041    Returns in R_REACHABLEP an sbitmap with bits set for reachable regions,
   4042    and in LP_REACHABLE an sbitmap with bits set for reachable landing pads.
   4043 
   4044    Passing NULL for LP_REACHABLE is valid, in this case only reachable
   4045    regions are marked.
   4046 
   4047    The caller is responsible for freeing the returned sbitmaps.  */
   4048 
   4049 static void
   4050 mark_reachable_handlers (sbitmap *r_reachablep, sbitmap *lp_reachablep)
   4051 {
   4052   sbitmap r_reachable, lp_reachable;
   4053   basic_block bb;
   4054   bool mark_landing_pads = (lp_reachablep != NULL);
   4055   gcc_checking_assert (r_reachablep != NULL);
   4056 
   4057   r_reachable = sbitmap_alloc (cfun->eh->region_array->length ());
   4058   bitmap_clear (r_reachable);
   4059   *r_reachablep = r_reachable;
   4060 
   4061   if (mark_landing_pads)
   4062     {
   4063       lp_reachable = sbitmap_alloc (cfun->eh->lp_array->length ());
   4064       bitmap_clear (lp_reachable);
   4065       *lp_reachablep = lp_reachable;
   4066     }
   4067   else
   4068     lp_reachable = NULL;
   4069 
   4070   FOR_EACH_BB_FN (bb, cfun)
   4071     {
   4072       gimple_stmt_iterator gsi;
   4073 
   4074       for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
   4075 	{
   4076 	  gimple *stmt = gsi_stmt (gsi);
   4077 
   4078 	  if (mark_landing_pads)
   4079 	    {
   4080 	      int lp_nr = lookup_stmt_eh_lp (stmt);
   4081 
   4082 	      /* Negative LP numbers are MUST_NOT_THROW regions which
   4083 		 are not considered BB enders.  */
   4084 	      if (lp_nr < 0)
   4085 		bitmap_set_bit (r_reachable, -lp_nr);
   4086 
   4087 	      /* Positive LP numbers are real landing pads, and BB enders.  */
   4088 	      else if (lp_nr > 0)
   4089 		{
   4090 		  gcc_assert (gsi_one_before_end_p (gsi));
   4091 		  eh_region region = get_eh_region_from_lp_number (lp_nr);
   4092 		  bitmap_set_bit (r_reachable, region->index);
   4093 		  bitmap_set_bit (lp_reachable, lp_nr);
   4094 		}
   4095 	    }
   4096 
   4097 	  /* Avoid removing regions referenced from RESX/EH_DISPATCH.  */
   4098 	  switch (gimple_code (stmt))
   4099 	    {
   4100 	    case GIMPLE_RESX:
   4101 	      bitmap_set_bit (r_reachable,
   4102 			      gimple_resx_region (as_a <gresx *> (stmt)));
   4103 	      break;
   4104 	    case GIMPLE_EH_DISPATCH:
   4105 	      bitmap_set_bit (r_reachable,
   4106 			      gimple_eh_dispatch_region (
   4107                                 as_a <geh_dispatch *> (stmt)));
   4108 	      break;
   4109 	    case GIMPLE_CALL:
   4110 	      if (gimple_call_builtin_p (stmt, BUILT_IN_EH_COPY_VALUES))
   4111 		for (int i = 0; i < 2; ++i)
   4112 		  {
   4113 		    tree rt = gimple_call_arg (stmt, i);
   4114 		    HOST_WIDE_INT ri = tree_to_shwi (rt);
   4115 
   4116 		    gcc_assert (ri == (int)ri);
   4117 		    bitmap_set_bit (r_reachable, ri);
   4118 		  }
   4119 	      break;
   4120 	    default:
   4121 	      break;
   4122 	    }
   4123 	}
   4124     }
   4125 }
   4126 
   4127 /* Remove unreachable handlers and unreachable landing pads.  */
   4128 
   4129 static void
   4130 remove_unreachable_handlers (void)
   4131 {
   4132   sbitmap r_reachable, lp_reachable;
   4133   eh_region region;
   4134   eh_landing_pad lp;
   4135   unsigned i;
   4136 
   4137   mark_reachable_handlers (&r_reachable, &lp_reachable);
   4138 
   4139   if (dump_file)
   4140     {
   4141       fprintf (dump_file, "Before removal of unreachable regions:\n");
   4142       dump_eh_tree (dump_file, cfun);
   4143       fprintf (dump_file, "Reachable regions: ");
   4144       dump_bitmap_file (dump_file, r_reachable);
   4145       fprintf (dump_file, "Reachable landing pads: ");
   4146       dump_bitmap_file (dump_file, lp_reachable);
   4147     }
   4148 
   4149   if (dump_file)
   4150     {
   4151       FOR_EACH_VEC_SAFE_ELT (cfun->eh->region_array, i, region)
   4152 	if (region && !bitmap_bit_p (r_reachable, region->index))
   4153 	  fprintf (dump_file,
   4154 		   "Removing unreachable region %d\n",
   4155 		   region->index);
   4156     }
   4157 
   4158   remove_unreachable_eh_regions (r_reachable);
   4159 
   4160   FOR_EACH_VEC_SAFE_ELT (cfun->eh->lp_array, i, lp)
   4161     if (lp && !bitmap_bit_p (lp_reachable, lp->index))
   4162       {
   4163 	if (dump_file)
   4164 	  fprintf (dump_file,
   4165 		   "Removing unreachable landing pad %d\n",
   4166 		   lp->index);
   4167 	remove_eh_landing_pad (lp);
   4168       }
   4169 
   4170   if (dump_file)
   4171     {
   4172       fprintf (dump_file, "\n\nAfter removal of unreachable regions:\n");
   4173       dump_eh_tree (dump_file, cfun);
   4174       fprintf (dump_file, "\n\n");
   4175     }
   4176 
   4177   sbitmap_free (r_reachable);
   4178   sbitmap_free (lp_reachable);
   4179 
   4180   if (flag_checking)
   4181     verify_eh_tree (cfun);
   4182 }
   4183 
   4184 /* Remove unreachable handlers if any landing pads have been removed after
   4185    last ehcleanup pass (due to gimple_purge_dead_eh_edges).  */
   4186 
   4187 void
   4188 maybe_remove_unreachable_handlers (void)
   4189 {
   4190   eh_landing_pad lp;
   4191   unsigned i;
   4192 
   4193   if (cfun->eh == NULL)
   4194     return;
   4195 
   4196   FOR_EACH_VEC_SAFE_ELT (cfun->eh->lp_array, i, lp)
   4197     if (lp
   4198 	&& (lp->post_landing_pad == NULL_TREE
   4199 	    || label_to_block (cfun, lp->post_landing_pad) == NULL))
   4200       {
   4201 	remove_unreachable_handlers ();
   4202 	return;
   4203       }
   4204 }
   4205 
   4206 /* Remove regions that do not have landing pads.  This assumes
   4207    that remove_unreachable_handlers has already been run, and
   4208    that we've just manipulated the landing pads since then.
   4209 
   4210    Preserve regions with landing pads and regions that prevent
   4211    exceptions from propagating further, even if these regions
   4212    are not reachable.  */
   4213 
   4214 static void
   4215 remove_unreachable_handlers_no_lp (void)
   4216 {
   4217   eh_region region;
   4218   sbitmap r_reachable;
   4219   unsigned i;
   4220 
   4221   mark_reachable_handlers (&r_reachable, /*lp_reachablep=*/NULL);
   4222 
   4223   FOR_EACH_VEC_SAFE_ELT (cfun->eh->region_array, i, region)
   4224     {
   4225       if (! region)
   4226 	continue;
   4227 
   4228       if (region->landing_pads != NULL
   4229 	  || region->type == ERT_MUST_NOT_THROW)
   4230 	bitmap_set_bit (r_reachable, region->index);
   4231 
   4232       if (dump_file
   4233 	  && !bitmap_bit_p (r_reachable, region->index))
   4234 	fprintf (dump_file,
   4235 		 "Removing unreachable region %d\n",
   4236 		 region->index);
   4237     }
   4238 
   4239   remove_unreachable_eh_regions (r_reachable);
   4240 
   4241   sbitmap_free (r_reachable);
   4242 }
   4243 
   4244 /* Undo critical edge splitting on an EH landing pad.  Earlier, we
   4245    optimisticaly split all sorts of edges, including EH edges.  The
   4246    optimization passes in between may not have needed them; if not,
   4247    we should undo the split.
   4248 
   4249    Recognize this case by having one EH edge incoming to the BB and
   4250    one normal edge outgoing; BB should be empty apart from the
   4251    post_landing_pad label.
   4252 
   4253    Note that this is slightly different from the empty handler case
   4254    handled by cleanup_empty_eh, in that the actual handler may yet
   4255    have actual code but the landing pad has been separated from the
   4256    handler.  As such, cleanup_empty_eh relies on this transformation
   4257    having been done first.  */
   4258 
   4259 static bool
   4260 unsplit_eh (eh_landing_pad lp)
   4261 {
   4262   basic_block bb = label_to_block (cfun, lp->post_landing_pad);
   4263   gimple_stmt_iterator gsi;
   4264   edge e_in, e_out;
   4265 
   4266   /* Quickly check the edge counts on BB for singularity.  */
   4267   if (!single_pred_p (bb) || !single_succ_p (bb))
   4268     return false;
   4269   e_in = single_pred_edge (bb);
   4270   e_out = single_succ_edge (bb);
   4271 
   4272   /* Input edge must be EH and output edge must be normal.  */
   4273   if ((e_in->flags & EDGE_EH) == 0 || (e_out->flags & EDGE_EH) != 0)
   4274     return false;
   4275 
   4276   /* The block must be empty except for the labels and debug insns.  */
   4277   gsi = gsi_after_labels (bb);
   4278   if (!gsi_end_p (gsi) && is_gimple_debug (gsi_stmt (gsi)))
   4279     gsi_next_nondebug (&gsi);
   4280   if (!gsi_end_p (gsi))
   4281     return false;
   4282 
   4283   /* The destination block must not already have a landing pad
   4284      for a different region.  */
   4285   for (gsi = gsi_start_bb (e_out->dest); !gsi_end_p (gsi); gsi_next (&gsi))
   4286     {
   4287       glabel *label_stmt = dyn_cast <glabel *> (gsi_stmt (gsi));
   4288       tree lab;
   4289       int lp_nr;
   4290 
   4291       if (!label_stmt)
   4292 	break;
   4293       lab = gimple_label_label (label_stmt);
   4294       lp_nr = EH_LANDING_PAD_NR (lab);
   4295       if (lp_nr && get_eh_region_from_lp_number (lp_nr) != lp->region)
   4296 	return false;
   4297     }
   4298 
   4299   /* The new destination block must not already be a destination of
   4300      the source block, lest we merge fallthru and eh edges and get
   4301      all sorts of confused.  */
   4302   if (find_edge (e_in->src, e_out->dest))
   4303     return false;
   4304 
   4305   /* ??? We can get degenerate phis due to cfg cleanups.  I would have
   4306      thought this should have been cleaned up by a phicprop pass, but
   4307      that doesn't appear to handle virtuals.  Propagate by hand.  */
   4308   if (!gimple_seq_empty_p (phi_nodes (bb)))
   4309     {
   4310       for (gphi_iterator gpi = gsi_start_phis (bb); !gsi_end_p (gpi); )
   4311 	{
   4312 	  gimple *use_stmt;
   4313 	  gphi *phi = gpi.phi ();
   4314 	  tree lhs = gimple_phi_result (phi);
   4315 	  tree rhs = gimple_phi_arg_def (phi, 0);
   4316 	  use_operand_p use_p;
   4317 	  imm_use_iterator iter;
   4318 
   4319 	  FOR_EACH_IMM_USE_STMT (use_stmt, iter, lhs)
   4320 	    {
   4321 	      FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
   4322 		SET_USE (use_p, rhs);
   4323 	    }
   4324 
   4325 	  if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (lhs))
   4326 	    SSA_NAME_OCCURS_IN_ABNORMAL_PHI (rhs) = 1;
   4327 
   4328 	  remove_phi_node (&gpi, true);
   4329 	}
   4330     }
   4331 
   4332   if (dump_file && (dump_flags & TDF_DETAILS))
   4333     fprintf (dump_file, "Unsplit EH landing pad %d to block %i.\n",
   4334 	     lp->index, e_out->dest->index);
   4335 
   4336   /* Redirect the edge.  Since redirect_eh_edge_1 expects to be moving
   4337      a successor edge, humor it.  But do the real CFG change with the
   4338      predecessor of E_OUT in order to preserve the ordering of arguments
   4339      to the PHI nodes in E_OUT->DEST.  */
   4340   redirect_eh_edge_1 (e_in, e_out->dest, false);
   4341   redirect_edge_pred (e_out, e_in->src);
   4342   e_out->flags = e_in->flags;
   4343   e_out->probability = e_in->probability;
   4344   remove_edge (e_in);
   4345 
   4346   return true;
   4347 }
   4348 
   4349 /* Examine each landing pad block and see if it matches unsplit_eh.  */
   4350 
   4351 static bool
   4352 unsplit_all_eh (void)
   4353 {
   4354   bool changed = false;
   4355   eh_landing_pad lp;
   4356   int i;
   4357 
   4358   for (i = 1; vec_safe_iterate (cfun->eh->lp_array, i, &lp); ++i)
   4359     if (lp)
   4360       changed |= unsplit_eh (lp);
   4361 
   4362   return changed;
   4363 }
   4364 
   4365 /* Wrapper around unsplit_all_eh that makes it usable everywhere.  */
   4366 
   4367 void
   4368 unsplit_eh_edges (void)
   4369 {
   4370   bool changed;
   4371 
   4372   /* unsplit_all_eh can die looking up unreachable landing pads.  */
   4373   maybe_remove_unreachable_handlers ();
   4374 
   4375   changed = unsplit_all_eh ();
   4376 
   4377   /* If EH edges have been unsplit, delete unreachable forwarder blocks.  */
   4378   if (changed)
   4379     {
   4380       free_dominance_info (CDI_DOMINATORS);
   4381       free_dominance_info (CDI_POST_DOMINATORS);
   4382       delete_unreachable_blocks ();
   4383     }
   4384 }
   4385 
   4386 /* A subroutine of cleanup_empty_eh.  Redirect all EH edges incoming
   4387    to OLD_BB to NEW_BB; return true on success, false on failure.
   4388 
   4389    OLD_BB_OUT is the edge into NEW_BB from OLD_BB, so if we miss any
   4390    PHI variables from OLD_BB we can pick them up from OLD_BB_OUT.
   4391    Virtual PHIs may be deleted and marked for renaming.  */
   4392 
   4393 static bool
   4394 cleanup_empty_eh_merge_phis (basic_block new_bb, basic_block old_bb,
   4395 			     edge old_bb_out, bool change_region)
   4396 {
   4397   gphi_iterator ngsi, ogsi;
   4398   edge_iterator ei;
   4399   edge e;
   4400   bitmap ophi_handled;
   4401 
   4402   /* The destination block must not be a regular successor for any
   4403      of the preds of the landing pad.  Thus, avoid turning
   4404         <..>
   4405 	 |  \ EH
   4406 	 |  <..>
   4407 	 |  /
   4408 	<..>
   4409      into
   4410         <..>
   4411 	|  | EH
   4412 	<..>
   4413      which CFG verification would choke on.  See PR45172 and PR51089.  */
   4414   if (!single_pred_p (new_bb))
   4415     FOR_EACH_EDGE (e, ei, old_bb->preds)
   4416       if (find_edge (e->src, new_bb))
   4417 	return false;
   4418 
   4419   FOR_EACH_EDGE (e, ei, old_bb->preds)
   4420     redirect_edge_var_map_clear (e);
   4421 
   4422   ophi_handled = BITMAP_ALLOC (NULL);
   4423 
   4424   /* First, iterate through the PHIs on NEW_BB and set up the edge_var_map
   4425      for the edges we're going to move.  */
   4426   for (ngsi = gsi_start_phis (new_bb); !gsi_end_p (ngsi); gsi_next (&ngsi))
   4427     {
   4428       gphi *ophi, *nphi = ngsi.phi ();
   4429       tree nresult, nop;
   4430 
   4431       nresult = gimple_phi_result (nphi);
   4432       nop = gimple_phi_arg_def (nphi, old_bb_out->dest_idx);
   4433 
   4434       /* Find the corresponding PHI in OLD_BB so we can forward-propagate
   4435 	 the source ssa_name.  */
   4436       ophi = NULL;
   4437       for (ogsi = gsi_start_phis (old_bb); !gsi_end_p (ogsi); gsi_next (&ogsi))
   4438 	{
   4439 	  ophi = ogsi.phi ();
   4440 	  if (gimple_phi_result (ophi) == nop)
   4441 	    break;
   4442 	  ophi = NULL;
   4443 	}
   4444 
   4445       /* If we did find the corresponding PHI, copy those inputs.  */
   4446       if (ophi)
   4447 	{
   4448 	  /* If NOP is used somewhere else beyond phis in new_bb, give up.  */
   4449 	  if (!has_single_use (nop))
   4450 	    {
   4451 	      imm_use_iterator imm_iter;
   4452 	      use_operand_p use_p;
   4453 
   4454 	      FOR_EACH_IMM_USE_FAST (use_p, imm_iter, nop)
   4455 		{
   4456 		  if (!gimple_debug_bind_p (USE_STMT (use_p))
   4457 		      && (gimple_code (USE_STMT (use_p)) != GIMPLE_PHI
   4458 			  || gimple_bb (USE_STMT (use_p)) != new_bb))
   4459 		    goto fail;
   4460 		}
   4461 	    }
   4462 	  bitmap_set_bit (ophi_handled, SSA_NAME_VERSION (nop));
   4463 	  FOR_EACH_EDGE (e, ei, old_bb->preds)
   4464 	    {
   4465 	      location_t oloc;
   4466 	      tree oop;
   4467 
   4468 	      if ((e->flags & EDGE_EH) == 0)
   4469 		continue;
   4470 	      oop = gimple_phi_arg_def (ophi, e->dest_idx);
   4471 	      oloc = gimple_phi_arg_location (ophi, e->dest_idx);
   4472 	      redirect_edge_var_map_add (e, nresult, oop, oloc);
   4473 	    }
   4474 	}
   4475       /* If we didn't find the PHI, if it's a real variable or a VOP, we know
   4476 	 from the fact that OLD_BB is tree_empty_eh_handler_p that the
   4477 	 variable is unchanged from input to the block and we can simply
   4478 	 re-use the input to NEW_BB from the OLD_BB_OUT edge.  */
   4479       else
   4480 	{
   4481 	  location_t nloc
   4482 	    = gimple_phi_arg_location (nphi, old_bb_out->dest_idx);
   4483 	  FOR_EACH_EDGE (e, ei, old_bb->preds)
   4484 	    redirect_edge_var_map_add (e, nresult, nop, nloc);
   4485 	}
   4486     }
   4487 
   4488   /* Second, verify that all PHIs from OLD_BB have been handled.  If not,
   4489      we don't know what values from the other edges into NEW_BB to use.  */
   4490   for (ogsi = gsi_start_phis (old_bb); !gsi_end_p (ogsi); gsi_next (&ogsi))
   4491     {
   4492       gphi *ophi = ogsi.phi ();
   4493       tree oresult = gimple_phi_result (ophi);
   4494       if (!bitmap_bit_p (ophi_handled, SSA_NAME_VERSION (oresult)))
   4495 	goto fail;
   4496     }
   4497 
   4498   /* Finally, move the edges and update the PHIs.  */
   4499   for (ei = ei_start (old_bb->preds); (e = ei_safe_edge (ei)); )
   4500     if (e->flags & EDGE_EH)
   4501       {
   4502 	/* ???  CFG manipluation routines do not try to update loop
   4503 	   form on edge redirection.  Do so manually here for now.  */
   4504 	/* If we redirect a loop entry or latch edge that will either create
   4505 	   a multiple entry loop or rotate the loop.  If the loops merge
   4506 	   we may have created a loop with multiple latches.
   4507 	   All of this isn't easily fixed thus cancel the affected loop
   4508 	   and mark the other loop as possibly having multiple latches.  */
   4509 	if (e->dest == e->dest->loop_father->header)
   4510 	  {
   4511 	    mark_loop_for_removal (e->dest->loop_father);
   4512 	    new_bb->loop_father->latch = NULL;
   4513 	    loops_state_set (LOOPS_MAY_HAVE_MULTIPLE_LATCHES);
   4514 	  }
   4515 	redirect_eh_edge_1 (e, new_bb, change_region);
   4516 	redirect_edge_succ (e, new_bb);
   4517 	flush_pending_stmts (e);
   4518       }
   4519     else
   4520       ei_next (&ei);
   4521 
   4522   BITMAP_FREE (ophi_handled);
   4523   return true;
   4524 
   4525  fail:
   4526   FOR_EACH_EDGE (e, ei, old_bb->preds)
   4527     redirect_edge_var_map_clear (e);
   4528   BITMAP_FREE (ophi_handled);
   4529   return false;
   4530 }
   4531 
   4532 /* A subroutine of cleanup_empty_eh.  Move a landing pad LP from its
   4533    old region to NEW_REGION at BB.  */
   4534 
   4535 static void
   4536 cleanup_empty_eh_move_lp (basic_block bb, edge e_out,
   4537 			  eh_landing_pad lp, eh_region new_region)
   4538 {
   4539   gimple_stmt_iterator gsi;
   4540   eh_landing_pad *pp;
   4541 
   4542   for (pp = &lp->region->landing_pads; *pp != lp; pp = &(*pp)->next_lp)
   4543     continue;
   4544   *pp = lp->next_lp;
   4545 
   4546   lp->region = new_region;
   4547   lp->next_lp = new_region->landing_pads;
   4548   new_region->landing_pads = lp;
   4549 
   4550   /* Delete the RESX that was matched within the empty handler block.  */
   4551   gsi = gsi_last_bb (bb);
   4552   unlink_stmt_vdef (gsi_stmt (gsi));
   4553   gsi_remove (&gsi, true);
   4554 
   4555   /* Clean up E_OUT for the fallthru.  */
   4556   e_out->flags = (e_out->flags & ~EDGE_EH) | EDGE_FALLTHRU;
   4557   e_out->probability = profile_probability::always ();
   4558 }
   4559 
   4560 /* A subroutine of cleanup_empty_eh.  Handle more complex cases of
   4561    unsplitting than unsplit_eh was prepared to handle, e.g. when
   4562    multiple incoming edges and phis are involved.  */
   4563 
   4564 static bool
   4565 cleanup_empty_eh_unsplit (basic_block bb, edge e_out, eh_landing_pad lp)
   4566 {
   4567   gimple_stmt_iterator gsi;
   4568   tree lab;
   4569 
   4570   /* We really ought not have totally lost everything following
   4571      a landing pad label.  Given that BB is empty, there had better
   4572      be a successor.  */
   4573   gcc_assert (e_out != NULL);
   4574 
   4575   /* The destination block must not already have a landing pad
   4576      for a different region.  */
   4577   lab = NULL;
   4578   for (gsi = gsi_start_bb (e_out->dest); !gsi_end_p (gsi); gsi_next (&gsi))
   4579     {
   4580       glabel *stmt = dyn_cast <glabel *> (gsi_stmt (gsi));
   4581       int lp_nr;
   4582 
   4583       if (!stmt)
   4584 	break;
   4585       lab = gimple_label_label (stmt);
   4586       lp_nr = EH_LANDING_PAD_NR (lab);
   4587       if (lp_nr && get_eh_region_from_lp_number (lp_nr) != lp->region)
   4588 	return false;
   4589     }
   4590 
   4591   /* Attempt to move the PHIs into the successor block.  */
   4592   if (cleanup_empty_eh_merge_phis (e_out->dest, bb, e_out, false))
   4593     {
   4594       if (dump_file && (dump_flags & TDF_DETAILS))
   4595 	fprintf (dump_file,
   4596 		 "Unsplit EH landing pad %d to block %i "
   4597 		 "(via cleanup_empty_eh).\n",
   4598 		 lp->index, e_out->dest->index);
   4599       return true;
   4600     }
   4601 
   4602   return false;
   4603 }
   4604 
   4605 /* Return true if edge E_FIRST is part of an empty infinite loop
   4606    or leads to such a loop through a series of single successor
   4607    empty bbs.  */
   4608 
   4609 static bool
   4610 infinite_empty_loop_p (edge e_first)
   4611 {
   4612   bool inf_loop = false;
   4613   edge e;
   4614 
   4615   if (e_first->dest == e_first->src)
   4616     return true;
   4617 
   4618   e_first->src->aux = (void *) 1;
   4619   for (e = e_first; single_succ_p (e->dest); e = single_succ_edge (e->dest))
   4620     {
   4621       gimple_stmt_iterator gsi;
   4622       if (e->dest->aux)
   4623 	{
   4624 	  inf_loop = true;
   4625 	  break;
   4626 	}
   4627       e->dest->aux = (void *) 1;
   4628       gsi = gsi_after_labels (e->dest);
   4629       if (!gsi_end_p (gsi) && is_gimple_debug (gsi_stmt (gsi)))
   4630 	gsi_next_nondebug (&gsi);
   4631       if (!gsi_end_p (gsi))
   4632 	break;
   4633     }
   4634   e_first->src->aux = NULL;
   4635   for (e = e_first; e->dest->aux; e = single_succ_edge (e->dest))
   4636     e->dest->aux = NULL;
   4637 
   4638   return inf_loop;
   4639 }
   4640 
   4641 /* Examine the block associated with LP to determine if it's an empty
   4642    handler for its EH region.  If so, attempt to redirect EH edges to
   4643    an outer region.  Return true the CFG was updated in any way.  This
   4644    is similar to jump forwarding, just across EH edges.  */
   4645 
   4646 static bool
   4647 cleanup_empty_eh (eh_landing_pad lp)
   4648 {
   4649   basic_block bb = label_to_block (cfun, lp->post_landing_pad);
   4650   gimple_stmt_iterator gsi;
   4651   gimple *resx;
   4652   eh_region new_region;
   4653   edge_iterator ei;
   4654   edge e, e_out;
   4655   bool has_non_eh_pred;
   4656   bool ret = false;
   4657   int new_lp_nr;
   4658 
   4659   /* There can be zero or one edges out of BB.  This is the quickest test.  */
   4660   switch (EDGE_COUNT (bb->succs))
   4661     {
   4662     case 0:
   4663       e_out = NULL;
   4664       break;
   4665     case 1:
   4666       e_out = single_succ_edge (bb);
   4667       break;
   4668     default:
   4669       return false;
   4670     }
   4671 
   4672   gsi = gsi_last_nondebug_bb (bb);
   4673   resx = gsi_stmt (gsi);
   4674   if (resx && is_gimple_resx (resx))
   4675     {
   4676       if (stmt_can_throw_external (cfun, resx))
   4677 	optimize_clobbers (bb);
   4678       else if (sink_clobbers (bb))
   4679 	ret = true;
   4680     }
   4681 
   4682   gsi = gsi_after_labels (bb);
   4683 
   4684   /* Make sure to skip debug statements.  */
   4685   if (!gsi_end_p (gsi) && is_gimple_debug (gsi_stmt (gsi)))
   4686     gsi_next_nondebug (&gsi);
   4687 
   4688   /* If the block is totally empty, look for more unsplitting cases.  */
   4689   if (gsi_end_p (gsi))
   4690     {
   4691       /* For the degenerate case of an infinite loop bail out.
   4692 	 If bb has no successors and is totally empty, which can happen e.g.
   4693 	 because of incorrect noreturn attribute, bail out too.  */
   4694       if (e_out == NULL
   4695 	  || infinite_empty_loop_p (e_out))
   4696 	return ret;
   4697 
   4698       return ret | cleanup_empty_eh_unsplit (bb, e_out, lp);
   4699     }
   4700 
   4701   /* The block should consist only of a single RESX statement, modulo a
   4702      preceding call to __builtin_stack_restore if there is no outgoing
   4703      edge, since the call can be eliminated in this case.  */
   4704   resx = gsi_stmt (gsi);
   4705   if (!e_out && gimple_call_builtin_p (resx, BUILT_IN_STACK_RESTORE))
   4706     {
   4707       gsi_next_nondebug (&gsi);
   4708       resx = gsi_stmt (gsi);
   4709     }
   4710   if (!is_gimple_resx (resx))
   4711     return ret;
   4712   gcc_assert (gsi_one_nondebug_before_end_p (gsi));
   4713 
   4714   /* Determine if there are non-EH edges, or resx edges into the handler.  */
   4715   has_non_eh_pred = false;
   4716   FOR_EACH_EDGE (e, ei, bb->preds)
   4717     if (!(e->flags & EDGE_EH))
   4718       has_non_eh_pred = true;
   4719 
   4720   /* Find the handler that's outer of the empty handler by looking at
   4721      where the RESX instruction was vectored.  */
   4722   new_lp_nr = lookup_stmt_eh_lp (resx);
   4723   new_region = get_eh_region_from_lp_number (new_lp_nr);
   4724 
   4725   /* If there's no destination region within the current function,
   4726      redirection is trivial via removing the throwing statements from
   4727      the EH region, removing the EH edges, and allowing the block
   4728      to go unreachable.  */
   4729   if (new_region == NULL)
   4730     {
   4731       gcc_assert (e_out == NULL);
   4732       for (ei = ei_start (bb->preds); (e = ei_safe_edge (ei)); )
   4733 	if (e->flags & EDGE_EH)
   4734 	  {
   4735 	    gimple *stmt = *gsi_last_bb (e->src);
   4736 	    remove_stmt_from_eh_lp (stmt);
   4737 	    remove_edge (e);
   4738 	  }
   4739 	else
   4740 	  ei_next (&ei);
   4741       goto succeed;
   4742     }
   4743 
   4744   /* If the destination region is a MUST_NOT_THROW, allow the runtime
   4745      to handle the abort and allow the blocks to go unreachable.  */
   4746   if (new_region->type == ERT_MUST_NOT_THROW)
   4747     {
   4748       for (ei = ei_start (bb->preds); (e = ei_safe_edge (ei)); )
   4749 	if (e->flags & EDGE_EH)
   4750 	  {
   4751 	    gimple *stmt = *gsi_last_bb (e->src);
   4752 	    remove_stmt_from_eh_lp (stmt);
   4753 	    add_stmt_to_eh_lp (stmt, new_lp_nr);
   4754 	    remove_edge (e);
   4755 	  }
   4756 	else
   4757 	  ei_next (&ei);
   4758       goto succeed;
   4759     }
   4760 
   4761   /* Try to redirect the EH edges and merge the PHIs into the destination
   4762      landing pad block.  If the merge succeeds, we'll already have redirected
   4763      all the EH edges.  The handler itself will go unreachable if there were
   4764      no normal edges.  */
   4765   if (cleanup_empty_eh_merge_phis (e_out->dest, bb, e_out, true))
   4766     goto succeed;
   4767 
   4768   /* Finally, if all input edges are EH edges, then we can (potentially)
   4769      reduce the number of transfers from the runtime by moving the landing
   4770      pad from the original region to the new region.  This is a win when
   4771      we remove the last CLEANUP region along a particular exception
   4772      propagation path.  Since nothing changes except for the region with
   4773      which the landing pad is associated, the PHI nodes do not need to be
   4774      adjusted at all.  */
   4775   if (!has_non_eh_pred)
   4776     {
   4777       cleanup_empty_eh_move_lp (bb, e_out, lp, new_region);
   4778       if (dump_file && (dump_flags & TDF_DETAILS))
   4779 	fprintf (dump_file, "Empty EH handler %i moved to EH region %i.\n",
   4780 		 lp->index, new_region->index);
   4781 
   4782       /* ??? The CFG didn't change, but we may have rendered the
   4783 	 old EH region unreachable.  Trigger a cleanup there.  */
   4784       return true;
   4785     }
   4786 
   4787   return ret;
   4788 
   4789  succeed:
   4790   if (dump_file && (dump_flags & TDF_DETAILS))
   4791     fprintf (dump_file, "Empty EH handler %i removed.\n", lp->index);
   4792   remove_eh_landing_pad (lp);
   4793   return true;
   4794 }
   4795 
   4796 /* Do a post-order traversal of the EH region tree.  Examine each
   4797    post_landing_pad block and see if we can eliminate it as empty.  */
   4798 
   4799 static bool
   4800 cleanup_all_empty_eh (void)
   4801 {
   4802   bool changed = false;
   4803   eh_landing_pad lp;
   4804   int i;
   4805 
   4806   /* The post-order traversal may lead to quadraticness in the redirection
   4807      of incoming EH edges from inner LPs, so first try to walk the region
   4808      tree from inner to outer LPs in order to eliminate these edges.  */
   4809   for (i = vec_safe_length (cfun->eh->lp_array) - 1; i >= 1; --i)
   4810     {
   4811       lp = (*cfun->eh->lp_array)[i];
   4812       if (lp)
   4813 	changed |= cleanup_empty_eh (lp);
   4814     }
   4815 
   4816   /* Now do the post-order traversal to eliminate outer empty LPs.  */
   4817   for (i = 1; vec_safe_iterate (cfun->eh->lp_array, i, &lp); ++i)
   4818     if (lp)
   4819       changed |= cleanup_empty_eh (lp);
   4820 
   4821   return changed;
   4822 }
   4823 
   4824 /* Perform cleanups and lowering of exception handling
   4825     1) cleanups regions with handlers doing nothing are optimized out
   4826     2) MUST_NOT_THROW regions that became dead because of 1) are optimized out
   4827     3) Info about regions that are containing instructions, and regions
   4828        reachable via local EH edges is collected
   4829     4) Eh tree is pruned for regions no longer necessary.
   4830 
   4831    TODO: Push MUST_NOT_THROW regions to the root of the EH tree.
   4832 	 Unify those that have the same failure decl and locus.
   4833 */
   4834 
   4835 static unsigned int
   4836 execute_cleanup_eh_1 (void)
   4837 {
   4838   /* Do this first: unsplit_all_eh and cleanup_all_empty_eh can die
   4839      looking up unreachable landing pads.  */
   4840   remove_unreachable_handlers ();
   4841 
   4842   /* Watch out for the region tree vanishing due to all unreachable.  */
   4843   if (cfun->eh->region_tree)
   4844     {
   4845       bool changed = false;
   4846 
   4847       if (optimize)
   4848 	changed |= unsplit_all_eh ();
   4849       changed |= cleanup_all_empty_eh ();
   4850 
   4851       if (changed)
   4852 	{
   4853 	  free_dominance_info (CDI_DOMINATORS);
   4854 	  free_dominance_info (CDI_POST_DOMINATORS);
   4855 
   4856           /* We delayed all basic block deletion, as we may have performed
   4857 	     cleanups on EH edges while non-EH edges were still present.  */
   4858 	  delete_unreachable_blocks ();
   4859 
   4860 	  /* We manipulated the landing pads.  Remove any region that no
   4861 	     longer has a landing pad.  */
   4862 	  remove_unreachable_handlers_no_lp ();
   4863 
   4864 	  return TODO_cleanup_cfg | TODO_update_ssa_only_virtuals;
   4865 	}
   4866     }
   4867 
   4868   return 0;
   4869 }
   4870 
   4871 namespace {
   4872 
   4873 const pass_data pass_data_cleanup_eh =
   4874 {
   4875   GIMPLE_PASS, /* type */
   4876   "ehcleanup", /* name */
   4877   OPTGROUP_NONE, /* optinfo_flags */
   4878   TV_TREE_EH, /* tv_id */
   4879   PROP_gimple_lcf, /* properties_required */
   4880   0, /* properties_provided */
   4881   0, /* properties_destroyed */
   4882   0, /* todo_flags_start */
   4883   0, /* todo_flags_finish */
   4884 };
   4885 
   4886 class pass_cleanup_eh : public gimple_opt_pass
   4887 {
   4888 public:
   4889   pass_cleanup_eh (gcc::context *ctxt)
   4890     : gimple_opt_pass (pass_data_cleanup_eh, ctxt)
   4891   {}
   4892 
   4893   /* opt_pass methods: */
   4894   opt_pass * clone () final override { return new pass_cleanup_eh (m_ctxt); }
   4895   bool gate (function *fun) final override
   4896     {
   4897       return fun->eh != NULL && fun->eh->region_tree != NULL;
   4898     }
   4899 
   4900   unsigned int execute (function *) final override;
   4901 
   4902 }; // class pass_cleanup_eh
   4903 
   4904 unsigned int
   4905 pass_cleanup_eh::execute (function *fun)
   4906 {
   4907   int ret = execute_cleanup_eh_1 ();
   4908 
   4909   /* If the function no longer needs an EH personality routine
   4910      clear it.  This exposes cross-language inlining opportunities
   4911      and avoids references to a never defined personality routine.  */
   4912   if (DECL_FUNCTION_PERSONALITY (current_function_decl)
   4913       && function_needs_eh_personality (fun) != eh_personality_lang)
   4914     DECL_FUNCTION_PERSONALITY (current_function_decl) = NULL_TREE;
   4915 
   4916   return ret;
   4917 }
   4918 
   4919 } // anon namespace
   4920 
   4921 gimple_opt_pass *
   4922 make_pass_cleanup_eh (gcc::context *ctxt)
   4923 {
   4924   return new pass_cleanup_eh (ctxt);
   4925 }
   4926 
   4927 /* Disable warnings about missing quoting in GCC diagnostics for
   4929    the verification errors.  Their format strings don't follow GCC
   4930    diagnostic conventions but are only used for debugging.  */
   4931 #if __GNUC__ >= 10
   4932 #  pragma GCC diagnostic push
   4933 #  pragma GCC diagnostic ignored "-Wformat-diag"
   4934 #endif
   4935 
   4936 /* Verify that BB containing STMT as the last statement, has precisely the
   4937    edge that make_eh_edge would create.  */
   4938 
   4939 DEBUG_FUNCTION bool
   4940 verify_eh_edges (gimple *stmt)
   4941 {
   4942   basic_block bb = gimple_bb (stmt);
   4943   eh_landing_pad lp = NULL;
   4944   int lp_nr;
   4945   edge_iterator ei;
   4946   edge e, eh_edge;
   4947 
   4948   lp_nr = lookup_stmt_eh_lp (stmt);
   4949   if (lp_nr > 0)
   4950     lp = get_eh_landing_pad_from_number (lp_nr);
   4951 
   4952   eh_edge = NULL;
   4953   FOR_EACH_EDGE (e, ei, bb->succs)
   4954     {
   4955       if (e->flags & EDGE_EH)
   4956 	{
   4957 	  if (eh_edge)
   4958 	    {
   4959 	      error ("BB %i has multiple EH edges", bb->index);
   4960 	      return true;
   4961 	    }
   4962 	  else
   4963 	    eh_edge = e;
   4964 	}
   4965     }
   4966 
   4967   if (lp == NULL)
   4968     {
   4969       if (eh_edge)
   4970 	{
   4971 	  error ("BB %i cannot throw but has an EH edge", bb->index);
   4972 	  return true;
   4973 	}
   4974       return false;
   4975     }
   4976 
   4977   if (!stmt_could_throw_p (cfun, stmt))
   4978     {
   4979       error ("BB %i last statement has incorrectly set lp", bb->index);
   4980       return true;
   4981     }
   4982 
   4983   if (eh_edge == NULL)
   4984     {
   4985       error ("BB %i is missing an EH edge", bb->index);
   4986       return true;
   4987     }
   4988 
   4989   if (eh_edge->dest != label_to_block (cfun, lp->post_landing_pad))
   4990     {
   4991       error ("Incorrect EH edge %i->%i", bb->index, eh_edge->dest->index);
   4992       return true;
   4993     }
   4994 
   4995   return false;
   4996 }
   4997 
   4998 /* Similarly, but handle GIMPLE_EH_DISPATCH specifically.  */
   4999 
   5000 DEBUG_FUNCTION bool
   5001 verify_eh_dispatch_edge (geh_dispatch *stmt)
   5002 {
   5003   eh_region r;
   5004   eh_catch c;
   5005   basic_block src, dst;
   5006   bool want_fallthru = true;
   5007   edge_iterator ei;
   5008   edge e, fall_edge;
   5009 
   5010   r = get_eh_region_from_number (gimple_eh_dispatch_region (stmt));
   5011   src = gimple_bb (stmt);
   5012 
   5013   FOR_EACH_EDGE (e, ei, src->succs)
   5014     gcc_assert (e->aux == NULL);
   5015 
   5016   switch (r->type)
   5017     {
   5018     case ERT_TRY:
   5019       for (c = r->u.eh_try.first_catch; c ; c = c->next_catch)
   5020 	{
   5021 	  dst = label_to_block (cfun, c->label);
   5022 	  e = find_edge (src, dst);
   5023 	  if (e == NULL)
   5024 	    {
   5025 	      error ("BB %i is missing an edge", src->index);
   5026 	      return true;
   5027 	    }
   5028 	  e->aux = (void *)e;
   5029 
   5030 	  /* A catch-all handler doesn't have a fallthru.  */
   5031 	  if (c->type_list == NULL)
   5032 	    {
   5033 	      want_fallthru = false;
   5034 	      break;
   5035 	    }
   5036 	}
   5037       break;
   5038 
   5039     case ERT_ALLOWED_EXCEPTIONS:
   5040       dst = label_to_block (cfun, r->u.allowed.label);
   5041       e = find_edge (src, dst);
   5042       if (e == NULL)
   5043 	{
   5044 	  error ("BB %i is missing an edge", src->index);
   5045 	  return true;
   5046 	}
   5047       e->aux = (void *)e;
   5048       break;
   5049 
   5050     default:
   5051       gcc_unreachable ();
   5052     }
   5053 
   5054   fall_edge = NULL;
   5055   FOR_EACH_EDGE (e, ei, src->succs)
   5056     {
   5057       if (e->flags & EDGE_FALLTHRU)
   5058 	{
   5059 	  if (fall_edge != NULL)
   5060 	    {
   5061 	      error ("BB %i too many fallthru edges", src->index);
   5062 	      return true;
   5063 	    }
   5064 	  fall_edge = e;
   5065 	}
   5066       else if (e->aux)
   5067 	e->aux = NULL;
   5068       else
   5069 	{
   5070 	  error ("BB %i has incorrect edge", src->index);
   5071 	  return true;
   5072 	}
   5073     }
   5074   if ((fall_edge != NULL) ^ want_fallthru)
   5075     {
   5076       error ("BB %i has incorrect fallthru edge", src->index);
   5077       return true;
   5078     }
   5079 
   5080   return false;
   5081 }
   5082 
   5083 #if __GNUC__ >= 10
   5084 #  pragma GCC diagnostic pop
   5085 #endif
   5086