LCOV - code coverage report
Current view: top level - gcc - postreload.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 97.8 % 1059 1036
Test Date: 2026-10-17 16:30:31 Functions: 100.0 % 27 27
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /* Perform simple optimizations to clean up the result of reload.
       2              :    Copyright (C) 1987-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 "target.h"
      25              : #include "rtl.h"
      26              : #include "tree.h"
      27              : #include "predict.h"
      28              : #include "df.h"
      29              : #include "memmodel.h"
      30              : #include "tm_p.h"
      31              : #include "optabs.h"
      32              : #include "regs.h"
      33              : #include "emit-rtl.h"
      34              : #include "recog.h"
      35              : 
      36              : #include "cfghooks.h"
      37              : #include "cfgrtl.h"
      38              : #include "cfgbuild.h"
      39              : #include "cfgcleanup.h"
      40              : #include "reload.h"
      41              : #include "cselib.h"
      42              : #include "tree-pass.h"
      43              : #include "dbgcnt.h"
      44              : #include "function-abi.h"
      45              : #include "rtl-iter.h"
      46              : 
      47              : static bool reload_cse_simplify (rtx_insn *, rtx);
      48              : static void reload_cse_regs_1 (void);
      49              : static int reload_cse_simplify_set (rtx, rtx_insn *);
      50              : static int reload_cse_simplify_operands (rtx_insn *, rtx);
      51              : 
      52              : static void reload_combine (void);
      53              : static void reload_combine_note_use (rtx *, rtx_insn *, int, rtx);
      54              : static void reload_combine_note_store (rtx, const_rtx, void *);
      55              : 
      56              : static bool reload_cse_move2add (rtx_insn *);
      57              : static void move2add_note_store (rtx, const_rtx, void *);
      58              : 
      59              : /* Call cse / combine like post-reload optimization phases.
      60              :    FIRST is the first instruction.  */
      61              : 
      62              : static void
      63      1070192 : reload_cse_regs (rtx_insn *first ATTRIBUTE_UNUSED)
      64              : {
      65      1070192 :   bool moves_converted;
      66      1070192 :   reload_cse_regs_1 ();
      67      1070192 :   reload_combine ();
      68      1070192 :   moves_converted = reload_cse_move2add (first);
      69      1070192 :   if (flag_expensive_optimizations)
      70              :     {
      71       988491 :       if (moves_converted)
      72         6258 :         reload_combine ();
      73       988491 :       reload_cse_regs_1 ();
      74              :     }
      75      1070192 : }
      76              : 
      77              : /* Try to simplify INSN.  Return true if the CFG may have changed.  */
      78              : static bool
      79    225970634 : reload_cse_simplify (rtx_insn *insn, rtx testreg)
      80              : {
      81    225970634 :   rtx body = PATTERN (insn);
      82    225970634 :   basic_block insn_bb = BLOCK_FOR_INSN (insn);
      83    225970634 :   unsigned insn_bb_succs = EDGE_COUNT (insn_bb->succs);
      84              : 
      85              :   /* If NO_FUNCTION_CSE has been set by the target, then we should not try
      86              :      to cse function calls.  */
      87    225970634 :   if (NO_FUNCTION_CSE && CALL_P (insn))
      88              :     return false;
      89              : 
      90              :   /* Remember if this insn has been sp += const_int.  */
      91    216543885 :   rtx sp_set = set_for_reg_notes (insn);
      92    216543885 :   rtx sp_addend = NULL_RTX;
      93    216543885 :   if (sp_set
      94     70476263 :       && SET_DEST (sp_set) == stack_pointer_rtx
      95      3337663 :       && GET_CODE (SET_SRC (sp_set)) == PLUS
      96      3307197 :       && XEXP (SET_SRC (sp_set), 0) == stack_pointer_rtx
      97      3307094 :       && CONST_INT_P (XEXP (SET_SRC (sp_set), 1)))
      98    216543885 :     sp_addend = XEXP (SET_SRC (sp_set), 1);
      99              : 
     100    216543885 :   if (GET_CODE (body) == SET)
     101              :     {
     102     91016313 :       int count = 0;
     103              : 
     104              :       /* Simplify even if we may think it is a no-op.
     105              :          We may think a memory load of a value smaller than WORD_SIZE
     106              :          is redundant because we haven't taken into account possible
     107              :          implicit extension.  reload_cse_simplify_set() will bring
     108              :          this out, so it's safer to simplify before we delete.  */
     109     91016313 :       count += reload_cse_simplify_set (body, insn);
     110              : 
     111     91016313 :       if (!count && cselib_redundant_set_p (body))
     112              :         {
     113       242332 :           if (check_for_inc_dec (insn))
     114       242332 :             delete_insn_and_edges (insn);
     115              :           /* We're done with this insn.  */
     116       242332 :           goto done;
     117              :         }
     118              : 
     119     90773981 :       if (count > 0)
     120       151392 :         apply_change_group ();
     121              :       else
     122     90622589 :         reload_cse_simplify_operands (insn, testreg);
     123              :     }
     124    125527572 :   else if (GET_CODE (body) == PARALLEL)
     125              :     {
     126     14445730 :       int i;
     127     14445730 :       int count = 0;
     128     14445730 :       rtx value = NULL_RTX;
     129              : 
     130              :       /* Registers mentioned in the clobber list for an asm cannot be reused
     131              :          within the body of the asm.  Invalidate those registers now so that
     132              :          we don't try to substitute values for them.  */
     133     14445730 :       if (asm_noperands (body) >= 0)
     134              :         {
     135       583079 :           for (i = XVECLEN (body, 0) - 1; i >= 0; --i)
     136              :             {
     137       449520 :               rtx part = XVECEXP (body, 0, i);
     138       449520 :               if (GET_CODE (part) == CLOBBER && REG_P (XEXP (part, 0)))
     139       188390 :                 cselib_invalidate_rtx (XEXP (part, 0));
     140              :             }
     141              :         }
     142              : 
     143              :       /* If every action in a PARALLEL is a noop, we can delete
     144              :          the entire PARALLEL.  */
     145     28889392 :       for (i = XVECLEN (body, 0) - 1; i >= 0; --i)
     146              :         {
     147     28885505 :           rtx part = XVECEXP (body, 0, i);
     148     28885505 :           if (GET_CODE (part) == SET)
     149              :             {
     150     14354813 :               if (! cselib_redundant_set_p (part))
     151              :                 break;
     152         3952 :               if (REG_P (SET_DEST (part))
     153         3952 :                   && REG_FUNCTION_VALUE_P (SET_DEST (part)))
     154              :                 {
     155            0 :                   if (value)
     156              :                     break;
     157              :                   value = SET_DEST (part);
     158              :                 }
     159              :             }
     160     14530692 :           else if (GET_CODE (part) != CLOBBER && GET_CODE (part) != USE)
     161              :             break;
     162              :         }
     163              : 
     164     14445730 :       if (i < 0)
     165              :         {
     166         3887 :           if (check_for_inc_dec (insn))
     167         3887 :             delete_insn_and_edges (insn);
     168              :           /* We're done with this insn.  */
     169         3887 :           goto done;
     170              :         }
     171              : 
     172              :       /* It's not a no-op, but we can try to simplify it.  */
     173     44121350 :       for (i = XVECLEN (body, 0) - 1; i >= 0; --i)
     174     29679507 :         if (GET_CODE (XVECEXP (body, 0, i)) == SET)
     175     15152666 :           count += reload_cse_simplify_set (XVECEXP (body, 0, i), insn);
     176              : 
     177     14441843 :       if (count > 0)
     178         5654 :         apply_change_group ();
     179              :       else
     180     14436189 :         reload_cse_simplify_operands (insn, testreg);
     181              :     }
     182              : 
     183              :   /* If sp += const_int insn is changed into sp = reg;, add REG_EQUAL
     184              :      note so that the stack_adjustments pass can undo it if beneficial.  */
     185    216297666 :   if (sp_addend
     186      3307094 :       && SET_DEST (sp_set) == stack_pointer_rtx
     187      3307094 :       && REG_P (SET_SRC (sp_set)))
     188         3055 :     set_dst_reg_note (insn, REG_EQUAL,
     189         3055 :                       gen_rtx_PLUS (Pmode, stack_pointer_rtx,
     190              :                                     sp_addend), stack_pointer_rtx);
     191              : 
     192    216294611 : done:
     193    433084283 :   return (EDGE_COUNT (insn_bb->succs) != insn_bb_succs);
     194              : }
     195              : 
     196              : /* Do a very simple CSE pass over the hard registers.
     197              : 
     198              :    This function detects no-op moves where we happened to assign two
     199              :    different pseudo-registers to the same hard register, and then
     200              :    copied one to the other.  Reload will generate a useless
     201              :    instruction copying a register to itself.
     202              : 
     203              :    This function also detects cases where we load a value from memory
     204              :    into two different registers, and (if memory is more expensive than
     205              :    registers) changes it to simply copy the first register into the
     206              :    second register.
     207              : 
     208              :    Another optimization is performed that scans the operands of each
     209              :    instruction to see whether the value is already available in a
     210              :    hard register.  It then replaces the operand with the hard register
     211              :    if possible, much like an optional reload would.  */
     212              : 
     213              : static void
     214      2058683 : reload_cse_regs_1 (void)
     215              : {
     216      2058683 :   bool cfg_changed = false;
     217      2058683 :   basic_block bb;
     218      2058683 :   rtx_insn *insn;
     219      2058683 :   rtx testreg = gen_rtx_REG (word_mode, LAST_VIRTUAL_REGISTER + 1);
     220              : 
     221      2058683 :   cselib_init (CSELIB_RECORD_MEMORY);
     222      2058683 :   init_alias_analysis ();
     223              : 
     224     24063795 :   FOR_EACH_BB_FN (bb, cfun)
     225              :     {
     226              :       /* If BB has a small number of predecessors, see if each of the
     227              :          has the same implicit set.  If so, record that implicit set so
     228              :          that we can add it to the cselib tables.  */
     229     22005112 :       rtx_insn *implicit_set;
     230              : 
     231     22005112 :       implicit_set = NULL;
     232     22005112 :       if (EDGE_COUNT (bb->preds) <= 3)
     233              :         {
     234     21442610 :           edge e;
     235     21442610 :           edge_iterator ei;
     236     21442610 :           rtx src = NULL_RTX;
     237     21442610 :           rtx dest = NULL_RTX;
     238              : 
     239              :           /* Iterate over each incoming edge and see if they
     240              :              all have the same implicit set.  */
     241     25109061 :           FOR_EACH_EDGE (e, ei, bb->preds)
     242              :             {
     243              :               /* Skip the entry/exit block.  */
     244     22196569 :               if (e->src == ENTRY_BLOCK_PTR_FOR_FN (cfun))
     245              :                 break;
     246              : 
     247              :               /* Verify this block ends with a suitable condjump  */
     248     20137942 :               rtx_insn *condjump = BB_END (e->src);
     249     20137942 :               if (!condjump || ! any_condjump_p (condjump))
     250              :                 break;
     251              : 
     252              :               /* get_condition reverses the condition only when the else arm
     253              :                  is a LABEL_REF, so a jump that returns in one arm would give
     254              :                  the condition of the other edge.  */
     255     15293319 :               if (!JUMP_LABEL (condjump) || !LABEL_P (JUMP_LABEL (condjump)))
     256              :                 break;
     257              : 
     258              :               /* This predecessor ends with a possible equivalence
     259              :                  producing conditional branch.  Extract the condition
     260              :                  and try to use it to create an equivalence.  */
     261     15293319 :               rtx cond = get_condition (condjump, NULL, false, true);
     262     15293319 :               if (!cond)
     263              :                 break;
     264              : 
     265     14040458 :               if ((e->flags & EDGE_FALLTHRU) != 0
     266     14040458 :                   ? GET_CODE (cond) == NE
     267      5699841 :                   : GET_CODE (cond) == EQ)
     268              :                 {
     269              :                   /* If this is the first time through record
     270              :                      the source and destination.  */
     271      5729041 :                   if (!dest)
     272              :                     {
     273      5557629 :                       dest = XEXP (cond, 0);
     274      5557629 :                       src = XEXP (cond, 1);
     275              :                     }
     276              :                   /* If this is not the first time through, then
     277              :                      verify the source and destination match.  */
     278       171412 :                   else if (rtx_equal_p (dest, XEXP (cond, 0))
     279       171412 :                            && rtx_equal_p (src, XEXP (cond, 1)))
     280              :                     ;
     281              :                   else
     282              :                     break;
     283              : 
     284              :                   /* A few more checks.  First make sure we're dealing with
     285              :                      integer modes, second make sure the values aren't clobbered
     286              :                      by the conditional branch itself.  Do this for every
     287              :                      conditional jump participating in creation of the
     288              :                      equivalence.  */
     289      5627978 :                   if (!REG_P (dest)
     290      3921040 :                       || !(REG_P (src) || CONST_INT_P (src))
     291      3666455 :                       || GET_MODE_CLASS (GET_MODE (dest)) != MODE_INT
     292      3666451 :                       || reg_set_p (dest, condjump)
     293      9294429 :                       || reg_set_p (src, condjump))
     294              :                     break;
     295              : 
     296              :                 }
     297              :               else
     298              :                 break;
     299              :             }
     300              : 
     301              :           /* If all the incoming edges had the same implicit
     302              :              set, then create a dummy insn for that set.
     303              : 
     304              :              It will be entered into the cselib tables before
     305              :              we process the first real insn in this block.  */
     306     21442610 :           if (dest && ei_end_p (ei))
     307              :             {
     308      2912492 :               rtx_insn *i;
     309      2912492 :               bool useful = false;
     310     22340270 :               FOR_BB_INSNS (bb, i)
     311              :                 {
     312     20623996 :                   if (!NONDEBUG_INSN_P (i))
     313     12565287 :                     continue;
     314      8058709 :                   rtx s = single_set (i);
     315      8058709 :                   if (s
     316      7644998 :                       && rtx_equal_p (SET_DEST (s), dest)
     317      8575717 :                       && rtx_equal_p (SET_SRC (s), src))
     318              :                     {
     319              :                       useful = true;
     320              :                       break;
     321              :                     }
     322      8035720 :                   if (reg_set_p (dest, i))
     323              :                     break;
     324              :                 }
     325      2912492 :               if (useful)
     326        22989 :                 implicit_set = make_insn_raw (gen_rtx_SET (dest, src));
     327              :             }
     328              :         }
     329              : 
     330    293773145 :       FOR_BB_INSNS (bb, insn)
     331              :         {
     332    271768033 :           if (INSN_P (insn))
     333              :             {
     334              :               /* If we recorded an implicit set, enter it
     335              :                  into the tables before the first real insn.
     336              : 
     337              :                  We have to do it this way because a CODE_LABEL
     338              :                  will flush the cselib tables.  */
     339    225970634 :               if (implicit_set)
     340              :                 {
     341        22989 :                   cselib_process_insn (implicit_set);
     342        22989 :                   implicit_set = NULL;
     343              :                 }
     344    225970634 :               cfg_changed |= reload_cse_simplify (insn, testreg);
     345              :             }
     346              : 
     347    271768033 :           cselib_process_insn (insn);
     348              :         }
     349              :     }
     350              : 
     351              :   /* Clean up.  */
     352      2058683 :   end_alias_analysis ();
     353      2058683 :   cselib_finish ();
     354      2058683 :   if (cfg_changed)
     355           85 :     cleanup_cfg (0);
     356      2058683 : }
     357              : 
     358              : /* Try to simplify a single SET instruction.  SET is the set pattern.
     359              :    INSN is the instruction it came from.
     360              :    This function only handles one case: if we set a register to a value
     361              :    which is not a register, we try to find that value in some other register
     362              :    and change the set into a register copy.  */
     363              : 
     364              : static int
     365    106168979 : reload_cse_simplify_set (rtx set, rtx_insn *insn)
     366              : {
     367    106168979 :   int did_change = 0;
     368    106168979 :   int dreg;
     369    106168979 :   rtx src;
     370    106168979 :   reg_class_t dclass;
     371    106168979 :   int old_cost;
     372    106168979 :   cselib_val *val;
     373    106168979 :   struct elt_loc_list *l;
     374    106168979 :   enum rtx_code extend_op = UNKNOWN;
     375    106168979 :   bool speed = optimize_bb_for_speed_p (BLOCK_FOR_INSN (insn));
     376              : 
     377    106168979 :   dreg = true_regnum (SET_DEST (set));
     378    106168979 :   if (dreg < 0)
     379              :     return 0;
     380              : 
     381     71763235 :   src = SET_SRC (set);
     382     71763235 :   if (side_effects_p (src) || true_regnum (src) >= 0)
     383              :     return 0;
     384              : 
     385     60352675 :   dclass = REGNO_REG_CLASS (dreg);
     386              : 
     387              :   /* When replacing a memory with a register, we need to honor assumptions
     388              :      that combine made wrt the contents of sign bits.  We'll do this by
     389              :      generating an extend instruction instead of a reg->reg copy.  Thus
     390              :      the destination must be a register that we can widen.  */
     391     60352675 :   if (MEM_P (src)
     392              :       && (extend_op = load_extend_op (GET_MODE (src))) != UNKNOWN
     393              :       && !REG_P (SET_DEST (set)))
     394              :     return 0;
     395              : 
     396     60352675 :   val = cselib_lookup (src, GET_MODE (SET_DEST (set)), 0, VOIDmode);
     397     60352675 :   if (! val)
     398              :     return 0;
     399              : 
     400              :   /* If memory loads are cheaper than register copies, don't change them.  */
     401      5770900 :   if (MEM_P (src))
     402       641217 :     old_cost = memory_move_cost (GET_MODE (src), dclass, true);
     403      5129683 :   else if (REG_P (src))
     404            0 :     old_cost = register_move_cost (GET_MODE (src),
     405            0 :                                    REGNO_REG_CLASS (REGNO (src)), dclass);
     406              :   else
     407      5129683 :     old_cost = set_src_cost (src, GET_MODE (SET_DEST (set)), speed);
     408              : 
     409     11523175 :   for (l = val->locs; l; l = l->next)
     410              :     {
     411      5752275 :       rtx this_rtx = l->loc;
     412      5752275 :       int this_cost;
     413              : 
     414      5752275 :       if (CONSTANT_P (this_rtx) && ! references_value_p (this_rtx))
     415              :         {
     416      1983055 :           if (extend_op != UNKNOWN)
     417              :             {
     418              :               wide_int result;
     419              : 
     420              :               if (!CONST_SCALAR_INT_P (this_rtx))
     421              :                 continue;
     422              : 
     423              :               switch (extend_op)
     424              :                 {
     425              :                 case ZERO_EXTEND:
     426              :                   result = wide_int::from (rtx_mode_t (this_rtx,
     427              :                                                        GET_MODE (src)),
     428              :                                            BITS_PER_WORD, UNSIGNED);
     429              :                   break;
     430              :                 case SIGN_EXTEND:
     431              :                   result = wide_int::from (rtx_mode_t (this_rtx,
     432              :                                                        GET_MODE (src)),
     433              :                                            BITS_PER_WORD, SIGNED);
     434              :                   break;
     435              :                 default:
     436              :                   gcc_unreachable ();
     437              :                 }
     438              :               this_rtx = immed_wide_int_const (result, word_mode);
     439              :             }
     440              : 
     441      1983055 :           this_cost = set_src_cost (this_rtx, GET_MODE (SET_DEST (set)), speed);
     442              :         }
     443      3769220 :       else if (REG_P (this_rtx))
     444              :         {
     445       826185 :           if (extend_op != UNKNOWN)
     446              :             {
     447              :               this_rtx = gen_rtx_fmt_e (extend_op, word_mode, this_rtx);
     448              :               this_cost = set_src_cost (this_rtx, word_mode, speed);
     449              :             }
     450              :           else
     451       826185 :             this_cost = register_move_cost (GET_MODE (this_rtx),
     452       826185 :                                             REGNO_REG_CLASS (REGNO (this_rtx)),
     453              :                                             dclass);
     454              :         }
     455              :       else
     456      2943035 :         continue;
     457              : 
     458              :       /* If equal costs, prefer registers over anything else.  That
     459              :          tends to lead to smaller instructions on some machines.  */
     460      2809240 :       if (this_cost < old_cost
     461      2652684 :           || (this_cost == old_cost
     462      1988296 :               && REG_P (this_rtx)
     463        13336 :               && !REG_P (SET_SRC (set))))
     464              :         {
     465       157381 :           if (extend_op != UNKNOWN
     466              :               && REG_CAN_CHANGE_MODE_P (REGNO (SET_DEST (set)),
     467              :                                         GET_MODE (SET_DEST (set)), word_mode))
     468              :             {
     469              :               rtx wide_dest = gen_rtx_REG (word_mode, REGNO (SET_DEST (set)));
     470              :               ORIGINAL_REGNO (wide_dest) = ORIGINAL_REGNO (SET_DEST (set));
     471              :               validate_change (insn, &SET_DEST (set), wide_dest, 1);
     472              :             }
     473              : 
     474       157381 :           validate_unshare_change (insn, &SET_SRC (set), this_rtx, 1);
     475       157381 :           old_cost = this_cost, did_change = 1;
     476              :         }
     477              :     }
     478              : 
     479              :   return did_change;
     480              : }
     481              : 
     482              : /* Try to replace operands in INSN with equivalent values that are already
     483              :    in registers.  This can be viewed as optional reloading.
     484              : 
     485              :    For each non-register operand in the insn, see if any hard regs are
     486              :    known to be equivalent to that operand.  Record the alternatives which
     487              :    can accept these hard registers.  Among all alternatives, select the
     488              :    ones which are better or equal to the one currently matching, where
     489              :    "better" is in terms of '?' and '!' constraints.  Among the remaining
     490              :    alternatives, select the one which replaces most operands with
     491              :    hard registers.  */
     492              : 
     493              : static int
     494    105058778 : reload_cse_simplify_operands (rtx_insn *insn, rtx testreg)
     495              : {
     496    105058778 :   int i, j;
     497              : 
     498              :   /* For each operand, all registers that are equivalent to it.  */
     499    105058778 :   HARD_REG_SET equiv_regs[MAX_RECOG_OPERANDS];
     500              : 
     501    105058778 :   const char *constraints[MAX_RECOG_OPERANDS];
     502              : 
     503              :   /* Vector recording how bad an alternative is.  */
     504    105058778 :   int *alternative_reject;
     505              :   /* Vector recording how many registers can be introduced by choosing
     506              :      this alternative.  */
     507    105058778 :   int *alternative_nregs;
     508              :   /* Array of vectors recording, for each operand and each alternative,
     509              :      which hard register to substitute, or -1 if the operand should be
     510              :      left as it is.  */
     511    105058778 :   int *op_alt_regno[MAX_RECOG_OPERANDS];
     512              :   /* Array of alternatives, sorted in order of decreasing desirability.  */
     513    105058778 :   int *alternative_order;
     514              : 
     515    105058778 :   extract_constrain_insn (insn);
     516              : 
     517    105058778 :   if (recog_data.n_alternatives == 0 || recog_data.n_operands == 0)
     518              :     return 0;
     519              : 
     520     90774663 :   alternative_reject = XALLOCAVEC (int, recog_data.n_alternatives);
     521     90774663 :   alternative_nregs = XALLOCAVEC (int, recog_data.n_alternatives);
     522     90774663 :   alternative_order = XALLOCAVEC (int, recog_data.n_alternatives);
     523     90774663 :   memset (alternative_reject, 0, recog_data.n_alternatives * sizeof (int));
     524     90774663 :   memset (alternative_nregs, 0, recog_data.n_alternatives * sizeof (int));
     525              : 
     526              :   /* For each operand, find out which regs are equivalent.  */
     527    293511539 :   for (i = 0; i < recog_data.n_operands; i++)
     528              :     {
     529              :       cselib_val *v;
     530              :       struct elt_loc_list *l;
     531              :       rtx op;
     532              : 
     533    202736876 :       CLEAR_HARD_REG_SET (equiv_regs[i]);
     534              : 
     535              :       /* cselib blows up on CODE_LABELs.  Trying to fix that doesn't seem
     536              :          right, so avoid the problem here.  Similarly NOTE_INSN_DELETED_LABEL.
     537              :          Likewise if we have a constant and the insn pattern doesn't tell us
     538              :          the mode we need.  */
     539    202736876 :       if (LABEL_P (recog_data.operand[i])
     540    202722102 :           || (NOTE_P (recog_data.operand[i])
     541          116 :               && NOTE_KIND (recog_data.operand[i]) == NOTE_INSN_DELETED_LABEL)
     542    202721986 :           || (CONSTANT_P (recog_data.operand[i])
     543     34617855 :               && recog_data.operand_mode[i] == VOIDmode))
     544       644652 :         continue;
     545              : 
     546    202092224 :       op = recog_data.operand[i];
     547    202092224 :       if (MEM_P (op) && load_extend_op (GET_MODE (op)) != UNKNOWN)
     548              :         {
     549              :           rtx set = single_set (insn);
     550              : 
     551              :           /* We might have multiple sets, some of which do implicit
     552              :              extension.  Punt on this for now.  */
     553              :           if (! set)
     554              :             continue;
     555              :           /* If the destination is also a MEM or a STRICT_LOW_PART, no
     556              :              extension applies.
     557              :              Also, if there is an explicit extension, we don't have to
     558              :              worry about an implicit one.  */
     559              :           else if (MEM_P (SET_DEST (set))
     560              :                    || GET_CODE (SET_DEST (set)) == STRICT_LOW_PART
     561              :                    || GET_CODE (SET_SRC (set)) == ZERO_EXTEND
     562              :                    || GET_CODE (SET_SRC (set)) == SIGN_EXTEND)
     563              :             ; /* Continue ordinary processing.  */
     564              :           /* If the register cannot change mode to word_mode, it follows that
     565              :              it cannot have been used in word_mode.  */
     566              :           else if (REG_P (SET_DEST (set))
     567              :                    && !REG_CAN_CHANGE_MODE_P (REGNO (SET_DEST (set)),
     568              :                                               GET_MODE (SET_DEST (set)),
     569              :                                               word_mode))
     570              :             ; /* Continue ordinary processing.  */
     571              :           /* If this is a straight load, make the extension explicit.  */
     572              :           else if (REG_P (SET_DEST (set))
     573              :                    && recog_data.n_operands == 2
     574              :                    && SET_SRC (set) == op
     575              :                    && SET_DEST (set) == recog_data.operand[1-i])
     576              :             {
     577              :               validate_change (insn, recog_data.operand_loc[i],
     578              :                                gen_rtx_fmt_e (load_extend_op (GET_MODE (op)),
     579              :                                               word_mode, op),
     580              :                                1);
     581              :               validate_change (insn, recog_data.operand_loc[1-i],
     582              :                                gen_rtx_REG (word_mode, REGNO (SET_DEST (set))),
     583              :                                1);
     584              :               if (! apply_change_group ())
     585              :                 return 0;
     586              :               return reload_cse_simplify_operands (insn, testreg);
     587              :             }
     588              :           else
     589              :             /* ??? There might be arithmetic operations with memory that are
     590              :                safe to optimize, but is it worth the trouble?  */
     591              :             continue;
     592              :         }
     593              : 
     594    202092224 :       if (side_effects_p (op))
     595      4561917 :         continue;
     596    197530307 :       v = cselib_lookup (op, recog_data.operand_mode[i], 0, VOIDmode);
     597    197530307 :       if (! v)
     598    131024881 :         continue;
     599              : 
     600    196194698 :       for (l = v->locs; l; l = l->next)
     601    129689272 :         if (REG_P (l->loc))
     602     69127146 :           SET_HARD_REG_BIT (equiv_regs[i], REGNO (l->loc));
     603              :     }
     604              : 
     605     90774663 :   alternative_mask preferred = get_preferred_alternatives (insn);
     606    384286202 :   for (i = 0; i < recog_data.n_operands; i++)
     607              :     {
     608    202736876 :       machine_mode mode;
     609    202736876 :       int regno;
     610    202736876 :       const char *p;
     611              : 
     612    202736876 :       op_alt_regno[i] = XALLOCAVEC (int, recog_data.n_alternatives);
     613   3030562146 :       for (j = 0; j < recog_data.n_alternatives; j++)
     614   2827825270 :         op_alt_regno[i][j] = -1;
     615              : 
     616    202736876 :       p = constraints[i] = recog_data.constraints[i];
     617    202736876 :       mode = recog_data.operand_mode[i];
     618              : 
     619              :       /* Add the reject values for each alternative given by the constraints
     620              :          for this operand.  */
     621    202736876 :       j = 0;
     622   8151781539 :       while (*p != '\0')
     623              :         {
     624   7949044663 :           char c = *p++;
     625   7949044663 :           if (c == ',')
     626   2615180037 :             j++;
     627   5333864626 :           else if (c == '?')
     628    640920471 :             alternative_reject[j] += 3;
     629   4692944155 :           else if (c == '!')
     630     18257555 :             alternative_reject[j] += 300;
     631              :         }
     632              : 
     633              :       /* We won't change operands which are already registers.  We
     634              :          also don't want to modify output operands.  */
     635    202736876 :       regno = true_regnum (recog_data.operand[i]);
     636    202736876 :       if (regno >= 0
     637     80839588 :           || constraints[i][0] == '='
     638     60870020 :           || constraints[i][0] == '+')
     639    141982010 :         continue;
     640              : 
     641   5771712270 :       for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
     642              :         {
     643   5710957404 :           enum reg_class rclass = NO_REGS;
     644              : 
     645   5710957404 :           if (! TEST_HARD_REG_BIT (equiv_regs[i], regno))
     646   5710196825 :             continue;
     647              : 
     648       760579 :           set_mode_and_regno (testreg, mode, regno);
     649              : 
     650              :           /* We found a register equal to this operand.  Now look for all
     651              :              alternatives that can accept this register and have not been
     652              :              assigned a register they can use yet.  */
     653       760579 :           j = 0;
     654       760579 :           p = constraints[i];
     655     41933405 :           for (;;)
     656              :             {
     657     41933405 :               char c = *p;
     658              : 
     659     41933405 :               switch (c)
     660              :                 {
     661       190451 :                 case 'g':
     662       190451 :                   rclass = reg_class_subunion[rclass][GENERAL_REGS];
     663       190451 :                   break;
     664              : 
     665     26558924 :                 default:
     666     26558924 :                   rclass
     667     26558924 :                     = (reg_class_subunion
     668     26558924 :                        [rclass]
     669     26558924 :                        [reg_class_for_constraint (lookup_constraint (p))]);
     670     26558924 :                   break;
     671              : 
     672     15184030 :                 case ',': case '\0':
     673              :                   /* See if REGNO fits this alternative, and set it up as the
     674              :                      replacement register if we don't have one for this
     675              :                      alternative yet and the operand being replaced is not
     676              :                      a cheap CONST_INT.  */
     677     15184030 :                   if (op_alt_regno[i][j] == -1
     678     15116603 :                       && TEST_BIT (preferred, j)
     679     10281521 :                       && reg_fits_class_p (testreg, rclass, 0, mode)
     680     17687723 :                       && (!CONST_INT_P (recog_data.operand[i])
     681      2377575 :                           || (set_src_cost (recog_data.operand[i], mode,
     682              :                                             optimize_bb_for_speed_p
     683      2377575 :                                              (BLOCK_FOR_INSN (insn)))
     684      2377575 :                               > set_src_cost (testreg, mode,
     685              :                                               optimize_bb_for_speed_p
     686      2377575 :                                                (BLOCK_FOR_INSN (insn))))))
     687              :                     {
     688       126806 :                       alternative_nregs[j]++;
     689       126806 :                       op_alt_regno[i][j] = regno;
     690              :                     }
     691     15184030 :                   j++;
     692     15184030 :                   rclass = NO_REGS;
     693     15184030 :                   break;
     694              :                 }
     695     41933405 :               p += CONSTRAINT_LEN (c, p);
     696              : 
     697     41933405 :               if (c == '\0')
     698              :                 break;
     699              :             }
     700              :         }
     701              :     }
     702              : 
     703              :   /* The loop below sets alternative_order[0] but -Wmaybe-uninitialized
     704              :      can't know that.  Clear it here to avoid the warning.  */
     705     90774663 :   alternative_order[0] = 0;
     706     90774663 :   gcc_assert (!recog_data.n_alternatives
     707              :               || (which_alternative >= 0
     708              :                   && which_alternative < recog_data.n_alternatives));
     709              : 
     710              :   /* Record all alternatives which are better or equal to the currently
     711              :      matching one in the alternative_order array.  */
     712   1437168176 :   for (i = j = 0; i < recog_data.n_alternatives; i++)
     713   1346393513 :     if (alternative_reject[i] <= alternative_reject[which_alternative])
     714    783277185 :       alternative_order[j++] = i;
     715     90774663 :   recog_data.n_alternatives = j;
     716              : 
     717              :   /* Sort it.  Given a small number of alternatives, a dumb algorithm
     718              :      won't hurt too much.  */
     719    783277185 :   for (i = 0; i < recog_data.n_alternatives - 1; i++)
     720              :     {
     721    692502522 :       int best = i;
     722    692502522 :       int best_reject = alternative_reject[alternative_order[i]];
     723    692502522 :       int best_nregs = alternative_nregs[alternative_order[i]];
     724              : 
     725   4822629770 :       for (j = i + 1; j < recog_data.n_alternatives; j++)
     726              :         {
     727   4130127248 :           int this_reject = alternative_reject[alternative_order[j]];
     728   4130127248 :           int this_nregs = alternative_nregs[alternative_order[j]];
     729              : 
     730   4130127248 :           if (this_reject < best_reject
     731   4123774418 :               || (this_reject == best_reject && this_nregs > best_nregs))
     732              :             {
     733      6426420 :               best = j;
     734      6426420 :               best_reject = this_reject;
     735      6426420 :               best_nregs = this_nregs;
     736              :             }
     737              :         }
     738              : 
     739    692502522 :       std::swap (alternative_order[best], alternative_order[i]);
     740              :     }
     741              : 
     742              :   /* Substitute the operands as determined by op_alt_regno for the best
     743              :      alternative.  */
     744     90774663 :   j = alternative_order[0];
     745              : 
     746    293511539 :   for (i = 0; i < recog_data.n_operands; i++)
     747              :     {
     748    202736876 :       machine_mode mode = recog_data.operand_mode[i];
     749    202736876 :       if (op_alt_regno[i][j] == -1)
     750    202688261 :         continue;
     751              : 
     752        48615 :       validate_change (insn, recog_data.operand_loc[i],
     753              :                        gen_rtx_REG (mode, op_alt_regno[i][j]), 1);
     754              :     }
     755              : 
     756     92154186 :   for (i = recog_data.n_dups - 1; i >= 0; i--)
     757              :     {
     758      1379523 :       int op = recog_data.dup_num[i];
     759      1379523 :       machine_mode mode = recog_data.operand_mode[op];
     760              : 
     761      1379523 :       if (op_alt_regno[op][j] == -1)
     762      1379187 :         continue;
     763              : 
     764          336 :       validate_change (insn, recog_data.dup_loc[i],
     765              :                        gen_rtx_REG (mode, op_alt_regno[op][j]), 1);
     766              :     }
     767              : 
     768     90774663 :   return apply_change_group ();
     769              : }
     770              : 
     771              : /* If reload couldn't use reg+reg+offset addressing, try to use reg+reg
     772              :    addressing now.
     773              :    This code might also be useful when reload gave up on reg+reg addressing
     774              :    because of clashes between the return register and INDEX_REG_CLASS.  */
     775              : 
     776              : /* The maximum number of uses of a register we can keep track of to
     777              :    replace them with reg+reg addressing.  */
     778              : #define RELOAD_COMBINE_MAX_USES 16
     779              : 
     780              : /* Describes a recorded use of a register.  */
     781              : struct reg_use
     782              : {
     783              :   /* The insn where a register has been used.  */
     784              :   rtx_insn *insn;
     785              :   /* Points to the memory reference enclosing the use, if any, NULL_RTX
     786              :      otherwise.  */
     787              :   rtx containing_mem;
     788              :   /* Location of the register within INSN.  */
     789              :   rtx *usep;
     790              :   /* The reverse uid of the insn.  */
     791              :   int ruid;
     792              : };
     793              : 
     794              : /* If the register is used in some unknown fashion, USE_INDEX is negative.
     795              :    If it is dead, USE_INDEX is RELOAD_COMBINE_MAX_USES, and STORE_RUID
     796              :    indicates where it is first set or clobbered.
     797              :    Otherwise, USE_INDEX is the index of the last encountered use of the
     798              :    register (which is first among these we have seen since we scan backwards).
     799              :    USE_RUID indicates the first encountered, i.e. last, of these uses.
     800              :    If ALL_OFFSETS_MATCH is true, all encountered uses were inside a PLUS
     801              :    with a constant offset; OFFSET contains this constant in that case.
     802              :    STORE_RUID is always meaningful if we only want to use a value in a
     803              :    register in a different place: it denotes the next insn in the insn
     804              :    stream (i.e. the last encountered) that sets or clobbers the register.
     805              :    REAL_STORE_RUID is similar, but clobbers are ignored when updating it.
     806              :    EXPR is the expression used when storing the register.  */
     807              : static struct
     808              :   {
     809              :     struct reg_use reg_use[RELOAD_COMBINE_MAX_USES];
     810              :     rtx offset;
     811              :     int use_index;
     812              :     int store_ruid;
     813              :     int real_store_ruid;
     814              :     int use_ruid;
     815              :     bool all_offsets_match;
     816              :     rtx expr;
     817              :   } reg_state[FIRST_PSEUDO_REGISTER];
     818              : 
     819              : /* Reverse linear uid.  This is increased in reload_combine while scanning
     820              :    the instructions from last to first.  It is used to set last_label_ruid
     821              :    and the store_ruid / use_ruid fields in reg_state.  */
     822              : static int reload_combine_ruid;
     823              : 
     824              : /* The RUID of the last label we encountered in reload_combine.  */
     825              : static int last_label_ruid;
     826              : 
     827              : /* The RUID of the last jump we encountered in reload_combine.  */
     828              : static int last_jump_ruid;
     829              : 
     830              : /* The register numbers of the first and last index register.  A value of
     831              :    -1 in LAST_INDEX_REG indicates that we've previously computed these
     832              :    values and found no suitable index registers.  */
     833              : static int first_index_reg = -1;
     834              : static int last_index_reg;
     835              : 
     836              : #define LABEL_LIVE(LABEL) \
     837              :   (label_live[CODE_LABEL_NUMBER (LABEL) - min_labelno])
     838              : 
     839              : /* Subroutine of reload_combine_split_ruids, called to fix up a single
     840              :    ruid pointed to by *PRUID if it is higher than SPLIT_RUID.  */
     841              : 
     842              : static inline void
     843       169847 : reload_combine_split_one_ruid (int *pruid, int split_ruid)
     844              : {
     845       169847 :   if (*pruid > split_ruid)
     846         6751 :     (*pruid)++;
     847              : }
     848              : 
     849              : /* Called when we insert a new insn in a position we've already passed in
     850              :    the scan.  Examine all our state, increasing all ruids that are higher
     851              :    than SPLIT_RUID by one in order to make room for a new insn.  */
     852              : 
     853              : static void
     854          590 : reload_combine_split_ruids (int split_ruid)
     855              : {
     856          590 :   unsigned i;
     857              : 
     858          590 :   reload_combine_split_one_ruid (&reload_combine_ruid, split_ruid);
     859          590 :   reload_combine_split_one_ruid (&last_label_ruid, split_ruid);
     860          590 :   reload_combine_split_one_ruid (&last_jump_ruid, split_ruid);
     861              : 
     862        56050 :   for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
     863              :     {
     864        55460 :       int j, idx = reg_state[i].use_index;
     865        55460 :       reload_combine_split_one_ruid (&reg_state[i].use_ruid, split_ruid);
     866        55460 :       reload_combine_split_one_ruid (&reg_state[i].store_ruid, split_ruid);
     867        55460 :       reload_combine_split_one_ruid (&reg_state[i].real_store_ruid,
     868              :                                      split_ruid);
     869        55460 :       if (idx < 0)
     870        25277 :         continue;
     871        31880 :       for (j = idx; j < RELOAD_COMBINE_MAX_USES; j++)
     872              :         {
     873         2932 :           reload_combine_split_one_ruid (&reg_state[i].reg_use[j].ruid,
     874              :                                          split_ruid);
     875              :         }
     876              :     }
     877          590 : }
     878              : 
     879              : /* Called when we are about to rescan a previously encountered insn with
     880              :    reload_combine_note_use after modifying some part of it.  This clears all
     881              :    information about uses in that particular insn.  */
     882              : 
     883              : static void
     884         5148 : reload_combine_purge_insn_uses (rtx_insn *insn)
     885              : {
     886         5148 :   unsigned i;
     887              : 
     888       489060 :   for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
     889              :     {
     890       483912 :       int j, k, idx = reg_state[i].use_index;
     891       483912 :       if (idx < 0)
     892        86500 :         continue;
     893              :       j = k = RELOAD_COMBINE_MAX_USES;
     894       434038 :       while (j-- > idx)
     895              :         {
     896        36626 :           if (reg_state[i].reg_use[j].insn != insn)
     897              :             {
     898        30952 :               k--;
     899        30952 :               if (k != j)
     900         3365 :                 reg_state[i].reg_use[k] = reg_state[i].reg_use[j];
     901              :             }
     902              :         }
     903       397412 :       reg_state[i].use_index = k;
     904              :     }
     905         5148 : }
     906              : 
     907              : /* Called when we need to forget about all uses of REGNO after an insn
     908              :    which is identified by RUID.  */
     909              : 
     910              : static void
     911          590 : reload_combine_purge_reg_uses_after_ruid (unsigned regno, int ruid)
     912              : {
     913          590 :   int j, k, idx = reg_state[regno].use_index;
     914          590 :   if (idx < 0)
     915              :     return;
     916              :   j = k = RELOAD_COMBINE_MAX_USES;
     917         2272 :   while (j-- > idx)
     918              :     {
     919         1682 :       if (reg_state[regno].reg_use[j].ruid >= ruid)
     920              :         {
     921          692 :           k--;
     922          692 :           if (k != j)
     923          562 :             reg_state[regno].reg_use[k] = reg_state[regno].reg_use[j];
     924              :         }
     925              :     }
     926          590 :   reg_state[regno].use_index = k;
     927              : }
     928              : 
     929              : /* Find the use of REGNO with the ruid that is highest among those
     930              :    lower than RUID_LIMIT, and return it if it is the only use of this
     931              :    reg in the insn.  Return NULL otherwise.  */
     932              : 
     933              : static struct reg_use *
     934      3930367 : reload_combine_closest_single_use (unsigned regno, int ruid_limit)
     935              : {
     936      3930367 :   int i, best_ruid = 0;
     937      3930367 :   int use_idx = reg_state[regno].use_index;
     938      3930367 :   struct reg_use *retval;
     939              : 
     940      3930367 :   if (use_idx < 0)
     941              :     return NULL;
     942              :   retval = NULL;
     943      3827102 :   for (i = use_idx; i < RELOAD_COMBINE_MAX_USES; i++)
     944              :     {
     945      2216290 :       struct reg_use *use = reg_state[regno].reg_use + i;
     946      2216290 :       int this_ruid = use->ruid;
     947      2216290 :       if (this_ruid >= ruid_limit)
     948       819980 :         continue;
     949      1396310 :       if (this_ruid > best_ruid)
     950              :         {
     951              :           best_ruid = this_ruid;
     952              :           retval = use;
     953              :         }
     954       371150 :       else if (this_ruid == best_ruid)
     955      2216290 :         retval = NULL;
     956              :     }
     957      1610812 :   if (last_label_ruid >= best_ruid)
     958       665909 :     return NULL;
     959              :   return retval;
     960              : }
     961              : 
     962              : /* After we've moved an add insn, fix up any debug insns that occur
     963              :    between the old location of the add and the new location.  REG is
     964              :    the destination register of the add insn; REPLACEMENT is the
     965              :    SET_SRC of the add.  FROM and TO specify the range in which we
     966              :    should make this change on debug insns.  */
     967              : 
     968              : static void
     969          759 : fixup_debug_insns (rtx reg, rtx replacement, rtx_insn *from, rtx_insn *to)
     970              : {
     971          759 :   rtx_insn *insn;
     972         6136 :   for (insn = from; insn != to; insn = NEXT_INSN (insn))
     973              :     {
     974         5377 :       rtx t;
     975              : 
     976         5377 :       if (!DEBUG_BIND_INSN_P (insn))
     977         4199 :         continue;
     978              : 
     979         1178 :       t = INSN_VAR_LOCATION_LOC (insn);
     980         1178 :       t = simplify_replace_rtx (t, reg, replacement);
     981         1178 :       validate_change (insn, &INSN_VAR_LOCATION_LOC (insn), t, 0);
     982              :     }
     983          759 : }
     984              : 
     985              : /* Subroutine of reload_combine_recognize_const_pattern.  Try to replace REG
     986              :    with SRC in the insn described by USE, taking costs into account.  Return
     987              :    true if we made the replacement.  */
     988              : 
     989              : static bool
     990       807052 : try_replace_in_use (struct reg_use *use, rtx reg, rtx src)
     991              : {
     992       807052 :   rtx_insn *use_insn = use->insn;
     993       807052 :   rtx mem = use->containing_mem;
     994       807052 :   bool speed = optimize_bb_for_speed_p (BLOCK_FOR_INSN (use_insn));
     995              : 
     996       807052 :   if (mem != NULL_RTX)
     997              :     {
     998        14096 :       addr_space_t as = MEM_ADDR_SPACE (mem);
     999        14096 :       rtx oldaddr = XEXP (mem, 0);
    1000        14096 :       rtx newaddr = NULL_RTX;
    1001        14096 :       int old_cost = address_cost (oldaddr, GET_MODE (mem), as, speed);
    1002        14096 :       int new_cost;
    1003              : 
    1004        14096 :       newaddr = simplify_replace_rtx (oldaddr, reg, src);
    1005        14096 :       if (memory_address_addr_space_p (GET_MODE (mem), newaddr, as))
    1006              :         {
    1007         4712 :           XEXP (mem, 0) = newaddr;
    1008         4712 :           new_cost = address_cost (newaddr, GET_MODE (mem), as, speed);
    1009         4712 :           XEXP (mem, 0) = oldaddr;
    1010         4712 :           if (new_cost <= old_cost
    1011         4712 :               && validate_change (use_insn,
    1012              :                                   &XEXP (mem, 0), newaddr, 0))
    1013              :             return true;
    1014              :         }
    1015              :     }
    1016              :   else
    1017              :     {
    1018       792956 :       rtx new_set = single_set (use_insn);
    1019       792956 :       if (new_set
    1020       791975 :           && REG_P (SET_DEST (new_set))
    1021       330386 :           && GET_CODE (SET_SRC (new_set)) == PLUS
    1022        21562 :           && REG_P (XEXP (SET_SRC (new_set), 0))
    1023        19498 :           && CONSTANT_P (XEXP (SET_SRC (new_set), 1)))
    1024              :         {
    1025         1608 :           rtx new_src;
    1026         1608 :           machine_mode mode = GET_MODE (SET_DEST (new_set));
    1027         1608 :           int old_cost = set_src_cost (SET_SRC (new_set), mode, speed);
    1028              : 
    1029         1608 :           gcc_assert (rtx_equal_p (XEXP (SET_SRC (new_set), 0), reg));
    1030         1608 :           new_src = simplify_replace_rtx (SET_SRC (new_set), reg, src);
    1031              : 
    1032         1608 :           if (set_src_cost (new_src, mode, speed) <= old_cost
    1033         1608 :               && validate_change (use_insn, &SET_SRC (new_set),
    1034              :                                   new_src, 0))
    1035              :             return true;
    1036              :         }
    1037              :     }
    1038              :   return false;
    1039              : }
    1040              : 
    1041              : /* Called by reload_combine when scanning INSN.  This function tries to detect
    1042              :    patterns where a constant is added to a register, and the result is used
    1043              :    in an address.
    1044              :    Return true if no further processing is needed on INSN; false if it wasn't
    1045              :    recognized and should be handled normally.  */
    1046              : 
    1047              : static bool
    1048     62968008 : reload_combine_recognize_const_pattern (rtx_insn *insn)
    1049              : {
    1050     62968008 :   int from_ruid = reload_combine_ruid;
    1051     62968008 :   rtx set, pat, reg, src, addreg;
    1052     62968008 :   unsigned int regno;
    1053     62968008 :   struct reg_use *use;
    1054     62968008 :   bool must_move_add;
    1055     62968008 :   rtx_insn *add_moved_after_insn = NULL;
    1056     62968008 :   int add_moved_after_ruid = 0;
    1057     62968008 :   int clobbered_regno = -1;
    1058              : 
    1059     62968008 :   set = single_set (insn);
    1060     62968008 :   if (set == NULL_RTX)
    1061              :     return false;
    1062              : 
    1063     58700139 :   reg = SET_DEST (set);
    1064     58700139 :   src = SET_SRC (set);
    1065     58700139 :   if (!REG_P (reg)
    1066     40068221 :       || REG_NREGS (reg) != 1
    1067     45670493 :       || GET_MODE (reg) != Pmode
    1068     81662297 :       || reg == stack_pointer_rtx)
    1069              :     return false;
    1070              : 
    1071     21270275 :   regno = REGNO (reg);
    1072              : 
    1073              :   /* We look for a REG1 = REG2 + CONSTANT insn, followed by either
    1074              :      uses of REG1 inside an address, or inside another add insn.  If
    1075              :      possible and profitable, merge the addition into subsequent
    1076              :      uses.  */
    1077     21270275 :   if (GET_CODE (src) != PLUS
    1078      4172125 :       || !REG_P (XEXP (src, 0))
    1079      3915212 :       || !CONSTANT_P (XEXP (src, 1)))
    1080              :     return false;
    1081              : 
    1082      3237654 :   addreg = XEXP (src, 0);
    1083      3237654 :   must_move_add = rtx_equal_p (reg, addreg);
    1084              : 
    1085      3237654 :   pat = PATTERN (insn);
    1086      3237654 :   if (must_move_add && set != pat)
    1087              :     {
    1088              :       /* We have to be careful when moving the add; apart from the
    1089              :          single_set there may also be clobbers.  Recognize one special
    1090              :          case, that of one clobber alongside the set (likely a clobber
    1091              :          of the CC register).  */
    1092       877686 :       gcc_assert (GET_CODE (PATTERN (insn)) == PARALLEL);
    1093       877686 :       if (XVECLEN (pat, 0) != 2 || XVECEXP (pat, 0, 0) != set
    1094       877686 :           || GET_CODE (XVECEXP (pat, 0, 1)) != CLOBBER
    1095       877686 :           || !REG_P (XEXP (XVECEXP (pat, 0, 1), 0)))
    1096              :         return false;
    1097       877686 :       clobbered_regno = REGNO (XEXP (XVECEXP (pat, 0, 1), 0));
    1098              :     }
    1099              : 
    1100      3930367 :   do
    1101              :     {
    1102      3930367 :       use = reload_combine_closest_single_use (regno, from_ruid);
    1103              : 
    1104      3930367 :       if (use)
    1105              :         /* Start the search for the next use from here.  */
    1106       921909 :         from_ruid = use->ruid;
    1107              : 
    1108      1277372 :       if (use && GET_MODE (*use->usep) == Pmode)
    1109              :         {
    1110       915681 :           bool delete_add = false;
    1111       915681 :           rtx_insn *use_insn = use->insn;
    1112       915681 :           int use_ruid = use->ruid;
    1113              : 
    1114              :           /* Avoid moving the add insn past a jump.  */
    1115       915681 :           if (must_move_add && use_ruid <= last_jump_ruid)
    1116              :             break;
    1117              : 
    1118              :           /* If the add clobbers another hard reg in parallel, don't move
    1119              :              it past a real set of this hard reg.  */
    1120       915450 :           if (must_move_add && clobbered_regno >= 0
    1121       145034 :               && reg_state[clobbered_regno].real_store_ruid >= use_ruid)
    1122              :             break;
    1123              : 
    1124       878006 :           gcc_assert (reg_state[regno].store_ruid <= use_ruid);
    1125              :           /* Avoid moving a use of ADDREG past a point where it is stored.  */
    1126       878006 :           if (reg_state[REGNO (addreg)].store_ruid > use_ruid)
    1127              :             break;
    1128              : 
    1129              :           /* We also must not move the addition past an insn that sets
    1130              :              the same register, unless we can combine two add insns.  */
    1131       807058 :           if (must_move_add && reg_state[regno].store_ruid == use_ruid)
    1132              :             {
    1133        30843 :               if (use->containing_mem == NULL_RTX)
    1134              :                 delete_add = true;
    1135              :               else
    1136              :                 break;
    1137              :             }
    1138              : 
    1139       807052 :           if (try_replace_in_use (use, reg, src))
    1140              :             {
    1141         5148 :               reload_combine_purge_insn_uses (use_insn);
    1142         5148 :               reload_combine_note_use (&PATTERN (use_insn), use_insn,
    1143              :                                        use_ruid, NULL_RTX);
    1144              : 
    1145         5148 :               if (delete_add)
    1146              :                 {
    1147           53 :                   fixup_debug_insns (reg, src, insn, use_insn);
    1148           53 :                   delete_insn (insn);
    1149           53 :                   return true;
    1150              :                 }
    1151         5095 :               if (must_move_add)
    1152              :                 {
    1153          966 :                   add_moved_after_insn = use_insn;
    1154          966 :                   add_moved_after_ruid = use_ruid;
    1155              :                 }
    1156         5095 :               continue;
    1157              :             }
    1158              :         }
    1159              :       /* If we get here, we couldn't handle this use.  */
    1160      3816590 :       if (must_move_add)
    1161              :         break;
    1162              :     }
    1163      2949523 :   while (use);
    1164              : 
    1165      3237601 :   if (!must_move_add || add_moved_after_insn == NULL_RTX)
    1166              :     /* Process the add normally.  */
    1167              :     return false;
    1168              : 
    1169          590 :   fixup_debug_insns (reg, src, insn, add_moved_after_insn);
    1170              : 
    1171          590 :   reorder_insns (insn, insn, add_moved_after_insn);
    1172          590 :   reload_combine_purge_reg_uses_after_ruid (regno, add_moved_after_ruid);
    1173          590 :   reload_combine_split_ruids (add_moved_after_ruid - 1);
    1174          590 :   reload_combine_note_use (&PATTERN (insn), insn,
    1175              :                            add_moved_after_ruid, NULL_RTX);
    1176          590 :   reg_state[regno].store_ruid = add_moved_after_ruid;
    1177              : 
    1178          590 :   return true;
    1179              : }
    1180              : 
    1181              : /* Called by reload_combine when scanning INSN.  Try to detect a pattern we
    1182              :    can handle and improve.  Return true if no further processing is needed on
    1183              :    INSN; false if it wasn't recognized and should be handled normally.  */
    1184              : 
    1185              : static bool
    1186     62967365 : reload_combine_recognize_pattern (rtx_insn *insn)
    1187              : {
    1188     62967365 :   rtx set, reg, src;
    1189              : 
    1190     62967365 :   set = single_set (insn);
    1191     62967365 :   if (set == NULL_RTX)
    1192              :     return false;
    1193              : 
    1194     58699496 :   reg = SET_DEST (set);
    1195     58699496 :   src = SET_SRC (set);
    1196     58699496 :   if (!REG_P (reg) || REG_NREGS (reg) != 1)
    1197              :     return false;
    1198              : 
    1199     39354080 :   unsigned int regno = REGNO (reg);
    1200     39354080 :   machine_mode mode = GET_MODE (reg);
    1201              : 
    1202     39354080 :   if (reg_state[regno].use_index < 0
    1203     39354080 :       || reg_state[regno].use_index >= RELOAD_COMBINE_MAX_USES)
    1204              :     return false;
    1205              : 
    1206     25371923 :   for (int i = reg_state[regno].use_index;
    1207     46428582 :        i < RELOAD_COMBINE_MAX_USES; i++)
    1208              :     {
    1209     26200570 :       struct reg_use *use = reg_state[regno].reg_use + i;
    1210     26200570 :       if (GET_MODE (*use->usep) != mode)
    1211              :         return false;
    1212              :       /* Don't try to adjust (use (REGX)).  */
    1213     25375632 :       if (GET_CODE (PATTERN (use->insn)) == USE
    1214     25375632 :           && &XEXP (PATTERN (use->insn), 0) == use->usep)
    1215              :         return false;
    1216              :     }
    1217              : 
    1218              :   /* Look for (set (REGX) (CONST_INT))
    1219              :      (set (REGX) (PLUS (REGX) (REGY)))
    1220              :      ...
    1221              :      ... (MEM (REGX)) ...
    1222              :      and convert it to
    1223              :      (set (REGZ) (CONST_INT))
    1224              :      ...
    1225              :      ... (MEM (PLUS (REGZ) (REGY)))... .
    1226              : 
    1227              :      First, check that we have (set (REGX) (PLUS (REGX) (REGY)))
    1228              :      and that we know all uses of REGX before it dies.
    1229              :      Also, explicitly check that REGX != REGY; our life information
    1230              :      does not yet show whether REGY changes in this insn.  */
    1231              : 
    1232     20228012 :   if (GET_CODE (src) == PLUS
    1233      2416970 :       && reg_state[regno].all_offsets_match
    1234      2153970 :       && last_index_reg != -1
    1235      2153970 :       && REG_P (XEXP (src, 1))
    1236       720231 :       && rtx_equal_p (XEXP (src, 0), reg)
    1237       524505 :       && !rtx_equal_p (XEXP (src, 1), reg)
    1238     20744181 :       && last_label_ruid < reg_state[regno].use_ruid)
    1239              :     {
    1240       483507 :       rtx base = XEXP (src, 1);
    1241       483507 :       rtx_insn *prev = prev_nonnote_nondebug_insn (insn);
    1242       483507 :       rtx prev_set = prev ? single_set (prev) : NULL_RTX;
    1243       483507 :       rtx index_reg = NULL_RTX;
    1244       483507 :       rtx reg_sum = NULL_RTX;
    1245       483507 :       int i;
    1246              : 
    1247              :       /* Now we need to set INDEX_REG to an index register (denoted as
    1248              :          REGZ in the illustration above) and REG_SUM to the expression
    1249              :          register+register that we want to use to substitute uses of REG
    1250              :          (typically in MEMs) with.  First check REG and BASE for being
    1251              :          index registers; we can use them even if they are not dead.  */
    1252       483507 :       if (TEST_HARD_REG_BIT (reg_class_contents[INDEX_REG_CLASS], regno)
    1253       483507 :           || TEST_HARD_REG_BIT (reg_class_contents[INDEX_REG_CLASS],
    1254              :                                 REGNO (base)))
    1255              :         {
    1256              :           index_reg = reg;
    1257              :           reg_sum = src;
    1258              :         }
    1259              :       else
    1260              :         {
    1261              :           /* Otherwise, look for a free index register.  Since we have
    1262              :              checked above that neither REG nor BASE are index registers,
    1263              :              if we find anything at all, it will be different from these
    1264              :              two registers.  */
    1265      8968089 :           for (i = first_index_reg; i <= last_index_reg; i++)
    1266              :             {
    1267      8880357 :               if (TEST_HARD_REG_BIT (reg_class_contents[INDEX_REG_CLASS], i)
    1268      3053337 :                   && reg_state[i].use_index == RELOAD_COMBINE_MAX_USES
    1269      1755514 :                   && reg_state[i].store_ruid <= reg_state[regno].use_ruid
    1270      1739513 :                   && (crtl->abi->clobbers_full_reg_p (i)
    1271       332902 :                       || df_regs_ever_live_p (i))
    1272      1470443 :                   && (!frame_pointer_needed || i != HARD_FRAME_POINTER_REGNUM)
    1273      1469411 :                   && !fixed_regs[i] && !global_regs[i]
    1274       533307 :                   && hard_regno_nregs (i, GET_MODE (reg)) == 1
    1275      9014630 :                   && targetm.hard_regno_scratch_ok (i))
    1276              :                 {
    1277       134273 :                   index_reg = gen_rtx_REG (GET_MODE (reg), i);
    1278       134273 :                   reg_sum = gen_rtx_PLUS (GET_MODE (reg), index_reg, base);
    1279       134273 :                   break;
    1280              :                 }
    1281              :             }
    1282              :         }
    1283              : 
    1284              :       /* Check that PREV_SET is indeed (set (REGX) (CONST_INT)) and that
    1285              :          (REGY), i.e. BASE, is not clobbered before the last use we'll
    1286              :          create.  */
    1287       483507 :       if (reg_sum
    1288       483507 :           && prev_set
    1289       389083 :           && CONST_INT_P (SET_SRC (prev_set))
    1290         9819 :           && rtx_equal_p (SET_DEST (prev_set), reg)
    1291       483507 :           && (reg_state[REGNO (base)].store_ruid
    1292         3498 :               <= reg_state[regno].use_ruid))
    1293              :         {
    1294              :           /* Change destination register and, if necessary, the constant
    1295              :              value in PREV, the constant loading instruction.  */
    1296         3389 :           validate_change (prev, &SET_DEST (prev_set), index_reg, 1);
    1297         3389 :           if (reg_state[regno].offset != const0_rtx)
    1298              :             {
    1299            0 :               HOST_WIDE_INT c
    1300            0 :                 = trunc_int_for_mode (UINTVAL (SET_SRC (prev_set))
    1301            0 :                                       + UINTVAL (reg_state[regno].offset),
    1302            0 :                                       GET_MODE (index_reg));
    1303            0 :               validate_change (prev, &SET_SRC (prev_set), GEN_INT (c), 1);
    1304              :             }
    1305              : 
    1306              :           /* Now for every use of REG that we have recorded, replace REG
    1307              :              with REG_SUM.  */
    1308         6854 :           for (i = reg_state[regno].use_index;
    1309         6854 :                i < RELOAD_COMBINE_MAX_USES; i++)
    1310         3465 :             validate_unshare_change (reg_state[regno].reg_use[i].insn,
    1311              :                                      reg_state[regno].reg_use[i].usep,
    1312              :                                      /* Each change must have its own
    1313              :                                         replacement.  */
    1314              :                                      reg_sum, 1);
    1315              : 
    1316         3389 :           if (apply_change_group ())
    1317              :             {
    1318          116 :               struct reg_use *lowest_ruid = NULL;
    1319              : 
    1320              :               /* For every new use of REG_SUM, we have to record the use
    1321              :                  of BASE therein, i.e. operand 1.  */
    1322          252 :               for (i = reg_state[regno].use_index;
    1323          252 :                    i < RELOAD_COMBINE_MAX_USES; i++)
    1324              :                 {
    1325          136 :                   struct reg_use *use = reg_state[regno].reg_use + i;
    1326          136 :                   reload_combine_note_use (&XEXP (*use->usep, 1), use->insn,
    1327              :                                            use->ruid, use->containing_mem);
    1328          136 :                   if (lowest_ruid == NULL || use->ruid < lowest_ruid->ruid)
    1329          136 :                     lowest_ruid = use;
    1330              :                 }
    1331              : 
    1332          116 :               fixup_debug_insns (reg, reg_sum, insn, lowest_ruid->insn);
    1333              : 
    1334              :               /* Delete the reg-reg addition.  */
    1335          116 :               delete_insn (insn);
    1336              : 
    1337          116 :               if (reg_state[regno].offset != const0_rtx)
    1338              :                 /* Previous REG_EQUIV / REG_EQUAL notes for PREV
    1339              :                    are now invalid.  */
    1340            0 :                 remove_reg_equal_equiv_notes (prev);
    1341              : 
    1342          116 :               reg_state[regno].use_index = RELOAD_COMBINE_MAX_USES;
    1343          116 :               return true;
    1344              :             }
    1345              :         }
    1346              :     }
    1347              :   return false;
    1348              : }
    1349              : 
    1350              : static void
    1351      1076450 : reload_combine (void)
    1352              : {
    1353      1076450 :   rtx_insn *insn, *prev;
    1354      1076450 :   basic_block bb;
    1355      1076450 :   unsigned int r;
    1356      1076450 :   int min_labelno, n_labels;
    1357      1076450 :   HARD_REG_SET ever_live_at_start, *label_live;
    1358              : 
    1359              :   /* To avoid wasting too much time later searching for an index register,
    1360              :      determine the minimum and maximum index register numbers.  */
    1361      1076450 :   if (INDEX_REG_CLASS == NO_REGS)
    1362              :     last_index_reg = -1;
    1363      1076450 :   else if (first_index_reg == -1 && last_index_reg == 0)
    1364              :     {
    1365       148008 :       hard_reg_set_iterator hrsi1;
    1366      4736256 :       EXECUTE_IF_SET_IN_HARD_REG_SET
    1367              :         (reg_class_contents[INDEX_REG_CLASS], 0, r, hrsi1)
    1368              :         {
    1369      4588248 :           if (first_index_reg == -1)
    1370       148008 :             first_index_reg = r;
    1371              : 
    1372      4588248 :           last_index_reg = r;
    1373              :         }
    1374              : 
    1375              :       /* If no index register is available, we can quit now.  Set LAST_INDEX_REG
    1376              :          to -1 so we'll know to quit early the next time we get here.  */
    1377       148008 :       if (first_index_reg == -1)
    1378              :         {
    1379            0 :           last_index_reg = -1;
    1380            0 :           return;
    1381              :         }
    1382              :     }
    1383              : 
    1384              :   /* Set up LABEL_LIVE and EVER_LIVE_AT_START.  The register lifetime
    1385              :      information is a bit fuzzy immediately after reload, but it's
    1386              :      still good enough to determine which registers are live at a jump
    1387              :      destination.  */
    1388      1076450 :   min_labelno = get_first_label_num ();
    1389      1076450 :   n_labels = max_label_num () - min_labelno;
    1390      1076450 :   label_live = XNEWVEC (HARD_REG_SET, n_labels);
    1391      1076450 :   CLEAR_HARD_REG_SET (ever_live_at_start);
    1392              : 
    1393     12967476 :   FOR_EACH_BB_REVERSE_FN (bb, cfun)
    1394              :     {
    1395     11891026 :       insn = BB_HEAD (bb);
    1396     11891026 :       if (LABEL_P (insn))
    1397              :         {
    1398      5551707 :           HARD_REG_SET live;
    1399      5551707 :           bitmap live_in = df_get_live_in (bb);
    1400              : 
    1401     11103414 :           REG_SET_TO_HARD_REG_SET (live, live_in);
    1402      5551707 :           compute_use_by_pseudos (&live, live_in);
    1403      5551707 :           LABEL_LIVE (insn) = live;
    1404     11103414 :           ever_live_at_start |= live;
    1405              :         }
    1406              :     }
    1407              : 
    1408              :   /* Initialize last_label_ruid, reload_combine_ruid and reg_state.  */
    1409      1076450 :   last_label_ruid = last_jump_ruid = reload_combine_ruid = 0;
    1410    102262750 :   for (r = 0; r < FIRST_PSEUDO_REGISTER; r++)
    1411              :     {
    1412    101186300 :       reg_state[r].store_ruid = 0;
    1413    101186300 :       reg_state[r].real_store_ruid = 0;
    1414    101186300 :       if (fixed_regs[r])
    1415              :         reg_state[r].use_index = -1;
    1416              :       else
    1417     50042873 :         reg_state[r].use_index = RELOAD_COMBINE_MAX_USES;
    1418              :     }
    1419              : 
    1420    152313461 :   for (insn = get_last_insn (); insn; insn = prev)
    1421              :     {
    1422    151237011 :       bool control_flow_insn;
    1423    151237011 :       rtx note;
    1424              : 
    1425    151237011 :       prev = PREV_INSN (insn);
    1426              : 
    1427              :       /* We cannot do our optimization across labels.  Invalidating all the use
    1428              :          information we have would be costly, so we just note where the label
    1429              :          is and then later disable any optimization that would cross it.  */
    1430    151237011 :       if (LABEL_P (insn))
    1431      5559197 :         last_label_ruid = reload_combine_ruid;
    1432    145677814 :       else if (BARRIER_P (insn))
    1433              :         {
    1434              :           /* Crossing a barrier resets all the use information.  */
    1435    304492670 :           for (r = 0; r < FIRST_PSEUDO_REGISTER; r++)
    1436    301287484 :             if (! fixed_regs[r])
    1437    144094816 :               reg_state[r].use_index = RELOAD_COMBINE_MAX_USES;
    1438              :         }
    1439    142472628 :       else if (INSN_P (insn) && volatile_insn_p (PATTERN (insn)))
    1440              :         /* Optimizations across insns being marked as volatile must be
    1441              :            prevented.  All the usage information is invalidated
    1442              :            here.  */
    1443     42430990 :         for (r = 0; r < FIRST_PSEUDO_REGISTER; r++)
    1444     41984348 :           if (! fixed_regs[r]
    1445     19297392 :               && reg_state[r].use_index != RELOAD_COMBINE_MAX_USES)
    1446       648016 :             reg_state[r].use_index = -1;
    1447              : 
    1448    151237011 :       if (! NONDEBUG_INSN_P (insn))
    1449     88269003 :         continue;
    1450              : 
    1451     62968008 :       reload_combine_ruid++;
    1452              : 
    1453     62968008 :       control_flow_insn = control_flow_insn_p (insn);
    1454     62968008 :       if (control_flow_insn)
    1455      9117021 :         last_jump_ruid = reload_combine_ruid;
    1456              : 
    1457     62968008 :       if (reload_combine_recognize_const_pattern (insn)
    1458     62968008 :           || reload_combine_recognize_pattern (insn))
    1459          759 :         continue;
    1460              : 
    1461     62967249 :       note_stores (insn, reload_combine_note_store, NULL);
    1462              : 
    1463     62967249 :       if (CALL_P (insn))
    1464              :         {
    1465      5039645 :           rtx link;
    1466      5039645 :           HARD_REG_SET used_regs = insn_callee_abi (insn).full_reg_clobbers ();
    1467              : 
    1468      5039645 :           hard_reg_set_iterator hrsi2;
    1469    426794290 :           EXECUTE_IF_SET_IN_HARD_REG_SET (used_regs, 0, r, hrsi2)
    1470              :             {
    1471    421754645 :               reg_state[r].use_index = RELOAD_COMBINE_MAX_USES;
    1472    421754645 :               reg_state[r].store_ruid = reload_combine_ruid;
    1473              :             }
    1474              : 
    1475     15191493 :           for (link = CALL_INSN_FUNCTION_USAGE (insn); link;
    1476     10151848 :                link = XEXP (link, 1))
    1477              :             {
    1478     10151848 :               rtx setuse = XEXP (link, 0);
    1479     10151848 :               rtx usage_rtx = XEXP (setuse, 0);
    1480              : 
    1481     10151848 :               if (GET_CODE (setuse) == USE && REG_P (usage_rtx))
    1482              :                 {
    1483      9173708 :                   unsigned int end_regno = END_REGNO (usage_rtx);
    1484     18404955 :                   for (unsigned int i = REGNO (usage_rtx); i < end_regno; ++i)
    1485      9231247 :                     reg_state[i].use_index = -1;
    1486              :                  }
    1487              :              }
    1488              :         }
    1489              : 
    1490     62967249 :       if (control_flow_insn && !ANY_RETURN_P (PATTERN (insn)))
    1491              :         {
    1492              :           /* Non-spill registers might be used at the call destination in
    1493              :              some unknown fashion, so we have to mark the unknown use.  */
    1494      9117021 :           HARD_REG_SET *live;
    1495              : 
    1496     10600703 :           if ((condjump_p (insn) || condjump_in_parallel_p (insn))
    1497      9117095 :               && JUMP_LABEL (insn))
    1498              :             {
    1499      7633413 :               if (ANY_RETURN_P (JUMP_LABEL (insn)))
    1500              :                 live = NULL;
    1501              :               else
    1502      7633413 :                 live = &LABEL_LIVE (JUMP_LABEL (insn));
    1503              :             }
    1504              :           else
    1505              :             live = &ever_live_at_start;
    1506              : 
    1507      7633413 :           if (live)
    1508              :             {
    1509      9117021 :               hard_reg_set_iterator hrsi3;
    1510     55440160 :               EXECUTE_IF_SET_IN_HARD_REG_SET (*live, 0, r, hrsi3)
    1511     46323139 :                 reg_state[r].use_index = -1;
    1512              :             }
    1513              :         }
    1514              : 
    1515     62967249 :       reload_combine_note_use (&PATTERN (insn), insn, reload_combine_ruid,
    1516              :                                NULL_RTX);
    1517              : 
    1518     87662102 :       for (note = REG_NOTES (insn); note; note = XEXP (note, 1))
    1519              :         {
    1520     24694853 :           if (REG_NOTE_KIND (note) == REG_INC && REG_P (XEXP (note, 0)))
    1521              :             {
    1522            0 :               int regno = REGNO (XEXP (note, 0));
    1523            0 :               reg_state[regno].store_ruid = reload_combine_ruid;
    1524            0 :               reg_state[regno].real_store_ruid = reload_combine_ruid;
    1525            0 :               reg_state[regno].use_index = -1;
    1526              :             }
    1527              :         }
    1528              :     }
    1529              : 
    1530      1076450 :   free (label_live);
    1531              : }
    1532              : 
    1533              : /* Check if DST is a register or a subreg of a register; if it is,
    1534              :    update store_ruid, real_store_ruid and use_index in the reg_state
    1535              :    structure accordingly.  Called via note_stores from reload_combine.  */
    1536              : 
    1537              : static void
    1538     67373715 : reload_combine_note_store (rtx dst, const_rtx set, void *data ATTRIBUTE_UNUSED)
    1539              : {
    1540     67373715 :   int regno = 0;
    1541     67373715 :   int i;
    1542     67373715 :   machine_mode mode = GET_MODE (dst);
    1543              : 
    1544     67373715 :   if (GET_CODE (dst) == SUBREG)
    1545              :     {
    1546         5492 :       regno = subreg_regno_offset (REGNO (SUBREG_REG (dst)),
    1547         2746 :                                    GET_MODE (SUBREG_REG (dst)),
    1548         2746 :                                    SUBREG_BYTE (dst),
    1549              :                                    GET_MODE (dst));
    1550         2746 :       dst = SUBREG_REG (dst);
    1551              :     }
    1552              : 
    1553              :   /* Some targets do argument pushes without adding REG_INC notes.  */
    1554              : 
    1555     67373715 :   if (MEM_P (dst))
    1556              :     {
    1557     11098119 :       dst = XEXP (dst, 0);
    1558     11098119 :       if (GET_CODE (dst) == PRE_INC || GET_CODE (dst) == POST_INC
    1559     11098119 :           || GET_CODE (dst) == PRE_DEC || GET_CODE (dst) == POST_DEC
    1560      9475774 :           || GET_CODE (dst) == PRE_MODIFY || GET_CODE (dst) == POST_MODIFY)
    1561              :         {
    1562      1692149 :           unsigned int end_regno = END_REGNO (XEXP (dst, 0));
    1563      3384298 :           for (unsigned int i = REGNO (XEXP (dst, 0)); i < end_regno; ++i)
    1564              :             {
    1565              :               /* We could probably do better, but for now mark the register
    1566              :                  as used in an unknown fashion and set/clobbered at this
    1567              :                  insn.  */
    1568      1692149 :               reg_state[i].use_index = -1;
    1569      1692149 :               reg_state[i].store_ruid = reload_combine_ruid;
    1570      1692149 :               reg_state[i].real_store_ruid = reload_combine_ruid;
    1571              :             }
    1572              :         }
    1573              :       else
    1574              :         return;
    1575              :     }
    1576              : 
    1577     57967745 :   if (!REG_P (dst))
    1578              :     return;
    1579     48629794 :   regno += REGNO (dst);
    1580              : 
    1581              :   /* note_stores might have stripped a STRICT_LOW_PART, so we have to be
    1582              :      careful with registers / register parts that are not full words.
    1583              :      Similarly for ZERO_EXTRACT.  */
    1584     48629794 :   if (GET_CODE (SET_DEST (set)) == ZERO_EXTRACT
    1585     48628623 :       || GET_CODE (SET_DEST (set)) == STRICT_LOW_PART)
    1586              :     {
    1587         9122 :       for (i = end_hard_regno (mode, regno) - 1; i >= regno; i--)
    1588              :         {
    1589         4561 :           reg_state[i].use_index = -1;
    1590         4561 :           reg_state[i].store_ruid = reload_combine_ruid;
    1591         4561 :           reg_state[i].real_store_ruid = reload_combine_ruid;
    1592              :         }
    1593              :     }
    1594              :   else
    1595              :     {
    1596     97972593 :       for (i = end_hard_regno (mode, regno) - 1; i >= regno; i--)
    1597              :         {
    1598     49347360 :           reg_state[i].store_ruid = reload_combine_ruid;
    1599     49347360 :           if (GET_CODE (set) == SET)
    1600     41656026 :             reg_state[i].real_store_ruid = reload_combine_ruid;
    1601     49347360 :           reg_state[i].use_index = RELOAD_COMBINE_MAX_USES;
    1602              :         }
    1603              :     }
    1604              : }
    1605              : 
    1606              : /* XP points to a piece of rtl that has to be checked for any uses of
    1607              :    registers.
    1608              :    *XP is the pattern of INSN, or a part of it.
    1609              :    Called from reload_combine, and recursively by itself.  */
    1610              : static void
    1611    223597792 : reload_combine_note_use (rtx *xp, rtx_insn *insn, int ruid, rtx containing_mem)
    1612              : {
    1613    264520914 :   rtx x = *xp;
    1614    264520914 :   enum rtx_code code = x->code;
    1615    264520914 :   const char *fmt;
    1616    264520914 :   int i, j;
    1617    264520914 :   rtx offset = const0_rtx; /* For the REG case below.  */
    1618              : 
    1619    264520914 :   switch (code)
    1620              :     {
    1621     59633472 :     case SET:
    1622     59633472 :       if (REG_P (SET_DEST (x)))
    1623              :         {
    1624     40923122 :           reload_combine_note_use (&SET_SRC (x), insn, ruid, NULL_RTX);
    1625     40923122 :           return;
    1626              :         }
    1627              :       break;
    1628              : 
    1629       668026 :     case USE:
    1630              :       /* If this is the USE of a return value, we can't change it.  */
    1631       668026 :       if (REG_P (XEXP (x, 0)) && REG_FUNCTION_VALUE_P (XEXP (x, 0)))
    1632              :         {
    1633              :           /* Mark the return register as used in an unknown fashion.  */
    1634       571960 :           rtx reg = XEXP (x, 0);
    1635       571960 :           unsigned int end_regno = END_REGNO (reg);
    1636      1172758 :           for (unsigned int regno = REGNO (reg); regno < end_regno; ++regno)
    1637       600798 :             reg_state[regno].use_index = -1;
    1638              :           return;
    1639              :         }
    1640              :       break;
    1641              : 
    1642      7741309 :     case CLOBBER:
    1643      7741309 :       if (REG_P (SET_DEST (x)))
    1644              :         {
    1645              :           /* No spurious CLOBBERs of pseudo registers may remain.  */
    1646      7689974 :           gcc_assert (REGNO (SET_DEST (x)) < FIRST_PSEUDO_REGISTER);
    1647              :           return;
    1648              :         }
    1649              :       break;
    1650              : 
    1651     23965886 :     case PLUS:
    1652              :       /* We are interested in (plus (reg) (const_int)) .  */
    1653     23965886 :       if (!REG_P (XEXP (x, 0))
    1654     21568447 :           || !CONST_INT_P (XEXP (x, 1)))
    1655              :         break;
    1656              :       offset = XEXP (x, 1);
    1657              :       x = XEXP (x, 0);
    1658              :       /* Fall through.  */
    1659     61899677 :     case REG:
    1660     61899677 :       {
    1661     61899677 :         int regno = REGNO (x);
    1662     61899677 :         int use_index;
    1663     61899677 :         int nregs;
    1664              : 
    1665              :         /* No spurious USEs of pseudo registers may remain.  */
    1666     61899677 :         gcc_assert (regno < FIRST_PSEUDO_REGISTER);
    1667              : 
    1668     61899677 :         nregs = REG_NREGS (x);
    1669              : 
    1670              :         /* We can't substitute into multi-hard-reg uses.  */
    1671     61899677 :         if (nregs > 1)
    1672              :           {
    1673      1541322 :             while (--nregs >= 0)
    1674      1027548 :               reg_state[regno + nregs].use_index = -1;
    1675              :             return;
    1676              :           }
    1677              : 
    1678              :         /* We may be called to update uses in previously seen insns.
    1679              :            Don't add uses beyond the last store we saw.  */
    1680     61385903 :         if (ruid < reg_state[regno].store_ruid)
    1681              :           return;
    1682              : 
    1683              :         /* If this register is already used in some unknown fashion, we
    1684              :            can't do anything.
    1685              :            If we decrement the index from zero to -1, we can't store more
    1686              :            uses, so this register becomes used in an unknown fashion.  */
    1687     61384694 :         use_index = --reg_state[regno].use_index;
    1688     61384694 :         if (use_index < 0)
    1689              :           return;
    1690              : 
    1691     37011754 :         if (use_index == RELOAD_COMBINE_MAX_USES - 1)
    1692              :           {
    1693              :             /* This is the first use of this register we have seen since we
    1694              :                marked it as dead.  */
    1695     28076203 :             reg_state[regno].offset = offset;
    1696     28076203 :             reg_state[regno].all_offsets_match = true;
    1697     28076203 :             reg_state[regno].use_ruid = ruid;
    1698              :           }
    1699              :         else
    1700              :           {
    1701      8935551 :             if (reg_state[regno].use_ruid > ruid)
    1702          322 :               reg_state[regno].use_ruid = ruid;
    1703              : 
    1704      8935551 :             if (! rtx_equal_p (offset, reg_state[regno].offset))
    1705      3982402 :               reg_state[regno].all_offsets_match = false;
    1706              :           }
    1707              : 
    1708     37011754 :         reg_state[regno].reg_use[use_index].insn = insn;
    1709     37011754 :         reg_state[regno].reg_use[use_index].ruid = ruid;
    1710     37011754 :         reg_state[regno].reg_use[use_index].containing_mem = containing_mem;
    1711     37011754 :         reg_state[regno].reg_use[use_index].usep = xp;
    1712     37011754 :         return;
    1713              :       }
    1714              : 
    1715              :     case MEM:
    1716    153436181 :       containing_mem = x;
    1717              :       break;
    1718              : 
    1719              :     default:
    1720              :       break;
    1721              :     }
    1722              : 
    1723              :   /* Recursively process the components of X.  */
    1724    153436181 :   fmt = GET_RTX_FORMAT (code);
    1725    392082012 :   for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
    1726              :     {
    1727    238645831 :       if (fmt[i] == 'e')
    1728    139710680 :         reload_combine_note_use (&XEXP (x, i), insn, ruid, containing_mem);
    1729     98935151 :       else if (fmt[i] == 'E')
    1730              :         {
    1731     30999351 :           for (j = XVECLEN (x, i) - 1; j >= 0; j--)
    1732     20913989 :             reload_combine_note_use (&XVECEXP (x, i, j), insn, ruid,
    1733              :                                      containing_mem);
    1734              :         }
    1735              :     }
    1736              : }
    1737              : 
    1738              : /* See if we can reduce the cost of a constant by replacing a move
    1739              :    with an add.  We track situations in which a register is set to a
    1740              :    constant or to a register plus a constant.  */
    1741              : /* We cannot do our optimization across labels.  Invalidating all the
    1742              :    information about register contents we have would be costly, so we
    1743              :    use move2add_last_label_luid to note where the label is and then
    1744              :    later disable any optimization that would cross it.
    1745              :    reg_offset[n] / reg_base_reg[n] / reg_symbol_ref[n] / reg_mode[n]
    1746              :    are only valid if reg_set_luid[n] is greater than
    1747              :    move2add_last_label_luid.
    1748              :    For a set that established a new (potential) base register with
    1749              :    non-constant value, we use move2add_luid from the place where the
    1750              :    setting insn is encountered; registers based off that base then
    1751              :    get the same reg_set_luid.  Constants all get
    1752              :    move2add_last_label_luid + 1 as their reg_set_luid.  */
    1753              : static int reg_set_luid[FIRST_PSEUDO_REGISTER];
    1754              : 
    1755              : /* If reg_base_reg[n] is negative, register n has been set to
    1756              :    reg_offset[n] or reg_symbol_ref[n] + reg_offset[n] in mode reg_mode[n].
    1757              :    If reg_base_reg[n] is non-negative, register n has been set to the
    1758              :    sum of reg_offset[n] and the value of register reg_base_reg[n]
    1759              :    before reg_set_luid[n], calculated in mode reg_mode[n] .
    1760              :    For multi-hard-register registers, all but the first one are
    1761              :    recorded as BLKmode in reg_mode.  Setting reg_mode to VOIDmode
    1762              :    marks it as invalid.  */
    1763              : static HOST_WIDE_INT reg_offset[FIRST_PSEUDO_REGISTER];
    1764              : static int reg_base_reg[FIRST_PSEUDO_REGISTER];
    1765              : static rtx reg_symbol_ref[FIRST_PSEUDO_REGISTER];
    1766              : static machine_mode reg_mode[FIRST_PSEUDO_REGISTER];
    1767              : 
    1768              : /* move2add_luid is linearly increased while scanning the instructions
    1769              :    from first to last.  It is used to set reg_set_luid in
    1770              :    reload_cse_move2add and move2add_note_store.  */
    1771              : static int move2add_luid;
    1772              : 
    1773              : /* move2add_last_label_luid is set whenever a label is found.  Labels
    1774              :    invalidate all previously collected reg_offset data.  */
    1775              : static int move2add_last_label_luid;
    1776              : 
    1777              : /* ??? We don't know how zero / sign extension is handled, hence we
    1778              :    can't go from a narrower to a wider mode.  */
    1779              : #define MODES_OK_FOR_MOVE2ADD(OUTMODE, INMODE) \
    1780              :   (GET_MODE_SIZE (OUTMODE) == GET_MODE_SIZE (INMODE) \
    1781              :    || (GET_MODE_SIZE (OUTMODE) <= GET_MODE_SIZE (INMODE) \
    1782              :        && TRULY_NOOP_TRUNCATION_MODES_P (OUTMODE, INMODE)))
    1783              : 
    1784              : /* Record that REG is being set to a value with the mode of REG.  */
    1785              : 
    1786              : static void
    1787     54631518 : move2add_record_mode (rtx reg)
    1788              : {
    1789     54631518 :   int regno, nregs;
    1790     54631518 :   machine_mode mode = GET_MODE (reg);
    1791              : 
    1792     54631518 :   if (GET_CODE (reg) == SUBREG)
    1793              :     {
    1794         2688 :       regno = subreg_regno (reg);
    1795         2688 :       nregs = subreg_nregs (reg);
    1796              :     }
    1797     54628830 :   else if (REG_P (reg))
    1798              :     {
    1799     54628830 :       regno = REGNO (reg);
    1800     54628830 :       nregs = REG_NREGS (reg);
    1801              :     }
    1802              :   else
    1803            0 :     gcc_unreachable ();
    1804     55332996 :   for (int i = nregs - 1; i > 0; i--)
    1805       701478 :     reg_mode[regno + i] = BLKmode;
    1806     54631518 :   reg_mode[regno] = mode;
    1807     54631518 : }
    1808              : 
    1809              : /* Record that REG is being set to the sum of SYM and OFF.  */
    1810              : 
    1811              : static void
    1812      2210222 : move2add_record_sym_value (rtx reg, rtx sym, rtx off)
    1813              : {
    1814      2210222 :   int regno = REGNO (reg);
    1815              : 
    1816      2210222 :   move2add_record_mode (reg);
    1817      2210222 :   reg_set_luid[regno] = move2add_luid;
    1818      2210222 :   reg_base_reg[regno] = -1;
    1819      2210222 :   reg_symbol_ref[regno] = sym;
    1820      2210222 :   reg_offset[regno] = INTVAL (off);
    1821      2210222 : }
    1822              : 
    1823              : /* Check if REGNO contains a valid value in MODE.  */
    1824              : 
    1825              : static bool
    1826    225629188 : move2add_valid_value_p (int regno, scalar_int_mode mode)
    1827              : {
    1828    225629188 :   if (reg_set_luid[regno] <= move2add_last_label_luid)
    1829              :     return false;
    1830              : 
    1831     22517659 :   if (mode != reg_mode[regno])
    1832              :     {
    1833     12115884 :       scalar_int_mode old_mode;
    1834     12115884 :       if (!is_a <scalar_int_mode> (reg_mode[regno], &old_mode)
    1835     17798592 :           || !MODES_OK_FOR_MOVE2ADD (mode, old_mode)
    1836       549799 :           || !REG_CAN_CHANGE_MODE_P (regno, old_mode, mode))
    1837    225629188 :         return false;
    1838              :       /* The value loaded into regno in reg_mode[regno] is also valid in
    1839              :          mode after truncation only if (REG:mode regno) is the lowpart of
    1840              :          (REG:reg_mode[regno] regno).  Now, for big endian, the starting
    1841              :          regno of the lowpart might be different.  */
    1842       549799 :       poly_int64 s_off = subreg_lowpart_offset (mode, old_mode);
    1843       549799 :       s_off = subreg_regno_offset (regno, old_mode, s_off, mode);
    1844       549799 :       if (maybe_ne (s_off, 0))
    1845              :         /* We could in principle adjust regno, check reg_mode[regno] to be
    1846              :            BLKmode, and return s_off to the caller (vs. -1 for failure),
    1847              :            but we currently have no callers that could make use of this
    1848              :            information.  */
    1849              :         return false;
    1850              :     }
    1851              : 
    1852     11014969 :   for (int i = end_hard_regno (mode, regno) - 1; i > regno; i--)
    1853        69396 :     if (reg_mode[i] != BLKmode)
    1854              :       return false;
    1855              :   return true;
    1856              : }
    1857              : 
    1858              : /* This function is called with INSN that sets REG (of mode MODE)
    1859              :    to (SYM + OFF), while REG is known to already have value (SYM + offset).
    1860              :    This function tries to change INSN into an add instruction
    1861              :    (set (REG) (plus (REG) (OFF - offset))) using the known value.
    1862              :    It also updates the information about REG's known value.
    1863              :    Return true if we made a change.  */
    1864              : 
    1865              : static bool
    1866       149799 : move2add_use_add2_insn (scalar_int_mode mode, rtx reg, rtx sym, rtx off,
    1867              :                         rtx_insn *insn)
    1868              : {
    1869       149799 :   rtx set = single_set (insn);
    1870       149799 :   rtx src = SET_SRC (set);
    1871       149799 :   int regno = REGNO (reg);
    1872       149799 :   rtx new_src = gen_int_mode (UINTVAL (off) - reg_offset[regno], mode);
    1873       149799 :   bool speed = optimize_bb_for_speed_p (BLOCK_FOR_INSN (insn));
    1874       149799 :   bool changed = false;
    1875              : 
    1876              :   /* (set (reg) (plus (reg) (const_int 0))) is not canonical;
    1877              :      use (set (reg) (reg)) instead.
    1878              :      We don't delete this insn, nor do we convert it into a
    1879              :      note, to avoid losing register notes or the return
    1880              :      value flag.  jump2 already knows how to get rid of
    1881              :      no-op moves.  */
    1882       149799 :   if (new_src == const0_rtx)
    1883              :     {
    1884              :       /* If the constants are different, this is a
    1885              :          truncation, that, if turned into (set (reg)
    1886              :          (reg)), would be discarded.  Maybe we should
    1887              :          try a truncMN pattern?  */
    1888        12493 :       if (INTVAL (off) == reg_offset [regno])
    1889        10240 :         changed = validate_change (insn, &SET_SRC (set), reg, 0);
    1890              :     }
    1891              :   else
    1892              :     {
    1893       137306 :       struct full_rtx_costs oldcst, newcst;
    1894       137306 :       rtx tem = gen_rtx_PLUS (mode, reg, new_src);
    1895              : 
    1896       137306 :       get_full_set_rtx_cost (set, &oldcst);
    1897       137306 :       SET_SRC (set) = tem;
    1898       137306 :       get_full_set_rtx_cost (set, &newcst);
    1899       137306 :       SET_SRC (set) = src;
    1900              : 
    1901       137306 :       if (costs_lt_p (&newcst, &oldcst, speed)
    1902       137306 :           && have_add2_insn (reg, new_src))
    1903         3719 :         changed = validate_change (insn, &SET_SRC (set), tem, 0);
    1904       133587 :       else if (sym == NULL_RTX && mode != BImode)
    1905              :         {
    1906       131661 :           scalar_int_mode narrow_mode;
    1907       447651 :           FOR_EACH_MODE_UNTIL (narrow_mode, mode)
    1908              :             {
    1909       315990 :               if (have_insn_for (STRICT_LOW_PART, narrow_mode)
    1910       315990 :                   && ((reg_offset[regno] & ~GET_MODE_MASK (narrow_mode))
    1911       232963 :                       == (INTVAL (off) & ~GET_MODE_MASK (narrow_mode))))
    1912              :                 {
    1913        94267 :                   rtx narrow_reg = gen_lowpart_common (narrow_mode, reg);
    1914        94267 :                   rtx narrow_src = gen_int_mode (INTVAL (off),
    1915              :                                                  narrow_mode);
    1916        94267 :                   rtx new_set
    1917        94267 :                     = gen_rtx_SET (gen_rtx_STRICT_LOW_PART (VOIDmode,
    1918              :                                                             narrow_reg),
    1919              :                                    narrow_src);
    1920        94267 :                   get_full_set_rtx_cost (new_set, &newcst);
    1921              : 
    1922              :                   /* We perform this replacement only if NEXT is either a
    1923              :                      naked SET, or else its single_set is the first element
    1924              :                      in a PARALLEL.  */
    1925        94267 :                   rtx *setloc = GET_CODE (PATTERN (insn)) == PARALLEL
    1926        94267 :                     ? &XVECEXP (PATTERN (insn), 0, 0) : &PATTERN (insn);
    1927        94267 :                   if (*setloc == set && costs_lt_p (&newcst, &oldcst, speed))
    1928              :                     {
    1929            0 :                       changed = validate_change (insn, setloc, new_set, 0);
    1930            0 :                       if (changed)
    1931              :                         break;
    1932              :                     }
    1933              :                 }
    1934              :             }
    1935              :         }
    1936              :     }
    1937       149799 :   move2add_record_sym_value (reg, sym, off);
    1938       149799 :   return changed;
    1939              : }
    1940              : 
    1941              : 
    1942              : /* This function is called with INSN that sets REG (of mode MODE) to
    1943              :    (SYM + OFF), but REG doesn't have known value (SYM + offset).  This
    1944              :    function tries to find another register which is known to already have
    1945              :    value (SYM + offset) and change INSN into an add instruction
    1946              :    (set (REG) (plus (the found register) (OFF - offset))) if such
    1947              :    a register is found.  It also updates the information about
    1948              :    REG's known value.
    1949              :    Return true iff we made a change.  */
    1950              : 
    1951              : static bool
    1952      1960607 : move2add_use_add3_insn (scalar_int_mode mode, rtx reg, rtx sym, rtx off,
    1953              :                         rtx_insn *insn)
    1954              : {
    1955      1960607 :   rtx set = single_set (insn);
    1956      1960607 :   rtx src = SET_SRC (set);
    1957      1960607 :   int regno = REGNO (reg);
    1958              :   int min_regno = 0;
    1959      1960607 :   bool speed = optimize_bb_for_speed_p (BLOCK_FOR_INSN (insn));
    1960      1960607 :   int i;
    1961      1960607 :   bool changed = false;
    1962      1960607 :   struct full_rtx_costs oldcst, newcst, mincst;
    1963      1960607 :   rtx plus_expr;
    1964              : 
    1965      1960607 :   init_costs_to_max (&mincst);
    1966      1960607 :   get_full_set_rtx_cost (set, &oldcst);
    1967              : 
    1968      1960607 :   plus_expr = gen_rtx_PLUS (GET_MODE (reg), reg, const0_rtx);
    1969      1960607 :   SET_SRC (set) = plus_expr;
    1970              : 
    1971    186257234 :   for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
    1972    184296633 :     if (move2add_valid_value_p (i, mode)
    1973      3899091 :         && reg_base_reg[i] < 0
    1974      1530648 :         && reg_symbol_ref[i] != NULL_RTX
    1975    185339831 :         && rtx_equal_p (sym, reg_symbol_ref[i]))
    1976              :       {
    1977        39052 :         rtx new_src = gen_int_mode (UINTVAL (off) - reg_offset[i],
    1978        19526 :                                     GET_MODE (reg));
    1979              :         /* (set (reg) (plus (reg) (const_int 0))) is not canonical;
    1980              :            use (set (reg) (reg)) instead.
    1981              :            We don't delete this insn, nor do we convert it into a
    1982              :            note, to avoid losing register notes or the return
    1983              :            value flag.  jump2 already knows how to get rid of
    1984              :            no-op moves.  */
    1985        19526 :         if (new_src == const0_rtx)
    1986              :           {
    1987            6 :             init_costs_to_zero (&mincst);
    1988            6 :             min_regno = i;
    1989            6 :             break;
    1990              :           }
    1991              :         else
    1992              :           {
    1993        19520 :             XEXP (plus_expr, 1) = new_src;
    1994        19520 :             get_full_set_rtx_cost (set, &newcst);
    1995              : 
    1996        19520 :             if (costs_lt_p (&newcst, &mincst, speed))
    1997              :               {
    1998        18975 :                 mincst = newcst;
    1999        18975 :                 min_regno = i;
    2000              :               }
    2001              :           }
    2002              :       }
    2003      1960607 :   SET_SRC (set) = src;
    2004              : 
    2005      1960607 :   if (costs_lt_p (&mincst, &oldcst, speed))
    2006              :     {
    2007           46 :       rtx tem;
    2008              : 
    2009           46 :       tem = gen_rtx_REG (GET_MODE (reg), min_regno);
    2010           46 :       if (i != min_regno)
    2011              :         {
    2012           80 :           rtx new_src = gen_int_mode (UINTVAL (off) - reg_offset[min_regno],
    2013           40 :                                       GET_MODE (reg));
    2014           40 :           tem = gen_rtx_PLUS (GET_MODE (reg), tem, new_src);
    2015              :         }
    2016           46 :       if (validate_change (insn, &SET_SRC (set), tem, 0))
    2017      1960607 :         changed = true;
    2018              :     }
    2019      1960607 :   reg_set_luid[regno] = move2add_luid;
    2020      1960607 :   move2add_record_sym_value (reg, sym, off);
    2021      1960607 :   return changed;
    2022              : }
    2023              : 
    2024              : /* Perform any invalidations necessary for INSN.  */
    2025              : 
    2026              : static void
    2027    112648533 : reload_cse_move2add_invalidate (rtx_insn *insn)
    2028              : {
    2029    135998406 :   for (rtx note = REG_NOTES (insn); note; note = XEXP (note, 1))
    2030              :     {
    2031     23349873 :       if (REG_NOTE_KIND (note) == REG_INC
    2032            0 :           && REG_P (XEXP (note, 0)))
    2033              :         {
    2034              :           /* Reset the information about this register.  */
    2035            0 :           int regno = REGNO (XEXP (note, 0));
    2036            0 :           if (regno < FIRST_PSEUDO_REGISTER)
    2037              :             {
    2038            0 :               move2add_record_mode (XEXP (note, 0));
    2039            0 :               reg_mode[regno] = VOIDmode;
    2040              :             }
    2041              :         }
    2042              :     }
    2043              : 
    2044              :   /* There are no REG_INC notes for SP autoinc.  */
    2045    112648533 :   subrtx_var_iterator::array_type array;
    2046    569131212 :   FOR_EACH_SUBRTX_VAR (iter, array, PATTERN (insn), NONCONST)
    2047              :     {
    2048    456482679 :       rtx mem = *iter;
    2049    456482679 :       if (mem
    2050    456482679 :           && MEM_P (mem)
    2051     28658670 :           && GET_RTX_CLASS (GET_CODE (XEXP (mem, 0))) == RTX_AUTOINC)
    2052              :         {
    2053      1677284 :           if (XEXP (XEXP (mem, 0), 0) == stack_pointer_rtx)
    2054      1677284 :             reg_mode[STACK_POINTER_REGNUM] = VOIDmode;
    2055              :         }
    2056              :     }
    2057              : 
    2058    112648533 :   note_stores (insn, move2add_note_store, insn);
    2059              : 
    2060              :   /* If INSN is a conditional branch, we try to extract an
    2061              :      implicit set out of it.  */
    2062    112648533 :   if (any_condjump_p (insn))
    2063              :     {
    2064      4926536 :       rtx cnd = fis_get_condition (insn);
    2065              : 
    2066      4926536 :       if (cnd != NULL_RTX
    2067      4414747 :           && GET_CODE (cnd) == NE
    2068      1980584 :           && REG_P (XEXP (cnd, 0))
    2069      1322287 :           && !reg_set_p (XEXP (cnd, 0), insn)
    2070              :           /* The following two checks, which are also in
    2071              :              move2add_note_store, are intended to reduce the
    2072              :              number of calls to gen_rtx_SET to avoid memory
    2073              :              allocation if possible.  */
    2074      1322287 :           && SCALAR_INT_MODE_P (GET_MODE (XEXP (cnd, 0)))
    2075      1322286 :           && REG_NREGS (XEXP (cnd, 0)) == 1
    2076      6248822 :           && CONST_INT_P (XEXP (cnd, 1)))
    2077              :         {
    2078       888775 :           rtx implicit_set = gen_rtx_SET (XEXP (cnd, 0), XEXP (cnd, 1));
    2079       888775 :           move2add_note_store (SET_DEST (implicit_set), implicit_set, insn);
    2080              :         }
    2081              :     }
    2082              : 
    2083              :   /* If this is a CALL_INSN, all call used registers are stored with
    2084              :      unknown values.  */
    2085    112648533 :   if (CALL_P (insn))
    2086              :     {
    2087      4852747 :       function_abi callee_abi = insn_callee_abi (insn);
    2088    465863712 :       for (int i = FIRST_PSEUDO_REGISTER - 1; i >= 0; i--)
    2089    456158218 :         if (reg_mode[i] != VOIDmode
    2090     23110667 :             && reg_mode[i] != BLKmode
    2091    478709935 :             && callee_abi.clobbers_reg_p (reg_mode[i], i))
    2092              :             /* Reset the information about this register.  */
    2093      8477273 :           reg_mode[i] = VOIDmode;
    2094              :     }
    2095    112648533 : }
    2096              : 
    2097              : /* Convert move insns with constant inputs to additions if they are cheaper.
    2098              :    Return true if any changes were made.  */
    2099              : static bool
    2100      1070192 : reload_cse_move2add (rtx_insn *first)
    2101              : {
    2102      1070192 :   int i;
    2103      1070192 :   rtx_insn *insn;
    2104      1070192 :   bool changed = false;
    2105              : 
    2106    101668240 :   for (i = FIRST_PSEUDO_REGISTER - 1; i >= 0; i--)
    2107              :     {
    2108    100598048 :       reg_set_luid[i] = 0;
    2109    100598048 :       reg_offset[i] = 0;
    2110    100598048 :       reg_base_reg[i] = 0;
    2111    100598048 :       reg_symbol_ref[i] = NULL_RTX;
    2112    100598048 :       reg_mode[i] = VOIDmode;
    2113              :     }
    2114              : 
    2115      1070192 :   move2add_last_label_luid = 0;
    2116      1070192 :   move2add_luid = 2;
    2117    144624910 :   for (insn = first; insn; insn = NEXT_INSN (insn), move2add_luid++)
    2118              :     {
    2119    143554718 :       rtx set;
    2120              : 
    2121    143554718 :       if (LABEL_P (insn))
    2122              :         {
    2123      5306722 :           move2add_last_label_luid = move2add_luid;
    2124              :           /* We're going to increment move2add_luid twice after a
    2125              :              label, so that we can use move2add_last_label_luid + 1 as
    2126              :              the luid for constants.  */
    2127      5306722 :           move2add_luid++;
    2128    143554718 :           continue;
    2129              :         }
    2130    138247996 :       if (! INSN_P (insn))
    2131     23489057 :         continue;
    2132    114758939 :       set = single_set (insn);
    2133              :       /* For simplicity, we only perform this optimization on
    2134              :          single-sets.  */
    2135    114758939 :       scalar_int_mode mode;
    2136    114758939 :       if (set
    2137     55901999 :           && REG_P (SET_DEST (set))
    2138    152971478 :           && is_a <scalar_int_mode> (GET_MODE (SET_DEST (set)), &mode))
    2139              :         {
    2140     28422445 :           rtx reg = SET_DEST (set);
    2141     28422445 :           int regno = REGNO (reg);
    2142     28422445 :           rtx src = SET_SRC (set);
    2143              : 
    2144              :           /* Check if we have valid information on the contents of this
    2145              :              register in the mode of REG.  */
    2146     28422445 :           if (move2add_valid_value_p (regno, mode)
    2147     28422445 :               && dbg_cnt (cse2_move2add))
    2148              :             {
    2149              :               /* Try to transform (set (REGX) (CONST_INT A))
    2150              :                                   ...
    2151              :                                   (set (REGX) (CONST_INT B))
    2152              :                  to
    2153              :                                   (set (REGX) (CONST_INT A))
    2154              :                                   ...
    2155              :                                   (set (REGX) (plus (REGX) (CONST_INT B-A)))
    2156              :                  or
    2157              :                                   (set (REGX) (CONST_INT A))
    2158              :                                   ...
    2159              :                                   (set (STRICT_LOW_PART (REGX)) (CONST_INT B))
    2160              :               */
    2161              : 
    2162      3972212 :               if (CONST_INT_P (src)
    2163       337674 :                   && reg_base_reg[regno] < 0
    2164       150998 :                   && reg_symbol_ref[regno] == NULL_RTX)
    2165              :                 {
    2166       147555 :                   changed |= move2add_use_add2_insn (mode, reg, NULL_RTX,
    2167              :                                                      src, insn);
    2168       147555 :                   continue;
    2169              :                 }
    2170              : 
    2171              :               /* Try to transform (set (REGX) (REGY))
    2172              :                                   (set (REGX) (PLUS (REGX) (CONST_INT A)))
    2173              :                                   ...
    2174              :                                   (set (REGX) (REGY))
    2175              :                                   (set (REGX) (PLUS (REGX) (CONST_INT B)))
    2176              :                  to
    2177              :                                   (set (REGX) (REGY))
    2178              :                                   (set (REGX) (PLUS (REGX) (CONST_INT A)))
    2179              :                                   ...
    2180              :                                   (set (REGX) (plus (REGX) (CONST_INT B-A)))  */
    2181      3824657 :               else if (REG_P (src)
    2182       485565 :                        && reg_set_luid[regno] == reg_set_luid[REGNO (src)]
    2183       124506 :                        && reg_base_reg[regno] == reg_base_reg[REGNO (src)]
    2184      3949163 :                        && move2add_valid_value_p (REGNO (src), mode))
    2185              :                 {
    2186        93046 :                   rtx_insn *next = next_nonnote_nondebug_insn (insn);
    2187        93046 :                   rtx set = NULL_RTX;
    2188        93046 :                   if (next)
    2189        93034 :                     set = single_set (next);
    2190        93034 :                   if (set
    2191        71649 :                       && SET_DEST (set) == reg
    2192         7321 :                       && GET_CODE (SET_SRC (set)) == PLUS
    2193          684 :                       && XEXP (SET_SRC (set), 0) == reg
    2194          676 :                       && CONST_INT_P (XEXP (SET_SRC (set), 1)))
    2195              :                     {
    2196          421 :                       rtx src3 = XEXP (SET_SRC (set), 1);
    2197          421 :                       unsigned HOST_WIDE_INT added_offset = UINTVAL (src3);
    2198          421 :                       HOST_WIDE_INT base_offset = reg_offset[REGNO (src)];
    2199          421 :                       HOST_WIDE_INT regno_offset = reg_offset[regno];
    2200          421 :                       rtx new_src =
    2201          842 :                         gen_int_mode (added_offset
    2202          421 :                                       + base_offset
    2203          421 :                                       - regno_offset,
    2204              :                                       mode);
    2205          421 :                       bool success = false;
    2206          421 :                       bool speed = optimize_bb_for_speed_p (BLOCK_FOR_INSN (insn));
    2207              : 
    2208          421 :                       if (new_src == const0_rtx)
    2209              :                         /* See above why we create (set (reg) (reg)) here.  */
    2210           43 :                         success
    2211           43 :                           = validate_change (next, &SET_SRC (set), reg, 0);
    2212              :                       else
    2213              :                         {
    2214          378 :                           rtx old_src = SET_SRC (set);
    2215          378 :                           struct full_rtx_costs oldcst, newcst;
    2216          378 :                           rtx tem = gen_rtx_PLUS (mode, reg, new_src);
    2217              : 
    2218          378 :                           get_full_set_rtx_cost (set, &oldcst);
    2219          378 :                           SET_SRC (set) = tem;
    2220          378 :                           get_full_set_src_cost (tem, mode, &newcst);
    2221          378 :                           SET_SRC (set) = old_src;
    2222          378 :                           costs_add_n_insns (&oldcst, 1);
    2223              : 
    2224          378 :                           rtx *setloc = GET_CODE (PATTERN (next)) == PARALLEL
    2225          378 :                             ? &XVECEXP (PATTERN (next), 0, 0) : &PATTERN (next);
    2226          378 :                           if (*setloc == set
    2227          378 :                               && costs_lt_p (&newcst, &oldcst, speed)
    2228          756 :                               && have_add2_insn (reg, new_src))
    2229              :                             {
    2230          378 :                               rtx newpat = gen_rtx_SET (reg, tem);
    2231          378 :                               success
    2232          378 :                                 = validate_change (next, setloc, newpat, 0);
    2233              :                             }
    2234              :                         }
    2235          421 :                       if (success)
    2236          421 :                         delete_insn (insn);
    2237          421 :                       changed |= success;
    2238          421 :                       insn = next;
    2239              :                       /* Make sure to perform any invalidations related to
    2240              :                          NEXT/INSN since we're going to bypass the normal
    2241              :                          flow with the continue below.
    2242              : 
    2243              :                          Do this before recording the new mode/offset.  */
    2244          421 :                       reload_cse_move2add_invalidate (insn);
    2245          421 :                       move2add_record_mode (reg);
    2246          421 :                       reg_offset[regno]
    2247          421 :                         = trunc_int_for_mode (added_offset + base_offset,
    2248              :                                               mode);
    2249          421 :                       continue;
    2250          421 :                     }
    2251              :                 }
    2252              :             }
    2253              : 
    2254              :           /* Try to transform
    2255              :              (set (REGX) (CONST (PLUS (SYMBOL_REF) (CONST_INT A))))
    2256              :              ...
    2257              :              (set (REGY) (CONST (PLUS (SYMBOL_REF) (CONST_INT B))))
    2258              :              to
    2259              :              (set (REGX) (CONST (PLUS (SYMBOL_REF) (CONST_INT A))))
    2260              :              ...
    2261              :              (set (REGY) (CONST (PLUS (REGX) (CONST_INT B-A))))  */
    2262     28274469 :           if ((GET_CODE (src) == SYMBOL_REF
    2263     26375169 :                || (GET_CODE (src) == CONST
    2264        63801 :                    && GET_CODE (XEXP (src, 0)) == PLUS
    2265        63573 :                    && GET_CODE (XEXP (XEXP (src, 0), 0)) == SYMBOL_REF
    2266        63551 :                    && CONST_INT_P (XEXP (XEXP (src, 0), 1))))
    2267     28338020 :               && dbg_cnt (cse2_move2add))
    2268              :             {
    2269      1962851 :               rtx sym, off;
    2270              : 
    2271      1962851 :               if (GET_CODE (src) == SYMBOL_REF)
    2272              :                 {
    2273      1899300 :                   sym = src;
    2274      1899300 :                   off = const0_rtx;
    2275              :                 }
    2276              :               else
    2277              :                 {
    2278        63551 :                   sym = XEXP (XEXP (src, 0), 0);
    2279        63551 :                   off = XEXP (XEXP (src, 0), 1);
    2280              :                 }
    2281              : 
    2282              :               /* If the reg already contains the value which is sum of
    2283              :                  sym and some constant value, we can use an add2 insn.  */
    2284      1962851 :               if (move2add_valid_value_p (regno, mode)
    2285       200747 :                   && reg_base_reg[regno] < 0
    2286       129604 :                   && reg_symbol_ref[regno] != NULL_RTX
    2287      2016864 :                   && rtx_equal_p (sym, reg_symbol_ref[regno]))
    2288         2244 :                 changed |= move2add_use_add2_insn (mode, reg, sym, off, insn);
    2289              : 
    2290              :               /* Otherwise, we have to find a register whose value is sum
    2291              :                  of sym and some constant value.  */
    2292              :               else
    2293      1960607 :                 changed |= move2add_use_add3_insn (mode, reg, sym, off, insn);
    2294              : 
    2295      1962851 :               continue;
    2296      1962851 :             }
    2297              :         }
    2298    112648112 :       reload_cse_move2add_invalidate (insn);
    2299              :     }
    2300      1070192 :   return changed;
    2301              : }
    2302              : 
    2303              : /* SET is a SET or CLOBBER that sets DST.  DATA is the insn which
    2304              :    contains SET.
    2305              :    Update reg_set_luid, reg_offset and reg_base_reg accordingly.
    2306              :    Called from reload_cse_move2add via note_stores.  */
    2307              : 
    2308              : static void
    2309     62959871 : move2add_note_store (rtx dst, const_rtx set, void *data)
    2310              : {
    2311     62959871 :   rtx_insn *insn = (rtx_insn *) data;
    2312     62959871 :   unsigned int regno = 0;
    2313     62959871 :   scalar_int_mode mode;
    2314              : 
    2315     62959871 :   if (GET_CODE (dst) == SUBREG)
    2316         2688 :     regno = subreg_regno (dst);
    2317     62957183 :   else if (REG_P (dst))
    2318     45162670 :     regno = REGNO (dst);
    2319              :   else
    2320              :     return;
    2321              : 
    2322     45165358 :   if (!is_a <scalar_int_mode> (GET_MODE (dst), &mode))
    2323     17211788 :     goto invalidate;
    2324              : 
    2325     27953570 :   if (GET_CODE (set) == SET)
    2326              :     {
    2327     27818264 :       rtx note, sym = NULL_RTX;
    2328     27818264 :       rtx off;
    2329              : 
    2330     27818264 :       note = find_reg_equal_equiv_note (insn);
    2331     27818264 :       if (note && GET_CODE (XEXP (note, 0)) == SYMBOL_REF)
    2332              :         {
    2333        89450 :           sym = XEXP (note, 0);
    2334        89450 :           off = const0_rtx;
    2335              :         }
    2336      4347261 :       else if (note && GET_CODE (XEXP (note, 0)) == CONST
    2337        10601 :                && GET_CODE (XEXP (XEXP (note, 0), 0)) == PLUS
    2338        10388 :                && GET_CODE (XEXP (XEXP (XEXP (note, 0), 0), 0)) == SYMBOL_REF
    2339        10366 :                && CONST_INT_P (XEXP (XEXP (XEXP (note, 0), 0), 1)))
    2340              :         {
    2341              :           sym = XEXP (XEXP (XEXP (note, 0), 0), 0);
    2342              :           off = XEXP (XEXP (XEXP (note, 0), 0), 1);
    2343              :         }
    2344              : 
    2345        99816 :       if (sym != NULL_RTX)
    2346              :         {
    2347        99816 :           move2add_record_sym_value (dst, sym, off);
    2348        99816 :           return;
    2349              :         }
    2350              :     }
    2351              : 
    2352     27853754 :   if (GET_CODE (set) == SET
    2353     27718448 :       && GET_CODE (SET_DEST (set)) != ZERO_EXTRACT
    2354     27717355 :       && GET_CODE (SET_DEST (set)) != STRICT_LOW_PART)
    2355              :     {
    2356     27714110 :       rtx src = SET_SRC (set);
    2357     27714110 :       rtx base_reg;
    2358     27714110 :       unsigned HOST_WIDE_INT offset;
    2359     27714110 :       int base_regno;
    2360              : 
    2361     27714110 :       switch (GET_CODE (src))
    2362              :         {
    2363      6236050 :         case PLUS:
    2364      6236050 :           if (REG_P (XEXP (src, 0)))
    2365              :             {
    2366      5938821 :               base_reg = XEXP (src, 0);
    2367              : 
    2368      5938821 :               if (CONST_INT_P (XEXP (src, 1)))
    2369      5107696 :                 offset = UINTVAL (XEXP (src, 1));
    2370       831125 :               else if (REG_P (XEXP (src, 1))
    2371       831125 :                        && move2add_valid_value_p (REGNO (XEXP (src, 1)), mode))
    2372              :                 {
    2373        91068 :                   if (reg_base_reg[REGNO (XEXP (src, 1))] < 0
    2374        91068 :                       && reg_symbol_ref[REGNO (XEXP (src, 1))] == NULL_RTX)
    2375         9477 :                     offset = reg_offset[REGNO (XEXP (src, 1))];
    2376              :                   /* Maybe the first register is known to be a
    2377              :                      constant.  */
    2378        81591 :                   else if (move2add_valid_value_p (REGNO (base_reg), mode)
    2379        23523 :                            && reg_base_reg[REGNO (base_reg)] < 0
    2380        82556 :                            && reg_symbol_ref[REGNO (base_reg)] == NULL_RTX)
    2381              :                     {
    2382          831 :                       offset = reg_offset[REGNO (base_reg)];
    2383          831 :                       base_reg = XEXP (src, 1);
    2384              :                     }
    2385              :                   else
    2386        80760 :                     goto invalidate;
    2387              :                 }
    2388              :               else
    2389       740057 :                 goto invalidate;
    2390              : 
    2391              :               break;
    2392              :             }
    2393              : 
    2394       297229 :           goto invalidate;
    2395              : 
    2396              :         case REG:
    2397              :           base_reg = src;
    2398              :           offset = 0;
    2399              :           break;
    2400              : 
    2401      4495208 :         case CONST_INT:
    2402              :           /* Start tracking the register as a constant.  */
    2403      4495208 :           reg_base_reg[regno] = -1;
    2404      4495208 :           reg_symbol_ref[regno] = NULL_RTX;
    2405      4495208 :           reg_offset[regno] = INTVAL (SET_SRC (set));
    2406              :           /* We assign the same luid to all registers set to constants.  */
    2407      4495208 :           reg_set_luid[regno] = move2add_last_label_luid + 1;
    2408      4495208 :           move2add_record_mode (dst);
    2409      4495208 :           return;
    2410              : 
    2411     12079637 :         default:
    2412     12079637 :           goto invalidate;
    2413              :         }
    2414              : 
    2415     10021219 :       base_regno = REGNO (base_reg);
    2416              :       /* If information about the base register is not valid, set it
    2417              :          up as a new base register, pretending its value is known
    2418              :          starting from the current insn.  */
    2419     10021219 :       if (!move2add_valid_value_p (base_regno, mode))
    2420              :         {
    2421      7355333 :           reg_base_reg[base_regno] = base_regno;
    2422      7355333 :           reg_symbol_ref[base_regno] = NULL_RTX;
    2423      7355333 :           reg_offset[base_regno] = 0;
    2424      7355333 :           reg_set_luid[base_regno] = move2add_luid;
    2425      7355333 :           gcc_assert (GET_MODE (base_reg) == mode);
    2426      7355333 :           move2add_record_mode (base_reg);
    2427              :         }
    2428              : 
    2429              :       /* Copy base information from our base register.  */
    2430     10021219 :       reg_set_luid[regno] = reg_set_luid[base_regno];
    2431     10021219 :       reg_base_reg[regno] = reg_base_reg[base_regno];
    2432     10021219 :       reg_symbol_ref[regno] = reg_symbol_ref[base_regno];
    2433              : 
    2434              :       /* Compute the sum of the offsets or constants.  */
    2435     10021219 :       reg_offset[regno]
    2436     10021219 :         = trunc_int_for_mode (offset + reg_offset[base_regno], mode);
    2437              : 
    2438     10021219 :       move2add_record_mode (dst);
    2439     10021219 :     }
    2440              :   else
    2441              :     {
    2442       139644 :     invalidate:
    2443              :       /* Invalidate the contents of the register.  */
    2444     30549115 :       move2add_record_mode (dst);
    2445     30549115 :       reg_mode[regno] = VOIDmode;
    2446              :     }
    2447              : }
    2448              : 
    2449              : namespace {
    2450              : 
    2451              : const pass_data pass_data_postreload_cse =
    2452              : {
    2453              :   RTL_PASS, /* type */
    2454              :   "postreload", /* name */
    2455              :   OPTGROUP_NONE, /* optinfo_flags */
    2456              :   TV_RELOAD_CSE_REGS, /* tv_id */
    2457              :   0, /* properties_required */
    2458              :   0, /* properties_provided */
    2459              :   0, /* properties_destroyed */
    2460              :   0, /* todo_flags_start */
    2461              :   TODO_df_finish, /* todo_flags_finish */
    2462              : };
    2463              : 
    2464              : class pass_postreload_cse : public rtl_opt_pass
    2465              : {
    2466              : public:
    2467       294536 :   pass_postreload_cse (gcc::context *ctxt)
    2468       589072 :     : rtl_opt_pass (pass_data_postreload_cse, ctxt)
    2469              :   {}
    2470              : 
    2471              :   /* opt_pass methods: */
    2472      1515929 :   bool gate (function *) final override
    2473              :   {
    2474      1515929 :     return (optimize > 0 && reload_completed);
    2475              :   }
    2476              : 
    2477              :   unsigned int execute (function *) final override;
    2478              : 
    2479              : }; // class pass_postreload_cse
    2480              : 
    2481              : unsigned int
    2482      1070192 : pass_postreload_cse::execute (function *fun)
    2483              : {
    2484      1070192 :   if (!dbg_cnt (postreload_cse))
    2485              :     return 0;
    2486              : 
    2487              :   /* Do a very simple CSE pass over just the hard registers.  */
    2488      1070192 :   reload_cse_regs (get_insns ());
    2489              :   /* Reload_cse_regs can eliminate potentially-trapping MEMs.
    2490              :      Remove any EH edges associated with them.  */
    2491      1070192 :   if (fun->can_throw_non_call_exceptions
    2492      1070192 :       && purge_all_dead_edges ())
    2493          115 :     cleanup_cfg (0);
    2494              : 
    2495              :   return 0;
    2496              : }
    2497              : 
    2498              : } // anon namespace
    2499              : 
    2500              : rtl_opt_pass *
    2501       294536 : make_pass_postreload_cse (gcc::context *ctxt)
    2502              : {
    2503       294536 :   return new pass_postreload_cse (ctxt);
    2504              : }
        

Generated by: LCOV version 2.5.0-beta

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