LCOV - code coverage report
Current view: top level - gcc - lra-remat.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 95.5 % 672 642
Test Date: 2026-02-28 14:20:25 Functions: 100.0 % 33 33
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /* Rematerialize pseudos values.
       2              :    Copyright (C) 2014-2026 Free Software Foundation, Inc.
       3              :    Contributed by Vladimir Makarov <vmakarov@redhat.com>.
       4              : 
       5              : This file is part of GCC.
       6              : 
       7              : GCC is free software; you can redistribute it and/or modify it under
       8              : the terms of the GNU General Public License as published by the Free
       9              : Software Foundation; either version 3, or (at your option) any later
      10              : version.
      11              : 
      12              : GCC is distributed in the hope that it will be useful, but WITHOUT ANY
      13              : WARRANTY; without even the implied warranty of MERCHANTABILITY or
      14              : FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
      15              : for more details.
      16              : 
      17              : You should have received a copy of the GNU General Public License
      18              : along with GCC; see the file COPYING3.  If not see
      19              : <http://www.gnu.org/licenses/>.    */
      20              : 
      21              : /* This code objective is to rematerialize spilled pseudo values.  To
      22              :    do this we calculate available insn candidates.  The candidate is
      23              :    available at some point if there is dominated set of insns with the
      24              :    same pattern, the insn inputs are not dying or modified on any path
      25              :    from the set, the outputs are not modified.
      26              : 
      27              :    The insns containing memory or spilled pseudos (except for the
      28              :    rematerialized pseudo) are not considered as such insns are not
      29              :    profitable in comparison with regular loads of spilled pseudo
      30              :    values.  That simplifies the implementation as we don't need to
      31              :    deal with memory aliasing.
      32              : 
      33              :    To speed up available candidate calculation, we calculate partially
      34              :    available candidates first and use them for initialization of the
      35              :    availability.  That is because (partial) availability sets are
      36              :    sparse.
      37              : 
      38              :    The rematerialization sub-pass could be improved further in the
      39              :    following ways:
      40              : 
      41              :    o We could make longer live ranges of inputs in the
      42              :      rematerialization candidates if their hard registers are not used
      43              :      for other purposes.  This could be complicated if we need to
      44              :      update BB live info information as LRA does not use
      45              :      DF-infrastructure for compile-time reasons.  This problem could
      46              :      be overcome if constrain making live ranges longer only in BB/EBB
      47              :      scope.
      48              :    o We could use cost-based decision to choose rematerialization insn
      49              :      (currently all insns without memory is can be used).
      50              :    o We could use other free hard regs for unused output pseudos in
      51              :      rematerialization candidates although such cases probably will
      52              :      be very rare.  */
      53              : 
      54              : 
      55              : #include "config.h"
      56              : #include "system.h"
      57              : #include "coretypes.h"
      58              : #include "backend.h"
      59              : #include "rtl.h"
      60              : #include "df.h"
      61              : #include "insn-config.h"
      62              : #include "regs.h"
      63              : #include "memmodel.h"
      64              : #include "ira.h"
      65              : #include "recog.h"
      66              : #include "lra.h"
      67              : #include "lra-int.h"
      68              : #include "function-abi.h"
      69              : 
      70              : /* Number of candidates for rematerialization.  */
      71              : static unsigned int cands_num;
      72              : 
      73              : /* Bitmap used for different calculations.  */
      74              : static bitmap_head temp_bitmap;
      75              : 
      76              : /* Registers accessed via subreg_p.  */
      77              : static bitmap_head subreg_regs;
      78              : 
      79              : typedef struct cand *cand_t;
      80              : typedef const struct cand *const_cand_t;
      81              : 
      82              : /* Insn candidates for rematerialization.  The candidate insn should
      83              :    have the following properies:
      84              :    o no any memory (as access to memory is non-profitable) or
      85              :      div/mod operations (as they are usually more expensive than loads)
      86              :    o no INOUT regs (it means no non-paradoxical subreg of output reg)
      87              :    o no multiple output pseudos
      88              :    o one output spilled pseudo (or reload pseudo of a spilled pseudo)
      89              :    o all other pseudos are with assigned hard regs.  */
      90              : struct cand
      91              : {
      92              :   /* Index of the candidates in all_cands. */
      93              :   int index;
      94              :   /* Insn pseudo regno for rematerialization.  */
      95              :   int regno;
      96              :   /* The candidate insn.  */
      97              :   rtx_insn *insn;
      98              :   /* Non-negative if a reload pseudo is in the insn instead of the
      99              :      pseudo for rematerialization.  */
     100              :   int reload_regno;
     101              :   /* Number of the operand containing the regno or its reload
     102              :      regno.  */
     103              :   int nop;
     104              :   /* Next candidate for the same regno.  */
     105              :   cand_t next_regno_cand;
     106              : };
     107              : 
     108              : /* Vector containing all candidates.  */
     109              : static vec<cand_t> all_cands;
     110              : /* Map: insn -> candidate representing it.  It is null if the insn cannot
     111              :    be used for rematerialization.  */
     112              : static cand_t *insn_to_cand;
     113              : /* A secondary map, for candidates that involve two insns, where the
     114              :    second one makes the equivalence.  The candidate must not be used
     115              :    before seeing this activation insn.  */
     116              : static cand_t *insn_to_cand_activation;
     117              : 
     118              : /* Map regno -> candidates can be used for the regno
     119              :    rematerialization.  */
     120              : static cand_t *regno_cands;
     121              : 
     122              : /* Data about basic blocks used for the rematerialization
     123              :    sub-pass.  */
     124              : class remat_bb_data
     125              : {
     126              : public:
     127              :   /* Basic block about which the below data are.  */
     128              :   basic_block bb;
     129              :   /* Registers changed in the basic block: */
     130              :   bitmap_head changed_regs;
     131              :   /* Registers becoming dead in the BB.  */
     132              :   bitmap_head dead_regs;
     133              :   /* Cands present in the BB whose in/out regs are not changed after
     134              :      the cands occurence and are not dead (except the reload
     135              :      regno).  */
     136              :   bitmap_head gen_cands;
     137              :   bitmap_head livein_cands; /* cands whose inputs live at the BB start.  */
     138              :   bitmap_head pavin_cands; /* cands partially available at BB entry.  */
     139              :   bitmap_head pavout_cands; /* cands partially available at BB exit.  */
     140              :   bitmap_head avin_cands; /* cands available at the entry of the BB.  */
     141              :   bitmap_head avout_cands; /* cands available at the exit of the BB.  */
     142              : };
     143              : 
     144              : /* Array for all BB data.  Indexed by the corresponding BB index.  */
     145              : typedef class remat_bb_data *remat_bb_data_t;
     146              : 
     147              : /* Basic blocks for data flow problems -- all bocks except the special
     148              :    ones.  */
     149              : static bitmap_head all_blocks;
     150              : 
     151              : /* All basic block data are referred through the following array.  */
     152              : static remat_bb_data_t remat_bb_data;
     153              : 
     154              : /* Two small functions for access to the bb data.  */
     155              : static inline remat_bb_data_t
     156    150022535 : get_remat_bb_data (basic_block bb)
     157              : {
     158    150022535 :   return &remat_bb_data[(bb)->index];
     159              : }
     160              : 
     161              : static inline remat_bb_data_t
     162     27812510 : get_remat_bb_data_by_index (int index)
     163              : {
     164     27812510 :   return &remat_bb_data[index];
     165              : }
     166              : 
     167              : 
     168              : 
     169              : /* Hash table for the candidates.  Different insns (e.g. structurally
     170              :    the same insns or even insns with different unused output regs) can
     171              :    be represented by the same candidate in the table.  */
     172              : static htab_t cand_table;
     173              : 
     174              : /* Hash function for candidate CAND.  */
     175              : static hashval_t
     176       323109 : cand_hash (const void *cand)
     177              : {
     178       323109 :   const_cand_t c = (const_cand_t) cand;
     179       323109 :   lra_insn_recog_data_t id = lra_get_insn_recog_data (c->insn);
     180       323109 :   struct lra_static_insn_data *static_id = id->insn_static_data;
     181       323109 :   int nops = static_id->n_operands;
     182       323109 :   hashval_t hash = 0;
     183              : 
     184       980495 :   for (int i = 0; i < nops; i++)
     185       657386 :     if (i == c->nop)
     186       323109 :       hash = iterative_hash_object (c->regno, hash);
     187       334277 :     else if (static_id->operand[i].type == OP_IN)
     188       334277 :       hash = iterative_hash_object (*id->operand_loc[i], hash);
     189       323109 :   return hash;
     190              : }
     191              : 
     192              : /* Equal function for candidates CAND1 and CAND2.  They are equal if
     193              :    the corresponding candidate insns have the same code, the same
     194              :    regno for rematerialization, the same input operands.  */
     195              : static int
     196        69934 : cand_eq_p (const void *cand1, const void *cand2)
     197              : {
     198        69934 :   const_cand_t c1 = (const_cand_t) cand1;
     199        69934 :   const_cand_t c2 = (const_cand_t) cand2;
     200        69934 :   lra_insn_recog_data_t id1 = lra_get_insn_recog_data (c1->insn);
     201        69934 :   lra_insn_recog_data_t id2 = lra_get_insn_recog_data (c2->insn);
     202        69934 :   struct lra_static_insn_data *static_id1 = id1->insn_static_data;
     203        69934 :   int nops = static_id1->n_operands;
     204              : 
     205        69934 :   if (c1->regno != c2->regno
     206        69508 :       || INSN_CODE (c1->insn) < 0
     207        69508 :       || INSN_CODE (c1->insn) != INSN_CODE (c2->insn))
     208              :     return false;
     209        69506 :   gcc_assert (c1->nop == c2->nop);
     210       208796 :   for (int i = 0; i < nops; i++)
     211       139296 :     if (i != c1->nop && static_id1->operand[i].type == OP_IN
     212        69790 :         && *id1->operand_loc[i] != *id2->operand_loc[i])
     213              :       return false;
     214              :   return true;
     215              : }
     216              : 
     217              : /* Insert candidate CAND into the table if it is not there yet.
     218              :    Return candidate which is in the table.  */
     219              : static cand_t
     220       323109 : insert_cand (cand_t cand)
     221              : {
     222       323109 :   void **entry_ptr;
     223              : 
     224       323109 :   entry_ptr = htab_find_slot (cand_table, cand, INSERT);
     225       323109 :   if (*entry_ptr == NULL)
     226       253609 :     *entry_ptr = (void *) cand;
     227       323109 :   return (cand_t) *entry_ptr;
     228              : }
     229              : 
     230              : /* Free candidate CAND memory.  */
     231              : static void
     232       253609 : free_cand (void *cand)
     233              : {
     234       253609 :   free (cand);
     235       253609 : }
     236              : 
     237              : /* Initiate the candidate table.  */
     238              : static void
     239       184086 : initiate_cand_table (void)
     240              : {
     241       184086 :   cand_table = htab_create (8000, cand_hash, cand_eq_p,
     242              :                             (htab_del) free_cand);
     243       184086 : }
     244              : 
     245              : /* Finish the candidate table.  */
     246              : static void
     247       184086 : finish_cand_table (void)
     248              : {
     249            0 :   htab_delete (cand_table);
     250            0 : }
     251              : 
     252              : 
     253              : 
     254              : /* Return true if X contains memory, some UNSPEC, or expensive operations.  We
     255              :    cannot just check insn operands as memory or unspec might be not an operand
     256              :    itself but contain an operand.  Insns with memory access or expensive ones
     257              :    are not profitable for rematerialization.  Rematerialization of UNSPEC might
     258              :    result in wrong code generation as the UNPEC effect is unknown
     259              :    (e.g. generating a label).  */
     260              : static bool
     261     53438086 : bad_for_rematerialization_p (rtx x)
     262              : {
     263     53438086 :   int i, j;
     264     53438086 :   const char *fmt;
     265     53438086 :   enum rtx_code code;
     266              : 
     267     53438086 :   if (MEM_P (x) || GET_CODE (x) == UNSPEC || GET_CODE (x) == UNSPEC_VOLATILE
     268              :       /* Usually the following operations are expensive and does not worth to
     269              :          rematerialize: */
     270              :       || GET_CODE(x) == DIV || GET_CODE(x) == UDIV
     271              :       || GET_CODE(x) == MOD || GET_CODE(x) == UMOD)
     272              :     return true;
     273     50693957 :   code = GET_CODE (x);
     274     50693957 :   fmt = GET_RTX_FORMAT (code);
     275    113650617 :   for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
     276              :     {
     277     66143046 :       if (fmt[i] == 'e')
     278              :         {
     279     34582062 :           if (bad_for_rematerialization_p (XEXP (x, i)))
     280              :             return true;
     281              :         }
     282     31560984 :       else if (fmt[i] == 'E')
     283              :         {
     284      5927000 :           for (j = XVECLEN (x, i) - 1; j >= 0; j--)
     285      4253552 :             if (bad_for_rematerialization_p (XVECEXP (x, i, j)))
     286              :               return true;
     287              :         }
     288              :     }
     289              :   return false;
     290              : }
     291              : 
     292              : /* If INSN cannot be used for rematerialization, return negative
     293              :    value.  If INSN can be considered as a candidate for
     294              :    rematerialization, return value which is the operand number of the
     295              :    pseudo for which the insn can be used for rematerialization.  Here
     296              :    we consider the insns without any memory, spilled pseudo (except
     297              :    for the rematerialization pseudo), or dying or unused regs.  */
     298              : static int
     299     42544251 : operand_to_remat (rtx_insn *insn)
     300              : {
     301     42544251 :   lra_insn_recog_data_t id = lra_get_insn_recog_data (insn);
     302     42544251 :   struct lra_static_insn_data *static_id = id->insn_static_data;
     303     42544251 :   struct lra_insn_reg *reg, *found_reg = NULL;
     304              : 
     305              :   /* Don't rematerialize insns which can change PC.  */
     306     42544251 :   if (JUMP_P (insn) || CALL_P (insn))
     307              :     return -1;
     308              :   /* First find a pseudo which can be rematerialized.  */
     309     78072727 :   for (reg = id->regs; reg != NULL; reg = reg->next)
     310              :     {
     311              :       /* True FRAME_POINTER_NEEDED might be because we cannot follow
     312              :          changing sp offsets, e.g. alloca is used.  If the insn contains
     313              :          stack pointer in such case, we cannot rematerialize it as we
     314              :          cannot know sp offset at a rematerialization place.  */
     315     57404548 :       if (reg->regno == STACK_POINTER_REGNUM && frame_pointer_needed)
     316              :         return -1;
     317     56685886 :       else if (reg->type == OP_OUT)
     318              :         {
     319              :           /* We permits only one spilled reg.  */
     320     24126753 :           if (found_reg != NULL)
     321              :             return -1;
     322              :           found_reg = reg;
     323              :         }
     324              :       /* IRA calculates conflicts separately for subregs of two words
     325              :          pseudo.  Even if the pseudo lives, e.g. one its subreg can be
     326              :          used lately, another subreg hard register can be already used
     327              :          for something else.  In such case, it is not safe to
     328              :          rematerialize the insn.  */
     329     56668237 :       if (reg->regno >= FIRST_PSEUDO_REGISTER
     330     56668237 :           && bitmap_bit_p (&subreg_regs, reg->regno))
     331              :         return -1;
     332              : 
     333              :       /* Don't allow hard registers to be rematerialized.  */
     334     55704684 :       if (reg->regno < FIRST_PSEUDO_REGISTER)
     335              :         return -1;
     336              :     }
     337     20668179 :   if (found_reg == NULL)
     338              :     return -1;
     339     14602472 :   if (found_reg->regno < FIRST_PSEUDO_REGISTER)
     340              :     return -1;
     341     14602472 :   if (bad_for_rematerialization_p (PATTERN (insn)))
     342              :     return -1;
     343              :   /* Check the other regs are not spilled. */
     344     25688764 :   for (reg = id->regs; reg != NULL; reg = reg->next)
     345     22746783 :     if (found_reg == reg)
     346     11857557 :       continue;
     347     10889226 :     else if (reg->type == OP_INOUT)
     348              :       return -1;
     349     10884928 :     else if (reg->regno >= FIRST_PSEUDO_REGISTER
     350     10884928 :              && reg_renumber[reg->regno] < 0)
     351              :       /* Another spilled reg.  */
     352              :       return -1;
     353      9217710 :     else if (reg->type == OP_IN)
     354              :       {
     355      9217710 :         if (find_regno_note (insn, REG_DEAD, reg->regno) != NULL)
     356              :           /* We don't want to make live ranges longer.  */
     357              :           return -1;
     358              :         /* Check that there is no output reg as the input one.  */
     359      1974735 :         for (struct lra_insn_reg *reg2 = id->regs;
     360      6176157 :              reg2 != NULL;
     361      4201422 :              reg2 = reg2->next)
     362      4203293 :           if (reg2->type == OP_OUT && reg->regno == reg2->regno)
     363              :             return -1;
     364      1972864 :         if (reg->regno < FIRST_PSEUDO_REGISTER)
     365            0 :           for (struct lra_insn_reg *reg2 = static_id->hard_regs;
     366            0 :                reg2 != NULL;
     367            0 :                reg2 = reg2->next)
     368            0 :             if (reg2->type == OP_OUT
     369            0 :                 && reg->regno <= reg2->regno
     370            0 :                 && (reg2->regno
     371            0 :                     < (int) end_hard_regno (reg->biggest_mode, reg->regno)))
     372              :               return -1;
     373              :       }
     374              :   /* Check hard coded insn registers.  */
     375      2941981 :   for (struct lra_insn_reg *reg = static_id->hard_regs;
     376      3323023 :        reg != NULL;
     377       381042 :        reg = reg->next)
     378       381042 :     if (reg->type == OP_INOUT)
     379              :       return -1;
     380       381042 :     else if (reg->type == OP_IN)
     381              :       {
     382              :         /* Check that there is no output hard reg as the input
     383              :            one.  */
     384            0 :           for (struct lra_insn_reg *reg2 = static_id->hard_regs;
     385            0 :                reg2 != NULL;
     386            0 :                reg2 = reg2->next)
     387            0 :             if (reg2->type == OP_OUT && reg->regno == reg2->regno)
     388              :                 return -1;
     389              :       }
     390              :   /* Find the rematerialization operand.  */
     391      2941981 :   int nop = static_id->n_operands;
     392      2968250 :   for (int i = 0; i < nop; i++)
     393      2944740 :     if (REG_P (*id->operand_loc[i])
     394      2944740 :         && (int) REGNO (*id->operand_loc[i]) == found_reg->regno)
     395              :       return i;
     396              :   return -1;
     397              : }
     398              : 
     399              : /* Create candidate for INSN with rematerialization operand NOP and
     400              :    REGNO.  Insert the candidate into the table and set up the
     401              :    corresponding INSN_TO_CAND element.  */
     402              : static void
     403       323109 : create_cand (rtx_insn *insn, int nop, int regno, rtx_insn *activation = NULL)
     404              : {
     405       323109 :   lra_insn_recog_data_t id = lra_get_insn_recog_data (insn);
     406       323109 :   rtx reg = *id->operand_loc[nop];
     407       323109 :   gcc_assert (REG_P (reg));
     408       323109 :   int op_regno = REGNO (reg);
     409       323109 :   gcc_assert (op_regno >= FIRST_PSEUDO_REGISTER);
     410       323109 :   cand_t cand = XNEW (struct cand);
     411       323109 :   cand->insn = insn;
     412       323109 :   cand->nop = nop;
     413       323109 :   cand->regno = regno;
     414       323109 :   cand->reload_regno = op_regno == regno ? -1 : op_regno;
     415       323109 :   gcc_assert (cand->regno >= 0);
     416       323109 :   cand_t cand_in_table = insert_cand (cand);
     417       323109 :   insn_to_cand[INSN_UID (insn)] = cand_in_table;
     418       323109 :   if (cand != cand_in_table)
     419        69500 :     free (cand);
     420              :   else
     421              :     {
     422              :       /* A new cand.  */
     423       253609 :       cand->index = all_cands.length ();
     424       253609 :       all_cands.safe_push (cand);
     425       253609 :       cand->next_regno_cand = regno_cands[cand->regno];
     426       253609 :       regno_cands[cand->regno] = cand;
     427              :     }
     428       323109 :   if (activation)
     429        23945 :     insn_to_cand_activation[INSN_UID (activation)] = cand_in_table;
     430       323109 : }
     431              : 
     432              : /* Create rematerialization candidates (inserting them into the
     433              :    table).  */
     434              : static void
     435       184086 : create_cands (void)
     436              : {
     437       184086 :   rtx_insn *insn;
     438       184086 :   struct potential_cand
     439              :   {
     440              :     rtx_insn *insn;
     441              :     int nop;
     442              :   };
     443       184086 :   struct potential_cand *regno_potential_cand;
     444              : 
     445              :   /* Create candidates.  */
     446       184086 :   regno_potential_cand = XCNEWVEC (struct potential_cand, max_reg_num ());
     447     95580904 :   for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
     448     95396818 :     if (NONDEBUG_INSN_P (insn))
     449              :       {
     450     42568196 :         lra_insn_recog_data_t id = lra_get_insn_recog_data (insn);
     451     42568196 :         int keep_regno = -1;
     452     42568196 :         rtx set = single_set (insn);
     453     42568196 :         int nop;
     454              : 
     455              :         /* See if this is an output reload for a previous insn.  */
     456     42568196 :         if (set != NULL
     457     40748051 :             && REG_P (SET_SRC (set)) && REG_P (SET_DEST (set)))
     458              :           {
     459     12199898 :             rtx dstreg = SET_DEST (set);
     460     12199898 :             int src_regno = REGNO (SET_SRC (set));
     461     12199898 :             int dst_regno = REGNO (dstreg);
     462     12199898 :             rtx_insn *insn2 = regno_potential_cand[src_regno].insn;
     463              : 
     464     12199898 :             if (insn2 != NULL
     465     12199898 :                 && dst_regno >= FIRST_PSEUDO_REGISTER
     466        88511 :                 && reg_renumber[dst_regno] < 0
     467        24096 :                 && BLOCK_FOR_INSN (insn2) == BLOCK_FOR_INSN (insn)
     468     12223994 :                 && insn2 == prev_nonnote_nondebug_insn (insn))
     469              :               {
     470        23945 :                 create_cand (insn2, regno_potential_cand[src_regno].nop,
     471              :                              dst_regno, insn);
     472        23945 :                 goto done;
     473              :               }
     474              :           }
     475              : 
     476     42544251 :         nop = operand_to_remat (insn);
     477     42544251 :         if (nop >= 0)
     478              :           {
     479      2918471 :             gcc_assert (REG_P (*id->operand_loc[nop]));
     480      2918471 :             int regno = REGNO (*id->operand_loc[nop]);
     481      2918471 :             gcc_assert (regno >= FIRST_PSEUDO_REGISTER);
     482              :             /* If we're setting an unrenumbered pseudo, make a candidate
     483              :                immediately.  If it's a potential output reload register, save
     484              :                it for later; the code above looks for output reload insns later
     485              :                on.  */
     486      2918471 :             if (reg_renumber[regno] < 0)
     487       299164 :               create_cand (insn, nop, regno);
     488      2619307 :             else if (regno >= lra_constraint_new_regno_start)
     489              :               {
     490       887509 :                 regno_potential_cand[regno].insn = insn;
     491       887509 :                 regno_potential_cand[regno].nop = nop;
     492       887509 :                 keep_regno = regno;
     493              :               }
     494              :           }
     495              : 
     496     39625780 :       done:
     497    111195844 :         for (struct lra_insn_reg *reg = id->regs; reg != NULL; reg = reg->next)
     498     68627648 :           if (reg->type != OP_IN && reg->regno != keep_regno
     499     28523918 :               && reg->regno >= FIRST_PSEUDO_REGISTER)
     500     20448100 :             regno_potential_cand[reg->regno].insn = NULL;
     501              :       }
     502       184086 :   cands_num = all_cands.length ();
     503       184086 :   free (regno_potential_cand);
     504       184086 : }
     505              : 
     506              : 
     507              : 
     508              : /* Create and initialize BB data.  */
     509              : static void
     510       184086 : create_remat_bb_data (void)
     511              : {
     512       184086 :   basic_block bb;
     513       184086 :   remat_bb_data_t bb_info;
     514              : 
     515       184086 :   remat_bb_data = XNEWVEC (class remat_bb_data,
     516              :                            last_basic_block_for_fn (cfun));
     517      7031324 :   FOR_ALL_BB_FN (bb, cfun)
     518              :     {
     519      6847238 :       gcc_checking_assert (bb->index >= 0
     520              :                            && bb->index < last_basic_block_for_fn (cfun));
     521      6847238 :       bb_info = get_remat_bb_data (bb);
     522      6847238 :       bb_info->bb = bb;
     523      6847238 :       bitmap_initialize (&bb_info->changed_regs, &reg_obstack);
     524      6847238 :       bitmap_initialize (&bb_info->dead_regs, &reg_obstack);
     525      6847238 :       bitmap_initialize (&bb_info->gen_cands, &reg_obstack);
     526      6847238 :       bitmap_initialize (&bb_info->livein_cands, &reg_obstack);
     527      6847238 :       bitmap_initialize (&bb_info->pavin_cands, &reg_obstack);
     528      6847238 :       bitmap_initialize (&bb_info->pavout_cands, &reg_obstack);
     529      6847238 :       bitmap_initialize (&bb_info->avin_cands, &reg_obstack);
     530      6847238 :       bitmap_initialize (&bb_info->avout_cands, &reg_obstack);
     531              :     }
     532       184086 : }
     533              : 
     534              : /* Dump all candidates to DUMP_FILE.  */
     535              : static void
     536            1 : dump_cands (FILE *dump_file)
     537              : {
     538            1 :   int i;
     539            1 :   cand_t cand;
     540              : 
     541            1 :   fprintf (dump_file, "\nCands:\n");
     542            2 :   for (i = 0; i < (int) cands_num; i++)
     543              :     {
     544            0 :       cand = all_cands[i];
     545            0 :       fprintf (dump_file, "%d (nop=%d, remat_regno=%d, reload_regno=%d):\n",
     546              :                i, cand->nop, cand->regno, cand->reload_regno);
     547            0 :       print_inline_rtx (dump_file, cand->insn, 6);
     548            0 :       fprintf (dump_file, "\n");
     549              :     }
     550            1 : }
     551              : 
     552              : /* Dump all candidates and BB data.  */
     553              : static void
     554       184086 : dump_candidates_and_remat_bb_data (void)
     555              : {
     556       184086 :   basic_block bb;
     557              : 
     558       184086 :   if (lra_dump_file == NULL)
     559              :     return;
     560            1 :   dump_cands (lra_dump_file);
     561           43 :   FOR_EACH_BB_FN (bb, cfun)
     562              :     {
     563           42 :       fprintf (lra_dump_file, "\nBB %d:\n", bb->index);
     564              :       /* Livein */
     565           42 :       fprintf (lra_dump_file, "  register live in:");
     566           42 :       dump_regset (df_get_live_in (bb), lra_dump_file);
     567           42 :       putc ('\n', lra_dump_file);
     568              :       /* Liveout */
     569           42 :       fprintf (lra_dump_file, "  register live out:");
     570           42 :       dump_regset (df_get_live_out (bb), lra_dump_file);
     571           42 :       putc ('\n', lra_dump_file);
     572              :       /* Changed/dead regs: */
     573           42 :       fprintf (lra_dump_file, "  changed regs:");
     574           42 :       dump_regset (&get_remat_bb_data (bb)->changed_regs, lra_dump_file);
     575           42 :       putc ('\n', lra_dump_file);
     576           42 :       fprintf (lra_dump_file, "  dead regs:");
     577           42 :       dump_regset (&get_remat_bb_data (bb)->dead_regs, lra_dump_file);
     578           42 :       putc ('\n', lra_dump_file);
     579           42 :       lra_dump_bitmap_with_title ("cands generated in BB",
     580           42 :                                   &get_remat_bb_data (bb)->gen_cands, bb->index);
     581           42 :       lra_dump_bitmap_with_title ("livein cands in BB",
     582           42 :                                   &get_remat_bb_data (bb)->livein_cands, bb->index);
     583           42 :       lra_dump_bitmap_with_title ("pavin cands in BB",
     584           42 :                                   &get_remat_bb_data (bb)->pavin_cands, bb->index);
     585           42 :       lra_dump_bitmap_with_title ("pavout cands in BB",
     586           42 :                                   &get_remat_bb_data (bb)->pavout_cands, bb->index);
     587           42 :       lra_dump_bitmap_with_title ("avin cands in BB",
     588           42 :                                   &get_remat_bb_data (bb)->avin_cands, bb->index);
     589           42 :       lra_dump_bitmap_with_title ("avout cands in BB",
     590           42 :                                   &get_remat_bb_data (bb)->avout_cands, bb->index);
     591              :     }
     592            1 :   fprintf (lra_dump_file, "subreg regs:");
     593            1 :   dump_regset (&subreg_regs, lra_dump_file);
     594            1 :   putc ('\n', lra_dump_file);
     595              : }
     596              : 
     597              : /* Free all BB data.  */
     598              : static void
     599       184086 : finish_remat_bb_data (void)
     600              : {
     601       184086 :   basic_block bb;
     602              : 
     603      6663152 :   FOR_EACH_BB_FN (bb, cfun)
     604              :     {
     605      6479066 :       bitmap_clear (&get_remat_bb_data (bb)->avout_cands);
     606      6479066 :       bitmap_clear (&get_remat_bb_data (bb)->avin_cands);
     607      6479066 :       bitmap_clear (&get_remat_bb_data (bb)->pavout_cands);
     608      6479066 :       bitmap_clear (&get_remat_bb_data (bb)->pavin_cands);
     609      6479066 :       bitmap_clear (&get_remat_bb_data (bb)->livein_cands);
     610      6479066 :       bitmap_clear (&get_remat_bb_data (bb)->gen_cands);
     611      6479066 :       bitmap_clear (&get_remat_bb_data (bb)->dead_regs);
     612      6479066 :       bitmap_clear (&get_remat_bb_data (bb)->changed_regs);
     613              :     }
     614       184086 :   free (remat_bb_data);
     615       184086 : }
     616              : 
     617              : 
     618              : 
     619              : /* Update changed_regs, dead_regs, subreg_regs of BB from INSN.  */
     620              : static void
     621     42568196 : set_bb_regs (basic_block bb, rtx_insn *insn)
     622              : {
     623     42568196 :   lra_insn_recog_data_t id = lra_get_insn_recog_data (insn);
     624     42568196 :   remat_bb_data_t bb_info = get_remat_bb_data (bb);
     625     42568196 :   struct lra_insn_reg *reg;
     626              : 
     627    111195844 :   for (reg = id->regs; reg != NULL; reg = reg->next)
     628              :     {
     629     68627648 :       unsigned regno = reg->regno;
     630     68627648 :       if (reg->type != OP_IN)
     631     29411427 :         bitmap_set_bit (&bb_info->changed_regs, regno);
     632     39216221 :       else if (find_regno_note (insn, REG_DEAD, regno) != NULL)
     633     22043271 :         bitmap_set_bit (&bb_info->dead_regs, regno);
     634     68627648 :       if (regno >= FIRST_PSEUDO_REGISTER && reg->subreg_p)
     635       536926 :         bitmap_set_bit (&subreg_regs, regno);
     636              :     }
     637     42568196 :   if (CALL_P (insn))
     638              :     {
     639              :       /* Partially-clobbered registers might still be live.  */
     640      2512395 :       HARD_REG_SET clobbers = insn_callee_abi (insn).full_reg_clobbers ();
     641      2512395 :       bitmap_ior_into (&get_remat_bb_data (bb)->dead_regs,
     642      2512395 :                        bitmap_view<HARD_REG_SET> (clobbers));
     643              :     }
     644     42568196 : }
     645              : 
     646              : /* Calculate changed_regs and dead_regs for each BB.  */
     647              : static void
     648       184086 : calculate_local_reg_remat_bb_data (void)
     649              : {
     650       184086 :   basic_block bb;
     651       184086 :   rtx_insn *insn;
     652              : 
     653      6663152 :   FOR_EACH_BB_FN (bb, cfun)
     654     99633419 :     FOR_BB_INSNS (bb, insn)
     655     93154353 :       if (NONDEBUG_INSN_P (insn))
     656     42568196 :         set_bb_regs (bb, insn);
     657       184086 : }
     658              : 
     659              : 
     660              : 
     661              : /* Return true if REG overlaps an input operand or non-input hard register of
     662              :    INSN.  Basically the function returns false if we can move rematerialization
     663              :    candidate INSN through another insn with output REG or dead input REG (we
     664              :    consider it to avoid extending reg live range) with possible output pseudo
     665              :    renaming in INSN.  */
     666              : static bool
     667      4428014 : reg_overlap_for_remat_p (lra_insn_reg *reg, rtx_insn *insn)
     668              : {
     669      4428014 :   int iter;
     670      4428014 :   lra_insn_recog_data_t id = lra_get_insn_recog_data (insn);
     671      4428014 :   struct lra_static_insn_data *static_id = id->insn_static_data;
     672      4428014 :   unsigned regno = reg->regno;
     673      4428014 :   int nregs;
     674              : 
     675      4428014 :   if (regno >= FIRST_PSEUDO_REGISTER && reg_renumber[regno] >= 0)
     676      3109121 :     regno = reg_renumber[regno];
     677      3726118 :   if (regno >= FIRST_PSEUDO_REGISTER)
     678              :     nregs = 1;
     679              :   else
     680      3811017 :     nregs = hard_regno_nregs (regno, reg->biggest_mode);
     681              : 
     682      4428014 :   struct lra_insn_reg *reg2;
     683              : 
     684     12135426 :   for (iter = 0; iter < 2; iter++)
     685      8287749 :     for (reg2 = (iter == 0 ? id->regs : static_id->hard_regs);
     686     15188477 :          reg2 != NULL;
     687      6900728 :          reg2 = reg2->next)
     688              :       {
     689      7481065 :         int nregs2;
     690      7481065 :         unsigned regno2 = reg2->regno;
     691              : 
     692      7481065 :         if (reg2->type != OP_IN && regno2 >= FIRST_PSEUDO_REGISTER)
     693      4428014 :           continue;
     694              : 
     695      2971171 :         if (regno2 >= FIRST_PSEUDO_REGISTER && reg_renumber[regno2] >= 0)
     696      2971171 :           regno2 = reg_renumber[regno2];
     697      2971171 :         if (regno2 >= FIRST_PSEUDO_REGISTER)
     698              :           nregs2 = 1;
     699              :         else
     700      3053051 :           nregs2 = hard_regno_nregs (regno2, reg->biggest_mode);
     701              : 
     702      3053051 :         if ((regno2 + nregs2 - 1 >= regno && regno2 < regno + nregs)
     703      2472714 :             || (regno + nregs - 1 >= regno2 && regno < regno2 + nregs2))
     704              :           return true;
     705              :       }
     706              :   return false;
     707              : }
     708              : 
     709              : /* Return true if a call used register is an input operand of INSN.  */
     710              : static bool
     711        28572 : call_used_input_regno_present_p (const function_abi &abi, rtx_insn *insn)
     712              : {
     713        28572 :   int iter;
     714        28572 :   lra_insn_recog_data_t id = lra_get_insn_recog_data (insn);
     715        28572 :   struct lra_static_insn_data *static_id = id->insn_static_data;
     716        28572 :   struct lra_insn_reg *reg;
     717              : 
     718        85716 :   for (iter = 0; iter < 2; iter++)
     719        57144 :     for (reg = (iter == 0 ? id->regs : static_id->hard_regs);
     720       111116 :          reg != NULL;
     721        53972 :          reg = reg->next)
     722        53972 :       if (reg->type == OP_IN
     723        23818 :           && reg->regno < FIRST_PSEUDO_REGISTER
     724        53972 :           && abi.clobbers_reg_p (reg->biggest_mode, reg->regno))
     725              :         return true;
     726              :   return false;
     727              : }
     728              : 
     729              : /* Calculate livein_cands for each BB.  */
     730              : static void
     731       184086 : calculate_livein_cands (void)
     732              : {
     733       184086 :   basic_block bb;
     734              : 
     735      6663152 :   FOR_EACH_BB_FN (bb, cfun)
     736              :     {
     737      6479066 :       bitmap livein_regs = df_get_live_in (bb);
     738      6479066 :       bitmap livein_cands = &get_remat_bb_data (bb)->livein_cands;
     739     60135835 :       for (unsigned int i = 0; i < cands_num; i++)
     740              :         {
     741     53656769 :           cand_t cand = all_cands[i];
     742     53656769 :           lra_insn_recog_data_t id = lra_get_insn_recog_data (cand->insn);
     743     53656769 :           struct lra_insn_reg *reg;
     744              : 
     745    108142627 :           for (reg = id->regs; reg != NULL; reg = reg->next)
     746     90608466 :             if (reg->type == OP_IN && ! bitmap_bit_p (livein_regs, reg->regno))
     747              :               break;
     748     53656769 :           if (reg == NULL)
     749     17534161 :             bitmap_set_bit (livein_cands, i);
     750              :         }
     751              :     }
     752       184086 : }
     753              : 
     754              : /* Calculate gen_cands for each BB.  */
     755              : static void
     756       184086 : calculate_gen_cands (void)
     757              : {
     758       184086 :   basic_block bb;
     759       184086 :   bitmap gen_cands;
     760       184086 :   rtx_insn *insn;
     761              : 
     762      6663152 :   FOR_EACH_BB_FN (bb, cfun)
     763              :     {
     764      6479066 :       gen_cands = &get_remat_bb_data (bb)->gen_cands;
     765      6479066 :       auto_bitmap gen_insns (&reg_obstack);
     766     99633419 :       FOR_BB_INSNS (bb, insn)
     767     93154353 :         if (INSN_P (insn))
     768              :           {
     769     79758604 :             lra_insn_recog_data_t id = lra_get_insn_recog_data (insn);
     770     79758604 :             struct lra_static_insn_data *static_id = id->insn_static_data;
     771     79758604 :             struct lra_insn_reg *reg;
     772     79758604 :             unsigned int uid;
     773     79758604 :             bitmap_iterator bi;
     774     79758604 :             cand_t cand;
     775     79758604 :             rtx set;
     776     79758604 :             int iter;
     777     79758604 :             int src_regno = -1, dst_regno = -1;
     778              : 
     779     79758604 :             if ((set = single_set (insn)) != NULL
     780     79758604 :                 && REG_P (SET_SRC (set)) && REG_P (SET_DEST (set)))
     781              :               {
     782     12199898 :                 src_regno = REGNO (SET_SRC (set));
     783     12199898 :                 dst_regno = REGNO (SET_DEST (set));
     784              :               }
     785              : 
     786              :             /* Update gen_cands:  */
     787     79758604 :             bitmap_clear (&temp_bitmap);
     788    239275812 :             for (iter = 0; iter < 2; iter++)
     789    159517208 :               for (reg = (iter == 0 ? id->regs : static_id->hard_regs);
     790    247035100 :                    reg != NULL;
     791     87517892 :                    reg = reg->next)
     792     87517892 :                 if (reg->type != OP_IN
     793     87517892 :                     || find_regno_note (insn, REG_DEAD, reg->regno) != NULL)
     794     64133600 :                   EXECUTE_IF_SET_IN_BITMAP (gen_insns, 0, uid, bi)
     795              :                     {
     796      1984348 :                       rtx_insn *insn2 = lra_insn_recog_data[uid]->insn;
     797              : 
     798      1984348 :                       cand = insn_to_cand[INSN_UID (insn2)];
     799      1984348 :                       gcc_assert (cand != NULL);
     800              :                       /* Ignore the reload insn.  */
     801      1984348 :                       if (src_regno == cand->reload_regno
     802       812687 :                           && dst_regno == cand->regno)
     803        45309 :                         continue;
     804      1939039 :                       if (cand->regno == reg->regno
     805      1939039 :                           || reg_overlap_for_remat_p (reg, insn2))
     806              :                         {
     807       274175 :                           bitmap_clear_bit (gen_cands, cand->index);
     808       274175 :                           bitmap_set_bit (&temp_bitmap, uid);
     809              :                         }
     810              :                     }
     811              : 
     812     79758604 :             if (CALL_P (insn))
     813              :               {
     814      2512395 :                 function_abi callee_abi = insn_callee_abi (insn);
     815      2521281 :                 EXECUTE_IF_SET_IN_BITMAP (gen_insns, 0, uid, bi)
     816              :                   {
     817         8886 :                     rtx_insn *insn2 = lra_insn_recog_data[uid]->insn;
     818              : 
     819         8886 :                     cand = insn_to_cand[INSN_UID (insn2)];
     820         8886 :                     gcc_assert (cand != NULL);
     821         8886 :                     if (call_used_input_regno_present_p (callee_abi, insn2))
     822              :                       {
     823            0 :                         bitmap_clear_bit (gen_cands, cand->index);
     824            0 :                         bitmap_set_bit (&temp_bitmap, uid);
     825              :                       }
     826              :                   }
     827              :               }
     828     79758604 :             bitmap_and_compl_into (gen_insns, &temp_bitmap);
     829              : 
     830     79758604 :             cand = insn_to_cand[INSN_UID (insn)];
     831     79758604 :             if (cand != NULL)
     832              :               {
     833       323109 :                 bitmap_set_bit (gen_cands, cand->index);
     834       323109 :                 bitmap_set_bit (gen_insns, INSN_UID (insn));
     835              :               }
     836              :           }
     837      6479066 :     }
     838       184086 : }
     839              : 
     840              : 
     841              : 
     842              : /* The common transfer function used by the DF equation solver to
     843              :    propagate (partial) availability info BB_IN to BB_OUT through block
     844              :    with BB_INDEX according to the following equation:
     845              : 
     846              :       bb.out =  ((bb.in & bb.livein) - bb.killed) OR  bb.gen
     847              : */
     848              : static bool
     849     13906255 : cand_trans_fun (int bb_index, bitmap bb_in, bitmap bb_out)
     850              : {
     851     13906255 :   remat_bb_data_t bb_info;
     852     13906255 :   bitmap bb_livein, bb_changed_regs, bb_dead_regs;
     853     13906255 :   unsigned int cid;
     854     13906255 :   bitmap_iterator bi;
     855              : 
     856     13906255 :   bb_info = get_remat_bb_data_by_index (bb_index);
     857     13906255 :   bb_livein = &bb_info->livein_cands;
     858     13906255 :   bb_changed_regs = &bb_info->changed_regs;
     859     13906255 :   bb_dead_regs = &bb_info->dead_regs;
     860              :   /* Calculate killed avin cands -- cands whose regs are changed or
     861              :      becoming dead in the BB.  We calculate it here as we hope that
     862              :      repeated calculations are compensated by smaller size of BB_IN in
     863              :      comparison with all candidates number.  */
     864     13906255 :   bitmap_clear (&temp_bitmap);
     865     22353506 :   EXECUTE_IF_SET_IN_BITMAP (bb_in, 0, cid, bi)
     866              :     {
     867      8447251 :       cand_t cand = all_cands[cid];
     868      8447251 :       lra_insn_recog_data_t id = lra_get_insn_recog_data (cand->insn);
     869      8447251 :       struct lra_insn_reg *reg;
     870              : 
     871      8447251 :       if (! bitmap_bit_p (bb_livein, cid))
     872              :         {
     873       100673 :           bitmap_set_bit (&temp_bitmap, cid);
     874       100673 :           continue;
     875              :         }
     876     16801530 :       for (reg = id->regs; reg != NULL; reg = reg->next)
     877              :         /* Ignore all outputs which are not the regno for
     878              :            rematerialization.  */
     879      8662723 :         if (reg->type == OP_OUT && reg->regno != cand->regno)
     880       534069 :           continue;
     881      8128654 :         else if (bitmap_bit_p (bb_changed_regs, reg->regno)
     882      8128654 :                  || bitmap_bit_p (bb_dead_regs, reg->regno))
     883              :           {
     884       207771 :             bitmap_set_bit (&temp_bitmap, cid);
     885       207771 :             break;
     886              :           }
     887              :       /* Check regno for rematerialization.  */
     888      8346578 :       if (bitmap_bit_p (bb_changed_regs, cand->regno)
     889      8346578 :           || bitmap_bit_p (bb_dead_regs, cand->regno))
     890       166820 :         bitmap_set_bit (&temp_bitmap, cid);
     891              :     }
     892     13906255 :   return bitmap_ior_and_compl (bb_out,
     893     13906255 :                                &bb_info->gen_cands, bb_in, &temp_bitmap);
     894              : }
     895              : 
     896              : 
     897              : 
     898              : /* The transfer function used by the DF equation solver to propagate
     899              :    partial candidate availability info through block with BB_INDEX
     900              :    according to the following equation:
     901              : 
     902              :      bb.pavout = ((bb.pavin & bb.livein) - bb.killed) OR bb.gen
     903              : */
     904              : static bool
     905      7059017 : cand_pav_trans_fun (int bb_index)
     906              : {
     907      7059017 :   remat_bb_data_t bb_info;
     908              : 
     909      7059017 :   bb_info = get_remat_bb_data_by_index (bb_index);
     910      7059017 :   return cand_trans_fun (bb_index, &bb_info->pavin_cands,
     911      7059017 :                          &bb_info->pavout_cands);
     912              : }
     913              : 
     914              : /* The confluence function used by the DF equation solver to set up
     915              :    cand_pav info for a block BB without predecessor.  */
     916              : static void
     917       185306 : cand_pav_con_fun_0 (basic_block bb)
     918              : {
     919       185306 :   bitmap_clear (&get_remat_bb_data (bb)->pavin_cands);
     920       185306 : }
     921              : 
     922              : /* The confluence function used by the DF equation solver to propagate
     923              :    partial candidate availability info from predecessor to successor
     924              :    on edge E (pred->bb) according to the following equation:
     925              : 
     926              :       bb.pavin_cands = 0 for entry block | OR (pavout_cands of predecessors)
     927              :  */
     928              : static bool
     929     10185389 : cand_pav_con_fun_n (edge e)
     930              : {
     931     10185389 :   basic_block pred = e->src;
     932     10185389 :   basic_block bb = e->dest;
     933     10185389 :   remat_bb_data_t bb_info;
     934     10185389 :   bitmap bb_pavin, pred_pavout;
     935              : 
     936     10185389 :   bb_info = get_remat_bb_data (bb);
     937     10185389 :   bb_pavin = &bb_info->pavin_cands;
     938     10185389 :   pred_pavout = &get_remat_bb_data (pred)->pavout_cands;
     939     10185389 :   return bitmap_ior_into (bb_pavin, pred_pavout);
     940              : }
     941              : 
     942              : 
     943              : 
     944              : /* The transfer function used by the DF equation solver to propagate
     945              :    candidate availability info through block with BB_INDEX according
     946              :    to the following equation:
     947              : 
     948              :       bb.avout =  ((bb.avin & bb.livein) - bb.killed) OR  bb.gen
     949              : */
     950              : static bool
     951      6847238 : cand_av_trans_fun (int bb_index)
     952              : {
     953      6847238 :   remat_bb_data_t bb_info;
     954              : 
     955      6847238 :   bb_info = get_remat_bb_data_by_index (bb_index);
     956      6847238 :   return cand_trans_fun (bb_index, &bb_info->avin_cands,
     957      6847238 :                          &bb_info->avout_cands);
     958              : }
     959              : 
     960              : /* The confluence function used by the DF equation solver to set up
     961              :    cand_av info for a block BB without predecessor.  */
     962              : static void
     963       185306 : cand_av_con_fun_0 (basic_block bb)
     964              : {
     965       185306 :   bitmap_clear (&get_remat_bb_data (bb)->avin_cands);
     966       185306 : }
     967              : 
     968              : /* The confluence function used by the DF equation solver to propagate
     969              :    cand_av info from predecessor to successor on edge E (pred->bb)
     970              :    according to the following equation:
     971              : 
     972              :       bb.avin_cands = 0 for entry block | AND (avout_cands of predecessors)
     973              :  */
     974              : static bool
     975      9789577 : cand_av_con_fun_n (edge e)
     976              : {
     977      9789577 :   basic_block pred = e->src;
     978      9789577 :   basic_block bb = e->dest;
     979      9789577 :   remat_bb_data_t bb_info;
     980      9789577 :   bitmap bb_avin, pred_avout;
     981              : 
     982      9789577 :   bb_info = get_remat_bb_data (bb);
     983      9789577 :   bb_avin = &bb_info->avin_cands;
     984      9789577 :   pred_avout = &get_remat_bb_data (pred)->avout_cands;
     985      9789577 :   return bitmap_and_into (bb_avin, pred_avout);
     986              : }
     987              : 
     988              : /* Calculate available candidates for each BB.  */
     989              : static void
     990       184086 : calculate_global_remat_bb_data (void)
     991              : {
     992       184086 :   basic_block bb;
     993              : 
     994       184086 :   df_simple_dataflow
     995       184086 :     (DF_FORWARD, NULL, cand_pav_con_fun_0, cand_pav_con_fun_n,
     996              :      cand_pav_trans_fun, &all_blocks,
     997              :      df_get_postorder (DF_FORWARD), df_get_n_blocks (DF_FORWARD));
     998              :   /* Initialize avin by pavin.  */
     999      6663152 :   FOR_EACH_BB_FN (bb, cfun)
    1000      6479066 :     bitmap_copy (&get_remat_bb_data (bb)->avin_cands,
    1001      6479066 :                  &get_remat_bb_data (bb)->pavin_cands);
    1002       184086 :   df_simple_dataflow
    1003       184086 :     (DF_FORWARD, NULL, cand_av_con_fun_0, cand_av_con_fun_n,
    1004              :      cand_av_trans_fun, &all_blocks,
    1005              :      df_get_postorder (DF_FORWARD), df_get_n_blocks (DF_FORWARD));
    1006       184086 : }
    1007              : 
    1008              : 
    1009              : 
    1010              : /* Setup sp offset attribute to SP_OFFSET for all INSNS.  */
    1011              : static void
    1012           74 : change_sp_offset (rtx_insn *insns, poly_int64 sp_offset)
    1013              : {
    1014          148 :   for (rtx_insn *insn = insns; insn != NULL; insn = NEXT_INSN (insn))
    1015           74 :     eliminate_regs_in_insn (insn, false, false, sp_offset);
    1016           74 : }
    1017              : 
    1018              : /* Return start hard register of REG (can be a hard or a pseudo reg)
    1019              :    or -1 (if it is a spilled pseudo).  Return number of hard registers
    1020              :    occupied by REG through parameter NREGS if the start hard reg is
    1021              :    not negative.  */
    1022              : static int
    1023     51007049 : get_hard_regs (struct lra_insn_reg *reg, int &nregs)
    1024              : {
    1025     51007049 :   int regno = reg->regno;
    1026     51007049 :   int hard_regno = regno < FIRST_PSEUDO_REGISTER ? regno : reg_renumber[regno];
    1027              : 
    1028     51007049 :   if (hard_regno >= 0)
    1029     47919515 :     nregs = hard_regno_nregs (hard_regno, reg->biggest_mode);
    1030     51007049 :   return hard_regno;
    1031              : }
    1032              : 
    1033              : /* Make copy of and register scratch pseudos in rematerialized insn
    1034              :    REMAT_INSN.  */
    1035              : static void
    1036         2605 : update_scratch_ops (rtx_insn *remat_insn)
    1037              : {
    1038         2605 :   lra_insn_recog_data_t id = lra_get_insn_recog_data (remat_insn);
    1039         2605 :   struct lra_static_insn_data *static_id = id->insn_static_data;
    1040         8482 :   for (int i = 0; i < static_id->n_operands; i++)
    1041              :     {
    1042         5877 :       rtx *loc = id->operand_loc[i];
    1043         5877 :       if (! REG_P (*loc))
    1044         2180 :         continue;
    1045         3697 :       int regno = REGNO (*loc);
    1046         3697 :       if (! ira_former_scratch_p (regno))
    1047         3697 :         continue;
    1048            0 :       *loc = lra_create_new_reg (GET_MODE (*loc), *loc,
    1049              :                                  lra_get_allocno_class (regno), NULL,
    1050              :                                  "scratch pseudo copy");
    1051            0 :       ira_register_new_scratch_op (remat_insn, i, id->icode);
    1052              :     }
    1053              : 
    1054         2605 : }
    1055              : 
    1056              : /* Insert rematerialization insns using the data-flow data calculated
    1057              :    earlier.  */
    1058              : static bool
    1059       184086 : do_remat (void)
    1060              : {
    1061       184086 :   unsigned regno;
    1062       184086 :   rtx_insn *insn;
    1063       184086 :   basic_block bb;
    1064       184086 :   bool changed_p = false;
    1065              :   /* Living hard regs and hard registers of living pseudos.  */
    1066       184086 :   HARD_REG_SET live_hard_regs;
    1067       184086 :   bitmap_iterator bi;
    1068              : 
    1069       184086 :   auto_bitmap avail_cands (&reg_obstack);
    1070       184086 :   auto_bitmap active_cands (&reg_obstack);
    1071      6663152 :   FOR_EACH_BB_FN (bb, cfun)
    1072              :     {
    1073      6479066 :       CLEAR_HARD_REG_SET (live_hard_regs);
    1074     67588446 :       EXECUTE_IF_SET_IN_BITMAP (df_get_live_in (bb), 0, regno, bi)
    1075              :         {
    1076      8628515 :           int hard_regno = regno < FIRST_PSEUDO_REGISTER
    1077     61109380 :                            ? regno
    1078     52480865 :                            : reg_renumber[regno];
    1079     61109380 :           if (hard_regno >= 0)
    1080     34925947 :             SET_HARD_REG_BIT (live_hard_regs, hard_regno);
    1081              :         }
    1082      6479066 :       bitmap_and (avail_cands, &get_remat_bb_data (bb)->avin_cands,
    1083      6479066 :                   &get_remat_bb_data (bb)->livein_cands);
    1084              :       /* Activating insns are always in the same block as their corresponding
    1085              :          remat insn, so at the start of a block the two bitsets are equal.  */
    1086      6479066 :       bitmap_copy (active_cands, avail_cands);
    1087     99633419 :       FOR_BB_INSNS (bb, insn)
    1088              :         {
    1089     93154353 :           if (!NONDEBUG_INSN_P (insn))
    1090     50588762 :             continue;
    1091              : 
    1092     42568196 :           lra_insn_recog_data_t id = lra_get_insn_recog_data (insn);
    1093     42568196 :           struct lra_static_insn_data *static_id = id->insn_static_data;
    1094     42568196 :           struct lra_insn_reg *reg;
    1095     42568196 :           cand_t cand;
    1096     42568196 :           unsigned int cid;
    1097     42568196 :           bitmap_iterator bi;
    1098     42568196 :           rtx set;
    1099     42568196 :           int iter;
    1100     42568196 :           int src_regno = -1, dst_regno = -1;
    1101              : 
    1102     42568196 :           if ((set = single_set (insn)) != NULL
    1103     42568196 :               && REG_P (SET_SRC (set)) && REG_P (SET_DEST (set)))
    1104              :             {
    1105     12199898 :               src_regno = REGNO (SET_SRC (set));
    1106     12199898 :               dst_regno = REGNO (SET_DEST (set));
    1107              :             }
    1108              : 
    1109     42568196 :           cand = NULL;
    1110              :           /* Check possibility of rematerialization (hard reg or
    1111              :              unpsilled pseudo <- spilled pseudo): */
    1112     42568196 :           if (dst_regno >= 0 && src_regno >= FIRST_PSEUDO_REGISTER
    1113     10772715 :               && reg_renumber[src_regno] < 0
    1114      1810947 :               && (dst_regno < FIRST_PSEUDO_REGISTER
    1115      1649837 :                   || reg_renumber[dst_regno] >= 0))
    1116              :             {
    1117      1810941 :               for (cand = regno_cands[src_regno];
    1118      2412106 :                    cand != NULL;
    1119       601165 :                    cand = cand->next_regno_cand)
    1120       604525 :                 if (bitmap_bit_p (avail_cands, cand->index)
    1121       604525 :                     && bitmap_bit_p (active_cands, cand->index))
    1122              :                   break;
    1123              :             }
    1124      1810941 :           int i, hard_regno, nregs;
    1125      1810941 :           int dst_hard_regno, dst_nregs;
    1126      1810941 :           rtx_insn *remat_insn = NULL;
    1127      1810941 :           poly_int64 cand_sp_offset = 0;
    1128      1810941 :           if (cand != NULL)
    1129              :             {
    1130         3360 :               lra_insn_recog_data_t cand_id
    1131         3360 :                 = lra_get_insn_recog_data (cand->insn);
    1132         3360 :               struct lra_static_insn_data *static_cand_id
    1133              :                 = cand_id->insn_static_data;
    1134         3360 :               rtx saved_op = *cand_id->operand_loc[cand->nop];
    1135              : 
    1136              :               /* Check clobbers do not kill something living.  */
    1137         3360 :               gcc_assert (REG_P (saved_op));
    1138         3360 :               int ignore_regno = REGNO (saved_op);
    1139              : 
    1140         6465 :               dst_hard_regno = dst_regno < FIRST_PSEUDO_REGISTER
    1141         3360 :                 ? dst_regno : reg_renumber[dst_regno];
    1142         3360 :               gcc_assert (dst_hard_regno >= 0);
    1143         3360 :               machine_mode mode = GET_MODE (SET_DEST (set));
    1144         3360 :               dst_nregs = hard_regno_nregs (dst_hard_regno, mode);
    1145              : 
    1146         8840 :               for (reg = cand_id->regs; reg != NULL; reg = reg->next)
    1147         5480 :                 if (reg->type != OP_IN && reg->regno != ignore_regno)
    1148              :                   {
    1149            0 :                     hard_regno = get_hard_regs (reg, nregs);
    1150            0 :                     gcc_assert (hard_regno >= 0);
    1151            0 :                     for (i = 0; i < nregs; i++)
    1152            0 :                       if (TEST_HARD_REG_BIT (live_hard_regs, hard_regno + i))
    1153              :                         break;
    1154            0 :                     if (i < nregs)
    1155              :                       break;
    1156              :                     /* Ensure the clobber also doesn't overlap dst_regno.  */
    1157            0 :                     if (hard_regno + nregs > dst_hard_regno
    1158            0 :                         && hard_regno < dst_hard_regno + dst_nregs)
    1159              :                       break;
    1160              :                   }
    1161              : 
    1162         3360 :               if (reg == NULL)
    1163              :                 {
    1164         3360 :                   for (reg = static_cand_id->hard_regs;
    1165         3752 :                        reg != NULL;
    1166          392 :                        reg = reg->next)
    1167          392 :                     if (reg->type != OP_IN)
    1168              :                       {
    1169          392 :                         if (TEST_HARD_REG_BIT (live_hard_regs, reg->regno))
    1170              :                           break;
    1171          392 :                         if (reg->regno >= dst_hard_regno
    1172          371 :                             && reg->regno < dst_hard_regno + dst_nregs)
    1173              :                           break;
    1174              :                       }
    1175              :                 }
    1176              : 
    1177         3360 :               if (reg == NULL)
    1178              :                 {
    1179         3360 :                   *cand_id->operand_loc[cand->nop] = SET_DEST (set);
    1180         3360 :                   lra_update_insn_regno_info (cand->insn);
    1181         3360 :                   bool ok_p = lra_constrain_insn (cand->insn);
    1182         3360 :                   if (ok_p)
    1183              :                     {
    1184         2605 :                       rtx remat_pat = copy_insn (PATTERN (cand->insn));
    1185              : 
    1186         2605 :                       start_sequence ();
    1187         2605 :                       emit_insn (remat_pat);
    1188         2605 :                       remat_insn = end_sequence ();
    1189         2605 :                       if (recog_memoized (remat_insn) < 0)
    1190            0 :                         remat_insn = NULL;
    1191         2605 :                       cand_sp_offset = cand_id->sp_offset;
    1192              :                     }
    1193         3360 :                   *cand_id->operand_loc[cand->nop] = saved_op;
    1194         3360 :                   lra_update_insn_regno_info (cand->insn);
    1195              :                 }
    1196              :             }
    1197              : 
    1198     42568196 :           bitmap_clear (&temp_bitmap);
    1199              :           /* Update avail_cands (see analogous code for
    1200              :              calculate_gen_cands).  */
    1201    170272784 :           for (iter = 0; iter < 2; iter++)
    1202     85136392 :             for (reg = (iter == 0 ? id->regs : static_id->hard_regs);
    1203    164558348 :                  reg != NULL;
    1204     79421956 :                  reg = reg->next)
    1205     79421956 :               if (reg->type != OP_IN
    1206     79421956 :                   || find_regno_note (insn, REG_DEAD, reg->regno) != NULL)
    1207     64697510 :                 EXECUTE_IF_SET_IN_BITMAP (avail_cands, 0, cid, bi)
    1208              :                   {
    1209      2548258 :                     cand = all_cands[cid];
    1210              : 
    1211              :                     /* Ignore the reload insn.  */
    1212      2548258 :                     if (src_regno == cand->reload_regno
    1213      1106098 :                         && dst_regno == cand->regno)
    1214        45309 :                       continue;
    1215      2502949 :                     if (cand->regno == reg->regno
    1216      2502949 :                         || reg_overlap_for_remat_p (reg, cand->insn))
    1217       320136 :                       bitmap_set_bit (&temp_bitmap, cand->index);
    1218              :                   }
    1219              : 
    1220     42568196 :           if (CALL_P (insn))
    1221              :             {
    1222      2512395 :               function_abi callee_abi = insn_callee_abi (insn);
    1223      2532081 :               EXECUTE_IF_SET_IN_BITMAP (avail_cands, 0, cid, bi)
    1224              :                 {
    1225        19686 :                   cand = all_cands[cid];
    1226              : 
    1227        19686 :                   if (call_used_input_regno_present_p (callee_abi, cand->insn))
    1228            0 :                     bitmap_set_bit (&temp_bitmap, cand->index);
    1229              :                 }
    1230              :             }
    1231              : 
    1232     42568196 :           bitmap_and_compl_into (avail_cands, &temp_bitmap);
    1233              : 
    1234              :           /* Now see whether a candidate is made active or available
    1235              :              by this insn.  */
    1236     42568196 :           cand = insn_to_cand_activation[INSN_UID (insn)];
    1237     42568196 :           if (cand)
    1238        23945 :             bitmap_set_bit (active_cands, cand->index);
    1239              : 
    1240     42568196 :           cand = insn_to_cand[INSN_UID (insn)];
    1241     42568196 :           if (cand != NULL)
    1242              :             {
    1243       323109 :               bitmap_set_bit (avail_cands, cand->index);
    1244       323109 :               if (cand->reload_regno == -1)
    1245       299175 :                 bitmap_set_bit (active_cands, cand->index);
    1246              :               else
    1247        23934 :                 bitmap_clear_bit (active_cands, cand->index);
    1248              :             }
    1249              : 
    1250     42568196 :           if (remat_insn != NULL)
    1251              :             {
    1252         2605 :               poly_int64 sp_offset_change = cand_sp_offset - id->sp_offset;
    1253         2605 :               if (maybe_ne (sp_offset_change, 0))
    1254           74 :                 change_sp_offset (remat_insn, sp_offset_change);
    1255         2605 :               update_scratch_ops (remat_insn);
    1256         2605 :               lra_process_new_insns (insn, remat_insn, NULL,
    1257              :                                      "Inserting rematerialization insn");
    1258         2605 :               lra_set_insn_deleted (insn);
    1259         2605 :               changed_p = true;
    1260         2605 :               continue;
    1261         2605 :             }
    1262              : 
    1263              :           /* Update live hard regs: */
    1264    111188029 :           for (reg = id->regs; reg != NULL; reg = reg->next)
    1265     68622438 :             if (reg->type == OP_IN
    1266     68622438 :                 && find_regno_note (insn, REG_DEAD, reg->regno) != NULL)
    1267              :               {
    1268     22041135 :                 if ((hard_regno = get_hard_regs (reg, nregs)) < 0)
    1269      1336258 :                   continue;
    1270     41757327 :                 for (i = 0; i < nregs; i++)
    1271     21052450 :                   CLEAR_HARD_REG_BIT (live_hard_regs, hard_regno + i);
    1272              :               }
    1273              :           /* Process also hard regs (e.g. CC register) which are part
    1274              :              of insn definition.  */
    1275     53359899 :           for (reg = static_id->hard_regs; reg != NULL; reg = reg->next)
    1276     10794308 :             if (reg->type == OP_IN
    1277     10794308 :                 && find_regno_note (insn, REG_DEAD, reg->regno) != NULL)
    1278      3010213 :               CLEAR_HARD_REG_BIT (live_hard_regs, reg->regno);
    1279              :           /* Inputs have been processed, now process outputs.  */
    1280    111188029 :           for (reg = id->regs; reg != NULL; reg = reg->next)
    1281     68622438 :             if (reg->type != OP_IN
    1282     68622438 :                 && find_regno_note (insn, REG_UNUSED, reg->regno) == NULL)
    1283              :               {
    1284     28965914 :                 if ((hard_regno = get_hard_regs (reg, nregs)) < 0)
    1285      1751276 :                   continue;
    1286     55057823 :                 for (i = 0; i < nregs; i++)
    1287     27843185 :                   SET_HARD_REG_BIT (live_hard_regs, hard_regno + i);
    1288              :               }
    1289     53359899 :           for (reg = static_id->hard_regs; reg != NULL; reg = reg->next)
    1290     10794308 :             if (reg->type != OP_IN
    1291     10794308 :                 && find_regno_note (insn, REG_UNUSED, reg->regno) == NULL)
    1292      3145121 :               SET_HARD_REG_BIT (live_hard_regs, reg->regno);
    1293              :         }
    1294              :     }
    1295       184086 :   return changed_p;
    1296       184086 : }
    1297              : 
    1298              : 
    1299              : 
    1300              : /* Current number of rematerialization iteration.  */
    1301              : int lra_rematerialization_iter;
    1302              : 
    1303              : /* Entry point of the rematerialization sub-pass.  Return true if we
    1304              :    did any rematerialization.  */
    1305              : bool
    1306       198257 : lra_remat (void)
    1307              : {
    1308       198257 :   basic_block bb;
    1309       198257 :   bool result;
    1310       198257 :   int max_regno = max_reg_num ();
    1311              : 
    1312       198257 :   if (! flag_lra_remat)
    1313              :     return false;
    1314       184173 :   lra_rematerialization_iter++;
    1315       184173 :   if (lra_rematerialization_iter > LRA_MAX_REMATERIALIZATION_PASSES)
    1316              :     return false;
    1317       184086 :   if (lra_dump_file != NULL)
    1318            1 :     fprintf (lra_dump_file,
    1319              :              "\n******** Rematerialization #%d: ********\n\n",
    1320              :              lra_rematerialization_iter);
    1321       184086 :   timevar_push (TV_LRA_REMAT);
    1322       184086 :   insn_to_cand = XCNEWVEC (cand_t, get_max_uid ());
    1323       184086 :   insn_to_cand_activation = XCNEWVEC (cand_t, get_max_uid ());
    1324       184086 :   regno_cands = XCNEWVEC (cand_t, max_regno);
    1325       184086 :   all_cands.create (8000);
    1326       184086 :   initiate_cand_table ();
    1327       184086 :   create_remat_bb_data ();
    1328       184086 :   bitmap_initialize (&temp_bitmap, &reg_obstack);
    1329       184086 :   bitmap_initialize (&subreg_regs, &reg_obstack);
    1330       184086 :   calculate_local_reg_remat_bb_data ();
    1331       184086 :   create_cands ();
    1332       184086 :   calculate_livein_cands ();
    1333       184086 :   calculate_gen_cands ();
    1334       184086 :   bitmap_initialize (&all_blocks, &reg_obstack);
    1335      7031324 :   FOR_ALL_BB_FN (bb, cfun)
    1336      6847238 :     bitmap_set_bit (&all_blocks, bb->index);
    1337       184086 :   calculate_global_remat_bb_data ();
    1338       184086 :   dump_candidates_and_remat_bb_data ();
    1339       184086 :   result = do_remat ();
    1340       184086 :   if (result)
    1341         1839 :     lra_dump_insns_if_possible ("changed func after rematerialization");
    1342       184086 :   all_cands.release ();
    1343       184086 :   bitmap_clear (&temp_bitmap);
    1344       184086 :   bitmap_clear (&subreg_regs);
    1345       184086 :   finish_remat_bb_data ();
    1346       184086 :   finish_cand_table ();
    1347       184086 :   bitmap_clear (&all_blocks);
    1348       184086 :   free (regno_cands);
    1349       184086 :   free (insn_to_cand);
    1350       184086 :   free (insn_to_cand_activation);
    1351       184086 :   timevar_pop (TV_LRA_REMAT);
    1352       184086 :   return result;
    1353              : }
        

Generated by: LCOV version 2.4-beta

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