LCOV - code coverage report
Current view: top level - gcc - lra-spills.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 74.9 % 403 302
Test Date: 2026-10-17 16:30:31 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      1458122 : assign_mem_slot (int i)
     133              : {
     134      1458122 :   rtx x = NULL_RTX;
     135      1458122 :   machine_mode mode = GET_MODE (regno_reg_rtx[i]);
     136      2916244 :   poly_int64 inherent_size = PSEUDO_REGNO_BYTES (i);
     137      1458122 :   machine_mode wider_mode
     138      1458122 :     = wider_subreg_mode (mode, lra_reg_info[i].biggest_mode);
     139      2916244 :   poly_int64 total_size = GET_MODE_SIZE (wider_mode);
     140      1458122 :   poly_int64 adjust = 0;
     141              : 
     142      1458122 :   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      1458122 :   unsigned int slot_num = pseudo_slots[i].slot_num;
     146      1458122 :   x = slots[slot_num].mem;
     147      1458122 :   if (!x)
     148              :     {
     149      1548910 :       x = assign_stack_local_1 (BLKmode, slots[slot_num].size,
     150       774455 :                                 slots[slot_num].align,
     151              :                                 ASLK_RECORD_PAD | ASLK_REDUCE_ALIGN);
     152       774455 :       slots[slot_num].mem = x;
     153              :     }
     154              : 
     155              :   /* On a big endian machine, the "address" of the slot is the address
     156              :      of the low part that fits its inherent mode.  */
     157      2916244 :   adjust += subreg_size_lowpart_offset (inherent_size, total_size);
     158      1458122 :   x = adjust_address_nv (x, GET_MODE (regno_reg_rtx[i]), adjust);
     159              : 
     160              :   /* Set all of the memory attributes as appropriate for a spill.  */
     161      1458122 :   set_mem_attrs_for_spill (x);
     162      1458122 :   pseudo_slots[i].mem = x;
     163      1458122 : }
     164              : 
     165              : /* Sort pseudos according their usage frequencies.  */
     166              : static int
     167     31508070 : regno_freq_compare (const void *v1p, const void *v2p)
     168              : {
     169     31508070 :   const int regno1 = *(const int *) v1p;
     170     31508070 :   const int regno2 = *(const int *) v2p;
     171     31508070 :   int diff;
     172              : 
     173     31508070 :   if ((diff = lra_reg_info[regno2].freq - lra_reg_info[regno1].freq) != 0)
     174              :     return diff;
     175     12703283 :   return regno1 - regno2;
     176              : }
     177              : 
     178              : /* Sort pseudos according to their slots, putting the slots in the order
     179              :    that they should be allocated.
     180              : 
     181              :    First prefer to group slots with variable sizes together and slots
     182              :    with constant sizes together, since that usually makes them easier
     183              :    to address from a common anchor point.  E.g. loads of polynomial-sized
     184              :    registers tend to take polynomial offsets while loads of constant-sized
     185              :    registers tend to take constant (non-polynomial) offsets.
     186              : 
     187              :    Next, slots with lower numbers have the highest priority and should
     188              :    get the smallest displacement from the stack or frame pointer
     189              :    (whichever is being used).
     190              : 
     191              :    The first allocated slot is always closest to the frame pointer,
     192              :    so prefer lower slot numbers when frame_pointer_needed.  If the stack
     193              :    and frame grow in the same direction, then the first allocated slot is
     194              :    always closest to the initial stack pointer and furthest away from the
     195              :    final stack pointer, so allocate higher numbers first when using the
     196              :    stack pointer in that case.  The reverse is true if the stack and
     197              :    frame grow in opposite directions.  */
     198              : static int
     199     32017650 : pseudo_reg_slot_compare (const void *v1p, const void *v2p)
     200              : {
     201     32017650 :   const int regno1 = *(const int *) v1p;
     202     32017650 :   const int regno2 = *(const int *) v2p;
     203     32017650 :   int diff, slot_num1, slot_num2;
     204              : 
     205     32017650 :   slot_num1 = pseudo_slots[regno1].slot_num;
     206     32017650 :   slot_num2 = pseudo_slots[regno2].slot_num;
     207     32017650 :   diff = (int (slots[slot_num1].size.is_constant ())
     208     32017650 :           - int (slots[slot_num2].size.is_constant ()));
     209     32017650 :   if (diff != 0)
     210              :     return diff;
     211     32017650 :   if ((diff = slot_num1 - slot_num2) != 0)
     212     23767021 :     return (frame_pointer_needed
     213     23767021 :             || (!FRAME_GROWS_DOWNWARD) == STACK_GROWS_DOWNWARD ? diff : -diff);
     214     16501258 :   poly_int64 total_size1 = GET_MODE_SIZE (lra_reg_info[regno1].biggest_mode);
     215     16501258 :   poly_int64 total_size2 = GET_MODE_SIZE (lra_reg_info[regno2].biggest_mode);
     216      9079379 :   if ((diff = compare_sizes_for_sort (total_size2, total_size1)) != 0)
     217              :     return diff;
     218      6713991 :   return regno1 - regno2;
     219              : }
     220              : 
     221              : /* Assign spill hard registers to N pseudos in PSEUDO_REGNOS which is
     222              :    sorted in order of highest frequency first.  Put the pseudos which
     223              :    did not get a spill hard register at the beginning of array
     224              :    PSEUDO_REGNOS.  Return the number of such pseudos.  */
     225              : static int
     226       200398 : assign_spill_hard_regs (int *pseudo_regnos, int n)
     227              : {
     228       200398 :   int i, k, p, regno, res, spill_class_size, hard_regno, nr;
     229       200398 :   enum reg_class rclass, spill_class;
     230       200398 :   machine_mode mode;
     231       200398 :   lra_live_range_t r;
     232       200398 :   rtx_insn *insn;
     233       200398 :   rtx set;
     234       200398 :   basic_block bb;
     235       200398 :   HARD_REG_SET conflict_hard_regs;
     236       200398 :   bitmap setjump_crosses = regstat_get_setjmp_crosses ();
     237              :   /* Hard registers which cannot be used for any purpose at given
     238              :      program point because they are unallocatable or already allocated
     239              :      for other pseudos.  */
     240       200398 :   HARD_REG_SET *reserved_hard_regs;
     241              : 
     242       200398 :   if (! lra_reg_spill_p)
     243              :     return n;
     244              :   /* Set up reserved hard regs for every program point.  */
     245            0 :   reserved_hard_regs = XNEWVEC (HARD_REG_SET, lra_live_max_point);
     246            0 :   for (p = 0; p < lra_live_max_point; p++)
     247            0 :     reserved_hard_regs[p] = lra_no_alloc_regs;
     248            0 :   for (i = FIRST_PSEUDO_REGISTER; i < regs_num; i++)
     249            0 :     if (lra_reg_info[i].nrefs != 0
     250            0 :         && (hard_regno = lra_get_regno_hard_regno (i)) >= 0)
     251            0 :       for (r = lra_reg_info[i].live_ranges; r != NULL; r = r->next)
     252            0 :         for (p = r->start; p <= r->finish; p++)
     253            0 :           add_to_hard_reg_set (&reserved_hard_regs[p],
     254              :                                lra_reg_info[i].biggest_mode, hard_regno);
     255            0 :   auto_bitmap ok_insn_bitmap (&reg_obstack);
     256            0 :   FOR_EACH_BB_FN (bb, cfun)
     257            0 :     FOR_BB_INSNS (bb, insn)
     258            0 :       if (DEBUG_INSN_P (insn)
     259            0 :           || ((set = single_set (insn)) != NULL_RTX
     260            0 :               && REG_P (SET_SRC (set)) && REG_P (SET_DEST (set))))
     261            0 :         bitmap_set_bit (ok_insn_bitmap, INSN_UID (insn));
     262            0 :   for (res = i = 0; i < n; i++)
     263              :     {
     264            0 :       regno = pseudo_regnos[i];
     265            0 :       gcc_assert (lra_reg_info[regno].live_ranges);
     266            0 :       rclass = lra_get_allocno_class (regno);
     267            0 :       if (bitmap_bit_p (setjump_crosses, regno)
     268            0 :           || (spill_class
     269            0 :               = ((enum reg_class)
     270            0 :                  targetm.spill_class ((reg_class_t) rclass,
     271            0 :                                       PSEUDO_REGNO_MODE (regno)))) == NO_REGS
     272            0 :           || bitmap_intersect_compl_p (&lra_reg_info[regno].insn_bitmap,
     273            0 :                                        ok_insn_bitmap))
     274              :         {
     275            0 :           pseudo_regnos[res++] = regno;
     276            0 :           continue;
     277              :         }
     278            0 :       lra_assert (spill_class != NO_REGS);
     279            0 :       conflict_hard_regs = lra_reg_info[regno].conflict_hard_regs;
     280            0 :       for (r = lra_reg_info[regno].live_ranges; r != NULL; r = r->next)
     281            0 :         for (p = r->start; p <= r->finish; p++)
     282            0 :           conflict_hard_regs |= reserved_hard_regs[p];
     283            0 :       spill_class_size = ira_class_hard_regs_num[spill_class];
     284            0 :       mode = lra_reg_info[regno].biggest_mode;
     285            0 :       for (k = 0; k < spill_class_size; k++)
     286              :         {
     287            0 :           hard_regno = ira_class_hard_regs[spill_class][k];
     288            0 :           if (TEST_HARD_REG_BIT (eliminable_regset, hard_regno)
     289            0 :               || !targetm.hard_regno_mode_ok (hard_regno, mode))
     290            0 :             continue;
     291            0 :           if (! overlaps_hard_reg_set_p (conflict_hard_regs, mode, hard_regno))
     292              :             break;
     293              :         }
     294            0 :       if (k >= spill_class_size)
     295              :         {
     296              :            /* There is no available regs -- assign memory later.  */
     297            0 :           pseudo_regnos[res++] = regno;
     298            0 :           continue;
     299              :         }
     300            0 :       if (lra_dump_file != NULL)
     301            0 :         fprintf (lra_dump_file, "  Spill r%d into hr%d\n", regno, hard_regno);
     302            0 :       add_to_hard_reg_set (&hard_regs_spilled_into,
     303            0 :                            lra_reg_info[regno].biggest_mode, hard_regno);
     304              :       /* Update reserved_hard_regs.  */
     305            0 :       for (r = lra_reg_info[regno].live_ranges; r != NULL; r = r->next)
     306            0 :         for (p = r->start; p <= r->finish; p++)
     307            0 :           add_to_hard_reg_set (&reserved_hard_regs[p],
     308              :                                lra_reg_info[regno].biggest_mode, hard_regno);
     309            0 :       spill_hard_reg[regno]
     310            0 :         = gen_raw_REG (PSEUDO_REGNO_MODE (regno), hard_regno);
     311            0 :       for (nr = 0;
     312            0 :            nr < hard_regno_nregs (hard_regno,
     313            0 :                                   lra_reg_info[regno].biggest_mode);
     314              :            nr++)
     315              :         /* Just loop.  */
     316            0 :         df_set_regs_ever_live (hard_regno + nr, true);
     317              :     }
     318            0 :   free (reserved_hard_regs);
     319            0 :   return res;
     320            0 : }
     321              : 
     322              : /* Add pseudo REGNO to slot SLOT_NUM.  */
     323              : static void
     324      1458122 : add_pseudo_to_slot (int regno, int slot_num)
     325              : {
     326      1458122 :   struct pseudo_slot *first;
     327              : 
     328              :   /* Each pseudo has an inherent size which comes from its own mode,
     329              :      and a total size which provides room for paradoxical subregs.
     330              :      We need to make sure the size and alignment of the slot are
     331              :      sufficient for both.  */
     332      2916244 :   machine_mode mode = wider_subreg_mode (PSEUDO_REGNO_MODE (regno),
     333      1458122 :                                          lra_reg_info[regno].biggest_mode);
     334      1458122 :   unsigned int align = spill_slot_alignment (mode);
     335      1458122 :   slots[slot_num].align = MAX (slots[slot_num].align, align);
     336      1458122 :   slots[slot_num].size = upper_bound (slots[slot_num].size,
     337      1458122 :                                       GET_MODE_SIZE (mode));
     338              : 
     339      1458122 :   if (slots[slot_num].regno < 0)
     340              :     {
     341              :       /* It is the first pseudo in the slot.  */
     342       774455 :       slots[slot_num].regno = regno;
     343       774455 :       pseudo_slots[regno].first = &pseudo_slots[regno];
     344       774455 :       pseudo_slots[regno].next = NULL;
     345              :     }
     346              :   else
     347              :     {
     348       683667 :       first = pseudo_slots[regno].first = &pseudo_slots[slots[slot_num].regno];
     349       683667 :       pseudo_slots[regno].next = first->next;
     350       683667 :       first->next = &pseudo_slots[regno];
     351       683667 :       lra_assert (slots[slot_num].live_ranges);
     352              :     }
     353      1458122 :   pseudo_slots[regno].mem = NULL_RTX;
     354      1458122 :   pseudo_slots[regno].slot_num = slot_num;
     355              : 
     356              :   /* Pseudos with empty ranges shouldn't need to be spilled; if we get
     357              :      an empty range added to a slot, something fishy is going on, such
     358              :      as missing live range information, and without that information
     359              :      we may generate wrong code.  We can probably relax this to an
     360              :      lra_assert at some point.  Likewise the analogous one in
     361              :      assign_spill_hard_regs.  */
     362      1458122 :   gcc_assert (lra_reg_info[regno].live_ranges);
     363              : 
     364      1458122 :   slots[slot_num].live_ranges
     365      1458122 :     = lra_merge_live_ranges (slots[slot_num].live_ranges,
     366              :                              lra_copy_live_range_list
     367              :                              (lra_reg_info[regno].live_ranges));
     368      1458122 : }
     369              : 
     370              : /* Recompute the combined live ranges of pseudos assigned to stack
     371              :    slots.  This brings the live ranges of slots back in sync with
     372              :    those of pseudos, after recomputing live ranges for pseudos.  */
     373              : void
     374            0 : lra_recompute_slots_live_ranges (void)
     375              : {
     376            0 :   for (int i = 0; i < slots_num; i++)
     377              :     {
     378            0 :       if (slots[i].regno < 0)
     379            0 :         continue;
     380            0 :       lra_reset_live_range_list (slots[i].live_ranges);
     381            0 :       for (struct pseudo_slot *next = pseudo_slots[slots[i].regno].first;
     382            0 :            next; next = next->next)
     383              :         {
     384            0 :           int regno = next - pseudo_slots;
     385            0 :           lra_assert (!(lra_intersected_live_ranges_p
     386              :                         (lra_reg_info[regno].live_ranges,
     387              :                          slots[i].live_ranges)));
     388            0 :           slots[i].live_ranges
     389            0 :             = lra_merge_live_ranges (slots[i].live_ranges,
     390              :                                      lra_copy_live_range_list
     391            0 :                                      (lra_reg_info[regno].live_ranges));
     392              :         }
     393              :     }
     394            0 : }
     395              : 
     396              : /* Assign stack slot numbers to pseudos in array PSEUDO_REGNOS of
     397              :    length N.  Sort pseudos in PSEUDO_REGNOS for subsequent assigning
     398              :    memory stack slots.  */
     399              : static void
     400       200398 : assign_stack_slot_num_and_sort_pseudos (int *pseudo_regnos, int n)
     401              : {
     402       200398 :   int i, j, regno;
     403              : 
     404              :   /* Assign stack slot numbers to spilled pseudos, use smaller numbers
     405              :      for most frequently used pseudos.  */
     406      1658520 :   for (i = 0; i < n; i++)
     407              :     {
     408      1458122 :       regno = pseudo_regnos[i];
     409      1458122 :       if (! flag_ira_share_spill_slots)
     410        27724 :         j = slots_num;
     411              :       else
     412              :         {
     413      1430398 :           machine_mode mode
     414      2860796 :             = wider_subreg_mode (PSEUDO_REGNO_MODE (regno),
     415      1430398 :                                  lra_reg_info[regno].biggest_mode);
     416     27504527 :           for (j = 0; j < slots_num; j++)
     417     26757796 :             if (slots[j].hard_regno < 0
     418              :                 /* Although it's possible to share slots between modes
     419              :                    with constant and non-constant widths, we usually
     420              :                    get better spill code by keeping the constant and
     421              :                    non-constant areas separate.  */
     422     26757796 :                 && (GET_MODE_SIZE (mode).is_constant ()
     423              :                     == slots[j].size.is_constant ())
     424     53515592 :                 && ! (lra_intersected_live_ranges_p
     425     26757796 :                       (slots[j].live_ranges,
     426     26757796 :                        lra_reg_info[regno].live_ranges)))
     427              :               {
     428              :                 /* A slot without allocated memory can be shared.  */
     429       683667 :                 if (slots[j].mem == NULL_RTX)
     430              :                   break;
     431              : 
     432              :                 /* A slot with allocated memory can be shared only with equal
     433              :                    or smaller register with equal or smaller alignment.  */
     434            0 :                 if (slots[j].align >= spill_slot_alignment (mode)
     435            0 :                     && known_ge (slots[j].size, GET_MODE_SIZE (mode)))
     436              :                   break;
     437              :               }
     438              :         }
     439      1458122 :       if (j >= slots_num)
     440              :         {
     441              :           /* New slot.  */
     442       774455 :           slots[j].live_ranges = NULL;
     443       774455 :           slots[j].size = 0;
     444       774455 :           slots[j].align = BITS_PER_UNIT;
     445       774455 :           slots[j].regno = slots[j].hard_regno = -1;
     446       774455 :           slots[j].mem = NULL_RTX;
     447       774455 :           slots_num++;
     448              :         }
     449      1458122 :       add_pseudo_to_slot (regno, j);
     450              :     }
     451              :   /* Sort regnos according to their slot numbers.  */
     452       200398 :   qsort (pseudo_regnos, n, sizeof (int), pseudo_reg_slot_compare);
     453       200398 : }
     454              : 
     455              : /* Recursively process LOC in INSN and change spilled pseudos to the
     456              :    corresponding memory or spilled hard reg.  Ignore spilled pseudos
     457              :    created from the scratches.  Return true if the pseudo nrefs equal
     458              :    to 0 (don't change the pseudo in this case).  Otherwise return false.  */
     459              : static bool
     460     37893274 : remove_pseudos (rtx *loc, rtx_insn *insn)
     461              : {
     462     37893274 :   int i;
     463     37893274 :   rtx hard_reg;
     464     37893274 :   const char *fmt;
     465     37893274 :   enum rtx_code code;
     466     37893274 :   bool res = false;
     467              : 
     468     37893274 :   if (*loc == NULL_RTX)
     469              :     return res;
     470     34930797 :   code = GET_CODE (*loc);
     471     34930797 :   if (code == SUBREG && REG_P (SUBREG_REG (*loc)))
     472              :     {
     473              :       /* Try to remove memory subregs to simplify LRA job
     474              :          and avoid LRA cycling in case of subreg memory reload.  */
     475       278222 :       res = remove_pseudos (&SUBREG_REG (*loc), insn);
     476       278222 :       if (GET_CODE (SUBREG_REG (*loc)) == MEM)
     477              :         {
     478       216126 :           alter_subreg (loc, false);
     479       216126 :           if (GET_CODE (*loc) == MEM)
     480              :             {
     481       216126 :               lra_update_insn_recog_data (insn);
     482       216126 :               if (lra_dump_file != NULL)
     483            1 :                 fprintf (lra_dump_file,
     484              :                          "Memory subreg was simplified in insn #%u\n",
     485            1 :                          INSN_UID (insn));
     486              :             }
     487              :         }
     488              :       return res;
     489              :     }
     490     15544312 :   else if (code == REG && (i = REGNO (*loc)) >= FIRST_PSEUDO_REGISTER
     491      8969992 :       && lra_get_regno_hard_regno (i) < 0
     492              :       /* We do not want to assign memory for former scratches because
     493              :          it might result in an address reload for some targets.  In
     494              :          any case we transform such pseudos not getting hard registers
     495              :          into scratches back.  */
     496     39755815 :       && ! ira_former_scratch_p (i))
     497              :     {
     498      5103240 :       if (lra_reg_info[i].nrefs == 0
     499        22464 :           && pseudo_slots[i].mem == NULL && spill_hard_reg[i] == NULL)
     500              :         return true;
     501      5103240 :       if ((hard_reg = spill_hard_reg[i]) != NULL_RTX)
     502            0 :         *loc = copy_rtx (hard_reg);
     503      5103240 :       else if (pseudo_slots[i].mem != NULL_RTX)
     504              :         /* There might be no memory slot or hard reg for a pseudo when we spill
     505              :            the frame pointer after elimination of frame pointer to stack
     506              :            pointer became impossible.  */
     507              :         {
     508     10206480 :           rtx x = lra_eliminate_regs_1 (insn, pseudo_slots[i].mem,
     509      5103240 :                                         GET_MODE (pseudo_slots[i].mem),
     510              :                                         false, false, 0, true);
     511      5103240 :           *loc = x != pseudo_slots[i].mem ? x : copy_rtx (x);
     512              :         }
     513              :       return res;
     514              :     }
     515              : 
     516     29549335 :   fmt = GET_RTX_FORMAT (code);
     517     71495508 :   for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
     518              :     {
     519     41946173 :       if (fmt[i] == 'e')
     520     29397103 :         res = remove_pseudos (&XEXP (*loc, i), insn) || res;
     521     12549070 :       else if (fmt[i] == 'E')
     522              :         {
     523       102071 :           int j;
     524              : 
     525       323083 :           for (j = XVECLEN (*loc, i) - 1; j >= 0; j--)
     526       221012 :             res = remove_pseudos (&XVECEXP (*loc, i, j), insn) || res;
     527              :         }
     528              :     }
     529              :   return res;
     530              : }
     531              : 
     532              : /* Convert spilled pseudos into their stack slots or spill hard regs,
     533              :    put insns to process on the constraint stack (that is all insns in
     534              :    which pseudos were changed to memory or spill hard regs).   */
     535              : static void
     536       200398 : spill_pseudos (void)
     537              : {
     538       200398 :   basic_block bb;
     539       200398 :   rtx_insn *insn, *curr;
     540       200398 :   int i;
     541              : 
     542       200398 :   auto_bitmap spilled_pseudos (&reg_obstack);
     543       200398 :   auto_bitmap changed_insns (&reg_obstack);
     544     37031495 :   for (i = FIRST_PSEUDO_REGISTER; i < regs_num; i++)
     545              :     {
     546     18860856 :       if (lra_reg_info[i].nrefs != 0 && lra_get_regno_hard_regno (i) < 0
     547     38291781 :           && ! ira_former_scratch_p (i))
     548              :         {
     549      1458122 :           bitmap_set_bit (spilled_pseudos, i);
     550      1458122 :           bitmap_ior_into (changed_insns, &lra_reg_info[i].insn_bitmap);
     551              :         }
     552              :     }
     553      7441275 :   FOR_EACH_BB_FN (bb, cfun)
     554              :     {
     555    219020421 :       FOR_BB_INSNS_SAFE (bb, insn, curr)
     556              :         {
     557    105889772 :           bool removed_pseudo_p = false;
     558              : 
     559    105889772 :           if (bitmap_bit_p (changed_insns, INSN_UID (insn)))
     560              :             {
     561      5034460 :               rtx *link_loc, link;
     562              : 
     563      5034460 :               removed_pseudo_p = remove_pseudos (&PATTERN (insn), insn);
     564      5034460 :               if (CALL_P (insn)
     565      5034460 :                   && remove_pseudos (&CALL_INSN_FUNCTION_USAGE (insn), insn))
     566              :                 removed_pseudo_p = true;
     567      5034460 :               for (link_loc = &REG_NOTES (insn);
     568      8443830 :                    (link = *link_loc) != NULL_RTX;
     569      3409370 :                    link_loc = &XEXP (link, 1))
     570              :                 {
     571      3409370 :                   switch (REG_NOTE_KIND (link))
     572              :                     {
     573            0 :                     case REG_FRAME_RELATED_EXPR:
     574            0 :                     case REG_CFA_DEF_CFA:
     575            0 :                     case REG_CFA_ADJUST_CFA:
     576            0 :                     case REG_CFA_OFFSET:
     577            0 :                     case REG_CFA_REGISTER:
     578            0 :                     case REG_CFA_EXPRESSION:
     579            0 :                     case REG_CFA_RESTORE:
     580            0 :                     case REG_CFA_SET_VDRAP:
     581            0 :                       if (remove_pseudos (&XEXP (link, 0), insn))
     582      3409370 :                         removed_pseudo_p = true;
     583              :                       break;
     584              :                     default:
     585              :                       break;
     586              :                     }
     587              :                 }
     588      5034460 :               if (GET_CODE (PATTERN (insn)) == CLOBBER)
     589              :                 /* This is a CLOBBER insn with pseudo spilled to memory.
     590              :                    Mark it for removing it later together with LRA temporary
     591              :                    CLOBBER insns.  */
     592         7528 :                 LRA_TEMP_CLOBBER_P (PATTERN (insn)) = 1;
     593      5034460 :               if (lra_dump_file != NULL)
     594            2 :                 fprintf (lra_dump_file,
     595              :                          "Changing spilled pseudos to memory in insn #%u\n",
     596            2 :                          INSN_UID (insn));
     597      5034460 :               lra_push_insn_and_update_insn_regno_info (insn);
     598      5034460 :               if (lra_reg_spill_p || targetm.different_addr_displacement_p ())
     599            0 :                 lra_set_used_insn_alternative (insn, LRA_UNKNOWN_ALT);
     600              :             }
     601    100855312 :           else if (CALL_P (insn)
     602              :                    /* Presence of any pseudo in CALL_INSN_FUNCTION_USAGE
     603              :                       does not affect value of insn_bitmap of the
     604              :                       corresponding lra_reg_info.  That is because we
     605              :                       don't need to reload pseudos in
     606              :                       CALL_INSN_FUNCTION_USAGEs.  So if we process only
     607              :                       insns in the insn_bitmap of given pseudo here, we
     608              :                       can miss the pseudo in some
     609              :                       CALL_INSN_FUNCTION_USAGEs.  */
     610    100855312 :                    && remove_pseudos (&CALL_INSN_FUNCTION_USAGE (insn), insn))
     611              :             removed_pseudo_p = true;
     612      5034460 :           if (removed_pseudo_p)
     613              :             {
     614            0 :               lra_assert (DEBUG_INSN_P (insn));
     615            0 :               lra_invalidate_insn_data (insn);
     616            0 :               INSN_VAR_LOCATION_LOC (insn) = gen_rtx_UNKNOWN_VAR_LOC ();
     617            0 :               if (lra_dump_file != NULL)
     618            0 :                 fprintf (lra_dump_file,
     619              :                          "Debug insn #%u is reset because it referenced "
     620            0 :                          "removed pseudo\n", INSN_UID (insn));
     621              :             }
     622    105889772 :           bitmap_and_compl_into (df_get_live_in (bb), spilled_pseudos);
     623    105889772 :           bitmap_and_compl_into (df_get_live_out (bb), spilled_pseudos);
     624              :         }
     625              :     }
     626       200398 : }
     627              : 
     628              : /* Return true if we need scratch reg assignments.  */
     629              : bool
     630          294 : lra_need_for_scratch_reg_p (void)
     631              : {
     632          294 :   int i; max_regno = max_reg_num ();
     633              : 
     634         9459 :   for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++)
     635         2171 :     if (lra_reg_info[i].nrefs != 0 && lra_get_regno_hard_regno (i) < 0
     636         9165 :         && ira_former_scratch_p (i))
     637              :       return true;
     638              :   return false;
     639              : }
     640              : 
     641              : /* Return true if we need to change some pseudos into memory.  */
     642              : bool
     643      1718007 : lra_need_for_spills_p (void)
     644              : {
     645      1718007 :   int i;
     646              : 
     647      1718007 :   max_regno = max_reg_num ();
     648     92584508 :   for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++)
     649     41039764 :     if (lra_reg_info[i].nrefs != 0 && lra_get_regno_hard_regno (i) < 0
     650     91275495 :         && ! ira_former_scratch_p (i))
     651              :       return true;
     652              :   return false;
     653              : }
     654              : 
     655              : /* Change spilled pseudos into memory or spill hard regs.  Put changed
     656              :    insns on the constraint stack (these insns will be considered on
     657              :    the next constraint pass).  The changed insns are all insns in
     658              :    which pseudos were changed.  */
     659              : void
     660       200398 : lra_spill (void)
     661              : {
     662       200398 :   int i, n, n2, curr_regno;
     663       200398 :   int *pseudo_regnos;
     664              : 
     665       200398 :   regs_num = max_reg_num ();
     666       200398 :   spill_hard_reg = XNEWVEC (rtx, regs_num);
     667       200398 :   pseudo_regnos = XNEWVEC (int, regs_num);
     668     37231893 :   for (n = 0, i = FIRST_PSEUDO_REGISTER; i < regs_num; i++)
     669     18860856 :     if (lra_reg_info[i].nrefs != 0 && lra_get_regno_hard_regno (i) < 0
     670              :         /* We do not want to assign memory for former scratches.  */
     671     38291781 :         && ! ira_former_scratch_p (i))
     672      1458122 :       pseudo_regnos[n++] = i;
     673       200398 :   lra_assert (n > 0);
     674       200398 :   pseudo_slots = XNEWVEC (struct pseudo_slot, regs_num);
     675     37031495 :   for (i = FIRST_PSEUDO_REGISTER; i < regs_num; i++)
     676              :     {
     677     36831097 :       spill_hard_reg[i] = NULL_RTX;
     678     36831097 :       pseudo_slots[i].mem = NULL_RTX;
     679              :     }
     680       200398 :   slots = XNEWVEC (class slot, regs_num);
     681              :   /* Sort regnos according their usage frequencies.  */
     682       200398 :   qsort (pseudo_regnos, n, sizeof (int), regno_freq_compare);
     683       200398 :   n = assign_spill_hard_regs (pseudo_regnos, n);
     684       200398 :   slots_num = 0;
     685       200398 :   assign_stack_slot_num_and_sort_pseudos (pseudo_regnos, n);
     686      1858918 :   for (i = 0; i < n; i++)
     687      1458122 :     if (pseudo_slots[pseudo_regnos[i]].mem == NULL_RTX)
     688      1458122 :       assign_mem_slot (pseudo_regnos[i]);
     689       200398 :   if ((n2 = lra_update_fp2sp_elimination (pseudo_regnos)) > 0)
     690              :     {
     691              :       /* Assign stack slots to spilled pseudos assigned to fp.  */
     692            0 :       assign_stack_slot_num_and_sort_pseudos (pseudo_regnos, n2);
     693            0 :       for (i = 0; i < n2; i++)
     694            0 :         if (pseudo_slots[pseudo_regnos[i]].mem == NULL_RTX)
     695            0 :           assign_mem_slot (pseudo_regnos[i]);
     696              :     }
     697       200398 :   if (n + n2 > 0 && crtl->stack_alignment_needed)
     698              :     /* If we have a stack frame, we must align it now.  The stack size
     699              :        may be a part of the offset computation for register
     700              :        elimination.  */
     701       200398 :     assign_stack_local (BLKmode, 0, crtl->stack_alignment_needed);
     702       200398 :   if (lra_dump_file != NULL)
     703              :     {
     704            2 :       for (i = 0; i < slots_num; i++)
     705              :         {
     706            1 :           fprintf (lra_dump_file, "  Slot %d regnos (width = ", i);
     707            1 :           print_dec (slots[i].size, lra_dump_file, SIGNED);
     708            1 :           fprintf (lra_dump_file, "):");
     709            1 :           for (curr_regno = slots[i].regno;;
     710            0 :                curr_regno = pseudo_slots[curr_regno].next - pseudo_slots)
     711              :             {
     712            1 :               fprintf (lra_dump_file, "     %d", curr_regno);
     713            1 :               if (pseudo_slots[curr_regno].next == NULL)
     714              :                 break;
     715              :             }
     716            1 :           fprintf (lra_dump_file, "\n");
     717              :         }
     718              :     }
     719       200398 :   spill_pseudos ();
     720       200398 :   free (slots);
     721       200398 :   free (pseudo_slots);
     722       200398 :   free (pseudo_regnos);
     723       200398 :   free (spill_hard_reg);
     724       200398 : }
     725              : 
     726              : /* Apply alter_subreg for subregs of regs in *LOC.  Use FINAL_P for
     727              :    alter_subreg calls. Return true if any subreg of reg is
     728              :    processed.  */
     729              : static bool
     730    368377647 : alter_subregs (rtx *loc, bool final_p)
     731              : {
     732    368377647 :   int i;
     733    368377647 :   rtx x = *loc;
     734    368377647 :   bool res;
     735    368377647 :   const char *fmt;
     736    368377647 :   enum rtx_code code;
     737              : 
     738    368377647 :   if (x == NULL_RTX)
     739              :     return false;
     740    368377647 :   code = GET_CODE (x);
     741    368377647 :   if (code == SUBREG && REG_P (SUBREG_REG (x)))
     742              :     {
     743      3102002 :       lra_assert (REGNO (SUBREG_REG (x)) < FIRST_PSEUDO_REGISTER);
     744      3102002 :       alter_subreg (loc, final_p);
     745      3102002 :       return true;
     746              :     }
     747    365275645 :   fmt = GET_RTX_FORMAT (code);
     748    365275645 :   res = false;
     749    871337269 :   for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
     750              :     {
     751    506061624 :       if (fmt[i] == 'e')
     752              :         {
     753    126561768 :           if (alter_subregs (&XEXP (x, i), final_p))
     754    506061624 :             res = true;
     755              :         }
     756    379499856 :       else if (fmt[i] == 'E')
     757              :         {
     758       560440 :           int j;
     759              : 
     760      2801859 :           for (j = XVECLEN (x, i) - 1; j >= 0; j--)
     761      2241419 :             if (alter_subregs (&XVECEXP (x, i, j), final_p))
     762          731 :               res = true;
     763              :         }
     764              :     }
     765              :   return res;
     766              : }
     767              : 
     768              : /* Final change of pseudos got hard registers into the corresponding
     769              :    hard registers and removing temporary clobbers.  */
     770              : void
     771      1515921 : lra_final_code_change (void)
     772              : {
     773      1515921 :   int i, hard_regno;
     774      1515921 :   basic_block bb;
     775      1515921 :   rtx_insn *insn, *curr;
     776      1515921 :   rtx set;
     777      1515921 :   int max_regno = max_reg_num ();
     778              : 
     779     81297320 :   for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++)
     780     78265478 :     if (lra_reg_info[i].nrefs != 0
     781    114296346 :         && (hard_regno = lra_get_regno_hard_regno (i)) >= 0)
     782     36026269 :       SET_REGNO (regno_reg_rtx[i], hard_regno);
     783     16430963 :   FOR_EACH_BB_FN (bb, cfun)
     784    375470528 :     FOR_BB_INSNS_SAFE (bb, insn, curr)
     785    180277743 :       if (INSN_P (insn))
     786              :         {
     787    150934661 :           rtx pat = PATTERN (insn);
     788              : 
     789    150934661 :           if (GET_CODE (pat) == USE && XEXP (pat, 0) == const1_rtx)
     790              :             {
     791              :               /* Remove markers to eliminate critical edges for jump insn
     792              :                  output reloads (see code in ira.cc::ira).  */
     793           11 :               lra_invalidate_insn_data (insn);
     794           11 :               delete_insn (insn);
     795           11 :               continue;
     796              :             }
     797    150934650 :           if (GET_CODE (pat) == CLOBBER && LRA_TEMP_CLOBBER_P (pat))
     798              :             {
     799              :               /* Remove clobbers temporarily created in LRA.  We don't
     800              :                  need them anymore and don't want to waste compiler
     801              :                  time processing them in a few subsequent passes.  */
     802       124690 :               lra_invalidate_insn_data (insn);
     803       124690 :               delete_insn (insn);
     804       124690 :               continue;
     805              :             }
     806              : 
     807              :           /* IRA can generate move insns involving pseudos.  It is
     808              :              better remove them earlier to speed up compiler a bit.
     809              :              It is also better to do it here as they might not pass
     810              :              final RTL check in LRA, (e.g. insn moving a control
     811              :              register into itself).  So remove an useless move insn
     812              :              unless next insn is USE marking the return reg (we should
     813              :              save this as some subsequent optimizations assume that
     814              :              such original insns are saved).  */
     815     80841152 :           if (NONJUMP_INSN_P (insn) && GET_CODE (pat) == SET
     816     68548753 :               && REG_P (SET_SRC (pat)) && REG_P (SET_DEST (pat))
     817     17850410 :               && REGNO (SET_SRC (pat)) == REGNO (SET_DEST (pat))
     818    161886837 :               && REGNO (SET_SRC (pat)) >= FIRST_PSEUDO_REGISTER)
     819              :             {
     820            0 :               lra_invalidate_insn_data (insn);
     821            0 :               delete_insn (insn);
     822            0 :               continue;
     823              :             }
     824              : 
     825    150809960 :           lra_insn_recog_data_t id = lra_get_insn_recog_data (insn);
     826    150809960 :           struct lra_insn_reg *reg;
     827              : 
     828    310703491 :           for (reg = id->regs; reg != NULL; reg = reg->next)
     829    159901043 :             if (reg->regno >= FIRST_PSEUDO_REGISTER
     830    104435088 :                 && lra_reg_info [reg->regno].nrefs == 0)
     831              :               break;
     832              : 
     833    150809960 :           if (reg != NULL)
     834              :             {
     835              :               /* Pseudos still can be in debug insns in some very rare
     836              :                  and complicated cases, e.g. the pseudo was removed by
     837              :                  inheritance and the debug insn is not EBBs where the
     838              :                  inheritance happened.  It is difficult and time
     839              :                  consuming to find what hard register corresponds the
     840              :                  pseudo -- so just remove the debug insn.  Another
     841              :                  solution could be assigning hard reg/memory but it
     842              :                  would be a misleading info.  It is better not to have
     843              :                  info than have it wrong.  */
     844         7512 :               lra_assert (DEBUG_INSN_P (insn));
     845         7512 :               lra_invalidate_insn_data (insn);
     846         7512 :               delete_insn (insn);
     847         7512 :               continue;
     848              :             }
     849              : 
     850    150802448 :           struct lra_static_insn_data *static_id = id->insn_static_data;
     851    150802448 :           bool insn_change_p = false;
     852              : 
     853    397283924 :           for (i = id->insn_static_data->n_operands - 1; i >= 0; i--)
     854    204112546 :             if ((DEBUG_INSN_P (insn) || ! static_id->operand[i].is_operator)
     855    442869666 :                 && alter_subregs (id->operand_loc[i], ! DEBUG_INSN_P (insn)))
     856              :               {
     857      3092514 :                 lra_update_dup (id, i);
     858      3092514 :                 insn_change_p = true;
     859              :               }
     860    150802448 :           if ((GET_CODE (pat) == USE || GET_CODE (pat) == CLOBBER)
     861    150802448 :               && alter_subregs (&XEXP (pat, 0), false))
     862              :             insn_change_p = true;
     863    150802448 :           if (insn_change_p)
     864      2754460 :             lra_update_operator_dups (id);
     865              : 
     866    150802448 :           if ((set = single_set (insn)) != NULL
     867     90722261 :               && REG_P (SET_SRC (set)) && REG_P (SET_DEST (set))
     868    169705938 :               && REGNO (SET_SRC (set)) == REGNO (SET_DEST (set)))
     869              :             {
     870              :               /* Remove an useless move insn.  IRA can generate move
     871              :                  insns involving pseudos.  It is better remove them
     872              :                  earlier to speed up compiler a bit.  It is also
     873              :                  better to do it here as they might not pass final RTL
     874              :                  check in LRA, (e.g. insn moving a control register
     875              :                  into itself).  */
     876     11428396 :               lra_invalidate_insn_data (insn);
     877     11428396 :               delete_insn (insn);
     878              :             }
     879              :         }
     880      1515921 : }
        

Generated by: LCOV version 2.5.0-beta

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