LCOV - code coverage report
Current view: top level - gcc - cfghooks.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 77.7 % 698 542
Test Date: 2025-03-22 13:13:03 Functions: 79.4 % 63 50
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: - 0 0

             Branch data     Line data    Source code
       1                 :             : /* Hooks for cfg representation specific functions.
       2                 :             :    Copyright (C) 2003-2025 Free Software Foundation, Inc.
       3                 :             :    Contributed by Sebastian Pop <s.pop@laposte.net>
       4                 :             : 
       5                 :             : This file is part of GCC.
       6                 :             : 
       7                 :             : GCC is free software; you can redistribute it and/or modify
       8                 :             : it under the terms of the GNU General Public License as published by
       9                 :             : the Free Software Foundation; either version 3, or (at your option)
      10                 :             : any later version.
      11                 :             : 
      12                 :             : GCC is distributed in the hope that it will be useful,
      13                 :             : but WITHOUT ANY WARRANTY; without even the implied warranty of
      14                 :             : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      15                 :             : GNU General Public License for more details.
      16                 :             : 
      17                 :             : You should have received a copy of the GNU General Public License
      18                 :             : along with GCC; see the file COPYING3.  If not see
      19                 :             : <http://www.gnu.org/licenses/>.  */
      20                 :             : 
      21                 :             : #include "config.h"
      22                 :             : #include "system.h"
      23                 :             : #include "coretypes.h"
      24                 :             : #include "backend.h"
      25                 :             : #include "rtl.h"
      26                 :             : #include "cfghooks.h"
      27                 :             : #include "timevar.h"
      28                 :             : #include "pretty-print.h"
      29                 :             : #include "diagnostic-core.h"
      30                 :             : #include "dumpfile.h"
      31                 :             : #include "cfganal.h"
      32                 :             : #include "tree.h"
      33                 :             : #include "tree-ssa.h"
      34                 :             : #include "cfgloop.h"
      35                 :             : #include "sreal.h"
      36                 :             : #include "profile.h"
      37                 :             : 
      38                 :             : /* Disable warnings about missing quoting in GCC diagnostics.  */
      39                 :             : #if __GNUC__ >= 10
      40                 :             : #  pragma GCC diagnostic push
      41                 :             : #  pragma GCC diagnostic ignored "-Wformat-diag"
      42                 :             : #endif
      43                 :             : 
      44                 :             : /* A pointer to one of the hooks containers.  */
      45                 :             : static struct cfg_hooks *cfg_hooks;
      46                 :             : 
      47                 :             : /* Initialization of functions specific to the rtl IR.  */
      48                 :             : void
      49                 :     3881270 : rtl_register_cfg_hooks (void)
      50                 :             : {
      51                 :     3881270 :   cfg_hooks = &rtl_cfg_hooks;
      52                 :     3881270 : }
      53                 :             : 
      54                 :             : /* Initialization of functions specific to the rtl IR.  */
      55                 :             : void
      56                 :     2444567 : cfg_layout_rtl_register_cfg_hooks (void)
      57                 :             : {
      58                 :     2444567 :   cfg_hooks = &cfg_layout_rtl_cfg_hooks;
      59                 :     2444567 : }
      60                 :             : 
      61                 :             : /* Initialization of functions specific to the tree IR.  */
      62                 :             : 
      63                 :             : void
      64                 :    13518677 : gimple_register_cfg_hooks (void)
      65                 :             : {
      66                 :    13518677 :   cfg_hooks = &gimple_cfg_hooks;
      67                 :    13518677 : }
      68                 :             : 
      69                 :             : struct cfg_hooks
      70                 :         782 : get_cfg_hooks (void)
      71                 :             : {
      72                 :         782 :   return *cfg_hooks;
      73                 :             : }
      74                 :             : 
      75                 :             : void
      76                 :        1564 : set_cfg_hooks (struct cfg_hooks new_cfg_hooks)
      77                 :             : {
      78                 :        1564 :   *cfg_hooks = new_cfg_hooks;
      79                 :        1564 : }
      80                 :             : 
      81                 :             : /* Returns current ir type.  */
      82                 :             : 
      83                 :             : enum ir_type
      84                 :   259872803 : current_ir_type (void)
      85                 :             : {
      86                 :   259872803 :   if (cfg_hooks == &gimple_cfg_hooks)
      87                 :             :     return IR_GIMPLE;
      88                 :   112784288 :   else if (cfg_hooks == &rtl_cfg_hooks)
      89                 :             :     return IR_RTL_CFGRTL;
      90                 :    38813848 :   else if (cfg_hooks == &cfg_layout_rtl_cfg_hooks)
      91                 :             :     return IR_RTL_CFGLAYOUT;
      92                 :             :   else
      93                 :           0 :     gcc_unreachable ();
      94                 :             : }
      95                 :             : 
      96                 :             : /* Verify the CFG consistency.
      97                 :             : 
      98                 :             :    Currently it does following: checks edge and basic block list correctness
      99                 :             :    and calls into IL dependent checking then.  */
     100                 :             : 
     101                 :             : DEBUG_FUNCTION void
     102                 :   317036577 : verify_flow_info (void)
     103                 :             : {
     104                 :   317036577 :   size_t *edge_checksum;
     105                 :   317036577 :   bool err = false;
     106                 :   317036577 :   basic_block bb, last_bb_seen;
     107                 :   317036577 :   basic_block *last_visited;
     108                 :             : 
     109                 :   317036577 :   timevar_push (TV_CFG_VERIFY);
     110                 :   317036577 :   last_visited = XCNEWVEC (basic_block, last_basic_block_for_fn (cfun));
     111                 :   317036577 :   edge_checksum = XCNEWVEC (size_t, last_basic_block_for_fn (cfun));
     112                 :             : 
     113                 :             :   /* Check bb chain & numbers.  */
     114                 :   317036577 :   last_bb_seen = ENTRY_BLOCK_PTR_FOR_FN (cfun);
     115                 :  3530209857 :   FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR_FOR_FN (cfun)->next_bb, NULL, next_bb)
     116                 :             :     {
     117                 :  3213173280 :       if (bb != EXIT_BLOCK_PTR_FOR_FN (cfun)
     118                 :  3213173280 :           && bb != BASIC_BLOCK_FOR_FN (cfun, bb->index))
     119                 :             :         {
     120                 :           0 :           error ("bb %d on wrong place", bb->index);
     121                 :           0 :           err = true;
     122                 :             :         }
     123                 :             : 
     124                 :  3213173280 :       if (bb->prev_bb != last_bb_seen)
     125                 :             :         {
     126                 :           0 :           error ("prev_bb of %d should be %d, not %d",
     127                 :             :                  bb->index, last_bb_seen->index, bb->prev_bb->index);
     128                 :           0 :           err = true;
     129                 :             :         }
     130                 :             : 
     131                 :  3213173280 :       last_bb_seen = bb;
     132                 :             :     }
     133                 :             : 
     134                 :             :   /* Now check the basic blocks (boundaries etc.) */
     135                 :  3213173280 :   FOR_EACH_BB_REVERSE_FN (bb, cfun)
     136                 :             :     {
     137                 :  2896136703 :       int n_fallthru = 0;
     138                 :  2896136703 :       edge e;
     139                 :  2896136703 :       edge_iterator ei;
     140                 :             : 
     141                 :  2896136703 :       if (bb->loop_father != NULL && current_loops == NULL)
     142                 :             :         {
     143                 :           0 :           error ("verify_flow_info: Block %i has loop_father, but there are no loops",
     144                 :             :                  bb->index);
     145                 :           0 :           err = true;
     146                 :             :         }
     147                 :  2896136703 :       if (bb->loop_father == NULL && current_loops != NULL)
     148                 :             :         {
     149                 :           0 :           error ("verify_flow_info: Block %i lacks loop_father", bb->index);
     150                 :           0 :           err = true;
     151                 :             :         }
     152                 :             : 
     153                 :  2896136703 :       if (!bb->count.verify ())
     154                 :             :         {
     155                 :           0 :           error ("verify_flow_info: Wrong count of block %i", bb->index);
     156                 :           0 :           err = true;
     157                 :             :         }
     158                 :             :       /* FIXME: Graphite and SLJL and target code still tends to produce
     159                 :             :          edges with no probability.  */
     160                 :  2896136703 :       if (profile_status_for_fn (cfun) >= PROFILE_GUESSED
     161                 :             :           && !bb->count.initialized_p () && !flag_graphite && 0)
     162                 :             :         {
     163                 :             :           error ("verify_flow_info: Missing count of block %i", bb->index);
     164                 :             :           err = true;
     165                 :             :         }
     166                 :             : 
     167                 :  2896136703 :       if (bb->flags & ~cfun->cfg->bb_flags_allocated)
     168                 :             :         {
     169                 :           0 :           error ("verify_flow_info: unallocated flag set on BB %d", bb->index);
     170                 :           0 :           err = true;
     171                 :             :         }
     172                 :             : 
     173                 :  6998909993 :       FOR_EACH_EDGE (e, ei, bb->succs)
     174                 :             :         {
     175                 :  4102773290 :           if (last_visited [e->dest->index] == bb)
     176                 :             :             {
     177                 :           0 :               error ("verify_flow_info: Duplicate edge %i->%i",
     178                 :           0 :                      e->src->index, e->dest->index);
     179                 :           0 :               err = true;
     180                 :             :             }
     181                 :             :           /* FIXME: Graphite and SLJL and target code still tends to produce
     182                 :             :              edges with no probability.  */
     183                 :  4102773290 :           if (profile_status_for_fn (cfun) >= PROFILE_GUESSED
     184                 :             :               && !e->probability.initialized_p () && !flag_graphite && 0)
     185                 :             :             {
     186                 :             :               error ("Uninitialized probability of edge %i->%i", e->src->index,
     187                 :             :                      e->dest->index);
     188                 :             :               err = true;
     189                 :             :             }
     190                 :  4102773290 :           if (!e->probability.verify ())
     191                 :             :             {
     192                 :           0 :               error ("verify_flow_info: Wrong probability of edge %i->%i",
     193                 :           0 :                      e->src->index, e->dest->index);
     194                 :           0 :               err = true;
     195                 :             :             }
     196                 :             : 
     197                 :  4102773290 :           last_visited [e->dest->index] = bb;
     198                 :             : 
     199                 :  4102773290 :           if (e->flags & EDGE_FALLTHRU)
     200                 :  1578514180 :             n_fallthru++;
     201                 :             : 
     202                 :  4102773290 :           if (e->src != bb)
     203                 :             :             {
     204                 :           0 :               error ("verify_flow_info: Basic block %d succ edge is corrupted",
     205                 :             :                      bb->index);
     206                 :           0 :               fprintf (stderr, "Predecessor: ");
     207                 :           0 :               dump_edge_info (stderr, e, TDF_DETAILS, 0);
     208                 :           0 :               fprintf (stderr, "\nSuccessor: ");
     209                 :           0 :               dump_edge_info (stderr, e, TDF_DETAILS, 1);
     210                 :           0 :               fprintf (stderr, "\n");
     211                 :           0 :               err = true;
     212                 :             :             }
     213                 :             : 
     214                 :  4102773290 :           if (e->flags & ~cfun->cfg->edge_flags_allocated)
     215                 :             :             {
     216                 :           0 :               error ("verify_flow_info: unallocated edge flag set on %d -> %d",
     217                 :           0 :                      e->src->index, e->dest->index);
     218                 :           0 :               err = true;
     219                 :             :             }
     220                 :             : 
     221                 :  4102773290 :           edge_checksum[e->dest->index] += (size_t) e;
     222                 :             :         }
     223                 :  2896136703 :       if (n_fallthru > 1)
     224                 :             :         {
     225                 :           0 :           error ("wrong amount of branch edges after unconditional jump %i", bb->index);
     226                 :           0 :           err = true;
     227                 :             :         }
     228                 :             : 
     229                 :  6996620286 :       FOR_EACH_EDGE (e, ei, bb->preds)
     230                 :             :         {
     231                 :  4100483583 :           if (e->dest != bb)
     232                 :             :             {
     233                 :           0 :               error ("basic block %d pred edge is corrupted", bb->index);
     234                 :           0 :               fputs ("Predecessor: ", stderr);
     235                 :           0 :               dump_edge_info (stderr, e, TDF_DETAILS, 0);
     236                 :           0 :               fputs ("\nSuccessor: ", stderr);
     237                 :           0 :               dump_edge_info (stderr, e, TDF_DETAILS, 1);
     238                 :           0 :               fputc ('\n', stderr);
     239                 :           0 :               err = true;
     240                 :             :             }
     241                 :             : 
     242                 :  4100483583 :           if (ei.index != e->dest_idx)
     243                 :             :             {
     244                 :           0 :               error ("basic block %d pred edge is corrupted", bb->index);
     245                 :           0 :               error ("its dest_idx should be %d, not %d",
     246                 :             :                      ei.index, e->dest_idx);
     247                 :           0 :               fputs ("Predecessor: ", stderr);
     248                 :           0 :               dump_edge_info (stderr, e, TDF_DETAILS, 0);
     249                 :           0 :               fputs ("\nSuccessor: ", stderr);
     250                 :           0 :               dump_edge_info (stderr, e, TDF_DETAILS, 1);
     251                 :           0 :               fputc ('\n', stderr);
     252                 :           0 :               err = true;
     253                 :             :             }
     254                 :             : 
     255                 :  4100483583 :           edge_checksum[e->dest->index] -= (size_t) e;
     256                 :             :         }
     257                 :             :     }
     258                 :             : 
     259                 :             :   /* Complete edge checksumming for ENTRY and EXIT.  */
     260                 :   317036577 :   {
     261                 :   317036577 :     edge e;
     262                 :   317036577 :     edge_iterator ei;
     263                 :             : 
     264                 :   634073154 :     FOR_EACH_EDGE (e, ei, ENTRY_BLOCK_PTR_FOR_FN (cfun)->succs)
     265                 :   317036577 :       edge_checksum[e->dest->index] += (size_t) e;
     266                 :             : 
     267                 :   636362861 :     FOR_EACH_EDGE (e, ei, EXIT_BLOCK_PTR_FOR_FN (cfun)->preds)
     268                 :   319326284 :       edge_checksum[e->dest->index] -= (size_t) e;
     269                 :             :   }
     270                 :             : 
     271                 :  3847246434 :   FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR_FOR_FN (cfun), NULL, next_bb)
     272                 :  3530209857 :     if (edge_checksum[bb->index])
     273                 :             :       {
     274                 :           0 :         error ("basic block %i edge lists are corrupted", bb->index);
     275                 :           0 :         err = true;
     276                 :             :       }
     277                 :             : 
     278                 :             :   /* Clean up.  */
     279                 :   317036577 :   free (last_visited);
     280                 :   317036577 :   free (edge_checksum);
     281                 :             : 
     282                 :   317036577 :   if (cfg_hooks->verify_flow_info)
     283                 :   317036577 :     if (cfg_hooks->verify_flow_info ())
     284                 :             :       err = true;
     285                 :             : 
     286                 :   317036577 :   if (err)
     287                 :           0 :     internal_error ("verify_flow_info failed");
     288                 :   317036577 :   timevar_pop (TV_CFG_VERIFY);
     289                 :   317036577 : }
     290                 :             : 
     291                 :             : /* Print out one basic block BB to file OUTF.  INDENT is printed at the
     292                 :             :    start of each new line.  FLAGS are the TDF_* flags in dumpfile.h.
     293                 :             : 
     294                 :             :    This function takes care of the purely graph related information.
     295                 :             :    The cfg hook for the active representation should dump
     296                 :             :    representation-specific information.  */
     297                 :             : 
     298                 :             : void
     299                 :      278928 : dump_bb (FILE *outf, basic_block bb, int indent, dump_flags_t flags)
     300                 :             : {
     301                 :      278928 :   if (flags & TDF_BLOCKS)
     302                 :       40944 :     dump_bb_info (outf, bb, indent, flags, true, false);
     303                 :      278928 :   if (cfg_hooks->dump_bb)
     304                 :      278928 :     cfg_hooks->dump_bb (outf, bb, indent, flags);
     305                 :      278928 :   if (flags & TDF_BLOCKS)
     306                 :       40944 :     dump_bb_info (outf, bb, indent, flags, false, true);
     307                 :      278928 :   fputc ('\n', outf);
     308                 :      278928 : }
     309                 :             : 
     310                 :             : DEBUG_FUNCTION void
     311                 :           0 : debug (basic_block_def &ref)
     312                 :             : {
     313                 :           0 :   dump_bb (stderr, &ref, 0, TDF_NONE);
     314                 :           0 : }
     315                 :             : 
     316                 :             : DEBUG_FUNCTION void
     317                 :           0 : debug (basic_block_def *ptr)
     318                 :             : {
     319                 :           0 :   if (ptr)
     320                 :           0 :     debug (*ptr);
     321                 :             :   else
     322                 :           0 :     fprintf (stderr, "<nil>\n");
     323                 :           0 : }
     324                 :             : 
     325                 :             : static void
     326                 :           0 : debug_slim (basic_block ptr)
     327                 :             : {
     328                 :           0 :   fprintf (stderr, "<basic_block %p (%d)>", (void *) ptr, ptr->index);
     329                 :           0 : }
     330                 :             : 
     331                 :           0 : DEFINE_DEBUG_VEC (basic_block_def *)
     332                 :           0 : DEFINE_DEBUG_HASH_SET (basic_block_def *)
     333                 :             : 
     334                 :             : /* Dumps basic block BB to pretty-printer PP, for use as a label of
     335                 :             :    a DOT graph record-node.  The implementation of this hook is
     336                 :             :    expected to write the label to the stream that is attached to PP.
     337                 :             :    Field separators between instructions are pipe characters printed
     338                 :             :    verbatim.  Instructions should be written with some characters
     339                 :             :    escaped, using pp_write_text_as_dot_label_to_stream().  */
     340                 :             : 
     341                 :             : void
     342                 :         435 : dump_bb_for_graph (pretty_printer *pp, basic_block bb)
     343                 :             : {
     344                 :         435 :   if (!cfg_hooks->dump_bb_for_graph)
     345                 :           0 :     internal_error ("%s does not support dump_bb_for_graph",
     346                 :             :                     cfg_hooks->name);
     347                 :             :   /* TODO: Add pretty printer for counter.  */
     348                 :         435 :   if (bb->count.initialized_p ())
     349                 :         340 :     pp_printf (pp, "COUNT:" "%" PRId64, bb->count.to_gcov_type ());
     350                 :         435 :   pp_write_text_to_stream (pp);
     351                 :         435 :   if (!(dump_flags & TDF_SLIM))
     352                 :         435 :     cfg_hooks->dump_bb_for_graph (pp, bb);
     353                 :         435 : }
     354                 :             : 
     355                 :             : /* Dump the complete CFG to FILE.  FLAGS are the TDF_* flags in dumpfile.h.  */
     356                 :             : void
     357                 :         287 : dump_flow_info (FILE *file, dump_flags_t flags)
     358                 :             : {
     359                 :         287 :   basic_block bb;
     360                 :             : 
     361                 :         287 :   fprintf (file, "\n%d basic blocks, %d edges.\n", n_basic_blocks_for_fn (cfun),
     362                 :         287 :            n_edges_for_fn (cfun));
     363                 :        2623 :   FOR_ALL_BB_FN (bb, cfun)
     364                 :        2336 :     dump_bb (file, bb, 0, flags);
     365                 :             : 
     366                 :         287 :   putc ('\n', file);
     367                 :         287 : }
     368                 :             : 
     369                 :             : /* Like above, but dump to stderr.  To be called from debuggers.  */
     370                 :             : void debug_flow_info (void);
     371                 :             : DEBUG_FUNCTION void
     372                 :           0 : debug_flow_info (void)
     373                 :             : {
     374                 :           0 :   dump_flow_info (stderr, TDF_DETAILS);
     375                 :           0 : }
     376                 :             : 
     377                 :             : /* Redirect edge E to the given basic block DEST and update underlying program
     378                 :             :    representation.  Returns edge representing redirected branch (that may not
     379                 :             :    be equivalent to E in the case of duplicate edges being removed) or NULL
     380                 :             :    if edge is not easily redirectable for whatever reason.  */
     381                 :             : 
     382                 :             : edge
     383                 :    71867008 : redirect_edge_and_branch (edge e, basic_block dest)
     384                 :             : {
     385                 :    71867008 :   edge ret;
     386                 :             : 
     387                 :    71867008 :   if (!cfg_hooks->redirect_edge_and_branch)
     388                 :           0 :     internal_error ("%s does not support redirect_edge_and_branch",
     389                 :             :                     cfg_hooks->name);
     390                 :             : 
     391                 :    71867008 :   ret = cfg_hooks->redirect_edge_and_branch (e, dest);
     392                 :             : 
     393                 :             :   /* If RET != E, then either the redirection failed, or the edge E
     394                 :             :      was removed since RET already lead to the same destination.  */
     395                 :    71867008 :   if (current_loops != NULL && ret == e)
     396                 :    59314184 :     rescan_loop_exit (e, false, false);
     397                 :             : 
     398                 :    71867008 :   return ret;
     399                 :             : }
     400                 :             : 
     401                 :             : /* Returns true if it is possible to remove the edge E by redirecting it
     402                 :             :    to the destination of the other edge going from its source.  */
     403                 :             : 
     404                 :             : bool
     405                 :      399567 : can_remove_branch_p (const_edge e)
     406                 :             : {
     407                 :      399567 :   if (!cfg_hooks->can_remove_branch_p)
     408                 :           0 :     internal_error ("%s does not support can_remove_branch_p",
     409                 :             :                     cfg_hooks->name);
     410                 :             : 
     411                 :      399567 :   if (EDGE_COUNT (e->src->succs) != 2)
     412                 :             :     return false;
     413                 :             : 
     414                 :      399567 :   return cfg_hooks->can_remove_branch_p (e);
     415                 :             : }
     416                 :             : 
     417                 :             : /* Removes E, by redirecting it to the destination of the other edge going
     418                 :             :    from its source.  Can_remove_branch_p must be true for E, hence this
     419                 :             :    operation cannot fail.  */
     420                 :             : 
     421                 :             : void
     422                 :      399622 : remove_branch (edge e)
     423                 :             : {
     424                 :      399622 :   edge other;
     425                 :      399622 :   basic_block src = e->src;
     426                 :      399622 :   int irr;
     427                 :             : 
     428                 :      399622 :   gcc_assert (EDGE_COUNT (e->src->succs) == 2);
     429                 :             : 
     430                 :      399622 :   other = EDGE_SUCC (src, EDGE_SUCC (src, 0) == e);
     431                 :      399622 :   irr = other->flags & EDGE_IRREDUCIBLE_LOOP;
     432                 :             : 
     433                 :      399622 :   e = redirect_edge_and_branch (e, other->dest);
     434                 :      399622 :   gcc_assert (e != NULL);
     435                 :             : 
     436                 :      399622 :   e->flags &= ~EDGE_IRREDUCIBLE_LOOP;
     437                 :      399622 :   e->flags |= irr;
     438                 :      399622 : }
     439                 :             : 
     440                 :             : /* Removes edge E from cfg.  Unlike remove_branch, it does not update IL.  */
     441                 :             : 
     442                 :             : void
     443                 :    77526185 : remove_edge (edge e)
     444                 :             : {
     445                 :    77526185 :   if (current_loops != NULL)
     446                 :             :     {
     447                 :    68904891 :       rescan_loop_exit (e, false, true);
     448                 :             : 
     449                 :             :       /* Removal of an edge inside an irreducible region or which leads
     450                 :             :          to an irreducible region can turn the region into a natural loop.
     451                 :             :          In that case, ask for the loop structure fixups.
     452                 :             : 
     453                 :             :          FIXME: Note that LOOPS_HAVE_MARKED_IRREDUCIBLE_REGIONS is not always
     454                 :             :          set, so always ask for fixups when removing an edge in that case.  */
     455                 :    68904891 :       if (!loops_state_satisfies_p (LOOPS_HAVE_MARKED_IRREDUCIBLE_REGIONS)
     456                 :     6869805 :           || (e->flags & EDGE_IRREDUCIBLE_LOOP)
     457                 :    75772163 :           || (e->dest->flags & BB_IRREDUCIBLE_LOOP))
     458                 :    62038177 :         loops_state_set (LOOPS_NEED_FIXUP);
     459                 :             :     }
     460                 :             : 
     461                 :             :   /* This is probably not needed, but it doesn't hurt.  */
     462                 :             :   /* FIXME: This should be called via a remove_edge hook.  */
     463                 :    77526185 :   if (current_ir_type () == IR_GIMPLE)
     464                 :    62129058 :     redirect_edge_var_map_clear (e);
     465                 :             : 
     466                 :    77526185 :   remove_edge_raw (e);
     467                 :    77526185 : }
     468                 :             : 
     469                 :             : /* Like redirect_edge_succ but avoid possible duplicate edge.  */
     470                 :             : 
     471                 :             : edge
     472                 :    75799584 : redirect_edge_succ_nodup (edge e, basic_block new_succ)
     473                 :             : {
     474                 :    75799584 :   edge s;
     475                 :             : 
     476                 :    75799584 :   s = find_edge (e->src, new_succ);
     477                 :    75799584 :   if (s && s != e)
     478                 :             :     {
     479                 :      364621 :       s->flags |= e->flags;
     480                 :      364621 :       s->probability += e->probability;
     481                 :             :       /* FIXME: This should be called via a hook and only for IR_GIMPLE.  */
     482                 :      364621 :       redirect_edge_var_map_dup (s, e);
     483                 :      364621 :       remove_edge (e);
     484                 :      364621 :       e = s;
     485                 :             :     }
     486                 :             :   else
     487                 :    75434963 :     redirect_edge_succ (e, new_succ);
     488                 :             : 
     489                 :    75799584 :   return e;
     490                 :             : }
     491                 :             : 
     492                 :             : /* Redirect the edge E to basic block DEST even if it requires creating
     493                 :             :    of a new basic block; then it returns the newly created basic block.
     494                 :             :    Aborts when redirection is impossible.  */
     495                 :             : 
     496                 :             : basic_block
     497                 :     8094440 : redirect_edge_and_branch_force (edge e, basic_block dest)
     498                 :             : {
     499                 :     8094440 :   basic_block ret, src = e->src;
     500                 :             : 
     501                 :     8094440 :   if (!cfg_hooks->redirect_edge_and_branch_force)
     502                 :           0 :     internal_error ("%s does not support redirect_edge_and_branch_force",
     503                 :             :                     cfg_hooks->name);
     504                 :             : 
     505                 :     8094440 :   if (current_loops != NULL)
     506                 :     6530811 :     rescan_loop_exit (e, false, true);
     507                 :             : 
     508                 :     8094440 :   ret = cfg_hooks->redirect_edge_and_branch_force (e, dest);
     509                 :             : 
     510                 :     8094440 :   if (ret != NULL && dom_info_available_p (CDI_DOMINATORS))
     511                 :       41123 :     set_immediate_dominator (CDI_DOMINATORS, ret, src);
     512                 :             : 
     513                 :     8094440 :   if (current_loops != NULL)
     514                 :             :     {
     515                 :     6530811 :       if (ret != NULL)
     516                 :             :         {
     517                 :           4 :           class loop *loop
     518                 :           4 :             = find_common_loop (single_pred (ret)->loop_father,
     519                 :           4 :                                 single_succ (ret)->loop_father);
     520                 :           4 :           add_bb_to_loop (ret, loop);
     521                 :             :         }
     522                 :     6530807 :       else if (find_edge (src, dest) == e)
     523                 :     6530800 :         rescan_loop_exit (e, true, false);
     524                 :             :     }
     525                 :             : 
     526                 :     8094440 :   return ret;
     527                 :             : }
     528                 :             : 
     529                 :             : /* Splits basic block BB after the specified instruction I (but at least after
     530                 :             :    the labels).  If I is NULL, splits just after labels.  The newly created edge
     531                 :             :    is returned.  The new basic block is created just after the old one.  */
     532                 :             : 
     533                 :             : static edge
     534                 :     7850456 : split_block_1 (basic_block bb, void *i)
     535                 :             : {
     536                 :     7850456 :   basic_block new_bb;
     537                 :     7850456 :   edge res;
     538                 :             : 
     539                 :     7850456 :   if (!cfg_hooks->split_block)
     540                 :           0 :     internal_error ("%s does not support split_block", cfg_hooks->name);
     541                 :             : 
     542                 :     7850456 :   new_bb = cfg_hooks->split_block (bb, i);
     543                 :     7850456 :   if (!new_bb)
     544                 :             :     return NULL;
     545                 :             : 
     546                 :     7850456 :   new_bb->count = bb->count;
     547                 :             : 
     548                 :     7850456 :   if (dom_info_available_p (CDI_DOMINATORS))
     549                 :             :     {
     550                 :      775060 :       redirect_immediate_dominators (CDI_DOMINATORS, bb, new_bb);
     551                 :      775060 :       set_immediate_dominator (CDI_DOMINATORS, new_bb, bb);
     552                 :             :     }
     553                 :             : 
     554                 :     7850456 :   if (current_loops != NULL)
     555                 :             :     {
     556                 :     6933809 :       edge_iterator ei;
     557                 :     6933809 :       edge e;
     558                 :     6933809 :       add_bb_to_loop (new_bb, bb->loop_father);
     559                 :             :       /* Identify all loops bb may have been the latch of and adjust them.  */
     560                 :    17237804 :       FOR_EACH_EDGE (e, ei, new_bb->succs)
     561                 :    10303995 :         if (e->dest->loop_father->latch == bb)
     562                 :      111571 :           e->dest->loop_father->latch = new_bb;
     563                 :             :     }
     564                 :             : 
     565                 :     7850456 :   res = make_single_succ_edge (bb, new_bb, EDGE_FALLTHRU);
     566                 :             : 
     567                 :     7850456 :   if (bb->flags & BB_IRREDUCIBLE_LOOP)
     568                 :             :     {
     569                 :        4277 :       new_bb->flags |= BB_IRREDUCIBLE_LOOP;
     570                 :        4277 :       res->flags |= EDGE_IRREDUCIBLE_LOOP;
     571                 :             :     }
     572                 :             : 
     573                 :             :   return res;
     574                 :             : }
     575                 :             : 
     576                 :             : edge
     577                 :     4875049 : split_block (basic_block bb, gimple *i)
     578                 :             : {
     579                 :     4875049 :   return split_block_1 (bb, i);
     580                 :             : }
     581                 :             : 
     582                 :             : edge
     583                 :     2738079 : split_block (basic_block bb, rtx i)
     584                 :             : {
     585                 :     2738079 :   return split_block_1 (bb, i);
     586                 :             : }
     587                 :             : 
     588                 :             : /* Splits block BB just after labels.  The newly created edge is returned.  */
     589                 :             : 
     590                 :             : edge
     591                 :      237328 : split_block_after_labels (basic_block bb)
     592                 :             : {
     593                 :      237328 :   return split_block_1 (bb, NULL);
     594                 :             : }
     595                 :             : 
     596                 :             : /* Moves block BB immediately after block AFTER.  Returns false if the
     597                 :             :    movement was impossible.  */
     598                 :             : 
     599                 :             : bool
     600                 :    20060461 : move_block_after (basic_block bb, basic_block after)
     601                 :             : {
     602                 :    20060461 :   bool ret;
     603                 :             : 
     604                 :    20060461 :   if (!cfg_hooks->move_block_after)
     605                 :           0 :     internal_error ("%s does not support move_block_after", cfg_hooks->name);
     606                 :             : 
     607                 :    20060461 :   ret = cfg_hooks->move_block_after (bb, after);
     608                 :             : 
     609                 :    20060461 :   return ret;
     610                 :             : }
     611                 :             : 
     612                 :             : /* Deletes the basic block BB.  */
     613                 :             : 
     614                 :             : void
     615                 :    40957251 : delete_basic_block (basic_block bb)
     616                 :             : {
     617                 :    40957251 :   if (!cfg_hooks->delete_basic_block)
     618                 :           0 :     internal_error ("%s does not support delete_basic_block", cfg_hooks->name);
     619                 :             : 
     620                 :    40957251 :   cfg_hooks->delete_basic_block (bb);
     621                 :             : 
     622                 :    40957251 :   if (current_loops != NULL)
     623                 :             :     {
     624                 :    36182686 :       class loop *loop = bb->loop_father;
     625                 :             : 
     626                 :             :       /* If we remove the header or the latch of a loop, mark the loop for
     627                 :             :          removal.  */
     628                 :    36182686 :       if (loop->latch == bb
     629                 :    35996490 :           || loop->header == bb)
     630                 :      226846 :         mark_loop_for_removal (loop);
     631                 :             : 
     632                 :    36182686 :       remove_bb_from_loops (bb);
     633                 :             :     }
     634                 :             : 
     635                 :             :   /* Remove the edges into and out of this block.  Note that there may
     636                 :             :      indeed be edges in, if we are removing an unreachable loop.  */
     637                 :    82493153 :   while (EDGE_COUNT (bb->preds) != 0)
     638                 :      598534 :     remove_edge (EDGE_PRED (bb, 0));
     639                 :    47394101 :   while (EDGE_COUNT (bb->succs) != 0)
     640                 :     6436850 :     remove_edge (EDGE_SUCC (bb, 0));
     641                 :             : 
     642                 :    40957251 :   if (dom_info_available_p (CDI_DOMINATORS))
     643                 :    29009460 :     delete_from_dominance_info (CDI_DOMINATORS, bb);
     644                 :    40957251 :   if (dom_info_available_p (CDI_POST_DOMINATORS))
     645                 :      411681 :     delete_from_dominance_info (CDI_POST_DOMINATORS, bb);
     646                 :             : 
     647                 :             :   /* Remove the basic block from the array.  */
     648                 :    40957251 :   expunge_block (bb);
     649                 :    40957251 : }
     650                 :             : 
     651                 :             : /* Splits edge E and returns the newly created basic block.  */
     652                 :             : 
     653                 :             : basic_block
     654                 :    28398756 : split_edge (edge e)
     655                 :             : {
     656                 :    28398756 :   basic_block ret;
     657                 :    28398756 :   profile_count count = e->count ();
     658                 :    28398756 :   edge f;
     659                 :    28398756 :   bool irr = (e->flags & EDGE_IRREDUCIBLE_LOOP) != 0;
     660                 :    28398756 :   bool back = (e->flags & EDGE_DFS_BACK) != 0;
     661                 :    28398756 :   class loop *loop;
     662                 :    28398756 :   basic_block src = e->src, dest = e->dest;
     663                 :             : 
     664                 :    28398756 :   if (!cfg_hooks->split_edge)
     665                 :           0 :     internal_error ("%s does not support split_edge", cfg_hooks->name);
     666                 :             : 
     667                 :    28398756 :   if (current_loops != NULL)
     668                 :    27085064 :     rescan_loop_exit (e, false, true);
     669                 :             : 
     670                 :    28398756 :   ret = cfg_hooks->split_edge (e);
     671                 :    28398756 :   ret->count = count;
     672                 :    28398756 :   single_succ_edge (ret)->probability = profile_probability::always ();
     673                 :             : 
     674                 :    28398756 :   if (irr)
     675                 :             :     {
     676                 :       55029 :       ret->flags |= BB_IRREDUCIBLE_LOOP;
     677                 :       55029 :       single_pred_edge (ret)->flags |= EDGE_IRREDUCIBLE_LOOP;
     678                 :       55029 :       single_succ_edge (ret)->flags |= EDGE_IRREDUCIBLE_LOOP;
     679                 :             :     }
     680                 :    28398756 :   if (back)
     681                 :             :     {
     682                 :     1938242 :       single_pred_edge (ret)->flags &= ~EDGE_DFS_BACK;
     683                 :     1938242 :       single_succ_edge (ret)->flags |= EDGE_DFS_BACK;
     684                 :             :     }
     685                 :             : 
     686                 :    28398756 :   if (dom_info_available_p (CDI_DOMINATORS))
     687                 :    24581749 :     set_immediate_dominator (CDI_DOMINATORS, ret, single_pred (ret));
     688                 :             : 
     689                 :    28398756 :   if (dom_info_state (CDI_DOMINATORS) >= DOM_NO_FAST_QUERY)
     690                 :             :     {
     691                 :             :       /* There are two cases:
     692                 :             : 
     693                 :             :          If the immediate dominator of e->dest is not e->src, it
     694                 :             :          remains unchanged.
     695                 :             : 
     696                 :             :          If immediate dominator of e->dest is e->src, it may become
     697                 :             :          ret, provided that all other predecessors of e->dest are
     698                 :             :          dominated by e->dest.  */
     699                 :             : 
     700                 :    24581749 :       if (get_immediate_dominator (CDI_DOMINATORS, single_succ (ret))
     701                 :    24581749 :           == single_pred (ret))
     702                 :             :         {
     703                 :     8578228 :           edge_iterator ei;
     704                 :    19085946 :           FOR_EACH_EDGE (f, ei, single_succ (ret)->preds)
     705                 :             :             {
     706                 :    15082153 :               if (f == single_succ_edge (ret))
     707                 :     6754249 :                 continue;
     708                 :             : 
     709                 :     8327904 :               if (!dominated_by_p (CDI_DOMINATORS, f->src,
     710                 :     8327904 :                                    single_succ (ret)))
     711                 :             :                 break;
     712                 :             :             }
     713                 :             : 
     714                 :     8578228 :           if (!f)
     715                 :     4003793 :             set_immediate_dominator (CDI_DOMINATORS, single_succ (ret), ret);
     716                 :             :         }
     717                 :             :     }
     718                 :             : 
     719                 :    28398756 :   if (current_loops != NULL)
     720                 :             :     {
     721                 :    27085064 :       loop = find_common_loop (src->loop_father, dest->loop_father);
     722                 :    27085064 :       add_bb_to_loop (ret, loop);
     723                 :             : 
     724                 :             :       /* If we split the latch edge of loop adjust the latch block.  */
     725                 :    27085064 :       if (loop->latch == src
     726                 :     6156978 :           && loop->header == dest)
     727                 :     6156916 :         loop->latch = ret;
     728                 :             :     }
     729                 :             : 
     730                 :    28398756 :   return ret;
     731                 :             : }
     732                 :             : 
     733                 :             : /* Creates a new basic block just after the basic block AFTER.
     734                 :             :    HEAD and END are the first and the last statement belonging
     735                 :             :    to the block.  If both are NULL, an empty block is created.  */
     736                 :             : 
     737                 :             : static basic_block
     738                 :    77928454 : create_basic_block_1 (void *head, void *end, basic_block after)
     739                 :             : {
     740                 :    77928454 :   basic_block ret;
     741                 :             : 
     742                 :    77928454 :   if (!cfg_hooks->create_basic_block)
     743                 :           0 :     internal_error ("%s does not support create_basic_block", cfg_hooks->name);
     744                 :             : 
     745                 :    77928454 :   ret = cfg_hooks->create_basic_block (head, end, after);
     746                 :             : 
     747                 :    77928454 :   if (dom_info_available_p (CDI_DOMINATORS))
     748                 :    29739257 :     add_to_dominance_info (CDI_DOMINATORS, ret);
     749                 :    77928454 :   if (dom_info_available_p (CDI_POST_DOMINATORS))
     750                 :      108244 :     add_to_dominance_info (CDI_POST_DOMINATORS, ret);
     751                 :             : 
     752                 :    77928454 :   return ret;
     753                 :             : }
     754                 :             : 
     755                 :             : basic_block
     756                 :    32755480 : create_basic_block (gimple_seq seq, basic_block after)
     757                 :             : {
     758                 :    32755480 :   return create_basic_block_1 (seq, NULL, after);
     759                 :             : }
     760                 :             : 
     761                 :             : basic_block
     762                 :    12563055 : create_basic_block (rtx head, rtx end, basic_block after)
     763                 :             : {
     764                 :    12563055 :   return create_basic_block_1 (head, end, after);
     765                 :             : }
     766                 :             : 
     767                 :             : 
     768                 :             : /* Creates an empty basic block just after basic block AFTER.  */
     769                 :             : 
     770                 :             : basic_block
     771                 :    32609919 : create_empty_bb (basic_block after)
     772                 :             : {
     773                 :    32609919 :   return create_basic_block_1 (NULL, NULL, after);
     774                 :             : }
     775                 :             : 
     776                 :             : /* Checks whether we may merge blocks BB1 and BB2.  */
     777                 :             : 
     778                 :             : bool
     779                 :   412663268 : can_merge_blocks_p (basic_block bb1, basic_block bb2)
     780                 :             : {
     781                 :   412663268 :   bool ret;
     782                 :             : 
     783                 :   412663268 :   if (!cfg_hooks->can_merge_blocks_p)
     784                 :           0 :     internal_error ("%s does not support can_merge_blocks_p", cfg_hooks->name);
     785                 :             : 
     786                 :   412663268 :   ret = cfg_hooks->can_merge_blocks_p (bb1, bb2);
     787                 :             : 
     788                 :   412663268 :   return ret;
     789                 :             : }
     790                 :             : 
     791                 :             : void
     792                 :     5938009 : predict_edge (edge e, enum br_predictor predictor, int probability)
     793                 :             : {
     794                 :     5938009 :   if (!cfg_hooks->predict_edge)
     795                 :           0 :     internal_error ("%s does not support predict_edge", cfg_hooks->name);
     796                 :             : 
     797                 :     5938009 :   cfg_hooks->predict_edge (e, predictor, probability);
     798                 :     5938009 : }
     799                 :             : 
     800                 :             : bool
     801                 :     3129944 : predicted_by_p (const_basic_block bb, enum br_predictor predictor)
     802                 :             : {
     803                 :     3129944 :   if (!cfg_hooks->predict_edge)
     804                 :           0 :     internal_error ("%s does not support predicted_by_p", cfg_hooks->name);
     805                 :             : 
     806                 :     3129944 :   return cfg_hooks->predicted_by_p (bb, predictor);
     807                 :             : }
     808                 :             : 
     809                 :             : /* Merges basic block B into basic block A.  */
     810                 :             : 
     811                 :             : void
     812                 :    18700059 : merge_blocks (basic_block a, basic_block b)
     813                 :             : {
     814                 :    18700059 :   edge e;
     815                 :    18700059 :   edge_iterator ei;
     816                 :             : 
     817                 :    18700059 :   if (!cfg_hooks->merge_blocks)
     818                 :           0 :     internal_error ("%s does not support merge_blocks", cfg_hooks->name);
     819                 :             : 
     820                 :    18700059 :   cfg_hooks->merge_blocks (a, b);
     821                 :             : 
     822                 :    18700059 :   if (current_loops != NULL)
     823                 :             :     {
     824                 :             :       /* If the block we merge into is a loop header do nothing unless ... */
     825                 :    15776647 :       if (a->loop_father->header == a)
     826                 :             :         {
     827                 :             :           /* ... we merge two loop headers, in which case we kill
     828                 :             :              the inner loop.  */
     829                 :      579900 :           if (b->loop_father->header == b)
     830                 :         436 :             mark_loop_for_removal (b->loop_father);
     831                 :             :         }
     832                 :             :       /* If we merge a loop header into its predecessor, update the loop
     833                 :             :          structure.  */
     834                 :    15196747 :       else if (b->loop_father->header == b)
     835                 :             :         {
     836                 :         165 :           remove_bb_from_loops (a);
     837                 :         165 :           add_bb_to_loop  (a, b->loop_father);
     838                 :         165 :           a->loop_father->header = a;
     839                 :             :         }
     840                 :             :       /* If we merge a loop latch into its predecessor, update the loop
     841                 :             :          structure.  */
     842                 :    15776647 :       if (b->loop_father->latch
     843                 :    15658158 :           && b->loop_father->latch == b)
     844                 :      222115 :         b->loop_father->latch = a;
     845                 :    15776647 :       remove_bb_from_loops (b);
     846                 :             :     }
     847                 :             : 
     848                 :             :   /* Normally there should only be one successor of A and that is B, but
     849                 :             :      partway though the merge of blocks for conditional_execution we'll
     850                 :             :      be merging a TEST block with THEN and ELSE successors.  Free the
     851                 :             :      whole lot of them and hope the caller knows what they're doing.  */
     852                 :             : 
     853                 :    37400118 :   while (EDGE_COUNT (a->succs) != 0)
     854                 :    18700059 :     remove_edge (EDGE_SUCC (a, 0));
     855                 :             : 
     856                 :             :   /* Adjust the edges out of B for the new owner.  */
     857                 :    42767137 :   FOR_EACH_EDGE (e, ei, b->succs)
     858                 :             :     {
     859                 :    24067078 :       e->src = a;
     860                 :    24067078 :       if (current_loops != NULL)
     861                 :             :         {
     862                 :             :           /* If b was a latch, a now is.  */
     863                 :    20787649 :           if (e->dest->loop_father->latch == b)
     864                 :         828 :             e->dest->loop_father->latch = a;
     865                 :    20787649 :           rescan_loop_exit (e, true, false);
     866                 :             :         }
     867                 :             :     }
     868                 :    18700059 :   a->succs = b->succs;
     869                 :    18700059 :   a->flags |= b->flags;
     870                 :             : 
     871                 :             :   /* B hasn't quite yet ceased to exist.  Attempt to prevent mishap.  */
     872                 :    18700059 :   b->preds = b->succs = NULL;
     873                 :             : 
     874                 :    18700059 :   if (dom_info_available_p (CDI_DOMINATORS))
     875                 :    14113845 :     redirect_immediate_dominators (CDI_DOMINATORS, b, a);
     876                 :             : 
     877                 :    18700059 :   if (dom_info_available_p (CDI_DOMINATORS))
     878                 :    14113845 :     delete_from_dominance_info (CDI_DOMINATORS, b);
     879                 :    18700059 :   if (dom_info_available_p (CDI_POST_DOMINATORS))
     880                 :       91354 :     delete_from_dominance_info (CDI_POST_DOMINATORS, b);
     881                 :             : 
     882                 :    18700059 :   expunge_block (b);
     883                 :    18700059 : }
     884                 :             : 
     885                 :             : /* Split BB into entry part and the rest (the rest is the newly created block).
     886                 :             :    Redirect those edges for that REDIRECT_EDGE_P returns true to the entry
     887                 :             :    part.  Returns the edge connecting the entry part to the rest.  */
     888                 :             : 
     889                 :             : edge
     890                 :      213951 : make_forwarder_block (basic_block bb, bool (*redirect_edge_p) (edge),
     891                 :             :                       void (*new_bb_cbk) (basic_block))
     892                 :             : {
     893                 :      213951 :   edge e, fallthru;
     894                 :      213951 :   edge_iterator ei;
     895                 :      213951 :   basic_block dummy, jump;
     896                 :      213951 :   class loop *loop, *ploop, *cloop;
     897                 :             : 
     898                 :      213951 :   if (!cfg_hooks->make_forwarder_block)
     899                 :           0 :     internal_error ("%s does not support make_forwarder_block",
     900                 :             :                     cfg_hooks->name);
     901                 :             : 
     902                 :      213951 :   fallthru = split_block_after_labels (bb);
     903                 :      213951 :   dummy = fallthru->src;
     904                 :      213951 :   dummy->count = profile_count::zero ();
     905                 :      213951 :   bb = fallthru->dest;
     906                 :             : 
     907                 :             :   /* Redirect back edges we want to keep.  */
     908                 :      961255 :   for (ei = ei_start (dummy->preds); (e = ei_safe_edge (ei)); )
     909                 :             :     {
     910                 :      747304 :       basic_block e_src;
     911                 :             : 
     912                 :      747304 :       if (redirect_edge_p (e))
     913                 :             :         {
     914                 :      524760 :           dummy->count += e->count ();
     915                 :      524760 :           ei_next (&ei);
     916                 :      524760 :           continue;
     917                 :             :         }
     918                 :             : 
     919                 :      222544 :       e_src = e->src;
     920                 :      222544 :       jump = redirect_edge_and_branch_force (e, bb);
     921                 :      222544 :       if (jump != NULL)
     922                 :             :         {
     923                 :             :           /* If we redirected the loop latch edge, the JUMP block now acts like
     924                 :             :              the new latch of the loop.  */
     925                 :           3 :           if (current_loops != NULL
     926                 :           3 :               && dummy->loop_father != NULL
     927                 :           3 :               && dummy->loop_father->header == dummy
     928                 :           3 :               && dummy->loop_father->latch == e_src)
     929                 :           0 :             dummy->loop_father->latch = jump;
     930                 :             : 
     931                 :           3 :           if (new_bb_cbk != NULL)
     932                 :           0 :             new_bb_cbk (jump);
     933                 :             :         }
     934                 :             :     }
     935                 :             : 
     936                 :      213951 :   if (dom_info_available_p (CDI_DOMINATORS))
     937                 :             :     {
     938                 :      175563 :       vec<basic_block> doms_to_fix;
     939                 :      175563 :       doms_to_fix.create (2);
     940                 :      175563 :       doms_to_fix.quick_push (dummy);
     941                 :      175563 :       doms_to_fix.quick_push (bb);
     942                 :      175563 :       iterate_fix_dominators (CDI_DOMINATORS, doms_to_fix, false);
     943                 :      175563 :       doms_to_fix.release ();
     944                 :             :     }
     945                 :             : 
     946                 :      213951 :   if (current_loops != NULL)
     947                 :             :     {
     948                 :             :       /* If we do not split a loop header, then both blocks belong to the
     949                 :             :          same loop.  In case we split loop header and do not redirect the
     950                 :             :          latch edge to DUMMY, then DUMMY belongs to the outer loop, and
     951                 :             :          BB becomes the new header.  If latch is not recorded for the loop,
     952                 :             :          we leave this updating on the caller (this may only happen during
     953                 :             :          loop analysis).  */
     954                 :      213951 :       loop = dummy->loop_father;
     955                 :      213951 :       if (loop->header == dummy
     956                 :      213799 :           && loop->latch != NULL
     957                 :      336978 :           && find_edge (loop->latch, dummy) == NULL)
     958                 :             :         {
     959                 :      122984 :           remove_bb_from_loops (dummy);
     960                 :      122984 :           loop->header = bb;
     961                 :             : 
     962                 :      122984 :           cloop = loop;
     963                 :      417573 :           FOR_EACH_EDGE (e, ei, dummy->preds)
     964                 :             :             {
     965                 :      294589 :               cloop = find_common_loop (cloop, e->src->loop_father);
     966                 :             :             }
     967                 :      122984 :           add_bb_to_loop (dummy, cloop);
     968                 :             :         }
     969                 :             : 
     970                 :             :       /* In case we split loop latch, update it.  */
     971                 :      696776 :       for (ploop = loop; ploop; ploop = loop_outer (ploop))
     972                 :      482825 :         if (ploop->latch == dummy)
     973                 :           0 :           ploop->latch = bb;
     974                 :             :     }
     975                 :             : 
     976                 :      213951 :   cfg_hooks->make_forwarder_block (fallthru);
     977                 :             : 
     978                 :      213951 :   return fallthru;
     979                 :             : }
     980                 :             : 
     981                 :             : /* Try to make the edge fallthru.  */
     982                 :             : 
     983                 :             : void
     984                 :      690483 : tidy_fallthru_edge (edge e)
     985                 :             : {
     986                 :      690483 :   if (cfg_hooks->tidy_fallthru_edge)
     987                 :      690483 :     cfg_hooks->tidy_fallthru_edge (e);
     988                 :      690483 : }
     989                 :             : 
     990                 :             : /* Fix up edges that now fall through, or rather should now fall through
     991                 :             :    but previously required a jump around now deleted blocks.  Simplify
     992                 :             :    the search by only examining blocks numerically adjacent, since this
     993                 :             :    is how they were created.
     994                 :             : 
     995                 :             :    ??? This routine is currently RTL specific.  */
     996                 :             : 
     997                 :             : void
     998                 :      431325 : tidy_fallthru_edges (void)
     999                 :             : {
    1000                 :      431325 :   basic_block b, c;
    1001                 :             : 
    1002                 :      431325 :   if (!cfg_hooks->tidy_fallthru_edge)
    1003                 :             :     return;
    1004                 :             : 
    1005                 :      115401 :   if (ENTRY_BLOCK_PTR_FOR_FN (cfun)->next_bb == EXIT_BLOCK_PTR_FOR_FN (cfun))
    1006                 :             :     return;
    1007                 :             : 
    1008                 :     3754115 :   FOR_BB_BETWEEN (b, ENTRY_BLOCK_PTR_FOR_FN (cfun)->next_bb,
    1009                 :             :                   EXIT_BLOCK_PTR_FOR_FN (cfun)->prev_bb, next_bb)
    1010                 :             :     {
    1011                 :     3638714 :       edge s;
    1012                 :             : 
    1013                 :     3638714 :       c = b->next_bb;
    1014                 :             : 
    1015                 :             :       /* We care about simple conditional or unconditional jumps with
    1016                 :             :          a single successor.
    1017                 :             : 
    1018                 :             :          If we had a conditional branch to the next instruction when
    1019                 :             :          CFG was built, then there will only be one out edge for the
    1020                 :             :          block which ended with the conditional branch (since we do
    1021                 :             :          not create duplicate edges).
    1022                 :             : 
    1023                 :             :          Furthermore, the edge will be marked as a fallthru because we
    1024                 :             :          merge the flags for the duplicate edges.  So we do not want to
    1025                 :             :          check that the edge is not a FALLTHRU edge.  */
    1026                 :             : 
    1027                 :     5352419 :       if (single_succ_p (b))
    1028                 :             :         {
    1029                 :     1713705 :           s = single_succ_edge (b);
    1030                 :     1713705 :           if (! (s->flags & EDGE_COMPLEX)
    1031                 :     1652699 :               && s->dest == c
    1032                 :     2441499 :               && !(JUMP_P (BB_END (b)) && CROSSING_JUMP_P (BB_END (b))))
    1033                 :      682236 :             tidy_fallthru_edge (s);
    1034                 :             :         }
    1035                 :             :     }
    1036                 :             : }
    1037                 :             : 
    1038                 :             : /* Edge E is assumed to be fallthru edge.  Emit needed jump instruction
    1039                 :             :    (and possibly create new basic block) to make edge non-fallthru.
    1040                 :             :    Return newly created BB or NULL if none.  */
    1041                 :             : 
    1042                 :             : basic_block
    1043                 :      793905 : force_nonfallthru (edge e)
    1044                 :             : {
    1045                 :      793905 :   basic_block ret, src = e->src;
    1046                 :             : 
    1047                 :      793905 :   if (!cfg_hooks->force_nonfallthru)
    1048                 :           0 :     internal_error ("%s does not support force_nonfallthru",
    1049                 :             :                     cfg_hooks->name);
    1050                 :             : 
    1051                 :      793905 :   ret = cfg_hooks->force_nonfallthru (e);
    1052                 :      793905 :   if (ret != NULL)
    1053                 :             :     {
    1054                 :      173391 :       if (dom_info_available_p (CDI_DOMINATORS))
    1055                 :        4152 :         set_immediate_dominator (CDI_DOMINATORS, ret, src);
    1056                 :             : 
    1057                 :      173391 :       if (current_loops != NULL)
    1058                 :             :         {
    1059                 :       71808 :           basic_block pred = single_pred (ret);
    1060                 :       71808 :           basic_block succ = single_succ (ret);
    1061                 :       71808 :           class loop *loop
    1062                 :       71808 :             = find_common_loop (pred->loop_father, succ->loop_father);
    1063                 :       71808 :           rescan_loop_exit (e, false, true);
    1064                 :       71808 :           add_bb_to_loop (ret, loop);
    1065                 :             : 
    1066                 :             :           /* If we split the latch edge of loop adjust the latch block.  */
    1067                 :       71808 :           if (loop->latch == pred
    1068                 :        3776 :               && loop->header == succ)
    1069                 :        3776 :             loop->latch = ret;
    1070                 :             :         }
    1071                 :             :     }
    1072                 :             : 
    1073                 :      793905 :   return ret;
    1074                 :             : }
    1075                 :             : 
    1076                 :             : /* Returns true if we can duplicate basic block BB.  */
    1077                 :             : 
    1078                 :             : bool
    1079                 :    16321897 : can_duplicate_block_p (const_basic_block bb)
    1080                 :             : {
    1081                 :    16321897 :   if (!cfg_hooks->can_duplicate_block_p)
    1082                 :           0 :     internal_error ("%s does not support can_duplicate_block_p",
    1083                 :             :                     cfg_hooks->name);
    1084                 :             : 
    1085                 :    16321897 :   if (bb == EXIT_BLOCK_PTR_FOR_FN (cfun) || bb == ENTRY_BLOCK_PTR_FOR_FN (cfun))
    1086                 :             :     return false;
    1087                 :             : 
    1088                 :    16321897 :   return cfg_hooks->can_duplicate_block_p (bb);
    1089                 :             : }
    1090                 :             : 
    1091                 :             : /* Duplicate basic block BB, place it after AFTER (if non-null) and redirect
    1092                 :             :    edge E to it (if non-null).  Return the new basic block.
    1093                 :             : 
    1094                 :             :    If BB contains a returns_twice call, the caller is responsible for recreating
    1095                 :             :    incoming abnormal edges corresponding to the "second return" for the copy.
    1096                 :             :    gimple_can_duplicate_bb_p rejects such blocks, while RTL likes to live
    1097                 :             :    dangerously.
    1098                 :             : 
    1099                 :             :    If BB has incoming abnormal edges for some other reason, their destinations
    1100                 :             :    should be tied to label(s) of the original BB and not the copy.  */
    1101                 :             : 
    1102                 :             : basic_block
    1103                 :     4090288 : duplicate_block (basic_block bb, edge e, basic_block after, copy_bb_data *id)
    1104                 :             : {
    1105                 :     4090288 :   edge s, n;
    1106                 :     4090288 :   basic_block new_bb;
    1107                 :     4364926 :   profile_count new_count = e ? e->count (): profile_count::uninitialized ();
    1108                 :     4090288 :   edge_iterator ei;
    1109                 :             : 
    1110                 :     4090288 :   if (!cfg_hooks->duplicate_block)
    1111                 :           0 :     internal_error ("%s does not support duplicate_block",
    1112                 :             :                     cfg_hooks->name);
    1113                 :             : 
    1114                 :     4090288 :   if (bb->count < new_count)
    1115                 :        1706 :     new_count = bb->count;
    1116                 :             : 
    1117                 :     4090288 :   gcc_checking_assert (can_duplicate_block_p (bb));
    1118                 :             : 
    1119                 :     4090288 :   new_bb = cfg_hooks->duplicate_block (bb, id);
    1120                 :     4090288 :   if (after)
    1121                 :     3757163 :     move_block_after (new_bb, after);
    1122                 :             : 
    1123                 :     4090288 :   new_bb->flags = (bb->flags & ~BB_DUPLICATED);
    1124                 :    11215727 :   FOR_EACH_EDGE (s, ei, bb->succs)
    1125                 :             :     {
    1126                 :             :       /* Since we are creating edges from a new block to successors
    1127                 :             :          of another block (which therefore are known to be disjoint), there
    1128                 :             :          is no need to actually check for duplicated edges.  */
    1129                 :     7125439 :       n = unchecked_make_edge (new_bb, s->dest, s->flags);
    1130                 :     7125439 :       n->probability = s->probability;
    1131                 :     7125439 :       n->aux = s->aux;
    1132                 :             :     }
    1133                 :             : 
    1134                 :     4090288 :   if (e)
    1135                 :             :     {
    1136                 :      274638 :       new_bb->count = new_count;
    1137                 :      274638 :       bb->count -= new_count;
    1138                 :             : 
    1139                 :      274638 :       redirect_edge_and_branch_force (e, new_bb);
    1140                 :             :     }
    1141                 :             :   else
    1142                 :     3815650 :     new_bb->count = bb->count;
    1143                 :             : 
    1144                 :     4090288 :   set_bb_original (new_bb, bb);
    1145                 :     4090288 :   set_bb_copy (bb, new_bb);
    1146                 :             : 
    1147                 :             :   /* Add the new block to the copy of the loop of BB, or directly to the loop
    1148                 :             :      of BB if the loop is not being copied.  */
    1149                 :     4090288 :   if (current_loops != NULL)
    1150                 :             :     {
    1151                 :     3796031 :       class loop *cloop = bb->loop_father;
    1152                 :     3796031 :       class loop *copy = get_loop_copy (cloop);
    1153                 :             :       /* If we copied the loop header block but not the loop
    1154                 :             :          we have created a loop with multiple entries.  Ditch the loop,
    1155                 :             :          add the new block to the outer loop and arrange for a fixup.  */
    1156                 :     3796031 :       if (!copy
    1157                 :      342167 :           && cloop->header == bb)
    1158                 :             :         {
    1159                 :         370 :           add_bb_to_loop (new_bb, loop_outer (cloop));
    1160                 :         370 :           mark_loop_for_removal (cloop);
    1161                 :             :         }
    1162                 :             :       else
    1163                 :             :         {
    1164                 :     3795661 :           add_bb_to_loop (new_bb, copy ? copy : cloop);
    1165                 :             :           /* If we copied the loop latch block but not the loop, adjust
    1166                 :             :              loop state.  */
    1167                 :     3795661 :           if (!copy
    1168                 :      341797 :               && cloop->latch == bb)
    1169                 :             :             {
    1170                 :         568 :               cloop->latch = NULL;
    1171                 :         568 :               loops_state_set (LOOPS_MAY_HAVE_MULTIPLE_LATCHES);
    1172                 :             :             }
    1173                 :             :         }
    1174                 :             :     }
    1175                 :             : 
    1176                 :     4090288 :   return new_bb;
    1177                 :             : }
    1178                 :             : 
    1179                 :             : /* Return 1 if BB ends with a call, possibly followed by some
    1180                 :             :    instructions that must stay with the call, 0 otherwise.  */
    1181                 :             : 
    1182                 :             : bool
    1183                 :     9158468 : block_ends_with_call_p (basic_block bb)
    1184                 :             : {
    1185                 :     9158468 :   if (!cfg_hooks->block_ends_with_call_p)
    1186                 :           0 :     internal_error ("%s does not support block_ends_with_call_p", cfg_hooks->name);
    1187                 :             : 
    1188                 :     9158468 :   return (cfg_hooks->block_ends_with_call_p) (bb);
    1189                 :             : }
    1190                 :             : 
    1191                 :             : /* Return 1 if BB ends with a conditional branch, 0 otherwise.  */
    1192                 :             : 
    1193                 :             : bool
    1194                 :        1717 : block_ends_with_condjump_p (const_basic_block bb)
    1195                 :             : {
    1196                 :        1717 :   if (!cfg_hooks->block_ends_with_condjump_p)
    1197                 :           0 :     internal_error ("%s does not support block_ends_with_condjump_p",
    1198                 :             :                     cfg_hooks->name);
    1199                 :             : 
    1200                 :        1717 :   return (cfg_hooks->block_ends_with_condjump_p) (bb);
    1201                 :             : }
    1202                 :             : 
    1203                 :             : /* Add fake edges to the function exit for any non constant and non noreturn
    1204                 :             :    calls, volatile inline assembly in the bitmap of blocks specified by
    1205                 :             :    BLOCKS or to the whole CFG if BLOCKS is zero.  Return the number of blocks
    1206                 :             :    that were split.
    1207                 :             : 
    1208                 :             :    The goal is to expose cases in which entering a basic block does not imply
    1209                 :             :    that all subsequent instructions must be executed.  */
    1210                 :             : 
    1211                 :             : int
    1212                 :        2226 : flow_call_edges_add (sbitmap blocks)
    1213                 :             : {
    1214                 :        2226 :   if (!cfg_hooks->flow_call_edges_add)
    1215                 :           0 :     internal_error ("%s does not support flow_call_edges_add",
    1216                 :             :                     cfg_hooks->name);
    1217                 :             : 
    1218                 :        2226 :   return (cfg_hooks->flow_call_edges_add) (blocks);
    1219                 :             : }
    1220                 :             : 
    1221                 :             : /* This function is called immediately after edge E is added to the
    1222                 :             :    edge vector E->dest->preds.  */
    1223                 :             : 
    1224                 :             : void
    1225                 :   188611947 : execute_on_growing_pred (edge e)
    1226                 :             : {
    1227                 :   188611947 :   if (! (e->dest->flags & BB_DUPLICATED)
    1228                 :   186607494 :       && cfg_hooks->execute_on_growing_pred)
    1229                 :   147654545 :     cfg_hooks->execute_on_growing_pred (e);
    1230                 :   188611947 : }
    1231                 :             : 
    1232                 :             : /* This function is called immediately before edge E is removed from
    1233                 :             :    the edge vector E->dest->preds.  */
    1234                 :             : 
    1235                 :             : void
    1236                 :   159196050 : execute_on_shrinking_pred (edge e)
    1237                 :             : {
    1238                 :   159196050 :   if (! (e->dest->flags & BB_DUPLICATED)
    1239                 :   157191597 :       && cfg_hooks->execute_on_shrinking_pred)
    1240                 :   120548571 :     cfg_hooks->execute_on_shrinking_pred (e);
    1241                 :   159196050 : }
    1242                 :             : 
    1243                 :             : /* This is used inside loop versioning when we want to insert
    1244                 :             :    stmts/insns on the edges, which have a different behavior
    1245                 :             :    in tree's and in RTL, so we made a CFG hook.  */
    1246                 :             : void
    1247                 :       33934 : lv_flush_pending_stmts (edge e)
    1248                 :             : {
    1249                 :       33934 :   if (cfg_hooks->flush_pending_stmts)
    1250                 :       33934 :     cfg_hooks->flush_pending_stmts (e);
    1251                 :       33934 : }
    1252                 :             : 
    1253                 :             : /* Loop versioning uses the duplicate_loop_body_to_header_edge to create
    1254                 :             :    a new version of the loop basic-blocks, the parameters here are
    1255                 :             :    exactly the same as in duplicate_loop_body_to_header_edge or
    1256                 :             :    tree_duplicate_loop_body_to_header_edge; while in tree-ssa there is
    1257                 :             :    additional work to maintain ssa information that's why there is
    1258                 :             :    a need to call the tree_duplicate_loop_body_to_header_edge rather
    1259                 :             :    than duplicate_loop_body_to_header_edge when we are in tree mode.  */
    1260                 :             : bool
    1261                 :       33944 : cfg_hook_duplicate_loop_body_to_header_edge (class loop *loop, edge e,
    1262                 :             :                                              unsigned int ndupl,
    1263                 :             :                                              sbitmap wont_exit, edge orig,
    1264                 :             :                                              vec<edge> *to_remove, int flags)
    1265                 :             : {
    1266                 :       33944 :   gcc_assert (cfg_hooks->cfg_hook_duplicate_loop_body_to_header_edge);
    1267                 :       33944 :   return cfg_hooks->cfg_hook_duplicate_loop_body_to_header_edge (
    1268                 :       33944 :     loop, e, ndupl, wont_exit, orig, to_remove, flags);
    1269                 :             : }
    1270                 :             : 
    1271                 :             : /* Conditional jumps are represented differently in trees and RTL,
    1272                 :             :    this hook takes a basic block that is known to have a cond jump
    1273                 :             :    at its end and extracts the taken and not taken edges out of it
    1274                 :             :    and store it in E1 and E2 respectively.  */
    1275                 :             : void
    1276                 :           0 : extract_cond_bb_edges (basic_block b, edge *e1, edge *e2)
    1277                 :             : {
    1278                 :           0 :   gcc_assert (cfg_hooks->extract_cond_bb_edges);
    1279                 :           0 :   cfg_hooks->extract_cond_bb_edges (b, e1, e2);
    1280                 :           0 : }
    1281                 :             : 
    1282                 :             : /* Responsible for updating the ssa info (PHI nodes) on the
    1283                 :             :    new condition basic block that guards the versioned loop.  */
    1284                 :             : void
    1285                 :       33934 : lv_adjust_loop_header_phi (basic_block first, basic_block second,
    1286                 :             :                            basic_block new_block, edge e)
    1287                 :             : {
    1288                 :       33934 :   if (cfg_hooks->lv_adjust_loop_header_phi)
    1289                 :       33934 :     cfg_hooks->lv_adjust_loop_header_phi (first, second, new_block, e);
    1290                 :       33934 : }
    1291                 :             : 
    1292                 :             : /* Conditions in trees and RTL are different so we need
    1293                 :             :    a different handling when we add the condition to the
    1294                 :             :    versioning code.  */
    1295                 :             : void
    1296                 :       33934 : lv_add_condition_to_bb (basic_block first, basic_block second,
    1297                 :             :                         basic_block new_block, void *cond)
    1298                 :             : {
    1299                 :       33934 :   gcc_assert (cfg_hooks->lv_add_condition_to_bb);
    1300                 :       33934 :   cfg_hooks->lv_add_condition_to_bb (first, second, new_block, cond);
    1301                 :       33934 : }
    1302                 :             : 
    1303                 :             : /* Checks whether all N blocks in BBS array can be copied.  */
    1304                 :             : bool
    1305                 :     2846242 : can_copy_bbs_p (basic_block *bbs, unsigned n)
    1306                 :             : {
    1307                 :     2846242 :   unsigned i;
    1308                 :     2846242 :   edge e;
    1309                 :     2846242 :   int ret = true;
    1310                 :             : 
    1311                 :    10408880 :   for (i = 0; i < n; i++)
    1312                 :     7562638 :     bbs[i]->flags |= BB_DUPLICATED;
    1313                 :             : 
    1314                 :    10244329 :   for (i = 0; i < n; i++)
    1315                 :             :     {
    1316                 :             :       /* In case we should redirect abnormal edge during duplication, fail.  */
    1317                 :     7409125 :       edge_iterator ei;
    1318                 :    19661077 :       FOR_EACH_EDGE (e, ei, bbs[i]->succs)
    1319                 :    12261111 :         if ((e->flags & EDGE_ABNORMAL)
    1320                 :      118917 :             && (e->dest->flags & BB_DUPLICATED))
    1321                 :             :           {
    1322                 :        9159 :             ret = false;
    1323                 :        9159 :             goto end;
    1324                 :             :           }
    1325                 :             : 
    1326                 :     7399966 :       if (!can_duplicate_block_p (bbs[i]))
    1327                 :             :         {
    1328                 :        1879 :           ret = false;
    1329                 :        1879 :           break;
    1330                 :             :         }
    1331                 :             :     }
    1332                 :             : 
    1333                 :     2835204 : end:
    1334                 :    10408880 :   for (i = 0; i < n; i++)
    1335                 :     7562638 :     bbs[i]->flags &= ~BB_DUPLICATED;
    1336                 :             : 
    1337                 :     2846242 :   return ret;
    1338                 :             : }
    1339                 :             : 
    1340                 :             : /* Duplicates N basic blocks stored in array BBS.  Newly created basic blocks
    1341                 :             :    are placed into array NEW_BBS in the same order.  Edges from basic blocks
    1342                 :             :    in BBS are also duplicated and copies of those that lead into BBS are
    1343                 :             :    redirected to appropriate newly created block.  The function assigns bbs
    1344                 :             :    into loops (copy of basic block bb is assigned to bb->loop_father->copy
    1345                 :             :    loop, so this must be set up correctly in advance)
    1346                 :             : 
    1347                 :             :    If UPDATE_DOMINANCE is true then this function updates dominators locally
    1348                 :             :    (LOOPS structure that contains the information about dominators is passed
    1349                 :             :    to enable this), otherwise it does not update the dominator information
    1350                 :             :    and it assumed that the caller will do this, perhaps by destroying and
    1351                 :             :    recreating it instead of trying to do an incremental update like this
    1352                 :             :    function does when update_dominance is true.
    1353                 :             : 
    1354                 :             :    BASE is the superloop to that basic block belongs; if its header or latch
    1355                 :             :    is copied, we do not set the new blocks as header or latch.
    1356                 :             : 
    1357                 :             :    Created copies of N_EDGES edges in array EDGES are stored in array NEW_EDGES,
    1358                 :             :    also in the same order.
    1359                 :             : 
    1360                 :             :    Newly created basic blocks are put after the basic block AFTER in the
    1361                 :             :    instruction stream, and the order of the blocks in BBS array is preserved.  */
    1362                 :             : 
    1363                 :             : void
    1364                 :     2092728 : copy_bbs (basic_block *bbs, unsigned n, basic_block *new_bbs,
    1365                 :             :           edge *edges, unsigned num_edges, edge *new_edges,
    1366                 :             :           class loop *base, basic_block after, bool update_dominance)
    1367                 :             : {
    1368                 :     2092728 :   unsigned i, j;
    1369                 :     2092728 :   basic_block bb, new_bb, dom_bb;
    1370                 :     2092728 :   edge e;
    1371                 :     2092728 :   copy_bb_data id;
    1372                 :             : 
    1373                 :             :   /* Mark the blocks to be copied.  This is used by edge creation hooks
    1374                 :             :      to decide whether to reallocate PHI nodes capacity to avoid reallocating
    1375                 :             :      PHIs in the set of source BBs.  */
    1376                 :     5575428 :   for (i = 0; i < n; i++)
    1377                 :     3482700 :     bbs[i]->flags |= BB_DUPLICATED;
    1378                 :             : 
    1379                 :             :   /* Duplicate bbs, update dominators, assign bbs to loops.  */
    1380                 :     5575428 :   for (i = 0; i < n; i++)
    1381                 :             :     {
    1382                 :             :       /* Duplicate.  */
    1383                 :     3482700 :       bb = bbs[i];
    1384                 :     3482700 :       new_bb = new_bbs[i] = duplicate_block (bb, NULL, after, &id);
    1385                 :     3482700 :       after = new_bb;
    1386                 :     3482700 :       if (bb->loop_father)
    1387                 :             :         {
    1388                 :             :           /* Possibly set loop header.  */
    1389                 :     3482700 :           if (bb->loop_father->header == bb && bb->loop_father != base)
    1390                 :       37443 :             new_bb->loop_father->header = new_bb;
    1391                 :             :           /* Or latch.  */
    1392                 :     3482700 :           if (bb->loop_father->latch == bb && bb->loop_father != base)
    1393                 :       37443 :             new_bb->loop_father->latch = new_bb;
    1394                 :             :         }
    1395                 :             :     }
    1396                 :             : 
    1397                 :             :   /* Set dominators.  */
    1398                 :     2092728 :   if (update_dominance)
    1399                 :             :     {
    1400                 :     3062394 :       for (i = 0; i < n; i++)
    1401                 :             :         {
    1402                 :     2014684 :           bb = bbs[i];
    1403                 :     2014684 :           new_bb = new_bbs[i];
    1404                 :             : 
    1405                 :     2014684 :           dom_bb = get_immediate_dominator (CDI_DOMINATORS, bb);
    1406                 :     2014684 :           if (dom_bb->flags & BB_DUPLICATED)
    1407                 :             :             {
    1408                 :      966974 :               dom_bb = get_bb_copy (dom_bb);
    1409                 :      966974 :               set_immediate_dominator (CDI_DOMINATORS, new_bb, dom_bb);
    1410                 :             :             }
    1411                 :             :         }
    1412                 :             :     }
    1413                 :             : 
    1414                 :             :   /* Redirect edges.  */
    1415                 :     5575428 :   for (i = 0; i < n; i++)
    1416                 :             :     {
    1417                 :     3482700 :       edge_iterator ei;
    1418                 :     3482700 :       new_bb = new_bbs[i];
    1419                 :     3482700 :       bb = bbs[i];
    1420                 :             : 
    1421                 :     9618304 :       FOR_EACH_EDGE (e, ei, new_bb->succs)
    1422                 :             :         {
    1423                 :     6135604 :           if (!(e->dest->flags & BB_DUPLICATED))
    1424                 :     4131151 :             continue;
    1425                 :     2004453 :           redirect_edge_and_branch_force (e, get_bb_copy (e->dest));
    1426                 :             :         }
    1427                 :             :     }
    1428                 :     4681870 :   for (j = 0; j < num_edges; j++)
    1429                 :             :     {
    1430                 :     2589142 :       if (!edges[j])
    1431                 :       72896 :         new_edges[j] = NULL;
    1432                 :             :       else
    1433                 :             :         {
    1434                 :     2516246 :           basic_block src = edges[j]->src;
    1435                 :     2516246 :           basic_block dest = edges[j]->dest;
    1436                 :     2516246 :           if (src->flags & BB_DUPLICATED)
    1437                 :     2516246 :             src = get_bb_copy (src);
    1438                 :     2516246 :           if (dest->flags & BB_DUPLICATED)
    1439                 :      446338 :             dest = get_bb_copy (dest);
    1440                 :     2516246 :           new_edges[j] = find_edge (src, dest);
    1441                 :             :         }
    1442                 :             :     }
    1443                 :             : 
    1444                 :             :   /* Clear information about duplicates.  */
    1445                 :     5575428 :   for (i = 0; i < n; i++)
    1446                 :     3482700 :     bbs[i]->flags &= ~BB_DUPLICATED;
    1447                 :     2092728 : }
    1448                 :             : 
    1449                 :             : /* Return true if BB contains only labels or non-executable
    1450                 :             :    instructions */
    1451                 :             : bool
    1452                 :    12729069 : empty_block_p (basic_block bb)
    1453                 :             : {
    1454                 :    12729069 :   gcc_assert (cfg_hooks->empty_block_p);
    1455                 :    12729069 :   return cfg_hooks->empty_block_p (bb);
    1456                 :             : }
    1457                 :             : 
    1458                 :             : /* Split a basic block if it ends with a conditional branch and if
    1459                 :             :    the other part of the block is not empty.  */
    1460                 :             : basic_block
    1461                 :         568 : split_block_before_cond_jump (basic_block bb)
    1462                 :             : {
    1463                 :         568 :   gcc_assert (cfg_hooks->split_block_before_cond_jump);
    1464                 :         568 :   return cfg_hooks->split_block_before_cond_jump (bb);
    1465                 :             : }
    1466                 :             : 
    1467                 :             : /* Work-horse for passes.cc:check_profile_consistency.
    1468                 :             :    Do book-keeping of the CFG for the profile consistency checker.
    1469                 :             :    Store the counting in RECORD.  */
    1470                 :             : 
    1471                 :             : void
    1472                 :           0 : profile_record_check_consistency (profile_record *record)
    1473                 :             : {
    1474                 :           0 :   basic_block bb;
    1475                 :           0 :   edge_iterator ei;
    1476                 :           0 :   edge e;
    1477                 :             : 
    1478                 :           0 :   FOR_ALL_BB_FN (bb, cfun)
    1479                 :             :    {
    1480                 :           0 :       if (bb != EXIT_BLOCK_PTR_FOR_FN (cfun)
    1481                 :           0 :           && profile_status_for_fn (cfun) != PROFILE_ABSENT
    1482                 :           0 :           && EDGE_COUNT (bb->succs))
    1483                 :             :         {
    1484                 :           0 :           sreal sum = 0;
    1485                 :           0 :           bool found = false;
    1486                 :           0 :           FOR_EACH_EDGE (e, ei, bb->succs)
    1487                 :             :             {
    1488                 :           0 :               if (!(e->flags & (EDGE_EH | EDGE_FAKE)))
    1489                 :           0 :                 found = true;
    1490                 :           0 :               if (e->probability.initialized_p ())
    1491                 :           0 :                 sum += e->probability.to_sreal ();
    1492                 :             :             }
    1493                 :           0 :           double dsum = sum.to_double ();
    1494                 :           0 :           if (found && (dsum < 0.9 || dsum > 1.1)
    1495                 :           0 :               && !(bb->count == profile_count::zero ()))
    1496                 :             :             {
    1497                 :           0 :               record->num_mismatched_prob_out++;
    1498                 :           0 :               dsum = dsum > 1 ? dsum - 1 : 1 - dsum;
    1499                 :           0 :               if (profile_info)
    1500                 :             :                 {
    1501                 :           0 :                   if (ENTRY_BLOCK_PTR_FOR_FN
    1502                 :           0 :                          (cfun)->count.ipa ().initialized_p ()
    1503                 :           0 :                       && ENTRY_BLOCK_PTR_FOR_FN
    1504                 :           0 :                          (cfun)->count.ipa ().nonzero_p ()
    1505                 :           0 :                       && bb->count.ipa ().initialized_p ())
    1506                 :           0 :                     record->dyn_mismatched_prob_out
    1507                 :           0 :                         += dsum * bb->count.ipa ().to_gcov_type ();
    1508                 :             :                 }
    1509                 :           0 :               else if (bb->count.initialized_p ())
    1510                 :           0 :                 record->dyn_mismatched_prob_out
    1511                 :           0 :                     += dsum * bb->count.to_sreal_scale
    1512                 :           0 :                         (ENTRY_BLOCK_PTR_FOR_FN (cfun)->count).to_double ();
    1513                 :             :             }
    1514                 :             :         }
    1515                 :           0 :       if (bb != ENTRY_BLOCK_PTR_FOR_FN (cfun)
    1516                 :           0 :           && profile_status_for_fn (cfun) != PROFILE_ABSENT)
    1517                 :             :         {
    1518                 :           0 :           profile_count lsum = profile_count::zero ();
    1519                 :           0 :           FOR_EACH_EDGE (e, ei, bb->preds)
    1520                 :           0 :             lsum += e->count ();
    1521                 :           0 :           if (lsum.differs_from_p (bb->count))
    1522                 :             :             {
    1523                 :           0 :               record->num_mismatched_count_in++;
    1524                 :           0 :               profile_count max;
    1525                 :           0 :               if (lsum < bb->count)
    1526                 :           0 :                 max = bb->count;
    1527                 :             :               else
    1528                 :           0 :                 max = lsum;
    1529                 :           0 :               if (profile_info)
    1530                 :             :                 {
    1531                 :           0 :                   if (ENTRY_BLOCK_PTR_FOR_FN
    1532                 :           0 :                          (cfun)->count.ipa ().initialized_p ()
    1533                 :           0 :                       && ENTRY_BLOCK_PTR_FOR_FN
    1534                 :           0 :                          (cfun)->count.ipa ().nonzero_p ()
    1535                 :           0 :                       && max.ipa ().initialized_p ())
    1536                 :           0 :                     record->dyn_mismatched_count_in
    1537                 :           0 :                         += max.ipa ().to_gcov_type ();
    1538                 :             :                 }
    1539                 :           0 :               else if (bb->count.initialized_p ())
    1540                 :           0 :                 record->dyn_mismatched_prob_out
    1541                 :           0 :                     += max.to_sreal_scale
    1542                 :           0 :                         (ENTRY_BLOCK_PTR_FOR_FN (cfun)->count).to_double ();
    1543                 :             :             }
    1544                 :             :         }
    1545                 :           0 :       if (bb == ENTRY_BLOCK_PTR_FOR_FN (cfun)
    1546                 :             :           || bb == EXIT_BLOCK_PTR_FOR_FN (cfun))
    1547                 :           0 :         continue;
    1548                 :             :    }
    1549                 :           0 : }
    1550                 :             : 
    1551                 :             : /* Work-horse for passes.cc:acount_profile.
    1552                 :             :    Do book-keeping of the CFG for the profile accounting.
    1553                 :             :    Store the counting in RECORD.  */
    1554                 :             : 
    1555                 :             : void
    1556                 :           0 : profile_record_account_profile (profile_record *record)
    1557                 :             : {
    1558                 :           0 :   basic_block bb;
    1559                 :             : 
    1560                 :           0 :   FOR_ALL_BB_FN (bb, cfun)
    1561                 :             :    {
    1562                 :           0 :       gcc_assert (cfg_hooks->account_profile_record);
    1563                 :           0 :       cfg_hooks->account_profile_record (bb, record);
    1564                 :             :    }
    1565                 :           0 : }
    1566                 :             : 
    1567                 :             : #if __GNUC__ >= 10
    1568                 :             : #  pragma GCC diagnostic pop
    1569                 :             : #endif
        

Generated by: LCOV version 2.1-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.