LCOV - code coverage report
Current view: top level - gcc - lra-spills.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 75.1 % 406 305
Test Date: 2026-02-28 14:20:25 Functions: 92.9 % 14 13
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /* Change pseudos by memory.
       2              :    Copyright (C) 2010-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              : 
      22              : /* This file contains code for a pass to change spilled pseudos into
      23              :    memory.
      24              : 
      25              :    The pass creates necessary stack slots and assigns spilled pseudos
      26              :    to the stack slots in following way:
      27              : 
      28              :    for all spilled pseudos P most frequently used first do
      29              :      for all stack slots S do
      30              :        if P doesn't conflict with pseudos assigned to S then
      31              :          assign S to P and goto to the next pseudo process
      32              :        end
      33              :      end
      34              :      create new stack slot S and assign P to S
      35              :    end
      36              : 
      37              :    The actual algorithm is bit more complicated because of different
      38              :    pseudo sizes.
      39              : 
      40              :    After that the code changes spilled pseudos (except ones created
      41              :    from scratches) by corresponding stack slot memory in RTL.
      42              : 
      43              :    If at least one stack slot was created, we need to run more passes
      44              :    because we have new addresses which should be checked and because
      45              :    the old address displacements might change and address constraints
      46              :    (or insn memory constraints) might not be satisfied any more.
      47              : 
      48              :    For some targets, the pass can spill some pseudos into hard
      49              :    registers of different class (usually into vector registers)
      50              :    instead of spilling them into memory if it is possible and
      51              :    profitable.  Spilling GENERAL_REGS pseudo into SSE registers for
      52              :    Intel Corei7 is an example of such optimization.  And this is
      53              :    actually recommended by Intel optimization guide.
      54              : 
      55              :    The file also contains code for final change of pseudos on hard
      56              :    regs correspondingly assigned to them.  */
      57              : 
      58              : #include "config.h"
      59              : #include "system.h"
      60              : #include "coretypes.h"
      61              : #include "backend.h"
      62              : #include "target.h"
      63              : #include "rtl.h"
      64              : #include "df.h"
      65              : #include "insn-config.h"
      66              : #include "regs.h"
      67              : #include "memmodel.h"
      68              : #include "ira.h"
      69              : #include "recog.h"
      70              : #include "output.h"
      71              : #include "cfgrtl.h"
      72              : #include "lra.h"
      73              : #include "lra-int.h"
      74              : 
      75              : 
      76              : /* Max regno at the start of the pass.  */
      77              : static int regs_num;
      78              : 
      79              : /* Map spilled regno -> hard regno used instead of memory for
      80              :    spilling.  */
      81              : static rtx *spill_hard_reg;
      82              : 
      83              : /* The structure describes stack slot of a spilled pseudo.  */
      84              : struct pseudo_slot
      85              : {
      86              :   /* Number (0, 1, ...) of the stack slot to which given pseudo
      87              :      belongs.  */
      88              :   int slot_num;
      89              :   /* First or next slot with the same slot number.  */
      90              :   struct pseudo_slot *next, *first;
      91              :   /* Memory representing the spilled pseudo.  */
      92              :   rtx mem;
      93              : };
      94              : 
      95              : /* The stack slots for each spilled pseudo.  Indexed by regnos.  */
      96              : static struct pseudo_slot *pseudo_slots;
      97              : 
      98              : /* The structure describes a register or a stack slot which can be
      99              :    used for several spilled pseudos.  */
     100              : class slot
     101              : {
     102              : public:
     103              :   /* First pseudo with given stack slot.  */
     104              :   int regno;
     105              :   /* Hard reg into which the slot pseudos are spilled.  The value is
     106              :      negative for pseudos spilled into memory.  */
     107              :   int hard_regno;
     108              :   /* Maximum alignment required by all users of the slot.  */
     109              :   unsigned int align;
     110              :   /* Maximum size required by all users of the slot.  */
     111              :   poly_int64 size;
     112              :   /* Memory representing the all stack slot.  It can be different from
     113              :      memory representing a pseudo belonging to give stack slot because
     114              :      pseudo can be placed in a part of the corresponding stack slot.
     115              :      The value is NULL for pseudos spilled into a hard reg.  */
     116              :   rtx mem;
     117              :   /* Combined live ranges of all pseudos belonging to given slot.  It
     118              :      is used to figure out that a new spilled pseudo can use given
     119              :      stack slot.  */
     120              :   lra_live_range_t live_ranges;
     121              : };
     122              : 
     123              : /* Array containing info about the stack slots.  The array element is
     124              :    indexed by the stack slot number in the range [0..slots_num).  */
     125              : static class slot *slots;
     126              : /* The number of the stack slots currently existing.  */
     127              : static int slots_num;
     128              : 
     129              : /* Set up memory of the spilled pseudo I.  The function can allocate
     130              :    the corresponding stack slot if it is not done yet.  */
     131              : static void
     132      1420453 : assign_mem_slot (int i)
     133              : {
     134      1420453 :   rtx x = NULL_RTX;
     135      1420453 :   machine_mode mode = GET_MODE (regno_reg_rtx[i]);
     136      2840906 :   poly_int64 inherent_size = PSEUDO_REGNO_BYTES (i);
     137      1420453 :   machine_mode wider_mode
     138      1420453 :     = wider_subreg_mode (mode, lra_reg_info[i].biggest_mode);
     139      2840906 :   poly_int64 total_size = GET_MODE_SIZE (wider_mode);
     140      1420453 :   poly_int64 adjust = 0;
     141              : 
     142      1420453 :   lra_assert (regno_reg_rtx[i] != NULL_RTX && REG_P (regno_reg_rtx[i])
     143              :               && lra_reg_info[i].nrefs != 0 && reg_renumber[i] < 0);
     144              : 
     145      1420453 :   unsigned int slot_num = pseudo_slots[i].slot_num;
     146      1420453 :   x = slots[slot_num].mem;
     147      1420453 :   if (!x)
     148              :     {
     149      1512928 :       x = assign_stack_local (BLKmode, slots[slot_num].size,
     150       756464 :                               slots[slot_num].align);
     151       756464 :       slots[slot_num].mem = x;
     152              :     }
     153              : 
     154              :   /* On a big endian machine, the "address" of the slot is the address
     155              :      of the low part that fits its inherent mode.  */
     156      1420453 :   adjust += subreg_size_lowpart_offset (inherent_size, total_size);
     157      1420453 :   x = adjust_address_nv (x, GET_MODE (regno_reg_rtx[i]), adjust);
     158              : 
     159              :   /* Set all of the memory attributes as appropriate for a spill.  */
     160      1420453 :   set_mem_attrs_for_spill (x);
     161      1420453 :   pseudo_slots[i].mem = x;
     162      1420453 : }
     163              : 
     164              : /* Sort pseudos according their usage frequencies.  */
     165              : static int
     166     30365621 : regno_freq_compare (const void *v1p, const void *v2p)
     167              : {
     168     30365621 :   const int regno1 = *(const int *) v1p;
     169     30365621 :   const int regno2 = *(const int *) v2p;
     170     30365621 :   int diff;
     171              : 
     172     30365621 :   if ((diff = lra_reg_info[regno2].freq - lra_reg_info[regno1].freq) != 0)
     173              :     return diff;
     174     12224679 :   return regno1 - regno2;
     175              : }
     176              : 
     177              : /* Sort pseudos according to their slots, putting the slots in the order
     178              :    that they should be allocated.
     179              : 
     180              :    First prefer to group slots with variable sizes together and slots
     181              :    with constant sizes together, since that usually makes them easier
     182              :    to address from a common anchor point.  E.g. loads of polynomial-sized
     183              :    registers tend to take polynomial offsets while loads of constant-sized
     184              :    registers tend to take constant (non-polynomial) offsets.
     185              : 
     186              :    Next, slots with lower numbers have the highest priority and should
     187              :    get the smallest displacement from the stack or frame pointer
     188              :    (whichever is being used).
     189              : 
     190              :    The first allocated slot is always closest to the frame pointer,
     191              :    so prefer lower slot numbers when frame_pointer_needed.  If the stack
     192              :    and frame grow in the same direction, then the first allocated slot is
     193              :    always closest to the initial stack pointer and furthest away from the
     194              :    final stack pointer, so allocate higher numbers first when using the
     195              :    stack pointer in that case.  The reverse is true if the stack and
     196              :    frame grow in opposite directions.  */
     197              : static int
     198     30848713 : pseudo_reg_slot_compare (const void *v1p, const void *v2p)
     199              : {
     200     30848713 :   const int regno1 = *(const int *) v1p;
     201     30848713 :   const int regno2 = *(const int *) v2p;
     202     30848713 :   int diff, slot_num1, slot_num2;
     203              : 
     204     30848713 :   slot_num1 = pseudo_slots[regno1].slot_num;
     205     30848713 :   slot_num2 = pseudo_slots[regno2].slot_num;
     206     30848713 :   diff = (int (slots[slot_num1].size.is_constant ())
     207     30848713 :           - int (slots[slot_num2].size.is_constant ()));
     208     30848713 :   if (diff != 0)
     209              :     return diff;
     210     30848713 :   if ((diff = slot_num1 - slot_num2) != 0)
     211     22762744 :     return (frame_pointer_needed
     212     22762744 :             || (!FRAME_GROWS_DOWNWARD) == STACK_GROWS_DOWNWARD ? diff : -diff);
     213     16171938 :   poly_int64 total_size1 = GET_MODE_SIZE (lra_reg_info[regno1].biggest_mode);
     214     16171938 :   poly_int64 total_size2 = GET_MODE_SIZE (lra_reg_info[regno2].biggest_mode);
     215      8085969 :   if ((diff = compare_sizes_for_sort (total_size2, total_size1)) != 0)
     216      1490891 :     return diff;
     217      6595078 :   return regno1 - regno2;
     218              : }
     219              : 
     220              : /* Assign spill hard registers to N pseudos in PSEUDO_REGNOS which is
     221              :    sorted in order of highest frequency first.  Put the pseudos which
     222              :    did not get a spill hard register at the beginning of array
     223              :    PSEUDO_REGNOS.  Return the number of such pseudos.  */
     224              : static int
     225       197959 : assign_spill_hard_regs (int *pseudo_regnos, int n)
     226              : {
     227       197959 :   int i, k, p, regno, res, spill_class_size, hard_regno, nr;
     228       197959 :   enum reg_class rclass, spill_class;
     229       197959 :   machine_mode mode;
     230       197959 :   lra_live_range_t r;
     231       197959 :   rtx_insn *insn;
     232       197959 :   rtx set;
     233       197959 :   basic_block bb;
     234       197959 :   HARD_REG_SET conflict_hard_regs;
     235       197959 :   bitmap setjump_crosses = regstat_get_setjmp_crosses ();
     236              :   /* Hard registers which cannot be used for any purpose at given
     237              :      program point because they are unallocatable or already allocated
     238              :      for other pseudos.  */
     239       197959 :   HARD_REG_SET *reserved_hard_regs;
     240              : 
     241       197959 :   if (! lra_reg_spill_p)
     242              :     return n;
     243              :   /* Set up reserved hard regs for every program point.  */
     244            0 :   reserved_hard_regs = XNEWVEC (HARD_REG_SET, lra_live_max_point);
     245            0 :   for (p = 0; p < lra_live_max_point; p++)
     246            0 :     reserved_hard_regs[p] = lra_no_alloc_regs;
     247            0 :   for (i = FIRST_PSEUDO_REGISTER; i < regs_num; i++)
     248            0 :     if (lra_reg_info[i].nrefs != 0
     249            0 :         && (hard_regno = lra_get_regno_hard_regno (i)) >= 0)
     250            0 :       for (r = lra_reg_info[i].live_ranges; r != NULL; r = r->next)
     251            0 :         for (p = r->start; p <= r->finish; p++)
     252            0 :           add_to_hard_reg_set (&reserved_hard_regs[p],
     253              :                                lra_reg_info[i].biggest_mode, hard_regno);
     254            0 :   auto_bitmap ok_insn_bitmap (&reg_obstack);
     255            0 :   FOR_EACH_BB_FN (bb, cfun)
     256            0 :     FOR_BB_INSNS (bb, insn)
     257            0 :       if (DEBUG_INSN_P (insn)
     258            0 :           || ((set = single_set (insn)) != NULL_RTX
     259            0 :               && REG_P (SET_SRC (set)) && REG_P (SET_DEST (set))))
     260            0 :         bitmap_set_bit (ok_insn_bitmap, INSN_UID (insn));
     261            0 :   for (res = i = 0; i < n; i++)
     262              :     {
     263            0 :       regno = pseudo_regnos[i];
     264            0 :       gcc_assert (lra_reg_info[regno].live_ranges);
     265            0 :       rclass = lra_get_allocno_class (regno);
     266            0 :       if (bitmap_bit_p (setjump_crosses, regno)
     267            0 :           || (spill_class
     268            0 :               = ((enum reg_class)
     269            0 :                  targetm.spill_class ((reg_class_t) rclass,
     270            0 :                                       PSEUDO_REGNO_MODE (regno)))) == NO_REGS
     271            0 :           || bitmap_intersect_compl_p (&lra_reg_info[regno].insn_bitmap,
     272            0 :                                        ok_insn_bitmap))
     273              :         {
     274            0 :           pseudo_regnos[res++] = regno;
     275            0 :           continue;
     276              :         }
     277            0 :       lra_assert (spill_class != NO_REGS);
     278            0 :       conflict_hard_regs = lra_reg_info[regno].conflict_hard_regs;
     279            0 :       for (r = lra_reg_info[regno].live_ranges; r != NULL; r = r->next)
     280            0 :         for (p = r->start; p <= r->finish; p++)
     281            0 :           conflict_hard_regs |= reserved_hard_regs[p];
     282            0 :       spill_class_size = ira_class_hard_regs_num[spill_class];
     283            0 :       mode = lra_reg_info[regno].biggest_mode;
     284            0 :       for (k = 0; k < spill_class_size; k++)
     285              :         {
     286            0 :           hard_regno = ira_class_hard_regs[spill_class][k];
     287            0 :           if (TEST_HARD_REG_BIT (eliminable_regset, hard_regno)
     288            0 :               || !targetm.hard_regno_mode_ok (hard_regno, mode))
     289            0 :             continue;
     290            0 :           if (! overlaps_hard_reg_set_p (conflict_hard_regs, mode, hard_regno))
     291              :             break;
     292              :         }
     293            0 :       if (k >= spill_class_size)
     294              :         {
     295              :            /* There is no available regs -- assign memory later.  */
     296            0 :           pseudo_regnos[res++] = regno;
     297            0 :           continue;
     298              :         }
     299            0 :       if (lra_dump_file != NULL)
     300            0 :         fprintf (lra_dump_file, "  Spill r%d into hr%d\n", regno, hard_regno);
     301            0 :       add_to_hard_reg_set (&hard_regs_spilled_into,
     302            0 :                            lra_reg_info[regno].biggest_mode, hard_regno);
     303              :       /* Update reserved_hard_regs.  */
     304            0 :       for (r = lra_reg_info[regno].live_ranges; r != NULL; r = r->next)
     305            0 :         for (p = r->start; p <= r->finish; p++)
     306            0 :           add_to_hard_reg_set (&reserved_hard_regs[p],
     307              :                                lra_reg_info[regno].biggest_mode, hard_regno);
     308            0 :       spill_hard_reg[regno]
     309            0 :         = gen_raw_REG (PSEUDO_REGNO_MODE (regno), hard_regno);
     310            0 :       for (nr = 0;
     311            0 :            nr < hard_regno_nregs (hard_regno,
     312            0 :                                   lra_reg_info[regno].biggest_mode);
     313              :            nr++)
     314              :         /* Just loop.  */
     315            0 :         df_set_regs_ever_live (hard_regno + nr, true);
     316              :     }
     317            0 :   free (reserved_hard_regs);
     318            0 :   return res;
     319            0 : }
     320              : 
     321              : /* Add pseudo REGNO to slot SLOT_NUM.  */
     322              : static void
     323      1420453 : add_pseudo_to_slot (int regno, int slot_num)
     324              : {
     325      1420453 :   struct pseudo_slot *first;
     326              : 
     327              :   /* Each pseudo has an inherent size which comes from its own mode,
     328              :      and a total size which provides room for paradoxical subregs.
     329              :      We need to make sure the size and alignment of the slot are
     330              :      sufficient for both.  */
     331      2840906 :   machine_mode mode = wider_subreg_mode (PSEUDO_REGNO_MODE (regno),
     332      1420453 :                                          lra_reg_info[regno].biggest_mode);
     333      1420453 :   unsigned int align = spill_slot_alignment (mode);
     334      1420453 :   slots[slot_num].align = MAX (slots[slot_num].align, align);
     335      1420453 :   slots[slot_num].size = upper_bound (slots[slot_num].size,
     336      1420453 :                                       GET_MODE_SIZE (mode));
     337              : 
     338      1420453 :   if (slots[slot_num].regno < 0)
     339              :     {
     340              :       /* It is the first pseudo in the slot.  */
     341       756464 :       slots[slot_num].regno = regno;
     342       756464 :       pseudo_slots[regno].first = &pseudo_slots[regno];
     343       756464 :       pseudo_slots[regno].next = NULL;
     344              :     }
     345              :   else
     346              :     {
     347       663989 :       first = pseudo_slots[regno].first = &pseudo_slots[slots[slot_num].regno];
     348       663989 :       pseudo_slots[regno].next = first->next;
     349       663989 :       first->next = &pseudo_slots[regno];
     350       663989 :       lra_assert (slots[slot_num].live_ranges);
     351              :     }
     352      1420453 :   pseudo_slots[regno].mem = NULL_RTX;
     353      1420453 :   pseudo_slots[regno].slot_num = slot_num;
     354              : 
     355              :   /* Pseudos with empty ranges shouldn't need to be spilled; if we get
     356              :      an empty range added to a slot, something fishy is going on, such
     357              :      as missing live range information, and without that information
     358              :      we may generate wrong code.  We can probably relax this to an
     359              :      lra_assert at some point.  Likewise the analogous one in
     360              :      assign_spill_hard_regs.  */
     361      1420453 :   gcc_assert (lra_reg_info[regno].live_ranges);
     362              : 
     363      1420453 :   slots[slot_num].live_ranges
     364      1420453 :     = lra_merge_live_ranges (slots[slot_num].live_ranges,
     365              :                              lra_copy_live_range_list
     366              :                              (lra_reg_info[regno].live_ranges));
     367      1420453 : }
     368              : 
     369              : /* Recompute the combined live ranges of pseudos assigned to stack
     370              :    slots.  This brings the live ranges of slots back in sync with
     371              :    those of pseudos, after recomputing live ranges for pseudos.  */
     372              : void
     373            0 : lra_recompute_slots_live_ranges (void)
     374              : {
     375            0 :   for (int i = 0; i < slots_num; i++)
     376              :     {
     377            0 :       if (slots[i].regno < 0)
     378            0 :         continue;
     379            0 :       lra_reset_live_range_list (slots[i].live_ranges);
     380            0 :       for (struct pseudo_slot *next = pseudo_slots[slots[i].regno].first;
     381            0 :            next; next = next->next)
     382              :         {
     383            0 :           int regno = next - pseudo_slots;
     384            0 :           lra_assert (!(lra_intersected_live_ranges_p
     385              :                         (lra_reg_info[regno].live_ranges,
     386              :                          slots[i].live_ranges)));
     387            0 :           slots[i].live_ranges
     388            0 :             = lra_merge_live_ranges (slots[i].live_ranges,
     389              :                                      lra_copy_live_range_list
     390            0 :                                      (lra_reg_info[regno].live_ranges));
     391              :         }
     392              :     }
     393            0 : }
     394              : 
     395              : /* Assign stack slot numbers to pseudos in array PSEUDO_REGNOS of
     396              :    length N.  Sort pseudos in PSEUDO_REGNOS for subsequent assigning
     397              :    memory stack slots.  */
     398              : static void
     399       197959 : assign_stack_slot_num_and_sort_pseudos (int *pseudo_regnos, int n)
     400              : {
     401       197959 :   int i, j, regno;
     402              : 
     403              :   /* Assign stack slot numbers to spilled pseudos, use smaller numbers
     404              :      for most frequently used pseudos.  */
     405      1618412 :   for (i = 0; i < n; i++)
     406              :     {
     407      1420453 :       regno = pseudo_regnos[i];
     408      1420453 :       if (! flag_ira_share_spill_slots)
     409        27608 :         j = slots_num;
     410              :       else
     411              :         {
     412      1392845 :           machine_mode mode
     413      2785690 :             = wider_subreg_mode (PSEUDO_REGNO_MODE (regno),
     414      1392845 :                                  lra_reg_info[regno].biggest_mode);
     415     26636867 :           for (j = 0; j < slots_num; j++)
     416     25908011 :             if (slots[j].hard_regno < 0
     417              :                 /* Although it's possible to share slots between modes
     418              :                    with constant and non-constant widths, we usually
     419              :                    get better spill code by keeping the constant and
     420              :                    non-constant areas separate.  */
     421     25908011 :                 && (GET_MODE_SIZE (mode).is_constant ()
     422              :                     == slots[j].size.is_constant ())
     423     51816022 :                 && ! (lra_intersected_live_ranges_p
     424     25908011 :                       (slots[j].live_ranges,
     425     25908011 :                        lra_reg_info[regno].live_ranges)))
     426              :               {
     427              :                 /* A slot without allocated memory can be shared.  */
     428       663989 :                 if (slots[j].mem == NULL_RTX)
     429              :                   break;
     430              : 
     431              :                 /* A slot with allocated memory can be shared only with equal
     432              :                    or smaller register with equal or smaller alignment.  */
     433            0 :                 if (slots[j].align >= spill_slot_alignment (mode)
     434            0 :                     && known_ge (slots[j].size, GET_MODE_SIZE (mode)))
     435              :                   break;
     436              :               }
     437              :         }
     438      1420453 :       if (j >= slots_num)
     439              :         {
     440              :           /* New slot.  */
     441       756464 :           slots[j].live_ranges = NULL;
     442       756464 :           slots[j].size = 0;
     443       756464 :           slots[j].align = BITS_PER_UNIT;
     444       756464 :           slots[j].regno = slots[j].hard_regno = -1;
     445       756464 :           slots[j].mem = NULL_RTX;
     446       756464 :           slots_num++;
     447              :         }
     448      1420453 :       add_pseudo_to_slot (regno, j);
     449              :     }
     450              :   /* Sort regnos according to their slot numbers.  */
     451       197959 :   qsort (pseudo_regnos, n, sizeof (int), pseudo_reg_slot_compare);
     452       197959 : }
     453              : 
     454              : /* Recursively process LOC in INSN and change spilled pseudos to the
     455              :    corresponding memory or spilled hard reg.  Ignore spilled pseudos
     456              :    created from the scratches.  Return true if the pseudo nrefs equal
     457              :    to 0 (don't change the pseudo in this case).  Otherwise return false.  */
     458              : static bool
     459     36774815 : remove_pseudos (rtx *loc, rtx_insn *insn)
     460              : {
     461     36774815 :   int i;
     462     36774815 :   rtx hard_reg;
     463     36774815 :   const char *fmt;
     464     36774815 :   enum rtx_code code;
     465     36774815 :   bool res = false;
     466              : 
     467     36774815 :   if (*loc == NULL_RTX)
     468              :     return res;
     469     33990581 :   code = GET_CODE (*loc);
     470     33990581 :   if (code == SUBREG && REG_P (SUBREG_REG (*loc)))
     471              :     {
     472              :       /* Try to remove memory subregs to simplify LRA job
     473              :          and avoid LRA cycling in case of subreg memory reload.  */
     474       270649 :       res = remove_pseudos (&SUBREG_REG (*loc), insn);
     475       270649 :       if (GET_CODE (SUBREG_REG (*loc)) == MEM)
     476              :         {
     477       208913 :           alter_subreg (loc, false);
     478       208913 :           if (GET_CODE (*loc) == MEM)
     479              :             {
     480       208913 :               lra_update_insn_recog_data (insn);
     481       208913 :               if (lra_dump_file != NULL)
     482            1 :                 fprintf (lra_dump_file,
     483              :                          "Memory subreg was simplified in insn #%u\n",
     484            1 :                          INSN_UID (insn));
     485              :             }
     486              :         }
     487       270649 :       return res;
     488              :     }
     489     15107141 :   else if (code == REG && (i = REGNO (*loc)) >= FIRST_PSEUDO_REGISTER
     490      8720217 :       && lra_get_regno_hard_regno (i) < 0
     491              :       /* We do not want to assign memory for former scratches because
     492              :          it might result in an address reload for some targets.  In
     493              :          any case we transform such pseudos not getting hard registers
     494              :          into scratches back.  */
     495     38677656 :       && ! ira_former_scratch_p (i))
     496              :     {
     497      4957724 :       if (lra_reg_info[i].nrefs == 0
     498        23057 :           && pseudo_slots[i].mem == NULL && spill_hard_reg[i] == NULL)
     499              :         return true;
     500      4957724 :       if ((hard_reg = spill_hard_reg[i]) != NULL_RTX)
     501            0 :         *loc = copy_rtx (hard_reg);
     502      4957724 :       else if (pseudo_slots[i].mem != NULL_RTX)
     503              :         /* There might be no memory slot or hard reg for a pseudo when we spill
     504              :            the frame pointer after elimination of frame pointer to stack
     505              :            pointer became impossible.  */
     506              :         {
     507      9915448 :           rtx x = lra_eliminate_regs_1 (insn, pseudo_slots[i].mem,
     508      4957724 :                                         GET_MODE (pseudo_slots[i].mem),
     509              :                                         false, false, 0, true);
     510      4957724 :           *loc = x != pseudo_slots[i].mem ? x : copy_rtx (x);
     511              :         }
     512      4957724 :       return res;
     513              :     }
     514              : 
     515     28762208 :   fmt = GET_RTX_FORMAT (code);
     516     69600318 :   for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
     517              :     {
     518     40838110 :       if (fmt[i] == 'e')
     519     28622370 :         res = remove_pseudos (&XEXP (*loc, i), insn) || res;
     520     12215740 :       else if (fmt[i] == 'E')
     521              :         {
     522       100507 :           int j;
     523              : 
     524       312719 :           for (j = XVECLEN (*loc, i) - 1; j >= 0; j--)
     525       212212 :             res = remove_pseudos (&XVECEXP (*loc, i, j), insn) || res;
     526              :         }
     527              :     }
     528              :   return res;
     529              : }
     530              : 
     531              : /* Convert spilled pseudos into their stack slots or spill hard regs,
     532              :    put insns to process on the constraint stack (that is all insns in
     533              :    which pseudos were changed to memory or spill hard regs).   */
     534              : static void
     535       197959 : spill_pseudos (void)
     536              : {
     537       197959 :   basic_block bb;
     538       197959 :   rtx_insn *insn, *curr;
     539       197959 :   int i;
     540              : 
     541       197959 :   auto_bitmap spilled_pseudos (&reg_obstack);
     542       197959 :   auto_bitmap changed_insns (&reg_obstack);
     543     35664544 :   for (i = FIRST_PSEUDO_REGISTER; i < regs_num; i++)
     544              :     {
     545     18301140 :       if (lra_reg_info[i].nrefs != 0 && lra_get_regno_hard_regno (i) < 0
     546     36890303 :           && ! ira_former_scratch_p (i))
     547              :         {
     548      1420453 :           bitmap_set_bit (spilled_pseudos, i);
     549      1420453 :           bitmap_ior_into (changed_insns, &lra_reg_info[i].insn_bitmap);
     550              :         }
     551              :     }
     552      7192151 :   FOR_EACH_BB_FN (bb, cfun)
     553              :     {
     554    211880852 :       FOR_BB_INSNS_SAFE (bb, insn, curr)
     555              :         {
     556     98946234 :           bool removed_pseudo_p = false;
     557              : 
     558     98946234 :           if (bitmap_bit_p (changed_insns, INSN_UID (insn)))
     559              :             {
     560      4885350 :               rtx *link_loc, link;
     561              : 
     562      4885350 :               removed_pseudo_p = remove_pseudos (&PATTERN (insn), insn);
     563      4885350 :               if (CALL_P (insn)
     564      4885350 :                   && remove_pseudos (&CALL_INSN_FUNCTION_USAGE (insn), insn))
     565              :                 removed_pseudo_p = true;
     566      4885350 :               for (link_loc = &REG_NOTES (insn);
     567      8216989 :                    (link = *link_loc) != NULL_RTX;
     568      3331639 :                    link_loc = &XEXP (link, 1))
     569              :                 {
     570      3331639 :                   switch (REG_NOTE_KIND (link))
     571              :                     {
     572            0 :                     case REG_FRAME_RELATED_EXPR:
     573            0 :                     case REG_CFA_DEF_CFA:
     574            0 :                     case REG_CFA_ADJUST_CFA:
     575            0 :                     case REG_CFA_OFFSET:
     576            0 :                     case REG_CFA_REGISTER:
     577            0 :                     case REG_CFA_EXPRESSION:
     578            0 :                     case REG_CFA_RESTORE:
     579            0 :                     case REG_CFA_SET_VDRAP:
     580            0 :                       if (remove_pseudos (&XEXP (link, 0), insn))
     581      3331639 :                         removed_pseudo_p = true;
     582              :                       break;
     583              :                     default:
     584              :                       break;
     585              :                     }
     586              :                 }
     587      4885350 :               if (GET_CODE (PATTERN (insn)) == CLOBBER)
     588              :                 /* This is a CLOBBER insn with pseudo spilled to memory.
     589              :                    Mark it for removing it later together with LRA temporary
     590              :                    CLOBBER insns.  */
     591         7076 :                 LRA_TEMP_CLOBBER_P (PATTERN (insn)) = 1;
     592      4885350 :               if (lra_dump_file != NULL)
     593            4 :                 fprintf (lra_dump_file,
     594              :                          "Changing spilled pseudos to memory in insn #%u\n",
     595            4 :                          INSN_UID (insn));
     596      4885350 :               lra_push_insn_and_update_insn_regno_info (insn);
     597      4885350 :               if (lra_reg_spill_p || targetm.different_addr_displacement_p ())
     598            0 :                 lra_set_used_insn_alternative (insn, LRA_UNKNOWN_ALT);
     599              :             }
     600     94060884 :           else if (CALL_P (insn)
     601              :                    /* Presence of any pseudo in CALL_INSN_FUNCTION_USAGE
     602              :                       does not affect value of insn_bitmap of the
     603              :                       corresponding lra_reg_info.  That is because we
     604              :                       don't need to reload pseudos in
     605              :                       CALL_INSN_FUNCTION_USAGEs.  So if we process only
     606              :                       insns in the insn_bitmap of given pseudo here, we
     607              :                       can miss the pseudo in some
     608              :                       CALL_INSN_FUNCTION_USAGEs.  */
     609     94060884 :                    && remove_pseudos (&CALL_INSN_FUNCTION_USAGE (insn), insn))
     610              :             removed_pseudo_p = true;
     611      4885350 :           if (removed_pseudo_p)
     612              :             {
     613            0 :               lra_assert (DEBUG_INSN_P (insn));
     614            0 :               lra_invalidate_insn_data (insn);
     615            0 :               INSN_VAR_LOCATION_LOC (insn) = gen_rtx_UNKNOWN_VAR_LOC ();
     616            0 :               if (lra_dump_file != NULL)
     617            0 :                 fprintf (lra_dump_file,
     618              :                          "Debug insn #%u is reset because it referenced "
     619            0 :                          "removed pseudo\n", INSN_UID (insn));
     620              :             }
     621     98946234 :           bitmap_and_compl_into (df_get_live_in (bb), spilled_pseudos);
     622     98946234 :           bitmap_and_compl_into (df_get_live_out (bb), spilled_pseudos);
     623              :         }
     624              :     }
     625       197959 : }
     626              : 
     627              : /* Return true if we need scratch reg assignments.  */
     628              : bool
     629          298 : lra_need_for_scratch_reg_p (void)
     630              : {
     631          298 :   int i; max_regno = max_reg_num ();
     632              : 
     633        10046 :   for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++)
     634         2515 :     if (lra_reg_info[i].nrefs != 0 && lra_get_regno_hard_regno (i) < 0
     635         9748 :         && ira_former_scratch_p (i))
     636              :       return true;
     637              :   return false;
     638              : }
     639              : 
     640              : /* Return true if we need to change some pseudos into memory.  */
     641              : bool
     642      1671160 : lra_need_for_spills_p (void)
     643              : {
     644      1671160 :   int i;
     645              : 
     646      1671160 :   max_regno = max_reg_num ();
     647     89488378 :   for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++)
     648     39888007 :     if (lra_reg_info[i].nrefs != 0 && lra_get_regno_hard_regno (i) < 0
     649     88222322 :         && ! ira_former_scratch_p (i))
     650              :       return true;
     651              :   return false;
     652              : }
     653              : 
     654              : /* Change spilled pseudos into memory or spill hard regs.  Put changed
     655              :    insns on the constraint stack (these insns will be considered on
     656              :    the next constraint pass).  The changed insns are all insns in
     657              :    which pseudos were changed.  */
     658              : void
     659       197959 : lra_spill (void)
     660              : {
     661       197959 :   int i, n, n2, curr_regno;
     662       197959 :   int *pseudo_regnos;
     663              : 
     664       197959 :   regs_num = max_reg_num ();
     665       197959 :   spill_hard_reg = XNEWVEC (rtx, regs_num);
     666       197959 :   pseudo_regnos = XNEWVEC (int, regs_num);
     667     35862503 :   for (n = 0, i = FIRST_PSEUDO_REGISTER; i < regs_num; i++)
     668     18301140 :     if (lra_reg_info[i].nrefs != 0 && lra_get_regno_hard_regno (i) < 0
     669              :         /* We do not want to assign memory for former scratches.  */
     670     36890303 :         && ! ira_former_scratch_p (i))
     671      1420453 :       pseudo_regnos[n++] = i;
     672       197959 :   lra_assert (n > 0);
     673       197959 :   pseudo_slots = XNEWVEC (struct pseudo_slot, regs_num);
     674     35664544 :   for (i = FIRST_PSEUDO_REGISTER; i < regs_num; i++)
     675              :     {
     676     35466585 :       spill_hard_reg[i] = NULL_RTX;
     677     35466585 :       pseudo_slots[i].mem = NULL_RTX;
     678              :     }
     679       197959 :   slots = XNEWVEC (class slot, regs_num);
     680              :   /* Sort regnos according their usage frequencies.  */
     681       197959 :   qsort (pseudo_regnos, n, sizeof (int), regno_freq_compare);
     682       197959 :   n = assign_spill_hard_regs (pseudo_regnos, n);
     683       197959 :   slots_num = 0;
     684       197959 :   assign_stack_slot_num_and_sort_pseudos (pseudo_regnos, n);
     685      1816371 :   for (i = 0; i < n; i++)
     686      1420453 :     if (pseudo_slots[pseudo_regnos[i]].mem == NULL_RTX)
     687      1420453 :       assign_mem_slot (pseudo_regnos[i]);
     688       197959 :   if ((n2 = lra_update_fp2sp_elimination (pseudo_regnos)) > 0)
     689              :     {
     690              :       /* Assign stack slots to spilled pseudos assigned to fp.  */
     691            0 :       assign_stack_slot_num_and_sort_pseudos (pseudo_regnos, n2);
     692            0 :       for (i = 0; i < n2; i++)
     693            0 :         if (pseudo_slots[pseudo_regnos[i]].mem == NULL_RTX)
     694            0 :           assign_mem_slot (pseudo_regnos[i]);
     695              :     }
     696       197959 :   if (n + n2 > 0 && crtl->stack_alignment_needed)
     697              :     /* If we have a stack frame, we must align it now.  The stack size
     698              :        may be a part of the offset computation for register
     699              :        elimination.  */
     700       197959 :     assign_stack_local (BLKmode, 0, crtl->stack_alignment_needed);
     701       197959 :   if (lra_dump_file != NULL)
     702              :     {
     703            3 :       for (i = 0; i < slots_num; i++)
     704              :         {
     705            2 :           fprintf (lra_dump_file, "  Slot %d regnos (width = ", i);
     706            2 :           print_dec (slots[i].size, lra_dump_file, SIGNED);
     707            2 :           fprintf (lra_dump_file, "):");
     708            2 :           for (curr_regno = slots[i].regno;;
     709            0 :                curr_regno = pseudo_slots[curr_regno].next - pseudo_slots)
     710              :             {
     711            2 :               fprintf (lra_dump_file, "     %d", curr_regno);
     712            2 :               if (pseudo_slots[curr_regno].next == NULL)
     713              :                 break;
     714              :             }
     715            2 :           fprintf (lra_dump_file, "\n");
     716              :         }
     717              :     }
     718       197959 :   spill_pseudos ();
     719       197959 :   free (slots);
     720       197959 :   free (pseudo_slots);
     721       197959 :   free (pseudo_regnos);
     722       197959 :   free (spill_hard_reg);
     723       197959 : }
     724              : 
     725              : /* Apply alter_subreg for subregs of regs in *LOC.  Use FINAL_P for
     726              :    alter_subreg calls. Return true if any subreg of reg is
     727              :    processed.  */
     728              : static bool
     729    351888690 : alter_subregs (rtx *loc, bool final_p)
     730              : {
     731    351888690 :   int i;
     732    351888690 :   rtx x = *loc;
     733    351888690 :   bool res;
     734    351888690 :   const char *fmt;
     735    351888690 :   enum rtx_code code;
     736              : 
     737    351888690 :   if (x == NULL_RTX)
     738              :     return false;
     739    351888690 :   code = GET_CODE (x);
     740    351888690 :   if (code == SUBREG && REG_P (SUBREG_REG (x)))
     741              :     {
     742      2905172 :       lra_assert (REGNO (SUBREG_REG (x)) < FIRST_PSEUDO_REGISTER);
     743      2905172 :       alter_subreg (loc, final_p);
     744      2905172 :       return true;
     745              :     }
     746    348983518 :   fmt = GET_RTX_FORMAT (code);
     747    348983518 :   res = false;
     748    834881009 :   for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
     749              :     {
     750    485897491 :       if (fmt[i] == 'e')
     751              :         {
     752    121046925 :           if (alter_subregs (&XEXP (x, i), final_p))
     753    485897491 :             res = true;
     754              :         }
     755    364850566 :       else if (fmt[i] == 'E')
     756              :         {
     757       489687 :           int j;
     758              : 
     759      2440531 :           for (j = XVECLEN (x, i) - 1; j >= 0; j--)
     760      1950844 :             if (alter_subregs (&XVECEXP (x, i, j), final_p))
     761          452 :               res = true;
     762              :         }
     763              :     }
     764              :   return res;
     765              : }
     766              : 
     767              : /* Final change of pseudos got hard registers into the corresponding
     768              :    hard registers and removing temporary clobbers.  */
     769              : void
     770      1471362 : lra_final_code_change (void)
     771              : {
     772      1471362 :   int i, hard_regno;
     773      1471362 :   basic_block bb;
     774      1471362 :   rtx_insn *insn, *curr;
     775      1471362 :   rtx set;
     776      1471362 :   int max_regno = max_reg_num ();
     777              : 
     778     78440631 :   for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++)
     779     75497907 :     if (lra_reg_info[i].nrefs != 0
     780    110414923 :         && (hard_regno = lra_get_regno_hard_regno (i)) >= 0)
     781     34911733 :       SET_REGNO (regno_reg_rtx[i], hard_regno);
     782     15984076 :   FOR_EACH_BB_FN (bb, cfun)
     783    370667224 :     FOR_BB_INSNS_SAFE (bb, insn, curr)
     784    170820898 :       if (INSN_P (insn))
     785              :         {
     786    142249898 :           rtx pat = PATTERN (insn);
     787              : 
     788    142249898 :           if (GET_CODE (pat) == USE && XEXP (pat, 0) == const1_rtx)
     789              :             {
     790              :               /* Remove markers to eliminate critical edges for jump insn
     791              :                  output reloads (see code in ira.cc::ira).  */
     792           11 :               lra_invalidate_insn_data (insn);
     793           11 :               delete_insn (insn);
     794           11 :               continue;
     795              :             }
     796    142249887 :           if (GET_CODE (pat) == CLOBBER && LRA_TEMP_CLOBBER_P (pat))
     797              :             {
     798              :               /* Remove clobbers temporarily created in LRA.  We don't
     799              :                  need them anymore and don't want to waste compiler
     800              :                  time processing them in a few subsequent passes.  */
     801       128637 :               lra_invalidate_insn_data (insn);
     802       128637 :               delete_insn (insn);
     803       128637 :               continue;
     804              :             }
     805              : 
     806              :           /* IRA can generate move insns involving pseudos.  It is
     807              :              better remove them earlier to speed up compiler a bit.
     808              :              It is also better to do it here as they might not pass
     809              :              final RTL check in LRA, (e.g. insn moving a control
     810              :              register into itself).  So remove an useless move insn
     811              :              unless next insn is USE marking the return reg (we should
     812              :              save this as some subsequent optimizations assume that
     813              :              such original insns are saved).  */
     814     78476309 :           if (NONJUMP_INSN_P (insn) && GET_CODE (pat) == SET
     815     66478493 :               && REG_P (SET_SRC (pat)) && REG_P (SET_DEST (pat))
     816     17143481 :               && REGNO (SET_SRC (pat)) == REGNO (SET_DEST (pat))
     817    152806741 :               && REGNO (SET_SRC (pat)) >= FIRST_PSEUDO_REGISTER)
     818              :             {
     819            0 :               lra_invalidate_insn_data (insn);
     820            0 :               delete_insn (insn);
     821            0 :               continue;
     822              :             }
     823              : 
     824    142121250 :           lra_insn_recog_data_t id = lra_get_insn_recog_data (insn);
     825    142121250 :           struct lra_insn_reg *reg;
     826              : 
     827    296709814 :           for (reg = id->regs; reg != NULL; reg = reg->next)
     828    154589169 :             if (reg->regno >= FIRST_PSEUDO_REGISTER
     829    101361064 :                 && lra_reg_info [reg->regno].nrefs == 0)
     830              :               break;
     831              : 
     832    142121250 :           if (reg != NULL)
     833              :             {
     834              :               /* Pseudos still can be in debug insns in some very rare
     835              :                  and complicated cases, e.g. the pseudo was removed by
     836              :                  inheritance and the debug insn is not EBBs where the
     837              :                  inheritance happened.  It is difficult and time
     838              :                  consuming to find what hard register corresponds the
     839              :                  pseudo -- so just remove the debug insn.  Another
     840              :                  solution could be assigning hard reg/memory but it
     841              :                  would be a misleading info.  It is better not to have
     842              :                  info than have it wrong.  */
     843          605 :               lra_assert (DEBUG_INSN_P (insn));
     844          605 :               lra_invalidate_insn_data (insn);
     845          605 :               delete_insn (insn);
     846          605 :               continue;
     847              :             }
     848              : 
     849    142120645 :           struct lra_static_insn_data *static_id = id->insn_static_data;
     850    142120645 :           bool insn_change_p = false;
     851              : 
     852    377754717 :           for (i = id->insn_static_data->n_operands - 1; i >= 0; i--)
     853    197950233 :             if ((DEBUG_INSN_P (insn) || ! static_id->operand[i].is_operator)
     854    426046708 :                 && alter_subregs (id->operand_loc[i], ! DEBUG_INSN_P (insn)))
     855              :               {
     856      2903328 :                 lra_update_dup (id, i);
     857      2903328 :                 insn_change_p = true;
     858              :               }
     859    142120645 :           if ((GET_CODE (pat) == USE || GET_CODE (pat) == CLOBBER)
     860    142120645 :               && alter_subregs (&XEXP (pat, 0), false))
     861              :             insn_change_p = true;
     862    142120645 :           if (insn_change_p)
     863      2571984 :             lra_update_operator_dups (id);
     864              : 
     865    142120645 :           if ((set = single_set (insn)) != NULL
     866     88086180 :               && REG_P (SET_SRC (set)) && REG_P (SET_DEST (set))
     867    160233188 :               && REGNO (SET_SRC (set)) == REGNO (SET_DEST (set)))
     868              :             {
     869              :               /* Remove an useless move insn.  IRA can generate move
     870              :                  insns involving pseudos.  It is better remove them
     871              :                  earlier to speed up compiler a bit.  It is also
     872              :                  better to do it here as they might not pass final RTL
     873              :                  check in LRA, (e.g. insn moving a control register
     874              :                  into itself).  */
     875     10994928 :               lra_invalidate_insn_data (insn);
     876     10994928 :               delete_insn (insn);
     877              :             }
     878              :         }
     879      1471362 : }
        

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.