LCOV - code coverage report
Current view: top level - gcc - tree-eh.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 92.3 % 2372 2190
Test Date: 2026-09-19 16:22:48 Functions: 98.2 % 112 110
Legend: Lines:     hit not hit

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

Generated by: LCOV version 2.4-beta

LCOV profile is generated on x86_64 machine using following configure options: configure --disable-bootstrap --enable-coverage=opt --enable-languages=c,c++,fortran,go,jit,lto,rust,m2 --enable-host-shared. GCC test suite is run with the built compiler.