LCOV - code coverage report
Current view: top level - gcc - postreload.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 97.6 % 1054 1029
Test Date: 2025-03-22 13:13:03 Functions: 100.0 % 27 27
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: - 0 0

             Branch data     Line data    Source code
       1                 :             : /* Perform simple optimizations to clean up the result of reload.
       2                 :             :    Copyright (C) 1987-2025 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                 :     1008570 : reload_cse_regs (rtx_insn *first ATTRIBUTE_UNUSED)
      64                 :             : {
      65                 :     1008570 :   bool moves_converted;
      66                 :     1008570 :   reload_cse_regs_1 ();
      67                 :     1008570 :   reload_combine ();
      68                 :     1008570 :   moves_converted = reload_cse_move2add (first);
      69                 :     1008570 :   if (flag_expensive_optimizations)
      70                 :             :     {
      71                 :      933022 :       if (moves_converted)
      72                 :        8428 :         reload_combine ();
      73                 :      933022 :       reload_cse_regs_1 ();
      74                 :             :     }
      75                 :     1008570 : }
      76                 :             : 
      77                 :             : /* Try to simplify INSN.  Return true if the CFG may have changed.  */
      78                 :             : static bool
      79                 :   191449384 : reload_cse_simplify (rtx_insn *insn, rtx testreg)
      80                 :             : {
      81                 :   191449384 :   rtx body = PATTERN (insn);
      82                 :   191449384 :   basic_block insn_bb = BLOCK_FOR_INSN (insn);
      83                 :   191449384 :   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                 :   191449384 :   if (NO_FUNCTION_CSE && CALL_P (insn))
      88                 :             :     return false;
      89                 :             : 
      90                 :             :   /* Remember if this insn has been sp += const_int.  */
      91                 :   182762251 :   rtx sp_set = set_for_reg_notes (insn);
      92                 :   182762251 :   rtx sp_addend = NULL_RTX;
      93                 :   182762251 :   if (sp_set
      94                 :    65215999 :       && SET_DEST (sp_set) == stack_pointer_rtx
      95                 :     3287038 :       && GET_CODE (SET_SRC (sp_set)) == PLUS
      96                 :     3259510 :       && XEXP (SET_SRC (sp_set), 0) == stack_pointer_rtx
      97                 :     3259446 :       && CONST_INT_P (XEXP (SET_SRC (sp_set), 1)))
      98                 :   182762251 :     sp_addend = XEXP (SET_SRC (sp_set), 1);
      99                 :             : 
     100                 :   182762251 :   if (GET_CODE (body) == SET)
     101                 :             :     {
     102                 :    83596305 :       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                 :    83596305 :       count += reload_cse_simplify_set (body, insn);
     110                 :             : 
     111                 :    83596305 :       if (!count && cselib_redundant_set_p (body))
     112                 :             :         {
     113                 :      228224 :           if (check_for_inc_dec (insn))
     114                 :      228224 :             delete_insn_and_edges (insn);
     115                 :             :           /* We're done with this insn.  */
     116                 :      228224 :           goto done;
     117                 :             :         }
     118                 :             : 
     119                 :    83368081 :       if (count > 0)
     120                 :      146875 :         apply_change_group ();
     121                 :             :       else
     122                 :    83221206 :         reload_cse_simplify_operands (insn, testreg);
     123                 :             :     }
     124                 :    99165946 :   else if (GET_CODE (body) == PARALLEL)
     125                 :             :     {
     126                 :    13474675 :       int i;
     127                 :    13474675 :       int count = 0;
     128                 :    13474675 :       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                 :    13474675 :       if (asm_noperands (body) >= 0)
     134                 :             :         {
     135                 :      586327 :           for (i = XVECLEN (body, 0) - 1; i >= 0; --i)
     136                 :             :             {
     137                 :      447557 :               rtx part = XVECEXP (body, 0, i);
     138                 :      447557 :               if (GET_CODE (part) == CLOBBER && REG_P (XEXP (part, 0)))
     139                 :      193469 :                 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                 :    27012781 :       for (i = XVECLEN (body, 0) - 1; i >= 0; --i)
     146                 :             :         {
     147                 :    27008687 :           rtx part = XVECEXP (body, 0, i);
     148                 :    27008687 :           if (GET_CODE (part) == SET)
     149                 :             :             {
     150                 :    13376896 :               if (! cselib_redundant_set_p (part))
     151                 :             :                 break;
     152                 :        4214 :               if (REG_P (SET_DEST (part))
     153                 :        4214 :                   && REG_FUNCTION_VALUE_P (SET_DEST (part)))
     154                 :             :                 {
     155                 :           0 :                   if (value)
     156                 :             :                     break;
     157                 :             :                   value = SET_DEST (part);
     158                 :             :                 }
     159                 :             :             }
     160                 :    13631791 :           else if (GET_CODE (part) != CLOBBER && GET_CODE (part) != USE)
     161                 :             :             break;
     162                 :             :         }
     163                 :             : 
     164                 :    13474675 :       if (i < 0)
     165                 :             :         {
     166                 :        4094 :           if (check_for_inc_dec (insn))
     167                 :        4094 :             delete_insn_and_edges (insn);
     168                 :             :           /* We're done with this insn.  */
     169                 :        4094 :           goto done;
     170                 :             :         }
     171                 :             : 
     172                 :             :       /* It's not a no-op, but we can try to simplify it.  */
     173                 :    41246814 :       for (i = XVECLEN (body, 0) - 1; i >= 0; --i)
     174                 :    27776233 :         if (GET_CODE (XVECEXP (body, 0, i)) == SET)
     175                 :    14148366 :           count += reload_cse_simplify_set (XVECEXP (body, 0, i), insn);
     176                 :             : 
     177                 :    13470581 :       if (count > 0)
     178                 :        5002 :         apply_change_group ();
     179                 :             :       else
     180                 :    13465579 :         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                 :   182529933 :   if (sp_addend
     186                 :     3259446 :       && SET_DEST (sp_set) == stack_pointer_rtx
     187                 :     3259446 :       && REG_P (SET_SRC (sp_set)))
     188                 :        3148 :     set_dst_reg_note (insn, REG_EQUAL,
     189                 :        3148 :                       gen_rtx_PLUS (Pmode, stack_pointer_rtx,
     190                 :             :                                     sp_addend), stack_pointer_rtx);
     191                 :             : 
     192                 :   182526785 : done:
     193                 :   365522331 :   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                 :     1941592 : reload_cse_regs_1 (void)
     215                 :             : {
     216                 :     1941592 :   bool cfg_changed = false;
     217                 :     1941592 :   basic_block bb;
     218                 :     1941592 :   rtx_insn *insn;
     219                 :     1941592 :   rtx testreg = gen_rtx_REG (word_mode, LAST_VIRTUAL_REGISTER + 1);
     220                 :             : 
     221                 :     1941592 :   cselib_init (CSELIB_RECORD_MEMORY);
     222                 :     1941592 :   init_alias_analysis ();
     223                 :             : 
     224                 :    22070469 :   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                 :    20128877 :       rtx_insn *implicit_set;
     230                 :             : 
     231                 :    20128877 :       implicit_set = NULL;
     232                 :    20128877 :       if (EDGE_COUNT (bb->preds) <= 3)
     233                 :             :         {
     234                 :    19633840 :           edge e;
     235                 :    19633840 :           edge_iterator ei;
     236                 :    19633840 :           rtx src = NULL_RTX;
     237                 :    19633840 :           rtx dest = NULL_RTX;
     238                 :             : 
     239                 :             :           /* Iterate over each incoming edge and see if they
     240                 :             :              all have the same implicit set.  */
     241                 :    19633970 :           FOR_EACH_EDGE (e, ei, bb->preds)
     242                 :             :             {
     243                 :             :               /* Skip the entry/exit block.  */
     244                 :    19633840 :               if (e->src == ENTRY_BLOCK_PTR_FOR_FN (cfun))
     245                 :             :                 break;
     246                 :             : 
     247                 :             :               /* Verify this block ends with a suitable condjump  */
     248                 :    17692305 :               rtx_insn *condjump = BB_END (e->src);
     249                 :    17692305 :               if (!condjump || ! any_condjump_p (condjump))
     250                 :             :                 break;
     251                 :             : 
     252                 :             :               /* This predecessor ends with a possible equivalence
     253                 :             :                  producing conditional branch.  Extract the condition
     254                 :             :                  and try to use it to create an equivalence.  */
     255                 :    13638073 :               rtx pat = pc_set (condjump);
     256                 :    13638073 :               rtx i_t_e = SET_SRC (pat);
     257                 :    13638073 :               gcc_assert (GET_CODE (i_t_e) == IF_THEN_ELSE);
     258                 :    13638073 :               rtx cond = XEXP (i_t_e, 0);
     259                 :             : 
     260                 :    13638073 :               if ((((e->flags & EDGE_FALLTHRU) != 0)
     261                 :    13638073 :                    == (XEXP (i_t_e, 1) == pc_rtx))
     262                 :    13638073 :                   ? GET_CODE (cond) == EQ
     263                 :     8394947 :                   : GET_CODE (cond) == NE)
     264                 :             :                 {
     265                 :             :                   /* If this is the first time through record
     266                 :             :                      the source and destination.  */
     267                 :     5336199 :                   if (!dest)
     268                 :             :                     {
     269                 :     5336199 :                       dest = XEXP (cond, 0);
     270                 :     5336199 :                       src = XEXP (cond, 1);
     271                 :             :                     }
     272                 :             :                   /* If this is not the first time through, then
     273                 :             :                      verify the source and destination match.  */
     274                 :           0 :                   else if (rtx_equal_p (dest, XEXP (cond, 0))
     275                 :           0 :                            && rtx_equal_p (src, XEXP (cond, 1)))
     276                 :             :                     ;
     277                 :             :                   else
     278                 :             :                     break;
     279                 :             : 
     280                 :             :                   /* A few more checks.  First make sure we're dealing with
     281                 :             :                      integer modes, second make sure the values aren't clobbered
     282                 :             :                      by the conditional branch itself.  Do this for every
     283                 :             :                      conditional jump participating in creation of the
     284                 :             :                      equivalence.  */
     285                 :     5336199 :                   if (!REG_P (dest)
     286                 :     5336175 :                       || !(REG_P (src) || CONST_INT_P (src))
     287                 :     5336175 :                       || GET_MODE_CLASS (GET_MODE (dest)) != MODE_INT
     288                 :         130 :                       || reg_set_p (dest, condjump)
     289                 :     5336329 :                       || reg_set_p (src, condjump))
     290                 :             :                     break;
     291                 :             : 
     292                 :             :                 }
     293                 :             :               else
     294                 :             :                 break;
     295                 :             :             }
     296                 :             : 
     297                 :             :           /* If all the incoming edges had the same implicit
     298                 :             :              set, then create a dummy insn for that set.
     299                 :             : 
     300                 :             :              It will be entered into the cselib tables before
     301                 :             :              we process the first real insn in this block.  */
     302                 :    19633840 :           if (dest && ei_end_p (ei))
     303                 :         130 :             implicit_set = make_insn_raw (gen_rtx_SET (dest, src));
     304                 :             :         }
     305                 :             : 
     306                 :   253554087 :       FOR_BB_INSNS (bb, insn)
     307                 :             :         {
     308                 :   233425210 :           if (INSN_P (insn))
     309                 :             :             {
     310                 :             :               /* If we recorded an implicit set, enter it
     311                 :             :                  into the tables before the first real insn.
     312                 :             : 
     313                 :             :                  We have to do it this way because a CODE_LABEL
     314                 :             :                  will flush the cselib tables.  */
     315                 :   191449384 :               if (implicit_set)
     316                 :             :                 {
     317                 :         130 :                   cselib_process_insn (implicit_set);
     318                 :         130 :                   implicit_set = NULL;
     319                 :             :                 }
     320                 :   191449384 :               cfg_changed |= reload_cse_simplify (insn, testreg);
     321                 :             :             }
     322                 :             : 
     323                 :   233425210 :           cselib_process_insn (insn);
     324                 :             :         }
     325                 :             :     }
     326                 :             : 
     327                 :             :   /* Clean up.  */
     328                 :     1941592 :   end_alias_analysis ();
     329                 :     1941592 :   cselib_finish ();
     330                 :     1941592 :   if (cfg_changed)
     331                 :          85 :     cleanup_cfg (0);
     332                 :     1941592 : }
     333                 :             : 
     334                 :             : /* Try to simplify a single SET instruction.  SET is the set pattern.
     335                 :             :    INSN is the instruction it came from.
     336                 :             :    This function only handles one case: if we set a register to a value
     337                 :             :    which is not a register, we try to find that value in some other register
     338                 :             :    and change the set into a register copy.  */
     339                 :             : 
     340                 :             : static int
     341                 :    97744671 : reload_cse_simplify_set (rtx set, rtx_insn *insn)
     342                 :             : {
     343                 :    97744671 :   int did_change = 0;
     344                 :    97744671 :   int dreg;
     345                 :    97744671 :   rtx src;
     346                 :    97744671 :   reg_class_t dclass;
     347                 :    97744671 :   int old_cost;
     348                 :    97744671 :   cselib_val *val;
     349                 :    97744671 :   struct elt_loc_list *l;
     350                 :    97744671 :   enum rtx_code extend_op = UNKNOWN;
     351                 :    97744671 :   bool speed = optimize_bb_for_speed_p (BLOCK_FOR_INSN (insn));
     352                 :             : 
     353                 :    97744671 :   dreg = true_regnum (SET_DEST (set));
     354                 :    97744671 :   if (dreg < 0)
     355                 :             :     return 0;
     356                 :             : 
     357                 :    66400825 :   src = SET_SRC (set);
     358                 :    66400825 :   if (side_effects_p (src) || true_regnum (src) >= 0)
     359                 :    10620069 :     return 0;
     360                 :             : 
     361                 :    55780756 :   dclass = REGNO_REG_CLASS (dreg);
     362                 :             : 
     363                 :             :   /* When replacing a memory with a register, we need to honor assumptions
     364                 :             :      that combine made wrt the contents of sign bits.  We'll do this by
     365                 :             :      generating an extend instruction instead of a reg->reg copy.  Thus
     366                 :             :      the destination must be a register that we can widen.  */
     367                 :    55780756 :   if (MEM_P (src)
     368                 :             :       && (extend_op = load_extend_op (GET_MODE (src))) != UNKNOWN
     369                 :             :       && !REG_P (SET_DEST (set)))
     370                 :             :     return 0;
     371                 :             : 
     372                 :    55780756 :   val = cselib_lookup (src, GET_MODE (SET_DEST (set)), 0, VOIDmode);
     373                 :    55780756 :   if (! val)
     374                 :             :     return 0;
     375                 :             : 
     376                 :             :   /* If memory loads are cheaper than register copies, don't change them.  */
     377                 :     5605661 :   if (MEM_P (src))
     378                 :      629410 :     old_cost = memory_move_cost (GET_MODE (src), dclass, true);
     379                 :     4976251 :   else if (REG_P (src))
     380                 :           0 :     old_cost = register_move_cost (GET_MODE (src),
     381                 :           0 :                                    REGNO_REG_CLASS (REGNO (src)), dclass);
     382                 :             :   else
     383                 :     4976251 :     old_cost = set_src_cost (src, GET_MODE (SET_DEST (set)), speed);
     384                 :             : 
     385                 :    11263021 :   for (l = val->locs; l; l = l->next)
     386                 :             :     {
     387                 :     5657360 :       rtx this_rtx = l->loc;
     388                 :     5657360 :       int this_cost;
     389                 :             : 
     390                 :     5657360 :       if (CONSTANT_P (this_rtx) && ! references_value_p (this_rtx, 0))
     391                 :             :         {
     392                 :     1987577 :           if (extend_op != UNKNOWN)
     393                 :             :             {
     394                 :             :               wide_int result;
     395                 :             : 
     396                 :             :               if (!CONST_SCALAR_INT_P (this_rtx))
     397                 :             :                 continue;
     398                 :             : 
     399                 :             :               switch (extend_op)
     400                 :             :                 {
     401                 :             :                 case ZERO_EXTEND:
     402                 :             :                   result = wide_int::from (rtx_mode_t (this_rtx,
     403                 :             :                                                        GET_MODE (src)),
     404                 :             :                                            BITS_PER_WORD, UNSIGNED);
     405                 :             :                   break;
     406                 :             :                 case SIGN_EXTEND:
     407                 :             :                   result = wide_int::from (rtx_mode_t (this_rtx,
     408                 :             :                                                        GET_MODE (src)),
     409                 :             :                                            BITS_PER_WORD, SIGNED);
     410                 :             :                   break;
     411                 :             :                 default:
     412                 :             :                   gcc_unreachable ();
     413                 :             :                 }
     414                 :             :               this_rtx = immed_wide_int_const (result, word_mode);
     415                 :             :             }
     416                 :             : 
     417                 :     1987577 :           this_cost = set_src_cost (this_rtx, GET_MODE (SET_DEST (set)), speed);
     418                 :             :         }
     419                 :     3669783 :       else if (REG_P (this_rtx))
     420                 :             :         {
     421                 :      821355 :           if (extend_op != UNKNOWN)
     422                 :             :             {
     423                 :             :               this_rtx = gen_rtx_fmt_e (extend_op, word_mode, this_rtx);
     424                 :             :               this_cost = set_src_cost (this_rtx, word_mode, speed);
     425                 :             :             }
     426                 :             :           else
     427                 :      821355 :             this_cost = register_move_cost (GET_MODE (this_rtx),
     428                 :      821355 :                                             REGNO_REG_CLASS (REGNO (this_rtx)),
     429                 :             :                                             dclass);
     430                 :             :         }
     431                 :             :       else
     432                 :     2848428 :         continue;
     433                 :             : 
     434                 :             :       /* If equal costs, prefer registers over anything else.  That
     435                 :             :          tends to lead to smaller instructions on some machines.  */
     436                 :     2808932 :       if (this_cost < old_cost
     437                 :     2662241 :           || (this_cost == old_cost
     438                 :     1997240 :               && REG_P (this_rtx)
     439                 :       17451 :               && !REG_P (SET_SRC (set))))
     440                 :             :         {
     441                 :      152028 :           if (extend_op != UNKNOWN
     442                 :             :               && REG_CAN_CHANGE_MODE_P (REGNO (SET_DEST (set)),
     443                 :             :                                         GET_MODE (SET_DEST (set)), word_mode))
     444                 :             :             {
     445                 :             :               rtx wide_dest = gen_rtx_REG (word_mode, REGNO (SET_DEST (set)));
     446                 :             :               ORIGINAL_REGNO (wide_dest) = ORIGINAL_REGNO (SET_DEST (set));
     447                 :             :               validate_change (insn, &SET_DEST (set), wide_dest, 1);
     448                 :             :             }
     449                 :             : 
     450                 :      152028 :           validate_unshare_change (insn, &SET_SRC (set), this_rtx, 1);
     451                 :      152028 :           old_cost = this_cost, did_change = 1;
     452                 :             :         }
     453                 :             :     }
     454                 :             : 
     455                 :             :   return did_change;
     456                 :             : }
     457                 :             : 
     458                 :             : /* Try to replace operands in INSN with equivalent values that are already
     459                 :             :    in registers.  This can be viewed as optional reloading.
     460                 :             : 
     461                 :             :    For each non-register operand in the insn, see if any hard regs are
     462                 :             :    known to be equivalent to that operand.  Record the alternatives which
     463                 :             :    can accept these hard registers.  Among all alternatives, select the
     464                 :             :    ones which are better or equal to the one currently matching, where
     465                 :             :    "better" is in terms of '?' and '!' constraints.  Among the remaining
     466                 :             :    alternatives, select the one which replaces most operands with
     467                 :             :    hard registers.  */
     468                 :             : 
     469                 :             : static int
     470                 :    96686785 : reload_cse_simplify_operands (rtx_insn *insn, rtx testreg)
     471                 :             : {
     472                 :    96686785 :   int i, j;
     473                 :             : 
     474                 :             :   /* For each operand, all registers that are equivalent to it.  */
     475                 :    96686785 :   HARD_REG_SET equiv_regs[MAX_RECOG_OPERANDS];
     476                 :             : 
     477                 :    96686785 :   const char *constraints[MAX_RECOG_OPERANDS];
     478                 :             : 
     479                 :             :   /* Vector recording how bad an alternative is.  */
     480                 :    96686785 :   int *alternative_reject;
     481                 :             :   /* Vector recording how many registers can be introduced by choosing
     482                 :             :      this alternative.  */
     483                 :    96686785 :   int *alternative_nregs;
     484                 :             :   /* Array of vectors recording, for each operand and each alternative,
     485                 :             :      which hard register to substitute, or -1 if the operand should be
     486                 :             :      left as it is.  */
     487                 :    96686785 :   int *op_alt_regno[MAX_RECOG_OPERANDS];
     488                 :             :   /* Array of alternatives, sorted in order of decreasing desirability.  */
     489                 :    96686785 :   int *alternative_order;
     490                 :             : 
     491                 :    96686785 :   extract_constrain_insn (insn);
     492                 :             : 
     493                 :    96686785 :   if (recog_data.n_alternatives == 0 || recog_data.n_operands == 0)
     494                 :             :     return 0;
     495                 :             : 
     496                 :    83596695 :   alternative_reject = XALLOCAVEC (int, recog_data.n_alternatives);
     497                 :    83596695 :   alternative_nregs = XALLOCAVEC (int, recog_data.n_alternatives);
     498                 :    83596695 :   alternative_order = XALLOCAVEC (int, recog_data.n_alternatives);
     499                 :    83596695 :   memset (alternative_reject, 0, recog_data.n_alternatives * sizeof (int));
     500                 :    83596695 :   memset (alternative_nregs, 0, recog_data.n_alternatives * sizeof (int));
     501                 :             : 
     502                 :             :   /* For each operand, find out which regs are equivalent.  */
     503                 :   270448264 :   for (i = 0; i < recog_data.n_operands; i++)
     504                 :             :     {
     505                 :             :       cselib_val *v;
     506                 :             :       struct elt_loc_list *l;
     507                 :             :       rtx op;
     508                 :             : 
     509                 :   186851569 :       CLEAR_HARD_REG_SET (equiv_regs[i]);
     510                 :             : 
     511                 :             :       /* cselib blows up on CODE_LABELs.  Trying to fix that doesn't seem
     512                 :             :          right, so avoid the problem here.  Similarly NOTE_INSN_DELETED_LABEL.
     513                 :             :          Likewise if we have a constant and the insn pattern doesn't tell us
     514                 :             :          the mode we need.  */
     515                 :   186851569 :       if (LABEL_P (recog_data.operand[i])
     516                 :   186838486 :           || (NOTE_P (recog_data.operand[i])
     517                 :          80 :               && NOTE_KIND (recog_data.operand[i]) == NOTE_INSN_DELETED_LABEL)
     518                 :   186838406 :           || (CONSTANT_P (recog_data.operand[i])
     519                 :    32124246 :               && recog_data.operand_mode[i] == VOIDmode))
     520                 :      547279 :         continue;
     521                 :             : 
     522                 :   186304290 :       op = recog_data.operand[i];
     523                 :   186304290 :       if (MEM_P (op) && load_extend_op (GET_MODE (op)) != UNKNOWN)
     524                 :             :         {
     525                 :             :           rtx set = single_set (insn);
     526                 :             : 
     527                 :             :           /* We might have multiple sets, some of which do implicit
     528                 :             :              extension.  Punt on this for now.  */
     529                 :             :           if (! set)
     530                 :             :             continue;
     531                 :             :           /* If the destination is also a MEM or a STRICT_LOW_PART, no
     532                 :             :              extension applies.
     533                 :             :              Also, if there is an explicit extension, we don't have to
     534                 :             :              worry about an implicit one.  */
     535                 :             :           else if (MEM_P (SET_DEST (set))
     536                 :             :                    || GET_CODE (SET_DEST (set)) == STRICT_LOW_PART
     537                 :             :                    || GET_CODE (SET_SRC (set)) == ZERO_EXTEND
     538                 :             :                    || GET_CODE (SET_SRC (set)) == SIGN_EXTEND)
     539                 :             :             ; /* Continue ordinary processing.  */
     540                 :             :           /* If the register cannot change mode to word_mode, it follows that
     541                 :             :              it cannot have been used in word_mode.  */
     542                 :             :           else if (REG_P (SET_DEST (set))
     543                 :             :                    && !REG_CAN_CHANGE_MODE_P (REGNO (SET_DEST (set)),
     544                 :             :                                               GET_MODE (SET_DEST (set)),
     545                 :             :                                               word_mode))
     546                 :             :             ; /* Continue ordinary processing.  */
     547                 :             :           /* If this is a straight load, make the extension explicit.  */
     548                 :             :           else if (REG_P (SET_DEST (set))
     549                 :             :                    && recog_data.n_operands == 2
     550                 :             :                    && SET_SRC (set) == op
     551                 :             :                    && SET_DEST (set) == recog_data.operand[1-i])
     552                 :             :             {
     553                 :             :               validate_change (insn, recog_data.operand_loc[i],
     554                 :             :                                gen_rtx_fmt_e (load_extend_op (GET_MODE (op)),
     555                 :             :                                               word_mode, op),
     556                 :             :                                1);
     557                 :             :               validate_change (insn, recog_data.operand_loc[1-i],
     558                 :             :                                gen_rtx_REG (word_mode, REGNO (SET_DEST (set))),
     559                 :             :                                1);
     560                 :             :               if (! apply_change_group ())
     561                 :             :                 return 0;
     562                 :             :               return reload_cse_simplify_operands (insn, testreg);
     563                 :             :             }
     564                 :             :           else
     565                 :             :             /* ??? There might be arithmetic operations with memory that are
     566                 :             :                safe to optimize, but is it worth the trouble?  */
     567                 :             :             continue;
     568                 :             :         }
     569                 :             : 
     570                 :   186304290 :       if (side_effects_p (op))
     571                 :     4484705 :         continue;
     572                 :   181819585 :       v = cselib_lookup (op, recog_data.operand_mode[i], 0, VOIDmode);
     573                 :   181819585 :       if (! v)
     574                 :   120086881 :         continue;
     575                 :             : 
     576                 :   180789900 :       for (l = v->locs; l; l = l->next)
     577                 :   119057196 :         if (REG_P (l->loc))
     578                 :    64118399 :           SET_HARD_REG_BIT (equiv_regs[i], REGNO (l->loc));
     579                 :             :     }
     580                 :             : 
     581                 :    83596695 :   alternative_mask preferred = get_preferred_alternatives (insn);
     582                 :   270448264 :   for (i = 0; i < recog_data.n_operands; i++)
     583                 :             :     {
     584                 :   186851569 :       machine_mode mode;
     585                 :   186851569 :       int regno;
     586                 :   186851569 :       const char *p;
     587                 :             : 
     588                 :   186851569 :       op_alt_regno[i] = XALLOCAVEC (int, recog_data.n_alternatives);
     589                 :  2745334797 :       for (j = 0; j < recog_data.n_alternatives; j++)
     590                 :  2558483228 :         op_alt_regno[i][j] = -1;
     591                 :             : 
     592                 :   186851569 :       p = constraints[i] = recog_data.constraints[i];
     593                 :   186851569 :       mode = recog_data.operand_mode[i];
     594                 :             : 
     595                 :             :       /* Add the reject values for each alternative given by the constraints
     596                 :             :          for this operand.  */
     597                 :   186851569 :       j = 0;
     598                 :  7417041863 :       while (*p != '\0')
     599                 :             :         {
     600                 :  7230190294 :           char c = *p++;
     601                 :  7230190294 :           if (c == ',')
     602                 :  2363217132 :             j++;
     603                 :  4866973162 :           else if (c == '?')
     604                 :   585621992 :             alternative_reject[j] += 3;
     605                 :  4281351170 :           else if (c == '!')
     606                 :    18622804 :             alternative_reject[j] += 300;
     607                 :             :         }
     608                 :             : 
     609                 :             :       /* We won't change operands which are already registers.  We
     610                 :             :          also don't want to modify output operands.  */
     611                 :   186851569 :       regno = true_regnum (recog_data.operand[i]);
     612                 :   186851569 :       if (regno >= 0
     613                 :    74344594 :           || constraints[i][0] == '='
     614                 :    56262397 :           || constraints[i][0] == '+')
     615                 :   130704595 :         continue;
     616                 :             : 
     617                 :  5221668582 :       for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
     618                 :             :         {
     619                 :  5165521608 :           enum reg_class rclass = NO_REGS;
     620                 :             : 
     621                 :  5165521608 :           if (! TEST_HARD_REG_BIT (equiv_regs[i], regno))
     622                 :  5164769686 :             continue;
     623                 :             : 
     624                 :      751922 :           set_mode_and_regno (testreg, mode, regno);
     625                 :             : 
     626                 :             :           /* We found a register equal to this operand.  Now look for all
     627                 :             :              alternatives that can accept this register and have not been
     628                 :             :              assigned a register they can use yet.  */
     629                 :      751922 :           j = 0;
     630                 :      751922 :           p = constraints[i];
     631                 :    39360150 :           for (;;)
     632                 :             :             {
     633                 :    39360150 :               char c = *p;
     634                 :             : 
     635                 :    39360150 :               switch (c)
     636                 :             :                 {
     637                 :      196618 :                 case 'g':
     638                 :      196618 :                   rclass = reg_class_subunion[rclass][GENERAL_REGS];
     639                 :      196618 :                   break;
     640                 :             : 
     641                 :    24865503 :                 default:
     642                 :    24865503 :                   rclass
     643                 :    24865503 :                     = (reg_class_subunion
     644                 :    24865503 :                        [rclass]
     645                 :    24865503 :                        [reg_class_for_constraint (lookup_constraint (p))]);
     646                 :    24865503 :                   break;
     647                 :             : 
     648                 :    14298029 :                 case ',': case '\0':
     649                 :             :                   /* See if REGNO fits this alternative, and set it up as the
     650                 :             :                      replacement register if we don't have one for this
     651                 :             :                      alternative yet and the operand being replaced is not
     652                 :             :                      a cheap CONST_INT.  */
     653                 :    14298029 :                   if (op_alt_regno[i][j] == -1
     654                 :    14229209 :                       && TEST_BIT (preferred, j)
     655                 :     9786475 :                       && reg_fits_class_p (testreg, rclass, 0, mode)
     656                 :    16737769 :                       && (!CONST_INT_P (recog_data.operand[i])
     657                 :     2305083 :                           || (set_src_cost (recog_data.operand[i], mode,
     658                 :             :                                             optimize_bb_for_speed_p
     659                 :     2305083 :                                              (BLOCK_FOR_INSN (insn)))
     660                 :     2305083 :                               > set_src_cost (testreg, mode,
     661                 :             :                                               optimize_bb_for_speed_p
     662                 :     2305083 :                                                (BLOCK_FOR_INSN (insn))))))
     663                 :             :                     {
     664                 :      134657 :                       alternative_nregs[j]++;
     665                 :      134657 :                       op_alt_regno[i][j] = regno;
     666                 :             :                     }
     667                 :    14298029 :                   j++;
     668                 :    14298029 :                   rclass = NO_REGS;
     669                 :    14298029 :                   break;
     670                 :             :                 }
     671                 :    39360150 :               p += CONSTRAINT_LEN (c, p);
     672                 :             : 
     673                 :    39360150 :               if (c == '\0')
     674                 :             :                 break;
     675                 :             :             }
     676                 :             :         }
     677                 :             :     }
     678                 :             : 
     679                 :             :   /* The loop below sets alternative_order[0] but -Wmaybe-uninitialized
     680                 :             :      can't know that.  Clear it here to avoid the warning.  */
     681                 :    83596695 :   alternative_order[0] = 0;
     682                 :    83596695 :   gcc_assert (!recog_data.n_alternatives
     683                 :             :               || (which_alternative >= 0
     684                 :             :                   && which_alternative < recog_data.n_alternatives));
     685                 :             : 
     686                 :             :   /* Record all alternatives which are better or equal to the currently
     687                 :             :      matching one in the alternative_order array.  */
     688                 :  1306899552 :   for (i = j = 0; i < recog_data.n_alternatives; i++)
     689                 :  1223302857 :     if (alternative_reject[i] <= alternative_reject[which_alternative])
     690                 :   709165114 :       alternative_order[j++] = i;
     691                 :    83596695 :   recog_data.n_alternatives = j;
     692                 :             : 
     693                 :             :   /* Sort it.  Given a small number of alternatives, a dumb algorithm
     694                 :             :      won't hurt too much.  */
     695                 :   709165114 :   for (i = 0; i < recog_data.n_alternatives - 1; i++)
     696                 :             :     {
     697                 :   625568419 :       int best = i;
     698                 :   625568419 :       int best_reject = alternative_reject[alternative_order[i]];
     699                 :   625568419 :       int best_nregs = alternative_nregs[alternative_order[i]];
     700                 :             : 
     701                 :  4351578692 :       for (j = i + 1; j < recog_data.n_alternatives; j++)
     702                 :             :         {
     703                 :  3726010273 :           int this_reject = alternative_reject[alternative_order[j]];
     704                 :  3726010273 :           int this_nregs = alternative_nregs[alternative_order[j]];
     705                 :             : 
     706                 :  3726010273 :           if (this_reject < best_reject
     707                 :  3719058634 :               || (this_reject == best_reject && this_nregs > best_nregs))
     708                 :             :             {
     709                 :     7029155 :               best = j;
     710                 :     7029155 :               best_reject = this_reject;
     711                 :     7029155 :               best_nregs = this_nregs;
     712                 :             :             }
     713                 :             :         }
     714                 :             : 
     715                 :   625568419 :       std::swap (alternative_order[best], alternative_order[i]);
     716                 :             :     }
     717                 :             : 
     718                 :             :   /* Substitute the operands as determined by op_alt_regno for the best
     719                 :             :      alternative.  */
     720                 :    83596695 :   j = alternative_order[0];
     721                 :             : 
     722                 :   270448264 :   for (i = 0; i < recog_data.n_operands; i++)
     723                 :             :     {
     724                 :   186851569 :       machine_mode mode = recog_data.operand_mode[i];
     725                 :   186851569 :       if (op_alt_regno[i][j] == -1)
     726                 :   186800235 :         continue;
     727                 :             : 
     728                 :       51334 :       validate_change (insn, recog_data.operand_loc[i],
     729                 :             :                        gen_rtx_REG (mode, op_alt_regno[i][j]), 1);
     730                 :             :     }
     731                 :             : 
     732                 :    84889696 :   for (i = recog_data.n_dups - 1; i >= 0; i--)
     733                 :             :     {
     734                 :     1293001 :       int op = recog_data.dup_num[i];
     735                 :     1293001 :       machine_mode mode = recog_data.operand_mode[op];
     736                 :             : 
     737                 :     1293001 :       if (op_alt_regno[op][j] == -1)
     738                 :     1292724 :         continue;
     739                 :             : 
     740                 :         277 :       validate_change (insn, recog_data.dup_loc[i],
     741                 :             :                        gen_rtx_REG (mode, op_alt_regno[op][j]), 1);
     742                 :             :     }
     743                 :             : 
     744                 :    83596695 :   return apply_change_group ();
     745                 :             : }
     746                 :             : 
     747                 :             : /* If reload couldn't use reg+reg+offset addressing, try to use reg+reg
     748                 :             :    addressing now.
     749                 :             :    This code might also be useful when reload gave up on reg+reg addressing
     750                 :             :    because of clashes between the return register and INDEX_REG_CLASS.  */
     751                 :             : 
     752                 :             : /* The maximum number of uses of a register we can keep track of to
     753                 :             :    replace them with reg+reg addressing.  */
     754                 :             : #define RELOAD_COMBINE_MAX_USES 16
     755                 :             : 
     756                 :             : /* Describes a recorded use of a register.  */
     757                 :             : struct reg_use
     758                 :             : {
     759                 :             :   /* The insn where a register has been used.  */
     760                 :             :   rtx_insn *insn;
     761                 :             :   /* Points to the memory reference enclosing the use, if any, NULL_RTX
     762                 :             :      otherwise.  */
     763                 :             :   rtx containing_mem;
     764                 :             :   /* Location of the register within INSN.  */
     765                 :             :   rtx *usep;
     766                 :             :   /* The reverse uid of the insn.  */
     767                 :             :   int ruid;
     768                 :             : };
     769                 :             : 
     770                 :             : /* If the register is used in some unknown fashion, USE_INDEX is negative.
     771                 :             :    If it is dead, USE_INDEX is RELOAD_COMBINE_MAX_USES, and STORE_RUID
     772                 :             :    indicates where it is first set or clobbered.
     773                 :             :    Otherwise, USE_INDEX is the index of the last encountered use of the
     774                 :             :    register (which is first among these we have seen since we scan backwards).
     775                 :             :    USE_RUID indicates the first encountered, i.e. last, of these uses.
     776                 :             :    If ALL_OFFSETS_MATCH is true, all encountered uses were inside a PLUS
     777                 :             :    with a constant offset; OFFSET contains this constant in that case.
     778                 :             :    STORE_RUID is always meaningful if we only want to use a value in a
     779                 :             :    register in a different place: it denotes the next insn in the insn
     780                 :             :    stream (i.e. the last encountered) that sets or clobbers the register.
     781                 :             :    REAL_STORE_RUID is similar, but clobbers are ignored when updating it.
     782                 :             :    EXPR is the expression used when storing the register.  */
     783                 :             : static struct
     784                 :             :   {
     785                 :             :     struct reg_use reg_use[RELOAD_COMBINE_MAX_USES];
     786                 :             :     rtx offset;
     787                 :             :     int use_index;
     788                 :             :     int store_ruid;
     789                 :             :     int real_store_ruid;
     790                 :             :     int use_ruid;
     791                 :             :     bool all_offsets_match;
     792                 :             :     rtx expr;
     793                 :             :   } reg_state[FIRST_PSEUDO_REGISTER];
     794                 :             : 
     795                 :             : /* Reverse linear uid.  This is increased in reload_combine while scanning
     796                 :             :    the instructions from last to first.  It is used to set last_label_ruid
     797                 :             :    and the store_ruid / use_ruid fields in reg_state.  */
     798                 :             : static int reload_combine_ruid;
     799                 :             : 
     800                 :             : /* The RUID of the last label we encountered in reload_combine.  */
     801                 :             : static int last_label_ruid;
     802                 :             : 
     803                 :             : /* The RUID of the last jump we encountered in reload_combine.  */
     804                 :             : static int last_jump_ruid;
     805                 :             : 
     806                 :             : /* The register numbers of the first and last index register.  A value of
     807                 :             :    -1 in LAST_INDEX_REG indicates that we've previously computed these
     808                 :             :    values and found no suitable index registers.  */
     809                 :             : static int first_index_reg = -1;
     810                 :             : static int last_index_reg;
     811                 :             : 
     812                 :             : #define LABEL_LIVE(LABEL) \
     813                 :             :   (label_live[CODE_LABEL_NUMBER (LABEL) - min_labelno])
     814                 :             : 
     815                 :             : /* Subroutine of reload_combine_split_ruids, called to fix up a single
     816                 :             :    ruid pointed to by *PRUID if it is higher than SPLIT_RUID.  */
     817                 :             : 
     818                 :             : static inline void
     819                 :      185952 : reload_combine_split_one_ruid (int *pruid, int split_ruid)
     820                 :             : {
     821                 :      185952 :   if (*pruid > split_ruid)
     822                 :        8193 :     (*pruid)++;
     823                 :             : }
     824                 :             : 
     825                 :             : /* Called when we insert a new insn in a position we've already passed in
     826                 :             :    the scan.  Examine all our state, increasing all ruids that are higher
     827                 :             :    than SPLIT_RUID by one in order to make room for a new insn.  */
     828                 :             : 
     829                 :             : static void
     830                 :         659 : reload_combine_split_ruids (int split_ruid)
     831                 :             : {
     832                 :         659 :   unsigned i;
     833                 :             : 
     834                 :         659 :   reload_combine_split_one_ruid (&reload_combine_ruid, split_ruid);
     835                 :         659 :   reload_combine_split_one_ruid (&last_label_ruid, split_ruid);
     836                 :         659 :   reload_combine_split_one_ruid (&last_jump_ruid, split_ruid);
     837                 :             : 
     838                 :       61287 :   for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
     839                 :             :     {
     840                 :       60628 :       int j, idx = reg_state[i].use_index;
     841                 :       60628 :       reload_combine_split_one_ruid (&reg_state[i].use_ruid, split_ruid);
     842                 :       60628 :       reload_combine_split_one_ruid (&reg_state[i].store_ruid, split_ruid);
     843                 :       60628 :       reload_combine_split_one_ruid (&reg_state[i].real_store_ruid,
     844                 :             :                                      split_ruid);
     845                 :       60628 :       if (idx < 0)
     846                 :       24562 :         continue;
     847                 :       38157 :       for (j = idx; j < RELOAD_COMBINE_MAX_USES; j++)
     848                 :             :         {
     849                 :        3591 :           reload_combine_split_one_ruid (&reg_state[i].reg_use[j].ruid,
     850                 :             :                                          split_ruid);
     851                 :             :         }
     852                 :             :     }
     853                 :         659 : }
     854                 :             : 
     855                 :             : /* Called when we are about to rescan a previously encountered insn with
     856                 :             :    reload_combine_note_use after modifying some part of it.  This clears all
     857                 :             :    information about uses in that particular insn.  */
     858                 :             : 
     859                 :             : static void
     860                 :        5837 : reload_combine_purge_insn_uses (rtx_insn *insn)
     861                 :             : {
     862                 :        5837 :   unsigned i;
     863                 :             : 
     864                 :      542841 :   for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
     865                 :             :     {
     866                 :      537004 :       int j, k, idx = reg_state[i].use_index;
     867                 :      537004 :       if (idx < 0)
     868                 :      121421 :         continue;
     869                 :             :       j = k = RELOAD_COMBINE_MAX_USES;
     870                 :      471124 :       while (j-- > idx)
     871                 :             :         {
     872                 :       55541 :           if (reg_state[i].reg_use[j].insn != insn)
     873                 :             :             {
     874                 :       48992 :               k--;
     875                 :       48992 :               if (k != j)
     876                 :        3750 :                 reg_state[i].reg_use[k] = reg_state[i].reg_use[j];
     877                 :             :             }
     878                 :             :         }
     879                 :      415583 :       reg_state[i].use_index = k;
     880                 :             :     }
     881                 :        5837 : }
     882                 :             : 
     883                 :             : /* Called when we need to forget about all uses of REGNO after an insn
     884                 :             :    which is identified by RUID.  */
     885                 :             : 
     886                 :             : static void
     887                 :         659 : reload_combine_purge_reg_uses_after_ruid (unsigned regno, int ruid)
     888                 :             : {
     889                 :         659 :   int j, k, idx = reg_state[regno].use_index;
     890                 :         659 :   if (idx < 0)
     891                 :             :     return;
     892                 :             :   j = k = RELOAD_COMBINE_MAX_USES;
     893                 :        2593 :   while (j-- > idx)
     894                 :             :     {
     895                 :        1934 :       if (reg_state[regno].reg_use[j].ruid >= ruid)
     896                 :             :         {
     897                 :         856 :           k--;
     898                 :         856 :           if (k != j)
     899                 :         644 :             reg_state[regno].reg_use[k] = reg_state[regno].reg_use[j];
     900                 :             :         }
     901                 :             :     }
     902                 :         659 :   reg_state[regno].use_index = k;
     903                 :             : }
     904                 :             : 
     905                 :             : /* Find the use of REGNO with the ruid that is highest among those
     906                 :             :    lower than RUID_LIMIT, and return it if it is the only use of this
     907                 :             :    reg in the insn.  Return NULL otherwise.  */
     908                 :             : 
     909                 :             : static struct reg_use *
     910                 :     3540393 : reload_combine_closest_single_use (unsigned regno, int ruid_limit)
     911                 :             : {
     912                 :     3540393 :   int i, best_ruid = 0;
     913                 :     3540393 :   int use_idx = reg_state[regno].use_index;
     914                 :     3540393 :   struct reg_use *retval;
     915                 :             : 
     916                 :     3540393 :   if (use_idx < 0)
     917                 :             :     return NULL;
     918                 :             :   retval = NULL;
     919                 :     3555323 :   for (i = use_idx; i < RELOAD_COMBINE_MAX_USES; i++)
     920                 :             :     {
     921                 :     2068647 :       struct reg_use *use = reg_state[regno].reg_use + i;
     922                 :     2068647 :       int this_ruid = use->ruid;
     923                 :     2068647 :       if (this_ruid >= ruid_limit)
     924                 :      774900 :         continue;
     925                 :     1293747 :       if (this_ruid > best_ruid)
     926                 :             :         {
     927                 :             :           best_ruid = this_ruid;
     928                 :             :           retval = use;
     929                 :             :         }
     930                 :      347365 :       else if (this_ruid == best_ruid)
     931                 :     2068647 :         retval = NULL;
     932                 :             :     }
     933                 :     1486676 :   if (last_label_ruid >= best_ruid)
     934                 :      613180 :     return NULL;
     935                 :             :   return retval;
     936                 :             : }
     937                 :             : 
     938                 :             : /* After we've moved an add insn, fix up any debug insns that occur
     939                 :             :    between the old location of the add and the new location.  REG is
     940                 :             :    the destination register of the add insn; REPLACEMENT is the
     941                 :             :    SET_SRC of the add.  FROM and TO specify the range in which we
     942                 :             :    should make this change on debug insns.  */
     943                 :             : 
     944                 :             : static void
     945                 :         826 : fixup_debug_insns (rtx reg, rtx replacement, rtx_insn *from, rtx_insn *to)
     946                 :             : {
     947                 :         826 :   rtx_insn *insn;
     948                 :        6973 :   for (insn = from; insn != to; insn = NEXT_INSN (insn))
     949                 :             :     {
     950                 :        6147 :       rtx t;
     951                 :             : 
     952                 :        6147 :       if (!DEBUG_BIND_INSN_P (insn))
     953                 :        4721 :         continue;
     954                 :             : 
     955                 :        1426 :       t = INSN_VAR_LOCATION_LOC (insn);
     956                 :        1426 :       t = simplify_replace_rtx (t, reg, replacement);
     957                 :        1426 :       validate_change (insn, &INSN_VAR_LOCATION_LOC (insn), t, 0);
     958                 :             :     }
     959                 :         826 : }
     960                 :             : 
     961                 :             : /* Subroutine of reload_combine_recognize_const_pattern.  Try to replace REG
     962                 :             :    with SRC in the insn described by USE, taking costs into account.  Return
     963                 :             :    true if we made the replacement.  */
     964                 :             : 
     965                 :             : static bool
     966                 :      742243 : try_replace_in_use (struct reg_use *use, rtx reg, rtx src)
     967                 :             : {
     968                 :      742243 :   rtx_insn *use_insn = use->insn;
     969                 :      742243 :   rtx mem = use->containing_mem;
     970                 :      742243 :   bool speed = optimize_bb_for_speed_p (BLOCK_FOR_INSN (use_insn));
     971                 :             : 
     972                 :      742243 :   if (mem != NULL_RTX)
     973                 :             :     {
     974                 :       17233 :       addr_space_t as = MEM_ADDR_SPACE (mem);
     975                 :       17233 :       rtx oldaddr = XEXP (mem, 0);
     976                 :       17233 :       rtx newaddr = NULL_RTX;
     977                 :       17233 :       int old_cost = address_cost (oldaddr, GET_MODE (mem), as, speed);
     978                 :       17233 :       int new_cost;
     979                 :             : 
     980                 :       17233 :       newaddr = simplify_replace_rtx (oldaddr, reg, src);
     981                 :       17233 :       if (memory_address_addr_space_p (GET_MODE (mem), newaddr, as))
     982                 :             :         {
     983                 :        5680 :           XEXP (mem, 0) = newaddr;
     984                 :        5680 :           new_cost = address_cost (newaddr, GET_MODE (mem), as, speed);
     985                 :        5680 :           XEXP (mem, 0) = oldaddr;
     986                 :        5680 :           if (new_cost <= old_cost
     987                 :        5680 :               && validate_change (use_insn,
     988                 :             :                                   &XEXP (mem, 0), newaddr, 0))
     989                 :             :             return true;
     990                 :             :         }
     991                 :             :     }
     992                 :             :   else
     993                 :             :     {
     994                 :      725010 :       rtx new_set = single_set (use_insn);
     995                 :      725010 :       if (new_set
     996                 :      724089 :           && REG_P (SET_DEST (new_set))
     997                 :      286263 :           && GET_CODE (SET_SRC (new_set)) == PLUS
     998                 :       18200 :           && REG_P (XEXP (SET_SRC (new_set), 0))
     999                 :       16668 :           && CONSTANT_P (XEXP (SET_SRC (new_set), 1)))
    1000                 :             :         {
    1001                 :        1304 :           rtx new_src;
    1002                 :        1304 :           machine_mode mode = GET_MODE (SET_DEST (new_set));
    1003                 :        1304 :           int old_cost = set_src_cost (SET_SRC (new_set), mode, speed);
    1004                 :             : 
    1005                 :        1304 :           gcc_assert (rtx_equal_p (XEXP (SET_SRC (new_set), 0), reg));
    1006                 :        1304 :           new_src = simplify_replace_rtx (SET_SRC (new_set), reg, src);
    1007                 :             : 
    1008                 :        1304 :           if (set_src_cost (new_src, mode, speed) <= old_cost
    1009                 :        1304 :               && validate_change (use_insn, &SET_SRC (new_set),
    1010                 :             :                                   new_src, 0))
    1011                 :             :             return true;
    1012                 :             :         }
    1013                 :             :     }
    1014                 :             :   return false;
    1015                 :             : }
    1016                 :             : 
    1017                 :             : /* Called by reload_combine when scanning INSN.  This function tries to detect
    1018                 :             :    patterns where a constant is added to a register, and the result is used
    1019                 :             :    in an address.
    1020                 :             :    Return true if no further processing is needed on INSN; false if it wasn't
    1021                 :             :    recognized and should be handled normally.  */
    1022                 :             : 
    1023                 :             : static bool
    1024                 :    58240510 : reload_combine_recognize_const_pattern (rtx_insn *insn)
    1025                 :             : {
    1026                 :    58240510 :   int from_ruid = reload_combine_ruid;
    1027                 :    58240510 :   rtx set, pat, reg, src, addreg;
    1028                 :    58240510 :   unsigned int regno;
    1029                 :    58240510 :   struct reg_use *use;
    1030                 :    58240510 :   bool must_move_add;
    1031                 :    58240510 :   rtx_insn *add_moved_after_insn = NULL;
    1032                 :    58240510 :   int add_moved_after_ruid = 0;
    1033                 :    58240510 :   int clobbered_regno = -1;
    1034                 :             : 
    1035                 :    58240510 :   set = single_set (insn);
    1036                 :    58240510 :   if (set == NULL_RTX)
    1037                 :             :     return false;
    1038                 :             : 
    1039                 :    54236009 :   reg = SET_DEST (set);
    1040                 :    54236009 :   src = SET_SRC (set);
    1041                 :    54236009 :   if (!REG_P (reg)
    1042                 :    37262792 :       || REG_NREGS (reg) != 1
    1043                 :    36652847 :       || GET_MODE (reg) != Pmode
    1044                 :    75412836 :       || reg == stack_pointer_rtx)
    1045                 :             :     return false;
    1046                 :             : 
    1047                 :    19496546 :   regno = REGNO (reg);
    1048                 :             : 
    1049                 :             :   /* We look for a REG1 = REG2 + CONSTANT insn, followed by either
    1050                 :             :      uses of REG1 inside an address, or inside another add insn.  If
    1051                 :             :      possible and profitable, merge the addition into subsequent
    1052                 :             :      uses.  */
    1053                 :    19496546 :   if (GET_CODE (src) != PLUS
    1054                 :     3724169 :       || !REG_P (XEXP (src, 0))
    1055                 :     3485710 :       || !CONSTANT_P (XEXP (src, 1)))
    1056                 :             :     return false;
    1057                 :             : 
    1058                 :     2893713 :   addreg = XEXP (src, 0);
    1059                 :     2893713 :   must_move_add = rtx_equal_p (reg, addreg);
    1060                 :             : 
    1061                 :     2893713 :   pat = PATTERN (insn);
    1062                 :     2893713 :   if (must_move_add && set != pat)
    1063                 :             :     {
    1064                 :             :       /* We have to be careful when moving the add; apart from the
    1065                 :             :          single_set there may also be clobbers.  Recognize one special
    1066                 :             :          case, that of one clobber alongside the set (likely a clobber
    1067                 :             :          of the CC register).  */
    1068                 :      772256 :       gcc_assert (GET_CODE (PATTERN (insn)) == PARALLEL);
    1069                 :      772256 :       if (XVECLEN (pat, 0) != 2 || XVECEXP (pat, 0, 0) != set
    1070                 :      772256 :           || GET_CODE (XVECEXP (pat, 0, 1)) != CLOBBER
    1071                 :      772256 :           || !REG_P (XEXP (XVECEXP (pat, 0, 1), 0)))
    1072                 :             :         return false;
    1073                 :      772256 :       clobbered_regno = REGNO (XEXP (XVECEXP (pat, 0, 1), 0));
    1074                 :             :     }
    1075                 :             : 
    1076                 :     3540393 :   do
    1077                 :             :     {
    1078                 :     3540393 :       use = reload_combine_closest_single_use (regno, from_ruid);
    1079                 :             : 
    1080                 :     3540393 :       if (use)
    1081                 :             :         /* Start the search for the next use from here.  */
    1082                 :      845849 :         from_ruid = use->ruid;
    1083                 :             : 
    1084                 :      845849 :       if (use && GET_MODE (*use->usep) == Pmode)
    1085                 :             :         {
    1086                 :      841158 :           bool delete_add = false;
    1087                 :      841158 :           rtx_insn *use_insn = use->insn;
    1088                 :      841158 :           int use_ruid = use->ruid;
    1089                 :             : 
    1090                 :             :           /* Avoid moving the add insn past a jump.  */
    1091                 :      841158 :           if (must_move_add && use_ruid <= last_jump_ruid)
    1092                 :             :             break;
    1093                 :             : 
    1094                 :             :           /* If the add clobbers another hard reg in parallel, don't move
    1095                 :             :              it past a real set of this hard reg.  */
    1096                 :      840878 :           if (must_move_add && clobbered_regno >= 0
    1097                 :      111616 :               && reg_state[clobbered_regno].real_store_ruid >= use_ruid)
    1098                 :             :             break;
    1099                 :             : 
    1100                 :      818615 :           gcc_assert (reg_state[regno].store_ruid <= use_ruid);
    1101                 :             :           /* Avoid moving a use of ADDREG past a point where it is stored.  */
    1102                 :      818615 :           if (reg_state[REGNO (addreg)].store_ruid > use_ruid)
    1103                 :             :             break;
    1104                 :             : 
    1105                 :             :           /* We also must not move the addition past an insn that sets
    1106                 :             :              the same register, unless we can combine two add insns.  */
    1107                 :      742260 :           if (must_move_add && reg_state[regno].store_ruid == use_ruid)
    1108                 :             :             {
    1109                 :       28810 :               if (use->containing_mem == NULL_RTX)
    1110                 :             :                 delete_add = true;
    1111                 :             :               else
    1112                 :             :                 break;
    1113                 :             :             }
    1114                 :             : 
    1115                 :      742243 :           if (try_replace_in_use (use, reg, src))
    1116                 :             :             {
    1117                 :        5837 :               reload_combine_purge_insn_uses (use_insn);
    1118                 :        5837 :               reload_combine_note_use (&PATTERN (use_insn), use_insn,
    1119                 :             :                                        use_ruid, NULL_RTX);
    1120                 :             : 
    1121                 :        5837 :               if (delete_add)
    1122                 :             :                 {
    1123                 :          55 :                   fixup_debug_insns (reg, src, insn, use_insn);
    1124                 :          55 :                   delete_insn (insn);
    1125                 :          55 :                   return true;
    1126                 :             :                 }
    1127                 :        5782 :               if (must_move_add)
    1128                 :             :                 {
    1129                 :        1120 :                   add_moved_after_insn = use_insn;
    1130                 :        1120 :                   add_moved_after_ruid = use_ruid;
    1131                 :             :                 }
    1132                 :        5782 :               continue;
    1133                 :             :             }
    1134                 :             :         }
    1135                 :             :       /* If we get here, we couldn't handle this use.  */
    1136                 :     3435641 :       if (must_move_add)
    1137                 :             :         break;
    1138                 :             :     }
    1139                 :     2665825 :   while (use);
    1140                 :             : 
    1141                 :     2893658 :   if (!must_move_add || add_moved_after_insn == NULL_RTX)
    1142                 :             :     /* Process the add normally.  */
    1143                 :             :     return false;
    1144                 :             : 
    1145                 :         659 :   fixup_debug_insns (reg, src, insn, add_moved_after_insn);
    1146                 :             : 
    1147                 :         659 :   reorder_insns (insn, insn, add_moved_after_insn);
    1148                 :         659 :   reload_combine_purge_reg_uses_after_ruid (regno, add_moved_after_ruid);
    1149                 :         659 :   reload_combine_split_ruids (add_moved_after_ruid - 1);
    1150                 :         659 :   reload_combine_note_use (&PATTERN (insn), insn,
    1151                 :             :                            add_moved_after_ruid, NULL_RTX);
    1152                 :         659 :   reg_state[regno].store_ruid = add_moved_after_ruid;
    1153                 :             : 
    1154                 :         659 :   return true;
    1155                 :             : }
    1156                 :             : 
    1157                 :             : /* Called by reload_combine when scanning INSN.  Try to detect a pattern we
    1158                 :             :    can handle and improve.  Return true if no further processing is needed on
    1159                 :             :    INSN; false if it wasn't recognized and should be handled normally.  */
    1160                 :             : 
    1161                 :             : static bool
    1162                 :    58239796 : reload_combine_recognize_pattern (rtx_insn *insn)
    1163                 :             : {
    1164                 :    58239796 :   rtx set, reg, src;
    1165                 :             : 
    1166                 :    58239796 :   set = single_set (insn);
    1167                 :    58239796 :   if (set == NULL_RTX)
    1168                 :             :     return false;
    1169                 :             : 
    1170                 :    54235295 :   reg = SET_DEST (set);
    1171                 :    54235295 :   src = SET_SRC (set);
    1172                 :    54235295 :   if (!REG_P (reg) || REG_NREGS (reg) != 1)
    1173                 :             :     return false;
    1174                 :             : 
    1175                 :    36652133 :   unsigned int regno = REGNO (reg);
    1176                 :    36652133 :   machine_mode mode = GET_MODE (reg);
    1177                 :             : 
    1178                 :    36652133 :   if (reg_state[regno].use_index < 0
    1179                 :    36652133 :       || reg_state[regno].use_index >= RELOAD_COMBINE_MAX_USES)
    1180                 :             :     return false;
    1181                 :             : 
    1182                 :    23556700 :   for (int i = reg_state[regno].use_index;
    1183                 :    43195278 :        i < RELOAD_COMBINE_MAX_USES; i++)
    1184                 :             :     {
    1185                 :    24296074 :       struct reg_use *use = reg_state[regno].reg_use + i;
    1186                 :    24296074 :       if (GET_MODE (*use->usep) != mode)
    1187                 :             :         return false;
    1188                 :             :       /* Don't try to adjust (use (REGX)).  */
    1189                 :    23560963 :       if (GET_CODE (PATTERN (use->insn)) == USE
    1190                 :    23560963 :           && &XEXP (PATTERN (use->insn), 0) == use->usep)
    1191                 :             :         return false;
    1192                 :             :     }
    1193                 :             : 
    1194                 :             :   /* Look for (set (REGX) (CONST_INT))
    1195                 :             :      (set (REGX) (PLUS (REGX) (REGY)))
    1196                 :             :      ...
    1197                 :             :      ... (MEM (REGX)) ...
    1198                 :             :      and convert it to
    1199                 :             :      (set (REGZ) (CONST_INT))
    1200                 :             :      ...
    1201                 :             :      ... (MEM (PLUS (REGZ) (REGY)))... .
    1202                 :             : 
    1203                 :             :      First, check that we have (set (REGX) (PLUS (REGX) (REGY)))
    1204                 :             :      and that we know all uses of REGX before it dies.
    1205                 :             :      Also, explicitly check that REGX != REGY; our life information
    1206                 :             :      does not yet show whether REGY changes in this insn.  */
    1207                 :             : 
    1208                 :    18899204 :   if (GET_CODE (src) == PLUS
    1209                 :     2277314 :       && reg_state[regno].all_offsets_match
    1210                 :     2035917 :       && last_index_reg != -1
    1211                 :     2035917 :       && REG_P (XEXP (src, 1))
    1212                 :      668156 :       && rtx_equal_p (XEXP (src, 0), reg)
    1213                 :      484362 :       && !rtx_equal_p (XEXP (src, 1), reg)
    1214                 :    19376887 :       && last_label_ruid < reg_state[regno].use_ruid)
    1215                 :             :     {
    1216                 :      449085 :       rtx base = XEXP (src, 1);
    1217                 :      449085 :       rtx_insn *prev = prev_nonnote_nondebug_insn (insn);
    1218                 :      449085 :       rtx prev_set = prev ? single_set (prev) : NULL_RTX;
    1219                 :      449085 :       rtx index_reg = NULL_RTX;
    1220                 :      449085 :       rtx reg_sum = NULL_RTX;
    1221                 :      449085 :       int i;
    1222                 :             : 
    1223                 :             :       /* Now we need to set INDEX_REG to an index register (denoted as
    1224                 :             :          REGZ in the illustration above) and REG_SUM to the expression
    1225                 :             :          register+register that we want to use to substitute uses of REG
    1226                 :             :          (typically in MEMs) with.  First check REG and BASE for being
    1227                 :             :          index registers; we can use them even if they are not dead.  */
    1228                 :      449085 :       if (TEST_HARD_REG_BIT (reg_class_contents[INDEX_REG_CLASS], regno)
    1229                 :      449085 :           || TEST_HARD_REG_BIT (reg_class_contents[INDEX_REG_CLASS],
    1230                 :             :                                 REGNO (base)))
    1231                 :             :         {
    1232                 :             :           index_reg = reg;
    1233                 :             :           reg_sum = src;
    1234                 :             :         }
    1235                 :             :       else
    1236                 :             :         {
    1237                 :             :           /* Otherwise, look for a free index register.  Since we have
    1238                 :             :              checked above that neither REG nor BASE are index registers,
    1239                 :             :              if we find anything at all, it will be different from these
    1240                 :             :              two registers.  */
    1241                 :     8638434 :           for (i = first_index_reg; i <= last_index_reg; i++)
    1242                 :             :             {
    1243                 :     8551584 :               if (TEST_HARD_REG_BIT (reg_class_contents[INDEX_REG_CLASS], i)
    1244                 :     2987311 :                   && reg_state[i].use_index == RELOAD_COMBINE_MAX_USES
    1245                 :     1550221 :                   && reg_state[i].store_ruid <= reg_state[regno].use_ruid
    1246                 :     1535206 :                   && (crtl->abi->clobbers_full_reg_p (i)
    1247                 :      328463 :                       || df_regs_ever_live_p (i))
    1248                 :     1286870 :                   && (!frame_pointer_needed || i != HARD_FRAME_POINTER_REGNUM)
    1249                 :     1285893 :                   && !fixed_regs[i] && !global_regs[i]
    1250                 :      526357 :                   && hard_regno_nregs (i, GET_MODE (reg)) == 1
    1251                 :     8685527 :                   && targetm.hard_regno_scratch_ok (i))
    1252                 :             :                 {
    1253                 :      133943 :                   index_reg = gen_rtx_REG (GET_MODE (reg), i);
    1254                 :      133943 :                   reg_sum = gen_rtx_PLUS (GET_MODE (reg), index_reg, base);
    1255                 :      133943 :                   break;
    1256                 :             :                 }
    1257                 :             :             }
    1258                 :             :         }
    1259                 :             : 
    1260                 :             :       /* Check that PREV_SET is indeed (set (REGX) (CONST_INT)) and that
    1261                 :             :          (REGY), i.e. BASE, is not clobbered before the last use we'll
    1262                 :             :          create.  */
    1263                 :      449085 :       if (reg_sum
    1264                 :      449085 :           && prev_set
    1265                 :      356653 :           && CONST_INT_P (SET_SRC (prev_set))
    1266                 :        7087 :           && rtx_equal_p (SET_DEST (prev_set), reg)
    1267                 :      449085 :           && (reg_state[REGNO (base)].store_ruid
    1268                 :        2324 :               <= reg_state[regno].use_ruid))
    1269                 :             :         {
    1270                 :             :           /* Change destination register and, if necessary, the constant
    1271                 :             :              value in PREV, the constant loading instruction.  */
    1272                 :        2252 :           validate_change (prev, &SET_DEST (prev_set), index_reg, 1);
    1273                 :        2252 :           if (reg_state[regno].offset != const0_rtx)
    1274                 :             :             {
    1275                 :           0 :               HOST_WIDE_INT c
    1276                 :           0 :                 = trunc_int_for_mode (UINTVAL (SET_SRC (prev_set))
    1277                 :           0 :                                       + UINTVAL (reg_state[regno].offset),
    1278                 :           0 :                                       GET_MODE (index_reg));
    1279                 :           0 :               validate_change (prev, &SET_SRC (prev_set), GEN_INT (c), 1);
    1280                 :             :             }
    1281                 :             : 
    1282                 :             :           /* Now for every use of REG that we have recorded, replace REG
    1283                 :             :              with REG_SUM.  */
    1284                 :        4550 :           for (i = reg_state[regno].use_index;
    1285                 :        4550 :                i < RELOAD_COMBINE_MAX_USES; i++)
    1286                 :        2298 :             validate_unshare_change (reg_state[regno].reg_use[i].insn,
    1287                 :             :                                      reg_state[regno].reg_use[i].usep,
    1288                 :             :                                      /* Each change must have its own
    1289                 :             :                                         replacement.  */
    1290                 :             :                                      reg_sum, 1);
    1291                 :             : 
    1292                 :        2252 :           if (apply_change_group ())
    1293                 :             :             {
    1294                 :         112 :               struct reg_use *lowest_ruid = NULL;
    1295                 :             : 
    1296                 :             :               /* For every new use of REG_SUM, we have to record the use
    1297                 :             :                  of BASE therein, i.e. operand 1.  */
    1298                 :         244 :               for (i = reg_state[regno].use_index;
    1299                 :         244 :                    i < RELOAD_COMBINE_MAX_USES; i++)
    1300                 :             :                 {
    1301                 :         132 :                   struct reg_use *use = reg_state[regno].reg_use + i;
    1302                 :         132 :                   reload_combine_note_use (&XEXP (*use->usep, 1), use->insn,
    1303                 :             :                                            use->ruid, use->containing_mem);
    1304                 :         132 :                   if (lowest_ruid == NULL || use->ruid < lowest_ruid->ruid)
    1305                 :         132 :                     lowest_ruid = use;
    1306                 :             :                 }
    1307                 :             : 
    1308                 :         112 :               fixup_debug_insns (reg, reg_sum, insn, lowest_ruid->insn);
    1309                 :             : 
    1310                 :             :               /* Delete the reg-reg addition.  */
    1311                 :         112 :               delete_insn (insn);
    1312                 :             : 
    1313                 :         112 :               if (reg_state[regno].offset != const0_rtx)
    1314                 :             :                 /* Previous REG_EQUIV / REG_EQUAL notes for PREV
    1315                 :             :                    are now invalid.  */
    1316                 :           0 :                 remove_reg_equal_equiv_notes (prev);
    1317                 :             : 
    1318                 :         112 :               reg_state[regno].use_index = RELOAD_COMBINE_MAX_USES;
    1319                 :         112 :               return true;
    1320                 :             :             }
    1321                 :             :         }
    1322                 :             :     }
    1323                 :             :   return false;
    1324                 :             : }
    1325                 :             : 
    1326                 :             : static void
    1327                 :     1016998 : reload_combine (void)
    1328                 :             : {
    1329                 :     1016998 :   rtx_insn *insn, *prev;
    1330                 :     1016998 :   basic_block bb;
    1331                 :     1016998 :   unsigned int r;
    1332                 :     1016998 :   int min_labelno, n_labels;
    1333                 :     1016998 :   HARD_REG_SET ever_live_at_start, *label_live;
    1334                 :             : 
    1335                 :             :   /* To avoid wasting too much time later searching for an index register,
    1336                 :             :      determine the minimum and maximum index register numbers.  */
    1337                 :     1016998 :   if (INDEX_REG_CLASS == NO_REGS)
    1338                 :             :     last_index_reg = -1;
    1339                 :     1016998 :   else if (first_index_reg == -1 && last_index_reg == 0)
    1340                 :             :     {
    1341                 :    12955086 :       for (r = 0; r < FIRST_PSEUDO_REGISTER; r++)
    1342                 :    12815784 :         if (TEST_HARD_REG_BIT (reg_class_contents[INDEX_REG_CLASS], r))
    1343                 :             :           {
    1344                 :     4318362 :             if (first_index_reg == -1)
    1345                 :      139302 :               first_index_reg = r;
    1346                 :             : 
    1347                 :     4318362 :             last_index_reg = r;
    1348                 :             :           }
    1349                 :             : 
    1350                 :             :       /* If no index register is available, we can quit now.  Set LAST_INDEX_REG
    1351                 :             :          to -1 so we'll know to quit early the next time we get here.  */
    1352                 :      139302 :       if (first_index_reg == -1)
    1353                 :             :         {
    1354                 :           0 :           last_index_reg = -1;
    1355                 :           0 :           return;
    1356                 :             :         }
    1357                 :             :     }
    1358                 :             : 
    1359                 :             :   /* Set up LABEL_LIVE and EVER_LIVE_AT_START.  The register lifetime
    1360                 :             :      information is a bit fuzzy immediately after reload, but it's
    1361                 :             :      still good enough to determine which registers are live at a jump
    1362                 :             :      destination.  */
    1363                 :     1016998 :   min_labelno = get_first_label_num ();
    1364                 :     1016998 :   n_labels = max_label_num () - min_labelno;
    1365                 :     1016998 :   label_live = XNEWVEC (HARD_REG_SET, n_labels);
    1366                 :     1016998 :   CLEAR_HARD_REG_SET (ever_live_at_start);
    1367                 :             : 
    1368                 :    11926172 :   FOR_EACH_BB_REVERSE_FN (bb, cfun)
    1369                 :             :     {
    1370                 :    10909174 :       insn = BB_HEAD (bb);
    1371                 :    10909174 :       if (LABEL_P (insn))
    1372                 :             :         {
    1373                 :     5073215 :           HARD_REG_SET live;
    1374                 :     5073215 :           bitmap live_in = df_get_live_in (bb);
    1375                 :             : 
    1376                 :    10146430 :           REG_SET_TO_HARD_REG_SET (live, live_in);
    1377                 :     5073215 :           compute_use_by_pseudos (&live, live_in);
    1378                 :     5073215 :           LABEL_LIVE (insn) = live;
    1379                 :    10146430 :           ever_live_at_start |= live;
    1380                 :             :         }
    1381                 :             :     }
    1382                 :             : 
    1383                 :             :   /* Initialize last_label_ruid, reload_combine_ruid and reg_state.  */
    1384                 :     1016998 :   last_label_ruid = last_jump_ruid = reload_combine_ruid = 0;
    1385                 :    94580814 :   for (r = 0; r < FIRST_PSEUDO_REGISTER; r++)
    1386                 :             :     {
    1387                 :    93563816 :       reg_state[r].store_ruid = 0;
    1388                 :    93563816 :       reg_state[r].real_store_ruid = 0;
    1389                 :    93563816 :       if (fixed_regs[r])
    1390                 :    46306551 :         reg_state[r].use_index = -1;
    1391                 :             :       else
    1392                 :    47257265 :         reg_state[r].use_index = RELOAD_COMBINE_MAX_USES;
    1393                 :             :     }
    1394                 :             : 
    1395                 :   131440983 :   for (insn = get_last_insn (); insn; insn = prev)
    1396                 :             :     {
    1397                 :   130423985 :       bool control_flow_insn;
    1398                 :   130423985 :       rtx note;
    1399                 :             : 
    1400                 :   130423985 :       prev = PREV_INSN (insn);
    1401                 :             : 
    1402                 :             :       /* We cannot do our optimization across labels.  Invalidating all the use
    1403                 :             :          information we have would be costly, so we just note where the label
    1404                 :             :          is and then later disable any optimization that would cross it.  */
    1405                 :   130423985 :       if (LABEL_P (insn))
    1406                 :     5080387 :         last_label_ruid = reload_combine_ruid;
    1407                 :   125343598 :       else if (BARRIER_P (insn))
    1408                 :             :         {
    1409                 :             :           /* Crossing a barrier resets all the use information.  */
    1410                 :   277297356 :           for (r = 0; r < FIRST_PSEUDO_REGISTER; r++)
    1411                 :   274315664 :             if (! fixed_regs[r])
    1412                 :   133267233 :               reg_state[r].use_index = RELOAD_COMBINE_MAX_USES;
    1413                 :             :         }
    1414                 :   122361906 :       else if (INSN_P (insn) && volatile_insn_p (PATTERN (insn)))
    1415                 :             :         /* Optimizations across insns being marked as volatile must be
    1416                 :             :            prevented.  All the usage information is invalidated
    1417                 :             :            here.  */
    1418                 :    42075711 :         for (r = 0; r < FIRST_PSEUDO_REGISTER; r++)
    1419                 :    41623284 :           if (! fixed_regs[r]
    1420                 :    19588215 :               && reg_state[r].use_index != RELOAD_COMBINE_MAX_USES)
    1421                 :      664958 :             reg_state[r].use_index = -1;
    1422                 :             : 
    1423                 :   130423985 :       if (! NONDEBUG_INSN_P (insn))
    1424                 :    72183475 :         continue;
    1425                 :             : 
    1426                 :    58240510 :       reload_combine_ruid++;
    1427                 :             : 
    1428                 :    58240510 :       control_flow_insn = control_flow_insn_p (insn);
    1429                 :    58240510 :       if (control_flow_insn)
    1430                 :     8357386 :         last_jump_ruid = reload_combine_ruid;
    1431                 :             : 
    1432                 :    58240510 :       if (reload_combine_recognize_const_pattern (insn)
    1433                 :    58240510 :           || reload_combine_recognize_pattern (insn))
    1434                 :         826 :         continue;
    1435                 :             : 
    1436                 :    58239684 :       note_stores (insn, reload_combine_note_store, NULL);
    1437                 :             : 
    1438                 :    58239684 :       if (CALL_P (insn))
    1439                 :             :         {
    1440                 :     4696286 :           rtx link;
    1441                 :     4696286 :           HARD_REG_SET used_regs = insn_callee_abi (insn).full_reg_clobbers ();
    1442                 :             : 
    1443                 :   436754598 :           for (r = 0; r < FIRST_PSEUDO_REGISTER; r++)
    1444                 :   432058312 :             if (TEST_HARD_REG_BIT (used_regs, r))
    1445                 :             :               {
    1446                 :   383009621 :                 reg_state[r].use_index = RELOAD_COMBINE_MAX_USES;
    1447                 :   383009621 :                 reg_state[r].store_ruid = reload_combine_ruid;
    1448                 :             :               }
    1449                 :             : 
    1450                 :    13836291 :           for (link = CALL_INSN_FUNCTION_USAGE (insn); link;
    1451                 :     9140005 :                link = XEXP (link, 1))
    1452                 :             :             {
    1453                 :     9140005 :               rtx setuse = XEXP (link, 0);
    1454                 :     9140005 :               rtx usage_rtx = XEXP (setuse, 0);
    1455                 :             : 
    1456                 :     9140005 :               if (GET_CODE (setuse) == USE && REG_P (usage_rtx))
    1457                 :             :                 {
    1458                 :     8610538 :                   unsigned int end_regno = END_REGNO (usage_rtx);
    1459                 :    17276086 :                   for (unsigned int i = REGNO (usage_rtx); i < end_regno; ++i)
    1460                 :     8665548 :                     reg_state[i].use_index = -1;
    1461                 :             :                  }
    1462                 :             :              }
    1463                 :             :         }
    1464                 :             : 
    1465                 :    58239684 :       if (control_flow_insn && !ANY_RETURN_P (PATTERN (insn)))
    1466                 :             :         {
    1467                 :             :           /* Non-spill registers might be used at the call destination in
    1468                 :             :              some unknown fashion, so we have to mark the unknown use.  */
    1469                 :     8357386 :           HARD_REG_SET *live;
    1470                 :             : 
    1471                 :     9724171 :           if ((condjump_p (insn) || condjump_in_parallel_p (insn))
    1472                 :     8357469 :               && JUMP_LABEL (insn))
    1473                 :             :             {
    1474                 :     6990684 :               if (ANY_RETURN_P (JUMP_LABEL (insn)))
    1475                 :             :                 live = NULL;
    1476                 :             :               else
    1477                 :     6990684 :                 live = &LABEL_LIVE (JUMP_LABEL (insn));
    1478                 :             :             }
    1479                 :             :           else
    1480                 :             :             live = &ever_live_at_start;
    1481                 :             : 
    1482                 :     8357386 :           if (live)
    1483                 :   777236898 :             for (r = 0; r < FIRST_PSEUDO_REGISTER; r++)
    1484                 :   768879512 :               if (TEST_HARD_REG_BIT (*live, r))
    1485                 :    41323544 :                 reg_state[r].use_index = -1;
    1486                 :             :         }
    1487                 :             : 
    1488                 :    58239684 :       reload_combine_note_use (&PATTERN (insn), insn, reload_combine_ruid,
    1489                 :             :                                NULL_RTX);
    1490                 :             : 
    1491                 :    81162486 :       for (note = REG_NOTES (insn); note; note = XEXP (note, 1))
    1492                 :             :         {
    1493                 :    22922802 :           if (REG_NOTE_KIND (note) == REG_INC && REG_P (XEXP (note, 0)))
    1494                 :             :             {
    1495                 :           0 :               int regno = REGNO (XEXP (note, 0));
    1496                 :           0 :               reg_state[regno].store_ruid = reload_combine_ruid;
    1497                 :           0 :               reg_state[regno].real_store_ruid = reload_combine_ruid;
    1498                 :           0 :               reg_state[regno].use_index = -1;
    1499                 :             :             }
    1500                 :             :         }
    1501                 :             :     }
    1502                 :             : 
    1503                 :     1016998 :   free (label_live);
    1504                 :             : }
    1505                 :             : 
    1506                 :             : /* Check if DST is a register or a subreg of a register; if it is,
    1507                 :             :    update store_ruid, real_store_ruid and use_index in the reg_state
    1508                 :             :    structure accordingly.  Called via note_stores from reload_combine.  */
    1509                 :             : 
    1510                 :             : static void
    1511                 :    62751754 : reload_combine_note_store (rtx dst, const_rtx set, void *data ATTRIBUTE_UNUSED)
    1512                 :             : {
    1513                 :    62751754 :   int regno = 0;
    1514                 :    62751754 :   int i;
    1515                 :    62751754 :   machine_mode mode = GET_MODE (dst);
    1516                 :             : 
    1517                 :    62751754 :   if (GET_CODE (dst) == SUBREG)
    1518                 :             :     {
    1519                 :        7090 :       regno = subreg_regno_offset (REGNO (SUBREG_REG (dst)),
    1520                 :        3545 :                                    GET_MODE (SUBREG_REG (dst)),
    1521                 :        3545 :                                    SUBREG_BYTE (dst),
    1522                 :             :                                    GET_MODE (dst));
    1523                 :        3545 :       dst = SUBREG_REG (dst);
    1524                 :             :     }
    1525                 :             : 
    1526                 :             :   /* Some targets do argument pushes without adding REG_INC notes.  */
    1527                 :             : 
    1528                 :    62751754 :   if (MEM_P (dst))
    1529                 :             :     {
    1530                 :    10094081 :       dst = XEXP (dst, 0);
    1531                 :    10094081 :       if (GET_CODE (dst) == PRE_INC || GET_CODE (dst) == POST_INC
    1532                 :    10094081 :           || GET_CODE (dst) == PRE_DEC || GET_CODE (dst) == POST_DEC
    1533                 :     8491580 :           || GET_CODE (dst) == PRE_MODIFY || GET_CODE (dst) == POST_MODIFY)
    1534                 :             :         {
    1535                 :     1685091 :           unsigned int end_regno = END_REGNO (XEXP (dst, 0));
    1536                 :     3370182 :           for (unsigned int i = REGNO (XEXP (dst, 0)); i < end_regno; ++i)
    1537                 :             :             {
    1538                 :             :               /* We could probably do better, but for now mark the register
    1539                 :             :                  as used in an unknown fashion and set/clobbered at this
    1540                 :             :                  insn.  */
    1541                 :     1685091 :               reg_state[i].use_index = -1;
    1542                 :     1685091 :               reg_state[i].store_ruid = reload_combine_ruid;
    1543                 :     1685091 :               reg_state[i].real_store_ruid = reload_combine_ruid;
    1544                 :             :             }
    1545                 :             :         }
    1546                 :             :       else
    1547                 :             :         return;
    1548                 :             :     }
    1549                 :             : 
    1550                 :    54342764 :   if (!REG_P (dst))
    1551                 :             :     return;
    1552                 :    45654183 :   regno += REGNO (dst);
    1553                 :             : 
    1554                 :             :   /* note_stores might have stripped a STRICT_LOW_PART, so we have to be
    1555                 :             :      careful with registers / register parts that are not full words.
    1556                 :             :      Similarly for ZERO_EXTRACT.  */
    1557                 :    45654183 :   if (GET_CODE (SET_DEST (set)) == ZERO_EXTRACT
    1558                 :    45652753 :       || GET_CODE (SET_DEST (set)) == STRICT_LOW_PART)
    1559                 :             :     {
    1560                 :       10488 :       for (i = end_hard_regno (mode, regno) - 1; i >= regno; i--)
    1561                 :             :         {
    1562                 :        5244 :           reg_state[i].use_index = -1;
    1563                 :        5244 :           reg_state[i].store_ruid = reload_combine_ruid;
    1564                 :        5244 :           reg_state[i].real_store_ruid = reload_combine_ruid;
    1565                 :             :         }
    1566                 :             :     }
    1567                 :             :   else
    1568                 :             :     {
    1569                 :    91915451 :       for (i = end_hard_regno (mode, regno) - 1; i >= regno; i--)
    1570                 :             :         {
    1571                 :    46266512 :           reg_state[i].store_ruid = reload_combine_ruid;
    1572                 :    46266512 :           if (GET_CODE (set) == SET)
    1573                 :    38681273 :             reg_state[i].real_store_ruid = reload_combine_ruid;
    1574                 :    46266512 :           reg_state[i].use_index = RELOAD_COMBINE_MAX_USES;
    1575                 :             :         }
    1576                 :             :     }
    1577                 :             : }
    1578                 :             : 
    1579                 :             : /* XP points to a piece of rtl that has to be checked for any uses of
    1580                 :             :    registers.
    1581                 :             :    *XP is the pattern of INSN, or a part of it.
    1582                 :             :    Called from reload_combine, and recursively by itself.  */
    1583                 :             : static void
    1584                 :   205031611 : reload_combine_note_use (rtx *xp, rtx_insn *insn, int ruid, rtx containing_mem)
    1585                 :             : {
    1586                 :   243084188 :   rtx x = *xp;
    1587                 :   243084188 :   enum rtx_code code = x->code;
    1588                 :   243084188 :   const char *fmt;
    1589                 :   243084188 :   int i, j;
    1590                 :   243084188 :   rtx offset = const0_rtx; /* For the REG case below.  */
    1591                 :             : 
    1592                 :   243084188 :   switch (code)
    1593                 :             :     {
    1594                 :    55119165 :     case SET:
    1595                 :    55119165 :       if (REG_P (SET_DEST (x)))
    1596                 :             :         {
    1597                 :    38052577 :           reload_combine_note_use (&SET_SRC (x), insn, ruid, NULL_RTX);
    1598                 :    38052577 :           return;
    1599                 :             :         }
    1600                 :             :       break;
    1601                 :             : 
    1602                 :      661259 :     case USE:
    1603                 :             :       /* If this is the USE of a return value, we can't change it.  */
    1604                 :      661259 :       if (REG_P (XEXP (x, 0)) && REG_FUNCTION_VALUE_P (XEXP (x, 0)))
    1605                 :             :         {
    1606                 :             :           /* Mark the return register as used in an unknown fashion.  */
    1607                 :      548104 :           rtx reg = XEXP (x, 0);
    1608                 :      548104 :           unsigned int end_regno = END_REGNO (reg);
    1609                 :     1124357 :           for (unsigned int regno = REGNO (reg); regno < end_regno; ++regno)
    1610                 :      576253 :             reg_state[regno].use_index = -1;
    1611                 :             :           return;
    1612                 :             :         }
    1613                 :             :       break;
    1614                 :             : 
    1615                 :     7212044 :     case CLOBBER:
    1616                 :     7212044 :       if (REG_P (SET_DEST (x)))
    1617                 :             :         {
    1618                 :             :           /* No spurious CLOBBERs of pseudo registers may remain.  */
    1619                 :     7161652 :           gcc_assert (REGNO (SET_DEST (x)) < FIRST_PSEUDO_REGISTER);
    1620                 :             :           return;
    1621                 :             :         }
    1622                 :             :       break;
    1623                 :             : 
    1624                 :    21780006 :     case PLUS:
    1625                 :             :       /* We are interested in (plus (reg) (const_int)) .  */
    1626                 :    21780006 :       if (!REG_P (XEXP (x, 0))
    1627                 :    19671464 :           || !CONST_INT_P (XEXP (x, 1)))
    1628                 :             :         break;
    1629                 :             :       offset = XEXP (x, 1);
    1630                 :             :       x = XEXP (x, 0);
    1631                 :             :       /* Fall through.  */
    1632                 :    56478657 :     case REG:
    1633                 :    56478657 :       {
    1634                 :    56478657 :         int regno = REGNO (x);
    1635                 :    56478657 :         int use_index;
    1636                 :    56478657 :         int nregs;
    1637                 :             : 
    1638                 :             :         /* No spurious USEs of pseudo registers may remain.  */
    1639                 :    56478657 :         gcc_assert (regno < FIRST_PSEUDO_REGISTER);
    1640                 :             : 
    1641                 :    56478657 :         nregs = REG_NREGS (x);
    1642                 :             : 
    1643                 :             :         /* We can't substitute into multi-hard-reg uses.  */
    1644                 :    56478657 :         if (nregs > 1)
    1645                 :             :           {
    1646                 :     1197519 :             while (--nregs >= 0)
    1647                 :      798346 :               reg_state[regno + nregs].use_index = -1;
    1648                 :             :             return;
    1649                 :             :           }
    1650                 :             : 
    1651                 :             :         /* We may be called to update uses in previously seen insns.
    1652                 :             :            Don't add uses beyond the last store we saw.  */
    1653                 :    56079484 :         if (ruid < reg_state[regno].store_ruid)
    1654                 :             :           return;
    1655                 :             : 
    1656                 :             :         /* If this register is already used in some unknown fashion, we
    1657                 :             :            can't do anything.
    1658                 :             :            If we decrement the index from zero to -1, we can't store more
    1659                 :             :            uses, so this register becomes used in an unknown fashion.  */
    1660                 :    56077459 :         use_index = --reg_state[regno].use_index;
    1661                 :    56077459 :         if (use_index < 0)
    1662                 :             :           return;
    1663                 :             : 
    1664                 :    34169920 :         if (use_index == RELOAD_COMBINE_MAX_USES - 1)
    1665                 :             :           {
    1666                 :             :             /* This is the first use of this register we have seen since we
    1667                 :             :                marked it as dead.  */
    1668                 :    26032532 :             reg_state[regno].offset = offset;
    1669                 :    26032532 :             reg_state[regno].all_offsets_match = true;
    1670                 :    26032532 :             reg_state[regno].use_ruid = ruid;
    1671                 :             :           }
    1672                 :             :         else
    1673                 :             :           {
    1674                 :     8137388 :             if (reg_state[regno].use_ruid > ruid)
    1675                 :         753 :               reg_state[regno].use_ruid = ruid;
    1676                 :             : 
    1677                 :     8137388 :             if (! rtx_equal_p (offset, reg_state[regno].offset))
    1678                 :     3776062 :               reg_state[regno].all_offsets_match = false;
    1679                 :             :           }
    1680                 :             : 
    1681                 :    34169920 :         reg_state[regno].reg_use[use_index].insn = insn;
    1682                 :    34169920 :         reg_state[regno].reg_use[use_index].ruid = ruid;
    1683                 :    34169920 :         reg_state[regno].reg_use[use_index].containing_mem = containing_mem;
    1684                 :    34169920 :         reg_state[regno].reg_use[use_index].usep = xp;
    1685                 :    34169920 :         return;
    1686                 :             :       }
    1687                 :             : 
    1688                 :             :     case MEM:
    1689                 :   140843198 :       containing_mem = x;
    1690                 :             :       break;
    1691                 :             : 
    1692                 :             :     default:
    1693                 :             :       break;
    1694                 :             :     }
    1695                 :             : 
    1696                 :             :   /* Recursively process the components of X.  */
    1697                 :   140843198 :   fmt = GET_RTX_FORMAT (code);
    1698                 :   359827325 :   for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
    1699                 :             :     {
    1700                 :   218984127 :       if (fmt[i] == 'e')
    1701                 :   127535039 :         reload_combine_note_use (&XEXP (x, i), insn, ruid, containing_mem);
    1702                 :    91449088 :       else if (fmt[i] == 'E')
    1703                 :             :         {
    1704                 :    28695053 :           for (j = XVECLEN (x, i) - 1; j >= 0; j--)
    1705                 :    19250260 :             reload_combine_note_use (&XVECEXP (x, i, j), insn, ruid,
    1706                 :             :                                      containing_mem);
    1707                 :             :         }
    1708                 :             :     }
    1709                 :             : }
    1710                 :             : 
    1711                 :             : /* See if we can reduce the cost of a constant by replacing a move
    1712                 :             :    with an add.  We track situations in which a register is set to a
    1713                 :             :    constant or to a register plus a constant.  */
    1714                 :             : /* We cannot do our optimization across labels.  Invalidating all the
    1715                 :             :    information about register contents we have would be costly, so we
    1716                 :             :    use move2add_last_label_luid to note where the label is and then
    1717                 :             :    later disable any optimization that would cross it.
    1718                 :             :    reg_offset[n] / reg_base_reg[n] / reg_symbol_ref[n] / reg_mode[n]
    1719                 :             :    are only valid if reg_set_luid[n] is greater than
    1720                 :             :    move2add_last_label_luid.
    1721                 :             :    For a set that established a new (potential) base register with
    1722                 :             :    non-constant value, we use move2add_luid from the place where the
    1723                 :             :    setting insn is encountered; registers based off that base then
    1724                 :             :    get the same reg_set_luid.  Constants all get
    1725                 :             :    move2add_last_label_luid + 1 as their reg_set_luid.  */
    1726                 :             : static int reg_set_luid[FIRST_PSEUDO_REGISTER];
    1727                 :             : 
    1728                 :             : /* If reg_base_reg[n] is negative, register n has been set to
    1729                 :             :    reg_offset[n] or reg_symbol_ref[n] + reg_offset[n] in mode reg_mode[n].
    1730                 :             :    If reg_base_reg[n] is non-negative, register n has been set to the
    1731                 :             :    sum of reg_offset[n] and the value of register reg_base_reg[n]
    1732                 :             :    before reg_set_luid[n], calculated in mode reg_mode[n] .
    1733                 :             :    For multi-hard-register registers, all but the first one are
    1734                 :             :    recorded as BLKmode in reg_mode.  Setting reg_mode to VOIDmode
    1735                 :             :    marks it as invalid.  */
    1736                 :             : static HOST_WIDE_INT reg_offset[FIRST_PSEUDO_REGISTER];
    1737                 :             : static int reg_base_reg[FIRST_PSEUDO_REGISTER];
    1738                 :             : static rtx reg_symbol_ref[FIRST_PSEUDO_REGISTER];
    1739                 :             : static machine_mode reg_mode[FIRST_PSEUDO_REGISTER];
    1740                 :             : 
    1741                 :             : /* move2add_luid is linearly increased while scanning the instructions
    1742                 :             :    from first to last.  It is used to set reg_set_luid in
    1743                 :             :    reload_cse_move2add and move2add_note_store.  */
    1744                 :             : static int move2add_luid;
    1745                 :             : 
    1746                 :             : /* move2add_last_label_luid is set whenever a label is found.  Labels
    1747                 :             :    invalidate all previously collected reg_offset data.  */
    1748                 :             : static int move2add_last_label_luid;
    1749                 :             : 
    1750                 :             : /* ??? We don't know how zero / sign extension is handled, hence we
    1751                 :             :    can't go from a narrower to a wider mode.  */
    1752                 :             : #define MODES_OK_FOR_MOVE2ADD(OUTMODE, INMODE) \
    1753                 :             :   (GET_MODE_SIZE (OUTMODE) == GET_MODE_SIZE (INMODE) \
    1754                 :             :    || (GET_MODE_SIZE (OUTMODE) <= GET_MODE_SIZE (INMODE) \
    1755                 :             :        && TRULY_NOOP_TRUNCATION_MODES_P (OUTMODE, INMODE)))
    1756                 :             : 
    1757                 :             : /* Record that REG is being set to a value with the mode of REG.  */
    1758                 :             : 
    1759                 :             : static void
    1760                 :    50980070 : move2add_record_mode (rtx reg)
    1761                 :             : {
    1762                 :    50980070 :   int regno, nregs;
    1763                 :    50980070 :   machine_mode mode = GET_MODE (reg);
    1764                 :             : 
    1765                 :    50980070 :   if (GET_CODE (reg) == SUBREG)
    1766                 :             :     {
    1767                 :        3519 :       regno = subreg_regno (reg);
    1768                 :        3519 :       nregs = subreg_nregs (reg);
    1769                 :             :     }
    1770                 :    50976551 :   else if (REG_P (reg))
    1771                 :             :     {
    1772                 :    50976551 :       regno = REGNO (reg);
    1773                 :    50976551 :       nregs = REG_NREGS (reg);
    1774                 :             :     }
    1775                 :             :   else
    1776                 :           0 :     gcc_unreachable ();
    1777                 :    51640935 :   for (int i = nregs - 1; i > 0; i--)
    1778                 :      660865 :     reg_mode[regno + i] = BLKmode;
    1779                 :    50980070 :   reg_mode[regno] = mode;
    1780                 :    50980070 : }
    1781                 :             : 
    1782                 :             : /* Record that REG is being set to the sum of SYM and OFF.  */
    1783                 :             : 
    1784                 :             : static void
    1785                 :     2061157 : move2add_record_sym_value (rtx reg, rtx sym, rtx off)
    1786                 :             : {
    1787                 :     2061157 :   int regno = REGNO (reg);
    1788                 :             : 
    1789                 :     2061157 :   move2add_record_mode (reg);
    1790                 :     2061157 :   reg_set_luid[regno] = move2add_luid;
    1791                 :     2061157 :   reg_base_reg[regno] = -1;
    1792                 :     2061157 :   reg_symbol_ref[regno] = sym;
    1793                 :     2061157 :   reg_offset[regno] = INTVAL (off);
    1794                 :     2061157 : }
    1795                 :             : 
    1796                 :             : /* Check if REGNO contains a valid value in MODE.  */
    1797                 :             : 
    1798                 :             : static bool
    1799                 :   207308924 : move2add_valid_value_p (int regno, scalar_int_mode mode)
    1800                 :             : {
    1801                 :   207308924 :   if (reg_set_luid[regno] <= move2add_last_label_luid)
    1802                 :             :     return false;
    1803                 :             : 
    1804                 :    20767901 :   if (mode != reg_mode[regno])
    1805                 :             :     {
    1806                 :    11064919 :       scalar_int_mode old_mode;
    1807                 :    11064919 :       if (!is_a <scalar_int_mode> (reg_mode[regno], &old_mode)
    1808                 :     7095780 :           || !MODES_OK_FOR_MOVE2ADD (mode, old_mode)
    1809                 :      514845 :           || !REG_CAN_CHANGE_MODE_P (regno, old_mode, mode))
    1810                 :    10550074 :         return false;
    1811                 :             :       /* The value loaded into regno in reg_mode[regno] is also valid in
    1812                 :             :          mode after truncation only if (REG:mode regno) is the lowpart of
    1813                 :             :          (REG:reg_mode[regno] regno).  Now, for big endian, the starting
    1814                 :             :          regno of the lowpart might be different.  */
    1815                 :      514845 :       poly_int64 s_off = subreg_lowpart_offset (mode, old_mode);
    1816                 :      514845 :       s_off = subreg_regno_offset (regno, old_mode, s_off, mode);
    1817                 :      514845 :       if (maybe_ne (s_off, 0))
    1818                 :             :         /* We could in principle adjust regno, check reg_mode[regno] to be
    1819                 :             :            BLKmode, and return s_off to the caller (vs. -1 for failure),
    1820                 :             :            but we currently have no callers that could make use of this
    1821                 :             :            information.  */
    1822                 :             :         return false;
    1823                 :             :     }
    1824                 :             : 
    1825                 :    10267576 :   for (int i = end_hard_regno (mode, regno) - 1; i > regno; i--)
    1826                 :       54501 :     if (reg_mode[i] != BLKmode)
    1827                 :             :       return false;
    1828                 :             :   return true;
    1829                 :             : }
    1830                 :             : 
    1831                 :             : /* This function is called with INSN that sets REG (of mode MODE)
    1832                 :             :    to (SYM + OFF), while REG is known to already have value (SYM + offset).
    1833                 :             :    This function tries to change INSN into an add instruction
    1834                 :             :    (set (REG) (plus (REG) (OFF - offset))) using the known value.
    1835                 :             :    It also updates the information about REG's known value.
    1836                 :             :    Return true if we made a change.  */
    1837                 :             : 
    1838                 :             : static bool
    1839                 :      145184 : move2add_use_add2_insn (scalar_int_mode mode, rtx reg, rtx sym, rtx off,
    1840                 :             :                         rtx_insn *insn)
    1841                 :             : {
    1842                 :      145184 :   rtx set = single_set (insn);
    1843                 :      145184 :   rtx src = SET_SRC (set);
    1844                 :      145184 :   int regno = REGNO (reg);
    1845                 :      145184 :   rtx new_src = gen_int_mode (UINTVAL (off) - reg_offset[regno], mode);
    1846                 :      145184 :   bool speed = optimize_bb_for_speed_p (BLOCK_FOR_INSN (insn));
    1847                 :      145184 :   bool changed = false;
    1848                 :             : 
    1849                 :             :   /* (set (reg) (plus (reg) (const_int 0))) is not canonical;
    1850                 :             :      use (set (reg) (reg)) instead.
    1851                 :             :      We don't delete this insn, nor do we convert it into a
    1852                 :             :      note, to avoid losing register notes or the return
    1853                 :             :      value flag.  jump2 already knows how to get rid of
    1854                 :             :      no-op moves.  */
    1855                 :      145184 :   if (new_src == const0_rtx)
    1856                 :             :     {
    1857                 :             :       /* If the constants are different, this is a
    1858                 :             :          truncation, that, if turned into (set (reg)
    1859                 :             :          (reg)), would be discarded.  Maybe we should
    1860                 :             :          try a truncMN pattern?  */
    1861                 :       18056 :       if (INTVAL (off) == reg_offset [regno])
    1862                 :       16497 :         changed = validate_change (insn, &SET_SRC (set), reg, 0);
    1863                 :             :     }
    1864                 :             :   else
    1865                 :             :     {
    1866                 :      127128 :       struct full_rtx_costs oldcst, newcst;
    1867                 :      127128 :       rtx tem = gen_rtx_PLUS (mode, reg, new_src);
    1868                 :             : 
    1869                 :      127128 :       get_full_set_rtx_cost (set, &oldcst);
    1870                 :      127128 :       SET_SRC (set) = tem;
    1871                 :      127128 :       get_full_set_rtx_cost (set, &newcst);
    1872                 :      127128 :       SET_SRC (set) = src;
    1873                 :             : 
    1874                 :      127128 :       if (costs_lt_p (&newcst, &oldcst, speed)
    1875                 :      127128 :           && have_add2_insn (reg, new_src))
    1876                 :        2734 :         changed = validate_change (insn, &SET_SRC (set), tem, 0);
    1877                 :      124394 :       else if (sym == NULL_RTX && mode != BImode)
    1878                 :             :         {
    1879                 :      122736 :           scalar_int_mode narrow_mode;
    1880                 :      408990 :           FOR_EACH_MODE_UNTIL (narrow_mode, mode)
    1881                 :             :             {
    1882                 :      286254 :               if (have_insn_for (STRICT_LOW_PART, narrow_mode)
    1883                 :      286254 :                   && ((reg_offset[regno] & ~GET_MODE_MASK (narrow_mode))
    1884                 :      214289 :                       == (INTVAL (off) & ~GET_MODE_MASK (narrow_mode))))
    1885                 :             :                 {
    1886                 :      101077 :                   rtx narrow_reg = gen_lowpart_common (narrow_mode, reg);
    1887                 :      101077 :                   rtx narrow_src = gen_int_mode (INTVAL (off),
    1888                 :             :                                                  narrow_mode);
    1889                 :      101077 :                   rtx new_set
    1890                 :      101077 :                     = gen_rtx_SET (gen_rtx_STRICT_LOW_PART (VOIDmode,
    1891                 :             :                                                             narrow_reg),
    1892                 :             :                                    narrow_src);
    1893                 :      101077 :                   get_full_set_rtx_cost (new_set, &newcst);
    1894                 :             : 
    1895                 :             :                   /* We perform this replacement only if NEXT is either a
    1896                 :             :                      naked SET, or else its single_set is the first element
    1897                 :             :                      in a PARALLEL.  */
    1898                 :      101077 :                   rtx *setloc = GET_CODE (PATTERN (insn)) == PARALLEL
    1899                 :      101077 :                     ? &XVECEXP (PATTERN (insn), 0, 0) : &PATTERN (insn);
    1900                 :      101077 :                   if (*setloc == set && costs_lt_p (&newcst, &oldcst, speed))
    1901                 :             :                     {
    1902                 :           0 :                       changed = validate_change (insn, setloc, new_set, 0);
    1903                 :           0 :                       if (changed)
    1904                 :             :                         break;
    1905                 :             :                     }
    1906                 :             :                 }
    1907                 :             :             }
    1908                 :             :         }
    1909                 :             :     }
    1910                 :      145184 :   move2add_record_sym_value (reg, sym, off);
    1911                 :      145184 :   return changed;
    1912                 :             : }
    1913                 :             : 
    1914                 :             : 
    1915                 :             : /* This function is called with INSN that sets REG (of mode MODE) to
    1916                 :             :    (SYM + OFF), but REG doesn't have known value (SYM + offset).  This
    1917                 :             :    function tries to find another register which is known to already have
    1918                 :             :    value (SYM + offset) and change INSN into an add instruction
    1919                 :             :    (set (REG) (plus (the found register) (OFF - offset))) if such
    1920                 :             :    a register is found.  It also updates the information about
    1921                 :             :    REG's known value.
    1922                 :             :    Return true iff we made a change.  */
    1923                 :             : 
    1924                 :             : static bool
    1925                 :     1837078 : move2add_use_add3_insn (scalar_int_mode mode, rtx reg, rtx sym, rtx off,
    1926                 :             :                         rtx_insn *insn)
    1927                 :             : {
    1928                 :     1837078 :   rtx set = single_set (insn);
    1929                 :     1837078 :   rtx src = SET_SRC (set);
    1930                 :     1837078 :   int regno = REGNO (reg);
    1931                 :     1837078 :   int min_regno = 0;
    1932                 :     1837078 :   bool speed = optimize_bb_for_speed_p (BLOCK_FOR_INSN (insn));
    1933                 :     1837078 :   int i;
    1934                 :     1837078 :   bool changed = false;
    1935                 :     1837078 :   struct full_rtx_costs oldcst, newcst, mincst;
    1936                 :     1837078 :   rtx plus_expr;
    1937                 :             : 
    1938                 :     1837078 :   init_costs_to_max (&mincst);
    1939                 :     1837078 :   get_full_set_rtx_cost (set, &oldcst);
    1940                 :             : 
    1941                 :     1837078 :   plus_expr = gen_rtx_PLUS (GET_MODE (reg), reg, const0_rtx);
    1942                 :     1837078 :   SET_SRC (set) = plus_expr;
    1943                 :             : 
    1944                 :   170847595 :   for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
    1945                 :   169010527 :     if (move2add_valid_value_p (i, mode)
    1946                 :     3540873 :         && reg_base_reg[i] < 0
    1947                 :     1453661 :         && reg_symbol_ref[i] != NULL_RTX
    1948                 :   169949739 :         && rtx_equal_p (sym, reg_symbol_ref[i]))
    1949                 :             :       {
    1950                 :       39672 :         rtx new_src = gen_int_mode (UINTVAL (off) - reg_offset[i],
    1951                 :       19836 :                                     GET_MODE (reg));
    1952                 :             :         /* (set (reg) (plus (reg) (const_int 0))) is not canonical;
    1953                 :             :            use (set (reg) (reg)) instead.
    1954                 :             :            We don't delete this insn, nor do we convert it into a
    1955                 :             :            note, to avoid losing register notes or the return
    1956                 :             :            value flag.  jump2 already knows how to get rid of
    1957                 :             :            no-op moves.  */
    1958                 :       19836 :         if (new_src == const0_rtx)
    1959                 :             :           {
    1960                 :          10 :             init_costs_to_zero (&mincst);
    1961                 :          10 :             min_regno = i;
    1962                 :          10 :             break;
    1963                 :             :           }
    1964                 :             :         else
    1965                 :             :           {
    1966                 :       19826 :             XEXP (plus_expr, 1) = new_src;
    1967                 :       19826 :             get_full_set_rtx_cost (set, &newcst);
    1968                 :             : 
    1969                 :       19826 :             if (costs_lt_p (&newcst, &mincst, speed))
    1970                 :             :               {
    1971                 :       19262 :                 mincst = newcst;
    1972                 :       19262 :                 min_regno = i;
    1973                 :             :               }
    1974                 :             :           }
    1975                 :             :       }
    1976                 :     1837078 :   SET_SRC (set) = src;
    1977                 :             : 
    1978                 :     1837078 :   if (costs_lt_p (&mincst, &oldcst, speed))
    1979                 :             :     {
    1980                 :          35 :       rtx tem;
    1981                 :             : 
    1982                 :          35 :       tem = gen_rtx_REG (GET_MODE (reg), min_regno);
    1983                 :          35 :       if (i != min_regno)
    1984                 :             :         {
    1985                 :          50 :           rtx new_src = gen_int_mode (UINTVAL (off) - reg_offset[min_regno],
    1986                 :          25 :                                       GET_MODE (reg));
    1987                 :          25 :           tem = gen_rtx_PLUS (GET_MODE (reg), tem, new_src);
    1988                 :             :         }
    1989                 :          35 :       if (validate_change (insn, &SET_SRC (set), tem, 0))
    1990                 :     1837078 :         changed = true;
    1991                 :             :     }
    1992                 :     1837078 :   reg_set_luid[regno] = move2add_luid;
    1993                 :     1837078 :   move2add_record_sym_value (reg, sym, off);
    1994                 :     1837078 :   return changed;
    1995                 :             : }
    1996                 :             : 
    1997                 :             : /* Perform any invalidations necessary for INSN.  */
    1998                 :             : 
    1999                 :             : static void
    2000                 :    95406280 : reload_cse_move2add_invalidate (rtx_insn *insn)
    2001                 :             : {
    2002                 :   117070869 :   for (rtx note = REG_NOTES (insn); note; note = XEXP (note, 1))
    2003                 :             :     {
    2004                 :    21664589 :       if (REG_NOTE_KIND (note) == REG_INC
    2005                 :           0 :           && REG_P (XEXP (note, 0)))
    2006                 :             :         {
    2007                 :             :           /* Reset the information about this register.  */
    2008                 :           0 :           int regno = REGNO (XEXP (note, 0));
    2009                 :           0 :           if (regno < FIRST_PSEUDO_REGISTER)
    2010                 :             :             {
    2011                 :           0 :               move2add_record_mode (XEXP (note, 0));
    2012                 :           0 :               reg_mode[regno] = VOIDmode;
    2013                 :             :             }
    2014                 :             :         }
    2015                 :             :     }
    2016                 :             : 
    2017                 :             :   /* There are no REG_INC notes for SP autoinc.  */
    2018                 :    95406280 :   subrtx_var_iterator::array_type array;
    2019                 :   493766008 :   FOR_EACH_SUBRTX_VAR (iter, array, PATTERN (insn), NONCONST)
    2020                 :             :     {
    2021                 :   398359728 :       rtx mem = *iter;
    2022                 :   398359728 :       if (mem
    2023                 :   398359728 :           && MEM_P (mem)
    2024                 :    26250100 :           && GET_RTX_CLASS (GET_CODE (XEXP (mem, 0))) == RTX_AUTOINC)
    2025                 :             :         {
    2026                 :     1647761 :           if (XEXP (XEXP (mem, 0), 0) == stack_pointer_rtx)
    2027                 :     1647761 :             reg_mode[STACK_POINTER_REGNUM] = VOIDmode;
    2028                 :             :         }
    2029                 :             :     }
    2030                 :             : 
    2031                 :    95406280 :   note_stores (insn, move2add_note_store, insn);
    2032                 :             : 
    2033                 :             :   /* If INSN is a conditional branch, we try to extract an
    2034                 :             :      implicit set out of it.  */
    2035                 :    95406280 :   if (any_condjump_p (insn))
    2036                 :             :     {
    2037                 :     4474773 :       rtx cnd = fis_get_condition (insn);
    2038                 :             : 
    2039                 :     4474773 :       if (cnd != NULL_RTX
    2040                 :     4014573 :           && GET_CODE (cnd) == NE
    2041                 :     1812221 :           && REG_P (XEXP (cnd, 0))
    2042                 :     1216685 :           && !reg_set_p (XEXP (cnd, 0), insn)
    2043                 :             :           /* The following two checks, which are also in
    2044                 :             :              move2add_note_store, are intended to reduce the
    2045                 :             :              number of calls to gen_rtx_SET to avoid memory
    2046                 :             :              allocation if possible.  */
    2047                 :     1216685 :           && SCALAR_INT_MODE_P (GET_MODE (XEXP (cnd, 0)))
    2048                 :     1216684 :           && REG_NREGS (XEXP (cnd, 0)) == 1
    2049                 :     5691457 :           && CONST_INT_P (XEXP (cnd, 1)))
    2050                 :             :         {
    2051                 :      835477 :           rtx implicit_set = gen_rtx_SET (XEXP (cnd, 0), XEXP (cnd, 1));
    2052                 :      835477 :           move2add_note_store (SET_DEST (implicit_set), implicit_set, insn);
    2053                 :             :         }
    2054                 :             :     }
    2055                 :             : 
    2056                 :             :   /* If this is a CALL_INSN, all call used registers are stored with
    2057                 :             :      unknown values.  */
    2058                 :    95406280 :   if (CALL_P (insn))
    2059                 :             :     {
    2060                 :     4489205 :       function_abi callee_abi = insn_callee_abi (insn);
    2061                 :   417496065 :       for (int i = FIRST_PSEUDO_REGISTER - 1; i >= 0; i--)
    2062                 :   413006860 :         if (reg_mode[i] != VOIDmode
    2063                 :    20748042 :             && reg_mode[i] != BLKmode
    2064                 :   433174287 :             && callee_abi.clobbers_reg_p (reg_mode[i], i))
    2065                 :             :             /* Reset the information about this register.  */
    2066                 :     7743507 :           reg_mode[i] = VOIDmode;
    2067                 :             :     }
    2068                 :    95406280 : }
    2069                 :             : 
    2070                 :             : /* Convert move insns with constant inputs to additions if they are cheaper.
    2071                 :             :    Return true if any changes were made.  */
    2072                 :             : static bool
    2073                 :     1008570 : reload_cse_move2add (rtx_insn *first)
    2074                 :             : {
    2075                 :     1008570 :   int i;
    2076                 :     1008570 :   rtx_insn *insn;
    2077                 :     1008570 :   bool changed = false;
    2078                 :             : 
    2079                 :    93797010 :   for (i = FIRST_PSEUDO_REGISTER - 1; i >= 0; i--)
    2080                 :             :     {
    2081                 :    92788440 :       reg_set_luid[i] = 0;
    2082                 :    92788440 :       reg_offset[i] = 0;
    2083                 :    92788440 :       reg_base_reg[i] = 0;
    2084                 :    92788440 :       reg_symbol_ref[i] = NULL_RTX;
    2085                 :    92788440 :       reg_mode[i] = VOIDmode;
    2086                 :             :     }
    2087                 :             : 
    2088                 :     1008570 :   move2add_last_label_luid = 0;
    2089                 :     1008570 :   move2add_luid = 2;
    2090                 :   124844856 :   for (insn = first; insn; insn = NEXT_INSN (insn), move2add_luid++)
    2091                 :             :     {
    2092                 :   123836286 :       rtx set;
    2093                 :             : 
    2094                 :   123836286 :       if (LABEL_P (insn))
    2095                 :             :         {
    2096                 :     4823960 :           move2add_last_label_luid = move2add_luid;
    2097                 :             :           /* We're going to increment move2add_luid twice after a
    2098                 :             :              label, so that we can use move2add_last_label_luid + 1 as
    2099                 :             :              the luid for constants.  */
    2100                 :     4823960 :           move2add_luid++;
    2101                 :   128660246 :           continue;
    2102                 :             :         }
    2103                 :   119012326 :       if (! INSN_P (insn))
    2104                 :    21623784 :         continue;
    2105                 :    97388542 :       set = single_set (insn);
    2106                 :             :       /* For simplicity, we only perform this optimization on
    2107                 :             :          single-sets.  */
    2108                 :    97388542 :       scalar_int_mode mode;
    2109                 :    97388542 :       if (set
    2110                 :    51476611 :           && REG_P (SET_DEST (set))
    2111                 :   132763451 :           && is_a <scalar_int_mode> (GET_MODE (SET_DEST (set)), &mode))
    2112                 :             :         {
    2113                 :    26369070 :           rtx reg = SET_DEST (set);
    2114                 :    26369070 :           int regno = REGNO (reg);
    2115                 :    26369070 :           rtx src = SET_SRC (set);
    2116                 :             : 
    2117                 :             :           /* Check if we have valid information on the contents of this
    2118                 :             :              register in the mode of REG.  */
    2119                 :    26369070 :           if (move2add_valid_value_p (regno, mode)
    2120                 :    26369070 :               && dbg_cnt (cse2_move2add))
    2121                 :             :             {
    2122                 :             :               /* Try to transform (set (REGX) (CONST_INT A))
    2123                 :             :                                   ...
    2124                 :             :                                   (set (REGX) (CONST_INT B))
    2125                 :             :                  to
    2126                 :             :                                   (set (REGX) (CONST_INT A))
    2127                 :             :                                   ...
    2128                 :             :                                   (set (REGX) (plus (REGX) (CONST_INT B-A)))
    2129                 :             :                  or
    2130                 :             :                                   (set (REGX) (CONST_INT A))
    2131                 :             :                                   ...
    2132                 :             :                                   (set (STRICT_LOW_PART (REGX)) (CONST_INT B))
    2133                 :             :               */
    2134                 :             : 
    2135                 :     3751139 :               if (CONST_INT_P (src)
    2136                 :      327604 :                   && reg_base_reg[regno] < 0
    2137                 :      145702 :                   && reg_symbol_ref[regno] == NULL_RTX)
    2138                 :             :                 {
    2139                 :      143211 :                   changed |= move2add_use_add2_insn (mode, reg, NULL_RTX,
    2140                 :             :                                                      src, insn);
    2141                 :      143211 :                   continue;
    2142                 :             :                 }
    2143                 :             : 
    2144                 :             :               /* Try to transform (set (REGX) (REGY))
    2145                 :             :                                   (set (REGX) (PLUS (REGX) (CONST_INT A)))
    2146                 :             :                                   ...
    2147                 :             :                                   (set (REGX) (REGY))
    2148                 :             :                                   (set (REGX) (PLUS (REGX) (CONST_INT B)))
    2149                 :             :                  to
    2150                 :             :                                   (set (REGX) (REGY))
    2151                 :             :                                   (set (REGX) (PLUS (REGX) (CONST_INT A)))
    2152                 :             :                                   ...
    2153                 :             :                                   (set (REGX) (plus (REGX) (CONST_INT B-A)))  */
    2154                 :     3607928 :               else if (REG_P (src)
    2155                 :      450558 :                        && reg_set_luid[regno] == reg_set_luid[REGNO (src)]
    2156                 :      110590 :                        && reg_base_reg[regno] == reg_base_reg[REGNO (src)]
    2157                 :     3718518 :                        && move2add_valid_value_p (REGNO (src), mode))
    2158                 :             :                 {
    2159                 :       85746 :                   rtx_insn *next = next_nonnote_nondebug_insn (insn);
    2160                 :       85746 :                   rtx set = NULL_RTX;
    2161                 :       85746 :                   if (next)
    2162                 :       85732 :                     set = single_set (next);
    2163                 :       85732 :                   if (set
    2164                 :       66479 :                       && SET_DEST (set) == reg
    2165                 :        5294 :                       && GET_CODE (SET_SRC (set)) == PLUS
    2166                 :         670 :                       && XEXP (SET_SRC (set), 0) == reg
    2167                 :         666 :                       && CONST_INT_P (XEXP (SET_SRC (set), 1)))
    2168                 :             :                     {
    2169                 :         435 :                       rtx src3 = XEXP (SET_SRC (set), 1);
    2170                 :         435 :                       unsigned HOST_WIDE_INT added_offset = UINTVAL (src3);
    2171                 :         435 :                       HOST_WIDE_INT base_offset = reg_offset[REGNO (src)];
    2172                 :         435 :                       HOST_WIDE_INT regno_offset = reg_offset[regno];
    2173                 :         435 :                       rtx new_src =
    2174                 :         870 :                         gen_int_mode (added_offset
    2175                 :         435 :                                       + base_offset
    2176                 :         435 :                                       - regno_offset,
    2177                 :             :                                       mode);
    2178                 :         435 :                       bool success = false;
    2179                 :         435 :                       bool speed = optimize_bb_for_speed_p (BLOCK_FOR_INSN (insn));
    2180                 :             : 
    2181                 :         435 :                       if (new_src == const0_rtx)
    2182                 :             :                         /* See above why we create (set (reg) (reg)) here.  */
    2183                 :          28 :                         success
    2184                 :          28 :                           = validate_change (next, &SET_SRC (set), reg, 0);
    2185                 :             :                       else
    2186                 :             :                         {
    2187                 :         407 :                           rtx old_src = SET_SRC (set);
    2188                 :         407 :                           struct full_rtx_costs oldcst, newcst;
    2189                 :         407 :                           rtx tem = gen_rtx_PLUS (mode, reg, new_src);
    2190                 :             : 
    2191                 :         407 :                           get_full_set_rtx_cost (set, &oldcst);
    2192                 :         407 :                           SET_SRC (set) = tem;
    2193                 :         407 :                           get_full_set_src_cost (tem, mode, &newcst);
    2194                 :         407 :                           SET_SRC (set) = old_src;
    2195                 :         407 :                           costs_add_n_insns (&oldcst, 1);
    2196                 :             : 
    2197                 :         407 :                           rtx *setloc = GET_CODE (PATTERN (next)) == PARALLEL
    2198                 :         407 :                             ? &XVECEXP (PATTERN (next), 0, 0) : &PATTERN (next);
    2199                 :         407 :                           if (*setloc == set
    2200                 :         407 :                               && costs_lt_p (&newcst, &oldcst, speed)
    2201                 :         814 :                               && have_add2_insn (reg, new_src))
    2202                 :             :                             {
    2203                 :         407 :                               rtx newpat = gen_rtx_SET (reg, tem);
    2204                 :         407 :                               success
    2205                 :         407 :                                 = validate_change (next, setloc, newpat, 0);
    2206                 :             :                             }
    2207                 :             :                         }
    2208                 :         435 :                       if (success)
    2209                 :         435 :                         delete_insn (insn);
    2210                 :         435 :                       changed |= success;
    2211                 :         435 :                       insn = next;
    2212                 :             :                       /* Make sure to perform any invalidations related to
    2213                 :             :                          NEXT/INSN since we're going to bypass the normal
    2214                 :             :                          flow with the continue below.
    2215                 :             : 
    2216                 :             :                          Do this before recording the new mode/offset.  */
    2217                 :         435 :                       reload_cse_move2add_invalidate (insn);
    2218                 :         435 :                       move2add_record_mode (reg);
    2219                 :         435 :                       reg_offset[regno]
    2220                 :         435 :                         = trunc_int_for_mode (added_offset + base_offset,
    2221                 :             :                                               mode);
    2222                 :         435 :                       continue;
    2223                 :         435 :                     }
    2224                 :             :                 }
    2225                 :             :             }
    2226                 :             : 
    2227                 :             :           /* Try to transform
    2228                 :             :              (set (REGX) (CONST (PLUS (SYMBOL_REF) (CONST_INT A))))
    2229                 :             :              ...
    2230                 :             :              (set (REGY) (CONST (PLUS (SYMBOL_REF) (CONST_INT B))))
    2231                 :             :              to
    2232                 :             :              (set (REGX) (CONST (PLUS (SYMBOL_REF) (CONST_INT A))))
    2233                 :             :              ...
    2234                 :             :              (set (REGY) (CONST (PLUS (REGX) (CONST_INT B-A))))  */
    2235                 :    26225424 :           if ((GET_CODE (src) == SYMBOL_REF
    2236                 :    24450949 :                || (GET_CODE (src) == CONST
    2237                 :       64783 :                    && GET_CODE (XEXP (src, 0)) == PLUS
    2238                 :       64595 :                    && GET_CODE (XEXP (XEXP (src, 0), 0)) == SYMBOL_REF
    2239                 :       64576 :                    && CONST_INT_P (XEXP (XEXP (src, 0), 1))))
    2240                 :    26290000 :               && dbg_cnt (cse2_move2add))
    2241                 :             :             {
    2242                 :     1839051 :               rtx sym, off;
    2243                 :             : 
    2244                 :     1839051 :               if (GET_CODE (src) == SYMBOL_REF)
    2245                 :             :                 {
    2246                 :     1774475 :                   sym = src;
    2247                 :     1774475 :                   off = const0_rtx;
    2248                 :             :                 }
    2249                 :             :               else
    2250                 :             :                 {
    2251                 :       64576 :                   sym = XEXP (XEXP (src, 0), 0);
    2252                 :       64576 :                   off = XEXP (XEXP (src, 0), 1);
    2253                 :             :                 }
    2254                 :             : 
    2255                 :             :               /* If the reg already contains the value which is sum of
    2256                 :             :                  sym and some constant value, we can use an add2 insn.  */
    2257                 :     1839051 :               if (move2add_valid_value_p (regno, mode)
    2258                 :      188197 :                   && reg_base_reg[regno] < 0
    2259                 :      125713 :                   && reg_symbol_ref[regno] != NULL_RTX
    2260                 :     1892927 :                   && rtx_equal_p (sym, reg_symbol_ref[regno]))
    2261                 :        1973 :                 changed |= move2add_use_add2_insn (mode, reg, sym, off, insn);
    2262                 :             : 
    2263                 :             :               /* Otherwise, we have to find a register whose value is sum
    2264                 :             :                  of sym and some constant value.  */
    2265                 :             :               else
    2266                 :     1837078 :                 changed |= move2add_use_add3_insn (mode, reg, sym, off, insn);
    2267                 :             : 
    2268                 :     1839051 :               continue;
    2269                 :     1839051 :             }
    2270                 :             :         }
    2271                 :    95405845 :       reload_cse_move2add_invalidate (insn);
    2272                 :             :     }
    2273                 :     1008570 :   return changed;
    2274                 :             : }
    2275                 :             : 
    2276                 :             : /* SET is a SET or CLOBBER that sets DST.  DATA is the insn which
    2277                 :             :    contains SET.
    2278                 :             :    Update reg_set_luid, reg_offset and reg_base_reg accordingly.
    2279                 :             :    Called from reload_cse_move2add via note_stores.  */
    2280                 :             : 
    2281                 :             : static void
    2282                 :    58478071 : move2add_note_store (rtx dst, const_rtx set, void *data)
    2283                 :             : {
    2284                 :    58478071 :   rtx_insn *insn = (rtx_insn *) data;
    2285                 :    58478071 :   unsigned int regno = 0;
    2286                 :    58478071 :   scalar_int_mode mode;
    2287                 :             : 
    2288                 :    58478071 :   if (GET_CODE (dst) == SUBREG)
    2289                 :        3519 :     regno = subreg_regno (dst);
    2290                 :    58474552 :   else if (REG_P (dst))
    2291                 :    42257058 :     regno = REGNO (dst);
    2292                 :             :   else
    2293                 :    58478071 :     return;
    2294                 :             : 
    2295                 :    42260577 :   if (!is_a <scalar_int_mode> (GET_MODE (dst), &mode))
    2296                 :    15903829 :     goto invalidate;
    2297                 :             : 
    2298                 :    26356748 :   if (GET_CODE (set) == SET)
    2299                 :             :     {
    2300                 :    25805796 :       rtx note, sym = NULL_RTX;
    2301                 :    25805796 :       rtx off;
    2302                 :             : 
    2303                 :    25805796 :       note = find_reg_equal_equiv_note (insn);
    2304                 :    25805796 :       if (note && GET_CODE (XEXP (note, 0)) == SYMBOL_REF)
    2305                 :             :         {
    2306                 :       68756 :           sym = XEXP (note, 0);
    2307                 :       68756 :           off = const0_rtx;
    2308                 :             :         }
    2309                 :     4143494 :       else if (note && GET_CODE (XEXP (note, 0)) == CONST
    2310                 :       10333 :                && GET_CODE (XEXP (XEXP (note, 0), 0)) == PLUS
    2311                 :       10158 :                && GET_CODE (XEXP (XEXP (XEXP (note, 0), 0), 0)) == SYMBOL_REF
    2312                 :       10139 :                && CONST_INT_P (XEXP (XEXP (XEXP (note, 0), 0), 1)))
    2313                 :             :         {
    2314                 :             :           sym = XEXP (XEXP (XEXP (note, 0), 0), 0);
    2315                 :             :           off = XEXP (XEXP (XEXP (note, 0), 0), 1);
    2316                 :             :         }
    2317                 :             : 
    2318                 :       78895 :       if (sym != NULL_RTX)
    2319                 :             :         {
    2320                 :       78895 :           move2add_record_sym_value (dst, sym, off);
    2321                 :       78895 :           return;
    2322                 :             :         }
    2323                 :             :     }
    2324                 :             : 
    2325                 :    26277853 :   if (GET_CODE (set) == SET
    2326                 :    25726901 :       && GET_CODE (SET_DEST (set)) != ZERO_EXTRACT
    2327                 :    25725499 :       && GET_CODE (SET_DEST (set)) != STRICT_LOW_PART)
    2328                 :             :     {
    2329                 :    25721843 :       rtx src = SET_SRC (set);
    2330                 :    25721843 :       rtx base_reg;
    2331                 :    25721843 :       unsigned HOST_WIDE_INT offset;
    2332                 :    25721843 :       int base_regno;
    2333                 :             : 
    2334                 :    25721843 :       switch (GET_CODE (src))
    2335                 :             :         {
    2336                 :     5741379 :         case PLUS:
    2337                 :     5741379 :           if (REG_P (XEXP (src, 0)))
    2338                 :             :             {
    2339                 :     5442736 :               base_reg = XEXP (src, 0);
    2340                 :             : 
    2341                 :     5442736 :               if (CONST_INT_P (XEXP (src, 1)))
    2342                 :     4709982 :                 offset = UINTVAL (XEXP (src, 1));
    2343                 :      732754 :               else if (REG_P (XEXP (src, 1))
    2344                 :      732754 :                        && move2add_valid_value_p (REGNO (XEXP (src, 1)), mode))
    2345                 :             :                 {
    2346                 :       80984 :                   if (reg_base_reg[REGNO (XEXP (src, 1))] < 0
    2347                 :       80984 :                       && reg_symbol_ref[REGNO (XEXP (src, 1))] == NULL_RTX)
    2348                 :        7153 :                     offset = reg_offset[REGNO (XEXP (src, 1))];
    2349                 :             :                   /* Maybe the first register is known to be a
    2350                 :             :                      constant.  */
    2351                 :       73831 :                   else if (move2add_valid_value_p (REGNO (base_reg), mode)
    2352                 :       18405 :                            && reg_base_reg[REGNO (base_reg)] < 0
    2353                 :       74777 :                            && reg_symbol_ref[REGNO (base_reg)] == NULL_RTX)
    2354                 :             :                     {
    2355                 :         807 :                       offset = reg_offset[REGNO (base_reg)];
    2356                 :         807 :                       base_reg = XEXP (src, 1);
    2357                 :             :                     }
    2358                 :             :                   else
    2359                 :       73024 :                     goto invalidate;
    2360                 :             :                 }
    2361                 :             :               else
    2362                 :      651770 :                 goto invalidate;
    2363                 :             : 
    2364                 :             :               break;
    2365                 :             :             }
    2366                 :             : 
    2367                 :      298643 :           goto invalidate;
    2368                 :             : 
    2369                 :             :         case REG:
    2370                 :             :           base_reg = src;
    2371                 :             :           offset = 0;
    2372                 :             :           break;
    2373                 :             : 
    2374                 :     4274678 :         case CONST_INT:
    2375                 :             :           /* Start tracking the register as a constant.  */
    2376                 :     4274678 :           reg_base_reg[regno] = -1;
    2377                 :     4274678 :           reg_symbol_ref[regno] = NULL_RTX;
    2378                 :     4274678 :           reg_offset[regno] = INTVAL (SET_SRC (set));
    2379                 :             :           /* We assign the same luid to all registers set to constants.  */
    2380                 :     4274678 :           reg_set_luid[regno] = move2add_last_label_luid + 1;
    2381                 :     4274678 :           move2add_record_mode (dst);
    2382                 :     4274678 :           return;
    2383                 :             : 
    2384                 :    11139201 :         default:
    2385                 :    11139201 :           goto invalidate;
    2386                 :             :         }
    2387                 :             : 
    2388                 :     9284527 :       base_regno = REGNO (base_reg);
    2389                 :             :       /* If information about the base register is not valid, set it
    2390                 :             :          up as a new base register, pretending its value is known
    2391                 :             :          starting from the current insn.  */
    2392                 :     9284527 :       if (!move2add_valid_value_p (base_regno, mode))
    2393                 :             :         {
    2394                 :     6736796 :           reg_base_reg[base_regno] = base_regno;
    2395                 :     6736796 :           reg_symbol_ref[base_regno] = NULL_RTX;
    2396                 :     6736796 :           reg_offset[base_regno] = 0;
    2397                 :     6736796 :           reg_set_luid[base_regno] = move2add_luid;
    2398                 :     6736796 :           gcc_assert (GET_MODE (base_reg) == mode);
    2399                 :     6736796 :           move2add_record_mode (base_reg);
    2400                 :             :         }
    2401                 :             : 
    2402                 :             :       /* Copy base information from our base register.  */
    2403                 :     9284527 :       reg_set_luid[regno] = reg_set_luid[base_regno];
    2404                 :     9284527 :       reg_base_reg[regno] = reg_base_reg[base_regno];
    2405                 :     9284527 :       reg_symbol_ref[regno] = reg_symbol_ref[base_regno];
    2406                 :             : 
    2407                 :             :       /* Compute the sum of the offsets or constants.  */
    2408                 :     9284527 :       reg_offset[regno]
    2409                 :     9284527 :         = trunc_int_for_mode (offset + reg_offset[base_regno], mode);
    2410                 :             : 
    2411                 :     9284527 :       move2add_record_mode (dst);
    2412                 :     9284527 :     }
    2413                 :             :   else
    2414                 :             :     {
    2415                 :      556010 :     invalidate:
    2416                 :             :       /* Invalidate the contents of the register.  */
    2417                 :    28622477 :       move2add_record_mode (dst);
    2418                 :    28622477 :       reg_mode[regno] = VOIDmode;
    2419                 :             :     }
    2420                 :             : }
    2421                 :             : 
    2422                 :             : namespace {
    2423                 :             : 
    2424                 :             : const pass_data pass_data_postreload_cse =
    2425                 :             : {
    2426                 :             :   RTL_PASS, /* type */
    2427                 :             :   "postreload", /* name */
    2428                 :             :   OPTGROUP_NONE, /* optinfo_flags */
    2429                 :             :   TV_RELOAD_CSE_REGS, /* tv_id */
    2430                 :             :   0, /* properties_required */
    2431                 :             :   0, /* properties_provided */
    2432                 :             :   0, /* properties_destroyed */
    2433                 :             :   0, /* todo_flags_start */
    2434                 :             :   TODO_df_finish, /* todo_flags_finish */
    2435                 :             : };
    2436                 :             : 
    2437                 :             : class pass_postreload_cse : public rtl_opt_pass
    2438                 :             : {
    2439                 :             : public:
    2440                 :      283157 :   pass_postreload_cse (gcc::context *ctxt)
    2441                 :      566314 :     : rtl_opt_pass (pass_data_postreload_cse, ctxt)
    2442                 :             :   {}
    2443                 :             : 
    2444                 :             :   /* opt_pass methods: */
    2445                 :     1435849 :   bool gate (function *) final override
    2446                 :             :   {
    2447                 :     1435849 :     return (optimize > 0 && reload_completed);
    2448                 :             :   }
    2449                 :             : 
    2450                 :             :   unsigned int execute (function *) final override;
    2451                 :             : 
    2452                 :             : }; // class pass_postreload_cse
    2453                 :             : 
    2454                 :             : unsigned int
    2455                 :     1008570 : pass_postreload_cse::execute (function *fun)
    2456                 :             : {
    2457                 :     1008570 :   if (!dbg_cnt (postreload_cse))
    2458                 :             :     return 0;
    2459                 :             : 
    2460                 :             :   /* Do a very simple CSE pass over just the hard registers.  */
    2461                 :     1008570 :   reload_cse_regs (get_insns ());
    2462                 :             :   /* Reload_cse_regs can eliminate potentially-trapping MEMs.
    2463                 :             :      Remove any EH edges associated with them.  */
    2464                 :     1008570 :   if (fun->can_throw_non_call_exceptions
    2465                 :     1008570 :       && purge_all_dead_edges ())
    2466                 :         102 :     cleanup_cfg (0);
    2467                 :             : 
    2468                 :             :   return 0;
    2469                 :             : }
    2470                 :             : 
    2471                 :             : } // anon namespace
    2472                 :             : 
    2473                 :             : rtl_opt_pass *
    2474                 :      283157 : make_pass_postreload_cse (gcc::context *ctxt)
    2475                 :             : {
    2476                 :      283157 :   return new pass_postreload_cse (ctxt);
    2477                 :             : }
        

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