LCOV - code coverage report
Current view: top level - gcc - tree-ssa-loop-unswitch.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 95.8 % 756 724
Test Date: 2026-02-28 14:20:25 Functions: 100.0 % 31 31
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /* Loop unswitching.
       2              :    Copyright (C) 2004-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 it
       7              : under the terms of the GNU General Public License as published by the
       8              : Free Software Foundation; either version 3, or (at your option) any
       9              : later version.
      10              : 
      11              : GCC is distributed in the hope that it will be useful, but WITHOUT
      12              : ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
      13              : FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
      14              : 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 "tree.h"
      25              : #include "gimple.h"
      26              : #include "tree-pass.h"
      27              : #include "ssa.h"
      28              : #include "fold-const.h"
      29              : #include "gimplify.h"
      30              : #include "tree-cfg.h"
      31              : #include "tree-ssa.h"
      32              : #include "tree-ssa-loop-niter.h"
      33              : #include "tree-ssa-loop.h"
      34              : #include "tree-into-ssa.h"
      35              : #include "cfgloop.h"
      36              : #include "tree-inline.h"
      37              : #include "gimple-iterator.h"
      38              : #include "cfghooks.h"
      39              : #include "tree-ssa-loop-manip.h"
      40              : #include "tree-vectorizer.h"
      41              : #include "tree-pretty-print.h"
      42              : #include "gimple-range.h"
      43              : #include "dbgcnt.h"
      44              : #include "cfganal.h"
      45              : 
      46              : /* This file implements the loop unswitching, i.e. transformation of loops like
      47              : 
      48              :    while (A)
      49              :      {
      50              :        if (inv)
      51              :          B;
      52              : 
      53              :        X;
      54              : 
      55              :        if (!inv)
      56              :          C;
      57              :      }
      58              : 
      59              :    where inv is the loop invariant, into
      60              : 
      61              :    if (inv)
      62              :      {
      63              :        while (A)
      64              :          {
      65              :            B;
      66              :            X;
      67              :          }
      68              :      }
      69              :    else
      70              :      {
      71              :        while (A)
      72              :          {
      73              :            X;
      74              :            C;
      75              :          }
      76              :      }
      77              : 
      78              :    Inv is considered invariant iff the values it compares are both invariant;
      79              :    tree-ssa-loop-im.cc ensures that all the suitable conditions are in this
      80              :    shape.  */
      81              : 
      82              : /* Loop unswitching algorithm for innermost loops works in the following steps:
      83              : 
      84              :    1) Number of instructions is estimated for each BB that belongs to a loop.
      85              :    2) Unswitching candidates are found for gcond and gswitch statements
      86              :       (note that an unswitching predicate for a gswitch actually corresponds
      87              :        to a non-default edge so it can contain multiple cases).
      88              :    3) The so called unswitch predicates are stored in a cache where the
      89              :       gimple_uid of the last stmt in a basic-block is an index to the cache.
      90              :    4) We consider one by one the unswitching candidates and calculate BBs that
      91              :       will be reachable in the unswitch version.
      92              :    5) A selected predicate is chosen and we simplify the CFG (dead edges) in
      93              :       both versions of the loop.  We utilize both Ranger for condition
      94              :       simplification and also symbol equivalence.  The folded if conditions
      95              :       are replaced with true/false values, while for gswitch we mark the
      96              :       corresponding edges with a pass-defined unreachable flag.
      97              :    6) Every time we unswitch a loop, we save unswitch_predicate to a vector
      98              :       together with information if true or false edge was taken.  Doing that
      99              :       we have a so called PREDICATE_PATH that is utilized for simplification
     100              :       of the cloned loop.
     101              :    7) The process is repeated until we reach a growth threshold or all
     102              :       unswitching opportunities are taken.  */
     103              : 
     104              : /* A tuple that holds a GENERIC condition and value range for an unswitching
     105              :    predicate.  */
     106              : 
     107              : struct unswitch_predicate
     108              : {
     109              :   /* CTOR for a switch edge predicate.  */
     110          106 :   unswitch_predicate (tree cond, tree lhs_, int edge_index_, edge e,
     111              :                       const int_range_max& edge_range)
     112          106 :     : condition (cond), lhs (lhs_),
     113          106 :       true_range (edge_range), edge_index (edge_index_), switch_p (true)
     114              :   {
     115          106 :     gcc_assert (!(e->flags & (EDGE_TRUE_VALUE|EDGE_FALSE_VALUE))
     116              :                 && irange::supports_p (TREE_TYPE (lhs)));
     117          106 :     false_range = true_range;
     118          106 :     if (!false_range.varying_p ()
     119          106 :         && !false_range.undefined_p ())
     120          106 :       false_range.invert ();
     121          106 :     count = e->count ();
     122          106 :     num = predicates->length ();
     123          106 :     predicates->safe_push (this);
     124          106 :   }
     125              : 
     126              :   /* CTOR for a GIMPLE condition statement.  */
     127         2785 :   unswitch_predicate (gcond *stmt)
     128         2785 :     : switch_p (false)
     129              :   {
     130         2785 :     basic_block bb = gimple_bb (stmt);
     131         2785 :     if (EDGE_SUCC (bb, 0)->flags & EDGE_TRUE_VALUE)
     132         2731 :       edge_index = 0;
     133              :     else
     134           54 :       edge_index = 1;
     135         2785 :     lhs = gimple_cond_lhs (stmt);
     136         2785 :     tree rhs = gimple_cond_rhs (stmt);
     137         2785 :     enum tree_code code = gimple_cond_code (stmt);
     138         2785 :     condition = build2 (code, boolean_type_node, lhs, rhs);
     139         2785 :     count = profile_count::max_prefer_initialized (EDGE_SUCC (bb, 0)->count (),
     140         2785 :                                                    EDGE_SUCC (bb, 1)->count ());
     141         2785 :     if (irange::supports_p (TREE_TYPE (lhs)))
     142              :       {
     143         2619 :         auto range_op = range_op_handler (code);
     144         2619 :         int_range<2> rhs_range (TREE_TYPE (rhs));
     145         2619 :         if (CONSTANT_CLASS_P (rhs))
     146              :           {
     147         2488 :             wide_int w = wi::to_wide (rhs);
     148         2488 :             rhs_range.set (TREE_TYPE (rhs), w, w);
     149         2488 :           }
     150         2619 :         if (!range_op.op1_range (true_range, TREE_TYPE (lhs),
     151         5238 :                                  range_true (), rhs_range)
     152         7857 :             || !range_op.op1_range (false_range, TREE_TYPE (lhs),
     153         5238 :                                     range_false (), rhs_range))
     154              :           {
     155            0 :             true_range.set_varying (TREE_TYPE (lhs));
     156            0 :             false_range.set_varying (TREE_TYPE (lhs));
     157              :           }
     158         2619 :       }
     159         2785 :     num = predicates->length ();
     160         2785 :     predicates->safe_push (this);
     161         2785 :   }
     162              : 
     163              :   /* Copy ranges for purpose of usage in predicate path.  */
     164              : 
     165              :   inline void
     166         7614 :   copy_merged_ranges ()
     167              :   {
     168         7614 :     merged_true_range = true_range;
     169         7614 :     merged_false_range = false_range;
     170         7614 :   }
     171              : 
     172              :   /* GENERIC unswitching expression testing LHS against CONSTANT.  */
     173              :   tree condition;
     174              : 
     175              :   /* LHS of the expression.  */
     176              :   tree lhs;
     177              : 
     178              :   /* Initial ranges (when the expression is true/false) for the expression.  */
     179              :   int_range_max true_range = {}, false_range = {};
     180              : 
     181              :   /* Modified range that is part of a predicate path.  */
     182              :   int_range_max merged_true_range = {}, merged_false_range = {};
     183              : 
     184              :   /* Index of the edge the predicate belongs to in the successor vector.  */
     185              :   int edge_index;
     186              : 
     187              :   /* The profile count of this predicate.  */
     188              :   profile_count count;
     189              : 
     190              :   /* Whether the predicate was created from a switch statement.  */
     191              :   bool switch_p;
     192              : 
     193              :   /* The number of the predicate in the predicates vector below.  */
     194              :   unsigned num;
     195              : 
     196              :   /* Vector of all used predicates, used for assigning a unique id that
     197              :      can be used for bitmap operations.  */
     198              :   static vec<unswitch_predicate *> *predicates;
     199              : };
     200              : 
     201              : vec<unswitch_predicate *> *unswitch_predicate::predicates;
     202              : 
     203              : /* Ranger instance used in the pass.  */
     204              : static gimple_ranger *ranger = NULL;
     205              : 
     206              : /* Cache storage for unswitch_predicate belonging to a basic block.  */
     207              : static vec<vec<unswitch_predicate *>> *bb_predicates;
     208              : 
     209              : /* The type represents a predicate path leading to a basic block.  */
     210              : typedef vec<std::pair<unswitch_predicate *, bool>> predicate_vector;
     211              : 
     212              : static class loop *tree_unswitch_loop (class loop *, edge, tree);
     213              : static bool tree_unswitch_single_loop (class loop *, dump_user_location_t,
     214              :                                        predicate_vector &predicate_path,
     215              :                                        unsigned loop_size, unsigned &budget,
     216              :                                        int ignored_edge_flag, bitmap,
     217              :                                        unswitch_predicate * = NULL,
     218              :                                        basic_block = NULL);
     219              : static void
     220              : find_unswitching_predicates_for_bb (basic_block bb, class loop *loop,
     221              :                                     class loop *&outer_loop,
     222              :                                     vec<unswitch_predicate *> &candidates,
     223              :                                     unswitch_predicate *&hottest,
     224              :                                     basic_block &hottest_bb);
     225              : static bool tree_unswitch_outer_loop (class loop *);
     226              : static edge find_loop_guard (class loop *, vec<gimple *>&);
     227              : static bool empty_bb_without_guard_p (class loop *, basic_block,
     228              :                                       vec<gimple *>&);
     229              : static bool used_outside_loop_p (class loop *, tree, vec<gimple *>&);
     230              : static void hoist_guard (class loop *, edge);
     231              : static bool check_exit_phi (class loop *);
     232              : static tree get_vop_from_header (class loop *);
     233              : static void clean_up_after_unswitching (int);
     234              : 
     235              : /* Return vector of predicates that belong to a basic block.  */
     236              : 
     237              : static vec<unswitch_predicate *> &
     238       471093 : get_predicates_for_bb (basic_block bb)
     239              : {
     240       471093 :   gimple *last = last_nondebug_stmt (bb);
     241       471093 :   return (*bb_predicates)[last == NULL ? 0 : gimple_uid (last)];
     242              : }
     243              : 
     244              : /* Save predicates that belong to a basic block.  */
     245              : 
     246              : static void
     247         2817 : set_predicates_for_bb (basic_block bb, vec<unswitch_predicate *> predicates)
     248              : {
     249         5634 :   gimple_set_uid (last_nondebug_stmt (bb), bb_predicates->length ());
     250         2817 :   bb_predicates->safe_push (predicates);
     251         2817 : }
     252              : 
     253              : /* Initialize LOOP information reused during the unswitching pass.
     254              :    Return total number of instructions in the loop.  Adjusts LOOP to
     255              :    the outermost loop all candidates are invariant in.  */
     256              : 
     257              : static unsigned
     258        62174 : init_loop_unswitch_info (class loop *&loop, unswitch_predicate *&hottest,
     259              :                          basic_block &hottest_bb)
     260              : {
     261        62174 :   unsigned total_insns = 0;
     262              : 
     263        62174 :   basic_block *bbs = get_loop_body (loop);
     264              : 
     265              :   /* Unswitch only nests with no sibling loops.  */
     266        62174 :   class loop *outer_loop = loop;
     267        62174 :   unsigned max_depth = param_max_unswitch_depth;
     268        62174 :   while (loop_outer (outer_loop)->num != 0
     269        17790 :          && !loop_outer (outer_loop)->inner->next
     270        84497 :          && --max_depth != 0)
     271        11159 :     outer_loop = loop_outer (outer_loop);
     272        62174 :   hottest = NULL;
     273        62174 :   hottest_bb = NULL;
     274              :   /* Find all unswitching candidates in the innermost loop.  */
     275       290632 :   for (unsigned i = 0; i != loop->num_nodes; i++)
     276              :     {
     277              :       /* Find a bb to unswitch on.  */
     278       228458 :       vec<unswitch_predicate *> candidates;
     279       228458 :       candidates.create (1);
     280       228458 :       find_unswitching_predicates_for_bb (bbs[i], loop, outer_loop, candidates,
     281              :                                           hottest, hottest_bb);
     282       228458 :       if (!candidates.is_empty ())
     283         2817 :         set_predicates_for_bb (bbs[i], candidates);
     284              :       else
     285              :         {
     286       225641 :           candidates.release ();
     287       225641 :           gimple *last = last_nondebug_stmt (bbs[i]);
     288       225641 :           if (last != NULL)
     289       142481 :             gimple_set_uid (last, 0);
     290              :         }
     291              :     }
     292              : 
     293        62174 :   if (outer_loop != loop)
     294              :     {
     295         8537 :       free (bbs);
     296         8537 :       bbs = get_loop_body (outer_loop);
     297              :     }
     298              : 
     299              :   /* Calculate instruction count.  */
     300       360434 :   for (unsigned i = 0; i < outer_loop->num_nodes; i++)
     301              :     {
     302       298260 :       unsigned insns = 0;
     303      1631590 :       for (gimple_stmt_iterator gsi = gsi_start_bb (bbs[i]); !gsi_end_p (gsi);
     304      1035070 :            gsi_next (&gsi))
     305      1035070 :         insns += estimate_num_insns (gsi_stmt (gsi), &eni_size_weights);
     306              :       /* No predicates to unswitch on in the outer loops.  */
     307       298260 :       if (!flow_bb_inside_loop_p (loop, bbs[i]))
     308              :         {
     309        69802 :           gimple *last = last_nondebug_stmt (bbs[i]);
     310        69802 :           if (last != NULL)
     311        42052 :             gimple_set_uid (last, 0);
     312              :         }
     313              : 
     314       298260 :       bbs[i]->aux = (void *)(uintptr_t)insns;
     315       298260 :       total_insns += insns;
     316              :     }
     317              : 
     318        62174 :   free (bbs);
     319              : 
     320        62174 :   loop = outer_loop;
     321        62174 :   return total_insns;
     322              : }
     323              : 
     324              : /* Main entry point.  Perform loop unswitching on all suitable loops.  */
     325              : 
     326              : unsigned int
     327        28166 : tree_ssa_unswitch_loops (function *fun)
     328              : {
     329        28166 :   bool changed_unswitch = false;
     330        28166 :   bool changed_hoist = false;
     331        28166 :   auto_edge_flag ignored_edge_flag (fun);
     332        28166 :   mark_ssa_maybe_undefs ();
     333              : 
     334        28166 :   ranger = enable_ranger (fun);
     335              : 
     336              :   /* Go through all loops starting from innermost, hoisting guards.  */
     337       164361 :   for (auto loop : loops_list (fun, LI_FROM_INNERMOST))
     338              :     {
     339        79863 :       if (loop->inner)
     340        14477 :         changed_hoist |= tree_unswitch_outer_loop (loop);
     341        28166 :     }
     342              : 
     343              :   /* Go through innermost loops, unswitching on invariant predicates
     344              :      within those.  */
     345       149884 :   for (auto loop : loops_list (fun, LI_ONLY_INNERMOST))
     346              :     {
     347              :       /* Perform initial tests if unswitch is eligible.  */
     348        65386 :       dump_user_location_t loc = find_loop_location (loop);
     349              : 
     350              :       /* Do not unswitch in cold regions. */
     351        65386 :       if (optimize_loop_for_size_p (loop))
     352              :         {
     353         1219 :           if (dump_enabled_p ())
     354            0 :             dump_printf_loc (MSG_NOTE, loc,
     355              :                              "Not unswitching cold loops\n");
     356         3212 :           continue;
     357              :         }
     358              : 
     359              :       /* If the loop is not expected to iterate, there is no need
     360              :          for unswitching.  */
     361        64167 :       HOST_WIDE_INT iterations = estimated_loop_iterations_int (loop);
     362        64167 :       if (iterations < 0)
     363        38489 :         iterations = likely_max_loop_iterations_int (loop);
     364        64167 :       if (iterations >= 0 && iterations <= 1)
     365              :         {
     366         1993 :           if (dump_enabled_p ())
     367            2 :             dump_printf_loc (MSG_NOTE, loc,
     368              :                              "Not unswitching, loop is not expected"
     369              :                              " to iterate\n");
     370         1993 :           continue;
     371              :         }
     372              : 
     373        62174 :       bb_predicates = new vec<vec<unswitch_predicate *>> ();
     374        62174 :       bb_predicates->safe_push (vec<unswitch_predicate *> ());
     375        62174 :       unswitch_predicate::predicates = new vec<unswitch_predicate *> ();
     376              : 
     377              :       /* Unswitch loop.  */
     378        62174 :       unswitch_predicate *hottest;
     379        62174 :       basic_block hottest_bb;
     380        62174 :       unsigned int loop_size = init_loop_unswitch_info (loop, hottest,
     381              :                                                         hottest_bb);
     382        62174 :       unsigned int budget = loop_size + param_max_unswitch_insns;
     383              : 
     384        62174 :       predicate_vector predicate_path;
     385        62174 :       predicate_path.create (8);
     386        62174 :       auto_bitmap handled;
     387        62174 :       changed_unswitch |= tree_unswitch_single_loop (loop, loc, predicate_path,
     388              :                                                      loop_size, budget,
     389              :                                                      ignored_edge_flag, handled,
     390              :                                                      hottest, hottest_bb);
     391        62174 :       predicate_path.release ();
     392              : 
     393       251513 :       for (auto predlist : bb_predicates)
     394        64991 :         predlist.release ();
     395        62174 :       bb_predicates->release ();
     396        62174 :       delete bb_predicates;
     397        62174 :       bb_predicates = NULL;
     398              : 
     399       189413 :       for (auto pred : unswitch_predicate::predicates)
     400         2891 :         delete pred;
     401        62174 :       unswitch_predicate::predicates->release ();
     402        62174 :       delete unswitch_predicate::predicates;
     403        62174 :       unswitch_predicate::predicates = NULL;
     404        62174 :     }
     405              : 
     406        28166 :   disable_ranger (fun);
     407        28166 :   clear_aux_for_blocks ();
     408              : 
     409        28166 :   if (changed_unswitch)
     410         1353 :     clean_up_after_unswitching (ignored_edge_flag);
     411              : 
     412        28166 :   if (changed_unswitch || changed_hoist)
     413         1857 :     return TODO_cleanup_cfg;
     414              : 
     415              :   return 0;
     416        28166 : }
     417              : 
     418              : /* Return TRUE if an SSA_NAME maybe undefined and is therefore
     419              :    unsuitable for unswitching.  STMT is the statement we are
     420              :    considering for unswitching and LOOP is the loop it appears in.  */
     421              : 
     422              : static bool
     423        18322 : is_maybe_undefined (const tree name, gimple *stmt, class loop *loop)
     424              : {
     425              :   /* The loop header is the only block we can trivially determine that
     426              :      will always be executed.  If the comparison is in the loop
     427              :      header, we know it's OK to unswitch on it.  */
     428            0 :   if (gimple_bb (stmt) == loop->header)
     429              :     return false;
     430              : 
     431         8858 :   return ssa_name_maybe_undef_p (name);
     432              : }
     433              : 
     434              : /* Checks whether we can unswitch LOOP on condition at end of BB -- one of its
     435              :    basic blocks (for what it means see comments below).
     436              :    All candidates all filled to the provided vector CANDIDATES.
     437              :    OUTER_LOOP is updated to the innermost loop all found candidates are
     438              :    invariant in.  */
     439              : 
     440              : static void
     441       228458 : find_unswitching_predicates_for_bb (basic_block bb, class loop *loop,
     442              :                                     class loop *&outer_loop,
     443              :                                     vec<unswitch_predicate *> &candidates,
     444              :                                     unswitch_predicate *&hottest,
     445              :                                     basic_block &hottest_bb)
     446              : {
     447       228458 :   gimple *last, *def;
     448       228458 :   tree use;
     449       228458 :   basic_block def_bb;
     450       228458 :   ssa_op_iter iter;
     451              : 
     452              :   /* BB must end in a simple conditional jump.  */
     453       228458 :   last = *gsi_last_bb (bb);
     454       228458 :   if (!last)
     455       200995 :     return;
     456              : 
     457       145657 :   if (gcond *stmt = safe_dyn_cast <gcond *> (last))
     458              :     {
     459              :       /* To keep the things simple, we do not directly remove the conditions,
     460              :          but just replace tests with 0 != 0 resp. 1 != 0.  Prevent the infinite
     461              :          loop where we would unswitch again on such a condition.  */
     462       120843 :       if (gimple_cond_true_p (stmt) || gimple_cond_false_p (stmt))
     463       118058 :         return;
     464              : 
     465              :       /* At least the LHS needs to be symbolic.  */
     466       120843 :       if (TREE_CODE (gimple_cond_lhs (stmt)) != SSA_NAME)
     467              :         return;
     468              : 
     469              :       /* Condition must be invariant.  */
     470       138374 :       FOR_EACH_SSA_TREE_OPERAND (use, stmt, iter, SSA_OP_USE)
     471              :         {
     472       135589 :           def = SSA_NAME_DEF_STMT (use);
     473       135589 :           def_bb = gimple_bb (def);
     474       135589 :           if (def_bb
     475       135589 :               && flow_bb_inside_loop_p (loop, def_bb))
     476              :             return;
     477              :           /* Unswitching on undefined values would introduce undefined
     478              :              behavior that the original program might never exercise.  */
     479        25933 :           if (is_maybe_undefined (use, stmt, loop))
     480              :             return;
     481              :         }
     482              :       /* Narrow OUTER_LOOP.  */
     483         2785 :       if (outer_loop != loop)
     484         1547 :         FOR_EACH_SSA_TREE_OPERAND (use, stmt, iter, SSA_OP_USE)
     485              :           {
     486          779 :             def = SSA_NAME_DEF_STMT (use);
     487          779 :             def_bb = gimple_bb (def);
     488          779 :             while (outer_loop != loop
     489         1113 :                    && ((def_bb && flow_bb_inside_loop_p (outer_loop, def_bb))
     490         1394 :                        || is_maybe_undefined (use, stmt, outer_loop)))
     491          334 :               outer_loop = superloop_at_depth (loop,
     492          668 :                                                loop_depth (outer_loop) + 1);
     493              :           }
     494              : 
     495         2785 :       unswitch_predicate *predicate = new unswitch_predicate (stmt);
     496         2785 :       candidates.safe_push (predicate);
     497              :       /* If we unswitch on this predicate we isolate both paths, so
     498              :          pick the highest count for updating of the hottest predicate
     499              :          to unswitch on first.  */
     500         2785 :       if (!hottest || predicate->count > hottest->count)
     501              :         {
     502         1835 :           hottest = predicate;
     503         1835 :           hottest_bb = bb;
     504              :         }
     505              :     }
     506        27631 :   else if (gswitch *stmt = safe_dyn_cast <gswitch *> (last))
     507              :     {
     508          168 :       unsigned nlabels = gimple_switch_num_labels (stmt);
     509          168 :       tree idx = gimple_switch_index (stmt);
     510          168 :       tree idx_type = TREE_TYPE (idx);
     511          168 :       if (!gimple_range_ssa_p (idx) || nlabels < 1)
     512          136 :         return;
     513              :       /* Index must be invariant.  */
     514          167 :       def = SSA_NAME_DEF_STMT (idx);
     515          167 :       def_bb = gimple_bb (def);
     516          167 :       if (def_bb
     517          167 :           && flow_bb_inside_loop_p (loop, def_bb))
     518              :         return;
     519              :       /* Unswitching on undefined values would introduce undefined
     520              :          behavior that the original program might never exercise.  */
     521           51 :       if (is_maybe_undefined (idx, stmt, loop))
     522              :         return;
     523              :       /* Narrow OUTER_LOOP.  */
     524           32 :       while (outer_loop != loop
     525           32 :              && ((def_bb && flow_bb_inside_loop_p (outer_loop, def_bb))
     526            4 :                  || is_maybe_undefined (idx, stmt, outer_loop)))
     527            0 :         outer_loop = superloop_at_depth (loop,
     528            0 :                                          loop_depth (outer_loop) + 1);
     529              : 
     530              :       /* Build compound expression for all outgoing edges of the switch.  */
     531           32 :       auto_vec<tree, 16> preds;
     532           32 :       auto_vec<int_range_max> edge_range;
     533           64 :       preds.safe_grow_cleared (EDGE_COUNT (gimple_bb (stmt)->succs), true);
     534           64 :       edge_range.safe_grow_cleared (EDGE_COUNT (gimple_bb (stmt)->succs), true);
     535           32 :       edge e;
     536           32 :       edge_iterator ei;
     537           32 :       unsigned edge_index = 0;
     538          167 :       FOR_EACH_EDGE (e, ei, gimple_bb (stmt)->succs)
     539          135 :         e->aux = (void *)(uintptr_t)edge_index++;
     540          146 :       for (unsigned i = 1; i < gimple_switch_num_labels (stmt); ++i)
     541              :         {
     542          114 :           tree lab = gimple_switch_label (stmt, i);
     543          114 :           tree cmp;
     544          114 :           int_range<2> lab_range;
     545          114 :           tree low = fold_convert (idx_type, CASE_LOW (lab));
     546          114 :           if (CASE_HIGH (lab) != NULL_TREE)
     547              :             {
     548            3 :               tree high = fold_convert (idx_type, CASE_HIGH (lab));
     549            3 :               tree cmp1 = fold_build2 (GE_EXPR, boolean_type_node, idx, low);
     550            3 :               tree cmp2 = fold_build2 (LE_EXPR, boolean_type_node, idx, high);
     551            3 :               cmp = fold_build2 (BIT_AND_EXPR, boolean_type_node, cmp1, cmp2);
     552            3 :               lab_range.set (idx_type, wi::to_wide (low), wi::to_wide (high));
     553              :             }
     554              :           else
     555              :             {
     556          111 :               cmp = fold_build2 (EQ_EXPR, boolean_type_node, idx, low);
     557          111 :               wide_int w = wi::to_wide (low);
     558          111 :               lab_range.set (idx_type, w, w);
     559          111 :             }
     560              : 
     561              :           /* Combine the expression with the existing one.  */
     562          114 :           basic_block dest = label_to_block (cfun, CASE_LABEL (lab));
     563          114 :           e = find_edge (gimple_bb (stmt), dest);
     564          114 :           tree &expr = preds[(uintptr_t)e->aux];
     565          114 :           if (expr == NULL_TREE)
     566          106 :             expr = cmp;
     567              :           else
     568            8 :             expr = fold_build2 (BIT_IOR_EXPR, boolean_type_node, expr, cmp);
     569          114 :           edge_range[(uintptr_t)e->aux].union_ (lab_range);
     570          114 :         }
     571              : 
     572              :       /* Now register the predicates.  */
     573          167 :       for (edge_index = 0; edge_index < preds.length (); ++edge_index)
     574              :         {
     575          135 :           edge e = EDGE_SUCC (gimple_bb (stmt), edge_index);
     576          135 :           e->aux = NULL;
     577          135 :           if (preds[edge_index] != NULL_TREE)
     578              :             {
     579          106 :               unswitch_predicate *predicate
     580          106 :                 = new unswitch_predicate (preds[edge_index], idx,
     581              :                                           edge_index, e,
     582          106 :                                           edge_range[edge_index]);
     583          106 :               candidates.safe_push (predicate);
     584          106 :               if (!hottest || predicate->count > hottest->count)
     585              :                 {
     586           26 :                   hottest = predicate;
     587           26 :                   hottest_bb = bb;
     588              :                 }
     589              :             }
     590              :         }
     591           32 :     }
     592              : }
     593              : 
     594              : /* Merge ranges for the last item of PREDICATE_PATH with a predicate
     595              :    that shared the same LHS.  */
     596              : 
     597              : static void
     598         7614 : merge_last (predicate_vector &predicate_path)
     599              : {
     600         7614 :   unswitch_predicate *last_predicate = predicate_path.last ().first;
     601              : 
     602        11518 :   for (int i = predicate_path.length () - 2; i >= 0; i--)
     603              :     {
     604         4918 :       unswitch_predicate *predicate = predicate_path[i].first;
     605         4918 :       bool true_edge = predicate_path[i].second;
     606              : 
     607         4918 :       if (operand_equal_p (predicate->lhs, last_predicate->lhs, 0))
     608              :         {
     609         1014 :           irange &other = (true_edge ? predicate->merged_true_range
     610              :                            : predicate->merged_false_range);
     611         1014 :           last_predicate->merged_true_range.intersect (other);
     612         1014 :           last_predicate->merged_false_range.intersect (other);
     613         1014 :           return;
     614              :         }
     615              :     }
     616              : }
     617              : 
     618              : /* Add PREDICATE to PREDICATE_PATH on TRUE_EDGE.  */
     619              : 
     620              : static void
     621         7614 : add_predicate_to_path (predicate_vector &predicate_path,
     622              :                        unswitch_predicate *predicate, bool true_edge)
     623              : {
     624         7614 :   predicate->copy_merged_ranges ();
     625         7614 :   predicate_path.safe_push (std::make_pair (predicate, true_edge));
     626         7614 :   merge_last (predicate_path);
     627         7614 : }
     628              : 
     629              : static bool
     630         1301 : find_range_for_lhs (predicate_vector &predicate_path, tree lhs,
     631              :                     int_range_max &range)
     632              : {
     633         2616 :   for (int i = predicate_path.length () - 1; i >= 0; i--)
     634              :     {
     635         1301 :       unswitch_predicate *predicate = predicate_path[i].first;
     636         1301 :       bool true_edge = predicate_path[i].second;
     637              : 
     638         1301 :       if (operand_equal_p (predicate->lhs, lhs, 0))
     639              :         {
     640         1287 :           range = (true_edge ? predicate->merged_true_range
     641         1287 :                    : predicate->merged_false_range);
     642         1287 :           return !range.undefined_p ();
     643              :         }
     644              :     }
     645              : 
     646              :   return false;
     647              : }
     648              : 
     649              : /* Simplifies STMT using the predicate we unswitched on which is the last
     650              :    in PREDICATE_PATH.  For switch statements add newly unreachable edges
     651              :    to IGNORED_EDGES (but do not set IGNORED_EDGE_FLAG on them).  */
     652              : 
     653              : static tree
     654        65012 : evaluate_control_stmt_using_entry_checks (gimple *stmt,
     655              :                                           predicate_vector &predicate_path,
     656              :                                           int ignored_edge_flag,
     657              :                                           hash_set<edge> *ignored_edges)
     658              : {
     659        65012 :   unswitch_predicate *last_predicate = predicate_path.last ().first;
     660        65012 :   bool true_edge = predicate_path.last ().second;
     661              : 
     662        65012 :   if (gcond *cond = dyn_cast<gcond *> (stmt))
     663              :     {
     664        64638 :       tree lhs = gimple_cond_lhs (cond);
     665        64638 :       if (!operand_equal_p (lhs, last_predicate->lhs))
     666              :         return NULL_TREE;
     667              :       /* Try a symbolic match which works for floating point and fully
     668              :          symbolic conditions.  */
     669        19057 :       if (gimple_cond_code (cond) == TREE_CODE (last_predicate->condition)
     670        37555 :           && operand_equal_p (gimple_cond_rhs (cond),
     671        18498 :                               TREE_OPERAND (last_predicate->condition, 1)))
     672        18090 :         return true_edge ? boolean_true_node : boolean_false_node;
     673              :       /* Else try ranger if it supports LHS.  */
     674          967 :       else if (irange::supports_p (TREE_TYPE (lhs)))
     675              :         {
     676          967 :           int_range<2> r;
     677          967 :           int_range_max path_range;
     678              : 
     679          967 :           if (find_range_for_lhs (predicate_path, lhs, path_range)
     680          967 :               && fold_range (r, cond, path_range)
     681         1934 :               && r.singleton_p ())
     682          362 :             return r.zero_p () ? boolean_false_node : boolean_true_node;
     683          967 :         }
     684              :     }
     685          374 :   else if (gswitch *swtch = dyn_cast<gswitch *> (stmt))
     686              :     {
     687          374 :       unsigned nlabels = gimple_switch_num_labels (swtch);
     688              : 
     689          374 :       tree idx = gimple_switch_index (swtch);
     690              : 
     691              :       /* Already folded switch.  */
     692          374 :       if (TREE_CONSTANT (idx))
     693          207 :         return NULL_TREE;
     694              : 
     695          334 :       int_range_max path_range;
     696          334 :       if (!find_range_for_lhs (predicate_path, idx, path_range))
     697              :         return NULL_TREE;
     698              : 
     699              :       tree result = NULL_TREE;
     700              :       edge single_edge = NULL;
     701         2018 :       for (unsigned i = 0; i < nlabels; ++i)
     702              :         {
     703         1698 :           tree lab = gimple_switch_label (swtch, i);
     704         1698 :           basic_block dest = label_to_block (cfun, CASE_LABEL (lab));
     705         1698 :           edge e = find_edge (gimple_bb (stmt), dest);
     706         1698 :           if (e->flags & ignored_edge_flag)
     707          392 :             continue;
     708              : 
     709         1306 :           int_range_max r;
     710         1306 :           if (!ranger->gori ().edge_range_p (r, e, idx,
     711              :                                              *get_global_range_query ()))
     712            0 :             continue;
     713         1306 :           r.intersect (path_range);
     714         1306 :           if (r.undefined_p ())
     715          643 :             ignored_edges->add (e);
     716              :           else
     717              :             {
     718          663 :               if (!single_edge)
     719              :                 {
     720          320 :                   single_edge = e;
     721          320 :                   result = CASE_LOW (lab);
     722              :                 }
     723          343 :               else if (single_edge != e)
     724         1306 :                 result = NULL;
     725              :             }
     726         1306 :         }
     727              : 
     728              :       /* Only one edge from the switch is alive.  */
     729          320 :       if (single_edge && result)
     730              :         return result;
     731          334 :     }
     732              : 
     733              :   return NULL_TREE;
     734              : }
     735              : 
     736              : /* Simplify LOOP based on PREDICATE_PATH where dead edges are properly
     737              :    marked.  */
     738              : 
     739              : static bool
     740         4826 : simplify_loop_version (class loop *loop, predicate_vector &predicate_path,
     741              :                        int ignored_edge_flag, bitmap handled)
     742              : {
     743         4826 :   bool changed = false;
     744         4826 :   basic_block *bbs = get_loop_body (loop);
     745              : 
     746         4826 :   hash_set<edge> ignored_edges;
     747        48708 :   for (unsigned i = 0; i != loop->num_nodes; i++)
     748              :     {
     749        43882 :       vec<unswitch_predicate *> &predicates = get_predicates_for_bb (bbs[i]);
     750        43882 :       if (predicates.is_empty ())
     751        33756 :         continue;
     752              : 
     753        10126 :       gimple *stmt = *gsi_last_bb (bbs[i]);
     754        10126 :       tree folded = evaluate_control_stmt_using_entry_checks (stmt,
     755              :                                                               predicate_path,
     756              :                                                               ignored_edge_flag,
     757              :                                                               &ignored_edges);
     758              : 
     759        10126 :       if (gcond *cond = dyn_cast<gcond *> (stmt))
     760              :         {
     761         9942 :           if (folded)
     762              :             {
     763              :               /* Remove path.  */
     764         5462 :               if (integer_nonzerop (folded))
     765         2668 :                 gimple_cond_set_condition_from_tree (cond, boolean_true_node);
     766              :               else
     767         2794 :                 gimple_cond_set_condition_from_tree (cond, boolean_false_node);
     768              : 
     769         5462 :               gcc_assert (predicates.length () == 1);
     770         5462 :               bitmap_set_bit (handled, predicates[0]->num);
     771              : 
     772         5462 :               update_stmt (cond);
     773         5462 :               changed = true;
     774              :             }
     775              :         }
     776        44066 :       else if (gswitch *swtch = dyn_cast<gswitch *> (stmt))
     777              :         {
     778          184 :           edge e;
     779          184 :           edge_iterator ei;
     780          968 :           FOR_EACH_EDGE (e, ei, bbs[i]->succs)
     781          784 :             if (ignored_edges.contains (e))
     782          274 :               e->flags |= ignored_edge_flag;
     783              : 
     784          790 :           for (unsigned j = 0; j < predicates.length (); j++)
     785              :             {
     786          606 :               edge e = EDGE_SUCC (bbs[i], predicates[j]->edge_index);
     787          606 :               if (ignored_edges.contains (e))
     788          204 :                 bitmap_set_bit (handled, predicates[j]->num);
     789              :             }
     790              : 
     791          184 :           if (folded)
     792              :             {
     793           70 :               gimple_switch_set_index (swtch, folded);
     794           70 :               update_stmt (swtch);
     795           70 :               changed = true;
     796              :             }
     797              :         }
     798              :     }
     799              : 
     800         4826 :   free (bbs);
     801         4826 :   return changed;
     802         4826 : }
     803              : 
     804              : /* Evaluate reachable blocks in LOOP and call VISIT on them, aborting the
     805              :    DFS walk if VISIT returns true.  When PREDICATE_PATH is specified then
     806              :    take into account that when computing reachability, otherwise just
     807              :    look at the simplified state and IGNORED_EDGE_FLAG.  */
     808              : 
     809              : template <typename VisitOp>
     810              : static void
     811        68070 : evaluate_bbs (class loop *loop, predicate_vector *predicate_path,
     812              :               int ignored_edge_flag, VisitOp visit)
     813              : {
     814        68070 :   auto_bb_flag reachable_flag (cfun);
     815        68070 :   auto_vec<basic_block, 10> worklist (loop->num_nodes);
     816        68070 :   auto_vec<basic_block, 10> reachable (loop->num_nodes);
     817        68070 :   hash_set<edge> ignored_edges;
     818              : 
     819        68070 :   loop->header->flags |= reachable_flag;
     820        68070 :   worklist.quick_push (loop->header);
     821        68070 :   reachable.safe_push (loop->header);
     822              : 
     823       639389 :   while (!worklist.is_empty ())
     824              :     {
     825              :       edge e;
     826              :       edge_iterator ei;
     827       572022 :       int flags = ignored_edge_flag;
     828       572022 :       basic_block bb = worklist.pop ();
     829              : 
     830       572022 :       if (visit (bb))
     831              :         break;
     832              : 
     833       571319 :       gimple *last = *gsi_last_bb (bb);
     834       296061 :       if (gcond *cond = safe_dyn_cast <gcond *> (last))
     835              :         {
     836       275258 :           if (gimple_cond_true_p (cond))
     837              :             flags = EDGE_FALSE_VALUE;
     838       269182 :           else if (gimple_cond_false_p (cond))
     839              :             flags = EDGE_TRUE_VALUE;
     840       262151 :           else if (predicate_path)
     841              :             {
     842              :               tree res;
     843       113666 :               if (!get_predicates_for_bb (bb).is_empty ()
     844        54696 :                   && (res = evaluate_control_stmt_using_entry_checks
     845        54696 :                               (cond, *predicate_path, ignored_edge_flag,
     846              :                                &ignored_edges)))
     847        19534 :                 flags = (integer_nonzerop (res)
     848        12990 :                          ? EDGE_FALSE_VALUE : EDGE_TRUE_VALUE);
     849              :             }
     850              :         }
     851       571783 :       else if (gswitch *swtch = safe_dyn_cast<gswitch *> (last))
     852              :         if (predicate_path
     853       571783 :             && !get_predicates_for_bb (bb).is_empty ())
     854          190 :           evaluate_control_stmt_using_entry_checks (swtch, *predicate_path,
     855              :                                                     ignored_edge_flag,
     856              :                                                     &ignored_edges);
     857              : 
     858              :       /* Note that for the moment we do not account reachable conditions
     859              :          which are simplified to take a known edge as zero size nor
     860              :          are we accounting for the required addition of the versioning
     861              :          condition.  Those should cancel out conservatively.  */
     862              : 
     863      1420214 :       FOR_EACH_EDGE (e, ei, bb->succs)
     864              :         {
     865       848895 :           basic_block dest = e->dest;
     866              : 
     867       848895 :           if (flow_bb_inside_loop_p (loop, dest)
     868       739271 :               && !(dest->flags & reachable_flag)
     869       528441 :               && !(e->flags & flags)
     870      1353167 :               && !ignored_edges.contains (e))
     871              :             {
     872       504016 :               dest->flags |= reachable_flag;
     873       504016 :               worklist.safe_push (dest);
     874       504016 :               reachable.safe_push (dest);
     875              :             }
     876              :         }
     877              :     }
     878              : 
     879              :   /* Clear the flag from basic blocks.  */
     880       708226 :   while (!reachable.is_empty ())
     881       572086 :     reachable.pop ()->flags &= ~reachable_flag;
     882        68070 : }
     883              : 
     884              : /* Evaluate how many instruction will we have if we unswitch LOOP (with BBS)
     885              :    based on PREDICATE predicate (using PREDICATE_PATH).  Store the
     886              :    result in TRUE_SIZE and FALSE_SIZE.  */
     887              : 
     888              : static void
     889         1394 : evaluate_loop_insns_for_predicate (class loop *loop,
     890              :                                    predicate_vector &predicate_path,
     891              :                                    unswitch_predicate *predicate,
     892              :                                    int ignored_edge_flag,
     893              :                                    unsigned *true_size, unsigned *false_size)
     894              : {
     895         1394 :   unsigned size = 0;
     896       260063 :   auto sum_size = [&](basic_block bb) -> bool
     897       258669 :     { size += (uintptr_t)bb->aux; return false; };
     898              : 
     899         1394 :   add_predicate_to_path (predicate_path, predicate, true);
     900         1394 :   evaluate_bbs (loop, &predicate_path, ignored_edge_flag, sum_size);
     901         1394 :   predicate_path.pop ();
     902         1394 :   unsigned true_loop_cost = size;
     903              : 
     904         1394 :   size = 0;
     905         1394 :   add_predicate_to_path (predicate_path, predicate, false);
     906         1394 :   evaluate_bbs (loop, &predicate_path, ignored_edge_flag, sum_size);
     907         1394 :   predicate_path.pop ();
     908         1394 :   unsigned false_loop_cost = size;
     909              : 
     910         1394 :   *true_size = true_loop_cost;
     911         1394 :   *false_size = false_loop_cost;
     912         1394 : }
     913              : 
     914              : /* Unswitch single LOOP.  PREDICATE_PATH contains so far used predicates
     915              :    for unswitching.  BUDGET is number of instruction for which we can increase
     916              :    the loop and is updated when unswitching occurs.  If HOTTEST is not
     917              :    NULL then pick this candidate as the one to unswitch on.  */
     918              : 
     919              : static bool
     920        67000 : tree_unswitch_single_loop (class loop *loop, dump_user_location_t loc,
     921              :                            predicate_vector &predicate_path,
     922              :                            unsigned loop_size, unsigned &budget,
     923              :                            int ignored_edge_flag, bitmap handled,
     924              :                            unswitch_predicate *hottest, basic_block hottest_bb)
     925              : {
     926        67000 :   class loop *nloop;
     927        67000 :   bool changed = false;
     928        67000 :   unswitch_predicate *predicate = NULL;
     929        67000 :   basic_block predicate_bb = NULL;
     930        67000 :   unsigned true_size = 0, false_size = 0;
     931              : 
     932       380353 :   auto check_predicates = [&](basic_block bb) -> bool
     933              :     {
     934       337123 :       for (auto pred : get_predicates_for_bb (bb))
     935              :         {
     936         8387 :           if (bitmap_bit_p (handled, pred->num))
     937         6993 :             continue;
     938              : 
     939         1394 :           evaluate_loop_insns_for_predicate (loop, predicate_path,
     940              :                                              pred, ignored_edge_flag,
     941              :                                              &true_size, &false_size);
     942              : 
     943              :           /* We'll get LOOP replaced with a simplified version according
     944              :              to PRED estimated to TRUE_SIZE and a copy simplified
     945              :              according to the inverted PRED estimated to FALSE_SIZE.  */
     946         1394 :           if (true_size + false_size < budget + loop_size)
     947              :             {
     948          703 :               predicate = pred;
     949          703 :               predicate_bb = bb;
     950              : 
     951              :               /* There are cases where true_size and false_size add up to
     952              :                  less than the original loop_size.  We do not want to
     953              :                  grow the remaining budget because of that.  */
     954          703 :               if (true_size + false_size > loop_size)
     955          703 :                 budget -= (true_size + false_size - loop_size);
     956              : 
     957              :               /* FIXME: right now we select first candidate, but we can
     958              :                  choose the cheapest or hottest one.  */
     959          703 :               return true;
     960              :             }
     961          691 :           else if (dump_enabled_p ())
     962           13 :             dump_printf_loc (MSG_NOTE, loc,
     963              :                              "not unswitching condition, cost too big "
     964              :                              "(%u insns copied to %u and %u)\n", loop_size,
     965              :                              true_size, false_size);
     966              :         }
     967              :       return false;
     968        67000 :     };
     969              : 
     970        67000 :   if (hottest)
     971              :     {
     972         1718 :       predicate = hottest;
     973         1718 :       predicate_bb = hottest_bb;
     974              :     }
     975              :   else
     976              :     /* Check predicates of reachable blocks.  */
     977        65282 :     evaluate_bbs (loop, NULL, ignored_edge_flag, check_predicates);
     978              : 
     979        67000 :   if (predicate != NULL)
     980              :     {
     981         2421 :       if (!dbg_cnt (loop_unswitch))
     982            0 :         goto exit;
     983              : 
     984         2421 :       if (dump_enabled_p ())
     985              :         {
     986          101 :           dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, loc,
     987              :                            "unswitching %sloop %d on %qs with condition: %T\n",
     988          101 :                            loop->inner ? "outer " : "",
     989          101 :                            loop->num, predicate->switch_p ? "switch" : "if",
     990              :                            predicate->condition);
     991          101 :           dump_printf_loc (MSG_NOTE, loc,
     992              :                            "optimized sizes estimated to %u (true) "
     993              :                            "and %u (false) from original size %u\n",
     994              :                            true_size, false_size, loop_size);
     995              :         }
     996              : 
     997         2421 :       bitmap_set_bit (handled, predicate->num);
     998         2421 :       initialize_original_copy_tables ();
     999              :       /* Unswitch the loop on this condition.  */
    1000         2421 :       nloop = tree_unswitch_loop (loop, EDGE_SUCC (predicate_bb,
    1001              :                                                    predicate->edge_index),
    1002              :                                   predicate->condition);
    1003         2421 :       if (!nloop)
    1004              :         {
    1005            8 :           free_original_copy_tables ();
    1006            8 :           goto exit;
    1007              :         }
    1008              : 
    1009              :       /* Copy BB costs.  */
    1010         2413 :       basic_block *bbs2 = get_loop_body (nloop);
    1011        24354 :       for (unsigned i = 0; i < nloop->num_nodes; i++)
    1012        21941 :         bbs2[i]->aux = get_bb_original (bbs2[i])->aux;
    1013         2413 :       free (bbs2);
    1014              : 
    1015         2413 :       free_original_copy_tables ();
    1016              : 
    1017              :       /* Update the SSA form after unswitching.  */
    1018         2413 :       update_ssa (TODO_update_ssa_no_phi);
    1019              : 
    1020              :       /* Invoke itself on modified loops.  */
    1021         2413 :       bitmap handled_copy = BITMAP_ALLOC (NULL);
    1022         2413 :       bitmap_copy (handled_copy, handled);
    1023         2413 :       add_predicate_to_path (predicate_path, predicate, false);
    1024         2413 :       changed |= simplify_loop_version (nloop, predicate_path,
    1025              :                                         ignored_edge_flag, handled_copy);
    1026         2413 :       tree_unswitch_single_loop (nloop, loc, predicate_path,
    1027              :                                  false_size, budget,
    1028              :                                  ignored_edge_flag, handled_copy);
    1029         2413 :       predicate_path.pop ();
    1030         2413 :       BITMAP_FREE (handled_copy);
    1031              : 
    1032              :       /* FIXME: After unwinding above we have to reset all ->handled
    1033              :          flags as otherwise we fail to realize unswitching opportunities
    1034              :          in the below recursion.  See gcc.dg/loop-unswitch-16.c  */
    1035         2413 :       add_predicate_to_path (predicate_path, predicate, true);
    1036         2413 :       changed |= simplify_loop_version (loop, predicate_path,
    1037              :                                         ignored_edge_flag, handled);
    1038         2413 :       tree_unswitch_single_loop (loop, loc, predicate_path,
    1039              :                                  true_size, budget,
    1040              :                                  ignored_edge_flag, handled);
    1041         2413 :       predicate_path.pop ();
    1042         2413 :       changed = true;
    1043              :     }
    1044              : 
    1045        64579 : exit:
    1046        67000 :   return changed;
    1047              : }
    1048              : 
    1049              : /* Unswitch a LOOP w.r. to given EDGE_TRUE.  We only support unswitching of
    1050              :    innermost loops.  COND is the condition determining which loop is entered;
    1051              :    the new loop is entered if COND is true.  Returns NULL if impossible, new
    1052              :    loop otherwise.  */
    1053              : 
    1054              : static class loop *
    1055         2421 : tree_unswitch_loop (class loop *loop, edge edge_true, tree cond)
    1056              : {
    1057              :   /* Some sanity checking.  */
    1058         2421 :   gcc_assert (flow_bb_inside_loop_p (loop, edge_true->src));
    1059         2421 :   gcc_assert (EDGE_COUNT (edge_true->src->succs) >= 2);
    1060              : 
    1061         2421 :   profile_probability prob_true = edge_true->probability;
    1062         2421 :   return loop_version (loop, unshare_expr (cond),
    1063              :                        NULL, prob_true,
    1064              :                        prob_true.invert (),
    1065              :                        prob_true, prob_true.invert (),
    1066         2421 :                        false);
    1067              : }
    1068              : 
    1069              : /* Unswitch outer loops by hoisting invariant guard on
    1070              :    inner loop without code duplication.  */
    1071              : static bool
    1072        14477 : tree_unswitch_outer_loop (class loop *loop)
    1073              : {
    1074        14477 :   edge exit, guard;
    1075        14477 :   HOST_WIDE_INT iterations;
    1076              : 
    1077        14477 :   gcc_assert (loop->inner);
    1078        14477 :   if (loop->inner->next)
    1079              :     return false;
    1080              :   /* Accept loops with single exit only which is not from inner loop.  */
    1081        12284 :   exit = single_exit (loop);
    1082        12284 :   if (!exit || exit->src->loop_father != loop)
    1083              :     return false;
    1084              :   /* Check that phi argument of exit edge is not defined inside loop.  */
    1085         8503 :   if (!check_exit_phi (loop))
    1086              :     return false;
    1087              :   /* If the loop is not expected to iterate, there is no need
    1088              :       for unswitching.  */
    1089         6092 :   iterations = estimated_loop_iterations_int (loop);
    1090         6092 :   if (iterations < 0)
    1091         3698 :     iterations = likely_max_loop_iterations_int (loop);
    1092         6092 :   if (iterations >= 0 && iterations <= 1)
    1093              :     {
    1094          275 :       if (dump_enabled_p ())
    1095            0 :         dump_printf_loc (MSG_MISSED_OPTIMIZATION, find_loop_location (loop),
    1096              :                          "Not unswitching, loop is not expected"
    1097              :                          " to iterate\n");
    1098          275 :       return false;
    1099              :     }
    1100              : 
    1101         5817 :   bool changed = false;
    1102         5817 :   auto_vec<gimple *> dbg_to_reset;
    1103         7561 :   while ((guard = find_loop_guard (loop, dbg_to_reset)))
    1104              :     {
    1105         1744 :       hoist_guard (loop, guard);
    1106         1744 :       for (gimple *debug_stmt : dbg_to_reset)
    1107              :         {
    1108            0 :           gimple_debug_bind_reset_value (debug_stmt);
    1109            0 :           update_stmt (debug_stmt);
    1110              :         }
    1111         1744 :       dbg_to_reset.truncate (0);
    1112         1744 :       changed = true;
    1113              :     }
    1114         5817 :   return changed;
    1115         5817 : }
    1116              : 
    1117              : /* Checks if the body of the LOOP is within an invariant guard.  If this
    1118              :    is the case, returns the edge that jumps over the real body of the loop,
    1119              :    otherwise returns NULL.  */
    1120              : 
    1121              : static edge
    1122         7561 : find_loop_guard (class loop *loop, vec<gimple *> &dbg_to_reset)
    1123              : {
    1124         7561 :   basic_block header = loop->header;
    1125         7561 :   edge guard_edge, te, fe;
    1126         7561 :   basic_block *body = NULL;
    1127        14814 :   unsigned i;
    1128        14814 :   tree use;
    1129        14814 :   ssa_op_iter iter;
    1130              : 
    1131              :   /* We check for the following situation:
    1132              : 
    1133              :      while (1)
    1134              :        {
    1135              :          [header]]
    1136              :          loop_phi_nodes;
    1137              :          something1;
    1138              :          if (cond1)
    1139              :            body;
    1140              :          nvar = phi(orig, bvar) ... for all variables changed in body;
    1141              :          [guard_end]
    1142              :          something2;
    1143              :          if (cond2)
    1144              :            break;
    1145              :          something3;
    1146              :        }
    1147              : 
    1148              :      where:
    1149              : 
    1150              :      1) cond1 is loop invariant
    1151              :      2) If cond1 is false, then the loop is essentially empty; i.e.,
    1152              :         a) nothing in something1, something2 and something3 has side
    1153              :            effects
    1154              :         b) anything defined in something1, something2 and something3
    1155              :            is not used outside of the loop.  */
    1156              : 
    1157        14814 :   gcond *cond;
    1158        14814 :   do
    1159              :     {
    1160        14814 :       basic_block next = NULL;
    1161        14814 :       if (single_succ_p (header))
    1162         4434 :         next = single_succ (header);
    1163              :       else
    1164              :         {
    1165        26415 :           cond = safe_dyn_cast <gcond *> (*gsi_last_bb (header));
    1166        10380 :           if (! cond)
    1167              :             return NULL;
    1168        10380 :           extract_true_false_edges_from_block (header, &te, &fe);
    1169              :           /* Make sure to skip earlier hoisted guards that are left
    1170              :              in place as if (true).  */
    1171        10380 :           if (gimple_cond_true_p (cond))
    1172          323 :             next = te->dest;
    1173        10057 :           else if (gimple_cond_false_p (cond))
    1174         2496 :             next = fe->dest;
    1175              :           else
    1176              :             break;
    1177              :         }
    1178              :       /* Never traverse a backedge.  */
    1179         7253 :       if (header->loop_father->header == next)
    1180              :         return NULL;
    1181              :       header = next;
    1182              :     }
    1183              :   while (1);
    1184         7561 :   if (!flow_bb_inside_loop_p (loop, te->dest)
    1185         7561 :       || !flow_bb_inside_loop_p (loop, fe->dest))
    1186           79 :     return NULL;
    1187              : 
    1188         7482 :   if (just_once_each_iteration_p (loop, te->dest)
    1189         7482 :       || (single_succ_p (te->dest)
    1190         4442 :           && just_once_each_iteration_p (loop, single_succ (te->dest))))
    1191              :     {
    1192         3812 :       if (just_once_each_iteration_p (loop, fe->dest))
    1193              :         return NULL;
    1194         3802 :       guard_edge = te;
    1195              :     }
    1196         3670 :   else if (just_once_each_iteration_p (loop, fe->dest)
    1197         3670 :            || (single_succ_p (fe->dest)
    1198         1905 :                && just_once_each_iteration_p (loop, single_succ (fe->dest))))
    1199         2191 :     guard_edge = fe;
    1200              :   else
    1201         1479 :     return NULL;
    1202              : 
    1203         5993 :   dump_user_location_t loc = find_loop_location (loop);
    1204              : 
    1205              :   /* Guard edge must skip inner loop.  */
    1206         5993 :   if (!dominated_by_p (CDI_DOMINATORS, loop->inner->header,
    1207         5993 :       guard_edge == fe ? te->dest : fe->dest))
    1208              :     {
    1209         2383 :       if (dump_enabled_p ())
    1210            4 :         dump_printf_loc (MSG_MISSED_OPTIMIZATION, loc,
    1211              :                          "Guard edge %d --> %d is not around the loop!\n",
    1212            4 :                          guard_edge->src->index, guard_edge->dest->index);
    1213         2383 :       return NULL;
    1214              :     }
    1215         3610 :   if (guard_edge->dest == loop->latch)
    1216              :     {
    1217            0 :       if (dump_enabled_p ())
    1218            0 :         dump_printf_loc (MSG_MISSED_OPTIMIZATION, loc,
    1219              :                          "Guard edge destination is loop latch.\n");
    1220            0 :       return NULL;
    1221              :     }
    1222              : 
    1223         3610 :   if (dump_enabled_p ())
    1224          103 :     dump_printf_loc (MSG_NOTE, loc,
    1225              :                      "Considering guard %d -> %d in loop %d\n",
    1226          103 :                      guard_edge->src->index, guard_edge->dest->index,
    1227              :                      loop->num);
    1228              :   /* Check if condition operands do not have definitions inside loop since
    1229              :      any bb copying is not performed.  */
    1230         6402 :   FOR_EACH_SSA_TREE_OPERAND (use, cond, iter, SSA_OP_USE)
    1231              :     {
    1232         4496 :       gimple *def = SSA_NAME_DEF_STMT (use);
    1233         4496 :       basic_block def_bb = gimple_bb (def);
    1234         4496 :       if (def_bb
    1235         4496 :           && flow_bb_inside_loop_p (loop, def_bb))
    1236              :         {
    1237         1704 :           if (dump_enabled_p ())
    1238           96 :             dump_printf_loc (MSG_NOTE, loc, "guard operands have definitions"
    1239              :                              " inside loop\n");
    1240         1704 :           return NULL;
    1241              :         }
    1242              :     }
    1243              : 
    1244         1906 :   body = get_loop_body (loop);
    1245        22139 :   for (i = 0; i < loop->num_nodes; i++)
    1246              :     {
    1247        20395 :       basic_block bb = body[i];
    1248        20395 :       if (bb->loop_father != loop)
    1249        10315 :         continue;
    1250        10080 :       if (bb->flags & BB_IRREDUCIBLE_LOOP)
    1251              :         {
    1252            0 :           if (dump_enabled_p ())
    1253            0 :             dump_printf_loc (MSG_MISSED_OPTIMIZATION, loc,
    1254              :                              "Block %d is marked as irreducible in loop\n",
    1255              :                              bb->index);
    1256            0 :           guard_edge = NULL;
    1257            0 :           goto end;
    1258              :         }
    1259              :       /* If any of the not skipped blocks has side-effects or defs with
    1260              :          uses outside of the loop we cannot hoist the guard.  */
    1261        10080 :       if (!dominated_by_p (CDI_DOMINATORS,
    1262        10080 :                            bb, guard_edge == te ? fe->dest : te->dest)
    1263        10080 :           && !empty_bb_without_guard_p (loop, bb, dbg_to_reset))
    1264              :         {
    1265          162 :           if (dump_enabled_p ())
    1266            0 :             dump_printf_loc (MSG_MISSED_OPTIMIZATION, loc,
    1267              :                              "Block %d has side effects\n", bb->index);
    1268          162 :           guard_edge = NULL;
    1269          162 :           goto end;
    1270              :         }
    1271              :     }
    1272              : 
    1273         1744 :   if (dump_enabled_p ())
    1274            7 :     dump_printf_loc (MSG_NOTE, loc,
    1275              :                      "suitable to hoist\n");
    1276         1737 : end:
    1277         1906 :   if (body)
    1278         1906 :     free (body);
    1279              :   return guard_edge;
    1280              : }
    1281              : 
    1282              : /* Returns true if
    1283              :    1) no statement in BB has side effects
    1284              :    2) assuming that edge GUARD is always taken, all definitions in BB
    1285              :       are noy used outside of the loop.
    1286              :    KNOWN_INVARIANTS is a set of ssa names we know to be invariant, and
    1287              :    PROCESSED is a set of ssa names for that we already tested whether they
    1288              :    are invariant or not.  Uses in debug stmts outside of the loop are
    1289              :    pushed to DBG_TO_RESET.  */
    1290              : 
    1291              : static bool
    1292         7077 : empty_bb_without_guard_p (class loop *loop, basic_block bb,
    1293              :                           vec<gimple *> &dbg_to_reset)
    1294              : {
    1295         7077 :   basic_block exit_bb = single_exit (loop)->src;
    1296         7077 :   bool may_be_used_outside = (bb == exit_bb
    1297         7077 :                               || !dominated_by_p (CDI_DOMINATORS, bb, exit_bb));
    1298         5189 :   tree name;
    1299         5189 :   ssa_op_iter op_iter;
    1300              : 
    1301              :   /* Phi nodes do not have side effects, but their results might be used
    1302              :      outside of the loop.  */
    1303         5189 :   if (may_be_used_outside)
    1304              :     {
    1305         5189 :       for (gphi_iterator gsi = gsi_start_phis (bb);
    1306        11099 :            !gsi_end_p (gsi); gsi_next (&gsi))
    1307              :         {
    1308         5910 :           gphi *phi = gsi.phi ();
    1309         5910 :           name = PHI_RESULT (phi);
    1310        11820 :           if (virtual_operand_p (name))
    1311         3735 :             continue;
    1312              : 
    1313         2175 :           if (used_outside_loop_p (loop, name, dbg_to_reset))
    1314            0 :             return false;
    1315              :         }
    1316              :     }
    1317              : 
    1318        14154 :   for (gimple_stmt_iterator gsi = gsi_start_bb (bb);
    1319        16434 :        !gsi_end_p (gsi); gsi_next (&gsi))
    1320              :     {
    1321         9519 :       gimple *stmt = gsi_stmt (gsi);
    1322         9519 :       if (is_gimple_debug (stmt))
    1323         1094 :         continue;
    1324              : 
    1325         8425 :       if (gimple_has_side_effects (stmt))
    1326              :         return false;
    1327              : 
    1328        12422 :       if (gimple_vdef(stmt))
    1329              :         return false;
    1330              : 
    1331        12300 :       FOR_EACH_SSA_TREE_OPERAND (name, stmt, op_iter, SSA_OP_DEF)
    1332              :         {
    1333         4037 :           if (may_be_used_outside
    1334         4037 :               && used_outside_loop_p (loop, name, dbg_to_reset))
    1335              :             return false;
    1336              :         }
    1337              :     }
    1338              :   return true;
    1339              : }
    1340              : 
    1341              : /* Return true if NAME is used outside of LOOP.  Pushes debug stmts that
    1342              :    have such uses to DBG_TO_RESET but do not consider such uses.  */
    1343              : 
    1344              : static bool
    1345         6190 : used_outside_loop_p (class loop *loop, tree name, vec<gimple *> &dbg_to_reset)
    1346              : {
    1347         6190 :   imm_use_iterator it;
    1348         6190 :   use_operand_p use;
    1349              : 
    1350        24231 :   FOR_EACH_IMM_USE_FAST (use, it, name)
    1351              :     {
    1352        11851 :       gimple *stmt = USE_STMT (use);
    1353        11851 :       if (!flow_bb_inside_loop_p (loop, gimple_bb (stmt)))
    1354              :         {
    1355            0 :           if (!is_gimple_debug (stmt))
    1356            0 :             return true;
    1357            0 :           dbg_to_reset.safe_push (stmt);
    1358              :         }
    1359            0 :     }
    1360              : 
    1361         6190 :   return false;
    1362              : }
    1363              : 
    1364              : /* Return argument for loop preheader edge in header virtual phi if any.  */
    1365              : 
    1366              : static tree
    1367         1733 : get_vop_from_header (class loop *loop)
    1368              : {
    1369         1733 :   for (gphi_iterator gsi = gsi_start_phis (loop->header);
    1370         3492 :        !gsi_end_p (gsi); gsi_next (&gsi))
    1371              :     {
    1372         3492 :       gphi *phi = gsi.phi ();
    1373         6984 :       if (!virtual_operand_p (gimple_phi_result (phi)))
    1374         1759 :         continue;
    1375         1733 :       return PHI_ARG_DEF_FROM_EDGE (phi, loop_preheader_edge (loop));
    1376              :     }
    1377            0 :   return NULL_TREE;
    1378              : }
    1379              : 
    1380              : /* Move the check of GUARD outside of LOOP.  */
    1381              : 
    1382              : static void
    1383         1744 : hoist_guard (class loop *loop, edge guard)
    1384              : {
    1385         1744 :   edge exit = single_exit (loop);
    1386         1744 :   edge preh = loop_preheader_edge (loop);
    1387         1744 :   basic_block pre_header = preh->src;
    1388         1744 :   basic_block bb;
    1389         1744 :   edge te, fe, e, new_edge;
    1390         1744 :   gimple *stmt;
    1391         1744 :   basic_block guard_bb = guard->src;
    1392         1744 :   edge not_guard;
    1393         1744 :   gimple_stmt_iterator gsi;
    1394         1744 :   int flags = 0;
    1395         1744 :   bool fix_dom_of_exit;
    1396         1744 :   gcond *cond_stmt, *new_cond_stmt;
    1397              : 
    1398         1744 :   bb = get_immediate_dominator (CDI_DOMINATORS, exit->dest);
    1399         1744 :   fix_dom_of_exit = flow_bb_inside_loop_p (loop, bb);
    1400         1744 :   gsi = gsi_last_bb (guard_bb);
    1401         1744 :   stmt = gsi_stmt (gsi);
    1402         1744 :   gcc_assert (gimple_code (stmt) == GIMPLE_COND);
    1403         1744 :   cond_stmt = as_a <gcond *> (stmt);
    1404         1744 :   extract_true_false_edges_from_block (guard_bb, &te, &fe);
    1405              :   /* Insert guard to PRE_HEADER.  */
    1406         1744 :   gsi = gsi_last_bb (pre_header);
    1407              :   /* Create copy of COND_STMT.  */
    1408         1744 :   new_cond_stmt = gimple_build_cond (gimple_cond_code (cond_stmt),
    1409              :                                      gimple_cond_lhs (cond_stmt),
    1410              :                                      gimple_cond_rhs (cond_stmt),
    1411              :                                      NULL_TREE, NULL_TREE);
    1412         1744 :   gsi_insert_after (&gsi, new_cond_stmt, GSI_NEW_STMT);
    1413              :   /* Convert COND_STMT to true/false conditional.  */
    1414         1744 :   if (guard == te)
    1415         1546 :     gimple_cond_make_false (cond_stmt);
    1416              :   else
    1417          198 :     gimple_cond_make_true (cond_stmt);
    1418         1744 :   update_stmt (cond_stmt);
    1419              :   /* Create new loop pre-header.  */
    1420         1744 :   e = split_block (pre_header, last_nondebug_stmt (pre_header));
    1421              : 
    1422         1744 :   dump_user_location_t loc = find_loop_location (loop);
    1423              : 
    1424         1744 :   if (dump_enabled_p ())
    1425              :     {
    1426            7 :       char buffer[64];
    1427            7 :       guard->probability.dump (buffer);
    1428              : 
    1429            7 :       dump_printf_loc (MSG_NOTE, loc,
    1430              :                        "Moving guard %i->%i (prob %s) to bb %i, "
    1431              :                        "new preheader is %i\n",
    1432            7 :                        guard->src->index, guard->dest->index,
    1433            7 :                        buffer, e->src->index, e->dest->index);
    1434              :     }
    1435              : 
    1436         1744 :   gcc_assert (loop_preheader_edge (loop)->src == e->dest);
    1437              : 
    1438         1744 :   if (guard == fe)
    1439              :     {
    1440          198 :       e->flags = EDGE_TRUE_VALUE;
    1441          198 :       flags |= EDGE_FALSE_VALUE;
    1442          198 :       not_guard = te;
    1443              :     }
    1444              :   else
    1445              :     {
    1446         1546 :       e->flags = EDGE_FALSE_VALUE;
    1447         1546 :       flags |= EDGE_TRUE_VALUE;
    1448         1546 :       not_guard = fe;
    1449              :     }
    1450         1744 :   new_edge = make_edge (pre_header, exit->dest, flags);
    1451              : 
    1452              :   /* Determine the probability that we skip the loop.  Assume that loop has
    1453              :      same average number of iterations regardless outcome of guard.  */
    1454         1744 :   new_edge->probability = guard->probability;
    1455         3488 :   profile_count skip_count = guard->src->count.nonzero_p ()
    1456         3488 :                    ? guard->count ().apply_scale (pre_header->count,
    1457         1744 :                                                guard->src->count)
    1458            0 :                    : guard->count ().apply_probability (new_edge->probability);
    1459              : 
    1460         1744 :   if (skip_count > e->count ())
    1461              :     {
    1462            0 :       if (dump_file && (dump_flags & TDF_DETAILS))
    1463            0 :         fprintf (dump_file, "  Capping count; expect profile inconsistency\n");
    1464            0 :       skip_count = e->count ();
    1465              :     }
    1466         1744 :   if (dump_enabled_p ())
    1467              :     {
    1468            7 :       char buffer[64];
    1469            7 :       new_edge->probability.dump (buffer);
    1470              : 
    1471            7 :       dump_printf_loc (MSG_NOTE, loc,
    1472              :                        "Estimated probability of skipping loop is %s\n",
    1473              :                        buffer);
    1474              :     }
    1475              : 
    1476              :   /* Update profile after the transform:
    1477              : 
    1478              :      First decrease count of path from newly hoisted loop guard
    1479              :      to loop header...  */
    1480         1744 :   e->probability = new_edge->probability.invert ();
    1481         1744 :   e->dest->count = e->count ();
    1482              : 
    1483              :   /* ... now update profile to represent that original guard will be optimized
    1484              :      away ...  */
    1485         1744 :   guard->probability = profile_probability::never ();
    1486         1744 :   not_guard->probability = profile_probability::always ();
    1487              : 
    1488              :   /* ... finally scale everything in the loop except for guarded basic blocks
    1489              :      where profile does not change.  */
    1490         1744 :   basic_block *body = get_loop_body (loop);
    1491              : 
    1492        21681 :   for (unsigned int i = 0; i < loop->num_nodes; i++)
    1493              :     {
    1494        19937 :       basic_block bb = body[i];
    1495        19937 :       if (!dominated_by_p (CDI_DOMINATORS, bb, not_guard->dest))
    1496              :         {
    1497         6619 :           if (dump_enabled_p ())
    1498           27 :             dump_printf_loc (MSG_NOTE, loc,
    1499              :                              "Scaling nonguarded BBs in loop: %i\n",
    1500              :                              bb->index);
    1501         6619 :           if (e->probability.initialized_p ())
    1502         6619 :             scale_bbs_frequencies (&bb, 1, e->probability);
    1503              :         }
    1504              :     }
    1505              : 
    1506         1744 :   if (fix_dom_of_exit)
    1507          664 :     set_immediate_dominator (CDI_DOMINATORS, exit->dest, pre_header);
    1508              :   /* Add NEW_ADGE argument for all phi in post-header block.  */
    1509         1744 :   bb = exit->dest;
    1510         1744 :   for (gphi_iterator gsi = gsi_start_phis (bb);
    1511         3674 :        !gsi_end_p (gsi); gsi_next (&gsi))
    1512              :     {
    1513         1930 :       gphi *phi = gsi.phi ();
    1514         1930 :       tree arg;
    1515         3860 :       if (virtual_operand_p (gimple_phi_result (phi)))
    1516              :         {
    1517         1733 :           arg = get_vop_from_header (loop);
    1518         1733 :           if (arg == NULL_TREE)
    1519              :             /* Use exit edge argument.  */
    1520            0 :             arg =  PHI_ARG_DEF_FROM_EDGE (phi, exit);
    1521         1733 :           add_phi_arg (phi, arg, new_edge, UNKNOWN_LOCATION);
    1522              :         }
    1523              :       else
    1524              :         {
    1525              :           /* Use exit edge argument.  */
    1526          197 :           arg = PHI_ARG_DEF_FROM_EDGE (phi, exit);
    1527          197 :           add_phi_arg (phi, arg, new_edge, UNKNOWN_LOCATION);
    1528              :         }
    1529              :     }
    1530              : 
    1531         1744 :   if (dump_enabled_p ())
    1532            7 :     dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, loc,
    1533              :                      "Guard hoisted\n");
    1534              : 
    1535         1744 :   free (body);
    1536         1744 : }
    1537              : 
    1538              : /* Return true if phi argument for exit edge can be used
    1539              :    for edge around loop.  */
    1540              : 
    1541              : static bool
    1542         8503 : check_exit_phi (class loop *loop)
    1543              : {
    1544         8503 :   edge exit = single_exit (loop);
    1545         8503 :   basic_block pre_header = loop_preheader_edge (loop)->src;
    1546              : 
    1547         8503 :   for (gphi_iterator gsi = gsi_start_phis (exit->dest);
    1548        14714 :        !gsi_end_p (gsi); gsi_next (&gsi))
    1549              :     {
    1550         8622 :       gphi *phi = gsi.phi ();
    1551         8622 :       tree arg;
    1552         8622 :       gimple *def;
    1553         8622 :       basic_block def_bb;
    1554        17244 :       if (virtual_operand_p (gimple_phi_result (phi)))
    1555         6056 :         continue;
    1556         2566 :       arg = PHI_ARG_DEF_FROM_EDGE (phi, exit);
    1557         2566 :       if (TREE_CODE (arg) != SSA_NAME)
    1558           12 :         continue;
    1559         2554 :       def = SSA_NAME_DEF_STMT (arg);
    1560         2554 :       if (!def)
    1561            0 :         continue;
    1562         2554 :       def_bb = gimple_bb (def);
    1563         2554 :       if (!def_bb)
    1564            0 :         continue;
    1565         2554 :       if (!dominated_by_p (CDI_DOMINATORS, pre_header, def_bb))
    1566              :         /* Definition inside loop!  */
    1567         2411 :         return false;
    1568              :       /* Check loop closed phi invariant.  */
    1569          143 :       if (!flow_bb_inside_loop_p (def_bb->loop_father, pre_header))
    1570              :         return false;
    1571              :     }
    1572         6092 :   return true;
    1573              : }
    1574              : 
    1575              : /* Remove all dead cases from switches that are unswitched.  */
    1576              : 
    1577              : static void
    1578         1353 : clean_up_after_unswitching (int ignored_edge_flag)
    1579              : {
    1580         1353 :   basic_block bb;
    1581         1353 :   edge e;
    1582         1353 :   edge_iterator ei;
    1583         1353 :   bool removed_edge = false;
    1584              : 
    1585        72080 :   FOR_EACH_BB_FN (bb, cfun)
    1586              :     {
    1587       141454 :       gswitch *stmt= safe_dyn_cast <gswitch *> (*gsi_last_bb (bb));
    1588          153 :       if (stmt && !CONSTANT_CLASS_P (gimple_switch_index (stmt)))
    1589              :         {
    1590           74 :           unsigned nlabels = gimple_switch_num_labels (stmt);
    1591           74 :           unsigned index = 1;
    1592           74 :           tree lab = gimple_switch_default_label (stmt);
    1593          148 :           edge default_e = find_edge (gimple_bb (stmt),
    1594           74 :                                       label_to_block (cfun, CASE_LABEL (lab)));
    1595          333 :           for (unsigned i = 1; i < nlabels; ++i)
    1596              :             {
    1597          259 :               tree lab = gimple_switch_label (stmt, i);
    1598          259 :               basic_block dest = label_to_block (cfun, CASE_LABEL (lab));
    1599          259 :               edge e = find_edge (gimple_bb (stmt), dest);
    1600          259 :               if (e == NULL)
    1601              :                 ; /* The edge is already removed.  */
    1602          251 :               else if (e->flags & ignored_edge_flag)
    1603              :                 {
    1604              :                   /* We may not remove the default label so we also have
    1605              :                      to preserve its edge.  But we can remove the
    1606              :                      non-default CASE sharing the edge.  */
    1607           89 :                   if (e != default_e)
    1608              :                     {
    1609           89 :                       remove_edge (e);
    1610           89 :                       removed_edge = true;
    1611              :                     }
    1612              :                 }
    1613              :               else
    1614              :                 {
    1615          162 :                   gimple_switch_set_label (stmt, index, lab);
    1616          162 :                   ++index;
    1617              :                 }
    1618              :             }
    1619              : 
    1620           74 :           if (index != nlabels)
    1621           35 :             gimple_switch_set_num_labels (stmt, index);
    1622              :         }
    1623              : 
    1624              :       /* Clean up the ignored_edge_flag from edges.  */
    1625       170926 :       FOR_EACH_EDGE (e, ei, bb->succs)
    1626       100199 :         e->flags &= ~ignored_edge_flag;
    1627              :     }
    1628              : 
    1629              :   /* If we removed an edge we possibly have to recompute dominators.  */
    1630         1353 :   if (removed_edge)
    1631           30 :     free_dominance_info (CDI_DOMINATORS);
    1632         1353 : }
    1633              : 
    1634              : /* Loop unswitching pass.  */
    1635              : 
    1636              : namespace {
    1637              : 
    1638              : const pass_data pass_data_tree_unswitch =
    1639              : {
    1640              :   GIMPLE_PASS, /* type */
    1641              :   "unswitch", /* name */
    1642              :   OPTGROUP_LOOP, /* optinfo_flags */
    1643              :   TV_TREE_LOOP_UNSWITCH, /* tv_id */
    1644              :   PROP_cfg, /* properties_required */
    1645              :   0, /* properties_provided */
    1646              :   0, /* properties_destroyed */
    1647              :   0, /* todo_flags_start */
    1648              :   0, /* todo_flags_finish */
    1649              : };
    1650              : 
    1651              : class pass_tree_unswitch : public gimple_opt_pass
    1652              : {
    1653              : public:
    1654       285722 :   pass_tree_unswitch (gcc::context *ctxt)
    1655       571444 :     : gimple_opt_pass (pass_data_tree_unswitch, ctxt)
    1656              :   {}
    1657              : 
    1658              :   /* opt_pass methods: */
    1659       241458 :   bool gate (function *) final override { return flag_unswitch_loops != 0; }
    1660              :   unsigned int execute (function *) final override;
    1661              : 
    1662              : }; // class pass_tree_unswitch
    1663              : 
    1664              : unsigned int
    1665        28166 : pass_tree_unswitch::execute (function *fun)
    1666              : {
    1667        56332 :   if (number_of_loops (fun) <= 1)
    1668              :     return 0;
    1669              : 
    1670        28166 :   return tree_ssa_unswitch_loops (fun);
    1671              : }
    1672              : 
    1673              : } // anon namespace
    1674              : 
    1675              : gimple_opt_pass *
    1676       285722 : make_pass_tree_unswitch (gcc::context *ctxt)
    1677              : {
    1678       285722 :   return new pass_tree_unswitch (ctxt);
    1679              : }
    1680              : 
    1681              : 
        

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.