LCOV - code coverage report
Current view: top level - gcc - cprop.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 95.0 % 756 718
Test Date: 2026-10-17 16:30:31 Functions: 100.0 % 46 46
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /* Global constant/copy propagation for RTL.
       2              :    Copyright (C) 1997-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 it under
       7              : the terms of the GNU General Public License as published by the Free
       8              : Software Foundation; either version 3, or (at your option) any later
       9              : version.
      10              : 
      11              : GCC is distributed in the hope that it will be useful, but WITHOUT ANY
      12              : WARRANTY; without even the implied warranty of MERCHANTABILITY or
      13              : FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
      14              : 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              : #include "config.h"
      21              : #include "system.h"
      22              : #include "coretypes.h"
      23              : #include "backend.h"
      24              : #include "rtl.h"
      25              : #include "rtlanal.h"
      26              : #include "cfghooks.h"
      27              : #include "df.h"
      28              : #include "insn-config.h"
      29              : #include "memmodel.h"
      30              : #include "emit-rtl.h"
      31              : #include "recog.h"
      32              : #include "diagnostic-core.h"
      33              : #include "toplev.h"
      34              : #include "cfgrtl.h"
      35              : #include "cfganal.h"
      36              : #include "lcm.h"
      37              : #include "cfgcleanup.h"
      38              : #include "cselib.h"
      39              : #include "intl.h"
      40              : #include "tree-pass.h"
      41              : #include "dbgcnt.h"
      42              : #include "cfgloop.h"
      43              : #include "gcse.h"
      44              : 
      45              : 
      46              : /* An obstack for our working variables.  */
      47              : static struct obstack cprop_obstack;
      48              : 
      49              : /* Occurrence of an expression.
      50              :    There is one per basic block.  If a pattern appears more than once the
      51              :    last appearance is used.  */
      52              : 
      53              : struct cprop_occr
      54              : {
      55              :   /* Next occurrence of this expression.  */
      56              :   struct cprop_occr *next;
      57              :   /* The insn that computes the expression.  */
      58              :   rtx_insn *insn;
      59              : };
      60              : 
      61              : /* Hash table entry for assignment expressions.  */
      62              : 
      63              : struct cprop_expr
      64              : {
      65              :   /* The expression (DEST := SRC).  */
      66              :   rtx dest;
      67              :   rtx src;
      68              : 
      69              :   /* Index in the available expression bitmaps.  */
      70              :   int bitmap_index;
      71              :   /* Next entry with the same hash.  */
      72              :   struct cprop_expr *next_same_hash;
      73              :   /* List of available occurrence in basic blocks in the function.
      74              :      An "available occurrence" is one that is the last occurrence in the
      75              :      basic block and whose operands are not modified by following statements
      76              :      in the basic block [including this insn].  */
      77              :   struct cprop_occr *avail_occr;
      78              : };
      79              : 
      80              : /* Hash table for copy propagation expressions.
      81              :    Each hash table is an array of buckets.
      82              :    ??? It is known that if it were an array of entries, structure elements
      83              :    `next_same_hash' and `bitmap_index' wouldn't be necessary.  However, it is
      84              :    not clear whether in the final analysis a sufficient amount of memory would
      85              :    be saved as the size of the available expression bitmaps would be larger
      86              :    [one could build a mapping table without holes afterwards though].
      87              :    Someday I'll perform the computation and figure it out.  */
      88              : 
      89              : struct hash_table_d
      90              : {
      91              :   /* The table itself.
      92              :      This is an array of `set_hash_table_size' elements.  */
      93              :   struct cprop_expr **table;
      94              : 
      95              :   /* Size of the hash table, in elements.  */
      96              :   unsigned int size;
      97              : 
      98              :   /* Number of hash table elements.  */
      99              :   unsigned int n_elems;
     100              : };
     101              : 
     102              : /* Copy propagation hash table.  */
     103              : static struct hash_table_d set_hash_table;
     104              : 
     105              : /* Array of implicit set patterns indexed by basic block index.  */
     106              : static rtx *implicit_sets;
     107              : 
     108              : /* Array of indexes of expressions for implicit set patterns indexed by basic
     109              :    block index.  In other words, implicit_set_indexes[i] is the bitmap_index
     110              :    of the expression whose RTX is implicit_sets[i].  */
     111              : static int *implicit_set_indexes;
     112              : 
     113              : /* Bitmap containing one bit for each register in the program.
     114              :    Used when performing GCSE to track which registers have been set since
     115              :    the start or end of the basic block while traversing that block.  */
     116              : static regset reg_set_bitmap;
     117              : 
     118              : /* Various variables for statistics gathering.  */
     119              : 
     120              : /* Memory used in a pass.
     121              :    This isn't intended to be absolutely precise.  Its intent is only
     122              :    to keep an eye on memory usage.  */
     123              : static int bytes_used;
     124              : 
     125              : /* Number of local constants propagated.  */
     126              : static int local_const_prop_count;
     127              : /* Number of local copies propagated.  */
     128              : static int local_copy_prop_count;
     129              : /* Number of global constants propagated.  */
     130              : static int global_const_prop_count;
     131              : /* Number of global copies propagated.  */
     132              : static int global_copy_prop_count;
     133              : 
     134              : #define GOBNEW(T)               ((T *) cprop_alloc (sizeof (T)))
     135              : #define GOBNEWVAR(T, S)         ((T *) cprop_alloc ((S)))
     136              : 
     137              : /* Cover function to obstack_alloc.  */
     138              : 
     139              : static void *
     140     31278408 : cprop_alloc (unsigned long size)
     141              : {
     142     31278408 :   bytes_used += size;
     143     31278408 :   return obstack_alloc (&cprop_obstack, size);
     144              : }
     145              : 
     146              : /* Return true if register X is unchanged from INSN to the end
     147              :    of INSN's basic block.  */
     148              : 
     149              : static bool
     150     71214272 : reg_available_p (const_rtx x, const rtx_insn *insn ATTRIBUTE_UNUSED)
     151              : {
     152      2757427 :   return ! REGNO_REG_SET_P (reg_set_bitmap, REGNO (x));
     153              : }
     154              : 
     155              : /* Hash a set of register REGNO.
     156              : 
     157              :    Sets are hashed on the register that is set.  This simplifies the PRE copy
     158              :    propagation code.
     159              : 
     160              :    ??? May need to make things more elaborate.  Later, as necessary.  */
     161              : 
     162              : static unsigned int
     163    117766611 : hash_mod (int regno, int hash_table_size)
     164              : {
     165    117766611 :   return (unsigned) regno % hash_table_size;
     166              : }
     167              : 
     168              : /* Insert assignment DEST:=SET from INSN in the hash table.
     169              :    DEST is a register and SET is a register or a suitable constant.
     170              :    If the assignment is already present in the table, record it as
     171              :    the last occurrence in INSN's basic block.
     172              :    IMPLICIT is true if it's an implicit set, false otherwise.  */
     173              : 
     174              : static void
     175     16570780 : insert_set_in_table (rtx dest, rtx src, rtx_insn *insn,
     176              :                      struct hash_table_d *table, bool implicit)
     177              : {
     178     16570780 :   bool found = false;
     179     16570780 :   unsigned int hash;
     180     16570780 :   struct cprop_expr *cur_expr, *last_expr = NULL;
     181     16570780 :   struct cprop_occr *cur_occr;
     182              : 
     183     16570780 :   hash = hash_mod (REGNO (dest), table->size);
     184              : 
     185     39152055 :   for (cur_expr = table->table[hash]; cur_expr;
     186     22581275 :        cur_expr = cur_expr->next_same_hash)
     187              :     {
     188     24444427 :       if (dest == cur_expr->dest
     189     23908820 :           && src == cur_expr->src)
     190              :         {
     191              :           found = true;
     192              :           break;
     193              :         }
     194     22581275 :       last_expr = cur_expr;
     195              :     }
     196              : 
     197     16570780 :   if (! found)
     198              :     {
     199     14707628 :       cur_expr = GOBNEW (struct cprop_expr);
     200     14707628 :       bytes_used += sizeof (struct cprop_expr);
     201     14707628 :       if (table->table[hash] == NULL)
     202              :         /* This is the first pattern that hashed to this index.  */
     203     11705450 :         table->table[hash] = cur_expr;
     204              :       else
     205              :         /* Add EXPR to end of this hash chain.  */
     206      3002178 :         last_expr->next_same_hash = cur_expr;
     207              : 
     208              :       /* Set the fields of the expr element.
     209              :          We must copy X because it can be modified when copy propagation is
     210              :          performed on its operands.  */
     211     14707628 :       cur_expr->dest = copy_rtx (dest);
     212     14707628 :       cur_expr->src = copy_rtx (src);
     213     14707628 :       cur_expr->bitmap_index = table->n_elems++;
     214     14707628 :       cur_expr->next_same_hash = NULL;
     215     14707628 :       cur_expr->avail_occr = NULL;
     216              :     }
     217              : 
     218              :   /* Now record the occurrence.  */
     219     16570780 :   cur_occr = cur_expr->avail_occr;
     220              : 
     221     16570780 :   if (cur_occr
     222     16570780 :       && BLOCK_FOR_INSN (cur_occr->insn) == BLOCK_FOR_INSN (insn))
     223              :     {
     224              :       /* Found another instance of the expression in the same basic block.
     225              :          Prefer this occurrence to the currently recorded one.  We want
     226              :          the last one in the block and the block is scanned from start
     227              :          to end.  */
     228            0 :       cur_occr->insn = insn;
     229              :     }
     230              :   else
     231              :     {
     232              :       /* First occurrence of this expression in this basic block.  */
     233     16570780 :       cur_occr = GOBNEW (struct cprop_occr);
     234     16570780 :       bytes_used += sizeof (struct cprop_occr);
     235     16570780 :       cur_occr->insn = insn;
     236     16570780 :       cur_occr->next = cur_expr->avail_occr;
     237     16570780 :       cur_expr->avail_occr = cur_occr;
     238              :     }
     239              : 
     240              :   /* Record bitmap_index of the implicit set in implicit_set_indexes.  */
     241     16570780 :   if (implicit)
     242      6473123 :     implicit_set_indexes[BLOCK_FOR_INSN (insn)->index]
     243      6473123 :       = cur_expr->bitmap_index;
     244     16570780 : }
     245              : 
     246              : /* Determine whether the rtx X should be treated as a constant for CPROP.
     247              :    Since X might be inserted more than once we have to take care that it
     248              :    is sharable.  */
     249              : 
     250              : static bool
     251    219876306 : cprop_constant_p (const_rtx x)
     252              : {
     253    219876306 :   return CONSTANT_P (x) && (GET_CODE (x) != CONST || shared_const_p (x));
     254              : }
     255              : 
     256              : /* Determine whether the rtx X should be treated as a register that can
     257              :    be propagated.  Any pseudo-register is fine.  */
     258              : 
     259              : static bool
     260    563093628 : cprop_reg_p (const_rtx x)
     261              : {
     262    415175418 :   return REG_P (x) && !HARD_REGISTER_P (x);
     263              : }
     264              : 
     265              : /* Scan SET present in INSN and add an entry to the hash TABLE.
     266              :    IMPLICIT is true if it's an implicit set, false otherwise.  */
     267              : 
     268              : static void
     269    152663257 : hash_scan_set (rtx set, rtx_insn *insn, struct hash_table_d *table,
     270              :                bool implicit)
     271              : {
     272    152663257 :   rtx src = SET_SRC (set);
     273    152663257 :   rtx dest = SET_DEST (set);
     274              : 
     275    221120102 :   if (cprop_reg_p (dest)
     276     68456845 :       && reg_available_p (dest, insn)
     277     67872293 :       && can_copy_p (GET_MODE (dest)))
     278              :     {
     279              :       /* See if a REG_EQUAL note shows this equivalent to a simpler expression.
     280              : 
     281              :          This allows us to do a single CPROP pass and still eliminate
     282              :          redundant constants, addresses or other expressions that are
     283              :          constructed with multiple instructions.
     284              : 
     285              :          However, keep the original SRC if INSN is a simple reg-reg move.  In
     286              :          In this case, there will almost always be a REG_EQUAL note on the
     287              :          insn that sets SRC.  By recording the REG_EQUAL value here as SRC
     288              :          for INSN, we miss copy propagation opportunities.
     289              : 
     290              :          Note that this does not impede profitable constant propagations.  We
     291              :          "look through" reg-reg sets in lookup_set.  */
     292     67872293 :       rtx note = find_reg_equal_equiv_note (insn);
     293     67872293 :       if (note != 0
     294      4442921 :           && REG_NOTE_KIND (note) == REG_EQUAL
     295      4004798 :           && !REG_P (src)
     296     71573458 :           && cprop_constant_p (XEXP (note, 0)))
     297      1741933 :         src = XEXP (note, 0), set = gen_rtx_SET (dest, src);
     298              : 
     299              :       /* Record sets for constant/copy propagation.  */
     300     67872293 :       if ((cprop_reg_p (src)
     301      2757427 :            && src != dest
     302      2757427 :            && reg_available_p (src, insn))
     303     65271076 :           || cprop_constant_p (src))
     304     16570780 :         insert_set_in_table (dest, src, insn, table, implicit);
     305              :     }
     306    152663257 : }
     307              : 
     308              : /* Process INSN and add hash table entries as appropriate.  */
     309              : 
     310              : static void
     311    153389774 : hash_scan_insn (rtx_insn *insn, struct hash_table_d *table)
     312              : {
     313    153389774 :   rtx pat = PATTERN (insn);
     314    153389774 :   int i;
     315              : 
     316              :   /* Pick out the sets of INSN and for other forms of instructions record
     317              :      what's been modified.  */
     318              : 
     319    153389774 :   if (GET_CODE (pat) == SET)
     320    121509611 :     hash_scan_set (pat, insn, table, false);
     321     31880163 :   else if (GET_CODE (pat) == PARALLEL)
     322     72682461 :     for (i = 0; i < XVECLEN (pat, 0); i++)
     323              :       {
     324     48790816 :         rtx x = XVECEXP (pat, 0, i);
     325              : 
     326     48790816 :         if (GET_CODE (x) == SET)
     327     24603147 :           hash_scan_set (x, insn, table, false);
     328              :       }
     329    153389774 : }
     330              : 
     331              : /* Dump the hash table TABLE to file FILE under the name NAME.  */
     332              : 
     333              : static void
     334           64 : dump_hash_table (FILE *file, const char *name, struct hash_table_d *table)
     335              : {
     336           64 :   int i;
     337              :   /* Flattened out table, so it's printed in proper order.  */
     338           64 :   struct cprop_expr **flat_table;
     339           64 :   unsigned int *hash_val;
     340           64 :   struct cprop_expr *expr;
     341              : 
     342           64 :   flat_table = XCNEWVEC (struct cprop_expr *, table->n_elems);
     343           64 :   hash_val = XNEWVEC (unsigned int, table->n_elems);
     344              : 
     345         1354 :   for (i = 0; i < (int) table->size; i++)
     346         1361 :     for (expr = table->table[i]; expr != NULL; expr = expr->next_same_hash)
     347              :       {
     348          135 :         flat_table[expr->bitmap_index] = expr;
     349          135 :         hash_val[expr->bitmap_index] = i;
     350              :       }
     351              : 
     352           64 :   fprintf (file, "%s hash table (%d buckets, %d entries)\n",
     353              :            name, table->size, table->n_elems);
     354              : 
     355          263 :   for (i = 0; i < (int) table->n_elems; i++)
     356          135 :     if (flat_table[i] != 0)
     357              :       {
     358          135 :         expr = flat_table[i];
     359          135 :         fprintf (file, "Index %d (hash value %d)\n  ",
     360          135 :                  expr->bitmap_index, hash_val[i]);
     361          135 :         print_rtl (file, expr->dest);
     362          135 :         fprintf (file, " := ");
     363          135 :         print_rtl (file, expr->src);
     364          135 :         fprintf (file, "\n");
     365              :       }
     366              : 
     367           64 :   fprintf (file, "\n");
     368              : 
     369           64 :   free (flat_table);
     370           64 :   free (hash_val);
     371           64 : }
     372              : 
     373              : /* Record as unavailable all registers that are DEF operands of INSN.  */
     374              : 
     375              : static void
     376    153389774 : make_set_regs_unavailable (rtx_insn *insn)
     377              : {
     378    153389774 :   df_ref def;
     379              : 
     380   1300958886 :   FOR_EACH_INSN_DEF (def, insn)
     381   1147569112 :     SET_REGNO_REG_SET (reg_set_bitmap, DF_REF_REGNO (def));
     382    153389774 : }
     383              : 
     384              : /* Top level function to create an assignment hash table.
     385              : 
     386              :    Assignment entries are placed in the hash table if
     387              :    - they are of the form (set (pseudo-reg) src),
     388              :    - src is something we want to perform const/copy propagation on,
     389              :    - none of the operands or target are subsequently modified in the block
     390              : 
     391              :    Currently src must be a pseudo-reg or a const_int.
     392              : 
     393              :    TABLE is the table computed.  */
     394              : 
     395              : static void
     396      1548784 : compute_hash_table_work (struct hash_table_d *table)
     397              : {
     398      1548784 :   basic_block bb;
     399              : 
     400              :   /* Allocate vars to track sets of regs.  */
     401      1548784 :   reg_set_bitmap = ALLOC_REG_SET (NULL);
     402              : 
     403     34118751 :   FOR_EACH_BB_FN (bb, cfun)
     404              :     {
     405     32569967 :       rtx_insn *insn;
     406              : 
     407              :       /* Reset tables used to keep track of what's not yet invalid [since
     408              :          the end of the block].  */
     409     32569967 :       CLEAR_REG_SET (reg_set_bitmap);
     410              : 
     411              :       /* Go over all insns from the last to the first.  This is convenient
     412              :          for tracking available registers, i.e. not set between INSN and
     413              :          the end of the basic block BB.  */
     414    395912996 :       FOR_BB_INSNS_REVERSE (bb, insn)
     415              :         {
     416              :           /* Only real insns are interesting.  */
     417    363343029 :           if (!NONDEBUG_INSN_P (insn))
     418    209953255 :             continue;
     419              : 
     420              :           /* Record interesting sets from INSN in the hash table.  */
     421    153389774 :           hash_scan_insn (insn, table);
     422              : 
     423              :           /* Any registers set in INSN will make SETs above it not AVAIL.  */
     424    153389774 :           make_set_regs_unavailable (insn);
     425              :         }
     426              : 
     427              :       /* Insert implicit sets in the hash table, pretending they appear as
     428              :          insns at the head of the basic block.  */
     429     32569967 :       if (implicit_sets[bb->index] != NULL_RTX)
     430      6550499 :         hash_scan_set (implicit_sets[bb->index], BB_HEAD (bb), table, true);
     431              :     }
     432              : 
     433      1548784 :   FREE_REG_SET (reg_set_bitmap);
     434      1548784 : }
     435              : 
     436              : /* Allocate space for the set/expr hash TABLE.
     437              :    It is used to determine the number of buckets to use.  */
     438              : 
     439              : static void
     440      1548784 : alloc_hash_table (struct hash_table_d *table)
     441              : {
     442      1548784 :   int n;
     443              : 
     444      1548784 :   n = get_max_insn_count ();
     445              : 
     446      1548784 :   table->size = n / 4;
     447      1548784 :   if (table->size < 11)
     448       567422 :     table->size = 11;
     449              : 
     450              :   /* Attempt to maintain efficient use of hash table.
     451              :      Making it an odd number is simplest for now.
     452              :      ??? Later take some measurements.  */
     453      1548784 :   table->size |= 1;
     454      1548784 :   n = table->size * sizeof (struct cprop_expr *);
     455      1548784 :   table->table = XNEWVAR (struct cprop_expr *, n);
     456      1548784 : }
     457              : 
     458              : /* Free things allocated by alloc_hash_table.  */
     459              : 
     460              : static void
     461      1548784 : free_hash_table (struct hash_table_d *table)
     462              : {
     463      1548784 :   free (table->table);
     464            0 : }
     465              : 
     466              : /* Compute the hash TABLE for doing copy/const propagation or
     467              :    expression hash table.  */
     468              : 
     469              : static void
     470      1548784 : compute_hash_table (struct hash_table_d *table)
     471              : {
     472              :   /* Initialize count of number of entries in hash table.  */
     473      1548784 :   table->n_elems = 0;
     474      1548784 :   memset (table->table, 0, table->size * sizeof (struct cprop_expr *));
     475              : 
     476      1548784 :   compute_hash_table_work (table);
     477      1548784 : }
     478              : 
     479              : /* Expression tracking support.  */
     480              : 
     481              : /* Lookup REGNO in the set TABLE.  The result is a pointer to the
     482              :    table entry, or NULL if not found.  */
     483              : 
     484              : static struct cprop_expr *
     485    101195831 : lookup_set (unsigned int regno, struct hash_table_d *table)
     486              : {
     487    101195831 :   unsigned int hash = hash_mod (regno, table->size);
     488    101195831 :   struct cprop_expr *expr;
     489              : 
     490    101195831 :   expr = table->table[hash];
     491              : 
     492    109662865 :   while (expr && REGNO (expr->dest) != regno)
     493      8467034 :     expr = expr->next_same_hash;
     494              : 
     495    101195831 :   return expr;
     496              : }
     497              : 
     498              : /* Return the next entry for REGNO in list EXPR.  */
     499              : 
     500              : static struct cprop_expr *
     501            0 : next_set (unsigned int regno, struct cprop_expr *expr)
     502              : {
     503     44211828 :   do
     504     44211828 :     expr = expr->next_same_hash;
     505     87509594 :   while (expr && REGNO (expr->dest) != regno);
     506              : 
     507            0 :   return expr;
     508              : }
     509              : 
     510              : /* Reset tables used to keep track of what's still available [since the
     511              :    start of the block].  */
     512              : 
     513              : static void
     514     30487069 : reset_opr_set_tables (void)
     515              : {
     516              :   /* Maintain a bitmap of which regs have been set since beginning of
     517              :      the block.  */
     518            0 :   CLEAR_REG_SET (reg_set_bitmap);
     519            0 : }
     520              : 
     521              : /* Return true if the register X has not been set yet [since the
     522              :    start of the basic block containing INSN].  */
     523              : 
     524              : static bool
     525    176518358 : reg_not_set_p (const_rtx x, const rtx_insn *insn ATTRIBUTE_UNUSED)
     526              : {
     527            0 :   return ! REGNO_REG_SET_P (reg_set_bitmap, REGNO (x));
     528              : }
     529              : 
     530              : /* Record things set by INSN.
     531              :    This data is used by reg_not_set_p.  */
     532              : 
     533              : static void
     534    283140963 : mark_oprs_set (rtx_insn *insn)
     535              : {
     536    283140963 :   df_ref def;
     537              : 
     538   1312609482 :   FOR_EACH_INSN_DEF (def, insn)
     539   1029468519 :     SET_REGNO_REG_SET (reg_set_bitmap, DF_REF_REGNO (def));
     540    283140963 : }
     541              : 
     542              : /* Compute copy/constant propagation working variables.  */
     543              : 
     544              : /* Local properties of assignments.  */
     545              : static sbitmap *cprop_avloc;
     546              : static sbitmap *cprop_kill;
     547              : 
     548              : /* Global properties of assignments (computed from the local properties).  */
     549              : static sbitmap *cprop_avin;
     550              : static sbitmap *cprop_avout;
     551              : 
     552              : /* Allocate vars used for copy/const propagation.  N_BLOCKS is the number of
     553              :    basic blocks.  N_SETS is the number of sets.  */
     554              : 
     555              : static void
     556      1396900 : alloc_cprop_mem (int n_blocks, int n_sets)
     557              : {
     558      1396900 :   cprop_avloc = sbitmap_vector_alloc (n_blocks, n_sets);
     559      1396900 :   cprop_kill = sbitmap_vector_alloc (n_blocks, n_sets);
     560              : 
     561      1396900 :   cprop_avin = sbitmap_vector_alloc (n_blocks, n_sets);
     562      1396900 :   cprop_avout = sbitmap_vector_alloc (n_blocks, n_sets);
     563      1396900 : }
     564              : 
     565              : /* Free vars used by copy/const propagation.  */
     566              : 
     567              : static void
     568      1396900 : free_cprop_mem (void)
     569              : {
     570      1396900 :   sbitmap_vector_free (cprop_avloc);
     571      1396900 :   sbitmap_vector_free (cprop_kill);
     572      1396900 :   sbitmap_vector_free (cprop_avin);
     573      1396900 :   sbitmap_vector_free (cprop_avout);
     574      1396900 : }
     575              : 
     576              : /* Compute the local properties of each recorded expression.
     577              : 
     578              :    Local properties are those that are defined by the block, irrespective of
     579              :    other blocks.
     580              : 
     581              :    An expression is killed in a block if its operands, either DEST or SRC, are
     582              :    modified in the block.
     583              : 
     584              :    An expression is computed (locally available) in a block if it is computed
     585              :    at least once and expression would contain the same value if the
     586              :    computation was moved to the end of the block.
     587              : 
     588              :    KILL and COMP are destination sbitmaps for recording local properties.  */
     589              : 
     590              : static void
     591      1396900 : compute_local_properties (sbitmap *kill, sbitmap *comp,
     592              :                           struct hash_table_d *table)
     593              : {
     594      1396900 :   unsigned int i;
     595              : 
     596              :   /* Initialize the bitmaps that were passed in.  */
     597      1396900 :   bitmap_vector_clear (kill, last_basic_block_for_fn (cfun));
     598      1396900 :   bitmap_vector_clear (comp, last_basic_block_for_fn (cfun));
     599              : 
     600     70614626 :   for (i = 0; i < table->size; i++)
     601              :     {
     602     67820826 :       struct cprop_expr *expr;
     603              : 
     604     82528454 :       for (expr = table->table[i]; expr != NULL; expr = expr->next_same_hash)
     605              :         {
     606     14707628 :           int indx = expr->bitmap_index;
     607     14707628 :           df_ref def;
     608     14707628 :           struct cprop_occr *occr;
     609              : 
     610              :           /* For each definition of the destination pseudo-reg, the expression
     611              :              is killed in the block where the definition is.  */
     612     14707628 :           for (def = DF_REG_DEF_CHAIN (REGNO (expr->dest));
     613     81731739 :                def; def = DF_REF_NEXT_REG (def))
     614     67024111 :             bitmap_set_bit (kill[DF_REF_BB (def)->index], indx);
     615              : 
     616              :           /* If the source is a pseudo-reg, for each definition of the source,
     617              :              the expression is killed in the block where the definition is.  */
     618     14707628 :           if (REG_P (expr->src))
     619      2389305 :             for (def = DF_REG_DEF_CHAIN (REGNO (expr->src));
     620      6749240 :                  def; def = DF_REF_NEXT_REG (def))
     621      4359935 :               bitmap_set_bit (kill[DF_REF_BB (def)->index], indx);
     622              : 
     623              :           /* The occurrences recorded in avail_occr are exactly those that
     624              :              are locally available in the block where they are.  */
     625     31278408 :           for (occr = expr->avail_occr; occr != NULL; occr = occr->next)
     626              :             {
     627     16570780 :               bitmap_set_bit (comp[BLOCK_FOR_INSN (occr->insn)->index], indx);
     628              :             }
     629              :         }
     630              :     }
     631      1396900 : }
     632              : 
     633              : /* Hash table support.  */
     634              : 
     635              : /* Top level routine to do the dataflow analysis needed by copy/const
     636              :    propagation.  */
     637              : 
     638              : static void
     639      1396900 : compute_cprop_data (void)
     640              : {
     641      1396900 :   basic_block bb;
     642              : 
     643      1396900 :   compute_local_properties (cprop_kill, cprop_avloc, &set_hash_table);
     644      1396900 :   compute_available (cprop_avloc, cprop_kill, cprop_avout, cprop_avin);
     645              : 
     646              :   /* Merge implicit sets into CPROP_AVIN.  They are always available at the
     647              :      entry of their basic block.  We need to do this because 1) implicit sets
     648              :      aren't recorded for the local pass so they cannot be propagated within
     649              :      their basic block by this pass and 2) the global pass would otherwise
     650              :      propagate them only in the successors of their basic block.  */
     651     33280869 :   FOR_EACH_BB_FN (bb, cfun)
     652              :     {
     653     31883969 :       int index = implicit_set_indexes[bb->index];
     654     31883969 :       if (index != -1)
     655      6473123 :         bitmap_set_bit (cprop_avin[bb->index], index);
     656              :     }
     657      1396900 : }
     658              : 
     659              : /* Copy/constant propagation.  */
     660              : 
     661              : /* Maximum number of register uses in an insn that we handle.  */
     662              : #define MAX_USES 8
     663              : 
     664              : /* Table of uses (registers, both hard and pseudo) found in an insn.
     665              :    Allocated statically to avoid alloc/free complexity and overhead.  */
     666              : static rtx reg_use_table[MAX_USES];
     667              : 
     668              : /* Index into `reg_use_table' while building it.  */
     669              : static unsigned reg_use_count;
     670              : 
     671              : /* Set up a list of register numbers used in INSN.  The found uses are stored
     672              :    in `reg_use_table'.  `reg_use_count' is initialized to zero before entry,
     673              :    and contains the number of uses in the table upon exit.
     674              : 
     675              :    ??? If a register appears multiple times we will record it multiple times.
     676              :    This doesn't hurt anything but it will slow things down.  */
     677              : 
     678              : static void
     679   1223415311 : find_used_regs (rtx *xptr, void *data ATTRIBUTE_UNUSED)
     680              : {
     681   1223415311 :   int i, j;
     682   1223415311 :   enum rtx_code code;
     683   1223415311 :   const char *fmt;
     684   1223415311 :   rtx x = *xptr;
     685              : 
     686              :   /* repeat is used to turn tail-recursion into iteration since GCC
     687              :      can't do it when there's no return value.  */
     688   1705107584 :  repeat:
     689   1705107584 :   if (x == 0)
     690              :     return;
     691              : 
     692   1705107584 :   code = GET_CODE (x);
     693   1705107584 :   if (REG_P (x))
     694              :     {
     695    371609925 :       if (reg_use_count == MAX_USES)
     696              :         return;
     697              : 
     698    371584423 :       reg_use_table[reg_use_count] = x;
     699    371584423 :       reg_use_count++;
     700              :     }
     701              : 
     702              :   /* Recursively scan the operands of this expression.  */
     703              : 
     704   3526562054 :   for (i = GET_RTX_LENGTH (code) - 1, fmt = GET_RTX_FORMAT (code); i >= 0; i--)
     705              :     {
     706   2303172245 :       if (fmt[i] == 'e')
     707              :         {
     708              :           /* If we are about to do the last recursive call
     709              :              needed at this level, change it into iteration.
     710              :              This function is called enough to be worth it.  */
     711   1023022356 :           if (i == 0)
     712              :             {
     713    481692273 :               x = XEXP (x, 0);
     714    481692273 :               goto repeat;
     715              :             }
     716              : 
     717    541330083 :           find_used_regs (&XEXP (x, i), data);
     718              :         }
     719   1280149889 :       else if (fmt[i] == 'E')
     720     34250915 :         for (j = 0; j < XVECLEN (x, i); j++)
     721     24930173 :           find_used_regs (&XVECEXP (x, i, j), data);
     722              :     }
     723              : }
     724              : 
     725              : /* Try to replace all uses of FROM in INSN with TO.
     726              :    Return true if successful.  */
     727              : 
     728              : static bool
     729      7998137 : try_replace_reg (rtx from, rtx to, rtx_insn *insn)
     730              : {
     731      7998137 :   rtx note = find_reg_equal_equiv_note (insn);
     732      7998137 :   rtx src = 0;
     733      7998137 :   bool success = false;
     734      7998137 :   rtx set = single_set (insn);
     735              : 
     736      7998137 :   bool check_rtx_costs = true;
     737      7998137 :   bool speed = optimize_bb_for_speed_p (BLOCK_FOR_INSN (insn));
     738      7998137 :   int old_cost = set ? set_rtx_cost (set, speed) : 0;
     739              : 
     740      7416675 :   if (!set
     741      7416675 :       || CONSTANT_P (SET_SRC (set))
     742      7383095 :       || (note != 0
     743      2813752 :           && REG_NOTE_KIND (note) == REG_EQUAL
     744      2813752 :           && (GET_CODE (XEXP (note, 0)) == CONST
     745      2803348 :               || CONSTANT_P (XEXP (note, 0)))))
     746              :     check_rtx_costs = false;
     747              : 
     748              :   /* Usually we substitute easy stuff, so we won't copy everything.
     749              :      We however need to take care to not duplicate non-trivial CONST
     750              :      expressions.  */
     751      7998137 :   to = copy_rtx (to);
     752              : 
     753      7998137 :   validate_replace_src_group (from, to, insn);
     754              : 
     755              :   /* If TO is a constant, check the cost of the set after propagation
     756              :      to the cost of the set before the propagation.  If the cost is
     757              :      higher, then do not replace FROM with TO.  */
     758              : 
     759      7998137 :   if (check_rtx_costs
     760      6529881 :       && CONSTANT_P (to)
     761     12351207 :       && set_rtx_cost (set, speed) > old_cost)
     762              :     {
     763      3080369 :       cancel_changes (0);
     764      3080369 :       return false;
     765              :     }
     766              : 
     767              : 
     768      4917768 :   if (num_changes_pending () && apply_change_group ())
     769              :     success = true;
     770              : 
     771              :   /* Try to simplify SET_SRC if we have substituted a constant.  */
     772      4917768 :   if (success && set && CONSTANT_P (to))
     773              :     {
     774       375405 :       src = simplify_rtx (SET_SRC (set));
     775              : 
     776       375405 :       if (src)
     777         6364 :         validate_change (insn, &SET_SRC (set), src, 0);
     778              :     }
     779              : 
     780              :   /* If there is already a REG_EQUAL note, update the expression in it
     781              :      with our replacement.  */
     782      4917768 :   if (note != 0 && REG_NOTE_KIND (note) == REG_EQUAL)
     783      2269470 :     set_unique_reg_note (insn, REG_EQUAL,
     784              :                          simplify_replace_rtx (XEXP (note, 0), from, to));
     785      4917768 :   if (!success && set && reg_mentioned_p (from, SET_SRC (set)))
     786              :     {
     787              :       /* If above failed and this is a single set, try to simplify the source
     788              :          of the set given our substitution.  We could perhaps try this for
     789              :          multiple SETs, but it probably won't buy us anything.  */
     790      1655350 :       src = simplify_replace_rtx (SET_SRC (set), from, to);
     791              : 
     792      1655350 :       if (!rtx_equal_p (src, SET_SRC (set))
     793      1655350 :           && validate_change (insn, &SET_SRC (set), src, 0))
     794              :         success = true;
     795              : 
     796              :       /* If we've failed perform the replacement, have a single SET to
     797              :          a REG destination and don't yet have a note, add a REG_EQUAL note
     798              :          to not lose information.  */
     799       169908 :       if (!success && note == 0 && set != 0 && REG_P (SET_DEST (set))
     800      1821864 :           && !contains_paradoxical_subreg_p (SET_SRC (set)))
     801       149828 :         note = set_unique_reg_note (insn, REG_EQUAL, copy_rtx (src));
     802              :     }
     803              : 
     804      4917768 :   if (set && MEM_P (SET_DEST (set)) && reg_mentioned_p (from, SET_DEST (set)))
     805              :     {
     806              :       /* Registers can also appear as uses in SET_DEST if it is a MEM.
     807              :          We could perhaps try this for multiple SETs, but it probably
     808              :          won't buy us anything.  */
     809         3601 :       rtx dest = simplify_replace_rtx (SET_DEST (set), from, to);
     810              : 
     811         3601 :       if (!rtx_equal_p (dest, SET_DEST (set))
     812         3601 :           && validate_change (insn, &SET_DEST (set), dest, 0))
     813              :         success = true;
     814              :     }
     815              : 
     816              :   /* REG_EQUAL may get simplified into register.
     817              :      We don't allow that. Remove that note. This code ought
     818              :      not to happen, because previous code ought to synthesize
     819              :      reg-reg move, but be on the safe side.  */
     820      4917768 :   if (note && REG_NOTE_KIND (note) == REG_EQUAL && REG_P (XEXP (note, 0)))
     821            0 :     remove_note (insn, note);
     822              : 
     823              :   return success;
     824              : }
     825              : 
     826              : /* Find a set of REGNOs that are available on entry to INSN's block.  If found,
     827              :    SET_RET[0] will be assigned a set with a register source and SET_RET[1] a
     828              :    set with a constant source.  If not found the corresponding entry is set to
     829              :    NULL.  */
     830              : 
     831              : static void
     832     98252809 : find_avail_set (int regno, rtx_insn *insn, struct cprop_expr *set_ret[2])
     833              : {
     834     98252809 :   set_ret[0] = set_ret[1] = NULL;
     835              : 
     836              :   /* Loops are not possible here.  To get a loop we would need two sets
     837              :      available at the start of the block containing INSN.  i.e. we would
     838              :      need two sets like this available at the start of the block:
     839              : 
     840              :        (set (reg X) (reg Y))
     841              :        (set (reg Y) (reg X))
     842              : 
     843              :      This cannot happen since the set of (reg Y) would have killed the
     844              :      set of (reg X) making it unavailable at the start of this block.  */
     845     99620079 :   while (1)
     846              :     {
     847     98936444 :       rtx src;
     848     98936444 :       struct cprop_expr *set = lookup_set (regno, &set_hash_table);
     849              : 
     850              :       /* Find a set that is available at the start of the block
     851              :          which contains INSN.  */
     852     98936444 :       while (set)
     853              :         {
     854     43184176 :           if (bitmap_bit_p (cprop_avin[BLOCK_FOR_INSN (insn)->index],
     855              :                         set->bitmap_index))
     856              :             break;
     857    139884930 :           set = next_set (regno, set);
     858              :         }
     859              : 
     860              :       /* If no available set was found we've reached the end of the
     861              :          (possibly empty) copy chain.  */
     862      2235690 :       if (set == 0)
     863              :         break;
     864              : 
     865      2235690 :       src = set->src;
     866              : 
     867              :       /* We know the set is available.
     868              :          Now check that SRC is locally anticipatable (i.e. none of the
     869              :          source operands have changed since the start of the block).
     870              : 
     871              :          If the source operand changed, we may still use it for the next
     872              :          iteration of this loop, but we may not use it for substitutions.  */
     873              : 
     874      2235690 :       if (cprop_constant_p (src))
     875      1552055 :         set_ret[1] = set;
     876       683635 :       else if (reg_not_set_p (src, insn))
     877       679219 :         set_ret[0] = set;
     878              : 
     879              :       /* If the source of the set is anything except a register, then
     880              :          we have reached the end of the copy chain.  */
     881      2235690 :       if (! REG_P (src))
     882              :         break;
     883              : 
     884              :       /* Follow the copy chain, i.e. start another iteration of the loop
     885              :          and see if we have an available copy into SRC.  */
     886       683635 :       regno = REGNO (src);
     887       683635 :     }
     888     98252809 : }
     889              : 
     890              : /* Subroutine of cprop_insn that tries to propagate constants into
     891              :    JUMP_INSNS.  JUMP must be a conditional jump.  If SETCC is non-NULL
     892              :    it is the instruction that immediately precedes JUMP, and must be a
     893              :    single SET of a register.  FROM is what we will try to replace,
     894              :    SRC is the constant we will try to substitute for it.  Return true
     895              :    if a change was made.  */
     896              : 
     897              : static bool
     898       628638 : cprop_jump (basic_block bb, rtx_insn *setcc, rtx_insn *jump, rtx from, rtx src)
     899              : {
     900       628638 :   rtx new_rtx, set_src, note_src;
     901       628638 :   rtx set = pc_set (jump);
     902       628638 :   rtx note = find_reg_equal_equiv_note (jump);
     903              : 
     904       628638 :   if (note)
     905              :     {
     906            0 :       note_src = XEXP (note, 0);
     907            0 :       if (GET_CODE (note_src) == EXPR_LIST)
     908              :         note_src = NULL_RTX;
     909              :     }
     910              :   else note_src = NULL_RTX;
     911              : 
     912              :   /* Prefer REG_EQUAL notes except those containing EXPR_LISTs.  */
     913       628638 :   set_src = note_src ? note_src : SET_SRC (set);
     914              : 
     915              :   /* First substitute the SETCC condition into the JUMP instruction,
     916              :      then substitute that given values into this expanded JUMP.  */
     917       628638 :   if (setcc != NULL_RTX
     918       628638 :       && !modified_between_p (from, setcc, jump)
     919      1257276 :       && !modified_between_p (src, setcc, jump))
     920              :     {
     921       628638 :       rtx setcc_src;
     922       628638 :       rtx setcc_set = single_set (setcc);
     923       628638 :       rtx setcc_note = find_reg_equal_equiv_note (setcc);
     924       628638 :       setcc_src = (setcc_note && GET_CODE (XEXP (setcc_note, 0)) != EXPR_LIST)
     925       628638 :                 ? XEXP (setcc_note, 0) : SET_SRC (setcc_set);
     926       628638 :       set_src = simplify_replace_rtx (set_src, SET_DEST (setcc_set),
     927              :                                       setcc_src);
     928              :     }
     929              :   else
     930              :     setcc = NULL;
     931              : 
     932       628638 :   new_rtx = simplify_replace_rtx (set_src, from, src);
     933              : 
     934              :   /* If no simplification can be made, then try the next register.  */
     935       628638 :   if (rtx_equal_p (new_rtx, SET_SRC (set)))
     936              :     return false;
     937              : 
     938              :   /* If this is now a no-op delete it, otherwise this must be a valid insn.  */
     939       625210 :   if (new_rtx == pc_rtx)
     940         2508 :     delete_insn (jump);
     941              :   else
     942              :     {
     943              :       /* Ensure the value computed inside the jump insn to be equivalent
     944              :          to one computed by setcc.  */
     945       622702 :       if (setcc && modified_in_p (new_rtx, setcc))
     946              :         return false;
     947         1605 :       if (! validate_unshare_change (jump, &SET_SRC (set), new_rtx, 0))
     948              :         {
     949              :           /* When (some) constants are not valid in a comparison, and there
     950              :              are two registers to be replaced by constants before the entire
     951              :              comparison can be folded into a constant, we need to keep
     952              :              intermediate information in REG_EQUAL notes.  For targets with
     953              :              separate compare insns, such notes are added by try_replace_reg.
     954              :              When we have a combined compare-and-branch instruction, however,
     955              :              we need to attach a note to the branch itself to make this
     956              :              optimization work.  */
     957              : 
     958            0 :           if (!rtx_equal_p (new_rtx, note_src))
     959            0 :             set_unique_reg_note (jump, REG_EQUAL, copy_rtx (new_rtx));
     960              :           return false;
     961              :         }
     962              : 
     963              :       /* Remove REG_EQUAL note after simplification.  */
     964         1605 :       if (note_src)
     965            0 :         remove_note (jump, note);
     966              :      }
     967              : 
     968         4113 :   global_const_prop_count++;
     969         4113 :   if (dump_file != NULL)
     970              :     {
     971            0 :       fprintf (dump_file,
     972              :                "GLOBAL CONST-PROP: Replacing reg %d in jump_insn %d with "
     973            0 :                "constant ", REGNO (from), INSN_UID (jump));
     974            0 :       print_rtl (dump_file, src);
     975            0 :       fprintf (dump_file, "\n");
     976              :     }
     977         4113 :   purge_dead_edges (bb);
     978              : 
     979              :   /* If a conditional jump has been changed into unconditional jump, remove
     980              :      the jump and make the edge fallthru - this is always called in
     981              :      cfglayout mode.  */
     982         4113 :   if (new_rtx != pc_rtx && simplejump_p (jump))
     983              :     {
     984         1605 :       edge e;
     985         1605 :       edge_iterator ei;
     986              : 
     987         1605 :       FOR_EACH_EDGE (e, ei, bb->succs)
     988         1605 :         if (e->dest != EXIT_BLOCK_PTR_FOR_FN (cfun)
     989         1605 :             && BB_HEAD (e->dest) == JUMP_LABEL (jump))
     990              :           {
     991         1605 :             e->flags |= EDGE_FALLTHRU;
     992         1605 :             break;
     993              :           }
     994         1605 :       delete_insn (jump);
     995              :     }
     996              : 
     997              :   return true;
     998              : }
     999              : 
    1000              : /* Subroutine of cprop_insn that tries to propagate constants.  FROM is what
    1001              :    we will try to replace, SRC is the constant we will try to substitute for
    1002              :    it and INSN is the instruction where this will be happening.  */
    1003              : 
    1004              : static bool
    1005      5671125 : constprop_register (rtx from, rtx src, rtx_insn *insn)
    1006              : {
    1007      5671125 :   rtx sset;
    1008      5671125 :   rtx_insn *next_insn;
    1009              : 
    1010              :   /* Check for reg setting instructions followed by conditional branch
    1011              :      instructions first.  */
    1012      5671125 :   if ((sset = single_set (insn)) != NULL
    1013      5179654 :       && (next_insn = next_nondebug_insn (insn)) != NULL
    1014      5177165 :       && any_condjump_p (next_insn)
    1015      6299769 :       && onlyjump_p (next_insn))
    1016              :     {
    1017       628644 :       rtx dest = SET_DEST (sset);
    1018       628644 :       if (REG_P (dest)
    1019       628644 :           && cprop_jump (BLOCK_FOR_INSN (insn), insn, next_insn,
    1020              :                          from, src))
    1021              :         return true;
    1022              :     }
    1023              : 
    1024              :   /* Handle normal insns next.  */
    1025      5667012 :   if (NONJUMP_INSN_P (insn) && try_replace_reg (from, src, insn))
    1026              :     return true;
    1027              : 
    1028              :   /* Try to propagate a CONST_INT into a conditional jump.
    1029              :      We're pretty specific about what we will handle in this
    1030              :      code, we can extend this as necessary over time.
    1031              : 
    1032              :      Right now the insn in question must look like
    1033              :      (set (pc) (if_then_else ...))  */
    1034      5277997 :   else if (any_condjump_p (insn) && onlyjump_p (insn))
    1035            0 :     return cprop_jump (BLOCK_FOR_INSN (insn), NULL, insn, from, src);
    1036              :   return false;
    1037              : }
    1038              : 
    1039              : /* Perform constant and copy propagation on INSN.
    1040              :    Return true if a change was made.  */
    1041              : 
    1042              : static bool
    1043    283140963 : cprop_insn (rtx_insn *insn)
    1044              : {
    1045    283140963 :   unsigned i;
    1046    283140963 :   int changed_this_round;
    1047    283140963 :   bool changed = false;
    1048    283949437 :   rtx note;
    1049              : 
    1050    283949437 :   do
    1051              :     {
    1052    283949437 :       changed_this_round = 0;
    1053    283949437 :       reg_use_count = 0;
    1054    283949437 :       note_uses (&PATTERN (insn), find_used_regs, NULL);
    1055              : 
    1056              :       /* We may win even when propagating constants into notes.  */
    1057    283949437 :       note = find_reg_equal_equiv_note (insn);
    1058    283949437 :       if (note)
    1059      7380733 :         find_used_regs (&XEXP (note, 0), NULL);
    1060              : 
    1061    459784160 :       for (i = 0; i < reg_use_count; i++)
    1062              :         {
    1063    175834723 :           rtx reg_used = reg_use_table[i];
    1064    175834723 :           unsigned int regno = REGNO (reg_used);
    1065    175834723 :           rtx src_cst = NULL, src_reg = NULL;
    1066    175834723 :           struct cprop_expr *set[2];
    1067              : 
    1068              :           /* If the register has already been set in this block, there's
    1069              :              nothing we can do.  */
    1070    175834723 :           if (! reg_not_set_p (reg_used, insn))
    1071     77581914 :             continue;
    1072              : 
    1073              :           /* Find an assignment that sets reg_used and is available
    1074              :              at the start of the block.  */
    1075     98252809 :           find_avail_set (regno, insn, set);
    1076     98252809 :           if (set[0])
    1077       678633 :             src_reg = set[0]->src;
    1078     98252809 :           if (set[1])
    1079      1552055 :             src_cst = set[1]->src;
    1080              : 
    1081              :           /* Constant propagation.  */
    1082      1552055 :           if (src_cst && cprop_constant_p (src_cst)
    1083      3104110 :               && constprop_register (reg_used, src_cst, insn))
    1084              :             {
    1085       155446 :               changed = true;
    1086       155446 :               changed_this_round = 1;
    1087       155446 :               global_const_prop_count++;
    1088       155446 :               if (dump_file != NULL)
    1089              :                 {
    1090            6 :                   fprintf (dump_file,
    1091              :                            "GLOBAL CONST-PROP: Replacing reg %d in ", regno);
    1092            6 :                   fprintf (dump_file, "insn %d with constant ",
    1093            6 :                            INSN_UID (insn));
    1094            6 :                   print_rtl (dump_file, src_cst);
    1095            6 :                   fprintf (dump_file, "\n");
    1096              :                 }
    1097       155446 :               if (insn->deleted ())
    1098            0 :                 return true;
    1099              :             }
    1100              :           /* Copy propagation.  */
    1101     98252809 :           else if (src_reg && cprop_reg_p (src_reg)
    1102       678139 :                    && REGNO (src_reg) != regno
    1103     98775502 :                    && try_replace_reg (reg_used, src_reg, insn))
    1104              :             {
    1105       657573 :               changed = true;
    1106       657573 :               changed_this_round = 1;
    1107       657573 :               global_copy_prop_count++;
    1108       657573 :               if (dump_file != NULL)
    1109              :                 {
    1110            4 :                   fprintf (dump_file,
    1111              :                            "GLOBAL COPY-PROP: Replacing reg %d in insn %d",
    1112            4 :                            regno, INSN_UID (insn));
    1113            4 :                   fprintf (dump_file, " with reg %d\n", REGNO (src_reg));
    1114              :                 }
    1115              : 
    1116              :               /* The original insn setting reg_used may or may not now be
    1117              :                  deletable.  We leave the deletion to DCE.  */
    1118              :               /* FIXME: If it turns out that the insn isn't deletable,
    1119              :                  then we may have unnecessarily extended register lifetimes
    1120              :                  and made things worse.  */
    1121              :             }
    1122              :         }
    1123              :     }
    1124              :   /* If try_replace_reg simplified the insn, the regs found by find_used_regs
    1125              :      may not be valid anymore.  Start over.  */
    1126    283949437 :   while (changed_this_round);
    1127              : 
    1128    283140963 :   if (changed && DEBUG_INSN_P (insn))
    1129        36011 :     return false;
    1130              : 
    1131              :   return changed;
    1132              : }
    1133              : 
    1134              : /* Like find_used_regs, but avoid recording uses that appear in
    1135              :    input-output contexts such as zero_extract or pre_dec.  This
    1136              :    restricts the cases we consider to those for which local cprop
    1137              :    can legitimately make replacements.  */
    1138              : 
    1139              : static void
    1140    349175491 : local_cprop_find_used_regs (rtx *xptr, void *data)
    1141              : {
    1142    349175491 :   rtx x = *xptr;
    1143              : 
    1144    349175491 :   if (x == 0)
    1145              :     return;
    1146              : 
    1147    349175491 :   switch (GET_CODE (x))
    1148              :     {
    1149              :     case ZERO_EXTRACT:
    1150              :     case SIGN_EXTRACT:
    1151              :     case STRICT_LOW_PART:
    1152              :       return;
    1153              : 
    1154              :     case PRE_DEC:
    1155              :     case PRE_INC:
    1156              :     case POST_DEC:
    1157              :     case POST_INC:
    1158              :     case PRE_MODIFY:
    1159              :     case POST_MODIFY:
    1160              :       /* Can only legitimately appear this early in the context of
    1161              :          stack pushes for function arguments, but handle all of the
    1162              :          codes nonetheless.  */
    1163              :       return;
    1164              : 
    1165      1116911 :     case SUBREG:
    1166      1116911 :       if (read_modify_subreg_p (x))
    1167              :         return;
    1168              :       break;
    1169              : 
    1170              :     default:
    1171              :       break;
    1172              :     }
    1173              : 
    1174    344082944 :   find_used_regs (xptr, data);
    1175              : }
    1176              : 
    1177              : /* Try to perform local const/copy propagation on X in INSN.  */
    1178              : 
    1179              : static bool
    1180    193200038 : do_local_cprop (rtx x, rtx_insn *insn)
    1181              : {
    1182    193200038 :   rtx newreg = NULL, newcnst = NULL;
    1183              : 
    1184              :   /* Rule out USE instructions and ASM statements as we don't want to
    1185              :      change the hard registers mentioned.  */
    1186    193200038 :   if (REG_P (x)
    1187    193200038 :       && (cprop_reg_p (x)
    1188     63853837 :           || (GET_CODE (PATTERN (insn)) != USE
    1189     63110978 :               && asm_noperands (PATTERN (insn)) < 0)))
    1190              :     {
    1191    192432721 :       cselib_val *val = cselib_lookup (x, GET_MODE (x), 0, VOIDmode);
    1192    192432721 :       struct elt_loc_list *l;
    1193              : 
    1194    192432721 :       if (!val)
    1195              :         return false;
    1196    213373158 :       for (l = val->locs; l; l = l->next)
    1197              :         {
    1198    137890934 :           rtx this_rtx = l->loc;
    1199    137890934 :           rtx note;
    1200              : 
    1201    137890934 :           if (cprop_constant_p (this_rtx))
    1202      4119070 :             newcnst = this_rtx;
    1203    225321359 :           if (cprop_reg_p (this_rtx)
    1204              :               /* Don't copy propagate if it has attached REG_EQUIV note.
    1205              :                  At this point this only function parameters should have
    1206              :                  REG_EQUIV notes and if the argument slot is used somewhere
    1207              :                  explicitly, it means address of parameter has been taken,
    1208              :                  so we should not extend the lifetime of the pseudo.  */
    1209     53699230 :               && (!(note = find_reg_note (l->setting_insn, REG_EQUIV, NULL_RTX))
    1210         3129 :                   || ! MEM_P (XEXP (note, 0))))
    1211              :             newreg = this_rtx;
    1212              :         }
    1213     75482224 :       if (newcnst && constprop_register (x, newcnst, insn))
    1214              :         {
    1215       237682 :           if (dump_file != NULL)
    1216              :             {
    1217            2 :               fprintf (dump_file, "LOCAL CONST-PROP: Replacing reg %d in ",
    1218              :                        REGNO (x));
    1219            2 :               fprintf (dump_file, "insn %d with constant ",
    1220            2 :                        INSN_UID (insn));
    1221            2 :               print_rtl (dump_file, newcnst);
    1222            2 :               fprintf (dump_file, "\n");
    1223              :             }
    1224       237682 :           local_const_prop_count++;
    1225       237682 :           return true;
    1226              :         }
    1227     75244542 :       else if (newreg && newreg != x && try_replace_reg (x, newreg, insn))
    1228              :         {
    1229      1668805 :           if (dump_file != NULL)
    1230              :             {
    1231           26 :               fprintf (dump_file,
    1232              :                        "LOCAL COPY-PROP: Replacing reg %d in insn %d",
    1233           26 :                        REGNO (x), INSN_UID (insn));
    1234           26 :               fprintf (dump_file, " with reg %d\n", REGNO (newreg));
    1235              :             }
    1236      1668805 :           local_copy_prop_count++;
    1237      1668805 :           return true;
    1238              :         }
    1239              :     }
    1240              :   return false;
    1241              : }
    1242              : 
    1243              : /* Do local const/copy propagation (i.e. within each basic block).  */
    1244              : 
    1245              : static bool
    1246      1548784 : local_cprop_pass (void)
    1247              : {
    1248      1548784 :   basic_block bb;
    1249      1548784 :   rtx_insn *insn;
    1250      1548784 :   bool changed = false;
    1251      1548784 :   unsigned i;
    1252              : 
    1253      1548784 :   auto_vec<rtx_insn *> uncond_traps;
    1254              : 
    1255      1548784 :   cselib_init (0);
    1256     31431594 :   FOR_EACH_BB_FN (bb, cfun)
    1257              :     {
    1258    390052446 :       FOR_BB_INSNS (bb, insn)
    1259              :         {
    1260    360169636 :           if (INSN_P (insn))
    1261              :             {
    1262    313263453 :               bool was_uncond_trap
    1263    313263453 :                 = (GET_CODE (PATTERN (insn)) == TRAP_IF
    1264    313263453 :                    && XEXP (PATTERN (insn), 0) == const1_rtx);
    1265    313263453 :               rtx note = find_reg_equal_equiv_note (insn);
    1266    315169940 :               do
    1267              :                 {
    1268    315169940 :                   reg_use_count = 0;
    1269    315169940 :                   note_uses (&PATTERN (insn), local_cprop_find_used_regs,
    1270              :                              NULL);
    1271    315169940 :                   if (note)
    1272     10075389 :                     local_cprop_find_used_regs (&XEXP (note, 0), NULL);
    1273              : 
    1274    506463491 :                   for (i = 0; i < reg_use_count; i++)
    1275              :                     {
    1276    193200038 :                       if (do_local_cprop (reg_use_table[i], insn))
    1277              :                         {
    1278      1906487 :                           if (!DEBUG_INSN_P (insn))
    1279      1864667 :                             changed = true;
    1280              :                           break;
    1281              :                         }
    1282              :                     }
    1283    315169940 :                   if (!was_uncond_trap
    1284    315155053 :                       && GET_CODE (PATTERN (insn)) == TRAP_IF
    1285    315169940 :                       && XEXP (PATTERN (insn), 0) == const1_rtx)
    1286              :                     {
    1287            0 :                       uncond_traps.safe_push (insn);
    1288            0 :                       break;
    1289              :                     }
    1290    315169940 :                   if (insn->deleted ())
    1291              :                     break;
    1292              :                 }
    1293    315169940 :               while (i < reg_use_count);
    1294              :             }
    1295    360169636 :           cselib_process_insn (insn);
    1296              :         }
    1297              : 
    1298              :       /* Forget everything at the end of a basic block.  */
    1299     29882810 :       cselib_clear_table ();
    1300              :     }
    1301              : 
    1302      1548784 :   cselib_finish ();
    1303              : 
    1304      3097568 :   while (!uncond_traps.is_empty ())
    1305              :     {
    1306            0 :       rtx_insn *insn = uncond_traps.pop ();
    1307            0 :       basic_block to_split = BLOCK_FOR_INSN (insn);
    1308            0 :       remove_edge (split_block (to_split, insn));
    1309            0 :       emit_barrier_after_bb (to_split);
    1310              :     }
    1311              : 
    1312      1548784 :   return changed;
    1313      1548784 : }
    1314              : 
    1315              : /* Similar to get_condition, only the resulting condition must be
    1316              :    valid at JUMP, instead of at EARLIEST.
    1317              : 
    1318              :    This differs from noce_get_condition in ifcvt.cc in that we prefer not to
    1319              :    settle for the condition variable in the jump instruction being integral.
    1320              :    We prefer to be able to record the value of a user variable, rather than
    1321              :    the value of a temporary used in a condition.  This could be solved by
    1322              :    recording the value of *every* register scanned by canonicalize_condition,
    1323              :    but this would require some code reorganization.  */
    1324              : 
    1325              : rtx
    1326     20961629 : fis_get_condition (rtx_insn *jump)
    1327              : {
    1328     20961629 :   return get_condition (jump, NULL, false, true);
    1329              : }
    1330              : 
    1331              : /* Check the comparison COND to see if we can safely form an implicit
    1332              :    set from it.  */
    1333              : 
    1334              : static bool
    1335     13374825 : implicit_set_cond_p (const_rtx cond)
    1336              : {
    1337     13374825 :   machine_mode mode;
    1338     13374825 :   rtx cst;
    1339              : 
    1340              :   /* COND must be either an EQ or NE comparison.  */
    1341     13374825 :   if (GET_CODE (cond) != EQ && GET_CODE (cond) != NE)
    1342              :     return false;
    1343              : 
    1344              :   /* The first operand of COND must be a register we can propagate.  */
    1345     10788967 :   if (!cprop_reg_p (XEXP (cond, 0)))
    1346              :     return false;
    1347              : 
    1348              :   /* The second operand of COND must be a suitable constant.  */
    1349      8873734 :   mode = GET_MODE (XEXP (cond, 0));
    1350      8873734 :   cst = XEXP (cond, 1);
    1351              : 
    1352              :   /* We can't perform this optimization if either operand might be or might
    1353              :      contain a signed zero.  */
    1354      8873734 :   if (HONOR_SIGNED_ZEROS (mode))
    1355              :     {
    1356              :       /* It is sufficient to check if CST is or contains a zero.  We must
    1357              :          handle float, complex, and vector.  If any subpart is a zero, then
    1358              :          the optimization can't be performed.  */
    1359              :       /* ??? The complex and vector checks are not implemented yet.  We just
    1360              :          always return false for them.  */
    1361            0 :       if (CONST_DOUBLE_AS_FLOAT_P (cst)
    1362            6 :           && real_equal (CONST_DOUBLE_REAL_VALUE (cst), &dconst0))
    1363              :         return false;
    1364              :       else
    1365              :         return false;
    1366              :     }
    1367              : 
    1368      8873728 :   return cprop_constant_p (cst);
    1369              : }
    1370              : 
    1371              : /* Find the implicit sets of a function.  An "implicit set" is a constraint
    1372              :    on the value of a variable, implied by a conditional jump.  For example,
    1373              :    following "if (x == 2)", the then branch may be optimized as though the
    1374              :    conditional performed an "explicit set", in this example, "x = 2".  This
    1375              :    function records the set patterns that are implicit at the start of each
    1376              :    basic block.
    1377              : 
    1378              :    If an implicit set is found but the set is implicit on a critical edge,
    1379              :    this critical edge is split.
    1380              : 
    1381              :    Return true if the CFG was modified, false otherwise.  */
    1382              : 
    1383              : static bool
    1384      1548784 : find_implicit_sets (void)
    1385              : {
    1386      1548784 :   basic_block bb, dest;
    1387      1548784 :   rtx cond, new_rtx;
    1388      1548784 :   unsigned int count = 0;
    1389      1548784 :   bool edges_split = false;
    1390      1548784 :   size_t implicit_sets_size = last_basic_block_for_fn (cfun) + 10;
    1391              : 
    1392      1548784 :   implicit_sets = XCNEWVEC (rtx, implicit_sets_size);
    1393              : 
    1394     34118751 :   FOR_EACH_BB_FN (bb, cfun)
    1395              :     {
    1396              :       /* Check for more than one successor.  */
    1397     32569967 :       if (EDGE_COUNT (bb->succs) <= 1)
    1398     16534874 :         continue;
    1399              : 
    1400     16035093 :       cond = fis_get_condition (BB_END (bb));
    1401              : 
    1402              :       /* If no condition is found or if it isn't of a suitable form,
    1403              :          ignore it.  */
    1404     16035093 :       if (! cond || ! implicit_set_cond_p (cond))
    1405      9484594 :         continue;
    1406              : 
    1407      6550499 :       dest = GET_CODE (cond) == EQ
    1408      6550499 :         ? BRANCH_EDGE (bb)->dest : FALLTHRU_EDGE (bb)->dest;
    1409              : 
    1410              :       /* If DEST doesn't go anywhere, ignore it.  */
    1411      6550499 :       if (! dest || dest == EXIT_BLOCK_PTR_FOR_FN (cfun))
    1412            0 :         continue;
    1413              : 
    1414              :       /* We have found a suitable implicit set.  Try to record it now as
    1415              :          a SET in DEST.  If DEST has more than one predecessor, the edge
    1416              :          between BB and DEST is a critical edge and we must split it,
    1417              :          because we can only record one implicit set per DEST basic block.  */
    1418      6550499 :       if (! single_pred_p (dest))
    1419              :         {
    1420      2688467 :           dest = split_edge (find_edge (bb, dest));
    1421      2688467 :           edges_split = true;
    1422              :         }
    1423              : 
    1424      6550499 :       if (implicit_sets_size <= (size_t) dest->index)
    1425              :       {
    1426        46187 :         size_t old_implicit_sets_size = implicit_sets_size;
    1427        46187 :         implicit_sets_size *= 2;
    1428        46187 :         implicit_sets = XRESIZEVEC (rtx, implicit_sets, implicit_sets_size);
    1429        46187 :         memset (implicit_sets + old_implicit_sets_size, 0,
    1430        46187 :                 (implicit_sets_size - old_implicit_sets_size) * sizeof (rtx));
    1431              :       }
    1432              : 
    1433      6550499 :       new_rtx = gen_rtx_SET (XEXP (cond, 0), XEXP (cond, 1));
    1434      6550499 :       implicit_sets[dest->index] = new_rtx;
    1435      6550499 :       if (dump_file)
    1436              :         {
    1437           38 :           fprintf (dump_file, "Implicit set of reg %d in ",
    1438           38 :                    REGNO (XEXP (cond, 0)));
    1439           38 :           fprintf (dump_file, "basic block %d\n", dest->index);
    1440              :         }
    1441      6550499 :       count++;
    1442              :     }
    1443              : 
    1444      1548784 :   if (dump_file)
    1445           64 :     fprintf (dump_file, "Found %d implicit sets\n", count);
    1446              : 
    1447              :   /* Confess our sins.  */
    1448      1548784 :   return edges_split;
    1449              : }
    1450              : 
    1451              : /* Bypass conditional jumps.  */
    1452              : 
    1453              : /* The value of last_basic_block at the beginning of the jump_bypass
    1454              :    pass.  The use of redirect_edge_and_branch_force may introduce new
    1455              :    basic blocks, but the data flow analysis is only valid for basic
    1456              :    block indices less than bypass_last_basic_block.  */
    1457              : 
    1458              : static int bypass_last_basic_block;
    1459              : 
    1460              : /* A find_bypass_set query and its result.  */
    1461              : 
    1462              : struct bypass_set_cache_entry
    1463              : {
    1464              :   /* The register number of the query, or -1 if there was no query.  */
    1465              :   int regno;
    1466              : 
    1467              :   /* The result of the query.  */
    1468              :   struct cprop_expr *set;
    1469              : };
    1470              : 
    1471              : /* The last find_bypass_set query for each basic block with an index less
    1472              :    than bypass_last_basic_block.  Jump bypassing can move an edge past a
    1473              :    long chain of blocks, and repeats the query for the source of the edge
    1474              :    at each step.  */
    1475              : 
    1476              : static struct bypass_set_cache_entry *bypass_set_cache;
    1477              : 
    1478              : /* Find a set of REGNO to a constant that is available at the end of basic
    1479              :    block BB.  Return NULL if no such set is found.  Based heavily upon
    1480              :    find_avail_set.  The set hash table and CPROP_AVOUT do not change
    1481              :    during jump bypassing, so the result is cached in bypass_set_cache.  */
    1482              : 
    1483              : static struct cprop_expr *
    1484      2143481 : find_bypass_set (int regno, int bb)
    1485              : {
    1486      2143481 :   struct cprop_expr *result = 0;
    1487              : 
    1488      2143481 :   gcc_checking_assert (bb < bypass_last_basic_block);
    1489      2143481 :   struct bypass_set_cache_entry *entry = &bypass_set_cache[bb];
    1490      2143481 :   if (entry->regno == regno)
    1491        13643 :     return entry->set;
    1492              : 
    1493              :   /* The loop below changes REGNO when it follows a copy.  */
    1494      2129838 :   entry->regno = regno;
    1495              : 
    1496      2388936 :   for (;;)
    1497              :     {
    1498      2259387 :       rtx src;
    1499      2259387 :       struct cprop_expr *set = lookup_set (regno, &set_hash_table);
    1500              : 
    1501      2259387 :       while (set)
    1502              :         {
    1503      2700938 :           if (bitmap_bit_p (cprop_avout[bb], set->bitmap_index))
    1504              :             break;
    1505      4608667 :           set = next_set (regno, set);
    1506              :         }
    1507              : 
    1508       351658 :       if (set == 0)
    1509              :         break;
    1510              : 
    1511       351658 :       src = set->src;
    1512       351658 :       if (cprop_constant_p (src))
    1513       222109 :         result = set;
    1514              : 
    1515       351658 :       if (! REG_P (src))
    1516              :         break;
    1517              : 
    1518       129549 :       regno = REGNO (src);
    1519       129549 :     }
    1520              : 
    1521      2129838 :   entry->set = result;
    1522      2129838 :   return result;
    1523              : }
    1524              : 
    1525              : /* Subroutine of bypass_block that checks whether a pseudo is killed by
    1526              :    any of the instructions inserted on an edge.  Jump bypassing places
    1527              :    condition code setters on CFG edges using insert_insn_on_edge.  This
    1528              :    function is required to check that our data flow analysis is still
    1529              :    valid prior to commit_edge_insertions.  */
    1530              : 
    1531              : static bool
    1532          768 : reg_killed_on_edge (const_rtx reg, const_edge e)
    1533              : {
    1534          768 :   rtx_insn *insn;
    1535              : 
    1536         1536 :   for (insn = e->insns.r; insn; insn = NEXT_INSN (insn))
    1537          768 :     if (INSN_P (insn) && reg_set_p (reg, insn))
    1538              :       return true;
    1539              : 
    1540              :   return false;
    1541              : }
    1542              : 
    1543              : /* Subroutine of bypass_block.  Return true if a copy of SETCC, the insn
    1544              :    before the jump of a bypassed block, must be placed on an edge that has
    1545              :    been redirected to DEST.
    1546              : 
    1547              :    The copy is not needed if SETCC has no side effects, cannot throw, and
    1548              :    sets only condition-code registers that are dead on entry to DEST.
    1549              :    Setters of other registers are always copied, because debug insns and
    1550              :    REG_EQUAL notes, which the liveness information ignores, can refer to
    1551              :    them.  The liveness information predates the global propagation and
    1552              :    the edge redirections, but neither can make a register set by SETCC
    1553              :    live on entry to DEST: hard registers are never propagated, SETCC kills
    1554              :    every copy from a pseudo that it sets, and a redirection omits a copy
    1555              :    of a setter only if its registers are dead on entry to the new
    1556              :    destination.  */
    1557              : 
    1558              : static bool
    1559       155828 : bypass_setcc_needed_p (rtx_insn *setcc, basic_block dest)
    1560              : {
    1561       155828 :   if (side_effects_p (PATTERN (setcc)) || !insn_nothrow_p (setcc))
    1562              :     return true;
    1563              : 
    1564              :   /* DEST existed when the DF information was computed.  */
    1565       155828 :   gcc_checking_assert (dest->index < bypass_last_basic_block);
    1566       155828 :   bitmap live = df_get_live_in (dest);
    1567       155828 :   df_ref def;
    1568       311656 :   FOR_EACH_INSN_DEF (def, setcc)
    1569       156598 :     if (GET_MODE_CLASS (GET_MODE (*DF_REF_REAL_LOC (def))) != MODE_CC
    1570       156598 :         || REGNO_REG_SET_P (live, DF_REF_REGNO (def)))
    1571              :       return true;
    1572              : 
    1573              :   return false;
    1574              : }
    1575              : 
    1576              : /* Subroutine of bypass_conditional_jumps that attempts to bypass the given
    1577              :    basic block BB which has more than one predecessor.  If not NULL, SETCC
    1578              :    is the first instruction of BB, which is immediately followed by JUMP_INSN
    1579              :    JUMP.  Otherwise, SETCC is NULL, and JUMP is the first insn of BB.
    1580              :    Returns true if a change was made.
    1581              : 
    1582              :    During the jump bypassing pass, we may place copies of SETCC instructions
    1583              :    on CFG edges.  The following routine must be careful to pay attention to
    1584              :    these inserted insns when performing its transformations.  */
    1585              : 
    1586              : static bool
    1587       888894 : bypass_block (basic_block bb, rtx_insn *setcc, rtx_insn *jump)
    1588              : {
    1589       888894 :   rtx_insn *insn;
    1590       888894 :   rtx setcc_src, setcc_dest;
    1591       888894 :   rtx note;
    1592       888894 :   edge e, edest;
    1593       888894 :   bool change;
    1594       888894 :   bool may_be_loop_header = false;
    1595       888894 :   bool removed_p;
    1596       888894 :   unsigned i;
    1597       888894 :   edge_iterator ei;
    1598              : 
    1599       888894 :   if (setcc != NULL)
    1600              :     {
    1601       888731 :       rtx set = single_set (setcc);
    1602       888731 :       setcc_dest = SET_DEST (set);
    1603       888731 :       setcc_src = SET_SRC (set);
    1604       888731 :       insn = setcc;
    1605              :     }
    1606              :   else
    1607              :     {
    1608              :       setcc_dest = NULL;
    1609              :       setcc_src = NULL;
    1610              :       insn = jump;
    1611              :     }
    1612              : 
    1613              :   /* Determine set of register uses in INSN.  */
    1614       888894 :   reg_use_count = 0;
    1615       888894 :   note_uses (&PATTERN (insn), find_used_regs, NULL);
    1616       888894 :   note = find_reg_equal_equiv_note (insn);
    1617       888894 :   if (note)
    1618         3113 :     find_used_regs (&XEXP (note, 0), NULL);
    1619              : 
    1620       888894 :   if (current_loops)
    1621              :     {
    1622              :       /* If we are to preserve loop structure then do not bypass
    1623              :          a loop header.  This will either rotate the loop, create
    1624              :          multiple entry loops or even irreducible regions.  */
    1625       623686 :       if (bb == bb->loop_father->header)
    1626              :         return 0;
    1627              :     }
    1628              :   else
    1629              :     {
    1630       777711 :       FOR_EACH_EDGE (e, ei, bb->preds)
    1631       588296 :         if (e->flags & EDGE_DFS_BACK)
    1632              :           {
    1633              :             may_be_loop_header = true;
    1634              :             break;
    1635              :           }
    1636              :     }
    1637              : 
    1638              :   /* The source of JUMP with SETCC substituted into it.  JUMP only changes
    1639              :      when an edge from BB itself is redirected.  With SETCC that never
    1640              :      happens, because DEST is a successor of BB (see the check of
    1641              :      find_edge (e->src, dest) below).  Without SETCC, SRC is the source
    1642              :      of JUMP itself.  */
    1643       743172 :   rtx src = SET_SRC (pc_set (jump));
    1644       743172 :   if (setcc != NULL)
    1645       743104 :     src = simplify_replace_rtx (src, setcc_dest, setcc_src);
    1646              : 
    1647       743172 :   change = false;
    1648      2560686 :   for (ei = ei_start (bb->preds); (e = ei_safe_edge (ei)); )
    1649              :     {
    1650      1817514 :       removed_p = false;
    1651              : 
    1652      1817514 :       if (e->flags & EDGE_COMPLEX)
    1653              :         {
    1654         4819 :           ei_next (&ei);
    1655         4819 :           continue;
    1656              :         }
    1657              : 
    1658              :       /* We can't redirect edges from new basic blocks.  */
    1659      1812695 :       if (e->src->index >= bypass_last_basic_block)
    1660              :         {
    1661            0 :           ei_next (&ei);
    1662            0 :           continue;
    1663              :         }
    1664              : 
    1665              :       /* The irreducible loops created by redirecting of edges entering the
    1666              :          loop from outside would decrease effectiveness of some of the
    1667              :          following optimizations, so prevent this.  */
    1668      1812695 :       if (may_be_loop_header
    1669       168376 :           && !(e->flags & EDGE_DFS_BACK))
    1670              :         {
    1671        80617 :           ei_next (&ei);
    1672        80617 :           continue;
    1673              :         }
    1674              : 
    1675      3719729 :       for (i = 0; i < reg_use_count; i++)
    1676              :         {
    1677      2143481 :           rtx reg_used = reg_use_table[i];
    1678      2143481 :           unsigned int regno = REGNO (reg_used);
    1679      2143481 :           basic_block dest, old_dest;
    1680      2143481 :           struct cprop_expr *set;
    1681      2143481 :           rtx new_rtx;
    1682              : 
    1683      2143481 :           set = find_bypass_set (regno, e->src->index);
    1684              : 
    1685      2143481 :           if (! set)
    1686      1914934 :             continue;
    1687              : 
    1688              :           /* Check the data flow is valid after edge insertions.  */
    1689       228547 :           if (e->insns.r && reg_killed_on_edge (reg_used, e))
    1690            0 :             continue;
    1691              : 
    1692       228547 :           new_rtx = simplify_replace_rtx (src, reg_used, set->src);
    1693              : 
    1694              :           /* Jump bypassing may have already placed instructions on
    1695              :              edges of the CFG.  We can't bypass an outgoing edge that
    1696              :              has instructions associated with it, as these insns won't
    1697              :              get executed if the incoming edge is redirected.  */
    1698       228547 :           if (new_rtx == pc_rtx)
    1699              :             {
    1700        79168 :               edest = FALLTHRU_EDGE (bb);
    1701        79168 :               dest = edest->insns.r ? NULL : edest->dest;
    1702              :             }
    1703       149379 :           else if (GET_CODE (new_rtx) == LABEL_REF)
    1704              :             {
    1705        76668 :               dest = BLOCK_FOR_INSN (label_ref_label (new_rtx));
    1706              :               /* Don't bypass edges containing instructions.  */
    1707        76668 :               if (dest)
    1708              :                 {
    1709        76664 :                   edest = find_edge (bb, dest);
    1710        76664 :                   if (edest && edest->insns.r)
    1711       228547 :                     dest = NULL;
    1712              :                 }
    1713              :             }
    1714              :           else
    1715              :             dest = NULL;
    1716              : 
    1717              :           /* Avoid unification of the edge with other edges from original
    1718              :              branch.  We would end up emitting the instruction on "both"
    1719              :              edges.  */
    1720       228547 :           if (dest && setcc && find_edge (e->src, dest))
    1721              :             dest = NULL;
    1722              : 
    1723       228547 :           old_dest = e->dest;
    1724       228547 :           if (dest != NULL
    1725       228547 :               && dest != old_dest
    1726       155830 :               && dest != EXIT_BLOCK_PTR_FOR_FN (cfun))
    1727              :             {
    1728       155830 :               redirect_edge_and_branch_force (e, dest);
    1729              : 
    1730              :               /* Copy the register setter to the redirected edge if it is
    1731              :                  needed on entry to DEST.  */
    1732       155830 :               if (setcc && bypass_setcc_needed_p (setcc, dest))
    1733              :                 {
    1734          770 :                   rtx pat = PATTERN (setcc);
    1735          770 :                   insert_insn_on_edge (copy_insn (pat), e);
    1736              :                 }
    1737              : 
    1738       155830 :               if (dump_file != NULL)
    1739              :                 {
    1740           28 :                   fprintf (dump_file, "JUMP-BYPASS: Proved reg %d "
    1741              :                                       "in jump_insn %d equals constant ",
    1742           28 :                            regno, INSN_UID (jump));
    1743           28 :                   print_rtl (dump_file, set->src);
    1744           28 :                   fprintf (dump_file, "\n\t     when BB %d is entered from "
    1745              :                                       "BB %d.  Redirect edge %d->%d to %d.\n",
    1746           28 :                            old_dest->index, e->src->index, e->src->index,
    1747              :                            old_dest->index, dest->index);
    1748              :                 }
    1749              :               change = true;
    1750              :               removed_p = true;
    1751              :               break;
    1752              :             }
    1753              :         }
    1754      1732078 :       if (!removed_p)
    1755      1576248 :         ei_next (&ei);
    1756              :     }
    1757              :   return change;
    1758              : }
    1759              : 
    1760              : /* Find basic blocks with more than one predecessor that only contain a
    1761              :    single conditional jump.  If the result of the comparison is known at
    1762              :    compile-time from any incoming edge, redirect that edge to the
    1763              :    appropriate target.  Return nonzero if a change was made.
    1764              : 
    1765              :    This function is now mis-named, because we also handle indirect jumps.  */
    1766              : 
    1767              : static bool
    1768      1396900 : bypass_conditional_jumps (void)
    1769              : {
    1770      1396900 :   basic_block bb;
    1771      1396900 :   bool changed;
    1772      1396900 :   rtx_insn *setcc;
    1773      1396900 :   rtx_insn *insn;
    1774      1396900 :   rtx dest;
    1775              : 
    1776              :   /* Note we start at block 1.  */
    1777      1396900 :   if (ENTRY_BLOCK_PTR_FOR_FN (cfun)->next_bb == EXIT_BLOCK_PTR_FOR_FN (cfun))
    1778              :     return false;
    1779              : 
    1780      1396900 :   mark_dfs_back_edges ();
    1781              : 
    1782      1396900 :   bypass_set_cache = XNEWVEC (struct bypass_set_cache_entry,
    1783              :                               bypass_last_basic_block);
    1784     37569357 :   for (int i = 0; i < bypass_last_basic_block; i++)
    1785     36172457 :     bypass_set_cache[i].regno = -1;
    1786              : 
    1787      1396900 :   changed = false;
    1788     31883969 :   FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR_FOR_FN (cfun)->next_bb->next_bb,
    1789              :                   EXIT_BLOCK_PTR_FOR_FN (cfun), next_bb)
    1790              :     {
    1791              :       /* Check for more than one predecessor.  */
    1792     30487069 :       if (!single_pred_p (bb))
    1793              :         {
    1794      8170566 :           setcc = NULL;
    1795     65846539 :           FOR_BB_INSNS (bb, insn)
    1796     64907227 :             if (DEBUG_INSN_P (insn))
    1797     35065905 :               continue;
    1798     29841322 :             else if (NONJUMP_INSN_P (insn))
    1799              :               {
    1800     12152663 :                 if (setcc)
    1801              :                   break;
    1802      7644517 :                 rtx singleset = single_set (insn);
    1803      7644517 :                 if (singleset == NULL_RTX)
    1804              :                   break;
    1805              : 
    1806      7547828 :                 dest = SET_DEST (singleset);
    1807      7547828 :                 if (REG_P (dest))
    1808              :                   setcc = insn;
    1809              :                 else
    1810              :                   break;
    1811              :               }
    1812     17688659 :             else if (JUMP_P (insn))
    1813              :               {
    1814       889409 :                 if ((any_condjump_p (insn) || computed_jump_p (insn))
    1815       889237 :                     && onlyjump_p (insn))
    1816       888894 :                   if (bypass_block (bb, setcc, insn))
    1817     30487069 :                     changed = true;
    1818              :                 break;
    1819              :               }
    1820     16799587 :             else if (INSN_P (insn))
    1821              :               break;
    1822              :         }
    1823              :     }
    1824              : 
    1825      1396900 :   free (bypass_set_cache);
    1826      1396900 :   bypass_set_cache = NULL;
    1827              : 
    1828              :   /* If we bypassed any register setting insns, we may have inserted
    1829              :      copies of them on the redirected edges.  These need to be committed.  */
    1830      1396900 :   if (changed)
    1831        43961 :     commit_edge_insertions ();
    1832              : 
    1833              :   return changed;
    1834              : }
    1835              : 
    1836              : /* Main function for the CPROP pass.  */
    1837              : 
    1838              : static bool
    1839      2963244 : one_cprop_pass (void)
    1840              : {
    1841      2963244 :   bool changed = false;
    1842      2963244 :   int i;
    1843              : 
    1844              :   /* Return if there's nothing to do, or it is too expensive.  */
    1845      2963244 :   if (n_basic_blocks_for_fn (cfun) <= NUM_FIXED_BLOCKS + 1
    1846      2963244 :       || gcse_or_cprop_is_too_expensive (_ ("const/copy propagation disabled")))
    1847              :     return false;
    1848              : 
    1849      1548784 :   global_const_prop_count = local_const_prop_count = 0;
    1850      1548784 :   global_copy_prop_count = local_copy_prop_count = 0;
    1851              : 
    1852      1548784 :   bytes_used = 0;
    1853      1548784 :   gcc_obstack_init (&cprop_obstack);
    1854              : 
    1855              :   /* Do a local const/copy propagation pass first.  The global pass
    1856              :      only handles global opportunities.
    1857              :      If the local pass changes something, remove any unreachable blocks
    1858              :      because the CPROP global dataflow analysis may get into infinite
    1859              :      loops for CFGs with unreachable blocks.
    1860              : 
    1861              :      FIXME: This local pass should not be necessary after CSE (but for
    1862              :             some reason it still is).  It is also (proven) not necessary
    1863              :             to run the local pass right after FWPWOP.
    1864              : 
    1865              :      FIXME: The global analysis would not get into infinite loops if it
    1866              :             would use the DF solver (via df_simple_dataflow) instead of
    1867              :             the solver implemented in this file.  */
    1868      1548784 :   if (local_cprop_pass ())
    1869       227757 :     changed = true;
    1870              : 
    1871       227757 :   if (changed)
    1872       227757 :     delete_unreachable_blocks ();
    1873              : 
    1874              :   /* Determine implicit sets.  This may change the CFG (split critical
    1875              :      edges if that exposes an implicit set).
    1876              :      Note that find_implicit_sets() does not rely on up-to-date DF caches
    1877              :      so that we do not have to re-run df_analyze() even if local CPROP
    1878              :      changed something.
    1879              :      ??? This could run earlier so that any uncovered implicit sets
    1880              :          sets could be exploited in local_cprop_pass() also.  Later.  */
    1881      1548784 :   if (find_implicit_sets ())
    1882              :     changed = true;
    1883              : 
    1884              :   /* If local_cprop_pass() or find_implicit_sets() changed something,
    1885              :      run df_analyze() to bring all insn caches up-to-date, and to take
    1886              :      new basic blocks from edge splitting on the DF radar.
    1887              :      NB: This also runs the fast DCE pass, because execute_rtl_cprop
    1888              :      sets DF_LR_RUN_DCE.  */
    1889       934847 :   if (changed)
    1890       707424 :     df_analyze ();
    1891              : 
    1892              :   /* Initialize implicit_set_indexes array.  */
    1893      1548784 :   implicit_set_indexes = XNEWVEC (int, last_basic_block_for_fn (cfun));
    1894     38750987 :   for (i = 0; i < last_basic_block_for_fn (cfun); i++)
    1895     37202203 :     implicit_set_indexes[i] = -1;
    1896              : 
    1897      1548784 :   alloc_hash_table (&set_hash_table);
    1898      1548784 :   compute_hash_table (&set_hash_table);
    1899              : 
    1900              :   /* Free implicit_sets before peak usage.  */
    1901      1548784 :   free (implicit_sets);
    1902      1548784 :   implicit_sets = NULL;
    1903              : 
    1904      1548784 :   if (dump_file)
    1905           64 :     dump_hash_table (dump_file, "SET", &set_hash_table);
    1906      1548784 :   if (set_hash_table.n_elems > 0)
    1907              :     {
    1908      1396900 :       basic_block bb;
    1909      1396900 :       auto_vec<rtx_insn *> uncond_traps;
    1910              : 
    1911      1396900 :       alloc_cprop_mem (last_basic_block_for_fn (cfun),
    1912              :                        set_hash_table.n_elems);
    1913      1396900 :       compute_cprop_data ();
    1914              : 
    1915      1396900 :       free (implicit_set_indexes);
    1916      1396900 :       implicit_set_indexes = NULL;
    1917              : 
    1918              :       /* Allocate vars to track sets of regs.  */
    1919      1396900 :       reg_set_bitmap = ALLOC_REG_SET (NULL);
    1920              : 
    1921     31883969 :       FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR_FOR_FN (cfun)->next_bb->next_bb,
    1922              :                       EXIT_BLOCK_PTR_FOR_FN (cfun),
    1923              :                       next_bb)
    1924              :         {
    1925     30487069 :           bool seen_uncond_trap = false;
    1926     30487069 :           rtx_insn *insn;
    1927              : 
    1928              :           /* Reset tables used to keep track of what's still valid [since
    1929              :              the start of the block].  */
    1930     30487069 :           reset_opr_set_tables ();
    1931              : 
    1932    361215914 :           FOR_BB_INSNS (bb, insn)
    1933    330728845 :             if (INSN_P (insn))
    1934              :               {
    1935    283140963 :                 bool was_uncond_trap
    1936    283140963 :                   = (GET_CODE (PATTERN (insn)) == TRAP_IF
    1937    283140963 :                      && XEXP (PATTERN (insn), 0) == const1_rtx);
    1938              : 
    1939    283140963 :                 if (cprop_insn (insn))
    1940       772425 :                   changed = true;
    1941              : 
    1942              :                 /* Keep track of everything modified by this insn.  */
    1943              :                 /* ??? Need to be careful w.r.t. mods done to INSN.
    1944              :                        Don't call mark_oprs_set if we turned the
    1945              :                        insn into a NOTE, or deleted the insn.  */
    1946    283140963 :                 if (! NOTE_P (insn) && ! insn->deleted ())
    1947    283140963 :                   mark_oprs_set (insn);
    1948              : 
    1949    283140963 :                 if (!was_uncond_trap
    1950    283127216 :                     && GET_CODE (PATTERN (insn)) == TRAP_IF
    1951    283140963 :                     && XEXP (PATTERN (insn), 0) == const1_rtx)
    1952              :                   {
    1953              :                     /* If we have already seen an unconditional trap
    1954              :                        earlier, the rest of the bb is going to be removed
    1955              :                        as unreachable.  Just turn it into a note, so that
    1956              :                        RTL verification doesn't complain about it before
    1957              :                        it is finally removed.  */
    1958            0 :                     if (seen_uncond_trap)
    1959            0 :                       set_insn_deleted (insn);
    1960              :                     else
    1961              :                       {
    1962            0 :                         seen_uncond_trap = true;
    1963            0 :                         uncond_traps.safe_push (insn);
    1964              :                       }
    1965              :                   }
    1966              :               }
    1967              :         }
    1968              : 
    1969              :       /* Make sure bypass_conditional_jumps will ignore not just its new
    1970              :          basic blocks, but also the ones after unconditional traps (those are
    1971              :          unreachable and will be eventually removed as such).  */
    1972      1396900 :       bypass_last_basic_block = last_basic_block_for_fn (cfun);
    1973              : 
    1974      1396900 :       while (!uncond_traps.is_empty ())
    1975              :         {
    1976            0 :           rtx_insn *insn = uncond_traps.pop ();
    1977            0 :           basic_block to_split = BLOCK_FOR_INSN (insn);
    1978            0 :           remove_edge (split_block (to_split, insn));
    1979            0 :           emit_barrier_after_bb (to_split);
    1980              :         }
    1981              : 
    1982      1396900 :       if (bypass_conditional_jumps ())
    1983        43961 :         changed = true;
    1984              : 
    1985      1396900 :       FREE_REG_SET (reg_set_bitmap);
    1986      1396900 :       free_cprop_mem ();
    1987      1396900 :     }
    1988              :   else
    1989              :     {
    1990       151884 :       free (implicit_set_indexes);
    1991       151884 :       implicit_set_indexes = NULL;
    1992              :     }
    1993              : 
    1994      1548784 :   free_hash_table (&set_hash_table);
    1995      1548784 :   obstack_free (&cprop_obstack, NULL);
    1996              : 
    1997      1548784 :   if (dump_file)
    1998              :     {
    1999           64 :       fprintf (dump_file, "CPROP of %s, %d basic blocks, %d bytes needed, ",
    2000           64 :                current_function_name (), n_basic_blocks_for_fn (cfun),
    2001              :                bytes_used);
    2002           64 :       fprintf (dump_file, "%d local const props, %d local copy props, ",
    2003              :                local_const_prop_count, local_copy_prop_count);
    2004           64 :       fprintf (dump_file, "%d global const props, %d global copy props\n\n",
    2005              :                global_const_prop_count, global_copy_prop_count);
    2006              :     }
    2007              : 
    2008              :   return changed;
    2009              : }
    2010              : 
    2011              : /* All the passes implemented in this file.  Each pass has its
    2012              :    own gate and execute function, and at the end of the file a
    2013              :    pass definition for passes.cc.
    2014              : 
    2015              :    We do not construct an accurate cfg in functions which call
    2016              :    setjmp, so none of these passes runs if the function calls
    2017              :    setjmp.
    2018              :    FIXME: Should just handle setjmp via REG_SETJMP notes.  */
    2019              : 
    2020              : static unsigned int
    2021      2963244 : execute_rtl_cprop (void)
    2022              : {
    2023      2963244 :   int changed;
    2024      2963244 :   delete_unreachable_blocks ();
    2025      2963244 :   df_set_flags (DF_LR_RUN_DCE);
    2026      2963244 :   df_analyze ();
    2027      2963244 :   changed = one_cprop_pass ();
    2028      2963244 :   flag_rerun_cse_after_global_opts |= changed;
    2029      2963244 :   if (changed)
    2030       746495 :     cleanup_cfg (CLEANUP_CFG_CHANGED);
    2031      2963244 :   return 0;
    2032              : }
    2033              : 
    2034              : namespace {
    2035              : 
    2036              : const pass_data pass_data_rtl_cprop =
    2037              : {
    2038              :   RTL_PASS, /* type */
    2039              :   "cprop", /* name */
    2040              :   OPTGROUP_NONE, /* optinfo_flags */
    2041              :   TV_CPROP, /* tv_id */
    2042              :   PROP_cfglayout, /* properties_required */
    2043              :   0, /* properties_provided */
    2044              :   0, /* properties_destroyed */
    2045              :   0, /* todo_flags_start */
    2046              :   TODO_df_finish, /* todo_flags_finish */
    2047              : };
    2048              : 
    2049              : class pass_rtl_cprop : public rtl_opt_pass
    2050              : {
    2051              : public:
    2052       883608 :   pass_rtl_cprop (gcc::context *ctxt)
    2053      1767216 :     : rtl_opt_pass (pass_data_rtl_cprop, ctxt)
    2054              :   {}
    2055              : 
    2056              :   /* opt_pass methods: */
    2057       589072 :   opt_pass * clone () final override { return new pass_rtl_cprop (m_ctxt); }
    2058      4547787 :   bool gate (function *fun) final override
    2059              :     {
    2060      3210579 :       return optimize > 0 && flag_gcse
    2061      2965401 :         && !fun->calls_setjmp
    2062      7511034 :         && dbg_cnt (cprop);
    2063              :     }
    2064              : 
    2065      2963244 :   unsigned int execute (function *) final override
    2066              :   {
    2067      2963244 :     return execute_rtl_cprop ();
    2068              :   }
    2069              : 
    2070              : }; // class pass_rtl_cprop
    2071              : 
    2072              : } // anon namespace
    2073              : 
    2074              : rtl_opt_pass *
    2075       294536 : make_pass_rtl_cprop (gcc::context *ctxt)
    2076              : {
    2077       294536 :   return new pass_rtl_cprop (ctxt);
    2078              : }
        

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