LCOV - code coverage report
Current view: top level - gcc - tree-ssa-ter.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 89.5 % 287 257
Test Date: 2026-02-28 14:20:25 Functions: 94.1 % 17 16
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /* Routines for performing Temporary Expression Replacement (TER) in SSA trees.
       2              :    Copyright (C) 2003-2026 Free Software Foundation, Inc.
       3              :    Contributed by Andrew MacLeod  <amacleod@redhat.com>
       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              : 
      22              : #include "config.h"
      23              : #include "system.h"
      24              : #include "coretypes.h"
      25              : #include "backend.h"
      26              : #include "tree.h"
      27              : #include "gimple.h"
      28              : #include "ssa.h"
      29              : #include "gimple-pretty-print.h"
      30              : #include "gimple-iterator.h"
      31              : #include "dumpfile.h"
      32              : #include "tree-ssa-live.h"
      33              : #include "tree-ssa-ter.h"
      34              : #include "tree-outof-ssa.h"
      35              : #include "gimple-walk.h"
      36              : 
      37              : 
      38              : /* Temporary Expression Replacement (TER)
      39              : 
      40              :    Replace SSA version variables during out-of-ssa with their defining
      41              :    expression if there is only one use of the variable.
      42              : 
      43              :    This pass is required in order for the RTL expansion pass to see larger
      44              :    chunks of code.  This allows it to make better choices on RTL pattern
      45              :    selection.  When expand is rewritten and merged with out-of-ssa, and
      46              :    understands SSA, this should be eliminated.
      47              : 
      48              :    A pass is made through the function, one block at a time.  No cross block
      49              :    information is tracked.
      50              : 
      51              :    Variables which only have one use, and whose defining stmt is considered
      52              :    a replaceable expression (see ssa_is_replaceable_p) are tracked to see whether
      53              :    they can be replaced at their use location.
      54              : 
      55              :    n_12 = C * 10
      56              :    a_2 = b_5 + 6
      57              :    v_9 = a_2 * n_12
      58              : 
      59              :    if there are the only use of n_12 and a_2, TER will substitute in their
      60              :    expressions in v_9, and end up with:
      61              : 
      62              :    v_9 = (b_5 + 6) * (C * 10)
      63              : 
      64              :    which will then have the ssa_name assigned to regular variables, and the
      65              :    resulting code which will be passed to the expander looks something like:
      66              : 
      67              :    v = (b + 6) * (C * 10)
      68              : 
      69              : 
      70              :    This requires ensuring that none of the variables used by the expression
      71              :    change between the def point and where it is used.  Furthermore, if any
      72              :    of the ssa_names used in this expression are themselves replaceable, we
      73              :    have to ensure none of that expressions' arguments change either.
      74              :    Although SSA_NAMES themselves don't change, this pass is performed after
      75              :    coalescing has coalesced different SSA_NAMES together, so there could be a
      76              :    definition of an SSA_NAME which is coalesced with a use that causes a
      77              :    problem, i.e.,
      78              : 
      79              :    PHI b_5 = <b_8(2), b_14(1)>
      80              :    <...>
      81              :    a_2 = b_5 + 6
      82              :    b_8 = c_4 + 4
      83              :    v_9 = a_2 * n_12
      84              :    <...>
      85              : 
      86              :    If b_5, b_8 and b_14 are all coalesced together...
      87              :    The expression b_5 + 6 CANNOT replace the use in the statement defining v_9
      88              :    because b_8 is in fact killing the value of b_5 since they share a partition
      89              :    and will be assigned the same memory or register location.
      90              : 
      91              :    TER implements this but stepping through the instructions in a block and
      92              :    tracking potential expressions for replacement, and the partitions they are
      93              :    dependent on.  Expressions are represented by the SSA_NAME_VERSION of the
      94              :    DEF on the LHS of a GIMPLE_ASSIGN and the expression is the RHS.
      95              : 
      96              :    When a stmt is determined to be a possible replacement expression, the
      97              :    following steps are taken:
      98              : 
      99              :    EXPR_DECL_UID bitmap is allocated and set to the base variable UID of the
     100              :    def and any uses in the expression.  non-NULL means the expression is being
     101              :    tracked.  The UID's themselves are used to prevent TER substitution into
     102              :    accumulating sequences, i.e.,
     103              : 
     104              :    x = x + y
     105              :    x = x + z
     106              :    x = x + w
     107              :    etc.
     108              :    this can result in very large expressions which don't accomplish anything
     109              :    see PR tree-optimization/17549.
     110              : 
     111              :    PARTITION_DEPENDENCIES is another bitmap array, and it has a bit set for any
     112              :    partition which is used in the expression.  This is primarily used to remove
     113              :    an expression from the partition kill lists when a decision is made whether
     114              :    to replace it or not.  This is indexed by ssa version number as well, and
     115              :    indicates a partition number.  virtual operands are not tracked individually,
     116              :    but they are summarized by an artificial partition called VIRTUAL_PARTITION.
     117              :    This means a MAY or MUST def will kill *ALL* expressions that are dependent
     118              :    on a virtual operand.
     119              :    Note that the EXPR_DECL_UID and this bitmap represent very similar
     120              :    information, but the info in one is not easy to obtain from the other.
     121              : 
     122              :    KILL_LIST is yet another bitmap array, this time it is indexed by partition
     123              :    number, and represents a list of active expressions which will no
     124              :    longer be valid if a definition into this partition takes place.
     125              : 
     126              :    PARTITION_IN_USE is simply a bitmap which is used to track which partitions
     127              :    currently have something in their kill list.  This is used at the end of
     128              :    a block to clear out the KILL_LIST bitmaps at the end of each block.
     129              : 
     130              :    NEW_REPLACEABLE_DEPENDENCIES is used as a temporary place to store
     131              :    dependencies which will be reused by the current definition. All the uses
     132              :    on an expression are processed before anything else is done. If a use is
     133              :    determined to be a replaceable expression AND the current stmt is also going
     134              :    to be replaceable, all the dependencies of this replaceable use will be
     135              :    picked up by the current stmt's expression. Rather than recreate them, they
     136              :    are simply copied here and then copied into the new expression when it is
     137              :    processed.
     138              : 
     139              :    a_2 = b_5 + 6
     140              :    v_8 = a_2 + c_4
     141              : 
     142              :    a_2's expression 'b_5 + 6' is determined to be replaceable at the use
     143              :    location. It is dependent on the partition 'b_5' is in. This is cached into
     144              :    the NEW_REPLACEABLE_DEPENDENCIES bitmap, and when v_8 is examined for
     145              :    replaceability, it is a candidate, and it is dependent on the partition
     146              :    b_5 is in *NOT* a_2, as well as c_4's partition.
     147              : 
     148              :    if v_8 is also replaceable:
     149              : 
     150              :    x_9 = v_8 * 5
     151              : 
     152              :    x_9 is dependent on partitions b_5, and c_4
     153              : 
     154              :    if a statement is found which has either of those partitions written to
     155              :    before x_9 is used, then x_9 itself is NOT replaceable.  */
     156              : 
     157              : 
     158              : /* Temporary Expression Replacement (TER) table information.  */
     159              : 
     160              : struct temp_expr_table
     161              : {
     162              :   var_map map;
     163              :   bitmap *partition_dependencies;       /* Partitions expr is dependent on.  */
     164              :   bitmap replaceable_expressions;       /* Replacement expression table.  */
     165              :   bitmap *expr_decl_uids;               /* Base uids of exprs.  */
     166              :   bitmap *kill_list;                    /* Expr's killed by a partition.  */
     167              :   int virtual_partition;                /* Pseudo partition for virtual ops.  */
     168              :   bitmap partition_in_use;              /* Partitions with kill entries.  */
     169              :   bitmap new_replaceable_dependencies;  /* Holding place for pending dep's.  */
     170              :   int *num_in_part;                     /* # of ssa_names in a partition.  */
     171              :   int *call_cnt;                        /* Call count at definition.  */
     172              :   int *reg_vars_cnt;                    /* Number of register variable
     173              :                                            definitions encountered.  */
     174              : };
     175              : 
     176              : /* Used to indicate a dependency on VDEFs.  */
     177              : #define VIRTUAL_PARTITION(table)        (table->virtual_partition)
     178              : 
     179              : /* A place for the many, many bitmaps we create.  */
     180              : static bitmap_obstack ter_bitmap_obstack;
     181              : 
     182              : extern void debug_ter (FILE *, temp_expr_table *);
     183              : 
     184              : 
     185              : /* Create a new TER table for MAP.  */
     186              : 
     187              : static temp_expr_table *
     188      1043996 : new_temp_expr_table (var_map map)
     189              : {
     190      1043996 :   temp_expr_table *t = XNEW (struct temp_expr_table);
     191      1043996 :   t->map = map;
     192              : 
     193      2087992 :   t->partition_dependencies = XCNEWVEC (bitmap, num_ssa_names + 1);
     194      2087992 :   t->expr_decl_uids = XCNEWVEC (bitmap, num_ssa_names + 1);
     195      1043996 :   t->kill_list = XCNEWVEC (bitmap, num_var_partitions (map) + 1);
     196              : 
     197      1043996 :   t->partition_in_use = BITMAP_ALLOC (&ter_bitmap_obstack);
     198              : 
     199      1043996 :   t->virtual_partition = num_var_partitions (map);
     200      1043996 :   t->new_replaceable_dependencies = BITMAP_ALLOC (&ter_bitmap_obstack);
     201              : 
     202      1043996 :   t->replaceable_expressions = NULL;
     203      1043996 :   t->num_in_part = XCNEWVEC (int, num_var_partitions (map));
     204              : 
     205      1043996 :   unsigned x;
     206      1043996 :   tree name;
     207              : 
     208     58647081 :   FOR_EACH_SSA_NAME (x, name, cfun)
     209              :     {
     210     35723946 :       int p;
     211     35723946 :       p = var_to_partition (map, name);
     212     35723946 :       if (p != NO_PARTITION)
     213     22775126 :         t->num_in_part[p]++;
     214              :     }
     215      1043996 :   t->call_cnt = XCNEWVEC (int, num_ssa_names + 1);
     216      2087992 :   t->reg_vars_cnt = XCNEWVEC (int, num_ssa_names + 1);
     217              : 
     218      1043996 :   return t;
     219              : }
     220              : 
     221              : 
     222              : /* Free TER table T.  If there are valid replacements, return the expression
     223              :    vector.  */
     224              : 
     225              : static bitmap
     226      1043996 : free_temp_expr_table (temp_expr_table *t)
     227              : {
     228      1043996 :   bitmap ret = NULL;
     229              : 
     230      1043996 :   if (flag_checking)
     231              :     {
     232     20667954 :       for (unsigned x = 0; x <= num_var_partitions (t->map); x++)
     233     19623976 :         gcc_assert (!t->kill_list[x]);
     234     59690742 :       for (unsigned x = 0; x < num_ssa_names; x++)
     235              :         {
     236     58646764 :           gcc_assert (t->expr_decl_uids[x] == NULL);
     237     58646764 :           gcc_assert (t->partition_dependencies[x] == NULL);
     238              :         }
     239              :     }
     240              : 
     241      1043996 :   BITMAP_FREE (t->partition_in_use);
     242      1043996 :   BITMAP_FREE (t->new_replaceable_dependencies);
     243              : 
     244      1043996 :   free (t->expr_decl_uids);
     245      1043996 :   free (t->kill_list);
     246      1043996 :   free (t->partition_dependencies);
     247      1043996 :   free (t->num_in_part);
     248      1043996 :   free (t->call_cnt);
     249      1043996 :   free (t->reg_vars_cnt);
     250              : 
     251      1043996 :   if (t->replaceable_expressions)
     252              :     ret = t->replaceable_expressions;
     253              : 
     254      1043996 :   free (t);
     255      1043996 :   return ret;
     256              : }
     257              : 
     258              : 
     259              : /* Return TRUE if VERSION is to be replaced by an expression in TAB.  */
     260              : 
     261              : static inline bool
     262      9640091 : version_to_be_replaced_p (temp_expr_table *tab, int version)
     263              : {
     264      9640091 :   if (!tab->replaceable_expressions)
     265              :     return false;
     266      8874074 :   return bitmap_bit_p (tab->replaceable_expressions, version);
     267              : }
     268              : 
     269              : 
     270              : /* Add partition P to the list if partitions VERSION is dependent on.  TAB is
     271              :    the expression table */
     272              : 
     273              : static inline void
     274      4349981 : make_dependent_on_partition (temp_expr_table *tab, int version, int p)
     275              : {
     276      4349981 :   if (!tab->partition_dependencies[version])
     277      3722693 :     tab->partition_dependencies[version] = BITMAP_ALLOC (&ter_bitmap_obstack);
     278              : 
     279      4349981 :   bitmap_set_bit (tab->partition_dependencies[version], p);
     280      4349981 : }
     281              : 
     282              : 
     283              : /* Add VER to the kill list for P.  TAB is the expression table */
     284              : 
     285              : static inline void
     286      6519897 : add_to_partition_kill_list (temp_expr_table *tab, int p, int ver)
     287              : {
     288      6519897 :   if (!tab->kill_list[p])
     289              :     {
     290      5544443 :       tab->kill_list[p] = BITMAP_ALLOC (&ter_bitmap_obstack);
     291      5544443 :       bitmap_set_bit (tab->partition_in_use, p);
     292              :     }
     293      6519897 :   bitmap_set_bit (tab->kill_list[p], ver);
     294      6519897 : }
     295              : 
     296              : 
     297              : /* Remove VER from the partition kill list for P.  TAB is the expression
     298              :    table.  */
     299              : 
     300              : static inline void
     301      6403728 : remove_from_partition_kill_list (temp_expr_table *tab, int p, int version)
     302              : {
     303      6403728 :   gcc_checking_assert (tab->kill_list[p]);
     304      6403728 :   bitmap_clear_bit (tab->kill_list[p], version);
     305      6403728 :   if (bitmap_empty_p (tab->kill_list[p]))
     306              :     {
     307      5544443 :       bitmap_clear_bit (tab->partition_in_use, p);
     308      5544443 :       BITMAP_FREE (tab->kill_list[p]);
     309              :     }
     310      6403728 : }
     311              : 
     312              : 
     313              : /* Add a dependency between the def of ssa VERSION and VAR.  If VAR is
     314              :    replaceable by an expression, add a dependence each of the elements of the
     315              :    expression.  These are contained in the new_replaceable list.  TAB is the
     316              :    expression table.  */
     317              : 
     318              : static void
     319      9640091 : add_dependence (temp_expr_table *tab, int version, tree var)
     320              : {
     321      9640091 :   int i;
     322      9640091 :   bitmap_iterator bi;
     323      9640091 :   unsigned x;
     324              : 
     325      9640091 :   i = SSA_NAME_VERSION (var);
     326     18514165 :   if (version_to_be_replaced_p (tab, i))
     327              :     {
     328      3735664 :       if (!bitmap_empty_p (tab->new_replaceable_dependencies))
     329              :         {
     330              :           /* Version will now be killed by a write to any partition the
     331              :              substituted expression would have been killed by.  */
     332      3974242 :           EXECUTE_IF_SET_IN_BITMAP (tab->new_replaceable_dependencies, 0, x, bi)
     333      2169916 :             add_to_partition_kill_list (tab, x, version);
     334              : 
     335              :           /* Rather than set partition_dependencies and in_use lists bit by
     336              :              bit, simply OR in the new_replaceable_dependencies bits.  */
     337      1804326 :           if (!tab->partition_dependencies[version])
     338      1766626 :             tab->partition_dependencies[version] =
     339      1766626 :               BITMAP_ALLOC (&ter_bitmap_obstack);
     340      1804326 :           bitmap_ior_into (tab->partition_dependencies[version],
     341      1804326 :                            tab->new_replaceable_dependencies);
     342      1804326 :           bitmap_ior_into (tab->partition_in_use,
     343      1804326 :                            tab->new_replaceable_dependencies);
     344              :           /* It is only necessary to add these once.  */
     345      1804326 :           bitmap_clear (tab->new_replaceable_dependencies);
     346              :         }
     347              :     }
     348              :   else
     349              :     {
     350      5904427 :       i = var_to_partition (tab->map, var);
     351      5904427 :       gcc_checking_assert (i != NO_PARTITION);
     352      5904427 :       gcc_checking_assert (tab->num_in_part[i] != 0);
     353              :       /* Only dependencies on ssa_names which are coalesced with something need
     354              :          to be tracked.  Partitions with containing only a single SSA_NAME
     355              :          *cannot* have their value changed.  */
     356      5904427 :       if (tab->num_in_part[i] > 1)
     357              :         {
     358      1425816 :           add_to_partition_kill_list (tab, i, version);
     359      1425816 :           make_dependent_on_partition (tab, version, i);
     360              :         }
     361              :     }
     362      9640091 : }
     363              : 
     364              : 
     365              : /* This function will remove the expression for VERSION from replacement
     366              :    consideration in table TAB.  If FREE_EXPR is true, then remove the
     367              :    expression from consideration as well by freeing the decl uid bitmap.  */
     368              : 
     369              : static void
     370      9171466 : finished_with_expr (temp_expr_table *tab, int version, bool free_expr)
     371              : {
     372      9171466 :   unsigned i;
     373      9171466 :   bitmap_iterator bi;
     374              : 
     375              :   /* Remove this expression from its dependent lists.  The partition dependence
     376              :      list is retained and transferred later to whomever uses this version.  */
     377      9171466 :   if (tab->partition_dependencies[version])
     378              :     {
     379     11893047 :       EXECUTE_IF_SET_IN_BITMAP (tab->partition_dependencies[version], 0, i, bi)
     380      6403728 :         remove_from_partition_kill_list (tab, i, version);
     381      5489319 :       BITMAP_FREE (tab->partition_dependencies[version]);
     382              :     }
     383      9171466 :   if (free_expr)
     384      5435802 :     BITMAP_FREE (tab->expr_decl_uids[version]);
     385      9171466 : }
     386              : 
     387              : 
     388              : /* Return TRUE if expression STMT is suitable for replacement.
     389              :    In addition to ssa_is_replaceable_p, require the same bb, and for -O0
     390              :    same locus and same BLOCK), Considers memory loads as replaceable if aliasing
     391              :    is available.  */
     392              : 
     393              : static inline bool
     394     42845968 : ter_is_replaceable_p (gimple *stmt)
     395              : {
     396              : 
     397     42845968 :   if (ssa_is_replaceable_p (stmt))
     398              :     {
     399     18765213 :       use_operand_p use_p;
     400     18765213 :       tree def;
     401     18765213 :       gimple *use_stmt;
     402     18765213 :       location_t locus1, locus2;
     403     18765213 :       tree block1, block2;
     404              : 
     405              :       /* Only consider definitions which have a single use.  ssa_is_replaceable_p
     406              :          already performed this check, but the use stmt pointer is required for
     407              :          further checks.  */
     408     18765213 :       def = SINGLE_SSA_TREE_OPERAND (stmt, SSA_OP_DEF);
     409     18765213 :       if (!single_imm_use (def, &use_p, &use_stmt))
     410              :           return false;
     411              : 
     412              :       /* If the use isn't in this block, it wont be replaced either.  */
     413     18765213 :       if (gimple_bb (use_stmt) != gimple_bb (stmt))
     414              :         return false;
     415              : 
     416     18348314 :       locus1 = gimple_location (stmt);
     417     18348314 :       block1 = LOCATION_BLOCK (locus1);
     418     14533642 :       locus1 = LOCATION_LOCUS (locus1);
     419              : 
     420     18348314 :       if (gphi *phi = dyn_cast <gphi *> (use_stmt))
     421            0 :         locus2 = gimple_phi_arg_location (phi,
     422            0 :                                           PHI_ARG_INDEX_FROM_USE (use_p));
     423              :       else
     424     18348314 :         locus2 = gimple_location (use_stmt);
     425     18348314 :       block2 = LOCATION_BLOCK (locus2);
     426     15510589 :       locus2 = LOCATION_LOCUS (locus2);
     427              : 
     428     18348314 :       if ((!optimize || optimize_debug)
     429        18286 :           && ((locus1 != UNKNOWN_LOCATION && locus1 != locus2)
     430        12904 :               || (block1 != NULL_TREE && block1 != block2)))
     431              :         return false;
     432              : 
     433              :       return true;
     434              :     }
     435              :   return false;
     436              : }
     437              : 
     438              : 
     439              : /* Create an expression entry for a replaceable expression.  */
     440              : 
     441              : static void
     442      9171466 : process_replaceable (temp_expr_table *tab, gimple *stmt, int call_cnt,
     443              :                      int reg_vars_cnt)
     444              : {
     445      9171466 :   tree var, def, basevar;
     446      9171466 :   int version;
     447      9171466 :   ssa_op_iter iter;
     448      9171466 :   bitmap def_vars, use_vars;
     449              : 
     450      9171466 :   gcc_checking_assert (ter_is_replaceable_p (stmt));
     451              : 
     452      9171466 :   def = SINGLE_SSA_TREE_OPERAND (stmt, SSA_OP_DEF);
     453      9171466 :   version = SSA_NAME_VERSION (def);
     454      9171466 :   def_vars = BITMAP_ALLOC (&ter_bitmap_obstack);
     455              : 
     456      9171466 :   basevar = SSA_NAME_VAR (def);
     457       798716 :   if (basevar)
     458       798716 :     bitmap_set_bit (def_vars, DECL_UID (basevar));
     459              : 
     460              :   /* Add this expression to the dependency list for each use partition.  */
     461     18811557 :   FOR_EACH_SSA_TREE_OPERAND (var, stmt, iter, SSA_OP_USE)
     462              :     {
     463      9640091 :       int var_version = SSA_NAME_VERSION (var);
     464              : 
     465      9640091 :       use_vars = tab->expr_decl_uids[var_version];
     466      9640091 :       add_dependence (tab, version, var);
     467      9640091 :       if (use_vars)
     468              :         {
     469      3735664 :           bitmap_ior_into (def_vars, use_vars);
     470      3735664 :           BITMAP_FREE (tab->expr_decl_uids[var_version]);
     471              :         }
     472      5904427 :       else if (SSA_NAME_VAR (var))
     473      3202038 :         bitmap_set_bit (def_vars, DECL_UID (SSA_NAME_VAR (var)));
     474              :     }
     475      9171466 :   tab->expr_decl_uids[version] = def_vars;
     476              : 
     477              :   /* If there are VUSES, add a dependence on virtual defs.  */
     478     18342932 :   if (gimple_vuse (stmt))
     479              :     {
     480      2924165 :       make_dependent_on_partition (tab, version, VIRTUAL_PARTITION (tab));
     481      2924165 :       add_to_partition_kill_list (tab, VIRTUAL_PARTITION (tab), version);
     482              :     }
     483              : 
     484      9171466 :   tab->call_cnt[version] = call_cnt;
     485      9171466 :   tab->reg_vars_cnt[version] = reg_vars_cnt;
     486      9171466 : }
     487              : 
     488              : 
     489              : /* This function removes any expression in TAB which is dependent on PARTITION
     490              :    from consideration, making it not replaceable.  */
     491              : 
     492              : static inline void
     493     11595461 : kill_expr (temp_expr_table *tab, int partition)
     494              : {
     495     11595461 :   unsigned version;
     496              : 
     497              :   /* Mark every active expr dependent on this var as not replaceable.
     498              :      finished_with_expr can modify the bitmap, so we can't execute over it.  */
     499     11796924 :   while (tab->kill_list[partition])
     500              :     {
     501       201463 :       version = bitmap_first_set_bit (tab->kill_list[partition]);
     502       201463 :       finished_with_expr (tab, version, true);
     503              :     }
     504              : 
     505     11595461 :   gcc_checking_assert (!tab->kill_list[partition]);
     506     11595461 : }
     507              : 
     508              : 
     509              : /* This function kills all expressions in TAB which are dependent on virtual
     510              :    partitions.  */
     511              : 
     512              : static inline void
     513     11574217 : kill_virtual_exprs (temp_expr_table *tab)
     514              : {
     515     11574217 :   kill_expr (tab, VIRTUAL_PARTITION (tab));
     516     11574217 : }
     517              : 
     518              : 
     519              : /* Mark the expression associated with VAR as replaceable, and enter
     520              :    the defining stmt into the partition_dependencies table TAB.  If
     521              :    MORE_REPLACING is true, accumulate the pending partition dependencies.  */
     522              : 
     523              : static void
     524      8711643 : mark_replaceable (temp_expr_table *tab, tree var, bool more_replacing)
     525              : {
     526      8711643 :   int version = SSA_NAME_VERSION (var);
     527              : 
     528              :   /* Move the dependence list to the pending listpending.  */
     529      8711643 :   if (more_replacing && tab->partition_dependencies[version])
     530      2035115 :     bitmap_ior_into (tab->new_replaceable_dependencies,
     531              :                      tab->partition_dependencies[version]);
     532              : 
     533      8711643 :   finished_with_expr (tab, version, !more_replacing);
     534              : 
     535              :   /* Set the replaceable expression.
     536              :      The bitmap for this "escapes" from this file so it's allocated
     537              :      on the default obstack.  */
     538      8711643 :   if (!tab->replaceable_expressions)
     539       660071 :     tab->replaceable_expressions = BITMAP_ALLOC (NULL);
     540      8711643 :   bitmap_set_bit (tab->replaceable_expressions, version);
     541      8711643 : }
     542              : 
     543              : 
     544              : /* Helper function for find_ssaname_in_stores.  Called via walk_tree to
     545              :    find a SSA_NAME DATA somewhere in *TP.  */
     546              : 
     547              : static tree
     548        26078 : find_ssaname (tree *tp, int *walk_subtrees, void *data)
     549              : {
     550        26078 :   tree var = (tree) data;
     551        26078 :   if (*tp == var)
     552              :     return var;
     553        26025 :   else if (IS_TYPE_OR_DECL_P (*tp))
     554        20856 :     *walk_subtrees = 0;
     555              :   return NULL_TREE;
     556              : }
     557              : 
     558              : /* Helper function for find_replaceable_in_bb.  Return true if SSA_NAME DATA
     559              :    is used somewhere in T, which is a store in the statement.  Called via
     560              :    walk_stmt_load_store_addr_ops.  */
     561              : 
     562              : static bool
     563        21577 : find_ssaname_in_store (gimple *, tree, tree t, void *data)
     564              : {
     565        21577 :   return walk_tree (&t, find_ssaname, data, NULL) != NULL_TREE;
     566              : }
     567              : 
     568              : /* This function processes basic block BB, and looks for variables which can
     569              :    be replaced by their expressions.  Results are stored in the table TAB.  */
     570              : 
     571              : static void
     572      9297567 : find_replaceable_in_bb (temp_expr_table *tab, basic_block bb)
     573              : {
     574      9297567 :   gimple_stmt_iterator bsi;
     575      9297567 :   gimple *stmt;
     576      9297567 :   tree def, use, fndecl;
     577      9297567 :   int partition;
     578      9297567 :   var_map map = tab->map;
     579      9297567 :   ssa_op_iter iter;
     580      9297567 :   bool stmt_replaceable;
     581      9297567 :   int cur_call_cnt = 0;
     582      9297567 :   int cur_reg_vars_cnt = 0;
     583              : 
     584    101415454 :   for (bsi = gsi_start_bb (bb); !gsi_end_p (bsi); gsi_next (&bsi))
     585              :     {
     586     82820320 :       stmt = gsi_stmt (bsi);
     587              : 
     588     82820320 :       if (is_gimple_debug (stmt))
     589     49145818 :         continue;
     590              : 
     591     33674502 :       stmt_replaceable = ter_is_replaceable_p (stmt);
     592              : 
     593              :       /* Determine if this stmt finishes an existing expression.  */
     594     64153818 :       FOR_EACH_SSA_TREE_OPERAND (use, stmt, iter, SSA_OP_USE)
     595              :         {
     596     30479316 :           unsigned ver = SSA_NAME_VERSION (use);
     597              : 
     598              :           /* If this use is a potential replacement variable, process it.  */
     599     30479316 :           if (tab->expr_decl_uids[ver])
     600              :             {
     601      8970003 :               bool same_root_var = false;
     602      8970003 :               ssa_op_iter iter2;
     603      8970003 :               bitmap vars = tab->expr_decl_uids[ver];
     604              : 
     605              :               /* See if the root variables are the same.  If they are, we
     606              :                  do not want to do the replacement to avoid problems with
     607              :                  code size, see PR tree-optimization/17549.  */
     608      8970003 :               if (!bitmap_empty_p (vars))
     609      7686784 :                 FOR_EACH_SSA_TREE_OPERAND (def, stmt, iter2, SSA_OP_DEF)
     610              :                   {
     611      3127139 :                     if (SSA_NAME_VAR (def)
     612       743482 :                         && bitmap_bit_p (vars, DECL_UID (SSA_NAME_VAR (def))))
     613              :                       {
     614              :                         same_root_var = true;
     615              :                         break;
     616              :                       }
     617              :                   }
     618              : 
     619              :               /* If the stmt does a memory store and the replacement
     620              :                  is a load aliasing it avoid creating overlapping
     621              :                  assignments which we cannot expand correctly.  */
     622     16551576 :               if (gimple_vdef (stmt))
     623              :                 {
     624      2102880 :                   gimple *def_stmt = SSA_NAME_DEF_STMT (use);
     625      2103071 :                   while (is_gimple_assign (def_stmt)
     626      2103071 :                          && gimple_assign_rhs_code (def_stmt) == SSA_NAME)
     627          191 :                     def_stmt
     628          191 :                       = SSA_NAME_DEF_STMT (gimple_assign_rhs1 (def_stmt));
     629     11072883 :                   if (gimple_vuse (def_stmt)
     630       694921 :                       && gimple_assign_single_p (def_stmt)
     631      2797464 :                       && stmt_may_clobber_ref_p (stmt,
     632              :                                                  gimple_assign_rhs1 (def_stmt)))
     633              :                     {
     634              :                       /* For calls, it is not a problem if USE is among
     635              :                          call's arguments or say OBJ_TYPE_REF argument,
     636              :                          all those necessarily need to be evaluated before
     637              :                          the call that may clobber the memory.  But if
     638              :                          LHS of the call refers to USE, expansion might
     639              :                          evaluate it after the call, prevent TER in that
     640              :                          case.
     641              :                          For inline asm, allow TER of loads into input
     642              :                          arguments, but disallow TER for USEs that occur
     643              :                          somewhere in outputs.  */
     644       432383 :                       if (is_gimple_call (stmt)
     645       432383 :                           || gimple_code (stmt) == GIMPLE_ASM)
     646              :                         {
     647       348034 :                           if (walk_stmt_load_store_ops (stmt, use, NULL,
     648              :                                                         find_ssaname_in_store))
     649        84402 :                             same_root_var = true;
     650              :                         }
     651              :                       else
     652              :                         same_root_var = true;
     653              :                     }
     654              :                 }
     655              : 
     656              :               /* Mark expression as replaceable unless stmt is volatile, or the
     657              :                  def variable has the same root variable as something in the
     658              :                  substitution list, or the def and use span a call such that
     659              :                  we'll expand lifetimes across a call.  We also don't want to
     660              :                  replace across these expressions that may call libcalls that
     661              :                  clobber the register involved.  See PR 70184.  Neither
     662              :                  do we want to move possibly trapping expressions across
     663              :                  a call.  See PRs 102129 and 33593.  */
     664     16498912 :               if (gimple_has_volatile_ops (stmt) || same_root_var
     665      8766624 :                   || (tab->call_cnt[ver] != cur_call_cnt
     666        90779 :                       && (SINGLE_SSA_USE_OPERAND (SSA_NAME_DEF_STMT (use),
     667              :                                                   SSA_OP_USE)
     668              :                             == NULL_USE_OPERAND_P
     669        39285 :                           || gimple_could_trap_p (SSA_NAME_DEF_STMT (use))))
     670     16293229 :                   || tab->reg_vars_cnt[ver] != cur_reg_vars_cnt)
     671       258360 :                 finished_with_expr (tab, ver, true);
     672              :               else
     673      8711643 :                 mark_replaceable (tab, use, stmt_replaceable);
     674              :             }
     675              :         }
     676              : 
     677              :       /* Next, see if this stmt kills off an active expression.  */
     678     51099425 :       FOR_EACH_SSA_TREE_OPERAND (def, stmt, iter, SSA_OP_DEF)
     679              :         {
     680     17424923 :           partition = var_to_partition (map, def);
     681     17424923 :           if (partition != NO_PARTITION && tab->kill_list[partition])
     682        21244 :             kill_expr (tab, partition);
     683              :         }
     684              : 
     685              :       /* Increment counter if this is a non BUILT_IN call. We allow
     686              :          replacement over BUILT_IN calls since many will expand to inline
     687              :          insns instead of a true call.  */
     688     33674502 :       if (is_gimple_call (stmt)
     689     38687935 :           && !((fndecl = gimple_call_fndecl (stmt))
     690      5013433 :                && fndecl_built_in_p (fndecl)))
     691      3821085 :         cur_call_cnt++;
     692              : 
     693              :       /* Increment counter if this statement sets a local
     694              :          register variable.  */
     695     33674502 :       if (gimple_assign_single_p (stmt)
     696     33674502 :           && (VAR_P (gimple_assign_lhs (stmt))
     697      1719691 :           && DECL_HARD_REGISTER (gimple_assign_lhs (stmt))))
     698         1011 :         cur_reg_vars_cnt++;
     699              : 
     700              :       /* Now see if we are creating a new expression or not.  */
     701     33674502 :       if (stmt_replaceable)
     702      9171466 :         process_replaceable (tab, stmt, cur_call_cnt, cur_reg_vars_cnt);
     703              : 
     704              :       /* Free any unused dependency lists.  */
     705     33674502 :       bitmap_clear (tab->new_replaceable_dependencies);
     706              : 
     707              :       /* A V_{MAY,MUST}_DEF kills any expression using a virtual operand,
     708              :          including the current stmt.  */
     709    145431701 :       if (gimple_vdef (stmt))
     710     11574217 :         kill_virtual_exprs (tab);
     711              :     }
     712      9297567 : }
     713              : 
     714              : 
     715              : /* This function is the driver routine for replacement of temporary expressions
     716              :    in the SSA->normal phase, operating on MAP.  If there are replaceable
     717              :    expressions, a table is returned which maps SSA versions to the
     718              :    expressions they should be replaced with.  A NULL_TREE indicates no
     719              :    replacement should take place.  If there are no replacements at all,
     720              :    NULL is returned by the function, otherwise an expression vector indexed
     721              :    by SSA_NAME version numbers.  */
     722              : 
     723              : bitmap
     724      1043996 : find_replaceable_exprs (var_map map)
     725              : {
     726      1043996 :   basic_block bb;
     727      1043996 :   temp_expr_table *table;
     728      1043996 :   bitmap ret;
     729              : 
     730      1043996 :   bitmap_obstack_initialize (&ter_bitmap_obstack);
     731      1043996 :   table = new_temp_expr_table (map);
     732     10341563 :   FOR_EACH_BB_FN (bb, cfun)
     733              :     {
     734      9297567 :       find_replaceable_in_bb (table, bb);
     735      9297567 :       gcc_checking_assert (bitmap_empty_p (table->partition_in_use));
     736              :     }
     737      1043996 :   ret = free_temp_expr_table (table);
     738      1043996 :   bitmap_obstack_release (&ter_bitmap_obstack);
     739      1043996 :   return ret;
     740              : }
     741              : 
     742              : /* Dump TER expression table EXPR to file F.  */
     743              : 
     744              : void
     745           12 : dump_replaceable_exprs (FILE *f, bitmap expr)
     746              : {
     747           12 :   tree var;
     748           12 :   unsigned x;
     749              : 
     750           12 :   fprintf (f, "\nReplacing Expressions\n");
     751          218 :   for (x = 0; x < num_ssa_names; x++)
     752          194 :     if (bitmap_bit_p (expr, x))
     753              :       {
     754           39 :         var = ssa_name (x);
     755           39 :         print_generic_expr (f, var, TDF_SLIM);
     756           39 :         fprintf (f, " replace with --> ");
     757           39 :         print_gimple_stmt (f, SSA_NAME_DEF_STMT (var), 0, TDF_SLIM);
     758           39 :         fprintf (f, "\n");
     759              :       }
     760           12 :   fprintf (f, "\n");
     761           12 : }
     762              : 
     763              : 
     764              : /* Dump the status of the various tables in the expression table.  This is used
     765              :    exclusively to debug TER.  F is the place to send debug info and T is the
     766              :    table being debugged.  */
     767              : 
     768              : DEBUG_FUNCTION void
     769            0 : debug_ter (FILE *f, temp_expr_table *t)
     770              : {
     771            0 :   unsigned x, y;
     772            0 :   bitmap_iterator bi;
     773              : 
     774            0 :   fprintf (f, "\nDumping current state of TER\n virtual partition = %d\n",
     775              :            VIRTUAL_PARTITION (t));
     776            0 :   if (t->replaceable_expressions)
     777            0 :     dump_replaceable_exprs (f, t->replaceable_expressions);
     778            0 :   fprintf (f, "Currently tracking the following expressions:\n");
     779              : 
     780            0 :   for (x = 1; x < num_ssa_names; x++)
     781            0 :     if (t->expr_decl_uids[x])
     782              :       {
     783            0 :         print_generic_expr (f, ssa_name (x), TDF_SLIM);
     784            0 :         fprintf (f, " dep-parts : ");
     785            0 :         if (t->partition_dependencies[x]
     786            0 :             && !bitmap_empty_p (t->partition_dependencies[x]))
     787              :           {
     788            0 :             EXECUTE_IF_SET_IN_BITMAP (t->partition_dependencies[x], 0, y, bi)
     789            0 :               fprintf (f, "P%d ",y);
     790              :           }
     791            0 :         fprintf (f, "   basedecls: ");
     792            0 :         EXECUTE_IF_SET_IN_BITMAP (t->expr_decl_uids[x], 0, y, bi)
     793            0 :           fprintf (f, "%d ",y);
     794            0 :         fprintf (f, "   call_cnt : %d",t->call_cnt[x]);
     795            0 :         fprintf (f, "\n");
     796              :       }
     797              : 
     798            0 :   bitmap_print (f, t->partition_in_use, "Partitions in use ",
     799              :                 "\npartition KILL lists:\n");
     800              : 
     801            0 :   for (x = 0; x <= num_var_partitions (t->map); x++)
     802            0 :     if (t->kill_list[x])
     803              :       {
     804            0 :         fprintf (f, "Partition %d : ", x);
     805            0 :         EXECUTE_IF_SET_IN_BITMAP (t->kill_list[x], 0, y, bi)
     806            0 :           fprintf (f, "_%d ",y);
     807              :       }
     808              : 
     809            0 :   fprintf (f, "\n----------\n");
     810            0 : }
        

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.