LCOV - code coverage report
Current view: top level - gcc - tree-ssa-sink.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 99.4 % 339 337
Test Date: 2026-02-28 14:20:25 Functions: 100.0 % 13 13
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /* Code sinking for trees
       2              :    Copyright (C) 2001-2026 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       672683 : find_bb_for_arg (gphi *phi, tree def)
      84              : {
      85       672683 :   size_t i;
      86       672683 :   bool foundone = false;
      87       672683 :   basic_block result = NULL;
      88      2175762 :   for (i = 0; i < gimple_phi_num_args (phi); i++)
      89      1521778 :     if (PHI_ARG_DEF (phi, i) == def)
      90              :       {
      91       691382 :         if (foundone)
      92              :           return NULL;
      93       672683 :         foundone = true;
      94       672683 :         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     12967630 : all_immediate_uses_same_place (def_operand_p def_p)
     109              : {
     110     12967630 :   tree var = DEF_FROM_PTR (def_p);
     111     12967630 :   imm_use_iterator imm_iter;
     112     12967630 :   use_operand_p use_p;
     113              : 
     114     12967630 :   gimple *firstuse = NULL;
     115     40668630 :   FOR_EACH_IMM_USE_FAST (use_p, imm_iter, var)
     116              :     {
     117     18528635 :       if (is_gimple_debug (USE_STMT (use_p)))
     118      1655872 :         continue;
     119     16872763 :       if (firstuse == NULL)
     120              :         firstuse = USE_STMT (use_p);
     121              :       else
     122      3905133 :         if (firstuse != USE_STMT (use_p))
     123      3795265 :           return false;
     124      3795265 :     }
     125              : 
     126      9172365 :   return true;
     127              : }
     128              : 
     129              : /* Find the nearest common dominator of all of the immediate uses in IMM.  */
     130              : 
     131              : static basic_block
     132     12340803 : nearest_common_dominator_of_uses (def_operand_p def_p, bool *debug_stmts)
     133              : {
     134     12340803 :   tree var = DEF_FROM_PTR (def_p);
     135     12340803 :   auto_bitmap blocks;
     136     12340803 :   basic_block commondom;
     137     12340803 :   unsigned int j;
     138     12340803 :   bitmap_iterator bi;
     139     12340803 :   imm_use_iterator imm_iter;
     140     12340803 :   use_operand_p use_p;
     141              : 
     142     56128696 :   FOR_EACH_IMM_USE_FAST (use_p, imm_iter, var)
     143              :     {
     144     31447090 :       gimple *usestmt = USE_STMT (use_p);
     145     31447090 :       basic_block useblock;
     146              : 
     147     31447090 :       if (gphi *phi = dyn_cast <gphi *> (usestmt))
     148              :         {
     149      3780857 :           int idx = PHI_ARG_INDEX_FROM_USE (use_p);
     150              : 
     151      3780857 :           useblock = gimple_phi_arg_edge (phi, idx)->src;
     152              :         }
     153     27666233 :       else if (is_gimple_debug (usestmt))
     154              :         {
     155      6659332 :           *debug_stmts = true;
     156      6659332 :           continue;
     157              :         }
     158              :       else
     159              :         {
     160     21006901 :           useblock = gimple_bb (usestmt);
     161              :         }
     162              : 
     163              :       /* Short circuit. Nothing dominates the entry block.  */
     164     24787758 :       if (useblock == ENTRY_BLOCK_PTR_FOR_FN (cfun))
     165            0 :         return NULL;
     166              : 
     167     24787758 :       bitmap_set_bit (blocks, useblock->index);
     168            0 :     }
     169     12340803 :   commondom = BASIC_BLOCK_FOR_FN (cfun, bitmap_first_set_bit (blocks));
     170     34147105 :   EXECUTE_IF_SET_IN_BITMAP (blocks, 0, j, bi)
     171     21806302 :     commondom = nearest_common_dominator (CDI_DOMINATORS, commondom,
     172     21806302 :                                           BASIC_BLOCK_FOR_FN (cfun, j));
     173              :   return commondom;
     174     12340803 : }
     175              : 
     176              : /* Return whether sinking STMT from EARLY_BB to BEST_BB should be avoided.  */
     177              : 
     178              : static bool
     179      4275451 : 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      4275451 :   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      4275363 :   if (best_bb == early_bb->loop_father->latch
     190      4275363 :       && 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      4012220 :   if (best_bb->loop_father == early_bb->loop_father
     196      2848065 :       && loop_outer (best_bb->loop_father)
     197       750535 :       && !best_bb->loop_father->inner
     198       426449 :       && gimple_vuse (stmt)
     199       174317 :       && !gimple_vdef (stmt)
     200       162277 :       && flag_tree_loop_vectorize
     201       153029 :       && !(cfun->curr_properties & PROP_loop_opts_done)
     202       111414 :       && dominated_by_p (CDI_DOMINATORS, best_bb->loop_father->latch, early_bb)
     203      4098676 :       && !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     15990913 : 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     15990913 :   while (late_bb != early_bb
     224     16274529 :          && do_not_sink (stmt, early_bb, late_bb))
     225       283616 :     late_bb = get_immediate_dominator (CDI_DOMINATORS, late_bb);
     226              : 
     227     15990913 :   basic_block best_bb = late_bb;
     228     15990913 :   basic_block temp_bb = late_bb;
     229     19121464 :   while (temp_bb != early_bb)
     230              :     {
     231              :       /* Walk up the dominator tree, hopefully we'll find a shallower
     232              :          loop nest.  */
     233      3130551 :       temp_bb = get_immediate_dominator (CDI_DOMINATORS, temp_bb);
     234              : 
     235              :       /* Do not consider blocks we do not want to sink to.  */
     236      3130551 :       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      3130306 :       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      2577088 :       else if (bb_loop_depth (temp_bb) > bb_loop_depth (best_bb))
     246              :         ;
     247              : 
     248              :       /* Likewise an irreducible region inside an otherwise same loop
     249              :          depth.  */
     250      2333677 :       else if ((temp_bb->flags & BB_IRREDUCIBLE_LOOP)
     251         5996 :                && !(best_bb->flags & BB_IRREDUCIBLE_LOOP))
     252              :         ;
     253              : 
     254              :       /* But sink the least distance, if the new candidate on the same
     255              :          loop depth is post-dominated by the current best block pick
     256              :          the new candidate.  */
     257      2333456 :       else if (dominated_by_p (CDI_POST_DOMINATORS, temp_bb, best_bb))
     258              :         best_bb = temp_bb;
     259              : 
     260              :       /* Avoid sinking across a conditional branching to exceptional
     261              :          code.  In practice this does not reduce the number of dynamic
     262              :          executions of the sunk statement (this includes EH and
     263              :          branches leading to abort for example).  Treat this case as
     264              :          post-dominating.  */
     265      3465520 :       else if (single_pred_p (best_bb)
     266      1513351 :                && single_pred_edge (best_bb)->src == temp_bb
     267      2708788 :                && (single_pred_edge (best_bb)->flags & EDGE_FALLTHRU
     268       981646 :                    || (single_pred_edge (best_bb)->probability
     269      2758199 :                        >= profile_probability::always ())))
     270      1353791 :         best_bb = temp_bb;
     271              :     }
     272              : 
     273     15990913 :   gcc_checking_assert (best_bb == early_bb
     274              :                        || !do_not_sink (stmt, early_bb, best_bb));
     275              : 
     276     15990913 :   return best_bb;
     277              : }
     278              : 
     279              : /* Given a statement (STMT) and the basic block it is currently in (FROMBB),
     280              :    determine the location to sink the statement to, if any.
     281              :    Returns true if there is such location; in that case, TOGSI points to the
     282              :    statement before that STMT should be moved.  */
     283              : 
     284              : static bool
     285    111688004 : statement_sink_location (gimple *stmt, basic_block frombb,
     286              :                          gimple_stmt_iterator *togsi, bool *zero_uses_p,
     287              :                          virtual_operand_live &vop_live)
     288              : {
     289    111688004 :   gimple *use;
     290    111688004 :   use_operand_p one_use = NULL_USE_OPERAND_P;
     291    111688004 :   basic_block sinkbb;
     292    111688004 :   use_operand_p use_p;
     293    111688004 :   def_operand_p def_p;
     294    111688004 :   ssa_op_iter iter;
     295    111688004 :   imm_use_iterator imm_iter;
     296              : 
     297    111688004 :   *zero_uses_p = false;
     298              : 
     299              :   /* We only can sink assignments and const/pure calls that are guaranteed
     300              :      to return exactly once.  */
     301    111688004 :   int cf;
     302    111688004 :   if (!is_gimple_assign (stmt)
     303    111688004 :       && (!is_gimple_call (stmt)
     304      5167211 :           || !((cf = gimple_call_flags (stmt)) & (ECF_CONST|ECF_PURE))
     305      1042999 :           || (cf & (ECF_LOOPING_CONST_OR_PURE|ECF_RETURNS_TWICE))))
     306     80173026 :     return false;
     307              : 
     308              :   /* We only can sink stmts with a single definition.  */
     309     31514978 :   def_p = single_ssa_def_operand (stmt, SSA_OP_ALL_DEFS);
     310     31514978 :   if (def_p == NULL_DEF_OPERAND_P)
     311              :     return false;
     312              : 
     313              :   /* There are a few classes of things we can't or don't move, some because we
     314              :      don't have code to handle it, some because it's not profitable and some
     315              :      because it's not legal.
     316              : 
     317              :      We can't sink things that may be global stores, at least not without
     318              :      calculating a lot more information, because we may cause it to no longer
     319              :      be seen by an external routine that needs it depending on where it gets
     320              :      moved to.
     321              : 
     322              :      We can't sink statements that end basic blocks without splitting the
     323              :      incoming edge for the sink location to place it there.
     324              : 
     325              :      We can't sink statements that have volatile operands.
     326              : 
     327              :      We don't want to sink dead code, so anything with 0 immediate uses is not
     328              :      sunk.
     329              : 
     330              :      Don't sink BLKmode assignments if current function has any local explicit
     331              :      register variables, as BLKmode assignments may involve memcpy or memset
     332              :      calls or, on some targets, inline expansion thereof that sometimes need
     333              :      to use specific hard registers.
     334              : 
     335              :   */
     336     31514915 :   if (stmt_ends_bb_p (stmt)
     337     31334691 :       || gimple_has_side_effects (stmt)
     338     60997424 :       || (cfun->has_local_explicit_reg_vars
     339         1652 :           && TYPE_MODE (TREE_TYPE (gimple_get_lhs (stmt))) == BLKmode))
     340      2032407 :     return false;
     341              : 
     342              :   /* Return if there are no immediate uses of this stmt.  */
     343     29482508 :   if (has_zero_uses (DEF_FROM_PTR (def_p)))
     344              :     {
     345       103699 :       *zero_uses_p = true;
     346       103699 :       return false;
     347              :     }
     348              : 
     349     29378809 :   if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (DEF_FROM_PTR (def_p)))
     350              :     return false;
     351              : 
     352     72199541 :   FOR_EACH_SSA_USE_OPERAND (use_p, stmt, iter, SSA_OP_ALL_USES)
     353              :     {
     354     42822981 :       tree use = USE_FROM_PTR (use_p);
     355     42822981 :       if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (use))
     356              :         return false;
     357              :     }
     358              : 
     359     29376560 :   use = NULL;
     360              : 
     361              :   /* If stmt is a store the one and only use needs to be a VUSE on
     362              :      the live path.  */
     363     29376560 :   if (virtual_operand_p (DEF_FROM_PTR (def_p)))
     364              :     {
     365      7863392 :       tree lhs = gimple_get_lhs (stmt);
     366      7863392 :       ao_ref ref;
     367      7863392 :       ao_ref_init (&ref, lhs);
     368     24492183 :       FOR_EACH_IMM_USE_FAST (use_p, imm_iter, DEF_FROM_PTR (def_p))
     369              :         {
     370     10420656 :           gimple *use_stmt = USE_STMT (use_p);
     371              : 
     372              :           /* A killing definition is not a use.  */
     373     10420656 :           if (gimple_vdef (use_stmt)
     374     10873301 :               && ((gimple_has_lhs (use_stmt)
     375      6542527 :                    && operand_equal_p (lhs,
     376      6542527 :                                        gimple_get_lhs (use_stmt), 0))
     377      7592832 :                   || stmt_kills_ref_p (use_stmt, &ref)))
     378              :             {
     379              :               /* If use_stmt is or might be a nop assignment then USE_STMT
     380              :                  acts as a use as well as definition.  */
     381        50416 :               if (stmt != use_stmt
     382        50416 :                   && ref_maybe_used_by_stmt_p (use_stmt, &ref))
     383              :                 {
     384         1605 :                   if (use && use != use_stmt)
     385              :                     return false;
     386              :                   use = use_stmt;
     387              :                 }
     388        50340 :               continue;
     389              :             }
     390              : 
     391     10370240 :           if (is_a <gphi *> (use_stmt)
     392     10370240 :               || ref_maybe_used_by_stmt_p (use_stmt, &ref))
     393              :             {
     394      3345143 :               if (use && use != use_stmt)
     395              :                 return false;
     396      2325860 :               use = use_stmt;
     397      2325860 :               continue;
     398              :             }
     399              : 
     400     21647519 :           if (gimple_vdef (use_stmt))
     401              :             {
     402      5857023 :               if (stmt_may_clobber_ref_p_1 (use_stmt, &ref, false))
     403              :                 return false;
     404              :               /* We do not look past VDEFs, so treat them as sink location.  */
     405      5447862 :               if (use && use != use_stmt)
     406              :                 return false;
     407              :               use = use_stmt;
     408              :             }
     409      1655257 :         }
     410      6208135 :       if (!use)
     411              :         return false;
     412              :     }
     413              :   /* If all the immediate uses are not in the same place, find the nearest
     414              :      common dominator of all the immediate uses.  For PHI nodes, we have to
     415              :      find the nearest common dominator of all of the predecessor blocks, since
     416              :      that is where insertion would have to take place.  */
     417     21513168 :   else if (gimple_vuse (stmt)
     418     21513168 :            || !all_immediate_uses_same_place (def_p))
     419              :     {
     420     12340803 :       bool debug_stmts = false;
     421     12340803 :       basic_block commondom = nearest_common_dominator_of_uses (def_p,
     422              :                                                                 &debug_stmts);
     423              : 
     424     12340803 :       if (commondom == frombb)
     425              :         return false;
     426              : 
     427              :       /* If this is a load then do not sink past any stores.  */
     428      2021442 :       if (gimple_vuse (stmt))
     429              :         {
     430              :           /* Do not sink loads from hard registers.  */
     431       781266 :           if (gimple_assign_single_p (stmt)
     432       778199 :               && VAR_P (gimple_assign_rhs1 (stmt))
     433       804337 :               && DECL_HARD_REGISTER (gimple_assign_rhs1 (stmt)))
     434              :             return false;
     435              : 
     436              :           /* When the live virtual operand at the intended sink location is
     437              :              not the same as the one from the load walk up the dominator tree
     438              :              for a new candidate location.  */
     439              :           while (commondom != frombb
     440      3447148 :                  && vop_live.get_live_in (commondom) != gimple_vuse (stmt))
     441      1129328 :             commondom = get_immediate_dominator (CDI_DOMINATORS, commondom);
     442       781260 :           if (commondom == frombb)
     443              :             return false;
     444              :         }
     445              : 
     446              :       /* Our common dominator has to be dominated by frombb in order to be a
     447              :          trivially safe place to put this statement, since it has multiple
     448              :          uses.  */
     449       636687 :       if (!dominated_by_p (CDI_DOMINATORS, commondom, frombb))
     450              :         return false;
     451              : 
     452       636687 :       commondom = select_best_block (frombb, commondom, stmt);
     453              : 
     454       636687 :       if (commondom == frombb)
     455              :         return false;
     456              : 
     457       391632 :       *togsi = gsi_after_labels (commondom);
     458              : 
     459       391632 :       return true;
     460              :     }
     461              :   else
     462              :     {
     463     18635067 :       FOR_EACH_IMM_USE_FAST (one_use, imm_iter, DEF_FROM_PTR (def_p))
     464              :         {
     465      9462702 :           if (is_gimple_debug (USE_STMT (one_use)))
     466       290337 :             continue;
     467              :           break;
     468      9172365 :         }
     469      9172365 :       use = USE_STMT (one_use);
     470              :     }
     471              : 
     472     15372925 :   if (gimple_code (use) != GIMPLE_PHI)
     473              :     {
     474     14700242 :       sinkbb = select_best_block (frombb, gimple_bb (use), stmt);
     475              : 
     476     14700242 :       if (sinkbb == frombb)
     477              :         return false;
     478              : 
     479              :       /* The SSA update for sinking of stores cannot insert PHIs, the
     480              :          sink location has to lead to exit without crossing any CFG
     481              :          merge points to paths not dominated by the sink location.  */
     482       352273 :       if (gimple_vdef (stmt)
     483     99243680 :           && (!single_succ_p (sinkbb)
     484         5770 :               || single_succ (sinkbb)->index != EXIT_BLOCK))
     485              :         return false;
     486              : 
     487       344221 :       *togsi = gsi_after_labels (sinkbb);
     488              : 
     489       344221 :       return true;
     490              :     }
     491              : 
     492       672683 :   sinkbb = find_bb_for_arg (as_a <gphi *> (use), DEF_FROM_PTR (def_p));
     493              : 
     494              :   /* This can happen if there are multiple uses in a PHI.  */
     495       672683 :   if (!sinkbb)
     496              :     return false;
     497              : 
     498       653984 :   basic_block bestbb = select_best_block (frombb, sinkbb, stmt);
     499       653984 :   if (bestbb == frombb
     500              :       /* When we sink a store make sure there's not a path to any of
     501              :          the possibly skipped killing defs as that wrecks the virtual
     502              :          operand update, requiring inserting of a PHI node.  */
     503       121856 :       || (gimple_vdef (stmt)
     504         4496 :           && bestbb != sinkbb
     505           20 :           && !dominated_by_p (CDI_POST_DOMINATORS, bestbb, sinkbb))
     506              :       /* Likewise avoid placing VDEFs into an irreducible region.  */
     507       771344 :       || (gimple_vdef (stmt)
     508         4477 :           && (bestbb->flags & BB_IRREDUCIBLE_LOOP)))
     509       536641 :     return false;
     510              : 
     511       117343 :   *togsi = gsi_after_labels (bestbb);
     512              : 
     513       117343 :   return true;
     514              : }
     515              : 
     516              : /* Very simplistic code to sink common stores from the predecessor through
     517              :    our virtual PHI.  We do this before sinking stmts from BB as it might
     518              :    expose sinking opportunities of the merged stores.
     519              :    Once we have partial dead code elimination through sth like SSU-PRE this
     520              :    should be moved there.  */
     521              : 
     522              : static unsigned
     523     31981313 : sink_common_stores_to_bb (basic_block bb)
     524              : {
     525     31981313 :   unsigned todo = 0;
     526     31981313 :   gphi *phi;
     527              : 
     528     31981313 :   if (EDGE_COUNT (bb->preds) > 1
     529     29898511 :       && (phi = get_virtual_phi (bb)))
     530              :     {
     531              :       /* Repeat until no more common stores are found.  */
     532      3749722 :       while (1)
     533              :         {
     534      3683735 :           gimple *first_store = NULL;
     535      3683735 :           auto_vec <tree, 5> vdefs;
     536      3683735 :           gimple_stmt_iterator gsi;
     537              : 
     538              :           /* Search for common stores defined by all virtual PHI args.
     539              :              ???  Common stores not present in all predecessors could
     540              :              be handled by inserting a forwarder to sink to.  Generally
     541              :              this involves deciding which stores to do this for if
     542              :              multiple common stores are present for different sets of
     543              :              predecessors.  See PR11832 for an interesting case.  */
     544      4500994 :           for (unsigned i = 0; i < gimple_phi_num_args (phi); ++i)
     545              :             {
     546      4432002 :               tree arg = gimple_phi_arg_def (phi, i);
     547      4432002 :               gimple *def = SSA_NAME_DEF_STMT (arg);
     548      4432002 :               if (! is_gimple_assign (def)
     549      1914625 :                   || stmt_can_throw_internal (cfun, def)
     550      1899876 :                   || (gimple_phi_arg_edge (phi, i)->flags & EDGE_ABNORMAL)
     551      6331876 :                   || stmt_references_abnormal_ssa_name (def))
     552              :                 {
     553              :                   /* ???  We could handle some cascading with the def being
     554              :                      another PHI.  We'd have to insert multiple PHIs for
     555              :                      the rhs then though (if they are not all equal).  */
     556              :                   first_store = NULL;
     557      3614743 :                   break;
     558              :                 }
     559              :               /* ???  Do not try to do anything fancy with aliasing, thus
     560              :                  do not sink across non-aliased loads (or even stores,
     561              :                  so different store order will make the sinking fail).  */
     562      1899859 :               bool all_uses_on_phi = true;
     563      1899859 :               imm_use_iterator iter;
     564      1899859 :               use_operand_p use_p;
     565      5217419 :               FOR_EACH_IMM_USE_FAST (use_p, iter, arg)
     566      2410313 :                 if (USE_STMT (use_p) != phi)
     567              :                   {
     568              :                     all_uses_on_phi = false;
     569              :                     break;
     570      1899859 :                   }
     571      1899859 :               if (! all_uses_on_phi)
     572              :                 {
     573              :                   first_store = NULL;
     574              :                   break;
     575              :                 }
     576              :               /* Check all stores are to the same LHS.  */
     577       907247 :               if (! first_store)
     578              :                 first_store = def;
     579              :               /* ??? We could handle differing SSA uses in the LHS by inserting
     580              :                  PHIs for them.  */
     581       254570 :               else if (! operand_equal_p (gimple_assign_lhs (first_store),
     582       254570 :                                           gimple_assign_lhs (def), 0)
     583       419152 :                        || (gimple_clobber_p (first_store)
     584       164582 :                            != gimple_clobber_p (def)))
     585              :                 {
     586              :                   first_store = NULL;
     587              :                   break;
     588              :                 }
     589       817259 :               vdefs.safe_push (arg);
     590              :             }
     591      3683735 :           if (! first_store)
     592              :             break;
     593              : 
     594              :           /* Check if we need a PHI node to merge the stored values.  */
     595        68992 :           bool allsame = true;
     596        68992 :           if (!gimple_clobber_p (first_store))
     597        89142 :             for (unsigned i = 1; i < vdefs.length (); ++i)
     598              :               {
     599        82146 :                 gimple *def = SSA_NAME_DEF_STMT (vdefs[i]);
     600        82146 :                 if (! operand_equal_p (gimple_assign_rhs1 (first_store),
     601        82146 :                                        gimple_assign_rhs1 (def), 0))
     602              :                   {
     603              :                     allsame = false;
     604              :                     break;
     605              :                   }
     606              :               }
     607              : 
     608              :           /* We cannot handle aggregate values if we need to merge them.  */
     609        68992 :           tree type = TREE_TYPE (gimple_assign_lhs (first_store));
     610        68992 :           if (! allsame
     611        68992 :               && ! is_gimple_reg_type (type))
     612              :             break;
     613              : 
     614        65987 :           if (dump_enabled_p ())
     615              :             {
     616           18 :               dump_printf_loc (MSG_OPTIMIZED_LOCATIONS,
     617            9 :                                first_store,
     618              :                                "sinking common stores %sto ",
     619              :                                allsame ? "with same value " : "");
     620            9 :               dump_generic_expr (MSG_OPTIMIZED_LOCATIONS, TDF_SLIM,
     621              :                                  gimple_assign_lhs (first_store));
     622            9 :               dump_printf (MSG_OPTIMIZED_LOCATIONS, "\n");
     623              :             }
     624              : 
     625              :           /* Insert a PHI to merge differing stored values if necessary.
     626              :              Note that in general inserting PHIs isn't a very good idea as
     627              :              it makes the job of coalescing and register allocation harder.
     628              :              Even common SSA uses on the rhs/lhs might extend their lifetime
     629              :              across multiple edges by this code motion which makes
     630              :              register allocation harder.  */
     631        65987 :           tree from;
     632        65987 :           if (! allsame)
     633              :             {
     634        51734 :               from = make_ssa_name (type);
     635        51734 :               gphi *newphi = create_phi_node (from, bb);
     636       216948 :               for (unsigned i = 0; i < vdefs.length (); ++i)
     637              :                 {
     638       165214 :                   gimple *def = SSA_NAME_DEF_STMT (vdefs[i]);
     639       165214 :                   add_phi_arg (newphi, gimple_assign_rhs1 (def),
     640       165214 :                                EDGE_PRED (bb, i), UNKNOWN_LOCATION);
     641              :                 }
     642              :             }
     643              :           else
     644        14253 :             from = gimple_assign_rhs1 (first_store);
     645              : 
     646              :           /* Remove all stores.  */
     647       539332 :           for (unsigned i = 0; i < vdefs.length (); ++i)
     648       203679 :             TREE_VISITED (vdefs[i]) = 1;
     649       269666 :           for (unsigned i = 0; i < vdefs.length (); ++i)
     650              :             /* If we have more than one use of a VDEF on the PHI make sure
     651              :                we remove the defining stmt only once.  */
     652       203679 :             if (TREE_VISITED (vdefs[i]))
     653              :               {
     654       200098 :                 TREE_VISITED (vdefs[i]) = 0;
     655       200098 :                 gimple *def = SSA_NAME_DEF_STMT (vdefs[i]);
     656       200098 :                 gsi = gsi_for_stmt (def);
     657       200098 :                 unlink_stmt_vdef (def);
     658       200098 :                 gsi_remove (&gsi, true);
     659       200098 :                 release_defs (def);
     660              :               }
     661              : 
     662              :           /* Insert the first store at the beginning of the merge BB.  */
     663        65987 :           gimple_set_vdef (first_store, gimple_phi_result (phi));
     664       131974 :           SSA_NAME_DEF_STMT (gimple_vdef (first_store)) = first_store;
     665        65987 :           gimple_phi_set_result (phi, make_ssa_name (gimple_vop (cfun)));
     666        65987 :           gimple_set_vuse (first_store, gimple_phi_result (phi));
     667        65987 :           gimple_assign_set_rhs1 (first_store, from);
     668              :           /* ???  Should we reset first_stores location?  */
     669        65987 :           gsi = gsi_after_labels (bb);
     670        65987 :           gsi_insert_before (&gsi, first_store, GSI_SAME_STMT);
     671        65987 :           sink_stats.commoned++;
     672              : 
     673        65987 :           todo |= TODO_cleanup_cfg;
     674      3683735 :         }
     675              : 
     676              :       /* We could now have empty predecessors that we could remove,
     677              :          forming a proper CFG for further sinking.  Note that even
     678              :          CFG cleanup doesn't do this fully at the moment and it
     679              :          doesn't preserve post-dominators in the process either.
     680              :          The mergephi pass might do it though.  gcc.dg/tree-ssa/ssa-sink-13.c
     681              :          shows this nicely if you disable tail merging or (same effect)
     682              :          make the stored values unequal.  */
     683              :     }
     684              : 
     685     31981313 :   return todo;
     686              : }
     687              : 
     688              : /* Perform code sinking on BB */
     689              : 
     690              : static unsigned
     691     31981313 : sink_code_in_bb (basic_block bb, virtual_operand_live &vop_live)
     692              : {
     693     31981313 :   gimple_stmt_iterator gsi;
     694     31981313 :   edge_iterator ei;
     695     31981313 :   edge e;
     696     31981313 :   bool last = true;
     697     31981313 :   unsigned todo = 0;
     698              : 
     699              :   /* Sink common stores from the predecessor through our virtual PHI.  */
     700     31981313 :   todo |= sink_common_stores_to_bb (bb);
     701              : 
     702              :   /* If this block doesn't dominate anything, there can't be any place to sink
     703              :      the statements to.  */
     704     31981313 :   if (first_dom_son (CDI_DOMINATORS, bb) == NULL)
     705              :     return todo;
     706              : 
     707              :   /* We can't move things across abnormal edges, so don't try.  */
     708     37692601 :   FOR_EACH_EDGE (e, ei, bb->succs)
     709     23907943 :     if (e->flags & EDGE_ABNORMAL)
     710              :       return todo;
     711              : 
     712    139257320 :   for (gsi = gsi_last_bb (bb); !gsi_end_p (gsi);)
     713              :     {
     714    111688004 :       gimple *stmt = gsi_stmt (gsi);
     715    111688004 :       gimple_stmt_iterator togsi;
     716    111688004 :       bool zero_uses_p;
     717              : 
     718    111688004 :       if (!statement_sink_location (stmt, bb, &togsi, &zero_uses_p, vop_live))
     719              :         {
     720    110834808 :           gimple_stmt_iterator saved = gsi;
     721    110834808 :           if (!gsi_end_p (gsi))
     722    110834808 :             gsi_prev (&gsi);
     723              :           /* If we face a dead stmt remove it as it possibly blocks
     724              :              sinking of uses.  */
     725    110834808 :           if (zero_uses_p
     726       103699 :               && !gimple_vdef (stmt)
     727    110934718 :               && (cfun->can_delete_dead_exceptions
     728        76542 :                   || !stmt_could_throw_p (cfun, stmt)))
     729              :             {
     730        52631 :               gsi_remove (&saved, true);
     731        52631 :               release_defs (stmt);
     732              :             }
     733              :           else
     734              :             last = false;
     735    110834808 :           continue;
     736    110834808 :         }
     737       853196 :       if (dump_file)
     738              :         {
     739           37 :           fprintf (dump_file, "Sinking ");
     740           37 :           print_gimple_stmt (dump_file, stmt, 0, TDF_VOPS);
     741           37 :           fprintf (dump_file, " from bb %d to bb %d\n",
     742           37 :                    bb->index, (gsi_bb (togsi))->index);
     743              :         }
     744              : 
     745              :       /* Update virtual operands of statements in the path we
     746              :          do not sink to.  */
     747      1706392 :       if (gimple_vdef (stmt))
     748              :         {
     749         5157 :           imm_use_iterator iter;
     750         5157 :           use_operand_p use_p;
     751         5157 :           gimple *vuse_stmt;
     752              : 
     753        28042 :           FOR_EACH_IMM_USE_STMT (vuse_stmt, iter, gimple_vdef (stmt))
     754        17728 :             if (gimple_code (vuse_stmt) != GIMPLE_PHI
     755        17728 :                 && !dominated_by_p (CDI_DOMINATORS, gimple_bb (vuse_stmt),
     756        13268 :                                     gsi_bb (togsi)))
     757        36438 :               FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
     758        29449 :                 SET_USE (use_p, gimple_vuse (stmt));
     759              :         }
     760              : 
     761              :       /* If this is the end of the basic block, we need to insert at the end
     762              :          of the basic block.  */
     763       853196 :       if (gsi_end_p (togsi))
     764       138962 :         gsi_move_to_bb_end (&gsi, gsi_bb (togsi));
     765              :       else
     766       714234 :         gsi_move_before (&gsi, &togsi);
     767              : 
     768       853196 :       sink_stats.sunk++;
     769              : 
     770              :       /* If we've just removed the last statement of the BB, the
     771              :          gsi_end_p() test below would fail, but gsi_prev() would have
     772              :          succeeded, and we want it to succeed.  So we keep track of
     773              :          whether we're at the last statement and pick up the new last
     774              :          statement.  */
     775       853196 :       if (last)
     776              :         {
     777          982 :           gsi = gsi_last_bb (bb);
     778          982 :           continue;
     779              :         }
     780              : 
     781       852214 :       last = false;
     782       852214 :       if (!gsi_end_p (gsi))
     783      1704428 :         gsi_prev (&gsi);
     784              : 
     785              :     }
     786              : 
     787              :   return todo;
     788              : }
     789              : 
     790              : /* Perform code sinking.
     791              :    This moves code down the flowgraph when we know it would be
     792              :    profitable to do so, or it wouldn't increase the number of
     793              :    executions of the statement.
     794              : 
     795              :    IE given
     796              : 
     797              :    a_1 = b + c;
     798              :    if (<something>)
     799              :    {
     800              :    }
     801              :    else
     802              :    {
     803              :      foo (&b, &c);
     804              :      a_5 = b + c;
     805              :    }
     806              :    a_6 = PHI (a_5, a_1);
     807              :    USE a_6.
     808              : 
     809              :    we'll transform this into:
     810              : 
     811              :    if (<something>)
     812              :    {
     813              :       a_1 = b + c;
     814              :    }
     815              :    else
     816              :    {
     817              :       foo (&b, &c);
     818              :       a_5 = b + c;
     819              :    }
     820              :    a_6 = PHI (a_5, a_1);
     821              :    USE a_6.
     822              : 
     823              :    Note that this reduces the number of computations of a = b + c to 1
     824              :    when we take the else edge, instead of 2.
     825              : */
     826              : namespace {
     827              : 
     828              : const pass_data pass_data_sink_code =
     829              : {
     830              :   GIMPLE_PASS, /* type */
     831              :   "sink", /* name */
     832              :   OPTGROUP_NONE, /* optinfo_flags */
     833              :   TV_TREE_SINK, /* tv_id */
     834              :   /* PROP_no_crit_edges is ensured by running split_edges_for_insertion in
     835              :      pass_data_sink_code::execute ().  */
     836              :   ( PROP_cfg | PROP_ssa ), /* properties_required */
     837              :   0, /* properties_provided */
     838              :   0, /* properties_destroyed */
     839              :   0, /* todo_flags_start */
     840              :   TODO_update_ssa, /* todo_flags_finish */
     841              : };
     842              : 
     843              : class pass_sink_code : public gimple_opt_pass
     844              : {
     845              : public:
     846       571444 :   pass_sink_code (gcc::context *ctxt)
     847      1142888 :     : gimple_opt_pass (pass_data_sink_code, ctxt), unsplit_edges (false)
     848              :   {}
     849              : 
     850              :   /* opt_pass methods: */
     851      2082968 :   bool gate (function *) final override { return flag_tree_sink != 0; }
     852              :   unsigned int execute (function *) final override;
     853       285722 :   opt_pass *clone (void) final override { return new pass_sink_code (m_ctxt); }
     854       571444 :   void set_pass_param (unsigned n, bool param) final override
     855              :     {
     856       571444 :       gcc_assert (n == 0);
     857       571444 :       unsplit_edges = param;
     858       571444 :     }
     859              : 
     860              : private:
     861              :   bool unsplit_edges;
     862              : }; // class pass_sink_code
     863              : 
     864              : unsigned int
     865      2082802 : pass_sink_code::execute (function *fun)
     866              : {
     867      2082802 :   loop_optimizer_init (LOOPS_NORMAL);
     868      2082802 :   split_edges_for_insertion ();
     869              :   /* Arrange for the critical edge splitting to be undone if requested.  */
     870      2082802 :   unsigned todo = unsplit_edges ? TODO_cleanup_cfg : 0;
     871      2082802 :   connect_infinite_loops_to_exit ();
     872      2082802 :   mark_dfs_back_edges (fun);
     873      2082802 :   memset (&sink_stats, 0, sizeof (sink_stats));
     874      2082802 :   calculate_dominance_info (CDI_DOMINATORS);
     875      2082802 :   calculate_dominance_info (CDI_POST_DOMINATORS);
     876              : 
     877      2082802 :   virtual_operand_live vop_live;
     878              : 
     879      2082802 :   int *rpo = XNEWVEC (int, n_basic_blocks_for_fn (cfun));
     880      2082802 :   int n = inverted_rev_post_order_compute (fun, rpo);
     881     34064115 :   for (int i = 0; i < n; ++i)
     882     31981313 :     todo |= sink_code_in_bb (BASIC_BLOCK_FOR_FN (fun, rpo[i]), vop_live);
     883      2082802 :   free (rpo);
     884              : 
     885      2082802 :   statistics_counter_event (fun, "Sunk statements", sink_stats.sunk);
     886      2082802 :   statistics_counter_event (fun, "Commoned stores", sink_stats.commoned);
     887      2082802 :   free_dominance_info (CDI_POST_DOMINATORS);
     888      2082802 :   remove_fake_exit_edges ();
     889      2082802 :   loop_optimizer_finalize ();
     890              : 
     891      2082802 :   return todo;
     892      2082802 : }
     893              : 
     894              : } // anon namespace
     895              : 
     896              : gimple_opt_pass *
     897       285722 : make_pass_sink_code (gcc::context *ctxt)
     898              : {
     899       285722 :   return new pass_sink_code (ctxt);
     900              : }
        

Generated by: LCOV version 2.4-beta

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