LCOV - code coverage report
Current view: top level - gcc - gimple-if-to-switch.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 99.6 % 257 256
Test Date: 2026-02-28 14:20:25 Functions: 100.0 % 13 13
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /* If-elseif-else to switch conversion pass
       2              :    Copyright (C) 2020-2026 Free Software Foundation, Inc.
       3              : 
       4              : This file is part of GCC.
       5              : 
       6              : GCC is free software; you can redistribute it and/or modify
       7              : it under the terms of the GNU General Public License as published by
       8              : the Free Software Foundation; either version 3, or (at your option)
       9              : any later version.
      10              : 
      11              : GCC is distributed in the hope that it will be useful,
      12              : but WITHOUT ANY WARRANTY; without even the implied warranty of
      13              : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14              : GNU General Public License for more details.
      15              : 
      16              : You should have received a copy of the GNU General Public License
      17              : along with GCC; see the file COPYING3.  If not see
      18              : <http://www.gnu.org/licenses/>.  */
      19              : 
      20              : /* Algorithm of the pass runs in the following steps:
      21              :    a) We walk basic blocks in DOMINATOR order so that we first reach
      22              :       a first condition of a future switch.
      23              :    b) We follow false edges of a if-else-chain and we record chain
      24              :       of GIMPLE conditions.  These blocks are only used for comparison
      25              :       of a common SSA_NAME and we do not allow any side effect.
      26              :    c) We remove all basic blocks (except first) of such chain and
      27              :       GIMPLE switch replaces the condition in the first basic block.
      28              :    d) We move all GIMPLE statements in the removed blocks into the
      29              :       first one.  */
      30              : 
      31              : #include "config.h"
      32              : #include "system.h"
      33              : #include "coretypes.h"
      34              : #include "backend.h"
      35              : #include "rtl.h"
      36              : #include "tree.h"
      37              : #include "gimple.h"
      38              : #include "tree-pass.h"
      39              : #include "ssa.h"
      40              : #include "gimple-pretty-print.h"
      41              : #include "fold-const.h"
      42              : #include "gimple-iterator.h"
      43              : #include "tree-cfg.h"
      44              : #include "tree-dfa.h"
      45              : #include "tree-cfgcleanup.h"
      46              : #include "alias.h"
      47              : #include "tree-ssa-loop.h"
      48              : #include "diagnostic.h"
      49              : #include "cfghooks.h"
      50              : #include "tree-into-ssa.h"
      51              : #include "cfganal.h"
      52              : #include "dbgcnt.h"
      53              : #include "target.h"
      54              : #include "alloc-pool.h"
      55              : #include "tree-switch-conversion.h"
      56              : #include "tree-ssa-reassoc.h"
      57              : #include "tree-ssa.h"
      58              : 
      59              : using namespace tree_switch_conversion;
      60              : 
      61              : struct condition_info
      62              : {
      63              :   typedef auto_vec<std::pair<gphi *, tree>> mapping_vec;
      64              : 
      65      3823700 :   condition_info (gcond *cond, bool has_side_effect): m_cond (cond),
      66      3823700 :     m_bb (gimple_bb (cond)), m_forwarder_bb (NULL), m_ranges (),
      67      3823700 :     m_true_edge (NULL), m_false_edge (NULL),
      68      3823700 :     m_true_edge_phi_mapping (), m_false_edge_phi_mapping (),
      69      3823700 :     m_has_side_effect (has_side_effect)
      70              :   {
      71      3823700 :     m_ranges.create (0);
      72              :   }
      73              : 
      74              :   /* Recond PHI mapping for an original edge E and save these into
      75              :      vector VEC.  */
      76              :   void record_phi_mapping (edge e, mapping_vec *vec);
      77              : 
      78              :   gcond *m_cond;
      79              :   basic_block m_bb;
      80              :   basic_block m_forwarder_bb;
      81              :   auto_vec<range_entry> m_ranges;
      82              :   edge m_true_edge;
      83              :   edge m_false_edge;
      84              :   mapping_vec m_true_edge_phi_mapping;
      85              :   mapping_vec m_false_edge_phi_mapping;
      86              :   bool m_has_side_effect;
      87              : };
      88              : 
      89              : /* Recond PHI mapping for an original edge E and save these into vector VEC.  */
      90              : 
      91              : void
      92      3698198 : condition_info::record_phi_mapping (edge e, mapping_vec *vec)
      93              : {
      94      4803582 :   for (gphi_iterator gsi = gsi_start_phis (e->dest); !gsi_end_p (gsi);
      95      1105384 :        gsi_next (&gsi))
      96              :     {
      97      1105384 :       gphi *phi = gsi.phi ();
      98      1105384 :       tree arg = PHI_ARG_DEF_FROM_EDGE (phi, e);
      99      1105384 :       vec->safe_push (std::make_pair (phi, arg));
     100              :     }
     101      3698198 : }
     102              : 
     103              : /* Master structure for one if to switch conversion candidate.  */
     104              : 
     105              : struct if_chain
     106              : {
     107              :   /* Default constructor.  */
     108      1805948 :   if_chain (): m_entries ()
     109              :   {
     110      3611896 :     m_entries.create (2);
     111              :   }
     112              : 
     113              :   /* Default destructor.  */
     114      1805948 :   ~if_chain ()
     115              :   {
     116         1629 :     m_entries.release ();
     117      1805948 :   }
     118              : 
     119              :   /* Verify that all case ranges do not overlap.  */
     120              :   bool check_non_overlapping_cases ();
     121              : 
     122              :   /* Return true when the switch can be expanded with a jump table or
     123              :      a bit test (at least partially).  */
     124              :   bool is_beneficial ();
     125              : 
     126              :   /* If chain entries.  */
     127              :   vec<condition_info *> m_entries;
     128              : };
     129              : 
     130              : /* Compare two case ranges by minimum value.  */
     131              : 
     132              : static int
     133       268287 : range_cmp (const void *a, const void *b)
     134              : {
     135       268287 :   const range_entry *re1 = *(const range_entry * const *) a;
     136       268287 :   const range_entry *re2 = *(const range_entry * const *) b;
     137              : 
     138       268287 :   return tree_int_cst_compare (re1->low, re2->low);
     139              : }
     140              : 
     141              : /* Verify that all case ranges do not overlap.  */
     142              : 
     143              : bool
     144        36711 : if_chain::check_non_overlapping_cases ()
     145              : {
     146        36711 :   auto_vec<range_entry *> all_ranges;
     147       116573 :   for (unsigned i = 0; i < m_entries.length (); i++)
     148       163289 :     for (unsigned j = 0; j < m_entries[i]->m_ranges.length (); j++)
     149        83427 :       all_ranges.safe_push (&m_entries[i]->m_ranges[j]);
     150              : 
     151        36711 :   all_ranges.qsort (range_cmp);
     152              : 
     153       147408 :   for (unsigned i = 0; i < all_ranges.length () - 1; i++)
     154              :     {
     155        46147 :       range_entry *left = all_ranges[i];
     156        46147 :       range_entry *right = all_ranges[i + 1];
     157        46147 :       if (tree_int_cst_le (left->low, right->low)
     158        46147 :           && tree_int_cst_le (right->low, left->high))
     159              :         return false;
     160              :     }
     161              : 
     162              :   return true;
     163        36711 : }
     164              : 
     165              : /* Compare clusters by minimum value.  */
     166              : 
     167              : static int
     168       235986 : cluster_cmp (const void *a, const void *b)
     169              : {
     170       235986 :   simple_cluster *sc1 = *(simple_cluster * const *) a;
     171       235986 :   simple_cluster *sc2 = *(simple_cluster * const *) b;
     172              : 
     173       235986 :   return tree_int_cst_compare (sc1->get_low (), sc2->get_high ());
     174              : }
     175              : 
     176              : /* Dump constructed CLUSTERS with prefix MESSAGE.  */
     177              : 
     178              : static void
     179        29186 : dump_clusters (vec<cluster *> *clusters, const char *message)
     180              : {
     181        29186 :   if (dump_file)
     182              :     {
     183           24 :       fprintf (dump_file, ";; %s: ", message);
     184           95 :       for (unsigned i = 0; i < clusters->length (); i++)
     185           71 :         (*clusters)[i]->dump (dump_file, dump_flags & TDF_DETAILS);
     186           24 :       fprintf (dump_file, "\n");
     187              :     }
     188        29186 : }
     189              : 
     190              : /* Return true when the switch can be expanded with a jump table or
     191              :    a bit test (at least partially).  */
     192              : 
     193              : bool
     194        27557 : if_chain::is_beneficial ()
     195              : {
     196        27557 :   profile_probability prob = profile_probability::uninitialized ();
     197              : 
     198        27557 :   auto_vec<cluster *> clusters;
     199        27557 :   clusters.create (m_entries.length ());
     200              : 
     201        88543 :   for (unsigned i = 0; i < m_entries.length (); i++)
     202              :     {
     203        60986 :       condition_info *info = m_entries[i];
     204       125536 :       for (unsigned j = 0; j < info->m_ranges.length (); j++)
     205              :         {
     206        64550 :           range_entry *range = &info->m_ranges[j];
     207        64550 :           basic_block bb = info->m_true_edge->dest;
     208        64550 :           bool has_forwarder = !info->m_true_edge_phi_mapping.is_empty ();
     209        64550 :           clusters.safe_push (new simple_cluster (range->low, range->high,
     210              :                                                   NULL_TREE, bb, prob,
     211        64550 :                                                   has_forwarder));
     212              :         }
     213              :     }
     214              : 
     215              :   /* Sort clusters and merge them.  */
     216        27557 :   auto_vec<cluster *> filtered_clusters;
     217        27557 :   filtered_clusters.create (16);
     218        27557 :   clusters.qsort (cluster_cmp);
     219        27557 :   simple_cluster *left = static_cast<simple_cluster *> (clusters[0]);
     220        27557 :   filtered_clusters.safe_push (left);
     221              : 
     222        64550 :   for (unsigned i = 1; i < clusters.length (); i++)
     223              :     {
     224        36993 :       simple_cluster *right = static_cast<simple_cluster *> (clusters[i]);
     225        36993 :       tree type = TREE_TYPE (left->get_low ());
     226        36993 :       if (!left->m_has_forward_bb
     227        25431 :           && !right->m_has_forward_bb
     228        24115 :           && left->m_case_bb == right->m_case_bb)
     229              :         {
     230        15000 :           if (wi::eq_p (wi::to_wide (right->get_low ()) - wi::to_wide
     231        22500 :                         (left->get_high ()), wi::one (TYPE_PRECISION (type))))
     232              :             {
     233         1347 :               left->set_high (right->get_high ());
     234         1347 :               delete right;
     235         1347 :               continue;
     236              :             }
     237              :         }
     238              : 
     239        35646 :       left = static_cast<simple_cluster *> (clusters[i]);
     240        35646 :       filtered_clusters.safe_push (left);
     241              :     }
     242              : 
     243        27557 :   dump_clusters (&filtered_clusters, "Canonical GIMPLE case clusters");
     244              : 
     245        27557 :   vec<cluster *> output
     246        27557 :     = jump_table_cluster::find_jump_tables (filtered_clusters);
     247        55114 :   bool r = output.length () < filtered_clusters.length ();
     248        27557 :   if (r)
     249              :     {
     250          655 :       dump_clusters (&output, "JT can be built");
     251          655 :       release_clusters (output);
     252          655 :       return true;
     253              :     }
     254              :   else
     255        26902 :     output.release ();
     256              : 
     257        26902 :   output = bit_test_cluster::find_bit_tests (filtered_clusters, 2);
     258        53804 :   r = output.length () < filtered_clusters.length ();
     259        26902 :   if (r)
     260          974 :     dump_clusters (&output, "BT can be built");
     261              : 
     262        26902 :   release_clusters (output);
     263        26902 :   return r;
     264        27557 : }
     265              : 
     266              : /* Build case label with MIN and MAX values of a given basic block DEST.  */
     267              : 
     268              : static tree
     269        11046 : build_case_label (tree index_type, tree min, tree max, basic_block dest)
     270              : {
     271        11046 :   if (min != NULL_TREE && index_type != TREE_TYPE (min))
     272          210 :     min = fold_convert (index_type, min);
     273        11046 :   if (max != NULL_TREE && index_type != TREE_TYPE (max))
     274          210 :     max = fold_convert (index_type, max);
     275              : 
     276        11046 :   tree label = gimple_block_label (dest);
     277        21226 :   return build_case_label (min, min == max ? NULL_TREE : max, label);
     278              : }
     279              : 
     280              : /* Compare two integer constants.  */
     281              : 
     282              : static int
     283       106798 : label_cmp (const void *a, const void *b)
     284              : {
     285       106798 :   const_tree l1 = *(const const_tree *) a;
     286       106798 :   const_tree l2 = *(const const_tree *) b;
     287              : 
     288       106798 :   return tree_int_cst_compare (CASE_LOW (l1), CASE_LOW (l2));
     289              : }
     290              : 
     291              : /* Convert a given if CHAIN into a switch GIMPLE statement.  */
     292              : 
     293              : static void
     294         1629 : convert_if_conditions_to_switch (if_chain *chain)
     295              : {
     296         1629 :   if (!dbg_cnt (if_to_switch))
     297            0 :     return;
     298              : 
     299         1629 :   auto_vec<tree> labels;
     300         1629 :   unsigned entries = chain->m_entries.length ();
     301         1629 :   condition_info *first_cond = chain->m_entries[0];
     302         1629 :   condition_info *last_cond = chain->m_entries[entries - 1];
     303              : 
     304         1629 :   edge default_edge = last_cond->m_false_edge;
     305         1629 :   basic_block default_bb = default_edge->dest;
     306              : 
     307         1629 :   gimple_stmt_iterator gsi = gsi_for_stmt (first_cond->m_cond);
     308         1629 :   tree index_type = TREE_TYPE (first_cond->m_ranges[0].exp);
     309         8167 :   for (unsigned i = 0; i < entries; i++)
     310              :     {
     311         6538 :       condition_info *info = chain->m_entries[i];
     312         6538 :       basic_block case_bb = info->m_true_edge->dest;
     313              : 
     314              :       /* Create a forwarder block if needed.  */
     315         6538 :       if (!info->m_true_edge_phi_mapping.is_empty ())
     316              :         {
     317         1081 :           info->m_forwarder_bb = split_edge (info->m_true_edge);
     318         1081 :           case_bb = info->m_forwarder_bb;
     319              :         }
     320              : 
     321        15955 :       for (unsigned j = 0; j < info->m_ranges.length (); j++)
     322         9417 :         labels.safe_push (build_case_label (index_type,
     323         9417 :                                             info->m_ranges[j].low,
     324         9417 :                                             info->m_ranges[j].high,
     325              :                                             case_bb));
     326         6538 :       default_bb = info->m_false_edge->dest;
     327              : 
     328         6538 :       if (i == 0)
     329              :         {
     330         1629 :           remove_edge (first_cond->m_true_edge);
     331         1629 :           remove_edge (first_cond->m_false_edge);
     332              :         }
     333              :       else
     334         4909 :         delete_basic_block (info->m_bb);
     335              : 
     336         6538 :       make_edge (first_cond->m_bb, case_bb, 0);
     337              :     }
     338              : 
     339         1629 :   labels.qsort (label_cmp);
     340              : 
     341         1629 :   edge e = find_edge (first_cond->m_bb, default_bb);
     342         1629 :   if (e == NULL)
     343         1629 :     e = make_edge (first_cond->m_bb, default_bb, 0);
     344         1629 :   gswitch *s
     345         1629 :     = gimple_build_switch (first_cond->m_ranges[0].exp,
     346              :                            build_case_label (index_type, NULL_TREE,
     347              :                                              NULL_TREE, default_bb),
     348              :                            labels);
     349              : 
     350         1629 :   gsi_remove (&gsi, true);
     351         1629 :   gsi_insert_before (&gsi, s, GSI_NEW_STMT);
     352              : 
     353         1629 :   if (dump_file)
     354              :     {
     355           10 :       fprintf (dump_file, "Expanded into a new gimple STMT: ");
     356           10 :       print_gimple_stmt (dump_file, s, 0, TDF_SLIM);
     357           10 :       putc ('\n', dump_file);
     358              :     }
     359              : 
     360              :   /* Fill up missing PHI node arguments.  */
     361        16334 :   for (unsigned i = 0; i < chain->m_entries.length (); ++i)
     362              :     {
     363         6538 :       condition_info *info = chain->m_entries[i];
     364         8163 :       for (unsigned j = 0; j < info->m_true_edge_phi_mapping.length (); ++j)
     365              :         {
     366         1625 :           std::pair<gphi *, tree> item = info->m_true_edge_phi_mapping[j];
     367         1625 :           add_phi_arg (item.first, item.second,
     368         1625 :                        single_succ_edge (info->m_forwarder_bb),
     369              :                        UNKNOWN_LOCATION);
     370              :         }
     371              :     }
     372              : 
     373              :   /* Fill up missing PHI nodes for the default BB.  */
     374         2236 :   for (unsigned j = 0; j < last_cond->m_false_edge_phi_mapping.length (); ++j)
     375              :     {
     376          607 :       std::pair<gphi *, tree> item = last_cond->m_false_edge_phi_mapping[j];
     377          607 :       add_phi_arg (item.first, item.second, e, UNKNOWN_LOCATION);
     378              :     }
     379         1629 : }
     380              : 
     381              : /* Identify an index variable used in BB in a GIMPLE condition.
     382              :    Save information about the condition into CONDITIONS_IN_BBS.  */
     383              : 
     384              : static void
     385     11024837 : find_conditions (basic_block bb,
     386              :                  hash_map<basic_block, condition_info *> *conditions_in_bbs)
     387              : {
     388     11024837 :   gimple_stmt_iterator gsi = gsi_last_nondebug_bb (bb);
     389     11024837 :   if (gsi_end_p (gsi))
     390      9050236 :     return;
     391              : 
     392     12873936 :   gcond *cond = dyn_cast<gcond *> (gsi_stmt (gsi));
     393      3823700 :   if (cond == NULL)
     394              :     return;
     395              : 
     396      3823700 :   tree lhs = gimple_cond_lhs (cond);
     397      3823700 :   tree rhs = gimple_cond_rhs (cond);
     398      3823700 :   tree_code code = gimple_cond_code (cond);
     399              : 
     400      3823700 :   condition_info *info = new condition_info (cond, !no_side_effect_bb (bb));
     401              : 
     402      3823700 :   gassign *def;
     403      3823700 :   if (code == NE_EXPR
     404      1878781 :       && TREE_CODE (lhs) == SSA_NAME
     405      1878513 :       && (def = dyn_cast<gassign *> (SSA_NAME_DEF_STMT (lhs))) != NULL
     406      4820369 :       && integer_zerop (rhs))
     407              :     {
     408       577214 :       enum tree_code rhs_code = gimple_assign_rhs_code (def);
     409       577214 :       if (rhs_code == BIT_IOR_EXPR)
     410              :         {
     411        28617 :           info->m_ranges.safe_grow (2, true);
     412        28617 :           init_range_entry (&info->m_ranges[0], gimple_assign_rhs1 (def), NULL);
     413        57234 :           init_range_entry (&info->m_ranges[1], gimple_assign_rhs2 (def), NULL);
     414              :         }
     415              :     }
     416              :   else
     417              :     {
     418      3246486 :       info->m_ranges.safe_grow (1, true);
     419      3246486 :       init_range_entry (&info->m_ranges[0], NULL_TREE, cond);
     420              :     }
     421              : 
     422              :   /* All identified ranges must have equal expression and IN_P flag.  */
     423      3823700 :   if (!info->m_ranges.is_empty ())
     424              :     {
     425      3275103 :       edge true_edge, false_edge;
     426      3275103 :       tree expr = info->m_ranges[0].exp;
     427      3275103 :       bool in_p = info->m_ranges[0].in_p;
     428              : 
     429      3275103 :       extract_true_false_edges_from_block (bb, &true_edge, &false_edge);
     430      3275103 :       info->m_true_edge = in_p ? true_edge : false_edge;
     431      3275103 :       info->m_false_edge = in_p ? false_edge : true_edge;
     432              : 
     433     10324052 :       for (unsigned i = 0; i < info->m_ranges.length (); ++i)
     434      3297342 :         if (info->m_ranges[i].exp == NULL_TREE
     435      2285867 :             || !INTEGRAL_TYPE_P (TREE_TYPE (info->m_ranges[i].exp))
     436      2087803 :             || info->m_ranges[i].low == NULL_TREE
     437      1953189 :             || info->m_ranges[i].high == NULL_TREE
     438      5184639 :             || (TYPE_PRECISION (TREE_TYPE (info->m_ranges[i].low))
     439      1887297 :                 != TYPE_PRECISION (TREE_TYPE (info->m_ranges[i].high))))
     440      1426004 :           goto exit;
     441              : 
     442      1870485 :       for (unsigned i = 1; i < info->m_ranges.length (); ++i)
     443        21386 :         if (info->m_ranges[i].exp != expr
     444        21386 :             || info->m_ranges[i].in_p != in_p)
     445        15585 :           goto exit;
     446              : 
     447      1849099 :       info->record_phi_mapping (info->m_true_edge,
     448              :                                 &info->m_true_edge_phi_mapping);
     449      1849099 :       info->record_phi_mapping (info->m_false_edge,
     450              :                                 &info->m_false_edge_phi_mapping);
     451      1849099 :       conditions_in_bbs->put (bb, info);
     452      1849099 :       return;
     453              :     }
     454              : 
     455      1974601 : exit:
     456      1974601 :   delete info;
     457              : }
     458              : 
     459              : namespace {
     460              : 
     461              : const pass_data pass_data_if_to_switch =
     462              : {
     463              :   GIMPLE_PASS, /* type */
     464              :   "iftoswitch", /* name */
     465              :   OPTGROUP_NONE, /* optinfo_flags */
     466              :   TV_TREE_IF_TO_SWITCH, /* tv_id */
     467              :   ( PROP_cfg | PROP_ssa ), /* properties_required */
     468              :   0, /* properties_provided */
     469              :   0, /* properties_destroyed */
     470              :   0, /* todo_flags_start */
     471              :   TODO_update_ssa /* todo_flags_finish */
     472              : };
     473              : 
     474              : class pass_if_to_switch : public gimple_opt_pass
     475              : {
     476              : public:
     477       285722 :   pass_if_to_switch (gcc::context *ctxt)
     478       571444 :     : gimple_opt_pass (pass_data_if_to_switch, ctxt)
     479              :   {}
     480              : 
     481              :   /* opt_pass methods: */
     482      2412428 :   bool gate (function *) final override
     483              :   {
     484      2412428 :     return (jump_table_cluster::is_enabled ()
     485      2412428 :             || bit_test_cluster::is_enabled ());
     486              :   }
     487              : 
     488              :   unsigned int execute (function *) final override;
     489              : 
     490              : }; // class pass_if_to_switch
     491              : 
     492              : unsigned int
     493      2412337 : pass_if_to_switch::execute (function *fun)
     494              : {
     495      2412337 :   auto_vec<if_chain *> all_candidates;
     496      2412337 :   hash_map<basic_block, condition_info *> conditions_in_bbs;
     497              : 
     498      2412337 :   mark_ssa_maybe_undefs ();
     499              : 
     500      2412337 :   basic_block bb;
     501     13437174 :   FOR_EACH_BB_FN (bb, fun)
     502     11024837 :     find_conditions (bb, &conditions_in_bbs);
     503              : 
     504      2412337 :   if (conditions_in_bbs.is_empty ())
     505              :     return 0;
     506              : 
     507       488884 :   int *rpo = XNEWVEC (int, n_basic_blocks_for_fn (fun));
     508       488884 :   unsigned n = pre_and_rev_post_order_compute_fn (fun, NULL, rpo, false);
     509              : 
     510       488884 :   auto_bitmap seen_bbs;
     511      7810389 :   for (int i = n - 1; i >= 0; --i)
     512              :     {
     513      7321505 :       basic_block bb = BASIC_BLOCK_FOR_FN (fun, rpo[i]);
     514      7321505 :       if (bitmap_bit_p (seen_bbs, bb->index))
     515        43151 :         continue;
     516              : 
     517      7278354 :       bitmap_set_bit (seen_bbs, bb->index);
     518      7278354 :       condition_info **slot = conditions_in_bbs.get (bb);
     519      7278354 :       if (slot)
     520              :         {
     521      1805948 :           condition_info *info = *slot;
     522      1805948 :           if_chain *chain = new if_chain ();
     523      1805948 :           chain->m_entries.safe_push (info);
     524              :           /* Try to find a chain starting in this BB.  */
     525      1892250 :           while (true)
     526              :             {
     527      1849099 :               if (!single_pred_p (gimple_bb (info->m_cond)))
     528              :                 break;
     529      1235227 :               edge e = single_pred_edge (gimple_bb (info->m_cond));
     530      1235227 :               condition_info **info2 = conditions_in_bbs.get (e->src);
     531      1235227 :               if (!info2 || info->m_ranges[0].exp != (*info2)->m_ranges[0].exp)
     532              :                 break;
     533              : 
     534              :               /* It is important that the blocks are linked through FALSE_EDGE.
     535              :                  For an expression of index != VALUE, true and false edges
     536              :                  are flipped.  */
     537        55869 :               if ((*info2)->m_false_edge != e)
     538              :                 break;
     539              : 
     540              :               /* Only the first BB in a chain can have a side effect.  */
     541        49923 :               if (info->m_has_side_effect)
     542              :                 break;
     543              : 
     544        43151 :               chain->m_entries.safe_push (*info2);
     545        43151 :               bitmap_set_bit (seen_bbs, e->src->index);
     546        43151 :               info = *info2;
     547        43151 :             }
     548              : 
     549      1805948 :           chain->m_entries.reverse ();
     550      1805948 :           if (chain->m_entries.length () >= 2
     551        36711 :               && chain->check_non_overlapping_cases ()
     552      1833505 :               && chain->is_beneficial ())
     553              :             {
     554         1629 :               gcond *cond = chain->m_entries[0]->m_cond;
     555         1629 :               if (dump_enabled_p ())
     556           10 :                 dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, cond,
     557              :                                  "Condition chain with %d BBs "
     558              :                                  "transformed into a switch statement.\n",
     559              :                                  chain->m_entries.length ());
     560         1629 :               all_candidates.safe_push (chain);
     561              :             }
     562              :           else
     563      1804319 :             delete chain;
     564              :         }
     565              :     }
     566              : 
     567       490513 :   for (unsigned i = 0; i < all_candidates.length (); i++)
     568              :     {
     569         1629 :       convert_if_conditions_to_switch (all_candidates[i]);
     570         3258 :       delete all_candidates[i];
     571              :     }
     572              : 
     573       488884 :   free (rpo);
     574              : 
     575      2337983 :   for (hash_map<basic_block, condition_info *>::iterator it
     576      4675966 :        = conditions_in_bbs.begin (); it != conditions_in_bbs.end (); ++it)
     577      1849099 :     delete (*it).second;
     578              : 
     579       490404 :   if (!all_candidates.is_empty ())
     580              :     {
     581         1520 :       free_dominance_info (CDI_DOMINATORS);
     582         1520 :       return TODO_cleanup_cfg;
     583              :     }
     584              : 
     585              :   return 0;
     586      2901221 : }
     587              : 
     588              : } // anon namespace
     589              : 
     590              : gimple_opt_pass *
     591       285722 : make_pass_if_to_switch (gcc::context *ctxt)
     592              : {
     593       285722 :   return new pass_if_to_switch (ctxt);
     594              : }
        

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.