LCOV - code coverage report
Current view: top level - gcc - ira-emit.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 93.9 % 690 648
Test Date: 2026-02-28 14:20:25 Functions: 93.5 % 31 29
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /* Integrated Register Allocator.  Changing code and generating moves.
       2              :    Copyright (C) 2006-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              : /* When we have more one region, we need to change the original RTL
      22              :    code after coloring.  Let us consider two allocnos representing the
      23              :    same pseudo-register outside and inside a region respectively.
      24              :    They can get different hard-registers.  The reload pass works on
      25              :    pseudo registers basis and there is no way to say the reload that
      26              :    pseudo could be in different registers and it is even more
      27              :    difficult to say in what places of the code the pseudo should have
      28              :    particular hard-registers.  So in this case IRA has to create and
      29              :    use a new pseudo-register inside the region and adds code to move
      30              :    allocno values on the region's borders.  This is done by the code
      31              :    in this file.
      32              : 
      33              :    The code makes top-down traversal of the regions and generate new
      34              :    pseudos and the move code on the region borders.  In some
      35              :    complicated cases IRA can create a new pseudo used temporarily to
      36              :    move allocno values when a swap of values stored in two
      37              :    hard-registers is needed (e.g. two allocnos representing different
      38              :    pseudos outside region got respectively hard registers 1 and 2 and
      39              :    the corresponding allocnos inside the region got respectively hard
      40              :    registers 2 and 1).  At this stage, the new pseudo is marked as
      41              :    spilled.
      42              : 
      43              :    IRA still creates the pseudo-register and the moves on the region
      44              :    borders even when the both corresponding allocnos were assigned to
      45              :    the same hard-register.  It is done because, if the reload pass for
      46              :    some reason spills a pseudo-register representing the original
      47              :    pseudo outside or inside the region, the effect will be smaller
      48              :    because another pseudo will still be in the hard-register.  In most
      49              :    cases, this is better then spilling the original pseudo in its
      50              :    whole live-range.  If reload does not change the allocation for the
      51              :    two pseudo-registers, the trivial move will be removed by
      52              :    post-reload optimizations.
      53              : 
      54              :    IRA does not generate a new pseudo and moves for the allocno values
      55              :    if the both allocnos representing an original pseudo inside and
      56              :    outside region assigned to the same hard register when the register
      57              :    pressure in the region for the corresponding pressure class is less
      58              :    than number of available hard registers for given pressure class.
      59              : 
      60              :    IRA also does some optimizations to remove redundant moves which is
      61              :    transformed into stores by the reload pass on CFG edges
      62              :    representing exits from the region.
      63              : 
      64              :    IRA tries to reduce duplication of code generated on CFG edges
      65              :    which are enters and exits to/from regions by moving some code to
      66              :    the edge sources or destinations when it is possible.  */
      67              : 
      68              : #include "config.h"
      69              : #include "system.h"
      70              : #include "coretypes.h"
      71              : #include "backend.h"
      72              : #include "rtl.h"
      73              : #include "tree.h"
      74              : #include "predict.h"
      75              : #include "df.h"
      76              : #include "insn-config.h"
      77              : #include "regs.h"
      78              : #include "memmodel.h"
      79              : #include "ira.h"
      80              : #include "ira-int.h"
      81              : #include "cfgrtl.h"
      82              : #include "cfgbuild.h"
      83              : #include "expr.h"
      84              : #include "reload.h"
      85              : #include "cfgloop.h"
      86              : 
      87              : 
      88              : /* Data used to emit live range split insns and to flattening IR.  */
      89              : ira_emit_data_t ira_allocno_emit_data;
      90              : 
      91              : /* Definitions for vectors of pointers.  */
      92              : typedef void *void_p;
      93              : 
      94              : /* Pointers to data allocated for allocnos being created during
      95              :    emitting.  Usually there are quite few such allocnos because they
      96              :    are created only for resolving loop in register shuffling.  */
      97              : static vec<void_p> new_allocno_emit_data_vec;
      98              : 
      99              : /* Allocate and initiate the emit data.  */
     100              : void
     101      1471362 : ira_initiate_emit_data (void)
     102              : {
     103      1471362 :   ira_allocno_t a;
     104      1471362 :   ira_allocno_iterator ai;
     105              : 
     106      1471362 :   ira_allocno_emit_data
     107      1471362 :     = (ira_emit_data_t) ira_allocate (ira_allocnos_num
     108              :                                       * sizeof (struct ira_emit_data));
     109      1471362 :   memset (ira_allocno_emit_data, 0,
     110      1471362 :           ira_allocnos_num * sizeof (struct ira_emit_data));
     111     37930378 :   FOR_EACH_ALLOCNO (a, ai)
     112     36459016 :     ALLOCNO_ADD_DATA (a) = ira_allocno_emit_data + ALLOCNO_NUM (a);
     113      1471362 :   new_allocno_emit_data_vec.create (50);
     114              : 
     115      1471362 : }
     116              : 
     117              : /* Free the emit data.  */
     118              : void
     119      1471362 : ira_finish_emit_data (void)
     120              : {
     121      1471362 :   void_p p;
     122      1471362 :   ira_allocno_t a;
     123      1471362 :   ira_allocno_iterator ai;
     124              : 
     125      1471362 :   ira_free (ira_allocno_emit_data);
     126     37935239 :   FOR_EACH_ALLOCNO (a, ai)
     127     36463877 :     ALLOCNO_ADD_DATA (a) = NULL;
     128      1476223 :   for (;new_allocno_emit_data_vec.length () != 0;)
     129              :     {
     130         4861 :       p = new_allocno_emit_data_vec.pop ();
     131         4861 :       ira_free (p);
     132              :     }
     133      1471362 :   new_allocno_emit_data_vec.release ();
     134      1471362 : }
     135              : 
     136              : /* Create and return a new allocno with given REGNO and
     137              :    LOOP_TREE_NODE.  Allocate emit data for it.  */
     138              : static ira_allocno_t
     139         4861 : create_new_allocno (int regno, ira_loop_tree_node_t loop_tree_node)
     140              : {
     141         4861 :   ira_allocno_t a;
     142              : 
     143         4861 :   a = ira_create_allocno (regno, false, loop_tree_node);
     144         4861 :   ALLOCNO_ADD_DATA (a) = ira_allocate (sizeof (struct ira_emit_data));
     145         4861 :   memset (ALLOCNO_ADD_DATA (a), 0, sizeof (struct ira_emit_data));
     146         4861 :   new_allocno_emit_data_vec.safe_push (ALLOCNO_ADD_DATA (a));
     147         4861 :   return a;
     148              : }
     149              : 
     150              : 
     151              : 
     152              : /* See comments below.  */
     153              : typedef struct move *move_t;
     154              : 
     155              : /* The structure represents an allocno move.  Both allocnos have the
     156              :    same original regno but different allocation.  */
     157              : struct move
     158              : {
     159              :   /* The allocnos involved in the move.  */
     160              :   ira_allocno_t from, to;
     161              :   /* The next move in the move sequence.  */
     162              :   move_t next;
     163              :   /* Used for finding dependencies.  */
     164              :   bool visited_p;
     165              :   /* The size of the following array. */
     166              :   int deps_num;
     167              :   /* Moves on which given move depends on.  Dependency can be cyclic.
     168              :      It means we need a temporary to generates the moves.  Sequence
     169              :      A1->A2, B1->B2 where A1 and B2 are assigned to reg R1 and A2 and
     170              :      B1 are assigned to reg R2 is an example of the cyclic
     171              :      dependencies.  */
     172              :   move_t *deps;
     173              :   /* First insn generated for the move.  */
     174              :   rtx_insn *insn;
     175              : };
     176              : 
     177              : /* Array of moves (indexed by BB index) which should be put at the
     178              :    start/end of the corresponding basic blocks.  */
     179              : static move_t *at_bb_start, *at_bb_end;
     180              : 
     181              : /* Max regno before renaming some pseudo-registers.  For example, the
     182              :    same pseudo-register can be renamed in a loop if its allocation is
     183              :    different outside the loop.  */
     184              : static int max_regno_before_changing;
     185              : 
     186              : /* Return new move of allocnos TO and FROM.  */
     187              : static move_t
     188      2234062 : create_move (ira_allocno_t to, ira_allocno_t from)
     189              : {
     190      2234062 :   move_t move;
     191              : 
     192      2234062 :   move = (move_t) ira_allocate (sizeof (struct move));
     193      2234062 :   move->deps = NULL;
     194      2234062 :   move->deps_num = 0;
     195      2234062 :   move->to = to;
     196      2234062 :   move->from = from;
     197      2234062 :   move->next = NULL;
     198      2234062 :   move->insn = NULL;
     199      2234062 :   move->visited_p = false;
     200      2234062 :   return move;
     201              : }
     202              : 
     203              : /* Free memory for MOVE and its dependencies.  */
     204              : static void
     205      2234062 : free_move (move_t move)
     206              : {
     207      2234062 :   if (move->deps != NULL)
     208      2047025 :     ira_free (move->deps);
     209      2234062 :   ira_free (move);
     210      2234062 : }
     211              : 
     212              : /* Free memory for list of the moves given by its HEAD.  */
     213              : static void
     214     10863366 : free_move_list (move_t head)
     215              : {
     216     10863366 :   move_t next;
     217              : 
     218     13097428 :   for (; head != NULL; head = next)
     219              :     {
     220      2234062 :       next = head->next;
     221      2234062 :       free_move (head);
     222              :     }
     223            0 : }
     224              : 
     225              : /* Return TRUE if the move list LIST1 and LIST2 are equal (two
     226              :    moves are equal if they involve the same allocnos).  */
     227              : static bool
     228      2913165 : eq_move_lists_p (move_t list1, move_t list2)
     229              : {
     230      3043109 :   for (; list1 != NULL && list2 != NULL;
     231       129944 :        list1 = list1->next, list2 = list2->next)
     232       132728 :     if (list1->from != list2->from || list1->to != list2->to)
     233              :       return false;
     234      2910381 :   return list1 == list2;
     235              : }
     236              : 
     237              : /* Print move list LIST into file F.  */
     238              : static void
     239            0 : print_move_list (FILE *f, move_t list)
     240              : {
     241            0 :   for (; list != NULL; list = list->next)
     242            0 :     fprintf (f, " a%dr%d->a%dr%d",
     243            0 :              ALLOCNO_NUM (list->from), ALLOCNO_REGNO (list->from),
     244            0 :              ALLOCNO_NUM (list->to), ALLOCNO_REGNO (list->to));
     245            0 :   fprintf (f, "\n");
     246            0 : }
     247              : 
     248              : extern void ira_debug_move_list (move_t list);
     249              : 
     250              : /* Print move list LIST into stderr.  */
     251              : void
     252            0 : ira_debug_move_list (move_t list)
     253              : {
     254            0 :   print_move_list (stderr, list);
     255            0 : }
     256              : 
     257              : /* This recursive function changes pseudo-registers in *LOC if it is
     258              :    necessary.  The function returns TRUE if a change was done.  */
     259              : static bool
     260    208563611 : change_regs (rtx *loc)
     261              : {
     262    208563611 :   int i, regno, result = false;
     263    208563611 :   const char *fmt;
     264    208563611 :   enum rtx_code code;
     265    208563611 :   rtx reg;
     266              : 
     267    208563611 :   if (*loc == NULL_RTX)
     268              :     return false;
     269    181319071 :   code = GET_CODE (*loc);
     270    181319071 :   if (code == REG)
     271              :     {
     272     45155971 :       regno = REGNO (*loc);
     273     45155971 :       if (regno < FIRST_PSEUDO_REGISTER)
     274              :         return false;
     275     24626448 :       if (regno >= max_regno_before_changing)
     276              :         /* It is a shared register which was changed already.  */
     277              :         return false;
     278     24626336 :       if (ira_curr_regno_allocno_map[regno] == NULL)
     279              :         return false;
     280     24618939 :       reg = allocno_emit_reg (ira_curr_regno_allocno_map[regno]);
     281     24618939 :       if (reg == *loc)
     282              :         return false;
     283      3249536 :       *loc = reg;
     284      3249536 :       return true;
     285              :     }
     286              : 
     287    136163100 :   fmt = GET_RTX_FORMAT (code);
     288    496541676 :   for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
     289              :     {
     290    360378576 :       if (fmt[i] == 'e')
     291    185488418 :         result = change_regs (&XEXP (*loc, i)) || result;
     292    185040984 :       else if (fmt[i] == 'E')
     293              :         {
     294      3190358 :           int j;
     295              : 
     296     10053130 :           for (j = XVECLEN (*loc, i) - 1; j >= 0; j--)
     297      7411917 :             result = change_regs (&XVECEXP (*loc, i, j)) || result;
     298              :         }
     299              :     }
     300    136163100 :   return result;
     301              : }
     302              : 
     303              : static bool
     304     26363247 : change_regs_in_insn (rtx_insn **insn_ptr)
     305              : {
     306     26363247 :   rtx rtx = *insn_ptr;
     307     26363247 :   bool result = change_regs (&rtx);
     308     26363247 :   *insn_ptr = as_a <rtx_insn *> (rtx);
     309     26363247 :   return result;
     310              : }
     311              : 
     312              : /* Attach MOVE to the edge E.  The move is attached to the head of the
     313              :    list if HEAD_P is TRUE.  */
     314              : static void
     315      2229201 : add_to_edge_list (edge e, move_t move, bool head_p)
     316              : {
     317      2229201 :   move_t last;
     318              : 
     319            0 :   if (head_p || e->aux == NULL)
     320              :     {
     321      2229201 :       move->next = (move_t) e->aux;
     322            0 :       e->aux = move;
     323              :     }
     324              :   else
     325              :     {
     326            0 :       for (last = (move_t) e->aux; last->next != NULL; last = last->next)
     327              :         ;
     328            0 :       last->next = move;
     329            0 :       move->next = NULL;
     330              :     }
     331            0 : }
     332              : 
     333              : /* Create and return new pseudo-register with the same attributes as
     334              :    ORIGINAL_REG.  */
     335              : rtx
     336      1239993 : ira_create_new_reg (rtx original_reg)
     337              : {
     338      1239993 :   rtx new_reg;
     339              : 
     340      1239993 :   new_reg = gen_reg_rtx (GET_MODE (original_reg));
     341      1239993 :   ORIGINAL_REGNO (new_reg) = ORIGINAL_REGNO (original_reg);
     342      1239993 :   REG_USERVAR_P (new_reg) = REG_USERVAR_P (original_reg);
     343      1239993 :   REG_POINTER (new_reg) = REG_POINTER (original_reg);
     344      1239993 :   REG_ATTRS (new_reg) = REG_ATTRS (original_reg);
     345      1239993 :   if (internal_flag_ira_verbose > 3 && ira_dump_file != NULL)
     346            2 :     fprintf (ira_dump_file, "      Creating newreg=%i from oldreg=%i\n",
     347              :              REGNO (new_reg), REGNO (original_reg));
     348      1239993 :   ira_expand_reg_equiv ();
     349      1239993 :   return new_reg;
     350              : }
     351              : 
     352              : /* Return TRUE if loop given by SUBNODE inside the loop given by
     353              :    NODE.  */
     354              : static bool
     355      8026852 : subloop_tree_node_p (ira_loop_tree_node_t subnode, ira_loop_tree_node_t node)
     356              : {
     357     25303274 :   for (; subnode != NULL; subnode = subnode->parent)
     358     19083730 :     if (subnode == node)
     359              :       return true;
     360              :   return false;
     361              : }
     362              : 
     363              : /* Set up member `reg' to REG for allocnos which has the same regno as
     364              :    ALLOCNO and which are inside the loop corresponding to ALLOCNO. */
     365              : static void
     366      1165348 : set_allocno_reg (ira_allocno_t allocno, rtx reg)
     367              : {
     368      1165348 :   int regno;
     369      1165348 :   ira_allocno_t a;
     370      1165348 :   ira_loop_tree_node_t node;
     371              : 
     372      1165348 :   node = ALLOCNO_LOOP_TREE_NODE (allocno);
     373      1165348 :   for (a = ira_regno_allocno_map[ALLOCNO_REGNO (allocno)];
     374      9192200 :        a != NULL;
     375      8026852 :        a = ALLOCNO_NEXT_REGNO_ALLOCNO (a))
     376     16053704 :     if (subloop_tree_node_p (ALLOCNO_LOOP_TREE_NODE (a), node))
     377      1807308 :       ALLOCNO_EMIT_DATA (a)->reg = reg;
     378      1167984 :   for (a = ALLOCNO_CAP (allocno); a != NULL; a = ALLOCNO_CAP (a))
     379         2636 :     ALLOCNO_EMIT_DATA (a)->reg = reg;
     380              :   regno = ALLOCNO_REGNO (allocno);
     381              :   for (a = allocno;;)
     382              :     {
     383      2621306 :       if (a == NULL || (a = ALLOCNO_CAP (a)) == NULL)
     384              :         {
     385      2319501 :           node = node->parent;
     386      2319501 :           if (node == NULL)
     387              :             break;
     388      1700795 :           a = node->regno_allocno_map[regno];
     389              :         }
     390      2002600 :       if (a == NULL)
     391       299275 :         continue;
     392      1703325 :       if (ALLOCNO_EMIT_DATA (a)->child_renamed_p)
     393              :         break;
     394      1156683 :       ALLOCNO_EMIT_DATA (a)->child_renamed_p = true;
     395              :     }
     396      1165348 : }
     397              : 
     398              : /* Return true if there is an entry to given loop not from its parent
     399              :    (or grandparent) block.  For example, it is possible for two
     400              :    adjacent loops inside another loop.  */
     401              : static bool
     402       203852 : entered_from_non_parent_p (ira_loop_tree_node_t loop_node)
     403              : {
     404       203852 :   ira_loop_tree_node_t bb_node, src_loop_node, parent;
     405       203852 :   edge e;
     406       203852 :   edge_iterator ei;
     407              : 
     408       203852 :   for (bb_node = loop_node->children;
     409      3130681 :        bb_node != NULL;
     410      2926829 :        bb_node = bb_node->next)
     411      2927412 :     if (bb_node->bb != NULL)
     412              :       {
     413      6965991 :         FOR_EACH_EDGE (e, ei, bb_node->bb->preds)
     414      4207414 :           if (e->src != ENTRY_BLOCK_PTR_FOR_FN (cfun)
     415      4207414 :               && (src_loop_node = IRA_BB_NODE (e->src)->parent) != loop_node)
     416              :             {
     417       492481 :               for (parent = src_loop_node->parent;
     418       639393 :                    parent != NULL;
     419       146912 :                    parent = parent->parent)
     420       448772 :                 if (parent == loop_node)
     421              :                   break;
     422       492481 :               if (parent != NULL)
     423              :                 /* That is an exit from a nested loop -- skip it.  */
     424       301860 :                 continue;
     425       190621 :               for (parent = loop_node->parent;
     426       191620 :                    parent != NULL;
     427          999 :                    parent = parent->parent)
     428       191037 :                 if (src_loop_node == parent)
     429              :                   break;
     430              :               if (parent == NULL)
     431              :                 return true;
     432              :             }
     433              :       }
     434              :   return false;
     435              : }
     436              : 
     437              : /* Set up ENTERED_FROM_NON_PARENT_P for each loop region.  */
     438              : static void
     439        35600 : setup_entered_from_non_parent_p (void)
     440              : {
     441        35600 :   unsigned int i;
     442        35600 :   loop_p loop;
     443              : 
     444        35600 :   ira_assert (current_loops != NULL);
     445       293072 :   FOR_EACH_VEC_SAFE_ELT (get_loops (cfun), i, loop)
     446       221872 :     if (ira_loop_nodes[i].regno_allocno_map != NULL)
     447       203852 :       ira_loop_nodes[i].entered_from_non_parent_p
     448       203852 :         = entered_from_non_parent_p (&ira_loop_nodes[i]);
     449        35600 : }
     450              : 
     451              : /* Return TRUE if move of SRC_ALLOCNO (assigned to hard register) to
     452              :    DEST_ALLOCNO (assigned to memory) can be removed because it does
     453              :    not change value of the destination.  One possible reason for this
     454              :    is the situation when SRC_ALLOCNO is not modified in the
     455              :    corresponding loop.  */
     456              : static bool
     457       126001 : store_can_be_removed_p (ira_allocno_t src_allocno, ira_allocno_t dest_allocno)
     458              : {
     459       126001 :   int regno, orig_regno;
     460       126001 :   ira_allocno_t a;
     461       126001 :   ira_loop_tree_node_t node;
     462              : 
     463       126001 :   ira_assert (ALLOCNO_CAP_MEMBER (src_allocno) == NULL
     464              :               && ALLOCNO_CAP_MEMBER (dest_allocno) == NULL);
     465       126001 :   orig_regno = ALLOCNO_REGNO (src_allocno);
     466       126001 :   regno = REGNO (allocno_emit_reg (dest_allocno));
     467       126001 :   for (node = ALLOCNO_LOOP_TREE_NODE (src_allocno);
     468       179766 :        node != NULL;
     469        53765 :        node = node->parent)
     470              :     {
     471       179766 :       a = node->regno_allocno_map[orig_regno];
     472       179766 :       ira_assert (a != NULL);
     473       179766 :       if (REGNO (allocno_emit_reg (a)) == (unsigned) regno)
     474              :         /* We achieved the destination and everything is ok.  */
     475              :         return true;
     476       154197 :       else if (bitmap_bit_p (node->modified_regnos, orig_regno))
     477              :         return false;
     478        53860 :       else if (node->entered_from_non_parent_p)
     479              :         /* If there is a path from a destination loop block to the
     480              :            source loop header containing basic blocks of non-parents
     481              :            (grandparents) of the source loop, we should have checked
     482              :            modifications of the pseudo on this path too to decide
     483              :            about possibility to remove the store.  It could be done by
     484              :            solving a data-flow problem.  Unfortunately such global
     485              :            solution would complicate IR flattening.  Therefore we just
     486              :            prohibit removal of the store in such complicated case.  */
     487              :         return false;
     488              :     }
     489              :   /* It is actually a loop entry -- do not remove the store.  */
     490              :   return false;
     491              : }
     492              : 
     493              : /* Generate and attach moves to the edge E.  This looks at the final
     494              :    regnos of allocnos living on the edge with the same original regno
     495              :    to figure out when moves should be generated.  */
     496              : static void
     497      4172619 : generate_edge_moves (edge e)
     498              : {
     499      4172619 :   ira_loop_tree_node_t src_loop_node, dest_loop_node;
     500      4172619 :   unsigned int regno;
     501      4172619 :   bitmap_iterator bi;
     502      4172619 :   ira_allocno_t src_allocno, dest_allocno, *src_map, *dest_map;
     503      4172619 :   move_t move;
     504      4172619 :   bitmap regs_live_in_dest, regs_live_out_src;
     505              : 
     506      4172619 :   src_loop_node = IRA_BB_NODE (e->src)->parent;
     507      4172619 :   dest_loop_node = IRA_BB_NODE (e->dest)->parent;
     508      4172619 :   e->aux = NULL;
     509      4172619 :   if (src_loop_node == dest_loop_node)
     510      3679922 :     return;
     511       492697 :   src_map = src_loop_node->regno_allocno_map;
     512       492697 :   dest_map = dest_loop_node->regno_allocno_map;
     513       492697 :   regs_live_in_dest = df_get_live_in (e->dest);
     514       492697 :   regs_live_out_src = df_get_live_out (e->src);
     515      7335957 :   EXECUTE_IF_SET_IN_REG_SET (regs_live_in_dest,
     516              :                              FIRST_PSEUDO_REGISTER, regno, bi)
     517      6843260 :     if (bitmap_bit_p (regs_live_out_src, regno))
     518              :       {
     519      6843260 :         src_allocno = src_map[regno];
     520      6843260 :         dest_allocno = dest_map[regno];
     521      6843260 :         if (REGNO (allocno_emit_reg (src_allocno))
     522      6843260 :             == REGNO (allocno_emit_reg (dest_allocno)))
     523      4588490 :           continue;
     524              :         /* Remove unnecessary stores at the region exit.  We should do
     525              :            this for readonly memory for sure and this is guaranteed by
     526              :            that we never generate moves on region borders (see
     527              :            checking in function change_loop).  */
     528      2280339 :         if (ALLOCNO_HARD_REGNO (dest_allocno) < 0
     529       126090 :             && ALLOCNO_HARD_REGNO (src_allocno) >= 0
     530      2380771 :             && store_can_be_removed_p (src_allocno, dest_allocno))
     531              :           {
     532        25569 :             ALLOCNO_EMIT_DATA (src_allocno)->mem_optimized_dest = dest_allocno;
     533        25569 :             ALLOCNO_EMIT_DATA (dest_allocno)->mem_optimized_dest_p = true;
     534        25569 :             if (internal_flag_ira_verbose > 3 && ira_dump_file != NULL)
     535            0 :               fprintf (ira_dump_file, "      Remove r%d:a%d->a%d(mem)\n",
     536              :                        regno, ALLOCNO_NUM (src_allocno),
     537              :                        ALLOCNO_NUM (dest_allocno));
     538        25569 :             continue;
     539              :           }
     540      2229201 :         move = create_move (dest_allocno, src_allocno);
     541      2229201 :         add_to_edge_list (e, move, true);
     542              :     }
     543              : }
     544              : 
     545              : /* Bitmap of allocnos local for the current loop.  */
     546              : static bitmap local_allocno_bitmap;
     547              : 
     548              : /* This bitmap is used to find that we need to generate and to use a
     549              :    new pseudo-register when processing allocnos with the same original
     550              :    regno.  */
     551              : static bitmap used_regno_bitmap;
     552              : 
     553              : /* This bitmap contains regnos of allocnos which were renamed locally
     554              :    because the allocnos correspond to disjoint live ranges in loops
     555              :    with a common parent.  */
     556              : static bitmap renamed_regno_bitmap;
     557              : 
     558              : /* Change (if necessary) pseudo-registers inside loop given by loop
     559              :    tree node NODE.  */
     560              : static void
     561      2963143 : change_loop (ira_loop_tree_node_t node)
     562              : {
     563      2963143 :   bitmap_iterator bi;
     564      2963143 :   unsigned int i;
     565      2963143 :   int regno;
     566      2963143 :   bool used_p;
     567      2963143 :   ira_allocno_t allocno, parent_allocno, *map;
     568      2963143 :   rtx_insn *insn;
     569      2963143 :   rtx original_reg;
     570      2963143 :   enum reg_class aclass, pclass;
     571      2963143 :   ira_loop_tree_node_t parent;
     572              : 
     573      2963143 :   if (node != ira_loop_tree_root)
     574              :     {
     575      2927543 :       ira_assert (current_loops != NULL);
     576              : 
     577      2927543 :       if (node->bb != NULL)
     578              :         {
     579     34210311 :           FOR_BB_INSNS (node->bb, insn)
     580     31451020 :             if (INSN_P (insn) && change_regs_in_insn (&insn))
     581              :               {
     582      2242324 :                 df_insn_rescan (insn);
     583      2242324 :                 df_notes_rescan (insn);
     584              :               }
     585      2759291 :           return;
     586              :         }
     587              : 
     588       168252 :       if (internal_flag_ira_verbose > 3 && ira_dump_file != NULL)
     589            0 :         fprintf (ira_dump_file,
     590              :                  "      Changing RTL for loop %d (header bb%d)\n",
     591            0 :                  node->loop_num, node->loop->header->index);
     592              : 
     593       168252 :       parent = ira_curr_loop_tree_node->parent;
     594       168252 :       map = parent->regno_allocno_map;
     595      3311800 :       EXECUTE_IF_SET_IN_REG_SET (ira_curr_loop_tree_node->border_allocnos,
     596              :                                  0, i, bi)
     597              :         {
     598      3143548 :           allocno = ira_allocnos[i];
     599      3143548 :           regno = ALLOCNO_REGNO (allocno);
     600      3143548 :           aclass = ALLOCNO_CLASS (allocno);
     601      3143548 :           pclass = ira_pressure_class_translate[aclass];
     602      3143548 :           parent_allocno = map[regno];
     603      3143548 :           ira_assert (regno < ira_reg_equiv_len);
     604              :           /* We generate the same hard register move because the
     605              :              reload pass can put an allocno into memory in this case
     606              :              we will have live range splitting.  If it does not happen
     607              :              such the same hard register moves will be removed.  The
     608              :              worst case when the both allocnos are put into memory by
     609              :              the reload is very rare.  */
     610      5123537 :           if (parent_allocno != NULL
     611      3143548 :               && (ALLOCNO_HARD_REGNO (allocno)
     612      3143548 :                   == ALLOCNO_HARD_REGNO (parent_allocno))
     613      6104239 :               && (ALLOCNO_HARD_REGNO (allocno) < 0
     614      1154715 :                   || (parent->reg_pressure[pclass] + 1
     615      1154715 :                       <= ira_class_hard_regs_num[pclass])
     616      1071293 :                   || TEST_HARD_REG_BIT (ira_prohibited_mode_move_regs
     617      1071293 :                                         [ALLOCNO_MODE (allocno)],
     618              :                                         ALLOCNO_HARD_REGNO (allocno))
     619              :                   /* don't create copies because reload can spill an
     620              :                      allocno set by copy although the allocno will not
     621              :                      get memory slot.  */
     622      1071293 :                   || ira_equiv_no_lvalue_p (regno)
     623       988683 :                   || (pic_offset_table_rtx != NULL
     624        98528 :                       && (ALLOCNO_REGNO (allocno)
     625        98528 :                           == (int) REGNO (pic_offset_table_rtx)))))
     626      1979989 :             continue;
     627      1163559 :           original_reg = allocno_emit_reg (allocno);
     628      1163559 :           if (parent_allocno == NULL
     629      1163559 :               || (REGNO (allocno_emit_reg (parent_allocno))
     630      1163559 :                   == REGNO (original_reg)))
     631              :             {
     632      1163559 :               if (internal_flag_ira_verbose > 3 && ira_dump_file)
     633            0 :                 fprintf (ira_dump_file, "  %i vs parent %i:",
     634            0 :                          ALLOCNO_HARD_REGNO (allocno),
     635            0 :                          ALLOCNO_HARD_REGNO (parent_allocno));
     636      1163559 :               set_allocno_reg (allocno, ira_create_new_reg (original_reg));
     637              :             }
     638              :         }
     639              :     }
     640              :   /* Rename locals: Local allocnos with same regno in different loops
     641              :      might get the different hard register.  So we need to change
     642              :      ALLOCNO_REG.  */
     643       203852 :   bitmap_and_compl (local_allocno_bitmap,
     644       203852 :                     ira_curr_loop_tree_node->all_allocnos,
     645       203852 :                     ira_curr_loop_tree_node->border_allocnos);
     646      8742402 :   EXECUTE_IF_SET_IN_REG_SET (local_allocno_bitmap, 0, i, bi)
     647              :     {
     648      8538550 :       allocno = ira_allocnos[i];
     649      8538550 :       regno = ALLOCNO_REGNO (allocno);
     650      8538550 :       if (ALLOCNO_CAP_MEMBER (allocno) != NULL)
     651      3704601 :         continue;
     652      4833949 :       used_p = !bitmap_set_bit (used_regno_bitmap, regno);
     653      4833949 :       ALLOCNO_EMIT_DATA (allocno)->somewhere_renamed_p = true;
     654      4833949 :       if (! used_p)
     655      4832160 :         continue;
     656         1789 :       bitmap_set_bit (renamed_regno_bitmap, regno);
     657         1789 :       set_allocno_reg (allocno, ira_create_new_reg (allocno_emit_reg (allocno)));
     658              :     }
     659              : }
     660              : 
     661              : /* Process to set up flag somewhere_renamed_p.  */
     662              : static void
     663        35600 : set_allocno_somewhere_renamed_p (void)
     664              : {
     665        35600 :   unsigned int regno;
     666        35600 :   ira_allocno_t allocno;
     667        35600 :   ira_allocno_iterator ai;
     668              : 
     669     11717698 :   FOR_EACH_ALLOCNO (allocno, ai)
     670              :     {
     671     11682098 :       regno = ALLOCNO_REGNO (allocno);
     672     11682098 :       if (bitmap_bit_p (renamed_regno_bitmap, regno)
     673     11682098 :           && REGNO (allocno_emit_reg (allocno)) == regno)
     674         2734 :         ALLOCNO_EMIT_DATA (allocno)->somewhere_renamed_p = true;
     675              :     }
     676        35600 : }
     677              : 
     678              : /* Return TRUE if move lists on all edges given in vector VEC are
     679              :    equal.  */
     680              : static bool
     681      5438067 : eq_edge_move_lists_p (vec<edge, va_gc> *vec)
     682              : {
     683      5438067 :   move_t list;
     684      5438067 :   int i;
     685              : 
     686      5438067 :   list = (move_t) EDGE_I (vec, 0)->aux;
     687      8033904 :   for (i = EDGE_COUNT (vec) - 1; i > 0; i--)
     688      2913165 :     if (! eq_move_lists_p (list, (move_t) EDGE_I (vec, i)->aux))
     689              :       return false;
     690              :   return true;
     691              : }
     692              : 
     693              : /* Look at all entry edges (if START_P) or exit edges of basic block
     694              :    BB and put move lists at the BB start or end if it is possible.  In
     695              :    other words, this decreases code duplication of allocno moves.  */
     696              : static void
     697      5518582 : unify_moves (basic_block bb, bool start_p)
     698              : {
     699      5518582 :   int i;
     700      5518582 :   edge e;
     701      5518582 :   move_t list;
     702      5518582 :   vec<edge, va_gc> *vec;
     703              : 
     704      5518582 :   vec = (start_p ? bb->preds : bb->succs);
     705      5518582 :   if (EDGE_COUNT (vec) == 0 || ! eq_edge_move_lists_p (vec))
     706              :     return;
     707      5120739 :   e = EDGE_I (vec, 0);
     708      5120739 :   list = (move_t) e->aux;
     709      5120739 :   if (! start_p && control_flow_insn_p (BB_END (bb)))
     710              :     return;
     711      3048046 :   e->aux = NULL;
     712      4181802 :   for (i = EDGE_COUNT (vec) - 1; i > 0; i--)
     713              :     {
     714      1133756 :       e = EDGE_I (vec, i);
     715      1133756 :       free_move_list ((move_t) e->aux);
     716      1133756 :       e->aux = NULL;
     717              :     }
     718      3048046 :   if (start_p)
     719      2547748 :     at_bb_start[bb->index] = list;
     720              :   else
     721       500298 :     at_bb_end[bb->index] = list;
     722              : }
     723              : 
     724              : /* Last move (in move sequence being processed) setting up the
     725              :    corresponding hard register.  */
     726              : static move_t hard_regno_last_set[FIRST_PSEUDO_REGISTER];
     727              : 
     728              : /* If the element value is equal to CURR_TICK then the corresponding
     729              :    element in `hard_regno_last_set' is defined and correct.  */
     730              : static int hard_regno_last_set_check[FIRST_PSEUDO_REGISTER];
     731              : 
     732              : /* Last move (in move sequence being processed) setting up the
     733              :    corresponding allocno.  */
     734              : static move_t *allocno_last_set;
     735              : 
     736              : /* If the element value is equal to CURR_TICK then the corresponding
     737              :    element in . `allocno_last_set' is defined and correct.  */
     738              : static int *allocno_last_set_check;
     739              : 
     740              : /* Definition of vector of moves.  */
     741              : 
     742              : /* This vec contains moves sorted topologically (depth-first) on their
     743              :    dependency graph.  */
     744              : static vec<move_t> move_vec;
     745              : 
     746              : /* The variable value is used to check correctness of values of
     747              :    elements of arrays `hard_regno_last_set' and
     748              :    `allocno_last_set_check'.  */
     749              : static int curr_tick;
     750              : 
     751              : /* This recursive function traverses dependencies of MOVE and produces
     752              :    topological sorting (in depth-first order).  */
     753              : static void
     754      2267940 : traverse_moves (move_t move)
     755              : {
     756      2267940 :   int i;
     757              : 
     758      2267940 :   if (move->visited_p)
     759              :     return;
     760      2194417 :   move->visited_p = true;
     761      2267940 :   for (i = move->deps_num - 1; i >= 0; i--)
     762        73523 :     traverse_moves (move->deps[i]);
     763      2194417 :   move_vec.safe_push (move);
     764              : }
     765              : 
     766              : /* Remove unnecessary moves in the LIST, makes topological sorting,
     767              :    and removes cycles on hard reg dependencies by introducing new
     768              :    allocnos assigned to memory and additional moves.  It returns the
     769              :    result move list.  */
     770              : static move_t
     771       390624 : modify_move_list (move_t list)
     772              : {
     773       390624 :   int i, n, nregs, hard_regno;
     774       390624 :   ira_allocno_t to, from;
     775       390624 :   move_t move, new_move, set_move, first, last;
     776              : 
     777       390624 :   if (list == NULL)
     778              :     return NULL;
     779              :   /* Create move deps.  */
     780       390624 :   curr_tick++;
     781      2585041 :   for (move = list; move != NULL; move = move->next)
     782              :     {
     783      2194417 :       to = move->to;
     784      2194417 :       if ((hard_regno = ALLOCNO_HARD_REGNO (to)) < 0)
     785        99826 :         continue;
     786      2094591 :       nregs = hard_regno_nregs (hard_regno, ALLOCNO_MODE (to));
     787      4203540 :       for (i = 0; i < nregs; i++)
     788              :         {
     789      2108949 :           hard_regno_last_set[hard_regno + i] = move;
     790      2108949 :           hard_regno_last_set_check[hard_regno + i] = curr_tick;
     791              :         }
     792              :     }
     793      2585041 :   for (move = list; move != NULL; move = move->next)
     794              :     {
     795      2194417 :       from = move->from;
     796      2194417 :       to = move->to;
     797      2194417 :       if ((hard_regno = ALLOCNO_HARD_REGNO (from)) >= 0)
     798              :         {
     799      2047025 :           nregs = hard_regno_nregs (hard_regno, ALLOCNO_MODE (from));
     800      4106804 :           for (n = i = 0; i < nregs; i++)
     801      2059779 :             if (hard_regno_last_set_check[hard_regno + i] == curr_tick
     802      1935375 :                 && (ALLOCNO_REGNO (hard_regno_last_set[hard_regno + i]->to)
     803      1935375 :                     != ALLOCNO_REGNO (from)))
     804        73523 :               n++;
     805      2047025 :           move->deps = (move_t *) ira_allocate (n * sizeof (move_t));
     806      4106804 :           for (n = i = 0; i < nregs; i++)
     807      2059779 :             if (hard_regno_last_set_check[hard_regno + i] == curr_tick
     808      1935375 :                 && (ALLOCNO_REGNO (hard_regno_last_set[hard_regno + i]->to)
     809      1935375 :                     != ALLOCNO_REGNO (from)))
     810        73523 :               move->deps[n++] = hard_regno_last_set[hard_regno + i];
     811      2047025 :           move->deps_num = n;
     812              :         }
     813              :     }
     814              :   /* Topological sorting:  */
     815       390624 :   move_vec.truncate (0);
     816      2975665 :   for (move = list; move != NULL; move = move->next)
     817      2194417 :     traverse_moves (move);
     818       390624 :   last = NULL;
     819      2975665 :   for (i = (int) move_vec.length () - 1; i >= 0; i--)
     820              :     {
     821      2194417 :       move = move_vec[i];
     822      2194417 :       move->next = NULL;
     823      2194417 :       if (last != NULL)
     824      1803793 :         last->next = move;
     825      2194417 :       last = move;
     826              :     }
     827       390624 :   first = move_vec.last ();
     828              :   /* Removing cycles:  */
     829       390624 :   curr_tick++;
     830       390624 :   move_vec.truncate (0);
     831      2585041 :   for (move = first; move != NULL; move = move->next)
     832              :     {
     833      2194417 :       from = move->from;
     834      2194417 :       to = move->to;
     835      2194417 :       if ((hard_regno = ALLOCNO_HARD_REGNO (from)) >= 0)
     836              :         {
     837      2047025 :           nregs = hard_regno_nregs (hard_regno, ALLOCNO_MODE (from));
     838      4106804 :           for (i = 0; i < nregs; i++)
     839      2059779 :             if (hard_regno_last_set_check[hard_regno + i] == curr_tick
     840         4861 :                 && ALLOCNO_HARD_REGNO
     841              :                    (hard_regno_last_set[hard_regno + i]->to) >= 0)
     842              :               {
     843         4861 :                 int n, j;
     844         4861 :                 ira_allocno_t new_allocno;
     845              : 
     846         4861 :                 set_move = hard_regno_last_set[hard_regno + i];
     847              :                 /* It does not matter what loop_tree_node (of TO or
     848              :                    FROM) to use for the new allocno because of
     849              :                    subsequent IRA internal representation
     850              :                    flattening.  */
     851         4861 :                 new_allocno
     852         4861 :                   = create_new_allocno (ALLOCNO_REGNO (set_move->to),
     853              :                                         ALLOCNO_LOOP_TREE_NODE (set_move->to));
     854         4861 :                 ALLOCNO_MODE (new_allocno) = ALLOCNO_MODE (set_move->to);
     855         4861 :                 ira_set_allocno_class (new_allocno,
     856         4861 :                                        ALLOCNO_CLASS (set_move->to));
     857         4861 :                 ira_create_allocno_objects (new_allocno);
     858         4861 :                 ALLOCNO_ASSIGNED_P (new_allocno) = true;
     859         4861 :                 ALLOCNO_HARD_REGNO (new_allocno) = -1;
     860         4861 :                 ALLOCNO_EMIT_DATA (new_allocno)->reg
     861         4861 :                   = ira_create_new_reg (allocno_emit_reg (set_move->to));
     862              : 
     863              :                 /* Make it possibly conflicting with all earlier
     864              :                    created allocnos.  Cases where temporary allocnos
     865              :                    created to remove the cycles are quite rare.  */
     866         4861 :                 n = ALLOCNO_NUM_OBJECTS (new_allocno);
     867         4861 :                 gcc_assert (n == ALLOCNO_NUM_OBJECTS (set_move->to));
     868         9722 :                 for (j = 0; j < n; j++)
     869              :                   {
     870         4861 :                     ira_object_t new_obj = ALLOCNO_OBJECT (new_allocno, j);
     871              : 
     872         4861 :                     OBJECT_MIN (new_obj) = 0;
     873         4861 :                     OBJECT_MAX (new_obj) = ira_objects_num - 1;
     874              :                   }
     875              : 
     876         4861 :                 new_move = create_move (set_move->to, new_allocno);
     877         4861 :                 set_move->to = new_allocno;
     878         4861 :                 move_vec.safe_push (new_move);
     879         4861 :                 ira_move_loops_num++;
     880         4861 :                 if (internal_flag_ira_verbose > 2 && ira_dump_file != NULL)
     881            0 :                   fprintf (ira_dump_file,
     882              :                            "    Creating temporary allocno a%dr%d\n",
     883              :                            ALLOCNO_NUM (new_allocno),
     884            0 :                            REGNO (allocno_emit_reg (new_allocno)));
     885              :               }
     886              :         }
     887      2194417 :       if ((hard_regno = ALLOCNO_HARD_REGNO (to)) < 0)
     888        99826 :         continue;
     889      2094591 :       nregs = hard_regno_nregs (hard_regno, ALLOCNO_MODE (to));
     890      4203540 :       for (i = 0; i < nregs; i++)
     891              :         {
     892      2108949 :           hard_regno_last_set[hard_regno + i] = move;
     893      2108949 :           hard_regno_last_set_check[hard_regno + i] = curr_tick;
     894              :         }
     895              :     }
     896       786109 :   for (i = (int) move_vec.length () - 1; i >= 0; i--)
     897              :     {
     898         4861 :       move = move_vec[i];
     899         4861 :       move->next = NULL;
     900         4861 :       last->next = move;
     901         4861 :       last = move;
     902              :     }
     903              :   return first;
     904              : }
     905              : 
     906              : /* Generate RTX move insns from the move list LIST.  This updates
     907              :    allocation cost using move execution frequency FREQ.  */
     908              : static rtx_insn *
     909       390624 : emit_move_list (move_t list, int freq)
     910              : {
     911       390624 :   rtx to, from, dest;
     912       390624 :   int to_regno, from_regno, cost, regno;
     913       390624 :   rtx_insn *result, *insn;
     914       390624 :   rtx set;
     915       390624 :   machine_mode mode;
     916       390624 :   enum reg_class aclass;
     917              : 
     918       390624 :   grow_reg_equivs ();
     919       390624 :   start_sequence ();
     920      2980526 :   for (; list != NULL; list = list->next)
     921              :     {
     922      2199278 :       start_sequence ();
     923      2199278 :       to = allocno_emit_reg (list->to);
     924      2199278 :       to_regno = REGNO (to);
     925      2199278 :       from = allocno_emit_reg (list->from);
     926      2199278 :       from_regno = REGNO (from);
     927      2199278 :       emit_move_insn (to, from);
     928      2199278 :       list->insn = end_sequence ();
     929      4398556 :       for (insn = list->insn; insn != NULL_RTX; insn = NEXT_INSN (insn))
     930              :         {
     931              :           /* The reload needs to have set up insn codes.  If the
     932              :              reload sets up insn codes by itself, it may fail because
     933              :              insns will have hard registers instead of pseudos and
     934              :              there may be no machine insn with given hard
     935              :              registers.  */
     936      2199278 :           recog_memoized (insn);
     937              :           /* Add insn to equiv init insn list if it is necessary.
     938              :              Otherwise reload will not remove this insn if it decides
     939              :              to use the equivalence.  */
     940      2199278 :           if ((set = single_set (insn)) != NULL_RTX)
     941              :             {
     942      2199278 :               dest = SET_DEST (set);
     943      2199278 :               if (GET_CODE (dest) == SUBREG)
     944            0 :                 dest = SUBREG_REG (dest);
     945      2199278 :               ira_assert (REG_P (dest));
     946      2199278 :               regno = REGNO (dest);
     947      2199278 :               if (regno >= ira_reg_equiv_len
     948      2199278 :                   || (ira_reg_equiv[regno].invariant == NULL_RTX
     949      2199259 :                       && ira_reg_equiv[regno].constant == NULL_RTX))
     950      2199242 :                 continue; /* regno has no equivalence.  */
     951           36 :               ira_assert ((int) reg_equivs->length () > regno);
     952           36 :               reg_equiv_init (regno)
     953           72 :                 = gen_rtx_INSN_LIST (VOIDmode, insn, reg_equiv_init (regno));
     954              :             }
     955              :         }
     956      2199278 :       if (ira_use_lra_p)
     957      2199278 :         ira_update_equiv_info_by_shuffle_insn (to_regno, from_regno, list->insn);
     958      2199278 :       emit_insn (list->insn);
     959      2199278 :       mode = ALLOCNO_MODE (list->to);
     960      2199278 :       aclass = ALLOCNO_CLASS (list->to);
     961      2199278 :       cost = 0;
     962      2199278 :       if (ALLOCNO_HARD_REGNO (list->to) < 0)
     963              :         {
     964       104687 :           if (ALLOCNO_HARD_REGNO (list->from) >= 0)
     965              :             {
     966       104599 :               cost = ira_memory_move_cost[mode][aclass][0] * freq;
     967       104599 :               ira_store_cost += cost;
     968              :             }
     969              :         }
     970      2094591 :       else if (ALLOCNO_HARD_REGNO (list->from) < 0)
     971              :         {
     972       152165 :           if (ALLOCNO_HARD_REGNO (list->to) >= 0)
     973              :             {
     974       152165 :               cost = ira_memory_move_cost[mode][aclass][0] * freq;
     975       152165 :               ira_load_cost += cost;
     976              :             }
     977              :         }
     978              :       else
     979              :         {
     980      1942426 :           ira_init_register_move_cost_if_necessary (mode);
     981      1942426 :           cost = ira_register_move_cost[mode][aclass][aclass] * freq;
     982      1942426 :           ira_shuffle_cost += cost;
     983              :         }
     984      2199278 :       ira_overall_cost += cost;
     985              :     }
     986       390624 :   result = end_sequence ();
     987       390624 :   return result;
     988              : }
     989              : 
     990              : /* Generate RTX move insns from move lists attached to basic blocks
     991              :    and edges.  */
     992              : static void
     993        35600 : emit_moves (void)
     994              : {
     995        35600 :   basic_block bb;
     996        35600 :   edge_iterator ei;
     997        35600 :   edge e;
     998        35600 :   rtx_insn *insns, *tmp, *next;
     999              : 
    1000      2794891 :   FOR_EACH_BB_FN (bb, cfun)
    1001              :     {
    1002      2759291 :       if (at_bb_start[bb->index] != NULL)
    1003              :         {
    1004       139680 :           at_bb_start[bb->index] = modify_move_list (at_bb_start[bb->index]);
    1005       139680 :           insns
    1006       139680 :             = emit_move_list (at_bb_start[bb->index], REG_FREQ_FROM_BB (bb));
    1007       139680 :           tmp = BB_HEAD (bb);
    1008       139680 :           if (LABEL_P (tmp))
    1009        23530 :             tmp = NEXT_INSN (tmp);
    1010       139680 :           if (NOTE_INSN_BASIC_BLOCK_P (tmp))
    1011       139680 :             tmp = NEXT_INSN (tmp);
    1012              :           /* Make sure to put the location of TMP or a subsequent instruction
    1013              :              to avoid inheriting the location of the previous instruction.  */
    1014       139680 :           next = tmp;
    1015       277969 :           while (next && !NONDEBUG_INSN_P (next))
    1016       138289 :             next = NEXT_INSN (next);
    1017       139680 :           if (next)
    1018       139680 :             set_insn_locations (insns, INSN_LOCATION (next));
    1019       139680 :           if (tmp == BB_HEAD (bb))
    1020            0 :             emit_insn_before (insns, tmp);
    1021       139680 :           else if (tmp)
    1022       139680 :             emit_insn_after (insns, PREV_INSN (tmp));
    1023              :           else
    1024            0 :             emit_insn_after (insns, get_last_insn ());
    1025              :         }
    1026              : 
    1027      2759291 :       if (at_bb_end[bb->index] != NULL)
    1028              :         {
    1029       109287 :           at_bb_end[bb->index] = modify_move_list (at_bb_end[bb->index]);
    1030       109287 :           insns = emit_move_list (at_bb_end[bb->index], REG_FREQ_FROM_BB (bb));
    1031       109287 :           ira_assert (! control_flow_insn_p (BB_END (bb)));
    1032       109287 :           emit_insn_after (insns, BB_END (bb));
    1033              :         }
    1034              : 
    1035      6970319 :       FOR_EACH_EDGE (e, ei, bb->succs)
    1036              :         {
    1037      4211028 :           if (e->aux == NULL)
    1038      4069371 :             continue;
    1039       141657 :           ira_assert ((e->flags & EDGE_ABNORMAL) == 0
    1040              :                       || ! EDGE_CRITICAL_P (e));
    1041       141657 :           e->aux = modify_move_list ((move_t) e->aux);
    1042       141657 :           insert_insn_on_edge
    1043       283233 :             (emit_move_list ((move_t) e->aux,
    1044       283233 :                              REG_FREQ_FROM_EDGE_FREQ (EDGE_FREQUENCY (e))),
    1045              :              e);
    1046       141657 :           if (e->src->next_bb != e->dest)
    1047        93954 :             ira_additional_jumps_num++;
    1048              :         }
    1049              :     }
    1050        35600 : }
    1051              : 
    1052              : /* Update costs of A and corresponding allocnos on upper levels on the
    1053              :    loop tree from reading (if READ_P) or writing A on an execution
    1054              :    path with FREQ.  */
    1055              : static void
    1056      4398556 : update_costs (ira_allocno_t a, bool read_p, int freq)
    1057              : {
    1058     10472982 :   ira_loop_tree_node_t parent;
    1059              : 
    1060     10472982 :   for (;;)
    1061              :     {
    1062     10472982 :       ALLOCNO_NREFS (a)++;
    1063     10472982 :       ALLOCNO_FREQ (a) += freq;
    1064     10472982 :       ALLOCNO_MEMORY_COST (a)
    1065     20945964 :         += (ira_memory_move_cost[ALLOCNO_MODE (a)][ALLOCNO_CLASS (a)]
    1066     10472982 :             [read_p ? 1 : 0] * freq);
    1067     10472982 :       if (ALLOCNO_CAP (a) != NULL)
    1068              :         a = ALLOCNO_CAP (a);
    1069      8931592 :       else if ((parent = ALLOCNO_LOOP_TREE_NODE (a)->parent) == NULL
    1070      8931592 :                || (a = parent->regno_allocno_map[ALLOCNO_REGNO (a)]) == NULL)
    1071              :         break;
    1072              :     }
    1073      4398556 : }
    1074              : 
    1075              : /* Process moves from LIST with execution FREQ to add ranges, copies,
    1076              :    and modify costs for allocnos involved in the moves.  All regnos
    1077              :    living through the list is in LIVE_THROUGH, and the loop tree node
    1078              :    used to find corresponding allocnos is NODE.  */
    1079              : static void
    1080      9729610 : add_range_and_copies_from_move_list (move_t list, ira_loop_tree_node_t node,
    1081              :                                      bitmap live_through, int freq)
    1082              : {
    1083      9729610 :   int start, n;
    1084      9729610 :   unsigned int regno;
    1085      9729610 :   move_t move;
    1086      9729610 :   ira_allocno_t a;
    1087      9729610 :   ira_copy_t cp;
    1088      9729610 :   live_range_t r;
    1089      9729610 :   bitmap_iterator bi;
    1090      9729610 :   HARD_REG_SET hard_regs_live;
    1091              : 
    1092      9729610 :   if (list == NULL)
    1093      9338986 :     return;
    1094       390624 :   n = 0;
    1095      6837149 :   EXECUTE_IF_SET_IN_BITMAP (live_through, FIRST_PSEUDO_REGISTER, regno, bi)
    1096      6446525 :     n++;
    1097       390624 :   REG_SET_TO_HARD_REG_SET (hard_regs_live, live_through);
    1098              :   /* This is a trick to guarantee that new ranges is not merged with
    1099              :      the old ones.  */
    1100       390624 :   ira_max_point++;
    1101       390624 :   start = ira_max_point;
    1102      2589902 :   for (move = list; move != NULL; move = move->next)
    1103              :     {
    1104      2199278 :       ira_allocno_t from = move->from;
    1105      2199278 :       ira_allocno_t to = move->to;
    1106      2199278 :       int nr, i;
    1107              : 
    1108      2199278 :       bitmap_clear_bit (live_through, ALLOCNO_REGNO (from));
    1109      2199278 :       bitmap_clear_bit (live_through, ALLOCNO_REGNO (to));
    1110              : 
    1111      2199278 :       nr = ALLOCNO_NUM_OBJECTS (to);
    1112      4414268 :       for (i = 0; i < nr; i++)
    1113              :         {
    1114      2214990 :           ira_object_t to_obj = ALLOCNO_OBJECT (to, i);
    1115      2214990 :           if (OBJECT_CONFLICT_ARRAY (to_obj) == NULL)
    1116              :             {
    1117         4861 :               if (internal_flag_ira_verbose > 2 && ira_dump_file != NULL)
    1118            0 :                 fprintf (ira_dump_file, "    Allocate conflicts for a%dr%d\n",
    1119            0 :                          ALLOCNO_NUM (to), REGNO (allocno_emit_reg (to)));
    1120         4861 :               ira_allocate_object_conflicts (to_obj, n);
    1121              :             }
    1122              :         }
    1123      2199278 :       ior_hard_reg_conflicts (from, hard_regs_live);
    1124      2199278 :       ior_hard_reg_conflicts (to, hard_regs_live);
    1125              : 
    1126      2199278 :       update_costs (from, true, freq);
    1127      2199278 :       update_costs (to, false, freq);
    1128      2199278 :       cp = ira_add_allocno_copy (from, to, freq, false, move->insn, NULL);
    1129      2199278 :       if (internal_flag_ira_verbose > 2 && ira_dump_file != NULL)
    1130            0 :         fprintf (ira_dump_file, "    Adding cp%d:a%dr%d-a%dr%d\n",
    1131              :                  cp->num, ALLOCNO_NUM (cp->first),
    1132            0 :                  REGNO (allocno_emit_reg (cp->first)),
    1133              :                  ALLOCNO_NUM (cp->second),
    1134            0 :                  REGNO (allocno_emit_reg (cp->second)));
    1135              : 
    1136      2199278 :       nr = ALLOCNO_NUM_OBJECTS (from);
    1137      4414268 :       for (i = 0; i < nr; i++)
    1138              :         {
    1139      2214990 :           ira_object_t from_obj = ALLOCNO_OBJECT (from, i);
    1140      2214990 :           r = OBJECT_LIVE_RANGES (from_obj);
    1141      2214990 :           if (r == NULL || r->finish >= 0)
    1142              :             {
    1143      2210129 :               ira_add_live_range_to_object (from_obj, start, ira_max_point);
    1144      2210129 :               if (internal_flag_ira_verbose > 2 && ira_dump_file != NULL)
    1145            0 :                 fprintf (ira_dump_file,
    1146              :                          "    Adding range [%d..%d] to allocno a%dr%d\n",
    1147              :                          start, ira_max_point, ALLOCNO_NUM (from),
    1148            0 :                          REGNO (allocno_emit_reg (from)));
    1149              :             }
    1150              :           else
    1151              :             {
    1152         4861 :               r->finish = ira_max_point;
    1153         4861 :               if (internal_flag_ira_verbose > 2 && ira_dump_file != NULL)
    1154            0 :                 fprintf (ira_dump_file,
    1155              :                          "    Adding range [%d..%d] to allocno a%dr%d\n",
    1156              :                          r->start, ira_max_point, ALLOCNO_NUM (from),
    1157            0 :                          REGNO (allocno_emit_reg (from)));
    1158              :             }
    1159              :         }
    1160      2199278 :       ira_max_point++;
    1161      2199278 :       nr = ALLOCNO_NUM_OBJECTS (to);
    1162      4414268 :       for (i = 0; i < nr; i++)
    1163              :         {
    1164      2214990 :           ira_object_t to_obj = ALLOCNO_OBJECT (to, i);
    1165      2214990 :           ira_add_live_range_to_object (to_obj, ira_max_point, -1);
    1166              :         }
    1167      2199278 :       ira_max_point++;
    1168              :     }
    1169      2589902 :   for (move = list; move != NULL; move = move->next)
    1170              :     {
    1171      2199278 :       int nr, i;
    1172      2199278 :       nr = ALLOCNO_NUM_OBJECTS (move->to);
    1173      4414268 :       for (i = 0; i < nr; i++)
    1174              :         {
    1175      2214990 :           ira_object_t to_obj = ALLOCNO_OBJECT (move->to, i);
    1176      2214990 :           r = OBJECT_LIVE_RANGES (to_obj);
    1177      2214990 :           if (r->finish < 0)
    1178              :             {
    1179      2210129 :               r->finish = ira_max_point - 1;
    1180      2210129 :               if (internal_flag_ira_verbose > 2 && ira_dump_file != NULL)
    1181            0 :                 fprintf (ira_dump_file,
    1182              :                          "    Adding range [%d..%d] to allocno a%dr%d\n",
    1183              :                          r->start, r->finish, ALLOCNO_NUM (move->to),
    1184            0 :                          REGNO (allocno_emit_reg (move->to)));
    1185              :             }
    1186              :         }
    1187              :     }
    1188      4642732 :   EXECUTE_IF_SET_IN_BITMAP (live_through, FIRST_PSEUDO_REGISTER, regno, bi)
    1189              :     {
    1190      4252108 :       ira_allocno_t to;
    1191      4252108 :       int nr, i;
    1192              : 
    1193      4252108 :       a = node->regno_allocno_map[regno];
    1194      4252108 :       if ((to = ALLOCNO_EMIT_DATA (a)->mem_optimized_dest) != NULL)
    1195         9406 :         a = to;
    1196      4252108 :       nr = ALLOCNO_NUM_OBJECTS (a);
    1197      8608043 :       for (i = 0; i < nr; i++)
    1198              :         {
    1199      4355935 :           ira_object_t obj = ALLOCNO_OBJECT (a, i);
    1200      4355935 :           ira_add_live_range_to_object (obj, start, ira_max_point - 1);
    1201              :         }
    1202      4252108 :       if (internal_flag_ira_verbose > 2 && ira_dump_file != NULL)
    1203            0 :         fprintf
    1204            0 :           (ira_dump_file,
    1205              :            "    Adding range [%d..%d] to live through %s allocno a%dr%d\n",
    1206              :            start, ira_max_point - 1,
    1207              :            to != NULL ? "upper level" : "",
    1208            0 :            ALLOCNO_NUM (a), REGNO (allocno_emit_reg (a)));
    1209              :     }
    1210              : }
    1211              : 
    1212              : /* Process all move list to add ranges, conflicts, copies, and modify
    1213              :    costs for allocnos involved in the moves.  */
    1214              : static void
    1215        35600 : add_ranges_and_copies (void)
    1216              : {
    1217        35600 :   basic_block bb;
    1218        35600 :   edge_iterator ei;
    1219        35600 :   edge e;
    1220        35600 :   ira_loop_tree_node_t node;
    1221        35600 :   bitmap live_through;
    1222              : 
    1223        35600 :   live_through = ira_allocate_bitmap ();
    1224      2794891 :   FOR_EACH_BB_FN (bb, cfun)
    1225              :     {
    1226              :       /* It does not matter what loop_tree_node (of source or
    1227              :          destination block) to use for searching allocnos by their
    1228              :          regnos because of subsequent IR flattening.  */
    1229      2759291 :       node = IRA_BB_NODE (bb)->parent;
    1230      2759291 :       bitmap_copy (live_through, df_get_live_in (bb));
    1231      2759291 :       add_range_and_copies_from_move_list
    1232      2759291 :         (at_bb_start[bb->index], node, live_through, REG_FREQ_FROM_BB (bb));
    1233      2759291 :       bitmap_copy (live_through, df_get_live_out (bb));
    1234      2759291 :       add_range_and_copies_from_move_list
    1235      2759291 :         (at_bb_end[bb->index], node, live_through, REG_FREQ_FROM_BB (bb));
    1236      6970319 :       FOR_EACH_EDGE (e, ei, bb->succs)
    1237              :         {
    1238      4211028 :           bitmap_and (live_through,
    1239      4211028 :                       df_get_live_in (e->dest), df_get_live_out (bb));
    1240      4211028 :           add_range_and_copies_from_move_list
    1241      8419987 :             ((move_t) e->aux, node, live_through,
    1242     12631015 :              REG_FREQ_FROM_EDGE_FREQ (EDGE_FREQUENCY (e)));
    1243              :         }
    1244              :     }
    1245        35600 :   ira_free_bitmap (live_through);
    1246        35600 : }
    1247              : 
    1248              : /* The entry function changes code and generates shuffling allocnos on
    1249              :    region borders for the regional (LOOPS_P is TRUE in this case)
    1250              :    register allocation.  */
    1251              : void
    1252      1471362 : ira_emit (bool loops_p)
    1253              : {
    1254      1471362 :   basic_block bb;
    1255      1471362 :   rtx_insn *insn;
    1256      1471362 :   edge_iterator ei;
    1257      1471362 :   edge e;
    1258      1471362 :   ira_allocno_t a;
    1259      1471362 :   ira_allocno_iterator ai;
    1260      1471362 :   size_t sz;
    1261              : 
    1262     37930378 :   FOR_EACH_ALLOCNO (a, ai)
    1263     36459016 :     ALLOCNO_EMIT_DATA (a)->reg = regno_reg_rtx[ALLOCNO_REGNO (a)];
    1264      1471362 :   if (! loops_p)
    1265      1435762 :     return;
    1266        35600 :   sz = sizeof (move_t) * last_basic_block_for_fn (cfun);
    1267        35600 :   at_bb_start = (move_t *) ira_allocate (sz);
    1268        35600 :   memset (at_bb_start, 0, sz);
    1269        35600 :   at_bb_end = (move_t *) ira_allocate (sz);
    1270        35600 :   memset (at_bb_end, 0, sz);
    1271        35600 :   local_allocno_bitmap = ira_allocate_bitmap ();
    1272        35600 :   used_regno_bitmap = ira_allocate_bitmap ();
    1273        35600 :   renamed_regno_bitmap = ira_allocate_bitmap ();
    1274        35600 :   max_regno_before_changing = max_reg_num ();
    1275        35600 :   ira_traverse_loop_tree (true, ira_loop_tree_root, change_loop, NULL);
    1276        35600 :   set_allocno_somewhere_renamed_p ();
    1277        35600 :   ira_free_bitmap (used_regno_bitmap);
    1278        35600 :   ira_free_bitmap (renamed_regno_bitmap);
    1279        35600 :   ira_free_bitmap (local_allocno_bitmap);
    1280        35600 :   setup_entered_from_non_parent_p ();
    1281      2794891 :   FOR_EACH_BB_FN (bb, cfun)
    1282              :     {
    1283      2759291 :       at_bb_start[bb->index] = NULL;
    1284      2759291 :       at_bb_end[bb->index] = NULL;
    1285      6970319 :       FOR_EACH_EDGE (e, ei, bb->succs)
    1286      4211028 :         if (e->dest != EXIT_BLOCK_PTR_FOR_FN (cfun))
    1287      4172619 :           generate_edge_moves (e);
    1288              :     }
    1289        35600 :   allocno_last_set
    1290        35600 :     = (move_t *) ira_allocate (sizeof (move_t) * max_reg_num ());
    1291        35600 :   allocno_last_set_check
    1292        35600 :     = (int *) ira_allocate (sizeof (int) * max_reg_num ());
    1293        35600 :   memset (allocno_last_set_check, 0, sizeof (int) * max_reg_num ());
    1294        35600 :   memset (hard_regno_last_set_check, 0, sizeof (hard_regno_last_set_check));
    1295        35600 :   curr_tick = 0;
    1296      2794891 :   FOR_EACH_BB_FN (bb, cfun)
    1297      2759291 :     unify_moves (bb, true);
    1298      2794891 :   FOR_EACH_BB_FN (bb, cfun)
    1299      2759291 :     unify_moves (bb, false);
    1300        35600 :   move_vec.create (ira_allocnos_num);
    1301        35600 :   emit_moves ();
    1302        35600 :   add_ranges_and_copies ();
    1303              :   /* Clean up: */
    1304      2794891 :   FOR_EACH_BB_FN (bb, cfun)
    1305              :     {
    1306      2759291 :       free_move_list (at_bb_start[bb->index]);
    1307      2759291 :       free_move_list (at_bb_end[bb->index]);
    1308      6970319 :       FOR_EACH_EDGE (e, ei, bb->succs)
    1309              :         {
    1310      4211028 :           free_move_list ((move_t) e->aux);
    1311      4211028 :           e->aux = NULL;
    1312              :         }
    1313              :     }
    1314        35600 :   move_vec.release ();
    1315        35600 :   ira_free (allocno_last_set_check);
    1316        35600 :   ira_free (allocno_last_set);
    1317        35600 :   commit_edge_insertions ();
    1318              :   /* Fix insn codes.  It is necessary to do it before reload because
    1319              :      reload assumes initial insn codes defined.  The insn codes can be
    1320              :      invalidated by CFG infrastructure for example in jump
    1321              :      redirection.  */
    1322      2903520 :   FOR_EACH_BB_FN (bb, cfun)
    1323     36723589 :     FOR_BB_INSNS_REVERSE (bb, insn)
    1324     33855669 :       if (INSN_P (insn))
    1325     28600255 :         recog_memoized (insn);
    1326        35600 :   ira_free (at_bb_end);
    1327        35600 :   ira_free (at_bb_start);
    1328              : }
        

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.