LCOV - code coverage report
Current view: top level - gcc - cprop.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 94.0 % 739 695
Test Date: 2026-02-28 14:20:25 Functions: 100.0 % 45 45
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     30504893 : cprop_alloc (unsigned long size)
     141              : {
     142     30504893 :   bytes_used += size;
     143     30504893 :   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     69023198 : reg_available_p (const_rtx x, const rtx_insn *insn ATTRIBUTE_UNUSED)
     151              : {
     152      2649995 :   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    112720511 : hash_mod (int regno, int hash_table_size)
     164              : {
     165    112720511 :   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     16183014 : insert_set_in_table (rtx dest, rtx src, rtx_insn *insn,
     176              :                      struct hash_table_d *table, bool implicit)
     177              : {
     178     16183014 :   bool found = false;
     179     16183014 :   unsigned int hash;
     180     16183014 :   struct cprop_expr *cur_expr, *last_expr = NULL;
     181     16183014 :   struct cprop_occr *cur_occr;
     182              : 
     183     16183014 :   hash = hash_mod (REGNO (dest), table->size);
     184              : 
     185     38324675 :   for (cur_expr = table->table[hash]; cur_expr;
     186     22141661 :        cur_expr = cur_expr->next_same_hash)
     187              :     {
     188     24002796 :       if (dest == cur_expr->dest
     189     23482031 :           && src == cur_expr->src)
     190              :         {
     191              :           found = true;
     192              :           break;
     193              :         }
     194     22141661 :       last_expr = cur_expr;
     195              :     }
     196              : 
     197     16183014 :   if (! found)
     198              :     {
     199     14321879 :       cur_expr = GOBNEW (struct cprop_expr);
     200     14321879 :       bytes_used += sizeof (struct cprop_expr);
     201     14321879 :       if (table->table[hash] == NULL)
     202              :         /* This is the first pattern that hashed to this index.  */
     203     11411866 :         table->table[hash] = cur_expr;
     204              :       else
     205              :         /* Add EXPR to end of this hash chain.  */
     206      2910013 :         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     14321879 :       cur_expr->dest = copy_rtx (dest);
     212     14321879 :       cur_expr->src = copy_rtx (src);
     213     14321879 :       cur_expr->bitmap_index = table->n_elems++;
     214     14321879 :       cur_expr->next_same_hash = NULL;
     215     14321879 :       cur_expr->avail_occr = NULL;
     216              :     }
     217              : 
     218              :   /* Now record the occurrence.  */
     219     16183014 :   cur_occr = cur_expr->avail_occr;
     220              : 
     221     16183014 :   if (cur_occr
     222     16183014 :       && 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     16183014 :       cur_occr = GOBNEW (struct cprop_occr);
     234     16183014 :       bytes_used += sizeof (struct cprop_occr);
     235     16183014 :       cur_occr->insn = insn;
     236     16183014 :       cur_occr->next = cur_expr->avail_occr;
     237     16183014 :       cur_expr->avail_occr = cur_occr;
     238              :     }
     239              : 
     240              :   /* Record bitmap_index of the implicit set in implicit_set_indexes.  */
     241     16183014 :   if (implicit)
     242      6308954 :     implicit_set_indexes[BLOCK_FOR_INSN (insn)->index]
     243      6308954 :       = cur_expr->bitmap_index;
     244     16183014 : }
     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    212470290 : cprop_constant_p (const_rtx x)
     252              : {
     253    212470290 :   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    542557781 : cprop_reg_p (const_rtx x)
     261              : {
     262    398990556 :   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    147609657 : hash_scan_set (rtx set, rtx_insn *insn, struct hash_table_d *table,
     270              :                bool implicit)
     271              : {
     272    147609657 :   rtx src = SET_SRC (set);
     273    147609657 :   rtx dest = SET_DEST (set);
     274              : 
     275    213982860 :   if (cprop_reg_p (dest)
     276     66373203 :       && reg_available_p (dest, insn)
     277     65862227 :       && 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     65862227 :       rtx note = find_reg_equal_equiv_note (insn);
     293     65862227 :       if (note != 0
     294      4256280 :           && REG_NOTE_KIND (note) == REG_EQUAL
     295      3822335 :           && !REG_P (src)
     296     69386398 :           && cprop_constant_p (XEXP (note, 0)))
     297      1693434 :         src = XEXP (note, 0), set = gen_rtx_SET (dest, src);
     298              : 
     299              :       /* Record sets for constant/copy propagation.  */
     300     65862227 :       if ((cprop_reg_p (src)
     301      2649995 :            && src != dest
     302      2649995 :            && reg_available_p (src, insn))
     303     63355767 :           || cprop_constant_p (src))
     304     16183014 :         insert_set_in_table (dest, src, insn, table, implicit);
     305              :     }
     306    147609657 : }
     307              : 
     308              : /* Process INSN and add hash table entries as appropriate.  */
     309              : 
     310              : static void
     311    148183430 : hash_scan_insn (rtx_insn *insn, struct hash_table_d *table)
     312              : {
     313    148183430 :   rtx pat = PATTERN (insn);
     314    148183430 :   int i;
     315              : 
     316              :   /* Pick out the sets of INSN and for other forms of instructions record
     317              :      what's been modified.  */
     318              : 
     319    148183430 :   if (GET_CODE (pat) == SET)
     320    117388470 :     hash_scan_set (pat, insn, table, false);
     321     30794960 :   else if (GET_CODE (pat) == PARALLEL)
     322     70521061 :     for (i = 0; i < XVECLEN (pat, 0); i++)
     323              :       {
     324     47316918 :         rtx x = XVECEXP (pat, 0, i);
     325              : 
     326     47316918 :         if (GET_CODE (x) == SET)
     327     23833301 :           hash_scan_set (x, insn, table, false);
     328              :       }
     329    148183430 : }
     330              : 
     331              : /* Dump the hash table TABLE to file FILE under the name NAME.  */
     332              : 
     333              : static void
     334           63 : dump_hash_table (FILE *file, const char *name, struct hash_table_d *table)
     335              : {
     336           63 :   int i;
     337              :   /* Flattened out table, so it's printed in proper order.  */
     338           63 :   struct cprop_expr **flat_table;
     339           63 :   unsigned int *hash_val;
     340           63 :   struct cprop_expr *expr;
     341              : 
     342           63 :   flat_table = XCNEWVEC (struct cprop_expr *, table->n_elems);
     343           63 :   hash_val = XNEWVEC (unsigned int, table->n_elems);
     344              : 
     345         1335 :   for (i = 0; i < (int) table->size; i++)
     346         1336 :     for (expr = table->table[i]; expr != NULL; expr = expr->next_same_hash)
     347              :       {
     348          127 :         flat_table[expr->bitmap_index] = expr;
     349          127 :         hash_val[expr->bitmap_index] = i;
     350              :       }
     351              : 
     352           63 :   fprintf (file, "%s hash table (%d buckets, %d entries)\n",
     353              :            name, table->size, table->n_elems);
     354              : 
     355          253 :   for (i = 0; i < (int) table->n_elems; i++)
     356          127 :     if (flat_table[i] != 0)
     357              :       {
     358          127 :         expr = flat_table[i];
     359          127 :         fprintf (file, "Index %d (hash value %d)\n  ",
     360          127 :                  expr->bitmap_index, hash_val[i]);
     361          127 :         print_rtl (file, expr->dest);
     362          127 :         fprintf (file, " := ");
     363          127 :         print_rtl (file, expr->src);
     364          127 :         fprintf (file, "\n");
     365              :       }
     366              : 
     367           63 :   fprintf (file, "\n");
     368              : 
     369           63 :   free (flat_table);
     370           63 :   free (hash_val);
     371           63 : }
     372              : 
     373              : /* Record as unavailable all registers that are DEF operands of INSN.  */
     374              : 
     375              : static void
     376    148183430 : make_set_regs_unavailable (rtx_insn *insn)
     377              : {
     378    148183430 :   df_ref def;
     379              : 
     380   1214511793 :   FOR_EACH_INSN_DEF (def, insn)
     381   1066328363 :     SET_REGNO_REG_SET (reg_set_bitmap, DF_REF_REGNO (def));
     382    148183430 : }
     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      1515405 : compute_hash_table_work (struct hash_table_d *table)
     397              : {
     398      1515405 :   basic_block bb;
     399              : 
     400              :   /* Allocate vars to track sets of regs.  */
     401      1515405 :   reg_set_bitmap = ALLOC_REG_SET (NULL);
     402              : 
     403     33064911 :   FOR_EACH_BB_FN (bb, cfun)
     404              :     {
     405     31549506 :       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     31549506 :       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    369653597 :       FOR_BB_INSNS_REVERSE (bb, insn)
     415              :         {
     416              :           /* Only real insns are interesting.  */
     417    338104091 :           if (!NONDEBUG_INSN_P (insn))
     418    189920661 :             continue;
     419              : 
     420              :           /* Record interesting sets from INSN in the hash table.  */
     421    148183430 :           hash_scan_insn (insn, table);
     422              : 
     423              :           /* Any registers set in INSN will make SETs above it not AVAIL.  */
     424    148183430 :           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     31549506 :       if (implicit_sets[bb->index] != NULL_RTX)
     430      6387886 :         hash_scan_set (implicit_sets[bb->index], BB_HEAD (bb), table, true);
     431              :     }
     432              : 
     433      1515405 :   FREE_REG_SET (reg_set_bitmap);
     434      1515405 : }
     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      1515405 : alloc_hash_table (struct hash_table_d *table)
     441              : {
     442      1515405 :   int n;
     443              : 
     444      1515405 :   n = get_max_insn_count ();
     445              : 
     446      1515405 :   table->size = n / 4;
     447      1515405 :   if (table->size < 11)
     448       560649 :     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      1515405 :   table->size |= 1;
     454      1515405 :   n = table->size * sizeof (struct cprop_expr *);
     455      1515405 :   table->table = XNEWVAR (struct cprop_expr *, n);
     456      1515405 : }
     457              : 
     458              : /* Free things allocated by alloc_hash_table.  */
     459              : 
     460              : static void
     461      1515405 : free_hash_table (struct hash_table_d *table)
     462              : {
     463      1515405 :   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      1515405 : compute_hash_table (struct hash_table_d *table)
     471              : {
     472              :   /* Initialize count of number of entries in hash table.  */
     473      1515405 :   table->n_elems = 0;
     474      1515405 :   memset (table->table, 0, table->size * sizeof (struct cprop_expr *));
     475              : 
     476      1515405 :   compute_hash_table_work (table);
     477      1515405 : }
     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     96537497 : lookup_set (unsigned int regno, struct hash_table_d *table)
     486              : {
     487     96537497 :   unsigned int hash = hash_mod (regno, table->size);
     488     96537497 :   struct cprop_expr *expr;
     489              : 
     490     96537497 :   expr = table->table[hash];
     491              : 
     492    104656074 :   while (expr && REGNO (expr->dest) != regno)
     493      8118577 :     expr = expr->next_same_hash;
     494              : 
     495     96537497 :   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     43753083 :   do
     504     43753083 :     expr = expr->next_same_hash;
     505     86625308 :   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     29496259 : 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    169769545 : 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    261374519 : mark_oprs_set (rtx_insn *insn)
     535              : {
     536    261374519 :   df_ref def;
     537              : 
     538   1214268653 :   FOR_EACH_INSN_DEF (def, insn)
     539    952894134 :     SET_REGNO_REG_SET (reg_set_bitmap, DF_REF_REGNO (def));
     540    261374519 : }
     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      1362609 : alloc_cprop_mem (int n_blocks, int n_sets)
     557              : {
     558      1362609 :   cprop_avloc = sbitmap_vector_alloc (n_blocks, n_sets);
     559      1362609 :   cprop_kill = sbitmap_vector_alloc (n_blocks, n_sets);
     560              : 
     561      1362609 :   cprop_avin = sbitmap_vector_alloc (n_blocks, n_sets);
     562      1362609 :   cprop_avout = sbitmap_vector_alloc (n_blocks, n_sets);
     563      1362609 : }
     564              : 
     565              : /* Free vars used by copy/const propagation.  */
     566              : 
     567              : static void
     568      1362609 : free_cprop_mem (void)
     569              : {
     570      1362609 :   sbitmap_vector_free (cprop_avloc);
     571      1362609 :   sbitmap_vector_free (cprop_kill);
     572      1362609 :   sbitmap_vector_free (cprop_avin);
     573      1362609 :   sbitmap_vector_free (cprop_avout);
     574      1362609 : }
     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      1362609 : compute_local_properties (sbitmap *kill, sbitmap *comp,
     592              :                           struct hash_table_d *table)
     593              : {
     594      1362609 :   unsigned int i;
     595              : 
     596              :   /* Initialize the bitmaps that were passed in.  */
     597      1362609 :   bitmap_vector_clear (kill, last_basic_block_for_fn (cfun));
     598      1362609 :   bitmap_vector_clear (comp, last_basic_block_for_fn (cfun));
     599              : 
     600     66781206 :   for (i = 0; i < table->size; i++)
     601              :     {
     602     65418597 :       struct cprop_expr *expr;
     603              : 
     604     79740476 :       for (expr = table->table[i]; expr != NULL; expr = expr->next_same_hash)
     605              :         {
     606     14321879 :           int indx = expr->bitmap_index;
     607     14321879 :           df_ref def;
     608     14321879 :           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     14321879 :           for (def = DF_REG_DEF_CHAIN (REGNO (expr->dest));
     613     80515691 :                def; def = DF_REF_NEXT_REG (def))
     614     66193812 :             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     14321879 :           if (REG_P (expr->src))
     619      2286415 :             for (def = DF_REG_DEF_CHAIN (REGNO (expr->src));
     620      6711834 :                  def; def = DF_REF_NEXT_REG (def))
     621      4425419 :               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     30504893 :           for (occr = expr->avail_occr; occr != NULL; occr = occr->next)
     626              :             {
     627     16183014 :               bitmap_set_bit (comp[BLOCK_FOR_INSN (occr->insn)->index], indx);
     628              :             }
     629              :         }
     630              :     }
     631      1362609 : }
     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      1362609 : compute_cprop_data (void)
     640              : {
     641      1362609 :   basic_block bb;
     642              : 
     643      1362609 :   compute_local_properties (cprop_kill, cprop_avloc, &set_hash_table);
     644      1362609 :   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     32221477 :   FOR_EACH_BB_FN (bb, cfun)
     652              :     {
     653     30858868 :       int index = implicit_set_indexes[bb->index];
     654     30858868 :       if (index != -1)
     655      6308954 :         bitmap_set_bit (cprop_avin[bb->index], index);
     656              :     }
     657      1362609 : }
     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   1131437515 : find_used_regs (rtx *xptr, void *data ATTRIBUTE_UNUSED)
     680              : {
     681   1131437515 :   int i, j;
     682   1131437515 :   enum rtx_code code;
     683   1131437515 :   const char *fmt;
     684   1131437515 :   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   1584684498 :  repeat:
     689   1584684498 :   if (x == 0)
     690              :     return;
     691              : 
     692   1584684498 :   code = GET_CODE (x);
     693   1584684498 :   if (REG_P (x))
     694              :     {
     695    356422641 :       if (reg_use_count == MAX_USES)
     696              :         return;
     697              : 
     698    356398252 :       reg_use_table[reg_use_count] = x;
     699    356398252 :       reg_use_count++;
     700              :     }
     701              : 
     702              :   /* Recursively scan the operands of this expression.  */
     703              : 
     704   3273102310 :   for (i = GET_RTX_LENGTH (code) - 1, fmt = GET_RTX_FORMAT (code); i >= 0; i--)
     705              :     {
     706   2141689184 :       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    953019135 :           if (i == 0)
     712              :             {
     713    453246983 :               x = XEXP (x, 0);
     714    453246983 :               goto repeat;
     715              :             }
     716              : 
     717    499772152 :           find_used_regs (&XEXP (x, i), data);
     718              :         }
     719   1188670049 :       else if (fmt[i] == 'E')
     720     30951226 :         for (j = 0; j < XVECLEN (x, i); j++)
     721     22314354 :           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      7778794 : try_replace_reg (rtx from, rtx to, rtx_insn *insn)
     730              : {
     731      7778794 :   rtx note = find_reg_equal_equiv_note (insn);
     732      7778794 :   rtx src = 0;
     733      7778794 :   bool success = false;
     734      7778794 :   rtx set = single_set (insn);
     735              : 
     736      7778794 :   bool check_rtx_costs = true;
     737      7778794 :   bool speed = optimize_bb_for_speed_p (BLOCK_FOR_INSN (insn));
     738      7778794 :   int old_cost = set ? set_rtx_cost (set, speed) : 0;
     739              : 
     740      7230040 :   if (!set
     741      7230040 :       || CONSTANT_P (SET_SRC (set))
     742      7194345 :       || (note != 0
     743      2674885 :           && REG_NOTE_KIND (note) == REG_EQUAL
     744      2674885 :           && (GET_CODE (XEXP (note, 0)) == CONST
     745      2665318 :               || 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      7778794 :   to = copy_rtx (to);
     752              : 
     753      7778794 :   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      7778794 :   if (check_rtx_costs
     760      6385184 :       && CONSTANT_P (to)
     761     12003762 :       && set_rtx_cost (set, speed) > old_cost)
     762              :     {
     763      2951863 :       cancel_changes (0);
     764      2951863 :       return false;
     765              :     }
     766              : 
     767              : 
     768      4826931 :   if (num_changes_pending () && apply_change_group ())
     769              :     success = true;
     770              : 
     771              :   /* Try to simplify SET_SRC if we have substituted a constant.  */
     772      4826931 :   if (success && set && CONSTANT_P (to))
     773              :     {
     774       367043 :       src = simplify_rtx (SET_SRC (set));
     775              : 
     776       367043 :       if (src)
     777         6417 :         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      4826931 :   if (note != 0 && REG_NOTE_KIND (note) == REG_EQUAL)
     783      2175205 :     set_unique_reg_note (insn, REG_EQUAL,
     784              :                          simplify_replace_rtx (XEXP (note, 0), from, to));
     785      4826931 :   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      1631458 :       src = simplify_replace_rtx (SET_SRC (set), from, to);
     791              : 
     792      1631458 :       if (!rtx_equal_p (src, SET_SRC (set))
     793      1631458 :           && 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       166137 :       if (!success && note == 0 && set != 0 && REG_P (SET_DEST (set))
     800      1795265 :           && !contains_paradoxical_subreg_p (SET_SRC (set)))
     801       147178 :         note = set_unique_reg_note (insn, REG_EQUAL, copy_rtx (src));
     802              :     }
     803              : 
     804      4826931 :   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         2404 :       rtx dest = simplify_replace_rtx (SET_DEST (set), from, to);
     810              : 
     811         2404 :       if (!rtx_equal_p (dest, SET_DEST (set))
     812         2404 :           && 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      4826931 :   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     93535339 : find_avail_set (int regno, rtx_insn *insn, struct cprop_expr *set_ret[2])
     833              : {
     834     93535339 :   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     95101025 :   while (1)
     846              :     {
     847     94318182 :       rtx src;
     848     94318182 :       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     94318182 :       while (set)
     853              :         {
     854     42725239 :           if (bitmap_bit_p (cprop_avin[BLOCK_FOR_INSN (insn)->index],
     855              :                         set->bitmap_index))
     856              :             break;
     857    134732644 :           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      2310777 :       if (set == 0)
     863              :         break;
     864              : 
     865      2310777 :       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      2310777 :       if (cprop_constant_p (src))
     875      1527934 :         set_ret[1] = set;
     876       782843 :       else if (reg_not_set_p (src, insn))
     877       779272 :         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      2310777 :       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       782843 :       regno = REGNO (src);
     887       782843 :     }
     888     93535339 : }
     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       635887 : cprop_jump (basic_block bb, rtx_insn *setcc, rtx_insn *jump, rtx from, rtx src)
     899              : {
     900       635887 :   rtx new_rtx, set_src, note_src;
     901       635887 :   rtx set = pc_set (jump);
     902       635887 :   rtx note = find_reg_equal_equiv_note (jump);
     903              : 
     904       635887 :   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       635887 :   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       635887 :   if (setcc != NULL_RTX
     918       635887 :       && !modified_between_p (from, setcc, jump)
     919      1271774 :       && !modified_between_p (src, setcc, jump))
     920              :     {
     921       635887 :       rtx setcc_src;
     922       635887 :       rtx setcc_set = single_set (setcc);
     923       635887 :       rtx setcc_note = find_reg_equal_equiv_note (setcc);
     924       635887 :       setcc_src = (setcc_note && GET_CODE (XEXP (setcc_note, 0)) != EXPR_LIST)
     925       635887 :                 ? XEXP (setcc_note, 0) : SET_SRC (setcc_set);
     926       635887 :       set_src = simplify_replace_rtx (set_src, SET_DEST (setcc_set),
     927              :                                       setcc_src);
     928              :     }
     929              :   else
     930              :     setcc = NULL;
     931              : 
     932       635887 :   new_rtx = simplify_replace_rtx (set_src, from, src);
     933              : 
     934              :   /* If no simplification can be made, then try the next register.  */
     935       635887 :   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       632508 :   if (new_rtx == pc_rtx)
     940         2023 :     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       630485 :       if (setcc && modified_in_p (new_rtx, setcc))
     946              :         return false;
     947         2105 :       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            0 :           return false;
     961              :         }
     962              : 
     963              :       /* Remove REG_EQUAL note after simplification.  */
     964         2105 :       if (note_src)
     965            0 :         remove_note (jump, note);
     966              :      }
     967              : 
     968         4128 :   global_const_prop_count++;
     969         4128 :   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         4128 :   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         4128 :   if (new_rtx != pc_rtx && simplejump_p (jump))
     983              :     {
     984         2105 :       edge e;
     985         2105 :       edge_iterator ei;
     986              : 
     987         2105 :       FOR_EACH_EDGE (e, ei, bb->succs)
     988         2105 :         if (e->dest != EXIT_BLOCK_PTR_FOR_FN (cfun)
     989         2105 :             && BB_HEAD (e->dest) == JUMP_LABEL (jump))
     990              :           {
     991         2105 :             e->flags |= EDGE_FALLTHRU;
     992         2105 :             break;
     993              :           }
     994         2105 :       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      5455013 : constprop_register (rtx from, rtx src, rtx_insn *insn)
    1006              : {
    1007      5455013 :   rtx sset;
    1008      5455013 :   rtx_insn *next_insn;
    1009              : 
    1010              :   /* Check for reg setting instructions followed by conditional branch
    1011              :      instructions first.  */
    1012      5455013 :   if ((sset = single_set (insn)) != NULL
    1013      5011184 :       && (next_insn = next_nondebug_insn (insn)) != NULL
    1014      5008958 :       && any_condjump_p (next_insn)
    1015      6090906 :       && onlyjump_p (next_insn))
    1016              :     {
    1017       635893 :       rtx dest = SET_DEST (sset);
    1018       635893 :       if (REG_P (dest)
    1019       635893 :           && cprop_jump (BLOCK_FOR_INSN (insn), insn, next_insn,
    1020              :                          from, src))
    1021              :         return true;
    1022              :     }
    1023              : 
    1024              :   /* Handle normal insns next.  */
    1025      5450885 :   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      5071515 :   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    261374519 : cprop_insn (rtx_insn *insn)
    1044              : {
    1045    261374519 :   unsigned i;
    1046    261374519 :   int changed_this_round;
    1047    261374519 :   bool changed = false;
    1048    262274269 :   rtx note;
    1049              : 
    1050    262274269 :   do
    1051              :     {
    1052    262274269 :       changed_this_round = 0;
    1053    262274269 :       reg_use_count = 0;
    1054    262274269 :       note_uses (&PATTERN (insn), find_used_regs, NULL);
    1055              : 
    1056              :       /* We may win even when propagating constants into notes.  */
    1057    262274269 :       note = find_reg_equal_equiv_note (insn);
    1058    262274269 :       if (note)
    1059      6912439 :         find_used_regs (&XEXP (note, 0), NULL);
    1060              : 
    1061    431260971 :       for (i = 0; i < reg_use_count; i++)
    1062              :         {
    1063    168986702 :           rtx reg_used = reg_use_table[i];
    1064    168986702 :           unsigned int regno = REGNO (reg_used);
    1065    168986702 :           rtx src_cst = NULL, src_reg = NULL;
    1066    168986702 :           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    168986702 :           if (! reg_not_set_p (reg_used, insn))
    1071     75451363 :             continue;
    1072              : 
    1073              :           /* Find an assignment that sets reg_used and is available
    1074              :              at the start of the block.  */
    1075     93535339 :           find_avail_set (regno, insn, set);
    1076     93535339 :           if (set[0])
    1077       777670 :             src_reg = set[0]->src;
    1078     93535339 :           if (set[1])
    1079      1527934 :             src_cst = set[1]->src;
    1080              : 
    1081              :           /* Constant propagation.  */
    1082      1527934 :           if (src_cst && cprop_constant_p (src_cst)
    1083      3055868 :               && constprop_register (reg_used, src_cst, insn))
    1084              :             {
    1085       152454 :               changed = true;
    1086       152454 :               changed_this_round = 1;
    1087       152454 :               global_const_prop_count++;
    1088       152454 :               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       152454 :               if (insn->deleted ())
    1098            0 :                 return true;
    1099              :             }
    1100              :           /* Copy propagation.  */
    1101     93535339 :           else if (src_reg && cprop_reg_p (src_reg)
    1102       777011 :                    && REGNO (src_reg) != regno
    1103     94159896 :                    && try_replace_reg (reg_used, src_reg, insn))
    1104              :             {
    1105       753670 :               changed = true;
    1106       753670 :               changed_this_round = 1;
    1107       753670 :               global_copy_prop_count++;
    1108       753670 :               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    262274269 :   while (changed_this_round);
    1127              : 
    1128    261374519 :   if (changed && DEBUG_INSN_P (insn))
    1129              :     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    324009796 : local_cprop_find_used_regs (rtx *xptr, void *data)
    1141              : {
    1142    324009796 :   rtx x = *xptr;
    1143              : 
    1144    324009796 :   if (x == 0)
    1145              :     return;
    1146              : 
    1147    324009796 :   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      1007995 :     case SUBREG:
    1166      1007995 :       if (read_modify_subreg_p (x))
    1167              :         return;
    1168              :       break;
    1169              : 
    1170              :     default:
    1171              :       break;
    1172              :     }
    1173              : 
    1174    318960785 :   find_used_regs (xptr, data);
    1175              : }
    1176              : 
    1177              : /* Try to perform local const/copy propagation on X in INSN.  */
    1178              : 
    1179              : static bool
    1180    185022798 : do_local_cprop (rtx x, rtx_insn *insn)
    1181              : {
    1182    185022798 :   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    185022798 :   if (REG_P (x)
    1187    185022798 :       && (cprop_reg_p (x)
    1188     60464770 :           || (GET_CODE (PATTERN (insn)) != USE
    1189     59734299 :               && asm_noperands (PATTERN (insn)) < 0)))
    1190              :     {
    1191    184265788 :       cselib_val *val = cselib_lookup (x, GET_MODE (x), 0, VOIDmode);
    1192    184265788 :       struct elt_loc_list *l;
    1193              : 
    1194    184265788 :       if (!val)
    1195              :         return false;
    1196    205348304 :       for (l = val->locs; l; l = l->next)
    1197              :         {
    1198    132749778 :           rtx this_rtx = l->loc;
    1199    132749778 :           rtx note;
    1200              : 
    1201    132749778 :           if (cprop_constant_p (this_rtx))
    1202      3927079 :             newcnst = this_rtx;
    1203    265499556 :           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     51537096 :               && (!(note = find_reg_note (l->setting_insn, REG_EQUIV, NULL_RTX))
    1210         3120 :                   || ! MEM_P (XEXP (note, 0))))
    1211              :             newreg = this_rtx;
    1212              :         }
    1213     72598526 :       if (newcnst && constprop_register (x, newcnst, insn))
    1214              :         {
    1215       231044 :           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       231044 :           local_const_prop_count++;
    1225       231044 :           return true;
    1226              :         }
    1227     72367482 :       else if (newreg && newreg != x && try_replace_reg (x, newreg, insn))
    1228              :         {
    1229      1565378 :           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      1565378 :           local_copy_prop_count++;
    1237      1565378 :           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      1515405 : local_cprop_pass (void)
    1247              : {
    1248      1515405 :   basic_block bb;
    1249      1515405 :   rtx_insn *insn;
    1250      1515405 :   bool changed = false;
    1251      1515405 :   unsigned i;
    1252              : 
    1253      1515405 :   auto_vec<rtx_insn *> uncond_traps;
    1254              : 
    1255      1515405 :   cselib_init (0);
    1256     30509952 :   FOR_EACH_BB_FN (bb, cfun)
    1257              :     {
    1258    364036126 :       FOR_BB_INSNS (bb, insn)
    1259              :         {
    1260    335041579 :           if (INSN_P (insn))
    1261              :             {
    1262    289537922 :               bool was_uncond_trap
    1263    289537922 :                 = (GET_CODE (PATTERN (insn)) == TRAP_IF
    1264    289537922 :                    && XEXP (PATTERN (insn), 0) == const1_rtx);
    1265    289537922 :               rtx note = find_reg_equal_equiv_note (insn);
    1266    291334344 :               do
    1267              :                 {
    1268    291334344 :                   reg_use_count = 0;
    1269    291334344 :                   note_uses (&PATTERN (insn), local_cprop_find_used_regs,
    1270              :                              NULL);
    1271    291334344 :                   if (note)
    1272      9428465 :                     local_cprop_find_used_regs (&XEXP (note, 0), NULL);
    1273              : 
    1274    474560720 :                   for (i = 0; i < reg_use_count; i++)
    1275              :                     {
    1276    185022798 :                       if (do_local_cprop (reg_use_table[i], insn))
    1277              :                         {
    1278      1796422 :                           if (!DEBUG_INSN_P (insn))
    1279      1758316 :                             changed = true;
    1280              :                           break;
    1281              :                         }
    1282              :                     }
    1283    291334344 :                   if (!was_uncond_trap
    1284    291319949 :                       && GET_CODE (PATTERN (insn)) == TRAP_IF
    1285    291334344 :                       && XEXP (PATTERN (insn), 0) == const1_rtx)
    1286              :                     {
    1287            0 :                       uncond_traps.safe_push (insn);
    1288            0 :                       break;
    1289              :                     }
    1290    291334344 :                   if (insn->deleted ())
    1291              :                     break;
    1292              :                 }
    1293    291334344 :               while (i < reg_use_count);
    1294              :             }
    1295    335041579 :           cselib_process_insn (insn);
    1296              :         }
    1297              : 
    1298              :       /* Forget everything at the end of a basic block.  */
    1299     28994547 :       cselib_clear_table ();
    1300              :     }
    1301              : 
    1302      1515405 :   cselib_finish ();
    1303              : 
    1304      3030810 :   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      1515405 :   return changed;
    1313      1515405 : }
    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     20407934 : fis_get_condition (rtx_insn *jump)
    1327              : {
    1328     20407934 :   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     13087672 : implicit_set_cond_p (const_rtx cond)
    1336              : {
    1337     13087672 :   machine_mode mode;
    1338     13087672 :   rtx cst;
    1339              : 
    1340              :   /* COND must be either an EQ or NE comparison.  */
    1341     13087672 :   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     13096460 :   if (!cprop_reg_p (XEXP (cond, 0)))
    1346              :     return false;
    1347              : 
    1348              :   /* The second operand of COND must be a suitable constant.  */
    1349      8650509 :   mode = GET_MODE (XEXP (cond, 0));
    1350      8650509 :   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      8650509 :   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            6 :         return false;
    1366              :     }
    1367              : 
    1368      8650503 :   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      1515405 : find_implicit_sets (void)
    1385              : {
    1386      1515405 :   basic_block bb, dest;
    1387      1515405 :   rtx cond, new_rtx;
    1388      1515405 :   unsigned int count = 0;
    1389      1515405 :   bool edges_split = false;
    1390      1515405 :   size_t implicit_sets_size = last_basic_block_for_fn (cfun) + 10;
    1391              : 
    1392      1515405 :   implicit_sets = XCNEWVEC (rtx, implicit_sets_size);
    1393              : 
    1394     33064911 :   FOR_EACH_BB_FN (bb, cfun)
    1395              :     {
    1396              :       /* Check for more than one successor.  */
    1397     31549506 :       if (EDGE_COUNT (bb->succs) <= 1)
    1398     15982361 :         continue;
    1399              : 
    1400     15567145 :       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     15567145 :       if (! cond || ! implicit_set_cond_p (cond))
    1405      9179259 :         continue;
    1406              : 
    1407      6387886 :       dest = GET_CODE (cond) == EQ
    1408      6387886 :         ? BRANCH_EDGE (bb)->dest : FALLTHRU_EDGE (bb)->dest;
    1409              : 
    1410              :       /* If DEST doesn't go anywhere, ignore it.  */
    1411      6387886 :       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      6387886 :       if (! single_pred_p (dest))
    1419              :         {
    1420      2556221 :           dest = split_edge (find_edge (bb, dest));
    1421      2556221 :           edges_split = true;
    1422              :         }
    1423              : 
    1424      6387886 :       if (implicit_sets_size <= (size_t) dest->index)
    1425              :       {
    1426        45370 :         size_t old_implicit_sets_size = implicit_sets_size;
    1427        45370 :         implicit_sets_size *= 2;
    1428        45370 :         implicit_sets = XRESIZEVEC (rtx, implicit_sets, implicit_sets_size);
    1429        45370 :         memset (implicit_sets + old_implicit_sets_size, 0,
    1430        45370 :                 (implicit_sets_size - old_implicit_sets_size) * sizeof (rtx));
    1431              :       }
    1432              : 
    1433      6387886 :       new_rtx = gen_rtx_SET (XEXP (cond, 0), XEXP (cond, 1));
    1434      6387886 :       implicit_sets[dest->index] = new_rtx;
    1435      6387886 :       if (dump_file)
    1436              :         {
    1437           30 :           fprintf (dump_file, "Implicit set of reg %d in ",
    1438           30 :                    REGNO (XEXP (cond, 0)));
    1439           30 :           fprintf (dump_file, "basic block %d\n", dest->index);
    1440              :         }
    1441      6387886 :       count++;
    1442              :     }
    1443              : 
    1444      1515405 :   if (dump_file)
    1445           63 :     fprintf (dump_file, "Found %d implicit sets\n", count);
    1446              : 
    1447              :   /* Confess our sins.  */
    1448      1515405 :   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              : /* Find a set of REGNO to a constant that is available at the end of basic
    1461              :    block BB.  Return NULL if no such set is found.  Based heavily upon
    1462              :    find_avail_set.  */
    1463              : 
    1464              : static struct cprop_expr *
    1465      2087035 : find_bypass_set (int regno, int bb)
    1466              : {
    1467      2087035 :   struct cprop_expr *result = 0;
    1468              : 
    1469      2351595 :   for (;;)
    1470              :     {
    1471      2219315 :       rtx src;
    1472      2219315 :       struct cprop_expr *set = lookup_set (regno, &set_hash_table);
    1473              : 
    1474      2219315 :       while (set)
    1475              :         {
    1476      2809123 :           if (bitmap_bit_p (cprop_avout[bb], set->bitmap_index))
    1477              :             break;
    1478      4677078 :           set = next_set (regno, set);
    1479              :         }
    1480              : 
    1481       351360 :       if (set == 0)
    1482              :         break;
    1483              : 
    1484       351360 :       src = set->src;
    1485       351360 :       if (cprop_constant_p (src))
    1486       219080 :         result = set;
    1487              : 
    1488       351360 :       if (! REG_P (src))
    1489              :         break;
    1490              : 
    1491       132280 :       regno = REGNO (src);
    1492       132280 :     }
    1493      2087035 :   return result;
    1494              : }
    1495              : 
    1496              : /* Subroutine of bypass_block that checks whether a pseudo is killed by
    1497              :    any of the instructions inserted on an edge.  Jump bypassing places
    1498              :    condition code setters on CFG edges using insert_insn_on_edge.  This
    1499              :    function is required to check that our data flow analysis is still
    1500              :    valid prior to commit_edge_insertions.  */
    1501              : 
    1502              : static bool
    1503         2593 : reg_killed_on_edge (const_rtx reg, const_edge e)
    1504              : {
    1505         2593 :   rtx_insn *insn;
    1506              : 
    1507         9223 :   for (insn = e->insns.r; insn; insn = NEXT_INSN (insn))
    1508         6630 :     if (INSN_P (insn) && reg_set_p (reg, insn))
    1509              :       return true;
    1510              : 
    1511              :   return false;
    1512              : }
    1513              : 
    1514              : /* Subroutine of bypass_conditional_jumps that attempts to bypass the given
    1515              :    basic block BB which has more than one predecessor.  If not NULL, SETCC
    1516              :    is the first instruction of BB, which is immediately followed by JUMP_INSN
    1517              :    JUMP.  Otherwise, SETCC is NULL, and JUMP is the first insn of BB.
    1518              :    Returns true if a change was made.
    1519              : 
    1520              :    During the jump bypassing pass, we may place copies of SETCC instructions
    1521              :    on CFG edges.  The following routine must be careful to pay attention to
    1522              :    these inserted insns when performing its transformations.  */
    1523              : 
    1524              : static bool
    1525       843088 : bypass_block (basic_block bb, rtx_insn *setcc, rtx_insn *jump)
    1526              : {
    1527       843088 :   rtx_insn *insn;
    1528       843088 :   rtx setcc_src, setcc_dest;
    1529       843088 :   rtx note;
    1530       843088 :   edge e, edest;
    1531       843088 :   bool change;
    1532       843088 :   bool may_be_loop_header = false;
    1533       843088 :   bool removed_p;
    1534       843088 :   unsigned i;
    1535       843088 :   edge_iterator ei;
    1536              : 
    1537       843088 :   if (setcc != NULL)
    1538              :     {
    1539       842931 :       rtx set = single_set (setcc);
    1540       842931 :       setcc_dest = SET_DEST (set);
    1541       842931 :       setcc_src = SET_SRC (set);
    1542       842931 :       insn = setcc;
    1543              :     }
    1544              :   else
    1545              :     {
    1546              :       setcc_dest = NULL;
    1547              :       setcc_src = NULL;
    1548              :       insn = jump;
    1549              :     }
    1550              : 
    1551              :   /* Determine set of register uses in INSN.  */
    1552       843088 :   reg_use_count = 0;
    1553       843088 :   note_uses (&PATTERN (insn), find_used_regs, NULL);
    1554       843088 :   note = find_reg_equal_equiv_note (insn);
    1555       843088 :   if (note)
    1556         2987 :     find_used_regs (&XEXP (note, 0), NULL);
    1557              : 
    1558       843088 :   if (current_loops)
    1559              :     {
    1560              :       /* If we are to preserve loop structure then do not bypass
    1561              :          a loop header.  This will either rotate the loop, create
    1562              :          multiple entry loops or even irreducible regions.  */
    1563       593922 :       if (bb == bb->loop_father->header)
    1564              :         return 0;
    1565              :     }
    1566              :   else
    1567              :     {
    1568       743226 :       FOR_EACH_EDGE (e, ei, bb->preds)
    1569       563257 :         if (e->flags & EDGE_DFS_BACK)
    1570              :           {
    1571              :             may_be_loop_header = true;
    1572              :             break;
    1573              :           }
    1574              :     }
    1575              : 
    1576       711934 :   change = false;
    1577      2468623 :   for (ei = ei_start (bb->preds); (e = ei_safe_edge (ei)); )
    1578              :     {
    1579      1756689 :       removed_p = false;
    1580              : 
    1581      1756689 :       if (e->flags & EDGE_COMPLEX)
    1582              :         {
    1583         3562 :           ei_next (&ei);
    1584         3562 :           continue;
    1585              :         }
    1586              : 
    1587              :       /* We can't redirect edges from new basic blocks.  */
    1588      1753127 :       if (e->src->index >= bypass_last_basic_block)
    1589              :         {
    1590            0 :           ei_next (&ei);
    1591            0 :           continue;
    1592              :         }
    1593              : 
    1594              :       /* The irreducible loops created by redirecting of edges entering the
    1595              :          loop from outside would decrease effectiveness of some of the
    1596              :          following optimizations, so prevent this.  */
    1597      1753127 :       if (may_be_loop_header
    1598       148977 :           && !(e->flags & EDGE_DFS_BACK))
    1599              :         {
    1600        71701 :           ei_next (&ei);
    1601        71701 :           continue;
    1602              :         }
    1603              : 
    1604      3616222 :       for (i = 0; i < reg_use_count; i++)
    1605              :         {
    1606      2087035 :           rtx reg_used = reg_use_table[i];
    1607      2087035 :           unsigned int regno = REGNO (reg_used);
    1608      2087035 :           basic_block dest, old_dest;
    1609      2087035 :           struct cprop_expr *set;
    1610      2087035 :           rtx src, new_rtx;
    1611              : 
    1612      2087035 :           set = find_bypass_set (regno, e->src->index);
    1613              : 
    1614      2087035 :           if (! set)
    1615      1867955 :             continue;
    1616              : 
    1617              :           /* Check the data flow is valid after edge insertions.  */
    1618       219080 :           if (e->insns.r && reg_killed_on_edge (reg_used, e))
    1619            0 :             continue;
    1620              : 
    1621       219080 :           src = SET_SRC (pc_set (jump));
    1622              : 
    1623       219080 :           if (setcc != NULL)
    1624       219042 :             src = simplify_replace_rtx (src, setcc_dest, setcc_src);
    1625              : 
    1626       219080 :           new_rtx = simplify_replace_rtx (src, reg_used, set->src);
    1627              : 
    1628              :           /* Jump bypassing may have already placed instructions on
    1629              :              edges of the CFG.  We can't bypass an outgoing edge that
    1630              :              has instructions associated with it, as these insns won't
    1631              :              get executed if the incoming edge is redirected.  */
    1632       219080 :           if (new_rtx == pc_rtx)
    1633              :             {
    1634        76775 :               edest = FALLTHRU_EDGE (bb);
    1635        76775 :               dest = edest->insns.r ? NULL : edest->dest;
    1636              :             }
    1637       142305 :           else if (GET_CODE (new_rtx) == LABEL_REF)
    1638              :             {
    1639        75469 :               dest = BLOCK_FOR_INSN (XEXP (new_rtx, 0));
    1640              :               /* Don't bypass edges containing instructions.  */
    1641        75469 :               if (dest)
    1642              :                 {
    1643        75465 :                   edest = find_edge (bb, dest);
    1644        75465 :                   if (edest && edest->insns.r)
    1645        66841 :                     dest = NULL;
    1646              :                 }
    1647              :             }
    1648              :           else
    1649              :             dest = NULL;
    1650              : 
    1651              :           /* Avoid unification of the edge with other edges from original
    1652              :              branch.  We would end up emitting the instruction on "both"
    1653              :              edges.  */
    1654       219080 :           if (dest && setcc && find_edge (e->src, dest))
    1655              :             dest = NULL;
    1656              : 
    1657       219080 :           old_dest = e->dest;
    1658       219080 :           if (dest != NULL
    1659       219080 :               && dest != old_dest
    1660       152239 :               && dest != EXIT_BLOCK_PTR_FOR_FN (cfun))
    1661              :             {
    1662       152239 :               redirect_edge_and_branch_force (e, dest);
    1663              : 
    1664              :               /* Copy the register setter to the redirected edge.  */
    1665       152239 :               if (setcc)
    1666              :                 {
    1667       152225 :                   rtx pat = PATTERN (setcc);
    1668       152225 :                   insert_insn_on_edge (copy_insn (pat), e);
    1669              :                 }
    1670              : 
    1671       152239 :               if (dump_file != NULL)
    1672              :                 {
    1673            0 :                   fprintf (dump_file, "JUMP-BYPASS: Proved reg %d "
    1674              :                                       "in jump_insn %d equals constant ",
    1675            0 :                            regno, INSN_UID (jump));
    1676            0 :                   print_rtl (dump_file, set->src);
    1677            0 :                   fprintf (dump_file, "\n\t     when BB %d is entered from "
    1678              :                                       "BB %d.  Redirect edge %d->%d to %d.\n",
    1679            0 :                            old_dest->index, e->src->index, e->src->index,
    1680              :                            old_dest->index, dest->index);
    1681              :                 }
    1682              :               change = true;
    1683              :               removed_p = true;
    1684              :               break;
    1685              :             }
    1686              :         }
    1687      1681426 :       if (!removed_p)
    1688      1529187 :         ei_next (&ei);
    1689              :     }
    1690              :   return change;
    1691              : }
    1692              : 
    1693              : /* Find basic blocks with more than one predecessor that only contain a
    1694              :    single conditional jump.  If the result of the comparison is known at
    1695              :    compile-time from any incoming edge, redirect that edge to the
    1696              :    appropriate target.  Return nonzero if a change was made.
    1697              : 
    1698              :    This function is now mis-named, because we also handle indirect jumps.  */
    1699              : 
    1700              : static bool
    1701      1362609 : bypass_conditional_jumps (void)
    1702              : {
    1703      1362609 :   basic_block bb;
    1704      1362609 :   bool changed;
    1705      1362609 :   rtx_insn *setcc;
    1706      1362609 :   rtx_insn *insn;
    1707      1362609 :   rtx dest;
    1708              : 
    1709              :   /* Note we start at block 1.  */
    1710      1362609 :   if (ENTRY_BLOCK_PTR_FOR_FN (cfun)->next_bb == EXIT_BLOCK_PTR_FOR_FN (cfun))
    1711              :     return false;
    1712              : 
    1713      1362609 :   mark_dfs_back_edges ();
    1714              : 
    1715      1362609 :   changed = false;
    1716     30858868 :   FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR_FOR_FN (cfun)->next_bb->next_bb,
    1717              :                   EXIT_BLOCK_PTR_FOR_FN (cfun), next_bb)
    1718              :     {
    1719              :       /* Check for more than one predecessor.  */
    1720     29496259 :       if (!single_pred_p (bb))
    1721              :         {
    1722      7972256 :           setcc = NULL;
    1723     62432542 :           FOR_BB_INSNS (bb, insn)
    1724     61499014 :             if (DEBUG_INSN_P (insn))
    1725     32416685 :               continue;
    1726     29082329 :             else if (NONJUMP_INSN_P (insn))
    1727              :               {
    1728     11844344 :                 if (setcc)
    1729              :                   break;
    1730      7425598 :                 rtx singleset = single_set (insn);
    1731      7425598 :                 if (singleset == NULL_RTX)
    1732              :                   break;
    1733              : 
    1734      7329625 :                 dest = SET_DEST (singleset);
    1735      7329625 :                 if (REG_P (dest))
    1736              :                   setcc = insn;
    1737              :                 else
    1738              :                   break;
    1739              :               }
    1740     17237985 :             else if (JUMP_P (insn))
    1741              :               {
    1742       843487 :                 if ((any_condjump_p (insn) || computed_jump_p (insn))
    1743       843371 :                     && onlyjump_p (insn))
    1744       843088 :                   if (bypass_block (bb, setcc, insn))
    1745     29496259 :                     changed = true;
    1746              :                 break;
    1747              :               }
    1748     16394775 :             else if (INSN_P (insn))
    1749              :               break;
    1750              :         }
    1751              :     }
    1752              : 
    1753              :   /* If we bypassed any register setting insns, we inserted a
    1754              :      copy on the redirected edge.  These need to be committed.  */
    1755      1362609 :   if (changed)
    1756        43202 :     commit_edge_insertions ();
    1757              : 
    1758              :   return changed;
    1759              : }
    1760              : 
    1761              : /* Main function for the CPROP pass.  */
    1762              : 
    1763              : static bool
    1764      2889666 : one_cprop_pass (void)
    1765              : {
    1766      2889666 :   bool changed = false;
    1767      2889666 :   int i;
    1768              : 
    1769              :   /* Return if there's nothing to do, or it is too expensive.  */
    1770      2889666 :   if (n_basic_blocks_for_fn (cfun) <= NUM_FIXED_BLOCKS + 1
    1771      2889666 :       || gcse_or_cprop_is_too_expensive (_ ("const/copy propagation disabled")))
    1772      1374261 :     return false;
    1773              : 
    1774      1515405 :   global_const_prop_count = local_const_prop_count = 0;
    1775      1515405 :   global_copy_prop_count = local_copy_prop_count = 0;
    1776              : 
    1777      1515405 :   bytes_used = 0;
    1778      1515405 :   gcc_obstack_init (&cprop_obstack);
    1779              : 
    1780              :   /* Do a local const/copy propagation pass first.  The global pass
    1781              :      only handles global opportunities.
    1782              :      If the local pass changes something, remove any unreachable blocks
    1783              :      because the CPROP global dataflow analysis may get into infinite
    1784              :      loops for CFGs with unreachable blocks.
    1785              : 
    1786              :      FIXME: This local pass should not be necessary after CSE (but for
    1787              :             some reason it still is).  It is also (proven) not necessary
    1788              :             to run the local pass right after FWPWOP.
    1789              : 
    1790              :      FIXME: The global analysis would not get into infinite loops if it
    1791              :             would use the DF solver (via df_simple_dataflow) instead of
    1792              :             the solver implemented in this file.  */
    1793      1515405 :   if (local_cprop_pass ())
    1794       218995 :     changed = true;
    1795              : 
    1796       218995 :   if (changed)
    1797       218995 :     delete_unreachable_blocks ();
    1798              : 
    1799              :   /* Determine implicit sets.  This may change the CFG (split critical
    1800              :      edges if that exposes an implicit set).
    1801              :      Note that find_implicit_sets() does not rely on up-to-date DF caches
    1802              :      so that we do not have to re-run df_analyze() even if local CPROP
    1803              :      changed something.
    1804              :      ??? This could run earlier so that any uncovered implicit sets
    1805              :          sets could be exploited in local_cprop_pass() also.  Later.  */
    1806      1515405 :   if (find_implicit_sets ())
    1807              :     changed = true;
    1808              : 
    1809              :   /* If local_cprop_pass() or find_implicit_sets() changed something,
    1810              :      run df_analyze() to bring all insn caches up-to-date, and to take
    1811              :      new basic blocks from edge splitting on the DF radar.
    1812              :      NB: This also runs the fast DCE pass, because execute_rtl_cprop
    1813              :      sets DF_LR_RUN_DCE.  */
    1814       916683 :   if (changed)
    1815       689533 :     df_analyze ();
    1816              : 
    1817              :   /* Initialize implicit_set_indexes array.  */
    1818      1515405 :   implicit_set_indexes = XNEWVEC (int, last_basic_block_for_fn (cfun));
    1819     37560469 :   for (i = 0; i < last_basic_block_for_fn (cfun); i++)
    1820     36045064 :     implicit_set_indexes[i] = -1;
    1821              : 
    1822      1515405 :   alloc_hash_table (&set_hash_table);
    1823      1515405 :   compute_hash_table (&set_hash_table);
    1824              : 
    1825              :   /* Free implicit_sets before peak usage.  */
    1826      1515405 :   free (implicit_sets);
    1827      1515405 :   implicit_sets = NULL;
    1828              : 
    1829      1515405 :   if (dump_file)
    1830           63 :     dump_hash_table (dump_file, "SET", &set_hash_table);
    1831      1515405 :   if (set_hash_table.n_elems > 0)
    1832              :     {
    1833      1362609 :       basic_block bb;
    1834      1362609 :       auto_vec<rtx_insn *> uncond_traps;
    1835              : 
    1836      1362609 :       alloc_cprop_mem (last_basic_block_for_fn (cfun),
    1837              :                        set_hash_table.n_elems);
    1838      1362609 :       compute_cprop_data ();
    1839              : 
    1840      1362609 :       free (implicit_set_indexes);
    1841      1362609 :       implicit_set_indexes = NULL;
    1842              : 
    1843              :       /* Allocate vars to track sets of regs.  */
    1844      1362609 :       reg_set_bitmap = ALLOC_REG_SET (NULL);
    1845              : 
    1846     30858868 :       FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR_FOR_FN (cfun)->next_bb->next_bb,
    1847              :                       EXIT_BLOCK_PTR_FOR_FN (cfun),
    1848              :                       next_bb)
    1849              :         {
    1850     29496259 :           bool seen_uncond_trap = false;
    1851     29496259 :           rtx_insn *insn;
    1852              : 
    1853              :           /* Reset tables used to keep track of what's still valid [since
    1854              :              the start of the block].  */
    1855     29496259 :           reset_opr_set_tables ();
    1856              : 
    1857    336908331 :           FOR_BB_INSNS (bb, insn)
    1858    307412072 :             if (INSN_P (insn))
    1859              :               {
    1860    261374519 :                 bool was_uncond_trap
    1861    261374519 :                   = (GET_CODE (PATTERN (insn)) == TRAP_IF
    1862    261374519 :                      && XEXP (PATTERN (insn), 0) == const1_rtx);
    1863              : 
    1864    261374519 :                 if (cprop_insn (insn))
    1865       844360 :                   changed = true;
    1866              : 
    1867              :                 /* Keep track of everything modified by this insn.  */
    1868              :                 /* ??? Need to be careful w.r.t. mods done to INSN.
    1869              :                        Don't call mark_oprs_set if we turned the
    1870              :                        insn into a NOTE, or deleted the insn.  */
    1871    261374519 :                 if (! NOTE_P (insn) && ! insn->deleted ())
    1872    261374519 :                   mark_oprs_set (insn);
    1873              : 
    1874    261374519 :                 if (!was_uncond_trap
    1875    261361565 :                     && GET_CODE (PATTERN (insn)) == TRAP_IF
    1876    261374519 :                     && XEXP (PATTERN (insn), 0) == const1_rtx)
    1877              :                   {
    1878              :                     /* If we have already seen an unconditional trap
    1879              :                        earlier, the rest of the bb is going to be removed
    1880              :                        as unreachable.  Just turn it into a note, so that
    1881              :                        RTL verification doesn't complain about it before
    1882              :                        it is finally removed.  */
    1883            0 :                     if (seen_uncond_trap)
    1884            0 :                       set_insn_deleted (insn);
    1885              :                     else
    1886              :                       {
    1887            0 :                         seen_uncond_trap = true;
    1888            0 :                         uncond_traps.safe_push (insn);
    1889              :                       }
    1890              :                   }
    1891              :               }
    1892              :         }
    1893              : 
    1894              :       /* Make sure bypass_conditional_jumps will ignore not just its new
    1895              :          basic blocks, but also the ones after unconditional traps (those are
    1896              :          unreachable and will be eventually removed as such).  */
    1897      1362609 :       bypass_last_basic_block = last_basic_block_for_fn (cfun);
    1898              : 
    1899      1362609 :       while (!uncond_traps.is_empty ())
    1900              :         {
    1901            0 :           rtx_insn *insn = uncond_traps.pop ();
    1902            0 :           basic_block to_split = BLOCK_FOR_INSN (insn);
    1903            0 :           remove_edge (split_block (to_split, insn));
    1904            0 :           emit_barrier_after_bb (to_split);
    1905              :         }
    1906              : 
    1907      1362609 :       if (bypass_conditional_jumps ())
    1908        43202 :         changed = true;
    1909              : 
    1910      1362609 :       FREE_REG_SET (reg_set_bitmap);
    1911      1362609 :       free_cprop_mem ();
    1912      1362609 :     }
    1913              :   else
    1914              :     {
    1915       152796 :       free (implicit_set_indexes);
    1916       152796 :       implicit_set_indexes = NULL;
    1917              :     }
    1918              : 
    1919      1515405 :   free_hash_table (&set_hash_table);
    1920      1515405 :   obstack_free (&cprop_obstack, NULL);
    1921              : 
    1922      1515405 :   if (dump_file)
    1923              :     {
    1924           63 :       fprintf (dump_file, "CPROP of %s, %d basic blocks, %d bytes needed, ",
    1925           63 :                current_function_name (), n_basic_blocks_for_fn (cfun),
    1926              :                bytes_used);
    1927           63 :       fprintf (dump_file, "%d local const props, %d local copy props, ",
    1928              :                local_const_prop_count, local_copy_prop_count);
    1929           63 :       fprintf (dump_file, "%d global const props, %d global copy props\n\n",
    1930              :                global_const_prop_count, global_copy_prop_count);
    1931              :     }
    1932              : 
    1933              :   return changed;
    1934              : }
    1935              : 
    1936              : /* All the passes implemented in this file.  Each pass has its
    1937              :    own gate and execute function, and at the end of the file a
    1938              :    pass definition for passes.cc.
    1939              : 
    1940              :    We do not construct an accurate cfg in functions which call
    1941              :    setjmp, so none of these passes runs if the function calls
    1942              :    setjmp.
    1943              :    FIXME: Should just handle setjmp via REG_SETJMP notes.  */
    1944              : 
    1945              : static unsigned int
    1946      2889666 : execute_rtl_cprop (void)
    1947              : {
    1948      2889666 :   int changed;
    1949      2889666 :   delete_unreachable_blocks ();
    1950      2889666 :   df_set_flags (DF_LR_RUN_DCE);
    1951      2889666 :   df_analyze ();
    1952      2889666 :   changed = one_cprop_pass ();
    1953      2889666 :   flag_rerun_cse_after_global_opts |= changed;
    1954      2889666 :   if (changed)
    1955       727213 :     cleanup_cfg (CLEANUP_CFG_CHANGED);
    1956      2889666 :   return 0;
    1957              : }
    1958              : 
    1959              : namespace {
    1960              : 
    1961              : const pass_data pass_data_rtl_cprop =
    1962              : {
    1963              :   RTL_PASS, /* type */
    1964              :   "cprop", /* name */
    1965              :   OPTGROUP_NONE, /* optinfo_flags */
    1966              :   TV_CPROP, /* tv_id */
    1967              :   PROP_cfglayout, /* properties_required */
    1968              :   0, /* properties_provided */
    1969              :   0, /* properties_destroyed */
    1970              :   0, /* todo_flags_start */
    1971              :   TODO_df_finish, /* todo_flags_finish */
    1972              : };
    1973              : 
    1974              : class pass_rtl_cprop : public rtl_opt_pass
    1975              : {
    1976              : public:
    1977       857166 :   pass_rtl_cprop (gcc::context *ctxt)
    1978      1714332 :     : rtl_opt_pass (pass_data_rtl_cprop, ctxt)
    1979              :   {}
    1980              : 
    1981              :   /* opt_pass methods: */
    1982       571444 :   opt_pass * clone () final override { return new pass_rtl_cprop (m_ctxt); }
    1983      4414110 :   bool gate (function *fun) final override
    1984              :     {
    1985      3131058 :       return optimize > 0 && flag_gcse
    1986      2891748 :         && !fun->calls_setjmp
    1987      7303779 :         && dbg_cnt (cprop);
    1988              :     }
    1989              : 
    1990      2889666 :   unsigned int execute (function *) final override
    1991              :   {
    1992      2889666 :     return execute_rtl_cprop ();
    1993              :   }
    1994              : 
    1995              : }; // class pass_rtl_cprop
    1996              : 
    1997              : } // anon namespace
    1998              : 
    1999              : rtl_opt_pass *
    2000       285722 : make_pass_rtl_cprop (gcc::context *ctxt)
    2001              : {
    2002       285722 :   return new pass_rtl_cprop (ctxt);
    2003              : }
        

Generated by: LCOV version 2.4-beta

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