LCOV - code coverage report
Current view: top level - gcc - gimple-ssa-backprop.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 98.7 % 455 449
Test Date: 2026-06-20 15:32:29 Functions: 97.6 % 41 40
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /* Back-propagation of usage information to definitions.
       2              :    Copyright (C) 2015-2026 Free Software Foundation, Inc.
       3              : 
       4              : This file is part of GCC.
       5              : 
       6              : GCC is free software; you can redistribute it and/or modify
       7              : it under the terms of the GNU General Public License as published by
       8              : the Free Software Foundation; either version 3, or (at your option)
       9              : any later version.
      10              : 
      11              : GCC is distributed in the hope that it will be useful,
      12              : but WITHOUT ANY WARRANTY; without even the implied warranty of
      13              : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14              : GNU General Public License for more details.
      15              : 
      16              : You should have received a copy of the GNU General Public License
      17              : along with GCC; see the file COPYING3.  If not see
      18              : <http://www.gnu.org/licenses/>.  */
      19              : 
      20              : /* This pass propagates information that is common to all uses of an SSA
      21              :    name back up through the sequence of statements that generate it,
      22              :    simplifying the statements where possible.  Sometimes this can expose
      23              :    fully or partially dead code, but the main focus is simplifying
      24              :    computations.
      25              : 
      26              :    At the moment the pass only handles one piece of information: whether the
      27              :    sign of a value matters, and therefore whether sign-changing operations
      28              :    can be skipped.  The pass could be extended to more interesting
      29              :    information in future, such as which bits of an integer are significant.
      30              : 
      31              :    For example, take the function:
      32              : 
      33              :      double
      34              :      f (double *a, int n, double start)
      35              :      {
      36              :        double x = fabs (start);
      37              :        for (int i = 0; i < n; ++i)
      38              :          x *= a[i];
      39              :        return __builtin_cos (x);
      40              :      }
      41              : 
      42              :    cos(x) == cos(-x), so the sign of the final x doesn't matter.
      43              :    That x is the result of a series of multiplications, and if
      44              :    the sign of the result of a multiplication doesn't matter,
      45              :    the signs of the inputs don't matter either.
      46              : 
      47              :    The pass would replace the incoming value of x (i.e. fabs(start))
      48              :    with start.  Since there are no other uses of the fabs result,
      49              :    the call would get deleted as dead.
      50              : 
      51              :    The algorithm is:
      52              : 
      53              :    (1) Do a post-order traversal of the blocks in the function, walking
      54              :        each block backwards.  For each potentially-simplifiable statement
      55              :        that defines an SSA name X, examine all uses of X to see what
      56              :        information is actually significant.  Record this in VAR_TABLE[X].
      57              :        Optimistically ignore for now any back-edge references to
      58              :        unprocessed phis.
      59              : 
      60              :        (An alternative would be to record each use when we visit its
      61              :        statement and take the intersection as we go along.  However,
      62              :        this would lead to more SSA names being entered into VAR_TABLE
      63              :        unnecessarily, only to be taken out again later.  At the moment
      64              :        very few SSA names end up with useful information.)
      65              : 
      66              :    (2) Iteratively reduce the optimistic result of (1) until we reach
      67              :        a maximal fixed point.  First push all SSA names that used an
      68              :        optimistic assumption about a backedge phi onto a worklist.
      69              :        While the worklist is nonempty, pick off an SSA name X and recompute
      70              :        the usage information in VAR_TABLE[X].  If the value changes, push all
      71              :        SSA names used in the definition of X onto the worklist.
      72              : 
      73              :    (3) Iterate over each SSA name X with info in VAR_TABLE, in the
      74              :        opposite order to (1), i.e. a forward reverse-post-order walk.
      75              :        Try to use the information in VAR_TABLE[X] to replace the definition
      76              :        of X with a simpler calculation that may yield a different result.
      77              :        When deciding to do such a replacement, record that each entry in
      78              :        VAR_TABLE that directly or indirectly depends on X will then also
      79              :        need to be replaced with a different calculation.  (The information
      80              :        in VAR_TABLE guarantees that other uses of X are unaffected.)
      81              : 
      82              :    (4) Iterate over each SSA name X with info in VAR_TABLE, in the same
      83              :        order as (1).  Carry out any scheduled replacement of X with a
      84              :        different value, ensuring that debug uses either keep their current
      85              :        value or are reset.  (This traversal order ensures that, if a chain
      86              :        of values is being replaced, a debug bind is created for the last
      87              :        value first, exposing a new debug use of the preceding value in
      88              :        the chain.)
      89              : 
      90              :    (5) Iterate over each SSA name X with info in VAR_TABLE, in the same order
      91              :        as (1).  Delete any statements that are now dead.  (This traversal order
      92              :        ensures that if a sequence of statements is dead, we delete the last
      93              :        statement first.  It is not safe to do this on-the-fly during (4)
      94              :        because multiple SSA names might be replaced with the same value.)
      95              : 
      96              :    Note that this pass does not deal with direct redundancies,
      97              :    such as cos(-x)->cos(x).  match.pd handles those cases instead.  */
      98              : 
      99              : #include "config.h"
     100              : #include "system.h"
     101              : #include "coretypes.h"
     102              : #include "backend.h"
     103              : #include "tree.h"
     104              : #include "gimple.h"
     105              : #include "gimple-iterator.h"
     106              : #include "ssa.h"
     107              : #include "fold-const.h"
     108              : #include "tree-pass.h"
     109              : #include "cfganal.h"
     110              : #include "gimple-pretty-print.h"
     111              : #include "tree-cfg.h"
     112              : #include "tree-ssa.h"
     113              : #include "tree-ssa-propagate.h"
     114              : #include "gimple-fold.h"
     115              : #include "alloc-pool.h"
     116              : #include "tree-hash-traits.h"
     117              : #include "case-cfn-macros.h"
     118              : 
     119              : namespace {
     120              : 
     121              : /* Information about a group of uses of an SSA name.  */
     122              : class usage_info
     123              : {
     124              : public:
     125     66808571 :   usage_info () : flag_word (0) {}
     126              :   usage_info &operator &= (const usage_info &);
     127              :   usage_info operator & (const usage_info &) const;
     128              :   bool operator == (const usage_info &) const;
     129              :   bool operator != (const usage_info &) const;
     130              :   bool is_useful () const;
     131              : 
     132              :   static usage_info intersection_identity ();
     133              : 
     134              :   union
     135              :   {
     136              :     struct
     137              :     {
     138              :       /* True if the uses treat x and -x in the same way.  */
     139              :       unsigned int ignore_sign : 1;
     140              :     } flags;
     141              :     /* All the flag bits as a single int.  */
     142              :     unsigned int flag_word;
     143              :   };
     144              : };
     145              : 
     146              : /* Return an X such that X & Y == Y for all Y.  This is the most
     147              :    optimistic assumption possible.  */
     148              : 
     149              : usage_info
     150     22500420 : usage_info::intersection_identity ()
     151              : {
     152     22500420 :   usage_info ret;
     153     22500420 :   ret.flag_word = -1;
     154     22500420 :   return ret;
     155              : }
     156              : 
     157              : /* Intersect *THIS with OTHER, so that *THIS describes all uses covered
     158              :    by the original *THIS and OTHER.  */
     159              : 
     160              : usage_info &
     161     21801963 : usage_info::operator &= (const usage_info &other)
     162              : {
     163     21801963 :   flag_word &= other.flag_word;
     164     21801963 :   return *this;
     165              : }
     166              : 
     167              : /* Return the intersection of *THIS and OTHER, i.e. a structure that
     168              :    describes all uses covered by *THIS and OTHER.  */
     169              : 
     170              : usage_info
     171           63 : usage_info::operator & (const usage_info &other) const
     172              : {
     173           63 :   usage_info info (*this);
     174           63 :   info &= other;
     175           63 :   return info;
     176              : }
     177              : 
     178              : bool
     179         5262 : usage_info::operator == (const usage_info &other) const
     180              : {
     181         5262 :   return flag_word == other.flag_word;
     182              : }
     183              : 
     184              : bool
     185         5262 : usage_info::operator != (const usage_info &other) const
     186              : {
     187         5262 :   return !operator == (other);
     188              : }
     189              : 
     190              : /* Return true if *THIS is not simply the default, safe assumption.  */
     191              : 
     192              : bool
     193     22506251 : usage_info::is_useful () const
     194              : {
     195     22506251 :   return flag_word != 0;
     196              : }
     197              : 
     198              : /* Start a dump line about SSA name VAR.  */
     199              : 
     200              : static void
     201          200 : dump_usage_prefix (FILE *file, tree var)
     202              : {
     203          200 :   fprintf (file, "  ");
     204          200 :   print_generic_expr (file, var);
     205          200 :   fprintf (file, ": ");
     206          200 : }
     207              : 
     208              : /* Print INFO to FILE.  */
     209              : 
     210              : static void
     211          332 : dump_usage_info (FILE *file, tree var, usage_info *info)
     212              : {
     213          332 :   if (info->flags.ignore_sign)
     214              :     {
     215          200 :       dump_usage_prefix (file, var);
     216          200 :       fprintf (file, "sign bit not important\n");
     217              :     }
     218          332 : }
     219              : 
     220              : /* Information about an SSA name that we might want to optimize.  */
     221              : struct var_info
     222              : {
     223       956026 :   var_info (tree var, unsigned int index, const usage_info &info)
     224       956026 :     : var (var), new_value (var), seq (nullptr), index (index), info (info)
     225              :   {}
     226              : 
     227              :   /* The SSA name itself.  */
     228              :   tree var;
     229              : 
     230              :   /* The value that VAR will be replaced with, or VAR itself if no
     231              :      replacement is scheduled.  */
     232              :   tree new_value;
     233              : 
     234              :   /* If NEW_VALUE != VAR, the definition of VAR will be replaced by this
     235              :      sequence, with an empty sequence meaning that the definition of VAR
     236              :      should simply be deleted.  */
     237              :   gimple_seq seq;
     238              : 
     239              :   /* The index of this entry in the M_VARS array.  */
     240              :   unsigned int index;
     241              : 
     242              :   /* Information about all uses of the SSA name.  */
     243              :   usage_info info;
     244              : };
     245              : 
     246              : /* Hash var_info based on the SSA name.  */
     247              : struct var_info_hasher : nofree_ptr_hash<var_info>
     248              : {
     249              :   using compare_type = const_tree;
     250              : 
     251              :   static inline hashval_t hash (const var_info *);
     252              :   static inline bool equal (const var_info *, const_tree);
     253              : };
     254              : 
     255              : hashval_t
     256      8171818 : var_info_hasher::hash (const var_info *v)
     257              : {
     258      8171818 :   return SSA_NAME_VERSION (v->var);
     259              : }
     260              : 
     261              : bool
     262     10974973 : var_info_hasher::equal (const var_info *v, const_tree var)
     263              : {
     264     10974973 :   return v->var == var;
     265              : }
     266              : 
     267              : /* Represents one execution of the pass.  */
     268              : class backprop
     269              : {
     270              : public:
     271              :   backprop (function *);
     272              :   ~backprop ();
     273              : 
     274              :   void execute ();
     275              : 
     276              : private:
     277              :   var_info *lookup_operand (tree);
     278              : 
     279              :   void push_to_worklist (var_info *);
     280              :   var_info *pop_from_worklist ();
     281              : 
     282              :   void process_builtin_call_use (gcall *, tree, usage_info *);
     283              :   void process_assign_use (gassign *, tree, usage_info *);
     284              :   void process_phi_use (gphi *, usage_info *);
     285              :   void process_use (gimple *, tree, usage_info *);
     286              :   bool intersect_uses (tree, usage_info *);
     287              :   void reprocess_inputs (gimple *);
     288              :   void process_var (tree, var_info *);
     289              :   void process_block (basic_block);
     290              : 
     291              :   void set_new_value (var_info *, tree);
     292              :   tree subst_operand (tree);
     293              :   gimple *copy_and_subst (var_info *);
     294              :   void finish_stmt (var_info *, gimple *);
     295              :   void optimize_builtin_call (gcall *, var_info *);
     296              :   void replace_assign_rhs (var_info *, tree, tree, tree);
     297              :   void optimize_assign (gassign *, var_info *);
     298              :   void optimize_phi (gphi *, var_info *);
     299              : 
     300              :   void propagate_change (var_info *);
     301              :   void commit_replacement (var_info *);
     302              : 
     303              :   /* The function we're optimizing.  */
     304              :   function *m_fn;
     305              : 
     306              :   /* Pool for allocating var_info structures.  */
     307              :   object_allocator<var_info> m_var_pool;
     308              : 
     309              :   /* All extant var_infos, hashed by SSA name.  All the usage_infos satisfy
     310              :      is_useful.
     311              : 
     312              :      We use a hash_table because the table is expected to be sparse
     313              :      (i.e. most SSA names won't have useful information attached to them).
     314              :      We could move to a directly-indexed array if that situation changes.  */
     315              :   hash_table<var_info_hasher> m_var_table;
     316              : 
     317              :   /* A post-ordered list of the contents of M_VAR_TABLE.  Entries might
     318              :      be null if we initially created a var_info and then withdrew it.  */
     319              :   auto_vec<var_info *, 128> m_vars;
     320              : 
     321              :   /* A bitmap of blocks that we have finished processing in the initial
     322              :      post-order walk.  */
     323              :   auto_sbitmap m_visited_blocks;
     324              : 
     325              :   /* A bitmap of phis that we have finished processing in the initial
     326              :      post-order walk, excluding those from blocks mentioned in
     327              :      M_VISITED_BLOCKS.  */
     328              :   auto_bitmap m_visited_phis;
     329              : 
     330              :   /* Two bitmaps that can be used for worklists.  The elements represent
     331              :      indices into M_VARS.  */
     332              :   auto_bitmap m_worklist1, m_worklist2;
     333              : 
     334              :   /* Used to perform a double-worklist update.  M_THIS_WORKLIST contains
     335              :      the elements of M_VARS that should be processed in the current pass,
     336              :      whereas M_NEXT_WORKLIST contains the elements of M_VARS that should
     337              :      be processed in the next pass.
     338              : 
     339              :      In a post-order traversal, any member of M_VARS beyond index
     340              :      M_WORKLIST_THRESHOLD can be added to M_THIS_WORKLIST whereas others
     341              :      should be added to M_NEXT_WORKLIST.  */
     342              :   bitmap m_this_worklist, m_next_worklist;
     343              :   unsigned int m_worklist_threshold;
     344              : };
     345              : 
     346      1039731 : backprop::backprop (function *fn)
     347      1039731 :   : m_fn (fn),
     348      1039731 :     m_var_pool ("var_info"),
     349      1039731 :     m_var_table (64),
     350      1039731 :     m_visited_blocks (last_basic_block_for_fn (m_fn)),
     351      1039731 :     m_this_worklist (m_worklist1),
     352      1039731 :     m_next_worklist (m_worklist2),
     353      1039731 :     m_worklist_threshold (UINT_MAX)
     354              : {
     355      1039731 :   bitmap_clear (m_visited_blocks);
     356      1039731 :   bitmap_tree_view (m_worklist1);
     357      1039731 :   bitmap_tree_view (m_worklist2);
     358      1039731 : }
     359              : 
     360      1039731 : backprop::~backprop ()
     361              : {
     362      1039731 :   m_var_pool.release ();
     363      1039731 : }
     364              : 
     365              : /* Return the var_info for general operand OP, or null if none.  */
     366              : 
     367              : var_info *
     368      8367551 : backprop::lookup_operand (tree op)
     369              : {
     370      8367551 :   if (op && TREE_CODE (op) == SSA_NAME)
     371      6616781 :     return m_var_table.find_with_hash (op, SSA_NAME_VERSION (op));
     372              :   return NULL;
     373              : }
     374              : 
     375              : /* Add V to the worklist, if it isn't on the worklist already.  */
     376              : 
     377              : void
     378       898486 : backprop::push_to_worklist (var_info *v)
     379              : {
     380       898486 :   bitmap worklist = (v->index > m_worklist_threshold
     381       898486 :                      ? m_this_worklist
     382              :                      : m_next_worklist);
     383       898486 :   if (bitmap_set_bit (worklist, v->index)
     384       898486 :       && (dump_file && (dump_flags & TDF_DETAILS)))
     385              :     {
     386           36 :       fprintf (dump_file, "[WORKLIST] Pushing ");
     387           36 :       print_generic_expr (dump_file, v->var);
     388           36 :       fprintf (dump_file, "\n");
     389              :     }
     390       898486 : }
     391              : 
     392              : /* Remove and return the next var_info from the worklist.  The worklist
     393              :    is known to be nonempty.  */
     394              : 
     395              : var_info *
     396       886313 : backprop::pop_from_worklist ()
     397              : {
     398       886313 :   m_worklist_threshold = bitmap_clear_first_set_bit (m_this_worklist);
     399       886313 :   var_info *v = m_vars[m_worklist_threshold];
     400       886313 :   if (dump_file && (dump_flags & TDF_DETAILS))
     401              :     {
     402           36 :       fprintf (dump_file, "[WORKLIST] Popping ");
     403           36 :       print_generic_expr (dump_file, v->var);
     404           36 :       fprintf (dump_file, "\n");
     405              :     }
     406       886313 :   return v;
     407              : }
     408              : 
     409              : /* Make INFO describe all uses of RHS in CALL, which is a call to a
     410              :    built-in function.  */
     411              : 
     412              : void
     413      2820475 : backprop::process_builtin_call_use (gcall *call, tree rhs, usage_info *info)
     414              : {
     415      2820475 :   combined_fn fn = gimple_call_combined_fn (call);
     416      2820475 :   tree lhs = gimple_call_lhs (call);
     417      2820475 :   switch (fn)
     418              :     {
     419              :     case CFN_LAST:
     420              :       break;
     421              : 
     422          571 :     CASE_CFN_COS:
     423          571 :     CASE_CFN_COS_FN:
     424          571 :     CASE_CFN_COSH:
     425          571 :     CASE_CFN_COSH_FN:
     426          571 :     CASE_CFN_CCOS:
     427          571 :     CASE_CFN_CCOS_FN:
     428          571 :     CASE_CFN_CCOSH:
     429          571 :     CASE_CFN_CCOSH_FN:
     430          571 :     CASE_CFN_HYPOT:
     431          571 :     CASE_CFN_HYPOT_FN:
     432              :       /* The signs of all inputs are ignored.  */
     433          571 :       info->flags.ignore_sign = true;
     434          571 :       break;
     435              : 
     436        28172 :     CASE_CFN_COPYSIGN:
     437        28172 :     CASE_CFN_COPYSIGN_FN:
     438              :       /* The sign of the first input is ignored.  */
     439        28172 :       if (rhs != gimple_call_arg (call, 1))
     440          591 :         info->flags.ignore_sign = true;
     441              :       break;
     442              : 
     443          564 :     CASE_CFN_POW:
     444          564 :     CASE_CFN_POW_FN:
     445          564 :       {
     446              :         /* The sign of the first input is ignored as long as the second
     447              :            input is an even real.  */
     448          564 :         tree power = gimple_call_arg (call, 1);
     449          564 :         HOST_WIDE_INT n;
     450          564 :         if (TREE_CODE (power) == REAL_CST
     451           63 :             && real_isinteger (&TREE_REAL_CST (power), &n)
     452          597 :             && (n & 1) == 0)
     453           31 :           info->flags.ignore_sign = true;
     454          564 :         break;
     455              :       }
     456              : 
     457          742 :     CASE_CFN_FMA:
     458          742 :     CASE_CFN_FMA_FN:
     459          742 :     case CFN_FMS:
     460          742 :     case CFN_FNMA:
     461          742 :     case CFN_FNMS:
     462              :       /* In X * X + Y, where Y is distinct from X, the sign of X doesn't
     463              :          matter.  */
     464          742 :       if (gimple_call_arg (call, 0) == rhs
     465          307 :           && gimple_call_arg (call, 1) == rhs
     466          796 :           && gimple_call_arg (call, 2) != rhs)
     467           54 :         info->flags.ignore_sign = true;
     468              :       break;
     469              : 
     470       737083 :     default:
     471       737083 :       if (negate_mathfn_p (fn))
     472              :         /* The sign of the (single) input doesn't matter provided
     473              :            that the sign of the output doesn't matter.  */
     474         2577 :         if (var_info *lhsv = lookup_operand (lhs))
     475           46 :           info->flags.ignore_sign = lhsv->info.flags.ignore_sign;
     476              :       break;
     477              :     }
     478      2820475 : }
     479              : 
     480              : /* Make INFO describe all uses of RHS in ASSIGN.  */
     481              : 
     482              : void
     483     12211300 : backprop::process_assign_use (gassign *assign, tree rhs, usage_info *info)
     484              : {
     485     12211300 :   tree lhs = gimple_assign_lhs (assign);
     486     17660857 :   switch (gimple_assign_rhs_code (assign))
     487              :     {
     488        13724 :     case ABS_EXPR:
     489        13724 :     case ABSU_EXPR:
     490              :       /* The sign of the input doesn't matter.  */
     491        13724 :       info->flags.ignore_sign = true;
     492        13724 :       break;
     493              : 
     494         7677 :     case COND_EXPR:
     495              :       /* For A = B ? C : D, propagate information about all uses of A
     496              :          to C and D.  */
     497         7677 :       if (rhs != gimple_assign_rhs1 (assign))
     498         3803 :         if (var_info *lhsv = lookup_operand (lhs))
     499          941 :           *info = lhsv->info;
     500              :       break;
     501              : 
     502       854910 :     case MULT_EXPR:
     503              :       /* In X * X, the sign of X doesn't matter.  */
     504       854910 :       if (gimple_assign_rhs1 (assign) == rhs
     505      1559532 :           && gimple_assign_rhs2 (assign) == rhs)
     506        15110 :         info->flags.ignore_sign = true;
     507              :       /* Fall through.  */
     508              : 
     509       907062 :     case NEGATE_EXPR:
     510       907062 :     case RDIV_EXPR:
     511              :       /* If the sign of the result doesn't matter, the sign of the inputs
     512              :          doesn't matter either.  */
     513       907062 :       if (FLOAT_TYPE_P (TREE_TYPE (rhs)))
     514       139710 :         if (var_info *lhsv = lookup_operand (lhs))
     515         2992 :           info->flags.ignore_sign = lhsv->info.flags.ignore_sign;
     516              :       break;
     517              : 
     518              :     default:
     519              :       break;
     520              :     }
     521     12211300 : }
     522              : 
     523              : /* Make INFO describe the uses of PHI's result.  */
     524              : 
     525              : void
     526      2496883 : backprop::process_phi_use (gphi *phi, usage_info *info)
     527              : {
     528      2496883 :   tree result = gimple_phi_result (phi);
     529      2496883 :   if (var_info *resultv = lookup_operand (result))
     530       228892 :     *info = resultv->info;
     531      2496883 : }
     532              : 
     533              : /* Make INFO describe all uses of RHS in STMT.  */
     534              : 
     535              : void
     536     21801900 : backprop::process_use (gimple *stmt, tree rhs, usage_info *info)
     537              : {
     538     21801900 :   if (dump_file && (dump_flags & TDF_DETAILS))
     539              :     {
     540          244 :       fprintf (dump_file, "[USE] ");
     541          244 :       print_generic_expr (dump_file, rhs);
     542          244 :       fprintf (dump_file, " in ");
     543          244 :       print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
     544              :     }
     545              : 
     546     21801900 :   if (gcall *call = dyn_cast <gcall *> (stmt))
     547      2820475 :     process_builtin_call_use (call, rhs, info);
     548     18981425 :   else if (gassign *assign = dyn_cast <gassign *> (stmt))
     549     12211300 :     process_assign_use (assign, rhs, info);
     550      6770125 :   else if (gphi *phi = dyn_cast <gphi *> (stmt))
     551      2496883 :     process_phi_use (phi, info);
     552              : 
     553     21801900 :   if (dump_file && (dump_flags & TDF_DETAILS))
     554          244 :     dump_usage_info (dump_file, rhs, info);
     555     21801900 : }
     556              : 
     557              : /* Make INFO describe all uses of VAR, returning true if the result
     558              :    is useful.  If the uses include phis that haven't been processed yet,
     559              :    make the most optimistic assumption possible, so that we aim for
     560              :    a maximum rather than a minimum fixed point.  */
     561              : 
     562              : bool
     563     22500420 : backprop::intersect_uses (tree var, usage_info *info)
     564              : {
     565     22500420 :   imm_use_iterator iter;
     566     22500420 :   use_operand_p use_p;
     567     22500420 :   *info = usage_info::intersection_identity ();
     568     49807154 :   FOR_EACH_IMM_USE_FAST (use_p, iter, var)
     569              :     {
     570     26345446 :       gimple *stmt = USE_STMT (use_p);
     571     26345446 :       if (is_gimple_debug (stmt))
     572      3548620 :         continue;
     573     22796826 :       gphi *phi = dyn_cast <gphi *> (stmt);
     574      3491809 :       if (phi
     575      3491809 :           && !bitmap_bit_p (m_visited_blocks, gimple_bb (phi)->index)
     576       998816 :           && !bitmap_bit_p (m_visited_phis,
     577       998816 :                             SSA_NAME_VERSION (gimple_phi_result (phi))))
     578              :         {
     579              :           /* Skip unprocessed phis.  */
     580       994926 :           if (dump_file && (dump_flags & TDF_DETAILS))
     581              :             {
     582           18 :               fprintf (dump_file, "[BACKEDGE] ");
     583           18 :               print_generic_expr (dump_file, var);
     584           18 :               fprintf (dump_file, " in ");
     585           18 :               print_gimple_stmt (dump_file, phi, 0, TDF_SLIM);
     586              :             }
     587              :         }
     588              :       else
     589              :         {
     590     21801900 :           usage_info subinfo;
     591     21801900 :           process_use (stmt, var, &subinfo);
     592     21801900 :           *info &= subinfo;
     593     21801900 :           if (!info->is_useful ())
     594     21539132 :             return false;
     595              :         }
     596     21539132 :     }
     597       961288 :   return true;
     598              : }
     599              : 
     600              : /* Queue for reconsideration any input of STMT that has information
     601              :    associated with it.  This is used if that information might be
     602              :    too optimistic.  */
     603              : 
     604              : void
     605      4523806 : backprop::reprocess_inputs (gimple *stmt)
     606              : {
     607      4523806 :   use_operand_p use_p;
     608      4523806 :   ssa_op_iter oi;
     609     14770026 :   FOR_EACH_PHI_OR_STMT_USE (use_p, stmt, oi, SSA_OP_USE)
     610      5722414 :     if (var_info *v = lookup_operand (get_use_from_ptr (use_p)))
     611       898486 :       push_to_worklist (v);
     612      4523806 : }
     613              : 
     614              : /* Say that we're recording INFO for SSA name VAR, or that we're deleting
     615              :    existing information if INFO is null.  INTRO describes the change.  */
     616              : 
     617              : static void
     618          106 : dump_var_info (tree var, usage_info *info, const char *intro)
     619              : {
     620          106 :   fprintf (dump_file, "[DEF] %s for ", intro);
     621          106 :   print_gimple_stmt (dump_file, SSA_NAME_DEF_STMT (var), 0, TDF_SLIM);
     622          106 :   if (info)
     623           88 :     dump_usage_info (dump_file, var, info);
     624          106 : }
     625              : 
     626              : /* Process all uses of VAR and record or update the result in
     627              :    M_VAR_TABLE and M_VARS.  V is the current entry for VAR, or null
     628              :    if we are looking at it for the first time.  */
     629              : 
     630              : void
     631     22660573 : backprop::process_var (tree var, var_info *v)
     632              : {
     633     22660573 :   if (has_zero_uses (var))
     634       154322 :     return;
     635              : 
     636     22506251 :   usage_info info;
     637              : 
     638              :   /* Propagating along abnormal edges is delicate, punt for now.  */
     639     22506251 :   if (!SSA_NAME_OCCURS_IN_ABNORMAL_PHI (var))
     640     22500420 :     intersect_uses (var, &info);
     641              : 
     642     22506251 :   gimple *stmt = SSA_NAME_DEF_STMT (var);
     643     22506251 :   auto hash = SSA_NAME_VERSION (var);
     644     22506251 :   if (info.is_useful ())
     645              :     {
     646       961288 :       if (!v)
     647              :         {
     648              :           /* Recording information about VAR for the first time.  */
     649      1912052 :           v = m_var_pool.allocate (var, m_vars.length (), info);
     650       956026 :           m_vars.safe_push (v);
     651       956026 :           *m_var_table.find_slot_with_hash (var, hash, INSERT) = v;
     652              : 
     653       956026 :           if (dump_file && (dump_flags & TDF_DETAILS))
     654           82 :             dump_var_info (var, &v->info, "Recording new information");
     655              : 
     656              :           /* If STMT is a phi, reprocess any backedge uses.  This is a
     657              :              no-op for other uses, which won't have any information
     658              :              associated with them.  */
     659       956026 :           if (is_a <gphi *> (stmt))
     660       180713 :             reprocess_inputs (stmt);
     661              :         }
     662         5262 :       else if (info != v->info)
     663              :         {
     664              :           /* Recording information that is less optimistic than before.  */
     665           63 :           gcc_checking_assert ((info & v->info) == info);
     666           63 :           v->info = info;
     667           63 :           if (dump_file && (dump_flags & TDF_DETAILS))
     668            6 :             dump_var_info (var, &v->info, "Updating information");
     669           63 :           reprocess_inputs (stmt);
     670              :         }
     671              :     }
     672              :   else
     673              :     {
     674     21544963 :       if (v)
     675              :         {
     676              :           /* Removing previously-recorded information.  */
     677       881051 :           m_var_table.remove_elt_with_hash (var, hash);
     678       881051 :           m_vars[v->index] = nullptr;
     679       881051 :           m_var_pool.remove (v);
     680              : 
     681       881051 :           if (dump_file && (dump_flags & TDF_DETAILS))
     682           18 :             dump_var_info (var, NULL, "Deleting information");
     683       881051 :           reprocess_inputs (stmt);
     684              :         }
     685              :       else
     686              :         {
     687              :           /* If STMT is a phi, remove any information recorded for
     688              :              its arguments.  */
     689     20663912 :           if (is_a <gphi *> (stmt))
     690      3461979 :             reprocess_inputs (stmt);
     691              :         }
     692              :     }
     693              : }
     694              : 
     695              : /* Process all statements and phis in BB, during the first post-order walk.  */
     696              : 
     697              : void
     698     11381393 : backprop::process_block (basic_block bb)
     699              : {
     700     11381393 :   for (gimple_stmt_iterator gsi = gsi_last_bb (bb); !gsi_end_p (gsi);
     701    183566461 :        gsi_prev (&gsi))
     702              :     {
     703     86092534 :       tree lhs = gimple_get_lhs (gsi_stmt (gsi));
     704     86092534 :       if (lhs && TREE_CODE (lhs) == SSA_NAME)
     705     18119876 :         process_var (lhs, nullptr);
     706              :     }
     707     15035777 :   for (gphi_iterator gpi = gsi_start_phis (bb); !gsi_end_p (gpi);
     708      3654384 :        gsi_next (&gpi))
     709              :     {
     710      3654384 :       tree result = gimple_phi_result (gpi.phi ());
     711      3654384 :       process_var (result, nullptr);
     712      3654384 :       bitmap_set_bit (m_visited_phis, SSA_NAME_VERSION (result));
     713              :     }
     714     11381393 :   bitmap_clear (m_visited_phis);
     715     11381393 : }
     716              : 
     717              : /* Delete the statement at GSI, which is now dead.  Note the deletion in the
     718              :    dump file unless QUIET is true.  */
     719              : 
     720              : static void
     721          191 : remove_dead_stmt (gimple_stmt_iterator *gsi, bool quiet = false)
     722              : {
     723          191 :   gimple *stmt = gsi_stmt (*gsi);
     724          191 :   if (!quiet && dump_file && (dump_flags & TDF_DETAILS))
     725              :     {
     726           28 :       fprintf (dump_file, "Deleting ");
     727           28 :       print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
     728              :     }
     729          191 :   if (gimple_code (stmt) == GIMPLE_PHI)
     730           97 :     remove_phi_node (gsi, true);
     731              :   else
     732              :     {
     733           94 :       unlink_stmt_vdef (stmt);
     734           94 :       gsi_remove (gsi, true);
     735           94 :       release_defs (stmt);
     736              :     }
     737          191 : }
     738              : 
     739              : /* If RHS is an SSA name whose definition just changes the sign of a value,
     740              :    return that other value, otherwise return null.  */
     741              : 
     742              : static tree
     743       152179 : strip_sign_op_1 (tree rhs)
     744              : {
     745       152179 :   if (TREE_CODE (rhs) != SSA_NAME)
     746              :     return NULL_TREE;
     747              : 
     748       151667 :   gimple *def_stmt = SSA_NAME_DEF_STMT (rhs);
     749       151667 :   if (gassign *assign = dyn_cast <gassign *> (def_stmt))
     750       144219 :     switch (gimple_assign_rhs_code (assign))
     751              :       {
     752          280 :       case ABS_EXPR:
     753          280 :       case NEGATE_EXPR:
     754          280 :         return gimple_assign_rhs1 (assign);
     755              : 
     756              :       default:
     757              :         break;
     758              :       }
     759        78901 :   else if (gcall *call = dyn_cast <gcall *> (def_stmt))
     760        39099 :     switch (gimple_call_combined_fn (call))
     761              :       {
     762           13 :       CASE_CFN_COPYSIGN:
     763           13 :       CASE_CFN_COPYSIGN_FN:
     764           13 :         return gimple_call_arg (call, 0);
     765              : 
     766              :       default:
     767              :         break;
     768              :       }
     769              : 
     770              :   return NULL_TREE;
     771              : }
     772              : 
     773              : /* If RHS is an SSA name whose definition just changes the sign of a value,
     774              :    strip all such operations and return the ultimate input to them.
     775              :    Return null otherwise.
     776              : 
     777              :    Although this could in principle lead to quadratic searching,
     778              :    in practice a long sequence of sign manipulations should already
     779              :    have been folded down.  E.g. --x -> x, abs(-x) -> abs(x).  We search
     780              :    for more than one operation in order to catch cases like -abs(x).  */
     781              : 
     782              : static tree
     783       151886 : strip_sign_op (tree rhs)
     784              : {
     785       151886 :   tree new_rhs = strip_sign_op_1 (rhs);
     786       151886 :   if (!new_rhs)
     787              :     return NULL_TREE;
     788          293 :   while (tree next = strip_sign_op_1 (new_rhs))
     789              :     new_rhs = next;
     790              :   return new_rhs;
     791              : }
     792              : 
     793              : /* Note that V's SSA name will be replaced with NEW_VALUE.  */
     794              : 
     795              : void
     796          362 : backprop::set_new_value (var_info *v, tree new_value)
     797              : {
     798          362 :   if (dump_file && (dump_flags & TDF_DETAILS))
     799              :     {
     800           33 :       if (v->var == v->new_value)
     801           30 :         fprintf (dump_file, "\n");
     802           33 :       fprintf (dump_file, "Uses of ");
     803           33 :       print_generic_expr (dump_file, v->var);
     804           33 :       fprintf (dump_file, " will be replaced by ");
     805           33 :       print_generic_expr (dump_file, new_value);
     806           33 :       fprintf (dump_file, "\n");
     807              :     }
     808          362 :   v->new_value = new_value;
     809          362 : }
     810              : 
     811              : /* Apply all current substitutions to gimple operand VALUE.  */
     812              : 
     813              : tree
     814         1216 : backprop::subst_operand (tree value)
     815              : {
     816         1216 :   if (const var_info *v = lookup_operand (value))
     817          509 :     return v->new_value;
     818              : 
     819              :   return value;
     820              : }
     821              : 
     822              : /* Assuming that V's SSA name occurs as "lhs" in a statement of the form:
     823              : 
     824              :       S: lhs = op (rhs1, rhs2, ...)
     825              : 
     826              :    create and insert a new statement:
     827              : 
     828              :       S': lhs'= op (rhs1', rhs2', ...)
     829              : 
     830              :    where:
     831              : 
     832              :       lhs' is a new SSA name
     833              :       rhsN' = subst_operand (rhsN)
     834              : 
     835              :    Arrange for lhs to be replaced with lhs'.
     836              : 
     837              :    Return S'.  After making any required changes to S', the caller should
     838              :    call finish_stmt (V, S') to finish scheduling the replacement.  */
     839              : 
     840              : gimple *
     841          330 : backprop::copy_and_subst (var_info *v)
     842              : {
     843          330 :   gcc_assert (v->new_value == v->var);
     844          330 :   gimple *stmt = SSA_NAME_DEF_STMT (v->var);
     845          330 :   set_new_value (v, copy_ssa_name_fn (m_fn, v->var, stmt));
     846          330 :   if (auto *phi = dyn_cast<gphi *> (stmt))
     847              :     {
     848           70 :       gphi *new_phi = create_phi_node (v->new_value, gimple_bb (phi));
     849           70 :       gimple_set_location (new_phi, gimple_location (phi));
     850          210 :       for (unsigned int i = 0; i < gimple_phi_num_args (phi); ++i)
     851              :         {
     852          140 :           tree arg_def = subst_operand (gimple_phi_arg_def (phi, i));
     853          140 :           SET_USE (gimple_phi_arg_imm_use_ptr (new_phi, i), arg_def);
     854              :         }
     855              :       return new_phi;
     856              :     }
     857              :   else
     858              :     {
     859          260 :       gimple *new_stmt = gimple_copy (stmt);
     860         1048 :       for (unsigned int i = 0; i < gimple_num_ops (new_stmt); ++i)
     861              :         {
     862          788 :           tree *op_ptr = gimple_op_ptr (new_stmt, i);
     863         1576 :           *op_ptr = subst_operand (*op_ptr);
     864              :         }
     865          260 :       SSA_NAME_DEF_STMT (v->new_value) = new_stmt;
     866          260 :       gimple_seq_add_stmt (&v->seq, new_stmt);
     867          260 :       return new_stmt;
     868              :     }
     869              : }
     870              : 
     871              : /* Finalize STMT, whose lhs will replace V's SSA name.  */
     872              : 
     873              : void
     874          330 : backprop::finish_stmt (var_info *v, gimple *stmt)
     875              : {
     876          330 :   if (dump_file && (dump_flags & TDF_DETAILS))
     877              :     {
     878           30 :       fprintf (dump_file, "Replacing ");
     879           30 :       print_gimple_stmt (dump_file, SSA_NAME_DEF_STMT (v->var), TDF_SLIM);
     880           30 :       fprintf (dump_file, "     with ");
     881           30 :       print_gimple_stmt (dump_file, stmt, TDF_SLIM);
     882              :     }
     883          330 :   tree new_value = v->new_value;
     884          330 :   gimple_stmt_iterator gsi;
     885          330 :   if (auto *phi = dyn_cast<gphi *> (stmt))
     886              :     {
     887           70 :       gsi = gsi_for_stmt (phi);
     888           70 :       new_value = degenerate_phi_result (phi);
     889              :     }
     890              :   else
     891              :     {
     892          260 :       gsi = gsi_for_stmt (stmt, &v->seq);
     893          260 :       fold_stmt (&gsi);
     894          260 :       stmt = gsi_stmt (gsi);
     895          260 :       if (gimple_assign_single_p (stmt))
     896            4 :         new_value = gimple_assign_rhs1 (stmt);
     897              :     }
     898          330 :   update_stmt (stmt);
     899          330 :   if (new_value && new_value != v->new_value && is_gimple_val (new_value))
     900              :     {
     901           26 :       remove_dead_stmt (&gsi);
     902           26 :       set_new_value (v, new_value);
     903              :     }
     904          330 : }
     905              : 
     906              : /* Optimize CALL, a call to a built-in function, given that V describes
     907              :    its lhs.  */
     908              : 
     909              : void
     910          327 : backprop::optimize_builtin_call (gcall *call, var_info *v)
     911              : {
     912              :   /* If we have an f such that -f(x) = f(-x), and if the sign of the result
     913              :      doesn't matter, strip any sign operations from the input.  */
     914          327 :   if (v->info.flags.ignore_sign
     915          327 :       && negate_mathfn_p (gimple_call_combined_fn (call)))
     916              :     {
     917           61 :       tree new_arg = strip_sign_op (gimple_call_arg (call, 0));
     918           61 :       if (new_arg)
     919              :         {
     920           24 :           call = as_a<gcall *> (copy_and_subst (v));
     921           48 :           gimple_call_set_arg (call, 0, subst_operand (new_arg));
     922           24 :           finish_stmt (v, call);
     923              :         }
     924              :     }
     925          327 : }
     926              : 
     927              : /* Optimize V by replacing rhs operand N with RHS<N>, if RHS<N> is nonnull.  */
     928              : 
     929              : void
     930          951 : backprop::replace_assign_rhs (var_info *v, tree rhs1, tree rhs2, tree rhs3)
     931              : {
     932          951 :   if (!rhs1 && !rhs2 && !rhs3)
     933              :     return;
     934              : 
     935          198 :   auto *assign = as_a<gassign *> (copy_and_subst (v));
     936          198 :   if (rhs1)
     937          260 :     gimple_assign_set_rhs1 (assign, subst_operand (rhs1));
     938          198 :   if (rhs2)
     939          136 :     gimple_assign_set_rhs2 (assign, subst_operand (rhs2));
     940          198 :   if (rhs3)
     941            0 :     gimple_assign_set_rhs3 (assign, subst_operand (rhs3));
     942          198 :   finish_stmt (v, assign);
     943              : }
     944              : 
     945              : /* Optimize ASSIGN given that V describes its lhs.  */
     946              : 
     947              : void
     948        15267 : backprop::optimize_assign (gassign *assign, var_info *v)
     949              : {
     950        20157 :   switch (gimple_assign_rhs_code (assign))
     951              :     {
     952          951 :     case MULT_EXPR:
     953          951 :     case RDIV_EXPR:
     954              :       /* If the sign of the result doesn't matter, strip sign operations
     955              :          from both inputs.  */
     956          951 :       if (v->info.flags.ignore_sign)
     957         1902 :         replace_assign_rhs (v, strip_sign_op (gimple_assign_rhs1 (assign)),
     958              :                             strip_sign_op (gimple_assign_rhs2 (assign)),
     959              :                             NULL_TREE);
     960              :       break;
     961              : 
     962            0 :     case COND_EXPR:
     963              :       /* If the sign of A ? B : C doesn't matter, strip sign operations
     964              :          from both B and C.  */
     965            0 :       if (v->info.flags.ignore_sign)
     966            0 :         replace_assign_rhs (v, NULL_TREE,
     967              :                             strip_sign_op (gimple_assign_rhs2 (assign)),
     968              :                             strip_sign_op (gimple_assign_rhs3 (assign)));
     969              :       break;
     970              : 
     971              :     default:
     972              :       break;
     973              :     }
     974        15267 : }
     975              : 
     976              : /* Optimize PHI given that V describes its result.  */
     977              : 
     978              : void
     979        59381 : backprop::optimize_phi (gphi *phi, var_info *v)
     980              : {
     981              :   /* If the sign of the result doesn't matter, strip sign operations
     982              :      from all arguments.  */
     983        59381 :   if (v->info.flags.ignore_sign)
     984              :     {
     985              :       gphi *replacement = nullptr;
     986       209304 :       for (unsigned int i = 0; i < gimple_phi_num_args (phi); ++i)
     987              :         {
     988       149923 :           tree arg = gimple_phi_arg_def (phi, i);
     989       149923 :           tree new_arg = strip_sign_op (arg);
     990       149923 :           if (new_arg)
     991              :             {
     992           66 :               if (!replacement)
     993           56 :                 replacement = as_a<gphi *> (copy_and_subst (v));
     994          132 :               SET_USE (gimple_phi_arg_imm_use_ptr (replacement, i),
     995              :                        subst_operand (new_arg));
     996              :             }
     997              :         }
     998        59381 :       if (replacement)
     999           56 :         finish_stmt (v, replacement);
    1000              :     }
    1001        59381 : }
    1002              : 
    1003              : /* V is being replaced with something that may have a different value.
    1004              :    If that would change the result of any dependent statement,
    1005              :    make sure that that dependent statement will also be replaced.  */
    1006              : 
    1007              : void
    1008          330 : backprop::propagate_change (var_info *v)
    1009              : {
    1010          330 :   use_operand_p use_p;
    1011          330 :   imm_use_iterator use_iter;
    1012         1278 :   FOR_EACH_IMM_USE_FAST (use_p, use_iter, v->var)
    1013              :     {
    1014          618 :       tree lhs = gimple_get_lhs (USE_STMT (use_p));
    1015          618 :       if (const var_info *lhsv = lookup_operand (lhs))
    1016          106 :         if (lhsv->new_value == lhsv->var)
    1017           73 :           bitmap_set_bit (m_this_worklist, lhsv->index);
    1018          330 :     }
    1019          330 : }
    1020              : 
    1021              : /* Implement the scheduled replacement for V.  */
    1022              : 
    1023              : void
    1024          330 : backprop::commit_replacement (var_info *v)
    1025              : {
    1026          330 :   if (MAY_HAVE_DEBUG_BIND_STMTS)
    1027          106 :     insert_debug_temp_for_var_def (NULL, v->var);
    1028              : 
    1029          330 :   gimple *stmt = SSA_NAME_DEF_STMT (v->var);
    1030          330 :   use_operand_p use_p;
    1031          330 :   imm_use_iterator iterator;
    1032          968 :   FOR_EACH_IMM_USE_STMT (stmt, iterator, v->var)
    1033              :     {
    1034         1584 :       FOR_EACH_IMM_USE_ON_STMT (use_p, iterator)
    1035          484 :         SET_USE (use_p, v->new_value);
    1036          308 :       update_stmt (stmt);
    1037          330 :     }
    1038              : 
    1039          330 :   gimple_stmt_iterator gsi = gsi_for_stmt (SSA_NAME_DEF_STMT (v->var));
    1040          330 :   if (v->seq)
    1041          256 :     gsi_replace_with_seq_vops (&gsi, v->seq);
    1042              :   else
    1043           74 :     remove_dead_stmt (&gsi, true);
    1044          330 : }
    1045              : 
    1046              : void
    1047      1039731 : backprop::execute ()
    1048              : {
    1049              :   /* Phase 1: Traverse the function, making optimistic assumptions
    1050              :      about any phi whose definition we haven't seen.  Add any variables
    1051              :      that need to be reconsidered to M_NEXT_WORKLIST.  */
    1052      1039731 :   int *postorder = XNEWVEC (int, n_basic_blocks_for_fn (m_fn));
    1053      1039731 :   unsigned int postorder_num = post_order_compute (postorder, false, false);
    1054     12421124 :   for (unsigned int i = 0; i < postorder_num; ++i)
    1055              :     {
    1056     11381393 :       process_block (BASIC_BLOCK_FOR_FN (m_fn, postorder[i]));
    1057     11381393 :       bitmap_set_bit (m_visited_blocks, postorder[i]);
    1058              :     }
    1059      1039731 :   XDELETEVEC (postorder);
    1060              : 
    1061              :   /* Phase 2: Use the initial (perhaps overly optimistic) information
    1062              :      to create a maximal fixed point solution.  Each pass uses a post-order
    1063              :      walk to reduce the number of repeat visits.  */
    1064      1219752 :   while (!bitmap_empty_p (m_next_worklist))
    1065              :     {
    1066       180021 :       std::swap (m_this_worklist, m_next_worklist);
    1067       180021 :       bitmap_clear (m_next_worklist);
    1068       886313 :       do
    1069              :         {
    1070       886313 :           var_info *v = pop_from_worklist ();
    1071       886313 :           process_var (v->var, v);
    1072              :         }
    1073       886313 :       while (!bitmap_empty_p (m_this_worklist));
    1074              :     }
    1075              : 
    1076              :   /* Phase 3: Do a reverse post-order walk, using information about the uses of
    1077              :      SSA names to see whether computing a different value would be simpler and
    1078              :      would have the same effect.  Start to compute the transitive closure of
    1079              :      SSA names whose definitions are due to be replaced with new
    1080              :      calculations.  */
    1081      1039731 :   bitmap_clear (m_this_worklist);
    1082      3035488 :   for (unsigned int i = m_vars.length (); i-- > 0;)
    1083       956026 :     if (var_info *v = m_vars[i])
    1084              :       {
    1085        74975 :         gimple *stmt = SSA_NAME_DEF_STMT (v->var);
    1086        74975 :         if (gcall *call = dyn_cast <gcall *> (stmt))
    1087          327 :           optimize_builtin_call (call, v);
    1088        74648 :         else if (gassign *assign = dyn_cast <gassign *> (stmt))
    1089        15267 :           optimize_assign (assign, v);
    1090        59381 :         else if (gphi *phi = dyn_cast <gphi *> (stmt))
    1091        59381 :           optimize_phi (phi, v);
    1092              : 
    1093        74975 :         if (bitmap_clear_bit (m_this_worklist, v->index))
    1094           50 :           if (v->new_value == v->var)
    1095           32 :             finish_stmt (v, copy_and_subst (v));
    1096              : 
    1097        74975 :         if (v->new_value != v->var)
    1098          310 :           propagate_change (v);
    1099              :       }
    1100              : 
    1101              :   /* Complete the transitive closure started by the previous loop.  */
    1102      1039751 :   while (!bitmap_empty_p (m_this_worklist))
    1103              :     {
    1104           20 :       var_info *v = m_vars[bitmap_clear_last_set_bit (m_this_worklist)];
    1105           20 :       finish_stmt (v, copy_and_subst (v));
    1106           20 :       propagate_change (v);
    1107              :     }
    1108              : 
    1109              :   /* Now that we have a complete set of values that need to change,
    1110              :      calculate the transitive closure of replacement values.  */
    1111      1039731 :   bool changed = false;
    1112      3035488 :   for (unsigned int i = m_vars.length (); i-- > 0;)
    1113       956026 :     if (var_info *v = m_vars[i])
    1114        74975 :       if (v->var != v->new_value)
    1115          330 :         if (var_info *newv = lookup_operand (v->new_value))
    1116              :           {
    1117            6 :             gcc_assert (newv->index > i);
    1118            6 :             if (!changed && dump_file && (dump_flags & TDF_DETAILS))
    1119            0 :               fprintf (dump_file, "\n");
    1120            6 :             set_new_value (v, newv->new_value);
    1121            6 :             changed = true;
    1122              :           }
    1123              : 
    1124      1039731 :   if (dump_file && (dump_flags & TDF_DETAILS))
    1125           21 :     fprintf (dump_file, "\n");
    1126              : 
    1127              :   /* Phase 4: Do a post-order walk, creating debug bind expressions for
    1128              :      SSA names that are about to disappear.  Replace all non-debug uses
    1129              :      of old SSA names with uses of whatever calculation is replacing them.  */
    1130      1995757 :   for (unsigned int i = 0; i < m_vars.length (); ++i)
    1131       956026 :     if (var_info *v = m_vars[i])
    1132        74975 :       if (v->var != v->new_value)
    1133          330 :         commit_replacement (v);
    1134              : 
    1135              :   /* Phase 5: Remove any statements that might have become dead.  */
    1136      1039731 :   auto_bitmap deleted_vars;
    1137      1995757 :   for (unsigned int i = 0; i < m_vars.length (); ++i)
    1138       956026 :     if (var_info *v = m_vars[i])
    1139        74975 :       if (TREE_CODE (v->new_value) == SSA_NAME
    1140        74971 :           && !SSA_NAME_IS_DEFAULT_DEF (v->new_value)
    1141        74956 :           && has_zero_uses (v->new_value)
    1142        75067 :           && bitmap_set_bit (deleted_vars, SSA_NAME_VERSION (v->new_value)))
    1143              :         {
    1144           91 :           gimple *stmt = SSA_NAME_DEF_STMT (v->new_value);
    1145           91 :           gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
    1146           91 :           remove_dead_stmt (&gsi);
    1147              :         }
    1148              : 
    1149      1039731 :   if (dump_file && (dump_flags & TDF_DETAILS))
    1150           21 :     fprintf (dump_file, "\n");
    1151      1039731 : }
    1152              : 
    1153              : const pass_data pass_data_backprop =
    1154              : {
    1155              :   GIMPLE_PASS, /* type */
    1156              :   "backprop", /* name */
    1157              :   OPTGROUP_NONE, /* optinfo_flags */
    1158              :   TV_TREE_BACKPROP, /* tv_id */
    1159              :   ( PROP_cfg | PROP_ssa ), /* properties_required */
    1160              :   0, /* properties_provided */
    1161              :   0, /* properties_destroyed */
    1162              :   0, /* todo_flags_start */
    1163              :   0, /* todo_flags_finish */
    1164              : };
    1165              : 
    1166              : class pass_backprop : public gimple_opt_pass
    1167              : {
    1168              : public:
    1169       298828 :   pass_backprop (gcc::context *ctxt)
    1170       597656 :     : gimple_opt_pass (pass_data_backprop, ctxt)
    1171              :   {}
    1172              : 
    1173              :   /* opt_pass methods: */
    1174            0 :   opt_pass * clone () final override { return new pass_backprop (m_ctxt); }
    1175      1039819 :   bool gate (function *) final override { return flag_ssa_backprop; }
    1176              :   unsigned int execute (function *) final override;
    1177              : 
    1178              : }; // class pass_backprop
    1179              : 
    1180              : unsigned int
    1181      1039731 : pass_backprop::execute (function *fn)
    1182              : {
    1183      1039731 :   backprop (fn).execute ();
    1184      1039731 :   return 0;
    1185              : }
    1186              : 
    1187              : } // anon namespace
    1188              : 
    1189              : gimple_opt_pass *
    1190       298828 : make_pass_backprop (gcc::context *ctxt)
    1191              : {
    1192       298828 :   return new pass_backprop (ctxt);
    1193              : }
        

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.