LCOV - code coverage report
Current view: top level - gcc - tree-ssa-sink.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 100.0 % 311 311
Test Date: 2025-04-26 15:52:03 Functions: 100.0 % 13 13
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: - 0 0

             Branch data     Line data    Source code
       1                 :             : /* Code sinking for trees
       2                 :             :    Copyright (C) 2001-2025 Free Software Foundation, Inc.
       3                 :             :    Contributed by Daniel Berlin <dan@dberlin.org>
       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 "tree.h"
      26                 :             : #include "gimple.h"
      27                 :             : #include "cfghooks.h"
      28                 :             : #include "tree-pass.h"
      29                 :             : #include "ssa.h"
      30                 :             : #include "gimple-pretty-print.h"
      31                 :             : #include "fold-const.h"
      32                 :             : #include "stor-layout.h"
      33                 :             : #include "cfganal.h"
      34                 :             : #include "gimple-iterator.h"
      35                 :             : #include "tree-cfg.h"
      36                 :             : #include "cfgloop.h"
      37                 :             : #include "tree-eh.h"
      38                 :             : #include "tree-ssa-live.h"
      39                 :             : #include "tree-dfa.h"
      40                 :             : 
      41                 :             : /* TODO:
      42                 :             :    1. Sinking store only using scalar promotion (IE without moving the RHS):
      43                 :             : 
      44                 :             :    *q = p;
      45                 :             :    p = p + 1;
      46                 :             :    if (something)
      47                 :             :      *q = <not p>;
      48                 :             :    else
      49                 :             :      y = *q;
      50                 :             : 
      51                 :             : 
      52                 :             :    should become
      53                 :             :    sinktemp = p;
      54                 :             :    p = p + 1;
      55                 :             :    if (something)
      56                 :             :      *q = <not p>;
      57                 :             :    else
      58                 :             :    {
      59                 :             :      *q = sinktemp;
      60                 :             :      y = *q
      61                 :             :    }
      62                 :             :    Store copy propagation will take care of the store elimination above.
      63                 :             : 
      64                 :             : 
      65                 :             :    2. Sinking using Partial Dead Code Elimination.  */
      66                 :             : 
      67                 :             : 
      68                 :             : static struct
      69                 :             : {
      70                 :             :   /* The number of statements sunk down the flowgraph by code sinking.  */
      71                 :             :   int sunk;
      72                 :             : 
      73                 :             :   /* The number of stores commoned and sunk down by store commoning.  */
      74                 :             :   int commoned;
      75                 :             : } sink_stats;
      76                 :             : 
      77                 :             : 
      78                 :             : /* Given a PHI, and one of its arguments (DEF), find the edge for
      79                 :             :    that argument and return it.  If the argument occurs twice in the PHI node,
      80                 :             :    we return NULL.  */
      81                 :             : 
      82                 :             : static basic_block
      83                 :      635741 : find_bb_for_arg (gphi *phi, tree def)
      84                 :             : {
      85                 :      635741 :   size_t i;
      86                 :      635741 :   bool foundone = false;
      87                 :      635741 :   basic_block result = NULL;
      88                 :     1993242 :   for (i = 0; i < gimple_phi_num_args (phi); i++)
      89                 :     1371418 :     if (PHI_ARG_DEF (phi, i) == def)
      90                 :             :       {
      91                 :      649658 :         if (foundone)
      92                 :             :           return NULL;
      93                 :      635741 :         foundone = true;
      94                 :      635741 :         result = gimple_phi_arg_edge (phi, i)->src;
      95                 :             :       }
      96                 :             :   return result;
      97                 :             : }
      98                 :             : 
      99                 :             : /* When the first immediate use is in a statement, then return true if all
     100                 :             :    immediate uses in IMM are in the same statement.
     101                 :             :    We could also do the case where  the first immediate use is in a phi node,
     102                 :             :    and all the other uses are in phis in the same basic block, but this
     103                 :             :    requires some expensive checking later (you have to make sure no def/vdef
     104                 :             :    in the statement occurs for multiple edges in the various phi nodes it's
     105                 :             :    used in, so that you only have one place you can sink it to.  */
     106                 :             : 
     107                 :             : static bool
     108                 :    12720868 : all_immediate_uses_same_place (def_operand_p def_p)
     109                 :             : {
     110                 :    12720868 :   tree var = DEF_FROM_PTR (def_p);
     111                 :    12720868 :   imm_use_iterator imm_iter;
     112                 :    12720868 :   use_operand_p use_p;
     113                 :             : 
     114                 :    12720868 :   gimple *firstuse = NULL;
     115                 :    27112975 :   FOR_EACH_IMM_USE_FAST (use_p, imm_iter, var)
     116                 :             :     {
     117                 :    17989262 :       if (is_gimple_debug (USE_STMT (use_p)))
     118                 :     1574525 :         continue;
     119                 :    16414737 :       if (firstuse == NULL)
     120                 :             :         firstuse = USE_STMT (use_p);
     121                 :             :       else
     122                 :     3693869 :         if (firstuse != USE_STMT (use_p))
     123                 :             :           return false;
     124                 :             :     }
     125                 :             : 
     126                 :             :   return true;
     127                 :             : }
     128                 :             : 
     129                 :             : /* Find the nearest common dominator of all of the immediate uses in IMM.  */
     130                 :             : 
     131                 :             : static basic_block
     132                 :    12115611 : nearest_common_dominator_of_uses (def_operand_p def_p, bool *debug_stmts)
     133                 :             : {
     134                 :    12115611 :   tree var = DEF_FROM_PTR (def_p);
     135                 :    12115611 :   auto_bitmap blocks;
     136                 :    12115611 :   basic_block commondom;
     137                 :    12115611 :   unsigned int j;
     138                 :    12115611 :   bitmap_iterator bi;
     139                 :    12115611 :   imm_use_iterator imm_iter;
     140                 :    12115611 :   use_operand_p use_p;
     141                 :             : 
     142                 :    41906717 :   FOR_EACH_IMM_USE_FAST (use_p, imm_iter, var)
     143                 :             :     {
     144                 :    29791106 :       gimple *usestmt = USE_STMT (use_p);
     145                 :    29791106 :       basic_block useblock;
     146                 :             : 
     147                 :    29791106 :       if (gphi *phi = dyn_cast <gphi *> (usestmt))
     148                 :             :         {
     149                 :     3572434 :           int idx = PHI_ARG_INDEX_FROM_USE (use_p);
     150                 :             : 
     151                 :     3572434 :           useblock = gimple_phi_arg_edge (phi, idx)->src;
     152                 :             :         }
     153                 :    26218672 :       else if (is_gimple_debug (usestmt))
     154                 :             :         {
     155                 :     6033309 :           *debug_stmts = true;
     156                 :     6033309 :           continue;
     157                 :             :         }
     158                 :             :       else
     159                 :             :         {
     160                 :    20185363 :           useblock = gimple_bb (usestmt);
     161                 :             :         }
     162                 :             : 
     163                 :             :       /* Short circuit. Nothing dominates the entry block.  */
     164                 :    23757797 :       if (useblock == ENTRY_BLOCK_PTR_FOR_FN (cfun))
     165                 :             :         return NULL;
     166                 :             : 
     167                 :    23757797 :       bitmap_set_bit (blocks, useblock->index);
     168                 :             :     }
     169                 :    12115611 :   commondom = BASIC_BLOCK_FOR_FN (cfun, bitmap_first_set_bit (blocks));
     170                 :    33065843 :   EXECUTE_IF_SET_IN_BITMAP (blocks, 0, j, bi)
     171                 :    20950232 :     commondom = nearest_common_dominator (CDI_DOMINATORS, commondom,
     172                 :    20950232 :                                           BASIC_BLOCK_FOR_FN (cfun, j));
     173                 :             :   return commondom;
     174                 :    12115611 : }
     175                 :             : 
     176                 :             : /* Return whether sinking STMT from EARLY_BB to BEST_BB should be avoided.  */
     177                 :             : 
     178                 :             : static bool
     179                 :     4217260 : do_not_sink (gimple *stmt, basic_block early_bb, basic_block best_bb)
     180                 :             : {
     181                 :             :   /* Placing a statement before a setjmp-like function would be invalid
     182                 :             :      (it cannot be reevaluated when execution follows an abnormal edge).
     183                 :             :      If we selected a block with abnormal predecessors, just punt.  */
     184                 :     4217260 :   if (bb_has_abnormal_pred (best_bb))
     185                 :             :     return true;
     186                 :             : 
     187                 :             :   /* If the latch block is empty, don't make it non-empty by sinking
     188                 :             :      something into it.  */
     189                 :     4217178 :   if (best_bb == early_bb->loop_father->latch
     190                 :     4217178 :       && empty_block_p (best_bb))
     191                 :             :     return true;
     192                 :             : 
     193                 :             :   /* Avoid turning an unconditional read into a conditional one when we
     194                 :             :      still might want to perform vectorization.  */
     195                 :     3957017 :   if (best_bb->loop_father == early_bb->loop_father
     196                 :     2820638 :       && loop_outer (best_bb->loop_father)
     197                 :      746938 :       && !best_bb->loop_father->inner
     198                 :      439871 :       && gimple_vuse (stmt)
     199                 :      161523 :       && !gimple_vdef (stmt)
     200                 :      160756 :       && flag_tree_loop_vectorize
     201                 :      153054 :       && !(cfun->curr_properties & PROP_loop_opts_done)
     202                 :      110637 :       && dominated_by_p (CDI_DOMINATORS, best_bb->loop_father->latch, early_bb)
     203                 :     4041964 :       && !dominated_by_p (CDI_DOMINATORS, best_bb->loop_father->latch, best_bb))
     204                 :             :     return true;
     205                 :             : 
     206                 :             :   return false;
     207                 :             : }
     208                 :             : 
     209                 :             : /* Given EARLY_BB and LATE_BB, two blocks in a path through the dominator
     210                 :             :    tree, return the best basic block between them (inclusive) to place
     211                 :             :    statements.
     212                 :             : 
     213                 :             :    We want the most control dependent block in the shallowest loop nest.
     214                 :             : 
     215                 :             :    If the resulting block is in a shallower loop nest, then use it.  */
     216                 :             : 
     217                 :             : static basic_block
     218                 :     9822849 : select_best_block (basic_block early_bb,
     219                 :             :                    basic_block late_bb,
     220                 :             :                    gimple *stmt)
     221                 :             : {
     222                 :             :   /* First pick a block we do not disqualify.  */
     223                 :     9822849 :   while (late_bb != early_bb
     224                 :    10103545 :          && do_not_sink (stmt, early_bb, late_bb))
     225                 :      280696 :     late_bb = get_immediate_dominator (CDI_DOMINATORS, late_bb);
     226                 :             : 
     227                 :     9822849 :   basic_block best_bb = late_bb;
     228                 :     9822849 :   basic_block temp_bb = late_bb;
     229                 :     9822849 :   while (temp_bb != early_bb)
     230                 :             :     {
     231                 :             :       /* Walk up the dominator tree, hopefully we'll find a shallower
     232                 :             :          loop nest.  */
     233                 :     3080710 :       temp_bb = get_immediate_dominator (CDI_DOMINATORS, temp_bb);
     234                 :             : 
     235                 :             :       /* Do not consider blocks we do not want to sink to.  */
     236                 :     3080710 :       if (temp_bb != early_bb && do_not_sink (stmt, early_bb, temp_bb))
     237                 :             :         ;
     238                 :             : 
     239                 :             :       /* If we've moved into a lower loop nest, then that becomes
     240                 :             :          our best block.  */
     241                 :     3080451 :       else if (bb_loop_depth (temp_bb) < bb_loop_depth (best_bb))
     242                 :             :         best_bb = temp_bb;
     243                 :             : 
     244                 :             :       /* A higher loop nest is always worse.  */
     245                 :     2558410 :       else if (bb_loop_depth (temp_bb) > bb_loop_depth (best_bb))
     246                 :             :         ;
     247                 :             : 
     248                 :             :       /* But sink the least distance, if the new candidate on the same
     249                 :             :          loop depth is post-dominated by the current best block pick
     250                 :             :          the new candidate.  */
     251                 :     2300466 :       else if (dominated_by_p (CDI_POST_DOMINATORS, temp_bb, best_bb))
     252                 :             :         best_bb = temp_bb;
     253                 :             : 
     254                 :             :       /* Avoid sinking across a conditional branching to exceptional
     255                 :             :          code.  In practice this does not reduce the number of dynamic
     256                 :             :          executions of the sunk statement (this includes EH and
     257                 :             :          branches leading to abort for example).  Treat this case as
     258                 :             :          post-dominating.  */
     259                 :    14597955 :       else if (single_pred_p (best_bb)
     260                 :     1479638 :                && single_pred_edge (best_bb)->src == temp_bb
     261                 :     2685053 :                && (single_pred_edge (best_bb)->flags & EDGE_FALLTHRU
     262                 :             :                    || (single_pred_edge (best_bb)->probability
     263                 :    13844387 :                        >= profile_probability::always ())))
     264                 :             :         best_bb = temp_bb;
     265                 :             :     }
     266                 :             : 
     267                 :     9822849 :   gcc_checking_assert (best_bb == early_bb
     268                 :             :                        || (!do_not_sink (stmt, early_bb, best_bb)
     269                 :             :                            && ((bb_loop_depth (best_bb)
     270                 :             :                                 < bb_loop_depth (early_bb))
     271                 :             :                                || !dominated_by_p (CDI_POST_DOMINATORS,
     272                 :             :                                                    early_bb, best_bb))));
     273                 :             : 
     274                 :     9822849 :   return best_bb;
     275                 :             : }
     276                 :             : 
     277                 :             : /* Given a statement (STMT) and the basic block it is currently in (FROMBB),
     278                 :             :    determine the location to sink the statement to, if any.
     279                 :             :    Returns true if there is such location; in that case, TOGSI points to the
     280                 :             :    statement before that STMT should be moved.  */
     281                 :             : 
     282                 :             : static bool
     283                 :   111191191 : statement_sink_location (gimple *stmt, basic_block frombb,
     284                 :             :                          gimple_stmt_iterator *togsi, bool *zero_uses_p,
     285                 :             :                          virtual_operand_live &vop_live)
     286                 :             : {
     287                 :   111191191 :   gimple *use;
     288                 :   111191191 :   use_operand_p one_use = NULL_USE_OPERAND_P;
     289                 :   111191191 :   basic_block sinkbb;
     290                 :   111191191 :   use_operand_p use_p;
     291                 :   111191191 :   def_operand_p def_p;
     292                 :   111191191 :   ssa_op_iter iter;
     293                 :   111191191 :   imm_use_iterator imm_iter;
     294                 :             : 
     295                 :   111191191 :   *zero_uses_p = false;
     296                 :             : 
     297                 :             :   /* We only can sink assignments and const/pure calls that are guaranteed
     298                 :             :      to return exactly once.  */
     299                 :   111191191 :   int cf;
     300                 :   111191191 :   if (!is_gimple_assign (stmt)
     301                 :   111191191 :       && (!is_gimple_call (stmt)
     302                 :     5254575 :           || !((cf = gimple_call_flags (stmt)) & (ECF_CONST|ECF_PURE))
     303                 :     1030058 :           || (cf & (ECF_LOOPING_CONST_OR_PURE|ECF_RETURNS_TWICE))))
     304                 :    79497601 :     return false;
     305                 :             : 
     306                 :             :   /* We only can sink stmts with a single definition.  */
     307                 :    31693590 :   def_p = single_ssa_def_operand (stmt, SSA_OP_ALL_DEFS);
     308                 :    31693590 :   if (def_p == NULL_DEF_OPERAND_P)
     309                 :             :     return false;
     310                 :             : 
     311                 :             :   /* There are a few classes of things we can't or don't move, some because we
     312                 :             :      don't have code to handle it, some because it's not profitable and some
     313                 :             :      because it's not legal.
     314                 :             : 
     315                 :             :      We can't sink things that may be global stores, at least not without
     316                 :             :      calculating a lot more information, because we may cause it to no longer
     317                 :             :      be seen by an external routine that needs it depending on where it gets
     318                 :             :      moved to.
     319                 :             : 
     320                 :             :      We can't sink statements that end basic blocks without splitting the
     321                 :             :      incoming edge for the sink location to place it there.
     322                 :             : 
     323                 :             :      We can't sink statements that have volatile operands.
     324                 :             : 
     325                 :             :      We don't want to sink dead code, so anything with 0 immediate uses is not
     326                 :             :      sunk.
     327                 :             : 
     328                 :             :      Don't sink BLKmode assignments if current function has any local explicit
     329                 :             :      register variables, as BLKmode assignments may involve memcpy or memset
     330                 :             :      calls or, on some targets, inline expansion thereof that sometimes need
     331                 :             :      to use specific hard registers.
     332                 :             : 
     333                 :             :   */
     334                 :    31693534 :   if (stmt_ends_bb_p (stmt)
     335                 :    31460397 :       || gimple_has_side_effects (stmt)
     336                 :    60844797 :       || (cfun->has_local_explicit_reg_vars
     337                 :        1617 :           && TYPE_MODE (TREE_TYPE (gimple_get_lhs (stmt))) == BLKmode))
     338                 :     2542271 :     return false;
     339                 :             : 
     340                 :             :   /* Return if there are no immediate uses of this stmt.  */
     341                 :    29151263 :   if (has_zero_uses (DEF_FROM_PTR (def_p)))
     342                 :             :     {
     343                 :       99940 :       *zero_uses_p = true;
     344                 :       99940 :       return false;
     345                 :             :     }
     346                 :             : 
     347                 :    29051323 :   if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (DEF_FROM_PTR (def_p)))
     348                 :             :     return false;
     349                 :             : 
     350                 :    71299671 :   FOR_EACH_SSA_USE_OPERAND (use_p, stmt, iter, SSA_OP_ALL_USES)
     351                 :             :     {
     352                 :    42250398 :       tree use = USE_FROM_PTR (use_p);
     353                 :    42250398 :       if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (use))
     354                 :             :         return false;
     355                 :             :     }
     356                 :             : 
     357                 :    29049273 :   use = NULL;
     358                 :             : 
     359                 :             :   /* If stmt is a store the one and only use needs to be the VOP
     360                 :             :      merging PHI node.  */
     361                 :    29049273 :   if (virtual_operand_p (DEF_FROM_PTR (def_p)))
     362                 :             :     {
     363                 :     8554796 :       FOR_EACH_IMM_USE_FAST (use_p, imm_iter, DEF_FROM_PTR (def_p))
     364                 :             :         {
     365                 :     8473811 :           gimple *use_stmt = USE_STMT (use_p);
     366                 :             : 
     367                 :             :           /* A killing definition is not a use.  */
     368                 :     8473811 :           if ((gimple_has_lhs (use_stmt)
     369                 :     6663605 :                && operand_equal_p (gimple_get_lhs (stmt),
     370                 :     6663605 :                                    gimple_get_lhs (use_stmt), 0))
     371                 :     9195849 :               || stmt_kills_ref_p (use_stmt, gimple_get_lhs (stmt)))
     372                 :             :             {
     373                 :             :               /* If use_stmt is or might be a nop assignment then USE_STMT
     374                 :             :                  acts as a use as well as definition.  */
     375                 :       27291 :               if (stmt != use_stmt
     376                 :       27291 :                   && ref_maybe_used_by_stmt_p (use_stmt,
     377                 :             :                                                gimple_get_lhs (stmt)))
     378                 :             :                 return false;
     379                 :       26784 :               continue;
     380                 :             :             }
     381                 :             : 
     382                 :     8446520 :           if (gimple_code (use_stmt) != GIMPLE_PHI)
     383                 :             :             return false;
     384                 :             : 
     385                 :     1057355 :           if (use
     386                 :     1057355 :               && use != use_stmt)
     387                 :             :             return false;
     388                 :             : 
     389                 :             :           use = use_stmt;
     390                 :             :         }
     391                 :       80985 :       if (!use)
     392                 :             :         return false;
     393                 :             :     }
     394                 :             :   /* If all the immediate uses are not in the same place, find the nearest
     395                 :             :      common dominator of all the immediate uses.  For PHI nodes, we have to
     396                 :             :      find the nearest common dominator of all of the predecessor blocks, since
     397                 :             :      that is where insertion would have to take place.  */
     398                 :    21239324 :   else if (gimple_vuse (stmt)
     399                 :    21239324 :            || !all_immediate_uses_same_place (def_p))
     400                 :             :     {
     401                 :    12115611 :       bool debug_stmts = false;
     402                 :    12115611 :       basic_block commondom = nearest_common_dominator_of_uses (def_p,
     403                 :             :                                                                 &debug_stmts);
     404                 :             : 
     405                 :    12115611 :       if (commondom == frombb)
     406                 :             :         return false;
     407                 :             : 
     408                 :             :       /* If this is a load then do not sink past any stores.  */
     409                 :     2042230 :       if (gimple_vuse (stmt))
     410                 :             :         {
     411                 :             :           /* Do not sink loads from hard registers.  */
     412                 :      795276 :           if (gimple_assign_single_p (stmt)
     413                 :      791235 :               && VAR_P (gimple_assign_rhs1 (stmt))
     414                 :      817278 :               && DECL_HARD_REGISTER (gimple_assign_rhs1 (stmt)))
     415                 :             :             return false;
     416                 :             : 
     417                 :             :           /* When the live virtual operand at the intended sink location is
     418                 :             :              not the same as the one from the load walk up the dominator tree
     419                 :             :              for a new candidate location.  */
     420                 :             :           while (commondom != frombb
     421                 :     3481990 :                  && vop_live.get_live_in (commondom) != gimple_vuse (stmt))
     422                 :     1137203 :             commondom = get_immediate_dominator (CDI_DOMINATORS, commondom);
     423                 :      795272 :           if (commondom == frombb)
     424                 :             :             return false;
     425                 :             :         }
     426                 :             : 
     427                 :             :       /* Our common dominator has to be dominated by frombb in order to be a
     428                 :             :          trivially safe place to put this statement, since it has multiple
     429                 :             :          uses.  */
     430                 :      638151 :       if (!dominated_by_p (CDI_DOMINATORS, commondom, frombb))
     431                 :             :         return false;
     432                 :             : 
     433                 :      638151 :       commondom = select_best_block (frombb, commondom, stmt);
     434                 :             : 
     435                 :      638151 :       if (commondom == frombb)
     436                 :             :         return false;
     437                 :             : 
     438                 :      390458 :       *togsi = gsi_after_labels (commondom);
     439                 :             : 
     440                 :      390458 :       return true;
     441                 :             :     }
     442                 :             :   else
     443                 :             :     {
     444                 :     9407655 :       FOR_EACH_IMM_USE_FAST (one_use, imm_iter, DEF_FROM_PTR (def_p))
     445                 :             :         {
     446                 :     9407655 :           if (is_gimple_debug (USE_STMT (one_use)))
     447                 :      283942 :             continue;
     448                 :             :           break;
     449                 :             :         }
     450                 :     9123713 :       use = USE_STMT (one_use);
     451                 :             : 
     452                 :     9123713 :       if (gimple_code (use) != GIMPLE_PHI)
     453                 :             :         {
     454                 :     8562874 :           sinkbb = select_best_block (frombb, gimple_bb (use), stmt);
     455                 :             : 
     456                 :     8562874 :           if (sinkbb == frombb)
     457                 :             :             return false;
     458                 :             : 
     459                 :      365626 :           *togsi = gsi_after_labels (sinkbb);
     460                 :             : 
     461                 :      365626 :           return true;
     462                 :             :         }
     463                 :             :     }
     464                 :             : 
     465                 :      635741 :   sinkbb = find_bb_for_arg (as_a <gphi *> (use), DEF_FROM_PTR (def_p));
     466                 :             : 
     467                 :             :   /* This can happen if there are multiple uses in a PHI.  */
     468                 :      635741 :   if (!sinkbb)
     469                 :             :     return false;
     470                 :             : 
     471                 :      621824 :   basic_block bestbb = select_best_block (frombb, sinkbb, stmt);
     472                 :      621824 :   if (bestbb == frombb
     473                 :             :       /* When we sink a store make sure there's not a path to any of
     474                 :             :          the possibly skipped killing defs as that wrecks the virtual
     475                 :             :          operand update, requiring inserting of a PHI node.  */
     476                 :      721594 :       || (gimple_vdef (stmt)
     477                 :        2530 :           && bestbb != sinkbb
     478                 :          16 :           && !dominated_by_p (CDI_POST_DOMINATORS, bestbb, sinkbb)))
     479                 :      522069 :     return false;
     480                 :             : 
     481                 :       99755 :   *togsi = gsi_after_labels (bestbb);
     482                 :             : 
     483                 :       99755 :   return true;
     484                 :             : }
     485                 :             : 
     486                 :             : /* Very simplistic code to sink common stores from the predecessor through
     487                 :             :    our virtual PHI.  We do this before sinking stmts from BB as it might
     488                 :             :    expose sinking opportunities of the merged stores.
     489                 :             :    Once we have partial dead code elimination through sth like SSU-PRE this
     490                 :             :    should be moved there.  */
     491                 :             : 
     492                 :             : static unsigned
     493                 :    31863222 : sink_common_stores_to_bb (basic_block bb)
     494                 :             : {
     495                 :    31863222 :   unsigned todo = 0;
     496                 :    31863222 :   gphi *phi;
     497                 :             : 
     498                 :    31863222 :   if (EDGE_COUNT (bb->preds) > 1
     499                 :    29823637 :       && (phi = get_virtual_phi (bb)))
     500                 :             :     {
     501                 :             :       /* Repeat until no more common stores are found.  */
     502                 :     3905649 :       while (1)
     503                 :             :         {
     504                 :     3812670 :           gimple *first_store = NULL;
     505                 :     3812670 :           auto_vec <tree, 5> vdefs;
     506                 :     3812670 :           gimple_stmt_iterator gsi;
     507                 :             : 
     508                 :             :           /* Search for common stores defined by all virtual PHI args.
     509                 :             :              ???  Common stores not present in all predecessors could
     510                 :             :              be handled by inserting a forwarder to sink to.  Generally
     511                 :             :              this involves deciding which stores to do this for if
     512                 :             :              multiple common stores are present for different sets of
     513                 :             :              predecessors.  See PR11832 for an interesting case.  */
     514                 :     4691990 :           for (unsigned i = 0; i < gimple_phi_num_args (phi); ++i)
     515                 :             :             {
     516                 :     4598032 :               tree arg = gimple_phi_arg_def (phi, i);
     517                 :     4598032 :               gimple *def = SSA_NAME_DEF_STMT (arg);
     518                 :     4598032 :               if (! is_gimple_assign (def)
     519                 :     1958233 :                   || stmt_can_throw_internal (cfun, def)
     520                 :     1927884 :                   || (gimple_phi_arg_edge (phi, i)->flags & EDGE_ABNORMAL)
     521                 :     6525914 :                   || stmt_references_abnormal_ssa_name (def))
     522                 :             :                 {
     523                 :             :                   /* ???  We could handle some cascading with the def being
     524                 :             :                      another PHI.  We'd have to insert multiple PHIs for
     525                 :             :                      the rhs then though (if they are not all equal).  */
     526                 :             :                   first_store = NULL;
     527                 :     3718712 :                   break;
     528                 :             :                 }
     529                 :             :               /* ???  Do not try to do anything fancy with aliasing, thus
     530                 :             :                  do not sink across non-aliased loads (or even stores,
     531                 :             :                  so different store order will make the sinking fail).  */
     532                 :     1927867 :               bool all_uses_on_phi = true;
     533                 :     1927867 :               imm_use_iterator iter;
     534                 :     1927867 :               use_operand_p use_p;
     535                 :     3429677 :               FOR_EACH_IMM_USE_FAST (use_p, iter, arg)
     536                 :     2470359 :                 if (USE_STMT (use_p) != phi)
     537                 :             :                   {
     538                 :             :                     all_uses_on_phi = false;
     539                 :             :                     break;
     540                 :             :                   }
     541                 :     1927867 :               if (! all_uses_on_phi)
     542                 :             :                 {
     543                 :             :                   first_store = NULL;
     544                 :             :                   break;
     545                 :             :                 }
     546                 :             :               /* Check all stores are to the same LHS.  */
     547                 :      959318 :               if (! first_store)
     548                 :             :                 first_store = def;
     549                 :             :               /* ??? We could handle differing SSA uses in the LHS by inserting
     550                 :             :                  PHIs for them.  */
     551                 :      279937 :               else if (! operand_equal_p (gimple_assign_lhs (first_store),
     552                 :      279937 :                                           gimple_assign_lhs (def), 0)
     553                 :      479876 :                        || (gimple_clobber_p (first_store)
     554                 :      199939 :                            != gimple_clobber_p (def)))
     555                 :             :                 {
     556                 :             :                   first_store = NULL;
     557                 :             :                   break;
     558                 :             :                 }
     559                 :      879320 :               vdefs.safe_push (arg);
     560                 :             :             }
     561                 :     3812670 :           if (! first_store)
     562                 :             :             break;
     563                 :             : 
     564                 :             :           /* Check if we need a PHI node to merge the stored values.  */
     565                 :       93958 :           bool allsame = true;
     566                 :       93958 :           if (!gimple_clobber_p (first_store))
     567                 :      109861 :             for (unsigned i = 1; i < vdefs.length (); ++i)
     568                 :             :               {
     569                 :      101777 :                 gimple *def = SSA_NAME_DEF_STMT (vdefs[i]);
     570                 :      101777 :                 if (! operand_equal_p (gimple_assign_rhs1 (first_store),
     571                 :      101777 :                                        gimple_assign_rhs1 (def), 0))
     572                 :             :                   {
     573                 :             :                     allsame = false;
     574                 :             :                     break;
     575                 :             :                   }
     576                 :             :               }
     577                 :             : 
     578                 :             :           /* We cannot handle aggregate values if we need to merge them.  */
     579                 :       93958 :           tree type = TREE_TYPE (gimple_assign_lhs (first_store));
     580                 :       93958 :           if (! allsame
     581                 :       93958 :               && ! is_gimple_reg_type (type))
     582                 :             :             break;
     583                 :             : 
     584                 :       92979 :           if (dump_enabled_p ())
     585                 :             :             {
     586                 :           8 :               dump_printf_loc (MSG_OPTIMIZED_LOCATIONS,
     587                 :             :                                first_store,
     588                 :             :                                "sinking common stores %sto ",
     589                 :             :                                allsame ? "with same value " : "");
     590                 :           5 :               dump_generic_expr (MSG_OPTIMIZED_LOCATIONS, TDF_SLIM,
     591                 :             :                                  gimple_assign_lhs (first_store));
     592                 :           5 :               dump_printf (MSG_OPTIMIZED_LOCATIONS, "\n");
     593                 :             :             }
     594                 :             : 
     595                 :             :           /* Insert a PHI to merge differing stored values if necessary.
     596                 :             :              Note that in general inserting PHIs isn't a very good idea as
     597                 :             :              it makes the job of coalescing and register allocation harder.
     598                 :             :              Even common SSA uses on the rhs/lhs might extend their lifetime
     599                 :             :              across multiple edges by this code motion which makes
     600                 :             :              register allocation harder.  */
     601                 :       92979 :           tree from;
     602                 :       92979 :           if (! allsame)
     603                 :             :             {
     604                 :       72357 :               from = make_ssa_name (type);
     605                 :       72357 :               gphi *newphi = create_phi_node (from, bb);
     606                 :      289807 :               for (unsigned i = 0; i < vdefs.length (); ++i)
     607                 :             :                 {
     608                 :      217450 :                   gimple *def = SSA_NAME_DEF_STMT (vdefs[i]);
     609                 :      217450 :                   add_phi_arg (newphi, gimple_assign_rhs1 (def),
     610                 :      217450 :                                EDGE_PRED (bb, i), UNKNOWN_LOCATION);
     611                 :             :                 }
     612                 :             :             }
     613                 :             :           else
     614                 :       20622 :             from = gimple_assign_rhs1 (first_store);
     615                 :             : 
     616                 :             :           /* Remove all stores.  */
     617                 :      730074 :           for (unsigned i = 0; i < vdefs.length (); ++i)
     618                 :      272058 :             TREE_VISITED (vdefs[i]) = 1;
     619                 :      365037 :           for (unsigned i = 0; i < vdefs.length (); ++i)
     620                 :             :             /* If we have more than one use of a VDEF on the PHI make sure
     621                 :             :                we remove the defining stmt only once.  */
     622                 :      272058 :             if (TREE_VISITED (vdefs[i]))
     623                 :             :               {
     624                 :      265820 :                 TREE_VISITED (vdefs[i]) = 0;
     625                 :      265820 :                 gimple *def = SSA_NAME_DEF_STMT (vdefs[i]);
     626                 :      265820 :                 gsi = gsi_for_stmt (def);
     627                 :      265820 :                 unlink_stmt_vdef (def);
     628                 :      265820 :                 gsi_remove (&gsi, true);
     629                 :      265820 :                 release_defs (def);
     630                 :             :               }
     631                 :             : 
     632                 :             :           /* Insert the first store at the beginning of the merge BB.  */
     633                 :       92979 :           gimple_set_vdef (first_store, gimple_phi_result (phi));
     634                 :      185958 :           SSA_NAME_DEF_STMT (gimple_vdef (first_store)) = first_store;
     635                 :       92979 :           gimple_phi_set_result (phi, make_ssa_name (gimple_vop (cfun)));
     636                 :       92979 :           gimple_set_vuse (first_store, gimple_phi_result (phi));
     637                 :       92979 :           gimple_assign_set_rhs1 (first_store, from);
     638                 :             :           /* ???  Should we reset first_stores location?  */
     639                 :       92979 :           gsi = gsi_after_labels (bb);
     640                 :       92979 :           gsi_insert_before (&gsi, first_store, GSI_SAME_STMT);
     641                 :       92979 :           sink_stats.commoned++;
     642                 :             : 
     643                 :       92979 :           todo |= TODO_cleanup_cfg;
     644                 :     3812670 :         }
     645                 :             : 
     646                 :             :       /* We could now have empty predecessors that we could remove,
     647                 :             :          forming a proper CFG for further sinking.  Note that even
     648                 :             :          CFG cleanup doesn't do this fully at the moment and it
     649                 :             :          doesn't preserve post-dominators in the process either.
     650                 :             :          The mergephi pass might do it though.  gcc.dg/tree-ssa/ssa-sink-13.c
     651                 :             :          shows this nicely if you disable tail merging or (same effect)
     652                 :             :          make the stored values unequal.  */
     653                 :             :     }
     654                 :             : 
     655                 :    31863222 :   return todo;
     656                 :             : }
     657                 :             : 
     658                 :             : /* Perform code sinking on BB */
     659                 :             : 
     660                 :             : static unsigned
     661                 :    31863222 : sink_code_in_bb (basic_block bb, virtual_operand_live &vop_live)
     662                 :             : {
     663                 :    31863222 :   gimple_stmt_iterator gsi;
     664                 :    31863222 :   edge_iterator ei;
     665                 :    31863222 :   edge e;
     666                 :    31863222 :   bool last = true;
     667                 :    31863222 :   unsigned todo = 0;
     668                 :             : 
     669                 :             :   /* Sink common stores from the predecessor through our virtual PHI.  */
     670                 :    31863222 :   todo |= sink_common_stores_to_bb (bb);
     671                 :             : 
     672                 :             :   /* If this block doesn't dominate anything, there can't be any place to sink
     673                 :             :      the statements to.  */
     674                 :    31863222 :   if (first_dom_son (CDI_DOMINATORS, bb) == NULL)
     675                 :             :     return todo;
     676                 :             : 
     677                 :             :   /* We can't move things across abnormal edges, so don't try.  */
     678                 :    37437006 :   FOR_EACH_EDGE (e, ei, bb->succs)
     679                 :    23756204 :     if (e->flags & EDGE_ABNORMAL)
     680                 :             :       return todo;
     681                 :             : 
     682                 :   138552795 :   for (gsi = gsi_last_bb (bb); !gsi_end_p (gsi);)
     683                 :             :     {
     684                 :   111191191 :       gimple *stmt = gsi_stmt (gsi);
     685                 :   111191191 :       gimple_stmt_iterator togsi;
     686                 :   111191191 :       bool zero_uses_p;
     687                 :             : 
     688                 :   111191191 :       if (!statement_sink_location (stmt, bb, &togsi, &zero_uses_p, vop_live))
     689                 :             :         {
     690                 :   110335352 :           gimple_stmt_iterator saved = gsi;
     691                 :   110335352 :           if (!gsi_end_p (gsi))
     692                 :   110335352 :             gsi_prev (&gsi);
     693                 :             :           /* If we face a dead stmt remove it as it possibly blocks
     694                 :             :              sinking of uses.  */
     695                 :   110335352 :           if (zero_uses_p
     696                 :       99940 :               && !gimple_vdef (stmt)
     697                 :   110431509 :               && (cfun->can_delete_dead_exceptions
     698                 :       76039 :                   || !stmt_could_throw_p (cfun, stmt)))
     699                 :             :             {
     700                 :       48100 :               gsi_remove (&saved, true);
     701                 :       48100 :               release_defs (stmt);
     702                 :             :             }
     703                 :             :           else
     704                 :             :             last = false;
     705                 :   110335352 :           continue;
     706                 :   110335352 :         }
     707                 :      855839 :       if (dump_file)
     708                 :             :         {
     709                 :          39 :           fprintf (dump_file, "Sinking ");
     710                 :          39 :           print_gimple_stmt (dump_file, stmt, 0, TDF_VOPS);
     711                 :          39 :           fprintf (dump_file, " from bb %d to bb %d\n",
     712                 :          39 :                    bb->index, (gsi_bb (togsi))->index);
     713                 :             :         }
     714                 :             : 
     715                 :             :       /* Update virtual operands of statements in the path we
     716                 :             :          do not sink to.  */
     717                 :     1711678 :       if (gimple_vdef (stmt))
     718                 :             :         {
     719                 :        2515 :           imm_use_iterator iter;
     720                 :        2515 :           use_operand_p use_p;
     721                 :        2515 :           gimple *vuse_stmt;
     722                 :             : 
     723                 :        7847 :           FOR_EACH_IMM_USE_STMT (vuse_stmt, iter, gimple_vdef (stmt))
     724                 :        5332 :             if (gimple_code (vuse_stmt) != GIMPLE_PHI
     725                 :        5332 :                 && !dominated_by_p (CDI_DOMINATORS, gimple_bb (vuse_stmt),
     726                 :        2817 :                                     gsi_bb (togsi)))
     727                 :        8451 :               FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
     728                 :        8149 :                 SET_USE (use_p, gimple_vuse (stmt));
     729                 :             :         }
     730                 :             : 
     731                 :             :       /* If this is the end of the basic block, we need to insert at the end
     732                 :             :          of the basic block.  */
     733                 :      855839 :       if (gsi_end_p (togsi))
     734                 :      123067 :         gsi_move_to_bb_end (&gsi, gsi_bb (togsi));
     735                 :             :       else
     736                 :      732772 :         gsi_move_before (&gsi, &togsi);
     737                 :             : 
     738                 :      855839 :       sink_stats.sunk++;
     739                 :             : 
     740                 :             :       /* If we've just removed the last statement of the BB, the
     741                 :             :          gsi_end_p() test below would fail, but gsi_prev() would have
     742                 :             :          succeeded, and we want it to succeed.  So we keep track of
     743                 :             :          whether we're at the last statement and pick up the new last
     744                 :             :          statement.  */
     745                 :      855839 :       if (last)
     746                 :             :         {
     747                 :       11241 :           gsi = gsi_last_bb (bb);
     748                 :       11241 :           continue;
     749                 :             :         }
     750                 :             : 
     751                 :      844598 :       last = false;
     752                 :      844598 :       if (!gsi_end_p (gsi))
     753                 :     1689196 :         gsi_prev (&gsi);
     754                 :             : 
     755                 :             :     }
     756                 :             : 
     757                 :             :   return todo;
     758                 :             : }
     759                 :             : 
     760                 :             : /* Perform code sinking.
     761                 :             :    This moves code down the flowgraph when we know it would be
     762                 :             :    profitable to do so, or it wouldn't increase the number of
     763                 :             :    executions of the statement.
     764                 :             : 
     765                 :             :    IE given
     766                 :             : 
     767                 :             :    a_1 = b + c;
     768                 :             :    if (<something>)
     769                 :             :    {
     770                 :             :    }
     771                 :             :    else
     772                 :             :    {
     773                 :             :      foo (&b, &c);
     774                 :             :      a_5 = b + c;
     775                 :             :    }
     776                 :             :    a_6 = PHI (a_5, a_1);
     777                 :             :    USE a_6.
     778                 :             : 
     779                 :             :    we'll transform this into:
     780                 :             : 
     781                 :             :    if (<something>)
     782                 :             :    {
     783                 :             :       a_1 = b + c;
     784                 :             :    }
     785                 :             :    else
     786                 :             :    {
     787                 :             :       foo (&b, &c);
     788                 :             :       a_5 = b + c;
     789                 :             :    }
     790                 :             :    a_6 = PHI (a_5, a_1);
     791                 :             :    USE a_6.
     792                 :             : 
     793                 :             :    Note that this reduces the number of computations of a = b + c to 1
     794                 :             :    when we take the else edge, instead of 2.
     795                 :             : */
     796                 :             : namespace {
     797                 :             : 
     798                 :             : const pass_data pass_data_sink_code =
     799                 :             : {
     800                 :             :   GIMPLE_PASS, /* type */
     801                 :             :   "sink", /* name */
     802                 :             :   OPTGROUP_NONE, /* optinfo_flags */
     803                 :             :   TV_TREE_SINK, /* tv_id */
     804                 :             :   /* PROP_no_crit_edges is ensured by running split_edges_for_insertion in
     805                 :             :      pass_data_sink_code::execute ().  */
     806                 :             :   ( PROP_cfg | PROP_ssa ), /* properties_required */
     807                 :             :   0, /* properties_provided */
     808                 :             :   0, /* properties_destroyed */
     809                 :             :   0, /* todo_flags_start */
     810                 :             :   TODO_update_ssa, /* todo_flags_finish */
     811                 :             : };
     812                 :             : 
     813                 :             : class pass_sink_code : public gimple_opt_pass
     814                 :             : {
     815                 :             : public:
     816                 :      555834 :   pass_sink_code (gcc::context *ctxt)
     817                 :     1111668 :     : gimple_opt_pass (pass_data_sink_code, ctxt), unsplit_edges (false)
     818                 :             :   {}
     819                 :             : 
     820                 :             :   /* opt_pass methods: */
     821                 :     2039738 :   bool gate (function *) final override { return flag_tree_sink != 0; }
     822                 :             :   unsigned int execute (function *) final override;
     823                 :      277917 :   opt_pass *clone (void) final override { return new pass_sink_code (m_ctxt); }
     824                 :      555834 :   void set_pass_param (unsigned n, bool param) final override
     825                 :             :     {
     826                 :      555834 :       gcc_assert (n == 0);
     827                 :      555834 :       unsplit_edges = param;
     828                 :      555834 :     }
     829                 :             : 
     830                 :             : private:
     831                 :             :   bool unsplit_edges;
     832                 :             : }; // class pass_sink_code
     833                 :             : 
     834                 :             : unsigned int
     835                 :     2039585 : pass_sink_code::execute (function *fun)
     836                 :             : {
     837                 :     2039585 :   loop_optimizer_init (LOOPS_NORMAL);
     838                 :     2039585 :   split_edges_for_insertion ();
     839                 :             :   /* Arrange for the critical edge splitting to be undone if requested.  */
     840                 :     2039585 :   unsigned todo = unsplit_edges ? TODO_cleanup_cfg : 0;
     841                 :     2039585 :   connect_infinite_loops_to_exit ();
     842                 :     2039585 :   mark_dfs_back_edges (fun);
     843                 :     2039585 :   memset (&sink_stats, 0, sizeof (sink_stats));
     844                 :     2039585 :   calculate_dominance_info (CDI_DOMINATORS);
     845                 :     2039585 :   calculate_dominance_info (CDI_POST_DOMINATORS);
     846                 :             : 
     847                 :     2039585 :   virtual_operand_live vop_live;
     848                 :             : 
     849                 :     2039585 :   int *rpo = XNEWVEC (int, n_basic_blocks_for_fn (cfun));
     850                 :     2039585 :   int n = inverted_rev_post_order_compute (fun, rpo);
     851                 :    33902807 :   for (int i = 0; i < n; ++i)
     852                 :    31863222 :     todo |= sink_code_in_bb (BASIC_BLOCK_FOR_FN (fun, rpo[i]), vop_live);
     853                 :     2039585 :   free (rpo);
     854                 :             : 
     855                 :     2039585 :   statistics_counter_event (fun, "Sunk statements", sink_stats.sunk);
     856                 :     2039585 :   statistics_counter_event (fun, "Commoned stores", sink_stats.commoned);
     857                 :     2039585 :   free_dominance_info (CDI_POST_DOMINATORS);
     858                 :     2039585 :   remove_fake_exit_edges ();
     859                 :     2039585 :   loop_optimizer_finalize ();
     860                 :             : 
     861                 :     2039585 :   return todo;
     862                 :     2039585 : }
     863                 :             : 
     864                 :             : } // anon namespace
     865                 :             : 
     866                 :             : gimple_opt_pass *
     867                 :      277917 : make_pass_sink_code (gcc::context *ctxt)
     868                 :             : {
     869                 :      277917 :   return new pass_sink_code (ctxt);
     870                 :             : }
        

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.